글자 수와 바이트 수 — UTF-8·EUC-KR·Shift_JIS
2026.10.03 업데이트 · 4분 읽기
같은 글도 UTF-8, UTF-16, EUC-KR(CP949), Shift_JIS(CP932)에서 바이트 수가 다릅니다. 한글·일본어·이모지의 바이트 수와 DB VARCHAR, 고정 길이 전문에서 길이를 맞추는 법을 정리했습니다.
글자 수·바이트 수 세기 바로 사용하기글자 수와 바이트 수는 다른 단위입니다. 안녕하세요 ZEKILO는 12글자지만 UTF-8로는 22바이트, EUC-KR로는 17바이트입니다. DB 컬럼 길이나 고정 길이 전문처럼 바이트로 길이를 재는 곳에서는 상대 시스템이 쓰는 문자 인코딩으로 세어야 합니다. 글자 수·바이트 수 세기에 글을 넣으면 글자 수, UTF-16 길이, UTF-8·EUC-KR·Shift_JIS 바이트 수를 한 번에 볼 수 있습니다.
글자 하나는 몇 바이트인가
아래 표의 숫자는 모두 바이트 수입니다.
| 글자 | UTF-8 | UTF-16 | EUC-KR(CP949) | Shift_JIS(CP932) |
|---|---|---|---|---|
A 영문·숫자 |
1 | 2 | 1 | 1 |
가 한글 |
3 | 2 | 2 | 표현 불가 |
あ 히라가나 |
3 | 2 | 2 | 2 |
漢 한자 |
3 | 2 | 2 | 2 |
ア 반각 가타카나 |
3 | 2 | 표현 불가 | 1 |
😀 이모지 |
4 | 4 | 표현 불가 | 표현 불가 |
- UTF-8은 코드 포인트 범위에 따라 1~4바이트를 씁니다(RFC 3629). U+007F까지 1바이트, U+07FF까지 2바이트, U+FFFF까지 3바이트, 그 위는 4바이트입니다. 한글, 가나, 자주 쓰는 한자는 3바이트입니다.
- UTF-16은 2바이트 단위입니다. U+FFFF를 넘는 글자는 단위 2개(4바이트)를 씁니다. JavaScript의
length와 Java의String.length()는 바이트가 아니라 이 단위의 개수입니다. - EUC-KR은 ASCII를 1바이트, 한글·가나·한자를 2바이트로 적습니다. Shift_JIS는 ASCII와 반각 가타카나를 1바이트, 가나·한자를 2바이트로 적고 한글은 적지 못합니다.
EUC-KR은 CP949(MS949), Shift_JIS는 CP932(Windows-31J) 기준입니다. 시스템마다 다를 수 있습니다. WHATWG Encoding 표준의 euc-kr은 KS X 1001과 통합 완성형을 합친 것, 곧 Windows 코드 페이지 949를 가리킵니다.
예시로 보는 차이
| 입력 | 글자 수 | UTF-16 길이 | UTF-8 | EUC-KR(CP949) | Shift_JIS(CP932) |
|---|---|---|---|---|---|
안녕하세요 ZEKILO |
12 | 12 | 22 | 17 | 한글 5자 표현 불가 |
こんにちは ZEKILO |
12 | 12 | 22 | 17 | 17 |
👍🏻가 |
2 | 5 | 11 | — | — |
똠방각하 |
4 | 4 | 12 | 8 | — |
①髙 |
2 | 2 | 6 | — | 4 |
「—」는 그 인코딩으로 표현할 수 없는 글자가 들어 있다는 뜻입니다.
👍🏻가의 엄지 이모지는 코드 포인트 2개(이모지와 피부색)로 이루어져 있지만 화면에는 한 글자로 보입니다. 사람이 보는 글자 단위(자소 클러스터, UAX #29)로는 2글자, 코드 포인트로는 3개, UTF-16 길이는 5입니다. 글자 수를 무엇으로 세느냐에 따라 답이 달라집니다.똠은 KS X 1001의 한글 2,350자에 없는 글자입니다. CP949는 확장 영역에 이 글자를 두어 2바이트로 적지만, KS X 1001 범위만 지원하는 시스템에서는 깨질 수 있습니다.①과髙는 JIS X 0208에 없고 CP932 확장에 있는 글자입니다.
DB VARCHAR: n은 글자인가 바이트인가
VARCHAR(10)의 10이 무엇을 세는지는 제품마다 다릅니다(2026년 10월 기준 각 제품 문서).
| 제품 | n의 단위 |
|---|---|
MySQL VARCHAR(n) |
글자 수 |
PostgreSQL varchar(n) |
글자 수 |
Oracle VARCHAR2(n) |
BYTE·CHAR로 지정. 생략하면 NLS_LENGTH_SEMANTICS(기본값 BYTE) 적용 |
SQL Server varchar(n) |
바이트 수 |
바이트 기준 컬럼에서는 문자 인코딩이 곧 한도입니다. 홍길동은 EUC-KR로 6바이트, UTF-8로 9바이트입니다. 바이트 기준 10짜리 컬럼에 한글은 EUC-KR이면 5자, UTF-8이면 3자까지 들어갑니다. EUC-KR 데이터베이스를 UTF-8로 옮길 때 한글이 2바이트에서 3바이트로 늘어 길이 초과 오류가 나는 이유입니다. 옮기기 전에 가장 긴 값의 바이트 수를 새 인코딩으로 세어 보세요.
글자 수 기준인 MySQL에도 행 전체 65,535바이트 한도가 있어서, 실제로 선언할 수 있는 최대 길이는 문자 집합에 따라 달라집니다.
고정 길이 전문에서 주의할 점
고정 길이 전문은 필드마다 바이트 수가 정해져 있고, 남는 자리를 공백이나 0으로 채웁니다. 한 필드가 1바이트만 어긋나도 뒤의 필드가 모두 밀립니다.
- 채우는 수는 바이트로 계산합니다. 10바이트 이름 필드에
홍길동을 넣으면 EUC-KR에서는 6바이트이므로 공백 4개를 붙입니다. 글자 수(3)로 계산해 공백 7개를 붙이면 13바이트가 됩니다. - 자를 때는 글자 경계에서 자릅니다. 2바이트 글자의 첫 바이트만 남으면 그 글자와 뒤따르는 내용이 깨집니다. 글자 단위로 더해 가다가 한도를 넘기 직전에 멈춥니다.
- 줄바꿈은 CRLF면 2바이트, LF면 1바이트입니다.
- 상대 시스템이 표현하지 못하는 글자는 미리 걸러 냅니다. 이모지, CP949에 없는 한자가 그런 예입니다. 글자 수·바이트 수 세기는 EUC-KR이나 Shift_JIS로 표현할 수 없는 글자가 몇 개인지 경고로 알려 줍니다.
정리
- 길이 제한을 보면 단위가 글자인지 바이트인지, 바이트라면 어떤 문자 인코딩인지 먼저 확인합니다.
- 한글은 UTF-8에서 3바이트, EUC-KR에서 2바이트입니다.
😀같은 이모지는 UTF-8에서 4바이트이고 EUC-KR·Shift_JIS로는 적을 수 없습니다. length가 돌려주는 값은 UTF-16 길이여서 글자 수와도, 바이트 수와도 다를 수 있습니다.- 보내기 전에 글자 수·바이트 수 세기로 실제 바이트 수를 확인하세요. 입력값은 브라우저 안에서만 처리됩니다.
이 글과 관련된 도구
출처와 기준
- WHATWG Encoding Standard
- RFC 3629 — UTF-8, a transformation format of ISO 10646
- Unicode UAX #29 — Unicode Text Segmentation
- MySQL 8.4 Reference Manual — The CHAR and VARCHAR Types
- PostgreSQL Documentation — Character Types
- Oracle Database 19c SQL Language Reference — Data Types
- Oracle Database 19c Reference — NLS_LENGTH_SEMANTICS
- Microsoft Learn — char and varchar (Transact-SQL)