1. ASCII Encoding
- 1 byte (8 bit) 중 Checksum으로 1 bit를 제외한 총 7 bit로 문자를 표현
- 한글이나 한자의 경우 2 개 이상의 특수문자를 합쳐서 표현하기 때문에 글자가 자주 깨짐
2. Unicode
- 2-4 byte 공간에 여유있게 문자 할당
- 문제점) 1 byte로 표현 가능한 문자(영어, 숫자)도 필요 이상의 공간을 할당해 메모리 낭비가 심함
3. UTF-8
- Unicode의 가변길이 문자 인코딩 방식: 불필요한 공간의 낭비를 줄일 수 있음
- 표) UTF-8 byte 순서의 이진 포맷
byte 수 | byte 1 | byte 2 | byte 3 | byte 4 |
1 | 0xxx xxxx | |||
2 | 110x xxxx | 10xx xxxx | ||
3 | 1110 xxxx | 10xx xxxx | 10xx xxxx | |
4 | 1111 0xxx | 10xx xxxx | 10xx xxxx | 10xx xxxx |
- 시작 bit를 확인해 전체 byte 결정할 수 있음. 첫 바이트의 맨 앞 비트를 확인해,
- 0인 경우 1 byte
- 10인 경우 특정 문자의 중간 바이트
- 110인 경우 2 byte
- 1110인 경우 3 byte
- 1111 0인 경우 4 byte
예시)
유니코드 A: 0x0041
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
UTF-8 A: 0x41
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
유니코드 $\pi$: 0x03C0
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
UTF-8 $\pi$: 0xCF 0x80
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
유니코드 '한': 0xD55C
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 0 |
UTF-8 '한': 0xED 0x95 0x9C
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 |
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
Python 3부터 Unicode로 모든 문자열을 표현하지만, 내부적으로 UTF-8 인코딩을 사용하지는 않는다. 인덱스를 통해 개별 문자에 접근하기가 어렵기 때문이다.
파이썬에서는 문자열 슬라이싱을 비롯해 원하는 문자에 인덱스로 접근할 수 있는 다양한 방식을 제공하는데, 만약 문자열을 UTF-8로 인코딩해둔다면 각 문자마다 바이트 길이가 달라지게 되므로 전체 문자열을 스캔하지 않는 한 원하는 인덱스에 빠르게 접근하기 어렵다. 따라서 고정 길이 인코딩 방식이 필요하며, 파이썬은 문자열 단위로 다른 고정 길이 인코딩 방식을 적용해 이 문제를 해결한다.
만약 모든 문자열이 ASCII 범위 내에 있으면 Latin-1 인코딩(고정 1 byte 인코딩)을 사용하고, 이외의 대부분의 문자열은 UCS-2(고정 2 byte 인코딩)로 2 바이트 인코딩을 할 수 있다. 특수 기호, 그림 이모티콘, 희귀 언어 등이 포함된 문자열이라면 UCS-4(고정 4 byte 인코딩)을 한다.
댓글