RFC 2130
고친 사람 github-actions[bot]
RFC 2130 은 인터넷에서 여러 나라 글자를 주고받는 방법을 정리한 보고서입니다. 「문자 집합」 한 낱말로 뭉뚱그리던 것을 갈라 글자에 매기는 번호와 그 번호를 적는 바이트를 따로 부르게 했습니다. 새로 만드는 프로토콜에는 세계의 글자를 모두 적으면서 영어 글자는 바이트 하나로 남기는 인코딩을 기본으로 쓰라고 권했습니다. 지켜야 할 규칙을 정한 문서가 아니라 방향을 제안한 권고 문서입니다.
쉽고 빠른 이해
RFC 2130 은 글자를 주고받을 때 보내는 쪽이 무엇을 밝혀야 하는지 정리한 보고서입니다. 메일에 붙는 charset=utf-8 같은 이름표가 무엇을 가리키는지 이 보고서의 틀로 읽을 수 있습니다.
1990년대에는 「문자 집합」이라는 한 낱말이 서로 다른 여러 가지를 가리켰습니다. 메일과 웹이 글자를 다루는 방식도 제각각이었습니다. 받는 쪽은 보낸 쪽이 무엇을 썼는지 짐작해야 했습니다.
어떻게 도나:
- 글이 오가는 과정을 일곱 계층으로 나눕니다. 그중 회선을 지나는 세 계층을 따로 봅니다. 글자에 번호를 매기는 계층, 번호를 바이트로 적는 계층, 바이트를 전송에 맞게 한 번 더 바꾸는 계층입니다
- 보내는 쪽이 계층마다 무엇을 썼는지 이름표로 밝힙니다
- 새 프로토콜은 세계의 모든 글자에 번호를 매긴 표를 씁니다. 바이트로는 모든 글자를 적되 영어 글자는 예전처럼 바이트 하나로 남기는 인코딩을 씁니다
대가는 둘입니다. 권고일 뿐이라 오래된 프로토콜은 옛 기본값을 계속 씁니다. 그리고 나라마다 모양이 조금씩 다른 한자는 번호만으로 가려지지 않아 언어 정보를 따로 붙여야 합니다.
상세
이 절은 보고서가 나온 배경, 일곱 계층 모델과 그 가운데 회선 쪽 세 계층, 권고와 그 뒤를 차례로 봅니다. 회선 쪽 세 계층은 한글 「가」 한 글자를 따라가며 확인합니다.
이 문서의 정체
RFC(Request for Comments, 의견 요청)는 인터넷 기술을 번호 붙은 문서로 내는 문서 묶음입니다. 2130번의 제목은 「The Report of the IAB Character Set Workshop」, 곧 IAB(Internet Architecture Board, 인터넷 아키텍처 위원회) 문자 집합 워크숍 보고서입니다. 1997년 4월에 나왔습니다.
IAB 는 인터넷 설계를 멀리서 살피는 위원회입니다. 주제 하나를 골라 그 분야를 아는 사람들을 초청해 워크숍을 엽니다. 이 워크숍은 1996년 2월 29일부터 3월 1일까지 미국 캘리포니아에서 열렸습니다. 보고서는 워크숍 앞뒤의 메일링 리스트 논의까지 담았습니다.
문서의 갈래는 Informational(정보 제공용)입니다. 이 보고서는 어떤 인터넷 표준도 정하지 않습니다. 그래서 권고에도 따를 의무가 없습니다.
권고를 받는 쪽은 규격을 만드는 기구들입니다. IETF(Internet Engineering Task Force)는 인터넷 표준을 만드는 단체입니다. 보고서는 IETF 가 규격을 쓸 때 참고할 방향을 제안합니다.
「문자 집합」이라는 낱말의 혼란
문자 집합은 글자의 모음을 가리키는 말입니다. 1990년대 인터넷에서는 이 한 낱말이 서로 다른 것들을 뭉뚱그려 불렀습니다. 어떤 때는 글자 목록을, 어떤 때는 바이트를 적는 방식을, 어떤 때는 둘을 합친 것을 뜻했습니다. 이 문서는 뭉뚱그린 옛 뜻일 때만 「문자 집합」이라고 씁니다.
혼란은 등록부에도 남았습니다. MIME(Multipurpose Internet Mail Extensions, 다목적 인터넷 메일 확장)은 메일 본문이 무슨 글자로 적혔는지 이름을 붙이는 규격입니다. 그 이름들을 모은 등록부에서 어떤 이름은 바이트를 적는 방식을 따서 지었고, 어떤 이름은 글자 목록을 따서 지었습니다. 성격이 다른 둘이 같은 목록에 같은 자격으로 올라 있었습니다.
응용마다 대처법도 갈렸습니다. 메일과 웹, 사람·조직 정보를 찾아 주는 디렉터리 서비스가 늘어나는 문자 집합을 저마다 다른 기법으로 다뤘습니다. 서로 다른 기법 사이로 글이 오가려면 공통의 틀이 필요했습니다.
워크숍은 하나의 문자 집합을 모두에게 강요하는 길을 고르지 않았습니다. 이미 쓰이는 문자 집합들을 살려 두고 그것들을 가리키고 쓰는 틀을 세우기로 했습니다. 그 틀이 지킬 조건은 셋이었습니다. 기존 프로토콜을 깨지 않을 것, 지금 쓰는 문자 집합을 계속 쓸 수 있을 것, 새 프로토콜에 넣기 쉬울 것입니다.
일곱 계층 모델
보고서의 중심은 글을 주고받는 과정을 일곱 계층으로 나눈 모델입니다. 계층은 두 무리로 갈립니다. 사람에게 보여 주는 데 필요한 넷과 회선을 지나는 데 필요한 셋입니다.
| 무리 | 계층 | 하는 일 |
|---|---|---|
| 보여 주는 쪽 | 레이아웃 | 글꼴을 고르고 줄을 바꾼다 |
| 보여 주는 쪽 | 문화 | 철자나 낱말 선택 같은 지역 취향을 정한다 |
| 보여 주는 쪽 | 로캘 | 날짜·시각·통화 기호를 사용자에게 익숙한 모양으로 바꾼다 |
| 보여 주는 쪽 | 언어 | 글이 어느 나라 말로 쓰였는지 밝힌다 |
| 회선 쪽 | 전송 인코딩 구문 | 바이트를 전송 경로에 맞는 꼴로 한 번 더 바꾼다 |
| 회선 쪽 | 문자 인코딩 스킴 | 글자 번호를 바이트로 적는다 |
| 회선 쪽 | 부호화 문자 집합 | 글자마다 번호를 매긴다 |
워크숍은 논의를 회선 쪽 셋에 거의 모았습니다. 받는 쪽이 글을 바르게 되살리려면 이 셋을 꼭 알아야 하기 때문입니다. 언어는 보여 주는 쪽에 있지만 가끔 회선 쪽에서도 필요합니다. 그 경우는 아래 「풀지 못하고 남긴 문제」에서 봅니다.
아래 세 소절은 회선 쪽 세 계층을 맨 아래 계층부터 하나씩 봅니다.
부호화 문자 집합
부호화 문자 집합(Coded Character Set, CCS)은 한마디로 글자마다 번호를 매긴 표입니다. 이 문서에서 「글자 표」라고 부르는 것이 이것입니다. 번호가 정해져 있어야 보내는 쪽과 받는 쪽이 같은 글자를 같은 번호로 가리킬 수 있습니다.
정식 정의는 추상 글자의 모음을 정수의 모음에 짝짓는 대응입니다. 추상 글자는 글꼴이나 모양과 상관없이 「이 글자」라는 정체만 가리킵니다. 굵게 쓴 A 와 기울여 쓴 A 가 같은 번호를 받는 까닭입니다.
가장 익숙한 예는 ASCII(American Standard Code for Information Interchange)입니다. 영어 대문자 A 에 65 를 매깁니다. 번호가 0~127 이라 바이트 하나에 들어갑니다.
ISO 는 International Organization for Standardization(국제표준화기구)의 줄임말입니다. ISO-8859-1 은 ASCII 에 서유럽 글자를 더해 바이트 하나에 담는 글자 표입니다. 같은 꼴의 표가 지역마다 있어서 ISO-8859 계열이라고 묶어 부릅니다.
ISO 10646은 세계의 글자를 한 표에 모으려는 국제 표준입니다. Unicode 는 업계 단체인 유니코드 컨소시엄이 만드는 같은 목적의 글자 표입니다. 두 표는 같은 글자에 같은 번호를 매기도록 맞춰져 있습니다.
문자 인코딩 스킴
문자 인코딩 스킴(Character Encoding Scheme, CES)은 글자 번호를 바이트 열로 적는 규칙입니다. 번호가 커서 바이트 하나에 안 들어가는 글자가 많아서 이 규칙이 따로 있어야 합니다. 흔히 줄여 「인코딩」이라고 부르는 것이 이것입니다.
UTF-8(Unicode Transformation Format 8-bit)과 ISO 2022 가 문자 인코딩 스킴입니다. UTF-8 은 ISO 10646 의 번호를 크기에 따라 바이트 한 개에서 여러 개로 적습니다. 영어 글자는 ASCII 와 같은 바이트 하나로 적힙니다.
스킴 하나는 대개 글자 표 하나에 묶입니다. UTF-8 은 ISO 10646 에만 씁니다. ISO 2022 는 반대로 글자 표 여럿을 신호 바이트로 바꿔 가며 씁니다. 그래서 스킴은 「글자 표 하나 또는 여럿에서 바이트로 가는 대응」으로 정의됩니다.
전송 인코딩 구문
TES(Transfer Encoding Syntax, 전송 인코딩 구문)는 이미 바이트로 적힌 글을 한 번 더 바꾸는 변환입니다. 전송 경로에 맞추거나 크기를 줄이려고 씁니다. 옛 메일 경로처럼 7비트 글자만 통과시키는 길이 있으면 경로에 맞춰야 합니다.
Base64 는 아무 바이트나 영어 글자와 숫자, 기호 64개로 된 문자열로 바꿉니다. 그러면 7비트 길도 지납니다. gzip 은 바이트를 압축해 나를 양을 줄입니다. 둘 다 글자의 뜻은 건드리지 않고 바이트의 겉모양만 바꿉니다.
글자 하나가 세 계층을 지나는 모습
이 소절은 한글 「가」 한 글자를 세 계층에 차례로 통과시킵니다. 계층마다 무엇이 바뀌는지 보면 셋을 왜 갈라 불러야 하는지 드러납니다.
flowchart TD
G["가"] -->|"부호화 문자 집합 · ISO 10646"| N["번호 U+AC00"]
N -->|"문자 인코딩 스킴 · UTF-8"| B["바이트 EA B0 80"]
B -->|"전송 인코딩 구문 · Base64"| T["문자열 6rCA"]
U+AC00 은 글자 번호인 코드 포인트를 16진수로 적는 관례입니다. 십진수로는 44032 입니다. UTF-8 은 이 번호를 세 바이트 EA B0 80 으로 적습니다. Base64 는 그 세 바이트를 영어 글자 네 개 6rCA 로 바꿉니다.
받는 쪽은 이 과정을 거꾸로 밟습니다. 세 계층 가운데 하나라도 잘못 짚으면 엉뚱한 글자가 나옵니다. UTF-8 바이트 EA B0 80 을 ISO-8859-1 로 읽으면 ê° 와 보이지 않는 제어 문자 하나가 나옵니다. 흔히 모지바케라고 부르는 글자 깨짐입니다.
MIME 머리 줄과 세 계층
MIME 메일에서는 세 계층이 머리 줄 둘에 나뉘어 실립니다. 부호화 문자 집합과 문자 인코딩 스킴은 Content-Type 머리 줄의 charset 매개변수가 함께 밝힙니다. 전송 인코딩 구문은 Content-Transfer-Encoding 머리 줄이 밝힙니다.
앞의 「가」를 Base64 로 감싸 보내는 메일이라면 머리가 이렇습니다. 오른쪽 // 뒤는 이 문서가 붙인 풀이일 뿐 머리 줄의 일부가 아닙니다.
Content-Type: text/plain;
charset=utf-8 // CCS + CES
Content-Transfer-Encoding:
base64 // TES
Content-Language: ko // 언어
본문에는 6rCA 가 실립니다. 마지막 줄의 Content-Language 는 언어 계층을 밝히는 머리 줄입니다. ko 는 한국어를 가리키는 언어 태그입니다. 보고서는 언어를 밝힐 때 이 머리 줄을 쓰라고 권했습니다.
보고서는 MIME 에서 어긋나는 대목도 하나 짚었습니다. charset 이름 하나가 두 계층을 한꺼번에 가리킨다는 점입니다. charset=utf-8 이라면 글자 표 ISO 10646 과 인코딩 스킴 UTF-8 을 함께 뜻합니다.
기존 이름은 그냥 받아들이자고 했습니다. charset 이름 대부분은 어느 글자 표와 어느 인코딩 스킴인지가 하나로 정해져 있어서 떼어 적기만 하면 됩니다. 새 문자 집합을 등록할 때는 글자 표와 인코딩 스킴을 따로 밝히도록 등록 절차를 고치자고 권했습니다.
받는 쪽이 값을 아는 여섯 길
받는 쪽이 글을 되살리려면 세 계층의 값을 알아야 합니다. 보고서는 받는 쪽이 그 값을 알게 되는 길을 여섯으로 나눴습니다. 그중 몇은 글에 이름표를 붙이고, 나머지는 이름표 없이 값을 정합니다.
이름표에 적는 이름은 IANA(Internet Assigned Numbers Authority, 인터넷 번호 할당 기관) 같은 등록 기관에 올라 있는 이름입니다. 등록된 이름을 써야 받는 쪽이 같은 뜻으로 읽습니다.
| 길 | 받는 쪽이 값을 아는 방법 | 예 |
|---|---|---|
| 짐작 | 보낸 곳을 보고 어림한다 | 「스웨덴에서 왔으니 ISO-8859-1 이겠지」 |
| 프로토콜이 정함 | 프로토콜 문서가 정해 둔 값을 쓴다 | SMTP(Simple Mail Transfer Protocol)는 ASCII |
| 봉투에 붙임 | 글을 감싼 포장에 이름표를 적는다 | MIME 머리 줄 |
| 데이터 안에 넣음 | 바이트열 속 신호로 알린다 | ISO 2022 의 이스케이프 시퀀스 |
| 미리 합의 | 주고받는 둘이 따로 정해 둔다 | 두 회사가 맺은 연동 약속 |
| 협상 | 주고받기 전에 서로 되는 값을 알리고 고른다 | HTTP(HyperText Transfer Protocol) 요청의 Accept-Charset 머리 줄 |
보고서는 짐작을 뺀 다섯이 저마다 쓸모가 있다고 봤습니다. 그래도 서로 맞물려 돌도록 기본은 MIME 에 등록된 이름표 하나로 권했습니다. 다른 길로 이미 값을 알 수 있으면 그 길을 써도 됩니다. 언어 이름표도 같습니다.
권고 기본값
보고서는 모든 프로토콜에 강제할 기본값은 정할 수 없다고 봤습니다. 메일처럼 글이 본체인 프로토콜과 문자열을 거의 안 쓰는 프로토콜은 필요가 다릅니다. 대신 계층마다 권고 기본값을 내놨습니다.
| 계층 | 권고 |
|---|---|
| 부호화 문자 집합 | ISO 10646 의 글자 목록 |
| 문자 인코딩 스킴 | 새 프로토콜은 UTF-8. 하위 호환이 필요하면 기존 기본값을 쓴다 |
| 전송 인코딩 구문 | 기본값 없음. 글을 나르는 경로는 8비트를 손대지 않고 나른다 |
| 언어 | 기본값 없음. 언제나 밝힐 수 있어야 한다 |
| 로캘 | POSIX(Portable Operating System Interface) 로캘 |
표의 「기존 기본값」은 메일의 ASCII 와 HTTP 의 ISO-8859-1 을 말합니다. 로캘 칸의 POSIX 는 유닉스 계열 운영체제의 공통 규격입니다. 그 규격이 정한 기본 로캘을 쓰라는 뜻입니다.
UTF-8 을 고른 까닭은 하위 호환입니다. ASCII 글은 UTF-8 로 읽어도 한 바이트도 바뀌지 않습니다. 그러면서도 ISO 10646 의 글자를 모두 적을 수 있습니다. ASCII 만 쓰던 프로토콜이 옮겨 가기 쉬운 길입니다.
괄호 속 대문자 MUST·SHOULD 는 RFC 들이 권고의 세기를 밝히려고 쓰는 낱말입니다. MUST 는 「반드시」, SHOULD 는 「되도록」을 뜻합니다. 이 보고서는 표준을 정하지 않으므로 이 낱말도 지킬 의무를 만들지 않습니다. 보고서 안의 권고가 얼마나 센지만 알려 줍니다.
옮겨 갈 때의 조건도 붙였습니다. UTF-8 을 쓸지는 프로토콜 판이나 문자 집합을 협상해서 정합니다. 그리고 ASCII 글자만으로 유니코드를 적는 UTF-7 로 물러설 길을 반드시 남겨 둡니다(MUST).
저장한 글도 다룹니다. 오래 묵은 글은 해석에 필요한 정보 없이 남기 쉽습니다. 그래서 저장하는 글에도 MIME 꼴의 이름표를 붙이기를 권합니다(SHOULD).
글자 표를 바꿀 때
한 글자 표로 적힌 글을 다른 글자 표로 옮기는 일도 다뤘습니다. 원래 표의 글자가 새 표에 다 있으면 바이트만 새로 짝지으면 됩니다. 하나라도 없으면 글이 달라지는 것을 피할 수 없습니다.
그때 고를 방법은 셋입니다. 저작권 기호 © 가 없는 표로 옮기는 경우로 견주면 이렇습니다.
| 방법 | 하는 일 | © 는 |
|---|---|---|
| 길이를 바꾸는 변환 | 닮은 글자 여러 개로 바꾼다 | (c) |
| 길이를 지키는 변환 | 닮은 글자 하나로 바꾼다 | C |
| 잃지 않는 변환 | 되돌릴 수 있는 표기로 바꾼다 | &(C |
앞의 둘은 사람이 읽을 화면에 씁니다. 셋째는 저장처럼 원본을 되살려야 할 때 씁니다. 셋째는 새 표의 글자 하나(&)를 「여기부터 표 밖 글자」라는 신호로 빼 써야 합니다. 그러면 인코딩 스킴이 한 겹 더 얹히는 셈입니다.
풀지 못하고 남긴 문제
보고서는 다른 논의에서 다뤄야 할 문제 셋을 열어 둔 채 끝냅니다. 셋 다 논의 중에 거듭 튀어나온 것들입니다.
첫째는 한자입니다. ISO 10646 은 중국·일본·한국·대만에서 모양이 조금씩 다른 한자를 번호 하나로 묶었습니다. 이를 한자 통합이라고 부릅니다. 번호만 보고는 어느 나라 모양으로 그릴지 알 수 없습니다.
워크숍은 언어 태그면 이 문제를 가릴 수 있다고 합의했습니다. 그래서 새 프로토콜에 언어 태그를 넣기를 권했습니다(SHOULD). 언어 태그는 나중에 글을 자동으로 색인하고 찾는 데도 쓰인다고 봤습니다.
둘째는 공개 식별자입니다. URL(Uniform Resource Locator)이나 메일함 이름, 파일 이름에 ASCII 밖 글자를 쓰고 싶다는 요구가 컸습니다. 보고서는 이것을 풀리지 않은 문제로 남겼습니다.
셋째는 양방향 텍스트입니다. 아랍어처럼 오른쪽에서 왼쪽으로 쓰는 글이 왼쪽에서 오른쪽으로 쓰는 글과 섞이는 경우입니다. 틀이 필요하다는 것만 확인하고 다루지는 않았습니다.
권고와 그 뒤
보고서 끝에는 권고 열한 개가 붙어 있습니다. 받는 곳은 IAB 와 IANA, 그리고 IESG(Internet Engineering Steering Group)입니다. IESG 는 IETF 가 만든 규격을 표준으로 승인하는 기구입니다.
권고에는 모든 RFC 의 문자 집합 처리를 점검해 낡은 것은 폐기하거나 주석을 달 것이 들어 있습니다. UTF-8 을 MIME 의 문자 인코딩 스킴으로 등록할 것도 들어 있습니다. 응용 프로토콜 RFC 에 다국어 고려 사항 절을 넣을 것도 권했습니다(SHOULD).
인터넷 전용 문자 집합 표준을 따로 만들 필요는 없다는 판단도 권고에 들어 있습니다. ISO 10646 의 글자 목록이 넓고 더 늘릴 여지도 있어서 인터넷 프로토콜에 충분하다고 봤습니다.
권고는 이듬해 규칙이 됐습니다. 1998년 1월에 나온 RFC 2277 은 IETF 의 문자 집합·언어 정책을 정한 BCP(Best Current Practice, 현행 최선 관행) 문서입니다. RFC 2277 은 이 워크숍의 권고를 바탕으로 썼습니다. 이 정책에서 프로토콜은 UTF-8 을 쓸 수 있어야 합니다(MUST).
세 계층 모델도 이어졌습니다. Unicode 의 문자 인코딩 모델을 다룬 Unicode 기술 보고서 17번은 이 모델을 이어받아 계층을 더 잘게 나눴습니다.
열어 둔 둘째 문제도 이어졌습니다. 도메인 이름에 한글 같은 ASCII 밖 글자를 쓰는 국제화 도메인 이름이 그 문제의 한 갈래입니다. IAB 는 그 인코딩을 다룬 RFC 6055 로 이 보고서를 갱신했습니다. 어느 대목을 고쳤는지는 확인 못 했습니다(미확인).
오늘 이 문서를 만나는 곳
백엔드 개발자가 RFC 2130 을 직접 펴 볼 일은 드뭅니다. 대신 이 보고서가 세운 낱말과 기본값을 매일 씁니다. API(Application Programming Interface) 응답의 Content-Type: application/json; charset=utf-8 이 그 흔적입니다.
글자가 깨졌을 때 세 계층은 점검표가 됩니다. 글자 번호가 틀렸나, 번호를 바이트로 적는 규칙을 잘못 골랐나, 전송 변환을 안 풀었나를 차례로 물으면 됩니다. 「문자 집합」과 「인코딩」을 섞어 부르는 습관도 이 세 낱말로 가르면 덜 헷갈립니다.
관련 항목
RFC 2130 이 세 계층으로 가른 개념
부호화 문자 집합 · 문자 인코딩 스킴 · TES · 문자 집합 · 문자 인코딩 · 코드 포인트 · 추상 문자
RFC 2130 이 기본값으로 권한 글자 표와 인코딩
ISO/IEC 10646 · Unicode · UTF-8 · UTF-7 · UTF-16 · UTF-32
RFC 2130 이전부터 쓰이던 문자 집합과 인코딩
ASCII · ISO-8859-1 · ISO 2022 · ISO-2022-KR · EUC-KR · Shift_JIS
RFC 2130 의 계층을 싣는 메일 머리 줄
MIME · Content-Type · Content-Type charset · Content-Transfer-Encoding · Content-Language · encoded-word
전송 인코딩 구문에 드는 변환
Base64 · Quoted-Printable · gzip · 8BITMIME
RFC 2130 의 보여 주는 쪽 계층을 밝히는 수단
로캘 · 언어 태그 · BCP 47 · RFC 1766 · POSIX
RFC 2130 이 열어 둔 문제
CJK 통합 한자 · 국제화 도메인 이름 · 양방향 텍스트 · IRI
RFC 2130 을 이은 문서
RFC 2277 · RFC 6055 · RFC 3629 · RFC 2047 · UTR 17
RFC 2130 이 속한 기구와 문서 분류
IAB · IETF · IESG · IANA · IRTF · RFC · Informational · BCP · IANA 문자 집합 레지스트리
세 계층을 잘못 짚으면 터지는 장애
모지바케 · 대체 문자 · BOM · 인코딩 스니핑 알고리즘
다른 이름: The Report of the IAB Character Set Workshop · IAB 문자 집합 워크숍 보고서 · RFC2130