ISO-2022-KR
고친 사람 github-actions[bot]
ISO-2022-KR 은 한글 메일이 옛 메일 서버를 지나도 깨지지 않게 적는 인코딩입니다. 모든 바이트를 영어 글자가 쓰는 값 안에 가둬서 한글을 적습니다. 한글이 시작되고 끝나는 곳마다 전환 신호를 끼워 넣습니다. 지금은 오래된 메일을 열 때나 만납니다.
쉽고 빠른 이해
ISO-2022-KR 은 한글을 영어 글자와 같은 값의 바이트만으로 적는 규칙입니다. 글자 「가」는 한글이 시작된다고 알리는 바이트 하나 뒤에 글자 0 과 ! 와 같은 값의 두 바이트로 적힙니다.
옛 메일 서버 가운데에는 바이트의 맨 윗 비트를 지워 버리는 것이 있었습니다. 한글을 흔한 방식으로 적으면 그 비트가 켜집니다. 그런 바이트는 서버를 지나는 동안 망가졌습니다. 윗 비트를 아예 안 쓰면 망가질 것이 없습니다.
한글 표는 한글 글자마다 번호를 붙인 목록입니다.
어떻게 도나:
- 첫 한글보다 앞에 「이 글에는 한글 표를 쓴다」는 네 바이트를 한 번 적습니다
- 한글이 시작되면 「한글 시작」 바이트를, 끝나면 「영어로 돌아감」 바이트를 끼웁니다
- 두 신호 사이의 바이트는 둘씩 묶어 한글 한 글자로 읽습니다
대가는 셋입니다. 같은 바이트가 신호 앞뒤에 따라 영어도 되고 한글도 되므로 중간부터 읽을 수 없습니다. 담을 수 있는 한글 음절은 2,350 자뿐입니다. 요즘 브라우저는 이 인코딩으로 적힌 문서를 아예 보여 주지 않습니다.
상세
이 절은 ISO-2022-KR 이 왜 생겼는지부터 봅니다. 그다음 바이트를 한 줄 따라 읽으며 신호가 어떻게 끼는지 보고, 그 방식이 치르는 값을 짚습니다.
ISO-2022-KR 은 문자 인코딩 가운데 하나입니다. 문자 인코딩은 글자를 바이트로 바꾸는 규칙입니다. 컴퓨터가 저장하고 주고받는 것은 바이트뿐입니다. 글자를 다루려면 이런 규칙이 꼭 있어야 합니다.
여덟째 비트를 지우던 메일 서버
바이트 하나는 비트 여덟 개입니다. 값은 0 부터 255 까지입니다. 맨 윗 비트가 꺼져 있으면 값이 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) 은 한글 바이트의 맨 윗 비트를 켜 둡니다. 「가」는 0xB0 0xA1 입니다. 이 두 바이트가 윗 비트를 지우는 서버를 지나면 0x30 0x21 이 됩니다. 받는 쪽에는 0! 이라는 엉뚱한 두 글자가 찍힙니다.
그래서 윗 비트를 처음부터 안 쓰는 한글 적기 방식이 필요했습니다. 그 방식이 ISO-2022-KR 입니다. 1993년에 한국 연구자들이 인터넷 메일용으로 문서화했습니다.
이름에 든 ISO 2022
앞머리 ISO 는 International Organization for Standardization(국제표준화기구)입니다. ISO 2022 는 그 기구가 만든 표준 하나의 이름입니다. 바이트열 하나 안에서 글자 표 여럿을 번갈아 쓰는 방법을 정합니다. 글자 표는 ASCII 처럼 글자마다 번호를 붙인 목록입니다.
방법의 뼈대는 두 동작입니다. 먼저 「이 글에서 쓸 표는 이것이다」라고 표를 걸어 둡니다. 그다음 글을 적는 도중에 「지금부터 그 표로 읽어라」라고 바꿔 끼웁니다. 거는 신호와 바꾸는 신호는 둘 다 정해진 바이트로 적습니다.
뒤의 KR(Korea) 은 이 틀에 한국어 표를 끼운 판이라는 뜻입니다. 거는 표는 KS X 1001(Korean Industrial Standards X 1001, 한국산업표준)입니다. 한글 음절과 한자, 기호에 번호를 붙인 표입니다.
KS X 1001 은 예전에 KS C 5601 이라고 불렀습니다. 두 이름이 가리키는 표는 같습니다.
같은 틀로 일본어 표를 끼운 ISO-2022-JP(Japan), 중국어 표를 끼운 ISO-2022-CN(China) 도 있습니다. 거는 표와 신호의 모양이 조금씩 다릅니다.
바이트열을 읽는 규칙
ISO-2022-KR 바이트열에는 글자 바이트 말고도 신호 바이트가 섞여 있습니다. 신호는 셋입니다. 표를 거는 네 바이트, 한글로 바꾸는 한 바이트, 영어로 돌아가는 한 바이트입니다.
| 신호 | 바이트 | 하는 일 |
|---|---|---|
ESC(Escape) $ ) C |
0x1B 0x24 0x29 0x43 |
이 글의 한글 표로 KS X 1001 을 건다 |
| SO(Shift Out) | 0x0E |
지금부터 바이트를 KS X 1001 로 읽는다 |
| SI(Shift In) | 0x0F |
지금부터 바이트를 ASCII 로 읽는다 |
첫 줄의 ESC 는 뒤따르는 바이트를 신호로 읽으라는 표시입니다. 이렇게 ESC 로 시작하는 신호 한 묶음을 이스케이프 시퀀스라고 부릅니다. ISO-2022-KR 에서는 이 신호를 한 글에 한 번, 첫 SO 보다 앞선 줄의 맨 앞에 적습니다. 보통은 본문 첫 줄의 맨 앞입니다.
SO 와 SI 는 둘 다 ASCII 가 원래부터 갖고 있던 제어 문자입니다. 제어 문자는 화면에 찍히지 않고 기계에게 할 일을 알리는 바이트입니다.
SO 와 SI 사이의 바이트는 둘씩 묶어 한글 한 글자로 읽습니다. 두 바이트 모두 0x21 부터 0x7E 사이 값입니다. 이 구간은 ASCII 에서 느낌표부터 물결표까지 눈에 보이는 글자가 쓰는 구간이라 윗 비트가 늘 꺼져 있습니다.
읽는 쪽은 지금 어느 표로 읽고 있는지를 기억하며 바이트를 따라갑니다. 이 기억을 상태라고 부릅니다. 상태는 둘입니다. ASCII 로 읽는 영어 모드와 KS X 1001 로 읽는 한글 모드입니다.
두 모드를 오가는 모습은 이렇습니다.
stateDiagram-v2
state "영어 모드 · 한 바이트가 한 글자" as ASCII
state "한글 모드 · 두 바이트가 한 글자" as KOR
[*] --> ASCII: 줄이 시작된다
ASCII --> KOR: SO 0x0E
KOR --> ASCII: SI 0x0F
ASCII --> [*]: 줄이 끝난다
줄은 언제나 영어 모드로 시작하고 영어 모드로 끝납니다. 한글로 끝나는 줄이라면 줄바꿈 앞에 SI 를 꼭 끼웁니다. 그래서 상태는 한 줄 안에서만 따라가면 됩니다.
바이트 한 조각
KS X 1001 은 글자마다 두 수로 된 번호를 줍니다. 「가」는 16 과 1, 16진수로 0x10 과 0x01 입니다. ISO-2022-KR 은 두 수에 각각 0x20 을 더해 적습니다. 「가」는 이렇게 0x30 0x21 이 됩니다.
EUC-KR 은 같은 번호에 0xA0 을 더해 적습니다. 「가」가 0xB0 0xA1 이 되는 까닭입니다. 두 인코딩의 한글 바이트는 맨 윗 비트 하나만 다릅니다.
A가 를 ISO-2022-KR 로 적은 바이트를 하나씩 풀면 이렇습니다.
1B 24 29 43 // 표 걸기 · 첫 SO 앞에 한 번
41 // A
0E // SO · 한글 모드로
30 21 // 가
0F // SI · 영어 모드로
글자는 둘인데 바이트는 열한 개입니다. 표 걸기 네 바이트는 글 전체에 한 번이라 길어질수록 덜 무겁습니다. SO 와 SI 두 바이트는 한글 덩어리마다 붙습니다.
상태가 있어서 치르는 값
바이트 0x47 0x51 은 영어 모드에서는 GQ 입니다. 한글 모드에서는 「한」입니다. 같은 바이트의 뜻이 앞에 나온 신호에 따라 갈립니다. 이런 인코딩을 상태 유지 인코딩이라고 부릅니다.
그래서 바이트열의 중간부터는 읽을 수 없습니다. 줄 가운데를 잘라 SO 가 떨어져 나가면 뒤의 한글 바이트가 영어 글자 무더기로 읽힙니다. 한글이 있어야 할 곳에 뜻 없는 영어와 기호가 줄줄이 찍히면 이 경우를 의심해 볼 만합니다.
글자를 모르고 바이트만 훑는 처리도 위험해집니다. GQ 를 찾는 검색은 「한」에도 걸립니다. 영어 대문자를 소문자로 바꾸는 처리를 거치면 한글이 다른 글자로 바뀌거나 없는 번호가 됩니다.
담는 글자의 폭도 좁습니다. 걸 수 있는 표가 KS X 1001 하나뿐입니다. 그 표에 없는 글자는 적을 방법이 없습니다. 현대 한글로 조합할 수 있는 음절 11,172 자 가운데 2,350 자만 들어 있습니다. 「뷁」 같은 드문 음절은 못 적습니다.
메일 제목의 한글
ISO-2022-KR 은 메일 본문에 씁니다. 제목처럼 메일 머리에 들어가는 한글은 다른 방법으로 적습니다.
머리의 한글은 EUC-KR 바이트로 적은 다음 한 번 더 감쌉니다. 감싸는 방법은 base64 같은 변환입니다. 이 변환은 아무 바이트나 영어 글자와 숫자만으로 된 문자열로 바꿉니다. 머리도 이렇게 7비트 글로 남습니다.
본문의 인코딩 이름은 MIME(Multipurpose Internet Mail Extensions, 다목적 인터넷 메일 확장)이 정한 머리 줄로 알립니다. 메일에는 Content-Type: text/plain; charset=iso-2022-kr 같은 줄이 붙습니다.
오늘 이 인코딩을 만나는 곳
8비트를 손대지 않고 나르는 메일 서버가 흔해졌습니다. 이제 이 방식을 새로 고를 까닭이 없습니다. 새 메일과 문서는 대개 UTF-8(Unicode Transformation Format 8-bit)로 적습니다. ISO-2022-KR 은 1990년대 메일을 모아 둔 보관함이나 오래된 메일링 리스트 기록에서 만납니다.
이름은 지금도 공식 등록부에 남아 있습니다. IANA 문자 집합 레지스트리는 IANA(Internet Assigned Numbers Authority, 인터넷 번호 할당 기관)가 인터넷에서 쓰는 인코딩 이름을 올려 두는 등록부입니다. 거기에 ISO-2022-KR 이 올라 있습니다.
브라우저는 반대로 이 인코딩을 버렸습니다. 문서에 iso-2022-kr 이라는 이름표가 붙어 있으면 내용을 해석하지 않고 전체를 대체 문자(�) 하나로 바꿔 보여 줍니다.
까닭은 서버와 브라우저가 같은 바이트를 서로 다르게 읽는 일을 막는 데 있습니다. 앞에서 본 0x47 0x51 처럼 이 인코딩에서는 같은 바이트가 영어 글자도 되고 한글 조각도 됩니다. 서버가 한 가지 뜻으로 읽고 안전하다고 본 바이트를 브라우저가 다른 뜻으로 읽으면, 서버가 검사하지 않은 내용이 화면에서 움직일 수 있습니다. 쓰는 곳이 드문 옛 인코딩이라 아예 막아 두었습니다.
넘겨받은 ISO-2022-KR 메일은 읽는 즉시 유니코드 문자열로 바꾸는 것이 보통입니다. 파이썬은 iso2022_kr 이라는 이름으로 이 인코딩을 읽습니다. 명령줄에서는 iconv 같은 변환 도구가 파일 하나를 한꺼번에 옮겨 줍니다.
관련 항목
ISO-2022-KR 이 속하는 상위 분류
문자 인코딩 · 포맷 · ISO 2022 · 상태 유지 인코딩 · 7비트 인코딩 · 멀티바이트 인코딩
ISO-2022-KR 이 한글 번호를 가져오는 표준
KS X 1001 · KSC-5601 · ASCII · 한글 음절 · 완성형
같은 한글을 다른 바이트로 적는 인코딩
EUC-KR · CP949 · UTF-8 · 유니코드 · UTF-7
ISO 2022 틀을 함께 쓰는 다른 언어용 인코딩
ISO-2022-JP · ISO-2022-JP-2 · ISO-2022-CN · ISO-2022-CN-EXT
ISO-2022-KR 을 싣고 나르는 메일 규약
이메일 · SMTP · MIME · RFC 1557 · Content-Transfer-Encoding · base64 · Quoted-Printable · 8BITMIME
ISO-2022-KR 바이트를 이루는 신호
이스케이프 시퀀스 · 제어 문자 · Shift Out · Shift In
ISO-2022-KR 임을 알리고 바꾸는 데 쓰는 수단
Content-Type charset · IANA 문자 집합 레지스트리 · WHATWG Encoding Standard · iconv · 파이썬
ISO-2022-KR 바이트를 잘못 읽었을 때 겪는 문제
다른 이름: iso-2022-kr · ISO2022KR · iso2022_kr · csISO2022KR