문자열 길이·바이트 계산기 쉽게 이해하기 — 개념과 원리
글의 '길이'는 무엇을 세느냐에 따라 달라집니다. 글자 수, UTF-8 바이트, UTF-16 바이트, 단어 수, 줄 수가 모두 다르고, 데이터베이스 열이나 문자 메시지, API는 대개 이 가운데 하나만 기준으로 삼습니다. 특히 한글과 이모지는 기준에 따라 값 차이가 크므로, 다섯 가지를 한꺼번에 확인하면 제한을 넘는지 정확히 판단할 수 있습니다.
계산 방법
- 글자 수: 유니코드 코드 포인트의 개수입니다.
- UTF-8 바이트: 코드 포인트마다 1바이트(U+007F까지), 2바이트(U+07FF까지), 3바이트(U+FFFF까지, 한글 음절 전부 포함), 4바이트(그 이상, 대부분의 이모지)를 씁니다.
- UTF-16 바이트: 16비트 단위 개수 × 2입니다. 기본 다국어 평면의 문자는 단위 1개, U+FFFF를 넘는 문자는 대리 쌍 2개를 씁니다.
- 단어 수: 앞뒤 공백을 지운 뒤 연속된 공백을 기준으로 나눈 개수입니다.
- 줄 수: 줄바꿈 문자 개수에 1을 더한 값입니다.
원리
문자는 번호로 저장되고, 인코딩마다 번호 하나에 쓰는 공간이 다릅니다. UTF-8은 영문을 1바이트로 유지하도록 설계되어 ASCII 밖의 문자는 더 많은 바이트를 씁니다. UTF-16은 모든 문자에 최소 2바이트를 쓰므로 한글이 많은 글에서는 UTF-8보다 작고, 영문 위주의 글에서는 더 큽니다. 단어 수는 공백만 보므로 띄어쓰기를 하는 언어에 맞는 값입니다.
예제 풀이
- 입력은 '안녕하세요 Hello'입니다.
- 글자 수는 한글 5자 + 공백 1자 + 영문 5자 = 11입니다.
- UTF-8은 5 × 3 + 1 + 5 × 1 = 15 + 1 + 5 = 21바이트입니다.
- 11자 모두 BMP 안에 있으므로 UTF-16은 11 × 2 = 22바이트입니다.
- 공백 하나로 나뉘어 단어는 2개, 줄바꿈이 없으므로 줄은 1줄입니다.
결과 해석
대상 시스템이 무엇으로 길이를 재는지와 비교하십시오. 데이터베이스의 VARCHAR는 제품과 설정에 따라 글자 수 또는 바이트 수로 셀 수 있고, 인덱스에는 바이트 제한이 따로 있는 경우가 많습니다. 자바스크립트 .length와 자바 String.length()는 UTF-16 단위를, 파이썬 len()은 코드 포인트를 셉니다. GSM 7비트 문자만 쓴 SMS는 160자까지 보낼 수 있지만, 그 밖의 문자가 하나라도 있으면 UCS-2로 바뀌어 70자로 줄어듭니다.
흔한 실수
- 바이트 제한 필드를 글자 수로 재는 것(한글 100자는 UTF-8로 300바이트입니다)
- 끝에 붙은 줄바꿈 때문에 빈 줄이 하나 더 세어지는 것을 놓치는 것
- 띄어쓰기가 없는 중국어·일본어에 단어 수를 그대로 적용하는 것
자주 묻는 질문
한글 한 글자는 몇 바이트입니까?
완성형 한글 음절은 UTF-8에서 3바이트, UTF-16에서 2바이트입니다.
UTF-16 바이트가 글자 수 × 2와 다를 때가 있습니까?
😀처럼 U+FFFF를 넘는 문자는 단위 2개, 곧 4바이트를 씁니다.
바이트 수에 BOM이 포함됩니까?
아닙니다. 글 자체만 인코딩하므로 편집기가 붙이는 바이트 순서 표시는 별도입니다.
출처: The Unicode Consortium, The Unicode Standard, Chapter 3 · IETF RFC 3629, UTF-8, a transformation format of ISO 10646 · 3GPP TS 23.038, Alphabets and language-specific information