문자열 인코딩

#javascript#encoding#unicode
• • •

계기

문자열 자르기는 흔한 요구사항이다. 최근 어떤 문자열을 substring()으로 자르면서 이모지가 영문 또는 한글과 다르게 카운트된다는 사실을 알게 됐다.

'abcdefghij'.substring(0,5); // "abcde"
'일이삼사오육칠팔구십'.substring(0, 5); // "일이삼사오"
'🌙🌙🌙🌙🌙🌙🌙🌙🌙🌙🌙🌙'.substring(0,5); // "🌙🌙\uD83C"

자바스크립트의 문자열 인코딩

자바스크립트는 UTF-16으로 문자열을 처리한다. UTF-16은 유니코드의 인코딩 방식 중 하나이다. 유니코드는 문자를 바이트로 인코딩 하기 위한 문자 세트로 국제 표준으로서 널리 사용되고 있다. 예를 들어, 문자 AU+0041라는 형식으로 표현되고 이런 표현을 코드 포인트(Code Point)라고 한다. UTF-16은 인간의 문자를 유니코드로 표현하는 방식이다. 하나 이상의 코드 유닛(Code Unit)을 사용하여 유니코드의 코드 포인트를 인코딩한다. UTF-16에서 코드 유닛은 16비트이다.

'A'.charCodeAt(0).toString(16); // "41"

console.log('\u0041'); // "A"

이모지는 왜 다르게 카운팅될까?

코드를 다시보면 영어와 한글은 정확히 다섯 글자로 잘리는 것을 볼 수 있다. 자바스크립트의 substring()UTF-16의 코드 유닛인 16비트를 기준으로 문자열을 자르는데, UTF-16에서 영어와 한글 모두 16비트로 표현되기 때문이다. 모든 문자가 16비트인 것은 아니다. 예를 들어, 이모지는 2개 이상의 코드 유닛으로 표현될 수 있기 때문에 우리가 인식하는 글자수와는 다르게 카운팅될 수 있다. 🌙 이모지는 2개의 코드 유닛으로 표현되기 때문에 아래처럼 2개 반에서 잘리는 것을 확인할 수 있다.

'abcdefghij'.substring(0,5); // "abcde"
'일이삼사오육칠팔구십'.substring(0, 5); // "일이삼사오"
'🌙🌙🌙🌙🌙🌙🌙🌙🌙🌙🌙🌙'.substring(0,5); // "🌙🌙\uD83C"
published almost 2 years ago · last updated almost 2 years ago