사전 KS X 1001
표준

KS X 1001

gabury1고친 사람 github-actions[bot]

KS X 1001 은 한국어 글자마다 번호를 하나씩 정해 주는 국가 표준입니다. 한글 음절과 한자, 여러 기호가 저마다 고정된 번호를 받습니다. 덕분에 컴퓨터끼리 한글을 주고받을 때 같은 글자를 같은 번호로 부릅니다. 한국어 인코딩들이 이 번호를 바탕으로 바이트를 만듭니다.

쉽고 빠른 이해

KS X 1001 은 한국어 글자에 번호를 매겨 둔 표입니다. 글자 「가」는 이 표의 16행 1열에 있습니다.

번호를 모두가 같이 정해 두지 않으면 기계마다 한글에 다른 번호를 붙입니다. 그러면 한 컴퓨터가 「가」라고 보낸 번호를 다른 컴퓨터는 엉뚱한 글자로 읽습니다. 모두가 같은 표를 쓰기로 약속한 것이 이 표준입니다.

어떻게 도나:

  1. 가로 94칸, 세로 94줄짜리 표를 하나 둡니다
  2. 한글과 한자, 기호를 칸마다 하나씩 넣고 몇 행 몇 열인지로 부릅니다
  3. 인코딩, 곧 번호를 바이트로 적는 규칙이 그 행과 열 번호를 두 바이트로 바꿔 적습니다

대가는 칸 수입니다. 한글 음절은 자주 쓰는 2,350 자만 들어갔습니다. 「뷁」이나 「똠」처럼 드문 음절은 표에 없어서 이 표만으로는 적을 수 없습니다.

새로 만드는 시스템은 KS X 1001 대신 유니코드로 글자에 번호를 줍니다. KS X 1001 은 옛 파일이나 기관이 내려 주는 연계 파일을 넘겨받을 때 만납니다.

상세

이 절은 KS X 1001 의 글자 번호표를 들여다봅니다. 표가 어떻게 생겼고 어느 줄에 무엇이 들었는지를 먼저 봅니다. 그다음 그 번호가 바이트가 되는 길과 유니코드로 옮겨 가는 길을 따라갑니다.

이름

KS 는 한국산업표준(Korean Industrial Standards)의 줄임말입니다. 뒤의 X 는 한국산업표준 가운데 정보 부문을 가리키는 분류 기호입니다. 1001 은 그 부문 안의 번호입니다.

같은 표준을 예전에는 전기 부문 기호 C 를 단 KS C 5601 이라고 불렀습니다. 정보 분야 표준을 X 부문으로 옮기면서 이름이 바뀌었습니다. 가리키는 표는 같습니다. 옛 이름은 ks_c_5601-1987 같은 인코딩 이름표에 아직 남아 있습니다(아래 「인코딩 이름표에 남은 옛 이름」).

문자 집합과 인코딩

KS X 1001 을 읽으려면 두 낱말을 먼저 갈라야 합니다. 문자 집합은 담을 글자를 고르고 글자마다 번호를 붙여 둔 목록입니다. 이런 목록이 있어야 서로 다른 프로그램이 같은 글자를 같은 번호로 부릅니다. KS X 1001 은 이 목록에 해당합니다.

문자 인코딩은 그 번호를 바이트로 옮겨 적는 규칙입니다. 파일에 저장하고 네트워크로 보내는 것은 번호가 아니라 바이트라서 이 규칙이 따로 필요합니다. EUC-KR(Extended Unix Code for Korean)가 KS X 1001 의 번호를 바이트로 옮기는 대표 인코딩입니다.

둘을 가르면 한 목록을 여러 방식으로 적을 수 있습니다. 같은 KS X 1001 번호를 바이트로 옮기는 인코딩이 여럿 있습니다. 반대로 어떤 글자를 적을 수 있는지는 인코딩이 아니라 목록이 정합니다.

94행 94열의 표

KS X 1001 의 목록은 가로 94칸, 세로 94줄로 된 표 한 장입니다. 글자는 몇 번째 줄의 몇 번째 칸에 있는지로 부릅니다. 줄 번호를 행, 칸 번호를 열이라고 합니다. 「가」는 16행 1열입니다.

한 변이 94인 데는 까닭이 있습니다. ASCII(American Standard Code for Information Interchange)는 영어 글자와 숫자, 기호에 번호를 붙인 128칸짜리 목록입니다. 그 가운데 눈에 보이는 글자를 찍는 값은 공백을 빼면 0x21 부터 0x7E 까지 94개입니다.

KS X 1001 은 표의 한 변을 이 94개에 맞췄습니다. 행과 열을 각각 이 94개 값 하나로 적을 수 있게 한 것입니다. 그래서 뒤에서 볼 인코딩들은 행과 열 번호에 일정한 값만 더해 바이트를 만듭니다.

표 안은 구역으로 나뉩니다. 앞쪽 줄에는 기호가, 가운데 줄에는 한글 음절이, 뒤쪽 줄에는 한자가 모여 있습니다. 사이사이에 글자를 넣지 않은 줄도 있습니다.

block-beta
  columns 1
  a["1~12행 · 기호 · 한글 낱자 · 외국 글자"]
  b["13~15행 · 비어 있음"]
  c["16~40행 · 한글 음절 2,350자"]
  d["41행 · 비어 있음"]
  e["42~93행 · 한자 4,888자"]
  f["94행 · 비어 있음"]

기호 구역의 열두 줄에는 이런 글자가 들어 있습니다.

행 담긴 글자
1~2 문장 부호 · 화살표 · 수학 기호
3 영어 글자와 숫자를 한글 한 글자 폭으로 넓힌 전각 문자
4 ㄱ · ㄴ · ㅏ 같은 한글 낱자 94개
5 로마 숫자 · 그리스 글자
6 표 테두리를 긋는 선 조각
7 ㎖ · ㎏ 같은 단위 기호
8~9 동그라미나 괄호를 친 글자와 숫자 · 유럽 글자 일부
10~11 히라가나 · 가타카나
12 키릴 글자

3행의 전각 문자는 영어 글자를 한글과 같은 폭으로 그리려고 번호를 하나 더 준 글자입니다. 그래서 KS X 1001 로 적힌 문서에는 「A」가 두 벌 있을 수 있습니다. 한 바이트짜리 ASCII 「A」와 두 바이트짜리 전각 「A」는 눈에 비슷해도 서로 다른 글자라서 문자열 비교와 검색에서 갈립니다.

한글 2,350 자

현대 한글로 조합할 수 있는 음절은 11,172 자입니다. 첫소리 19개, 가운뎃소리 21개, 끝소리 28개(받침 없음까지 한 칸으로 셉니다)를 곱한 수입니다. KS X 1001 에는 그 가운데 2,350 자가 들어 있습니다. 16행부터 40행까지 25줄을 한 줄에 94자씩 채운 수입니다.

음절은 가나다 순으로 놓였습니다. 16행은 「가」「각」「간」으로 시작합니다. 「각」 다음에 올 「갂」과 「갃」은 건너뛰고 바로 「간」이 옵니다. 자주 쓰는 음절만 골라 담았기 때문입니다.

이렇게 음절 하나에 번호 하나를 통째로 주는 방식을 완성형이라고 부릅니다. 완성형은 번호 하나로 글자를 바로 찾습니다. 대신 표에 넣지 않은 음절은 적을 방법이 없습니다. 첫소리·가운뎃소리·끝소리에 번호를 하나씩 주고 셋을 합쳐 음절을 만드는 방식은 조합형입니다.

표에 없는 음절이 「뷁」이나 「똠」 같은 글자입니다. 사람 이름이나 가게 이름에 이런 음절이 들어가면 KS X 1001 만으로는 저장하지 못합니다. 이 빈틈을 메우려고 나온 것이 CP949(Code Page 949)입니다. CP949 는 KS X 1001 목록에 나머지 8,822 자를 더 얹은 자기 목록을 갖습니다. 적을 수 있는 글자가 늘어난 것은 인코딩을 바꿔서가 아니라 목록이 커져서입니다.

한자 4,888 자

한자는 42행부터 93행까지 52줄에 4,888 자가 들어 있습니다. 한자도 우리말 소리의 가나다 순으로 놓였습니다. 「가」로 읽는 한자가 먼저 오고 「각」으로 읽는 한자가 그 뒤에 옵니다.

소리가 여럿인 한자는 소리마다 번호를 따로 받습니다. 「樂」은 읽는 소리가 여럿이라 표에 네 번 나옵니다. 모양이 같은 글자가 번호 넷을 가진 셈입니다. 이 겹침은 뒤에서 유니코드로 옮길 때 다시 나옵니다.

번호가 바이트가 되는 길

행과 열 번호는 아직 바이트가 아닙니다. 인코딩이 두 번호에 정해진 값을 더해 두 바이트를 만듭니다. 더하는 값이 인코딩마다 달라서, 같은 「가」가 인코딩마다 다른 바이트가 됩니다.

flowchart TD
    G["글자 「가」"] --> RC["KS X 1001 번호 · 16행 1열"]
    RC -->|"행과 열에 0xA0 을 더한다"| E["EUC-KR · 0xB0 0xA1"]
    RC -->|"행과 열에 0x20 을 더한다"| I["ISO-2022-KR · 0x30 0x21<br/>앞뒤에 전환 신호"]
    E --> C["CP949 · EUC-KR 바이트를 손대지 않고 읽는다"]

EUC-KR 는 행과 열에 각각 0xA0(십진 160)을 더합니다. 16행 1열인 「가」는 0xB0 0xA1 이 됩니다. 두 바이트 모두 0x7F 보다 커서 ASCII 글자와 값이 겹치지 않습니다. 영어와 한글을 한 파일에 섞어도 바이트만 보고 둘을 가를 수 있는 이유입니다.

파이썬으로 EUC-KR 바이트에서 거꾸로 행과 열을 되찾아 보면 이렇습니다.

Python
b = "가".encode("euc-kr")  # b'\xb0\xa1'
b[0] - 0xA0                # 16 (행)
b[1] - 0xA0                # 1 (열)

두 바이트에서 0xA0 씩 빼니 16행 1열이 돌아왔습니다. EUC-KR 바이트가 곧 KS X 1001 번호를 옮겨 적은 것이라는 뜻입니다.

ISO-2022-KR(ISO: International Organization for Standardization) 은 행과 열에 0x20 만 더합니다. 그러면 「가」는 0x30 0x21 이 됩니다. 이 두 바이트는 ASCII 로 적은 두 글자 0! 과 같은 값입니다.

그래서 ISO-2022-KR 는 한글이 시작하는 곳과 끝나는 곳에 전환 신호 바이트를 넣습니다. 이 신호가 거기서부터 다른 문자 집합으로 읽으라고 알립니다. 신호가 없으면 받는 쪽은 0! 이 ASCII 두 글자인지 「가」인지 구별할 수 없습니다.

한 바이트가 가질 수 있는 값을 구간으로 나눠 보면 두 인코딩의 차이가 보입니다. EUC-KR 한글은 ASCII 가 쓰지 않는 위쪽 값에 있습니다. ISO-2022-KR 한글은 ASCII 글자와 같은 값을 씁니다.

block-beta
  columns 1
  a["0x21~0x7E · ASCII 글자 = ISO-2022-KR 한글 바이트"]
  b["0x7F · ASCII 128칸의 끝"]
  c["0xA1~0xFE · EUC-KR 한글 바이트 (행·열 + 0xA0)"]

CP949 는 자기 목록을 바이트로 적는 인코딩이기도 합니다. KS X 1001 에 있는 글자는 EUC-KR 와 똑같은 바이트로 적습니다. 그래서 EUC-KR 로 적은 바이트는 CP949 로 읽어도 같은 글자가 됩니다. 더 얹은 8,822 자는 EUC-KR 가 비워 둔 바이트 값을 끌어다 적습니다.

인코딩 이름표에 남은 옛 이름

웹 문서와 전자 메일은 자기 바이트가 어느 인코딩인지 이름표를 붙여 알립니다. 옛 한국어 문서에서는 ks_c_5601-1987 이라는 이름표를 자주 만납니다. 이름만 보면 KS X 1001 목록을 가리킵니다. 하지만 목록은 바이트 적는 법을 정하지 않으므로, 그 문서의 바이트는 EUC-KR 나 CP949 로 적혀 있습니다.

이 이름표가 붙은 바이트를 서버에서 받았다면 CP949 로 여는 편이 덜 깨집니다. CP949 는 EUC-KR 를 품고 있어서 두 인코딩 어느 쪽으로 적힌 바이트든 읽어 냅니다.

유니코드와 오갈 때

새로 만드는 시스템은 KS X 1001 대신 유니코드로 글자에 번호를 줍니다. 바이트로는 UTF-8(Unicode Transformation Format 8-bit)로 적는 경우가 많습니다. KS X 1001 은 옛 파일이나 오래된 데이터베이스, 기관이 내려 주는 연계 파일을 넘겨받을 때 만납니다.

KS X 1001 에 있는 글자는 모두 유니코드에도 있습니다. 그래서 KS X 1001 에서 유니코드로 옮기는 쪽은 막히는 글자가 없습니다. 반대쪽은 막힙니다. 유니코드 한글 음절 11,172 자 가운데 8,822 자는 KS X 1001 에 번호가 없어서 EUC-KR 로 되돌릴 수 없습니다.

flowchart TD
    subgraph H["유니코드 한글 음절 11,172 자"]
        A["KS X 1001 에 있는 2,350 자"]
        B["KS X 1001 에 없는 8,822 자"]
    end
    A <-->|"오가도 막히지 않는다"| E["EUC-KR"]
    B -.->|"되돌릴 수 없다"| E
    B -->|"CP949 가 목록에 더 얹었다"| C["CP949"]

8,822 자도 CP949 로는 바이트가 됩니다. 앞에서 본 대로 CP949 가 이 음절들을 자기 목록에 더 얹었기 때문입니다.

한자 쪽에는 걸리는 점이 하나 더 있습니다. 유니코드는 모양과 뜻이 같은 한자에 번호를 하나만 줍니다. 이렇게 한 번호로 모은 한자를 통합 한자라고 합니다.

그대로 두면 KS X 1001 에서 네 번 나온 「樂」이 통합 한자 한 칸으로 모입니다. 그러면 되돌릴 때 원래 어느 칸이었는지 잃습니다.

유니코드는 이 겹친 한자를 위해 호환 한자라는 구역을 두었습니다. 「樂」 네 칸 가운데 한 칸만 통합 한자로 갑니다. 나머지 세 칸은 호환 한자 구역의 번호로 갑니다. KS X 1001 한자 가운데 이렇게 호환 한자로 가는 글자가 268 자입니다.

네 칸이 유니코드에서도 서로 다른 번호를 가집니다. 그래서 유니코드로 갔다가 그대로 돌아오면 원래 칸을 되찾습니다.

유니코드 정규화를 거치면 이 구분이 사라집니다. 정규화는 같은 글자를 한 가지 번호로 맞추는 처리입니다. 호환 한자도 통합 한자 하나로 바꿉니다. 그 뒤에 KS X 1001 로 되돌리면 네 칸 모두 통합 한자로 갔던 한 칸으로 돌아갑니다.

flowchart TD
    subgraph K["KS X 1001 · 「樂」 네 칸"]
        K1["칸 1"]
        K2["칸 2"]
        K3["칸 3"]
        K4["칸 4"]
    end
    subgraph U["유니코드"]
        T["통합 한자 「樂」 1"]
        C["호환 한자 「樂」 3"]
    end
    K1 --> T
    K2 --> C
    K3 --> C
    K4 --> C
    U -->|"그대로 되돌리면"| B1["네 칸 그대로"]
    U -->|"정규화를 거치면"| N["통합 한자 「樂」 하나"]
    N -->|"되돌리면"| B2["통합 한자로 갔던 한 칸만"]

관련 항목

KS X 1001 이 속하는 상위 분류

문자 집합 · 부호화 문자 집합 · 한국산업표준 · ISO 2022

KS X 1001 번호를 바이트로 적는 인코딩

EUC-KR · CP949 · ISO-2022-KR · 문자 인코딩 · 멀티바이트 인코딩

KS X 1001 에 담긴 글자 갈래

한글 음절 · 한글 호환 자모 · 한자 · 전각 문자 · 괘선 문자

KS X 1001 이 한글 음절에 번호를 주는 방식과 그 대안

완성형 · 조합형 · 첫가끝 · 옛한글

KS X 1001 과 같은 역할을 하는 다른 나라 문자 집합

JIS X 0208 · GB 2312 · Big5 · ASCII · ISO-8859-1

KS X 1001 을 넘겨받는 유니코드 쪽 개념

유니코드 · UTF-8 · 코드 포인트 · 호환 한자 · CJK 통합 한자 · 유니코드 정규화

KS X 1001 을 가리키는 인코딩 이름표를 다루는 규약

IANA 문자 집합 레지스트리 · WHATWG Encoding Standard · Content-Type charset · meta charset

KS X 1001 바이트를 잘못 읽었을 때 겪는 문제

모지바케 · 대체 문자 · 인코딩 불일치 · 잘린 멀티바이트 문자

다른 이름: KS C 5601 · KSC-5601 · ks_c_5601-1987