UTF-8는 훌륭한 설계임

3 days ago 11

  • UTF-8은 전 세계 수백만 개의 문자를 표현하면서도 ASCII와의 하위 호환성을 유지함
  • 가변 길이 인코딩 구조로, 1~4바이트를 활용해 효율적으로 각 문자 정보를 저장함
  • 첫 128개 문자는 단일 바이트로 표현되어 ASCII 파일과 완벽하게 호환
  • 인코딩 과정에서 각 바이트의 선행 비트 패턴으로 문자 크기를 구분함
  • UTF-16, UTF-32 같은 다른 유니코드 인코딩은 이런 ASCII 호환성을 제공하지 않음

UTF-8 설계의 탁월함

UTF-8 인코딩을 처음 접했을 때, 서로 다른 언어와 문자의 수백만 가지 캐릭터를 하나의 체계로 아우르면서도 기존 ASCII와 호환되는 구조에 큰 인상을 받음

기본적으로 UTF-8은 최대 32비트를 활용하지만, ASCII는 7비트만 사용함
UTF-8의 설계 원칙은 다음과 같음

  • 모든 ASCII 인코딩 파일이 유효한 UTF-8 파일
  • 모든 ASCII 문자만 가진 UTF-8 파일이 유효한 ASCII 파일

불과 128문자에 한정된 구식 시스템과 수백만 문자를 아우르는 체계를 접목하는 발상이 매우 혁신적임

UTF-8 동작 방식

UTF-8은 유니코드 문자 집합의 모든 문자를 표현할 목적으로 설계된 가변 길이 문자 인코딩

  • 1~4바이트로 각 문자를 인코딩함

  • 첫 128개 문자(U+0000~U+007F)는 단일 바이트로 저장되어 ASCII와 하위 호환성 확보

  • 그 외 문자는 두, 세, 네 바이트로 인코딩

첫 번째 바이트의 선행 비트가 인코딩에 필요한 전체 바이트 수를 결정함

1바이트 패턴 바이트 수 전체 바이트 시퀀스 패턴
0xxxxxxx 1 0xxxxxxx (일반적인 ASCII)
110xxxxx 2 110xxxxx 10xxxxxx
1110xxxx 3 1110xxxx 10xxxxxx 10xxxxxx
11110xxx 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  • 다중 바이트 시퀀스의 2, 3, 4번째 바이트는 항상 10으로 시작하며, 이는 연속 바이트임을 명확히 표시

주바이트와 연속 바이트의 나머지 비트를 결합해 하나의 코드 포인트를 만듦
코드 포인트는 고유 유니코드 문자 식별자로, "U+" 접두사와 16진수로 표현됨
예: "A"의 코드 포인트는 U+0041임

UTF-8 인코딩 바이트로부터 문자를 해석하는 흐름은 다음과 같음

  1. 바이트를 읽고, 처음이 0이면 단일 바이트 문자(ASCII)로 간주해서 나머지 7비트로 문자를 표시하고 다음 바이트로 이동
  2. 0이 아니라면
    • 110이면 2바이트 문자로 다음 바이트 한개 추가로 읽음
    • 1110이면 3바이트 문자로 다음 2개 바이트 읽음
    • 11110이면 4바이트 문자로 추가 3개 바이트 읽음
  3. 결정된 바이트에서 선두 비트 제외한 나머지 비트를 결합해서 코드 포인트의 이진값으로 활용
  4. 유니코드 문자 집합에서 코드 포인트 찾아 화면에 표시
  5. 다음 바이트로 반복

예를 들어 힌디어 문자 "अ"(Devanagari Letter A)는 UTF-8로
11100000 10100100 10000101
로 인코딩됨

  • 첫 바이트 11100000은 3바이트 문자임을 표시
  • 세 바이트에서 선두 비트 제외한 00001001 00000101을 합쳐 16진수 0x0905(코드 포인트 U+0905)로 변환
  • 이는 유니코드 힌디어 "अ"에 해당

예시 텍스트 파일

1. Hey👋 Buddy가 포함된 파일

  • 이 텍스트는 영어와 이모지 문자를 모두 포함

  • 저장시 총 13바이트를 가짐:

    01001000 01100101 01111001 11110000 10011111 10010001 10001011 00100000 01000010 01110101 01100100 01100100 01111001

먼저, 각 바이트를 UTF-8 디코딩 규칙에 따라 평가함

바이트 해석
01001000 0으로 시작, 단일 바이트 ASCII, 'H'를 표시
01100101 0으로 시작, 단일 바이트 ASCII, 'e' 표시
01111001 0으로 시작, 단일 바이트 ASCII, 'y' 표시
11110000 11110으로 시작, 4바이트 문자의 첫 바이트
10011111 10으로 시작, 연속 바이트
10010001 10으로 시작, 연속 바이트
10001011 10으로 시작, 연속 바이트
- 이 4바이트의 나머지 비트 합성 결과: 0000111111010001001011(16진수 1F44B) → 코드 포인트 U+1F44B(손흔드는 이모지 "👋")
00100000 0으로 시작, 단일 바이트 ASCII, 공백
01000010 0으로 시작, 단일 바이트 ASCII, 'B'
01110101 0으로 시작, 단일 바이트 ASCII, 'u'
01100100 0으로 시작, 단일 바이트 ASCII, 'd'
01100100 0으로 시작, 단일 바이트 ASCII, 'd'
01111001 0으로 시작, 단일 바이트 ASCII, 'y'

이 파일은 유효한 UTF-8 파일이지만, 비ASCII 문자(이모지)가 포함되어 있으므로 ASCII와의 하위 호환성은 아님

2. Hey Buddy가 포함된 파일

  • 이 파일엔 비ASCII 문자가 없음

  • 저장시 9바이트로 구성

    01001000 01100101 01111001 00100000 01000010 01110101 01100100 01100100 01111001

각 바이트 분석 결과

바이트 해석
01001000 0으로 시작, 단일 바이트 ASCII, 'H' 표시
01100101 0으로 시작, 단일 바이트 ASCII, 'e' 표시
01111001 0으로 시작, 단일 바이트 ASCII, 'y' 표시
00100000 0으로 시작, 단일 바이트 ASCII, 공백 표시
01000010 0으로 시작, 단일 바이트 ASCII, 'B' 표시
01110101 0으로 시작, 단일 바이트 ASCII, 'u' 표시
01100100 0으로 시작, 단일 바이트 ASCII, 'd' 표시
01100100 0으로 시작, 단일 바이트 ASCII, 'd' 표시
01111001 0으로 시작, 단일 바이트 ASCII, 'y' 표시

따라서 이 파일은 유효한 UTF-8 파일이며 동시에 유효한 ASCII 파일
두 인코딩 규칙 모두를 만족하기 때문에, 하위 호환이 이뤄짐

기타 인코딩 비교

ASCII와 호환성을 제공하는 인코딩은 몇 가지 있으나, UTF-8만큼 널리 쓰이지 않음

  • 예시: GB18030(중국 국가 표준), ISO/IEC 8859 시리즈(128~256문자만 지원)
  • UTF-16, UTF-32 등은 ASCII 호환성 없음
    • 예: 'A'는 각각 두 바이트(00 41), 네 바이트(00 00 00 41)로 표현됨

보너스: UTF-8 Playground 도구

글쓴이가 직접 제작한 도구 'UTF-8 Playground'를 통해, UTF-8 인코딩을 시각적으로 체험 가능

결론

UTF-8은 ASCII 시스템과의 호환성, 유니코드 범위의 효율적 지원, 가변 길이 인코딩 등 현대 텍스트 기반 시스템에 필수적인 엔지니어링 혁신

Read Entire Article