사전 RFC 1557
표준

RFC 1557

gabury1고친 사람 github-actions[bot]

RFC 1557 은 한글 메일이 인터넷을 지나도 깨지지 않게 적는 법을 정합니다. 본문과 제목의 한글을 적는 법과 그 방식의 이름을 함께 정했습니다. 메일에 붙는 iso-2022-kr 이라는 이름표가 RFC 1557 에서 나왔습니다. 지금은 1990년대 메일을 읽을 때 만나는 문서입니다.

쉽고 빠른 이해

RFC 1557 은 한글 메일을 적는 방법과 그 방법의 이름을 정한 문서입니다. 메일에 charset=iso-2022-kr 이라는 이름표가 붙어 있으면 이 문서가 정한 방식으로 적은 본문입니다.

옛 메일 서버 가운데에는 바이트의 맨 윗 비트를 지우는 것이 있었습니다. 한글을 흔한 방식으로 적으면 그 비트가 켜지므로 서버를 지나며 깨졌습니다. 받는 쪽이 어느 방식으로 적었는지 모르는 것도 문제였습니다.

어떻게 도나:

  1. 본문의 한글은 윗 비트를 안 쓰는 방식으로 적습니다. 한글이 시작하고 끝나는 곳에는 신호 바이트를 끼웁니다
  2. 제목의 한글은 흔한 방식으로 적은 뒤 영어 글자만으로 된 문자열로 한 번 더 감쌉니다
  3. 두 방식 모두 메일 머리에 이름을 적어 받는 쪽이 읽는 법을 고르게 합니다

대가는 둘입니다. 본문과 제목이 서로 다른 방식을 쓰므로 받는 프로그램은 두 방식을 다 읽을 줄 알아야 합니다. 그리고 담을 수 있는 한글 음절이 2,350 자뿐이라 표에 없는 글자는 못 적습니다.

지금은 1990년대 메일을 읽을 때만 만납니다. 새로 보내는 메일은 이 방식을 쓰지 않습니다.

상세

이 절은 RFC 1557 이 어떤 문서인지부터 봅니다. 왜 필요했는지가 그다음입니다. 이어서 본문 규칙과 제목 규칙을 바이트 한 조각씩 따라가며 확인합니다. 끝으로 형식 문법과 바탕 이야기, 그리고 오늘의 쓰임을 짚습니다.

어떤 문서인가

RFC(Request for Comments)는 인터넷 기술을 번호 붙은 문서로 내는 문서 묶음입니다. 지금은 IETF(Internet Engineering Task Force, 인터넷 표준을 만드는 단체)가 주로 이 묶음을 냅니다. 1557번 문서의 제목은 「Korean Character Encoding for Internet Messages」입니다.

나온 때는 1993년 12월입니다. KAIST(Korea Advanced Institute of Science and Technology, 한국과학기술원) 전산학과 연구자들이 중심이 되어 썼습니다.

문서의 갈래는 Informational(정보 제공용)입니다. RFC 에는 인터넷 표준으로 올라가는 갈래와 정보만 알리는 갈래가 따로 있습니다. 정보 제공용 문서는 지켜야 할 규칙을 새로 세우지 않고 이미 있는 관행을 알립니다. RFC 1557 도 어떤 인터넷 표준도 정하지 않는다고 밝힙니다.

알리는 관행은 1991년에 정해진 한글 메일 방식입니다. 이 방식은 문서가 나오기 전부터 국내 인터넷망에서 널리 쓰이고 있었습니다. RFC 1557 은 쓰던 방식을 국제 문서로 적어 남긴 셈입니다.

필요했던 까닭

바이트 하나는 비트 여덟 개입니다. 맨 윗 비트가 꺼져 있으면 값이 127 이하입니다. 켜져 있으면 128 이상입니다.

ASCII(American Standard Code for Information Interchange)는 영어 글자와 숫자, 기호에 0 부터 127 까지 번호를 붙인 표입니다. 맨 윗 비트를 안 써도 다 적히므로 이런 글을 7비트 글이라고 부릅니다.

초기 인터넷 메일은 7비트 글만 나른다고 약속하고 만들어졌습니다. 메일을 나르는 규약 SMTP(Simple Mail Transfer Protocol)를 따르는 서버 가운데 일부는 맨 윗 비트를 지우거나 무시했습니다.

한글을 흔히 적는 EUC-KR(Extended Unix Code for Korean)은 한글 바이트의 맨 윗 비트를 켜 둡니다. 이런 바이트가 윗 비트를 지우는 서버를 지나면 다른 글자로 바뀝니다.

flowchart TD
    A["가 · EUC-KR 로 B0 A1 · 윗 비트 켜짐"] --> S["윗 비트를 지우는 SMTP 서버"]
    S --> C["30 21 · ASCII 로 읽으면 0!"]

B0 에서 윗 비트를 지우면 30 이, A1 에서 지우면 21 이 남습니다. 받는 쪽 화면에는 「가」 대신 숫자 0 과 느낌표가 찍힙니다. 그래서 메일에는 윗 비트를 안 쓰는 한글 적기 방식이 따로 필요했습니다.

이렇게 글자를 바이트로 바꿔 적는 방식을 인코딩이라고 부릅니다. 메일 머리에서는 인코딩 이름을 charset 이라는 칸에 적습니다. 인코딩이 여럿이면 받는 쪽은 이 메일이 어느 인코딩인지 알아야 바이트를 읽을 수 있습니다.

1993년 9월에 MIME(Multipurpose Internet Mail Extensions, 다목적 인터넷 메일 확장)을 정한 RFC 1521 과 RFC 1522 가 나왔습니다. MIME 은 메일 머리에 「이 본문은 무슨 인코딩이다」라는 이름을 적는 길을 열었습니다. 그 칸에 넣을 한글 인코딩의 이름을 정한 것이 RFC 1557 입니다.

본문과 제목이 나뉘는 모습

메일은 머리와 본문으로 나뉩니다. 이 짜임은 메일 형식 문서 RFC 822 가 정했습니다. 머리에는 제목과 보낸 사람 같은 줄이 들어갑니다. 그 아래 빈 줄 다음부터가 본문입니다.

RFC 1557 은 두 부분에 서로 다른 인코딩을 씁니다. 본문은 ISO(International Organization for Standardization, 국제표준화기구) 표준을 바탕에 둔 ISO-2022-KR 로 적습니다. 제목처럼 머리에 들어가는 한글은 EUC-KR 로 적고 한 번 더 감쌉니다.

flowchart TD
    subgraph 머리["메일 머리"]
        H1["제목의 한글"] --> H2["EUC-KR 로 적는다"]
        H2 --> H3["영어 글자만으로 한 번 더 감싼다"]
    end
    subgraph 본문["메일 본문"]
        B1["본문의 한글"] --> B2["ISO-2022-KR 로 적는다"]
    end

두 부분은 차례로 바뀌는 것이 아니라 나란히 놓입니다. 어느 쪽이든 서버를 지날 때는 7비트 글이 됩니다.

본문의 한글

이 절은 A가 두 글자가 본문에서 어떤 바이트로 적히는지를 따라갑니다. 먼저 이름과 글자 표를 보고, 신호 바이트와 실제 바이트를 차례로 봅니다.

ISO-2022-KR 이라는 이름은 두 조각으로 읽습니다. 앞의 ISO 2022 는 국제표준화기구가 정한 표준 ISO 2022 의 이름입니다. ISO 2022 는 바이트열 하나 안에서 글자 표 여럿을 신호로 바꿔 가며 쓰는 법을 정합니다. 끝의 KR(Korea)은 그 틀에 한국어 글자 표를 끼웠다는 뜻입니다.

끼운 표는 KS C 5601 입니다. KS 는 Korean Industrial Standards(한국산업표준)의 줄임말입니다. 이 표는 한글 음절과 한자, 기호에 두 수로 된 번호를 붙인 글자 목록입니다. 지금은 KS X 1001 이라는 이름으로 부릅니다.

이 표에 든 한글 음절은 2,350 자입니다. 한글 자모로 짤 수 있는 음절은 11,172 자이므로 표에 없는 음절은 적을 수 없습니다. 「똠」 같은 글자가 그렇습니다.

ISO-2022-KR 은 한글을 영어 글자와 같은 값의 바이트만으로 적습니다. 바이트 30 은 영어로 읽으면 숫자 0 입니다. 한글로 읽으면 「가」의 앞 바이트입니다. 지금 바이트를 영어로 읽을지 한글로 읽을지는 신호 바이트로 알립니다.

신호는 셋입니다. 쓸 글자 표를 정하는 네 바이트, 한글로 바꾸는 한 바이트, 영어로 돌아가는 한 바이트입니다. 쓸 글자 표를 정하는 일을 표를 지정한다고 합니다.

신호 바이트 하는 일
ESC(Escape) $ ) C 1B 24 29 43 쓸 한글 표로 KS C 5601 을 지정한다
SO(Shift Out) 0E 다음 바이트부터 한글로 읽는다
SI(Shift In) 0F 다음 바이트부터 영어로 읽는다

표의 첫 줄처럼 ESC 로 시작하는 신호 묶음을 이스케이프 시퀀스라고 부릅니다. 표 지정은 첫 SO 보다 앞에 한 번만 적습니다. 놓는 곳은 어떤 줄의 맨 앞입니다. 같은 줄의 나머지에는 글이 바로 이어져도 됩니다.

SO 와 SI 는 ASCII 가 원래 갖고 있던 제어 문자입니다. 제어 문자는 화면에 찍히지 않고 기계에게 할 일을 알리는 바이트입니다.

영어로 읽는 상태를 영어 모드, 한글로 읽는 상태를 한글 모드라고 부르겠습니다. 한 번 바뀐 모드는 다음 신호가 올 때까지 이어집니다. SO 뒤의 바이트는 SI 를 만날 때까지 전부 한글로 읽습니다.

stateDiagram-v2
    state "영어 모드" as E
    state "한글 모드" as H
    [*] --> E : 글의 시작 · 표 지정은 여기서 한 번
    E --> H : SO
    H --> E : SI
    note right of E : 줄은 언제나 이 모드로 끝난다

A가 한 줄은 바이트 다섯 덩어리로 적힙니다. 다섯 덩어리는 한 줄 안에 이어서 놓입니다. 표 지정이 줄 맨 앞에 오고 바로 뒤에 A 가 붙습니다.

block-beta
columns 5
  a["1B 24 29 43 · 표 지정"] b["41 · A"] c["0E · SO"] d["30 21 · 가"] e["0F · SI"]

「가」는 KS C 5601 에서 16 과 1 이라는 번호를 받습니다. 16진수로는 0x10 과 0x01 입니다. 각각 0x20 을 더하면 0x30 과 0x21 이 되어 30 21 로 적습니다.

0x20(32)을 더하는 까닭은 값 0 부터 32 까지를 피하려는 것입니다. 0 부터 31 까지는 제어 문자, 32 는 띄어쓰기입니다. 1 부터 94 까지의 번호에 32 를 더하면 33 부터 126 까지 안에 들어갑니다. 두 바이트가 모두 127 이하라서 윗 비트를 지우는 서버를 지나도 안 바뀝니다.

ISO-2022-KR 본문은 그 자체로 7비트 글입니다. 서버를 지나려고 따로 손볼 것이 없습니다.

MIME 에는 8비트 본문을 7비트 글자로 바꿔 싣는 방법이 따로 있습니다. 어떤 방법으로 바꿨는지는 Content-Transfer-Encoding 머리 줄에 적습니다. ISO-2022-KR 본문에는 이 줄이 필요 없습니다.

바꾸는 방법은 둘입니다. base64 는 아무 바이트나 영어 글자와 숫자, 기호 몇 개만으로 된 문자열로 바꿉니다. Quoted-Printable 은 영어 글자는 그대로 두고 나머지 바이트만 =B0 처럼 16진수로 적습니다. 당시 한글 메일 프로그램은 ISO-2022-KR 본문 위에 이 둘을 덧씌운 메일을 읽지 못했습니다.

본문의 인코딩 이름은 MIME 머리 줄로 알립니다. 메일에는 이런 줄이 붙습니다.

Content-Type: text/plain; charset=iso-2022-kr

RFC 1557 이 다루는 본문은 꾸밈 없는 글뿐입니다. 서식을 입힌 글은 범위 밖입니다.

제목의 한글

제목의 한글은 EUC-KR 바이트로 적습니다. EUC-KR 에서는 윗 비트가 켜진 바이트를 KS C 5601 글자로 읽습니다. 「가」는 B0 A1 입니다.

flowchart TD
    N["KS C 5601 번호 16 · 1"] -->|"각각 0x20 더함"| A["30 21 · ISO-2022-KR · 본문"]
    A -->|"윗 비트 켬"| B["B0 A1 · EUC-KR · 제목"]

같은 번호에서 본문 바이트와 제목 바이트가 함께 나옵니다. 두 꼴은 바이트마다 맨 윗 비트 하나만 다릅니다. 0x30 에 0x80 을 더하면 0xB0, 0x21 에 더하면 0xA1 입니다.

이 바이트를 머리에 그냥 적으면 다시 윗 비트 문제가 생깁니다. 머리의 한글은 RFC 1522 가 정한 방법으로 한 번 더 감쌉니다. 감싼 결과를 encoded-word 라고 부릅니다. 감싸는 방법은 B 와 Q 둘 중에서 고릅니다.

B 는 앞에서 본 base64 입니다. Q 는 Quoted-Printable 과 거의 같아서 영어 글자는 남기고 나머지 바이트만 =B0 처럼 16진수로 적습니다.

제목이 「가」 한 글자인 메일의 머리 줄입니다.

Subject: =?EUC-KR?B?sKE=?=   // 가
flowchart TD
    G["가"] --> E["B0 A1 · EUC-KR"]
    E --> W["sKE= · B(base64)"]
    W --> R
    subgraph R["=?EUC-KR?B?sKE=?="]
        r1["=?"] --> r2["EUC-KR · 인코딩 이름"]
        r2 --> r3["B · 감싼 방법"]
        r3 --> r4["sKE= · 감싼 결과"]
        r4 --> r5["?="]
    end

=? 와 ?= 사이에 인코딩 이름, 감싼 방법, 감싼 결과가 차례로 들어갑니다. sKE= 를 base64 로 풀면 B0 A1 이 나옵니다.

감싼 결과에는 7비트 글자만 남습니다. 윗 비트가 켜진 EUC-KR 바이트도 머리에서는 이렇게 안전해집니다.

한 문서가 두 이름을 함께 정했으므로 IANA 의 목록에도 흔적이 남았습니다. IANA(Internet Assigned Numbers Authority, 인터넷 번호 할당 기관)가 charset 이름을 모아 둔 목록이 IANA 문자 집합 레지스트리입니다. 이 레지스트리는 ISO-2022-KR 과 EUC-KR 두 항목의 근거로 모두 RFC 1557 을 듭니다.

형식 문법

본문 규칙은 말로 한 번, 문법으로 한 번 적혀 있습니다. 둘이 어긋나면 문법이 이깁니다.

문법을 이루는 이름은 다섯입니다. 아래 표는 이름마다 뜻을 풉니다.

문법 이름 뜻
designator 표를 지정하는 네 바이트 ESC $ ) C
e-line 한글이 없는 줄
h-line 한글 덩어리가 하나 이상 든 줄
segment SO 로 시작해 SI 로 끝나는 한글 덩어리
one-of-94 한글 바이트 하나. 값은 33 부터 126 까지

다섯 이름은 한 줄로 포개지지 않습니다. 본문 아래에 e-line, designator, h-line 이 차례로 놓입니다. segment 는 h-line 안에 들고, one-of-94 는 segment 안에 둘씩 짝지어 듭니다.

flowchart TD
    B["본문"] --> E1["e-line 여럿 · 없어도 됨"]
    E1 --> D["designator · 한 번 · 한글이 없으면 생략"]
    D --> L["h-line 과 e-line 이 섞여 여럿"]
    L --> H
    subgraph H["h-line 한 줄"]
        T["영어 글자"]
        subgraph S["segment"]
            SO["SO"] --> P["one-of-94 둘 = 글자 하나 · 되풀이"]
            P --> SI["SI"]
        end
    end

그림을 따라가면 규칙이 드러납니다. 본문은 한글 없는 줄로 시작해도 됩니다. 다만 첫 SO 가 나오기 전에, 어떤 줄의 맨 앞에 표 지정이 한 번 옵니다.

한글 덩어리는 반드시 SI 로 닫힙니다. 그래서 줄은 언제나 영어 모드로 끝납니다. 덩어리 안의 한글 바이트는 두 개씩 짝을 지어 글자 하나가 됩니다.

바탕에 깐 것

RFC 1557 의 본문 규칙은 새로 만든 것이 아닙니다. 국내에서 쓰던 SO/SI 방식에 국가 표준 글자 표를 끼우고, ISO 2022 의 틀에 맞춰 적은 것입니다.

flowchart TD
    A["ISO 2022 · 틀"] --> K["ISO-2022-KR · RFC 1557 본문 규칙"]
    B["KS C 5601 · 글자 표"] --> K
    C["N바이트 한글 · SO 와 SI 로 오가던 경험"] --> K

ISO 2022 에는 글 맨 앞에서 「이 글은 어떤 틀을 쓴다」고 알리는 신호도 있습니다. ISO-2022-KR 은 이 알림 신호를 적지 않습니다. 어떤 틀인지는 메일 머리의 charset 이름이 대신 알립니다.

KS C 5601 은 1987년, 1989년, 1992년 판이 있습니다. 세 판의 글자 표는 같아서 어느 판을 따랐든 똑같이 읽힙니다. RFC 1557 은 1992년 뒤에 나오는 판도 같은 표로 봅니다. 그래서 표 이름이 KS X 1001 로 바뀐 뒤에도 이 방식으로 읽힙니다.

KS C 5601 이 국가 표준이 되기 전, 국내 연구망 SDN(System Development Network)과 유닉스 사용자들은 「N바이트 한글」이라는 방식을 썼습니다. SO 와 SI 로 한글과 영어를 오가는 방식입니다. RFC 1557 은 이 방식에서 글자 표만 KS C 5601 로 바꿨습니다. 이름의 N 이 무엇을 뜻하는지는 확인 못 했습니다(미확인).

이 방식은 한글 메시지를 주고받는 데만 씁니다. RFC 1557 은 다른 용도에는 알맞지 않다고 밝힙니다.

오늘 만나는 곳

RFC 1557 을 폐기하거나 고친 뒤 문서는 없습니다.

기댄 문서들은 바뀌었습니다. RFC 822 는 RFC 5322 로, RFC 1522 는 RFC 2047 로 대체됐습니다. 제목을 감싸는 B·Q 방법은 RFC 2047 이 이어받아 지금도 같은 모양으로 씁니다.

본문 쪽은 쓰임이 거의 사라졌습니다. 8비트를 손대지 않고 나르는 메일 서버가 흔해졌습니다. 새 메일은 대개 UTF-8(Unicode Transformation Format 8-bit)로 적습니다.

그래도 1990년대 메일 보관함이나 오래된 메일링 리스트 기록을 읽다 보면 charset=iso-2022-kr 을 만납니다. 그때 본문은 RFC 1557 의 본문 규칙으로, 제목은 제목 규칙으로 풀면 됩니다. 본문은 ISO-2022-KR, 제목은 EUC-KR 을 쓰므로 한 메일에 두 인코딩이 섞여 있는 것이 정상입니다.

관련 항목

RFC 1557 이 이름을 정한 인코딩

ISO-2022-KR · EUC-KR · KS X 1001 · KSC-5601 · N바이트 한글

RFC 1557 이 기대는 표준 문서

RFC 822 · RFC 1521 · RFC 1522 · ISO 2022 · ASCII · KS C 5861

RFC 1557 의 뒤를 이은 메일 표준 문서

RFC 2045 · RFC 2047 · RFC 2822 · RFC 5322 · RFC 6532 · 8BITMIME

RFC 1557 의 인코딩을 싣고 나르는 메일 규약

이메일 · SMTP · MIME · Content-Type charset · Content-Transfer-Encoding · encoded-word

제목 한글을 감싸는 변환

base64 · Quoted-Printable · B 인코딩 · Q 인코딩

RFC 1557 의 본문 바이트를 이루는 신호

이스케이프 시퀀스 · 제어 문자 · Shift Out · Shift In · 상태 유지 인코딩

RFC 1557 을 내고 등록한 기관

RFC · IETF · IANA · IANA 문자 집합 레지스트리 · KAIST · SDN

RFC 1557 의 문서 갈래와 고침 수단

Informational · 인터넷 표준 · 정오표 · RFC 2119

RFC 1557 의 인코딩을 대신하는 인코딩

UTF-8 · 유니코드 · CP949 · ISO-2022-JP · 문자 인코딩

다른 이름: Korean Character Encoding for Internet Messages · RFC1557