김우석 개발자

인코딩

개요 : 인코딩의 역사와 인코딩의 종류에 관한 글

인코딩이란 무엇일까? 흐름과 특징

teleprinter (전신타자기)


과거에 사람들은 우편의 불편함에서 전기 신호를 이용하여 통신하는 방법들을 연구해왔다. 모스부호도 그런 전신들 중 하나이다. 이러한 전신의 성공적인 설계에는 모두 정교한 설치 절차와 표준화된 전신 코드를 알고 있는 숙련된 조작자가 필요했다. teleprint는 typewriter를 적용시켜 이러한 문제를 해결하여 당시 표준 사업 기계로 채택되었다. teleprinter는 덜 숙달된 사람들도 다룰 수 있어서 많은 사람들의 인기를 끌었다.

teleprinter를 사용하기 위해서 표준화된 전신 코드가 필요했는데 1920년대에는 Baudot Code를 사용하였지만 1960년 부터는 ASCII Code를 사용하였다. ASCII는 7개의 전기 스위치를 사용하여, 128가지의 경우의 수를 제공할 수 있었으며 5개의 전기 스위치를 사용한 Baudot보다 많은 기호를 전송할 수 있었다.

ASCII (char → number(byte)) code table


teleprinter 이후에 컴퓨터와 유닉스가 발명되고 C 프로그래밍 언어를 작성하던 시절, 당시는 모든 것이 단순했다. 문자를 표현하기 위해서는 32부터 127까지의 (컴퓨터)숫자를 이용하는 ASCII 코드를 사용했으며 그중 32개의 unprintable control code가 있었고 특수문자, (문자)숫자, 영어로 127까지의 (컴퓨터)숫자를 채웠다.

이렇게 7비트의 문자는 채워졌지만 문제는 당시 컴퓨터는 8비트 바이트를 이용하고 있었기 때문에 256까지 남는 128개의 공간들에 대하여, 여러 나라와 조직에서 너무 다양한 사용법이 혼재했다. 이러 한 상황들은 사실 당시에는 큰 문제가 되지 않았지만, 웹이 생겨나면서 웹의 문서들을 전 세계의 사람들이 볼 수 있게 되었고, 이러한 혼재되어 있는 코드들은 문서를 깨진 글자의 형태로 전송했다.

그래서 이러한 혼재된 Extended ASCII characters를 표준화 하기 위해 ANSI 표준이 등장한다.

../../../../../public/assets/2021-06-01-encoding/asciicode.png

ANSI 표준 ASCII 코드. ‘A’는 65에 할당되어 있고 이는 이진수로 1000001이며 ‘a’는 97에 할당되어 있고 이진수로 1100001 이다

아시아의 문자들은 개수만 수천 가지가 넘기 때문에 8비트로는 처리할 수가 없었다. 그래서 DBCS(Double Byte Character Set)라는 시스템이 만들어졌다. 한국, 중국 일본은 글자 당 2바이트를 사용하는 DBCS를 사용했다.

유니코드 (char → number) code table


역사적으로 컴퓨터 프로그래밍에는 수백가지의 인코딩이 존재했다. 각각 다른 언어와 목적을 위해 개발되었다. 결과적으로 텍스트의 해석, 입력, 정렬, 표시 및 저장의 해석은 모두 다른 유형의 문자 집합과 인코딩에 대한 이해에 따라 달라졌다. 이러한 무법지대 속에서 유니코드는 전 세계의 모든 문자를 컴퓨터에서 일관되게 표현하고 다룰 수 있도록 산업표준을 설계하였다.

유니코드의 목적은 당시 존재하는 모든 문자 인코딩 방법들을 유니코드로 교체하는 것이었다.

유니코드는 Unicode code point라는 고유한 숫자를 사용하여 모든 문자를 구별하여 사용할 수 있게 하였다.

../../../../../public/assets/2021-06-01-encoding/hangeul_jamo.jpg

한글의 UNICODE, Unicode code point별로 나누어져 있다.

What is Unicode

Hello 라는 글자는 유니코드에서 다섯개의 Unicode code point(magic number)로 나타난다.

U+0048 U+0065 U+006C U+006C U+006F

이것들은 단지 Unicode code point의 묶음이고 숫자일 뿐이다. 이게 메모리에 어떤 식으로 저장되거나 텍스트로 어떻게 표현될까?

인코딩


이제 인코딩이 필요하다.

우리가 방금 Hello를 유니코드로 만들어서 저장하면 다음과 같아진다.

00 48 00 65 00 6C 00 6C 00 6F

리틀 엔디안의 경우

48 00 65 00 6C 00 6C 00 6F 00

으로도 표현할 수 있다. 유니코드를 저장하는 방법이 두 가지 존재했기 때문에, FE FF를 모든 유니코드 문자열 시작 부분에 저장시키는 습관이 생겨났으며, 이를 Unicode Byte Order Mask(BOM) 이라고 부른다.

이후에 많은 프로그래머들은 유니코드에 ‘0’이 너무 많다고 생각했고, 네 배의 불필요한 바이트가 저장되는 것이 불편했으며 ANSI의 표준과 DBCS로 지금까지 적어놓은 많은 문서들을 유니코드로 변환하는 작업을 번거로워 했기 때문에 대부분은 유니코드의 등장을 반기지 않았다.

이러한 배경 속에서 UTF-8이 개발되었다.

UTF-8 (Unicode code point → byte)


UTF-8 인코딩은 유니코드 한 문자를 나타내기 위해 1바이트에서 4바이트까지를 사용한다. 예를 들어서, U+0000(0)부터 U+007F(127) 범위에 있는 ASCII 문자들은 1바이트만으로 표시된다.

이로써 영어 텍스트는 ASCII와 UTF-8이 동일해진다.

U+0048 U+0065 U+006C U+006C U+006F

위의 경우 UTF-8 으로 인코딩하면

48 65 6C 6C 6F (16)
			UTF-8
72 101 108 108 111 (10)
-------------------------------
H   e   l   l   o (ASCII)

위와 같이 저장된다. ANSI의 ASCII, 나머지 표준화 되지 않은 ASCII와 동일하게 표기된다. UTF-8의 인코딩 방법은 밑에 그림과 같다.

../../../../../public/assets/2021-06-01-encoding/utf-8.jpg

UTF-8 표기법

예를 들어서, 문자 “위”([U+C704](http://www.unicode.org/charts/PDF/UAC00.pdf))는 다음과 같은 방법으로 UTF-8로 인코딩된다.

  • 이 문자는 U+0800부터 U+FFFF 사이의 영역에 있으므로, 표에 따라 1110xxxx 10xxxxxx 10xxxxxx 형식으로 인코딩된다.
  • 16진수 C704는 2진수 1100-0111-0000-0100와 같다.
  • 이 비트들은 순서대로 x로 표시된 비트에 들어 간다: 1110**1100** 10**011100** 10**000100**
  • 결과적으로 이 문자는 3바이트로 인코딩된다. (16진수로 표시하면 EC 9C 84가 된다.)

base64 (byte → char)


8비트 이진 데이터를 문자 코드에 영향을 받지 않는 공통 ASCII 영역의 문자들로만 이루어진 일련의 문자열로 바꾸는 인코딩 방식이다.

과거에 많은 인코딩 방식(Baudot 등)이 만들어졌고, 이것은 문자당 7비트의 표준(ASCII Code)이 될 때까지 문자당 비트 수를 다르게 사용해왔다. 그러나 대부분의 컴퓨터는 이진 데이터를 8비트 바이트로 저장하므로 ASCII Code는 데이터를 전송하기에 적합하지 않았다. 일부 시스템은 ASCII Code로 만들기 위해 가장 앞에있는 비트(MSB)를 제거하기도 했다. 또한 여러 시스템의 인코딩의 차이로 ASCII Code의 줄 변환 코드 10(LF), 13(CR)로 읽을 경우 메일이 도중에 끊기는 경우도 있었다.(CRLF)

이러한 문제를 해결하기 위해 base64 인코딩이 생겼다. 256과 128의 공통분모이면서 출력 가능한 문자들을 모은 base64를 사용하여 임의적으로 바이트를 손상하지 않고, 전송해도 원본 내용이 손상되지 않게 ASCII Code로 인코딩할 수 있다. 단점은 길이가 증가한 다는 점이다. 데이터의 3바이트마다 4개의 ASCII Code로 인코딩 되기 때문이다.

../../../../../public/assets/2021-06-01-encoding/base64.jpg

base64 인코딩. 문자를 3개씩 나눠서 ascii code로 변환한 뒤 bit로 표현한다. 이 bit를 base64로 6자리씩 나눠서 4개의 문자를 만든다.

https://t1.daumcdn.net/cfile/tistory/99C7F8345C90BF422C

base64 code table. 64가지의 출력가능한 문자로 이진데이터를 표시한다.

텍스트를 안정적으로 전송하기 위해서 먼저 텍스트를 인코딩 하여 바이트로 바꾼 다음 base64가 결과 이진 데이터를 ASCII로 인코딩된 텍스트 문자열로 보여줄 수 있다.

문자 ⇒ 아스키코드 (숫자) ⇒ 이진데이터 ⇒ base64 ⇒ 이진데이터 ⇒ 아스키코드 ⇒문자

문자 ⇒ 유니코드 (숫자)⇒ utf-8 (이진데이터) ⇒ base64 ⇒ 이진데이터 ⇒ utf-8 디코드 ⇒문자

base64는 6비트(64)로 하나의 문자를 표현하기 때문에 이는 반대편에서는 1바이트로 해석된다. 그래서 6비트가 8비트로 데이터가 증가하는 단점이 있다.

인코딩 심화


문자집합 용어


  • 문자
    • 알파벳, 숫자, 구두점, 표의문자, 기호 등 글쓰기의 최소 단위.
    • 약식으로 유니코드라고 불리는 국제 문자 세트 계획에 따라 여러 언어의 여러 글자에게 알맞고 유일한 이름을 부여하기 위한 표준화된 이름 집합이 개발되어 왔다.
  • 글리프 (glyph)
    • 하나의 글자를 표현하기 위한, 획의 패턴이나 다른 것과 구분되는 유일한 시각적 형태.
    • 글리프와 문자의 차이는 문자는 유일하고 추상화된 언어의 요소이고 글리프는 각 글자를 그리는 방법이다.
    • 하나의 ‘문자’를 여러 방식으로 쓰는 것이 가능하다면 글리프를 여러 개 가질수도 있다

    ../../../../../public/assets/2021-06-01-encoding/arabic_ayn.png

    위 네 개의 문자는 같은 아랍어 ‘ayn’을 적는 위치에 따라 다른 쓰는 방식을 나타낸다. 단어의 끝에 올 때, 중간, 시작, 혼자 쓸 때 전부 다르게 쓸 수 있다.

    • 코딩된 문자 (coded character)
      • 우리가 글자를 다룰 수 있도록 각 글자에 할당된 유일한 숫자
    • 코드 공간 (coding space)
      • 문자 코드 값으로 사용하려고 계획해 둔 정수의 범위
    • 사용 가능 문자집합 (character repertoire)
      • 글자들에 대한 특정한 작업 집합(세상에 존재하는 모든 글자의 부분집합)
    • 코딩된 문자집합 (coded character set)
      • 사용 가능 문자집합을 받아서 각 글자에 코드 공간의 코드를 할당해주는 코딩된 문자들의 집합.
      • 실제 글자들에 숫자로 된 문자코드(code point)를 대응시킨 것이다
      • ASCII Code, Unicode 등등
    • 문자 인코딩 구조 (character encoding scheme)
      • 숫자로 된 문자 코드들을 콘텐츠 비트의 연속으로 인코딩(디코딩)하는 알고리즘.
      • 문자 인코딩 구조는 글자를 식별하기 위해 필요한 데이터의 양을 줄이거나
      • 전송상의 어떠한 제약을 회피하거나, 중복된 코딩된 문자 집합들을 통합하는데 사용
      • UTF-8 등등

Charset


MIME 차셋 태그(Content-Type charset, Accept-Charset)는 문자집합(character set)을 의미하는 것이 아니다. 이는 데이터 비트를 고유한 문자의 코드로 매핑하는 알고리즘의 이름이다.

../../../../../public/assets/2021-06-01-encoding/charset.png

charset은 형편없는 이름이다

../../../../../public/assets/2021-06-01-encoding/encoding.png

Charset 태그는 데이터 비트를 문자코드(숫자)로 바꾼 뒤 코딩된 문자집합을 사용하여 글자를 찾는 과정이 혼합된 표현이다

참고자료


Characters, Symbols and the Unicode Miracle - Computerphile

Teleprinter instrument

Why do we use Base64?

What is the purpose of base64 conversion in web technology?

What is Base64?

The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

같은 카테고리의 글