이 등호(=) 기호들은 도대체 뭐지?
(lars.ingebrigtsen.no)- 최근 트위터에 옛 이메일 인용문이 퍼지며, 문장 끝의 등호(=) 가 왜 생기는지에 대한 의문이 제기됨
- 이 기호는 ‘quoted-printable’ 인코딩 과정에서 생기는 것으로, 긴 줄을 강제로 나눌 때 줄이 이어짐을 표시하기 위해 사용됨
- 이메일 전송 시 CRLF(캐리지리턴+라인피드) 를 줄바꿈으로 쓰는데, 이를 Unix의 NL 로 변환할 때 디코딩 알고리듬이 잘못 작동하면 등호가 남거나 문자가 손실됨
- 등호는 줄바꿈 외에도 비ASCII 문자(예: =C2=A0) 를 표현하는 데 쓰이며, 잘못된 디코더가 이를 단순 치환해 오류를 유발함
- 문제의 원인은 버그가 있는 디코딩 로직과 부적절한 변환 처리로, 이메일을 가공한 사람이 기술적으로 미숙했음을 보여줌
이메일 인용문 속 등호(=)의 정체
-
최근 며칠간 트위터에 옛 이메일 인용문이 다수 공유되며, 문장 끝의 등호 기호가 눈에 띄는 현상 발생
- 작성자는 이를 코드나 OCR(광학문자인식) 오류로 오해하는 주장들을 반박
- 실제로는 이메일을 읽기 쉽게 변환한 과정에서 발생한 인코딩 처리 오류임
-
이메일은 과거 단순 텍스트였으나, 긴 줄이나 특수문자를 처리하기 위해 ‘quoted-printable’ 인코딩이 도입됨
- 긴 줄을 나눌 때 줄 끝에 등호(=)를 붙여 “이 줄은 이어진다”는 의미를 표시
- 이때 등호 다음에는 CRLF(캐리지리턴+라인피드) 가 붙음
줄바꿈 인코딩과 디코딩 오류
-
이메일 서버는 CRLF 줄바꿈을 표준으로 사용하지만, Unix 시스템은 NL만 사용
- 변환 과정에서 한 바이트가 줄어들며, 디코더가 이를 잘못 처리하면 등호가 남거나 문자가 빠짐
- 예시로, “non- =CRLF cloven”이 잘못 처리되면 “non- loven”처럼 ‘c’가 사라짐
-
일부 구현체는 줄 끝의 등호를 발견하면 두 문자를 삭제하는 방식으로 처리
- 이 알고리듬이 Unix 형식 파일에서는 오작동해 등호가 그대로 남는 현상 발생
등호의 또 다른 용도: 비ASCII 문자 인코딩
-
등호는 줄바꿈 외에도 비ASCII 문자 인코딩에 사용됨
- 예: “=C2=A0”은 non-breaking space(줄바꿈 방지 공백) 을 의미
- 이메일 본문에서 들여쓰기나 특수문자 표현 시 자주 등장
-
작성자는 일부 변환자가 =C2, =A0 등을 단순 치환(search-replace)만 하고, 정상적인 디코더를 사용하지 않은 것으로 추정
기술적 배경과 표준
-
RFC 2045 표준은 quoted-printable 인코딩을 전송용(transport) 으로 정의
- 수신 후에는 디코딩되어 깨끗한 텍스트로 저장되는 것이 원칙
- 그러나 실제 구현에서는 이 과정이 생략되어, 줄바꿈 처리 오류가 잦음
-
예시 코드에서
(quoted-printable-decode-string "he=\nllo")는"hello"로 정상 복원됨- 이는 SMTP 서버 맥락에서 CRLF를 가정한 알고리듬을 재사용했기 때문
- Windows 기반 파일에서는 정상 작동하지만, Unix 기반에서는 실패함
결론
- 이메일 인용문 속 등호는 quoted-printable 인코딩의 잔재이며,
줄바꿈 처리와 비ASCII 문자 디코딩의 결함이 결합된 결과 - 문제의 근본 원인은 부정확한 디코더 구현과 인코딩 변환 실수
- 작성자는 이를 “기술적 문제이자, 잘못된 처리의 결과”로 요약하며,
이메일 변환 과정의 세밀한 표준 준수가 필요함을 강조함
Hacker News 의견들
-
이 글의 주인공은 Lars Ingebrigtsen으로, Emacs의 이메일/Usenet 리더 패키지인 Gnus의 매뉴얼을 쓴 사람임
그의 매뉴얼은 재치 있고 유익하며, 이메일 파싱에 대해 대부분의 사람보다 훨씬 깊은 이해를 가지고 있음
매뉴얼은 여기서 볼 수 있음, 또 다른 버전은 이 링크에 있음- 그는 매뉴얼뿐 아니라 Gnus 자체의 개발자이기도 함
내가 오슬로대(UiO)에서 그가 Gnus를 처음 만들던 시절을 기억함
우리 정보학과 학생들 사이에서 작은 스타 개발자였고, 모두 Emacs와 Gnus를 썼음
- 그는 매뉴얼뿐 아니라 Gnus 자체의 개발자이기도 함
-
이 사건은 “위험할 정도로 아는 사람”의 전형적인 사례임
이메일이 단순 텍스트가 아니라는 건 알았지만, quoted-printable 디코딩을 단순 치환으로 처리하면 안 된다는 건 몰랐던 것임
정규식으로 HTML을 직접 파싱하는 버그와 같은 부류로, 처음엔 잘 되다가 나중에 의회 증거물에 ‘=’ 기호가 잔뜩 남는 사태가 생김- 이와 관련해 유명한 Stack Overflow 답변을 공유함. HTML을 정규식으로 파싱하면 안 되는 이유를 유머러스하게 설명함
- 출력이 대체로 읽을 만하니, 아무도 문제를 눈치채지 못하다가 수년 후 의회 증거로 제출될 때야 깨닫게 됨
- “지금 최고 인력들이 처리 중임”이라는 농담으로 마무리함
-
“메일 서버가 왜 긴 줄을 싫어하냐”는 질문이 있었음
- SMTP는 라인 기반 프로토콜이라 메시지 본문도 줄 단위로 전송됨
서버는 헤더를 파싱해야 하므로 단순한 바이너리 블롭으로 다룰 수 없음
IMAP은 서버가 완전한 파싱을 해야 하고, POP3는 단일 기기용이라 요즘엔 맞지 않음 - 과거에는 메일을 고정 길이 버퍼로 줄 단위 처리했음
RFC 821이 줄 길이를 최대 1000바이트로 제한했고, 호환성을 위해 80자 이하로 끊는 게 일반적이었음
그래서 Base64 인코딩도 76자마다 줄바꿈을 넣음 - SMTP가 설계될 당시 메모리가 극도로 제한적이었음
예를 들어 PDP-11은 512KB, VAX-11은 2MB 정도였고, 프로그래머들은 바이트 단위로 메모리를 계산했음 - SMTP 명령 흐름을 직접 보여주며,
HELO,MAIL FROM,RCPT TO,DATA등으로 통신하는 구조를 설명함 - 1980년대 대학 네트워크 BITNET을 언급하며, 당시에도 줄 길이 제한이 있었음을 회상함
관련 문서는 IBM 공식 문서와 Wikipedia에서 볼 수 있음
- SMTP는 라인 기반 프로토콜이라 메시지 본문도 줄 단위로 전송됨
-
처음엔 이 글이
= == === .=. <== ==> <<== ==>> (==) => =~=같은 연산자 의미에 대한 이야기일 줄 알았음- “이건 개미용 Haskell인가?”라는 농담이 달림
- 하지만 실제 내용이 훨씬 흥미로웠다고 함
-
나는 개인적으로 이메일 아카이빙 소프트웨어를 직접 만들었음
20년 넘게 쌓인 .eml 파일의 엣지 케이스 처리가 가장 어려웠음
개념은 단순하지만 이메일은 놀라울 정도로 복잡함- 이메일 표준은 처음부터 새로 만든 게 아니라, 기존 시스템들을 억지로 이어붙여 만든 저주받은 표준임
이메일 주소 유효성 검증도 사실상 불가능에 가까움 - 콘솔 기반 메일 클라이언트를 만들었는데, 25%는 C++, 75%는 Lua로 UI와 처리를 정의했음
몇 년간 소수의 사용자가 있었지만, MIME 처리가 가장 큰 고통이었음
- 이메일 표준은 처음부터 새로 만든 게 아니라, 기존 시스템들을 억지로 이어붙여 만든 저주받은 표준임
-
내가 흥미롭게 본 건 ‘=’ 기호 자체보다, 그 주변의 문자가 사라지는 현상이었음
마치 off-by-one 오류처럼, ‘=’을 지우는 대신 실제 텍스트 일부가 사라진 것 같음
아마 CRLF/LF 변환이 관련 있을지도 모름- 원문 기사에서 그 이유를 정확히 설명함
- 이런 식으로 증거물에서 문자가 사라지는 미스터리가 생김
-
왜 이런 문제가 지금 나타나는지 궁금했음
최근 며칠간 사람들이 오래된 이메일을 트위터에 올리고 있는데, 이유가 뭘까 했음- 아마 Epstein 관련 이메일 공개 때문일 것 같다고 함
- 실제로 DOJ가 Epstein 이메일을 추가로 공개했다고 함
-
어떤 사람은 이 문제의 원인이 Gmail이 아니라 중간 서버의 변환일 가능성을 제기함
CRLF→LF 변환 외에도, quoted-printable을 두 번 적용하면 ‘=’이 남는 현상이 생기므로, 두 개의 메일 서버가 관여했을 수도 있음- 일부 PDF에서 Apple Mail.app의 plist 메타데이터가 보여서, 내부 포맷에서 추출된 것일 가능성이 있음
- 법적 증거물 수집 과정에서 이런 일이 자주 발생함
실제로는 비전문 인턴이 단순한 도구로 데이터를 모으고, 여러 번 변환되며 포맷이 망가짐
원본은 이미 파기되고, 남은 건 형태만 남은 파편 데이터뿐임 - 종종 이메일을 MS Outlook의 PST 파일로 임포트하면서 이런 문제가 생김
- 단일 Gmail 덤프가 아니라, 여러 시스템이 “도와준답시고” 데이터를 변형한 결과물 같음
- 이 가설이 가장 설득력 있어 보인다는 의견도 있었음
-
archive.today의 기사도 같은 quoted-printable 깨짐 현상을 보임
관련 링크는 pastes.io/correspond와 HN 스레드임 -
Outlook에서 다운로드한 메일을 볼 때, quoted-printable을 자동으로 풀어주는 .eml 뷰어가 있으면 좋겠다고 함