2025년 10월 21일
문자 집합의 발전 과정과 MySQL utf8mb3 vs utf8mb4 차이
사전 지식 정리
- 문자 집합(character set): 컴퓨터가 이해할 수 있는 문자들의 집합
- 문자 인코딩(character encoding): 문자 집합에 속한 문자를 컴퓨터가 이해하는 0과 1로 이루어진 문자 코드로 변환하는 과정
- 문자 디코딩(character decoding): 반대로 0과 1로 표현된 문자를 사람이 이해하는 문자로 변환하는 과정
아스키(ASCII, American Standard Code for Information Interchange)
- 초창기 컴퓨터에서 사용하던 문자 집합 중 하나
- 영어의 알파벳과 아라비아 숫자, 일부 특수 문자를 포함
- 하나의 아스키 문자를 표현하기 위해서는 8비트(1바이트)를 사용
- 8비트 중 1비트는 패리티 비트(parity bit). 실질적으로 문자 표현을 위해 사용되는 비트는 7비트
- 7비트로 표현할 수 있는 정보의 가짓수는 2^7개이므로 총 128개의 문자를 표현 가능

EUC-KR
- 한글을 표기할 수 없는 아스키 코드의 한계를 극복하기 위해 등장한 한글 인코딩 방식 중 하나
- EUC-KR은 KS X 1001, KS X 1003이라는 문자 집합 기반의 인코딩 방식으로, 아스키 문자를 표현할 때는 1바이트, 하나의 한글 글자를 표현할 때는 2바이트 크기의 코드를 부여
- 2바이트(16비트)는 네 자리 16진수로 표현할 수 있으므로 EUC-KR로 인코딩된 한글 글자 하나는 네 자리 16진수로 표현 가능
- 예를 들어, '가'의 경우
0xb0a1로 인코딩 됨.
- EUC-KR 인코딩 방식을 사용하면 총 2,350개 정도의 한글 단어를 표현 가능
- 하지만 여전히 모든 한글 조합을 표현하지는 못했음. ('쀓', '똠'과 같은 문자는 EUC-KR로 표현 불가능)

유니코드(unicode)
- 유니코드는 한글을 포함해 EUC-KR에 비해 훨씬 많은 언어, 특수문자, 화살표, 이모티콘까지 코드로 표현할 수 있는 통일된 문자 집합
- 유니코드는 대부분의 언어를 지원하기 때문에 국가별로 다른 문자 집합과 인코딩 방식을 준비할 필요가 없음.
- 그 덕분에 유니코드는 현대 가장 많이 사용되는 표준 문자 집합으로 자리 잡음.
- 유니코드 문자 집합 상에서 '가'라는 글자에 부여된 값은
0xAC00(코드 포인트로 표현하면U+AC00)

- ⭐️⭐️⭐️ 아스키 코드나 EUC-KR은 글자에 부여된 값을 그대로 인코딩 값으로 삼았지만, 유니코드는 조금 다름.
- 글자에 부여된 값 자체를 인코딩된 값으로 삼지 않고, 이 값을 다양한 방법으로 인코딩 함.
- 이러한 인코딩 방법에는 대표적으로 UTF-8, UTF-16, UTF-32 등이 존재
- 요컨대, 유니코드가 문자의 집합이라면 UTF-8, UTF-16, UTF-32는 유니코드 문자에 부여된 값을 인코딩하는 방식을 의미

- UTF-8, UTF-16, UTF-32는 가변 길이 인코딩 방식
- 예를 들어, 아래와 같이 '한'이라는 같은 문자에 대해서도 다른 인코딩 결과가 도출되는 모습을 확인할 수 있음.
utf-8 한: ed959c utf-16 한: fffe5cd5 utf-32 한: fffe00005cd50000
UTF-8
- UTF-8은 유니코드를 위한 가변 길이 문자 인코딩 방식 중 하나
- 8-bit 단위로 문자를 인코딩한다는 의미 (즉, 1바이트 = 8비트 단위로 유니코드 코드 포인트를 쪼개서 저장)
- 대부분의 웹사이트의 경우 UTF-8을 사용
- UTF-8은 문자 하나를 표현하기 위해 적게는 1바이트에서 많게는 4바이트를 사용
- 1바이트 (U+0000 ~ U+007F): ASCII 코드 전체
- 2바이트 (U+0080 ~ U+07FF): 일부문자 (제어문자, 라틴어, 음성기호, 조정문자, 결합문자, 그리스어, 아랍어 등등..)
- 3바이트 (U+0800 ~ U+FFFF): 대부분의 문자들. 한국어, 중국어, 일본어는 여기에 포함.
- 4바이트 (U+10000 ~ U+10FFFF): BMP에 속하지 않는 문자 전부 (이모지, 확장 한자, 고대 문자, 일부 특수 기호 등)
- UTF-8는 1바이트부터 4바이트까지 문자를 나타내기 위해 사용되는 비트 패턴이 다름.
- 1바이트만 사용되는 문자는 첫 비트에 0을 두고, 나머지 7비트로 문자를 표현 (ASCII의 인코딩 체계와 동일)
- 문자를 표현하는데 2바이트 이상 사용되는 경우, 아래 표 처럼 첫번째 바이트에 총 몇바이트를 사용하는지 알리는 비트를 먼저 넣음. (2바이트는 110, 3바이트는 1110, 4바이트는 11110)
- 그리고 이후 바이트는 10으로 시작

- 이런 패턴을 사용함으로써 첫 바이트 시작 패턴이 문자의 시작임을 명확히 나타내고, 이후 10으로 시작하는 연속 바이트는 문자의 나머지 부분임을 명시 가능
- 즉, 임의의 바이트 시퀀스에서 명확하게 문자의 경계를 나타낼 수 있게 됨.
- 이를 통해 데이터 손상, 전송 오류 상황에서도 명확히 문자의 시작과 끝을 식별 가능

- 예를 들어, '곰' 이라는 글자를 UTF-8 인코딩 하면 다음과 같이 인코딩된다.
- 첫번째 바이트: 맨 앞에 1110을 두고, 상위 4비트를 가져온다. -> 11101010
- 두번째 바이트: 맨 앞에 10을 두고, 이어지는 6비트를 가져온다. -> 10110011
- 세번째 바이트: 맨 앞에 10을 두고, 나머지 6비트를 가져온다. -> 10110000
- 따라서 '곰' 이라는 글자는
111010101011001110110000로 인코딩된다.
MySQL utf8mb3 vs utf8mb4
- MySQL에서
utf8mb3와utf8mb4는 유니코드 문자를 저장하는 방식을 의미하지만, 지원하는 문자 범위가 다름.
1️⃣ utf8mb3
- 이전 MySQL 버전에서 사용된 "3바이트 유니코드" 인코딩
- BMP(Basic Multillingual Plane) 영역의 문자만 저장 가능 (즉, U+0000~U+FFFF 범위)
- 한글, 대부분의 일반 문자, 숫자, 특수 문자는 저장 가능
- 이모지, 일부 중국, 일본 확장 문자 등은 저장 불가
2️⃣ utf8mb4
- MySQL 5.5 이후 권장되는 "4바이트 유니코드" 인코딩
- 모든 유니코드 문자 저장 가능 -> BMP 외 문자, 이모지, 다양한 특수 기호 포함
- MySQL에서 사실상 현대 표준 문자셋
왜 MySQL은 utf8mb4를 초창기에 지원하지 않았나?
- MySQL 초창기에는 UTF-8 전체 범위(4바이트까지) 지원이 필요 없다고 판단
- 당시 대부분의 사용자는 이모지, 확장 문자 등은 거의 사용하지 않았음
- 그래서 UTF-8의 3바이트만 지원하도록 설계 ->
utf8mb3 mb3에서3은 maximum 3 bytes per character 의미
- 또한, 당시 서버 자원이 제한적이었기 때문에 3바이트로 제한해서 사용했음. (4바이트까지 지원하면 인덱스, 테이블 크기, 메모리 사용량 증가)
- 이후 4바이트 유니코드 수요가 증가하면서
utf8mb4가 등장
참고 자료
- '이것이 취업을 위한 컴퓨터 과학이다' 책 p51~p57
