Unicode
전 세계의 모든 문자를 컴퓨터에서 일관되게 표현하고 다룰 수 있도록 설계된 국제 표준
이전에는 문자 체계도 다르고 인코딩 방식도 달라 문자 간의 상호 호환성이 없었는데, 이러한 문제점을 유니코드를 통해 해결할 수 있게 됐다.
유니코드는 'U+0031' 과 같이 생겼다.
U+는 접두어고, 0031은 문자를 고유한 코드 포인트(Code Point)라는 숫자로 나타낸 것이다. 이 코드 포인트는 문자 코드라고도 부른다. U+0031은 숫자 1을 뜻하고, U+0041은 영어 알파벳 대문자 A를 뜻한다. 이 코드 포인트를 통해 문자나 이모지를 표현하는데, 대부분 4자리 이상의 UTF-16 진수 형태를 띄고 있다. (UTF-16은 16비트(2바이트) 단위로 문자를 인코딩하는 방식)
110만개 정도 표현이 가능하며 16진수라서 U+0000 ~ U+10FFFF 까지 다룰 수 있다.
plane(평면)
코드 포인트 전체를 17개 plane으로 나눈다. 하나의 plane은 65535(U+FFFF)개의 코드 포인트를 포함한다.
각 plane은 특정 문자 세트를 나타내는데, 첫 번째 plane인 BMP(Basic Multillingual Plane)이라고 부른다.
BMP에는 일반적인 문자(영문, 숫자)가 속하며, 한글도 여기에 속한다.
BMP을 제외한 plane은 SMP(보충 다국어 평면: Supplementary Multillingual Plane), Astral plane이라고도 불리는데 5자리 이상의 코드 포인트를 표현할 수 있고, 희귀한 문자나 특정 언어의 문자들이 추가로 포함된다. 그래서 유니코드는 다양한 plane을 통해 전 세계의 다양한 문자를 포괄하고, 사용할 수 있게 되는 것이다.
이스케이프 시퀀스
역슬래시(\)와 16진수로 값을 작성한다.
유니코드의 이스케이프 시퀀스 범위는 UTF-16진수로 U+0000 ~ U+FFFF까지 가능하다.
const escape = "\x31\x32\x33"
console.log(escape) // 123
const unicodeEscape = "\u0034\u0035\u0036"
console.log(unicodeEscape) // 456
4자리보다 더 큰 코드 포인트는 어떻게 작성할 것인지 문제가 생겼다.
확장된 유니코드 이스케이프인 \u{} 형태를 사용하면 임의의 길이를 가진 코드 포인트를 나타낼 수 있다.
중괄호 안에 16진수로 표현된 코드 포인트를 넣어 더 다양한 유니코드 문자를 표현할 수 있게 되었다.
const unicodeEscape = "\u0031\u0032\u0033"
console.log(unicodeEscape) // 123
const es6 = "\u{34}\u{35}\u{36}"
console.log(es6) //456
console.log("\u{1f418}") // 🐘
Surrogate pair
ES5는 유니코드를 4자리, ES6에서는 5자리를 표현할 수 있는데... 이러면 호환에 문제가 생긴다.
\u{1f418} 같은 형태를 ES5에서는 사용할 수 없으니 말이다.
그래서 ES5에서는 두 개의 유니코드 이스케이프 시퀀스를 사용한다.
이를 Surrogate pair라고 한다.
const pair = "\uD83D\uDC18"
console.log(pair) // 🐘
String.prototype.fromCodePoint()
유니코드의 코드 포인트에 해당하는 문자를 반환한다.
파라미터에 다수의 코드 포인트를 작성할 수 있다.
아래 코드를 보면 유니코드의 코드 포인트 49, 50, 51에 해당하는 숫자 123이 출력되었다.
가각도 같은 원리로 출력되었고 코드 포인트를 16진수로 작성한 경우에도 동일하게 출력된다.
const point = String.fromCodePoint;
console.log(point(49, 50, 51)); // 123
console.log(point(44032, 44033)); // 가각
console.log(point(0x31, 0x32, 0x33)); // 123
console.log(point(0x1F418)); // 🐘
ES5의 fromCharCode()도 있는데 여기서는 5자리를 쓸 수 없어서 위에서 말한 Surrogate pair로 작성해야 한다.
console.log(String.fromCharCode(0xD83D, 0xDC18)) // 🐘
String.prototype.codePointAt()
괄호 안에 유니코드로 변환할 문자열의 인덱스를 작성한다.
가나다에서 2번째 인덱스인 다의 코드 포인트가 출력됐다.
만약 없는 3번째 인덱스의 값을 유니코드로 변환하려고 하면 undefined가 뜬다.
45796에 해당되는 문자를 확인하고 싶으면 String.fromCodePoint로 해당 값을 넣어주면 매칭되는 문자가 나온다.
const result = "가나다".codePointAt(2)
console.log(result) // 45796 (다의 코드포인트)
console.log(typeof result) // number
console.log("가나다".codePointAt(3)) // undefined
console.log(String.fromCodePoint(result)) // 다
String.prototype.normalize()
대상 문자열을 유니코드 정규화 형식으로 반환한다.
정규화 형식은 NFC, NFD, NFKC, NFKD 4가지가 있다.
가로 표시되지만 뭔가 이상하다. 정규화 형식으로 반환해보자.
console.log("ㄱ".codePointAt().toString(16)); // 3131
console.log("ㅏ".codePointAt().toString(16)); // 314f
console.log("\u{3131}\u{314F}") // ㄱㅏ
NFKC, NFKD 형식으로 반환했을 때 자음과 모음을 모아 표시한다는 걸 알 수 있다.
const point = "\u{3131}\u{314F}";
console.log(point.normalize("NFC")); // ㄱㅏ
console.log(point.normalize("NFD")); // ㄱㅏ
console.log(point.normalize("NFKC")); // 가
console.log(point.normalize("NFKD")); // 가
'👋🏻 JavaScript > 📖 자바스크립트 ES6+' 카테고리의 다른 글
[JS] Object 오브젝트 중 is 메서드와 복사를 알아보자 (0) | 2023.06.20 |
---|---|
[JS] String 오브젝트 중 다양한 메서드를 알아보자 (0) | 2023.06.20 |
[JS] Number 오브젝트를 알아보자 (0) | 2023.06.19 |
[JS] getter, setter를 알아보자 (0) | 2023.06.15 |
[JS] Default Value를 알아보자 (0) | 2023.06.15 |