문자 인코딩: 유니코드와 UTF-8 설명
업데이트 2026-07-06
본 적 있을 겁니다: José로 읽혀야 할 이름이 José로 나타나거나, 이모지가 물음표 상자로 바뀌는 것. 그 깨짐에는 이름이 있습니다 — 모지바케(mojibake) — 그리고 거의 언제나 문자 인코딩 불일치입니다. 이 가이드는 문자·유니코드·UTF-8이 정말 무엇인지 설명해, 그런 버그가 더는 수수께끼가 아니게 합니다.
컴퓨터는 글자가 아니라 숫자를 저장한다
가장 낮은 수준에서 컴퓨터는 숫자(바이트)만 저장합니다. 텍스트를 저장하려면 각 문자를 숫자에 대응시키고 다시 되돌리는, 합의된 표가 필요합니다. 그 표가 문자 인코딩입니다. 한 프로그램이 한 표로 텍스트를 쓰고 다른 프로그램이 다른 표로 읽으면, 숫자가 엉뚱한 문자로 해석돼 — 모지바케가 생깁니다.
ASCII: 작은 시작
널리 퍼진 원조 인코딩 ASCII는 128개 문자 — 영어 알파벳, 숫자, 구두점, 일부 제어 코드 — 에 숫자를 정했습니다. 영어에는 충분하지만 é, ü, ß, 你, 😀나 세계 언어가 쓰는 수만 개 문자를 담을 자리가 없습니다. 수십 년간 모두가 저마다 호환 안 되는 확장을 만들었고, 바로 그래서 텍스트가 시스템 사이를 건널 때 깨졌습니다.
유니코드: 모든 문자에 하나의 숫자
유니코드(Unicode)는 보편적 해법입니다: 모든 문자 체계의 모든 문자에, 그리고 기호와 이모지에 고유한 숫자 — 코드 포인트(code point) — 를 배정하는 단일 표준입니다. 코드 포인트는 U+ 뒤에 16진수를 붙여 씁니다:
A → U+0041 é → U+00E9 你 → U+4F60 😀 → U+1F600
결정적으로, 유니코드는 숫자를 정의하지 그것을 바이트로 어떻게 저장할지는 정의하지 않습니다. 그것은 별개의 결정이며 — 여기서 UTF-8이 등장합니다.
UTF-8: 유니코드가 바이트가 되는 법
UTF-8은 유니코드 코드 포인트를 바이트로 인코딩하는 방식이며, 웹이 압도적으로 쓰는 것입니다. 그 영리한 설계는 가변 길이라는 점입니다:
- 128개 ASCII 문자는 각각 1바이트 — 그래서 UTF-8은 ASCII와 하위 호환됩니다.
- 대부분의 악센트 붙은 라틴 문자와 그리스·키릴 문자는 2바이트.
- 중국어·일본어·한국어를 포함한 대부분의 다른 문자는 3바이트.
- 이모지와 더 드문 문자는 4바이트.
그래서 "100자" 문자열이 항상 100바이트는 아닙니다: 한 문자가 여러 바이트일 수 있습니다. 고전적인 José 버그도 이걸로 설명됩니다 — é의 UTF-8 바이트를 옛 서구 인코딩으로 한 바이트씩 잘못 읽은 것입니다.
문자, 코드 포인트, 바이트
관련은 있지만 서로 다른 세 개념이 사람들을 끊임없이 헷갈리게 합니다:
- 문자(Character) — 사람이 보는 것(글자
é). - 코드 포인트(Code point) — 그것의 유니코드 숫자(
U+00E9). - 바이트(Byte) — 저장되는 방식(UTF-8에서는 두 바이트
0xC3 0xA9).
코드 포인트가 그대로 적힌 것을 보는 게 텍스트 문제를 진단하는 가장 빠른 길일 때가 많습니다 — 예를 들어, 알고 보니 줄바꿈 없는 공백(U+00A0)이었던 "스페이스". 우리 유니코드 변환기는 어떤 텍스트든 그 뒤의 코드 포인트를 보여주고 문자와 이스케이프 시퀀스 사이를 변환합니다.
모지바케를 피하는 법
- 어디서나 UTF-8을 쓰세요. 파일을 UTF-8로 저장하고 선언하세요 — 웹 페이지에는
<meta charset="utf-8">, HTTP에는Content-Typecharset, 데이터베이스에는 UTF-8 콜레이션. - 끝에서 끝까지 일관되게 유지하세요. 대부분의 손상은 한쪽이 다른 인코딩을 가정하는 경계에서 일어납니다.
- 맥락에 맞게 이스케이프하세요. 특수 문자를 HTML에 안전하게 넣으려면 HTML 엔티티를, URL에 넣으려면 URL 인코딩을 쓰세요.
짧게 말하면: 유니코드가 모든 문자에 숫자를 주고, UTF-8이 그 숫자를 바이트로 바꾸며, 모두가 UTF-8을 쓰기로 합의하면 텍스트는 더 이상 깨지지 않습니다.
데이터 포맷 & 인코딩 더 보기
데이터 포맷 & 인코딩 가이드 전체 보기 →이 가이드에서 언급한 도구