Unicode Scalar Value

Any Unicode code point except high-surrogate and low-surrogate code points.

대리 코드 포인트를 제외한 모든 유니코드 코드 포인트이다.

<aside> 💡 surrogate code point란, UTF-16 에서 코드 유닛 쌍의 선행 및 후행 값으로 사용하기 위해 예약된 유니코드 값 범위에 포함된 코드 포인트이다. (라고 하는데 뭔진 모르겠다.) (대충 유니코드와 1:1 대응이 안되는 값이라고 생각하면 될 듯..)

</aside>

더 많은 정의는 The Unicode Standard - 3.9 Unicode Encoding Form을 보자.

UTF

Unicode transformation format (UTF) is an algorithmic mapping from every Unicode code point (except surrogate code points) to a unique byte sequence.

유니코드 전송을 위한 가변 길이 문자 인코딩 알고리즘이다. 이름에서 알 수 있듯이, 유니코드를 전송하기 위해 만들어졌다. (유니코드를 이진 데이터로 변환 후 전송한다.)

모든 UTF는 모든 유니코드를 유일한 바이트로 매핑해야 하며, 가역적이여야 한다. 이를 위해 손실 없는 라운드 트리핑을 지원해야 한다. 손실 없는 라운드 트리핑을 지원하기 위해, 대리 코드 포인트를 제외한 모든 유니코드는 유일한 바이트로 매핑되어야 한다.

만약 전송 혹은 번역 도중 잘못된 형식(malformed)의 바이트 시퀀스가 발견된다면(ex 110xxxxx 0xxxxxxx), 에러 신호를 보내서 프로세스를 종료시키거나, 해당 바이트를 제거하거나, 대체 문자(U+FFFD�)로 치환한다. 여기서 마지막 두 방법은 다음 바이트(0xxxxxxx)부터 정상적으로 프로세스를 이어나갈 수 있다.

<aside> 💡 MDN에 따르면, Web API 또한 USVString을 번역할 때 surrogate code points를 U+FFFD로 대체한다고 한다.

</aside>

준수한 인터프리터는 잘못 인코딩된 바이트 시퀀스를 번역하면 안되지만, 에러 복구 동작을 행할 수 있다. (물론 이 동작은 구현체마다 제각각..)

UTF-8

Universal Coded Character Set + Transformation Format – 8-bit

유니코드 문자를 이진 데이터로 변환하기 위한, 가변 길이 문자 인코딩 방식 중 하나이다. (물론 가역적이기 때문에 디코딩해서 파일을 유니코드 문자열로 변환할 수도 있다.)

const c = '위'; // U+C704
const encoder = new TextEncoder();
const encoded = encoder.encode(c);

encoded
// Uint8Array(3) [236, 156, 132, buffer: ArrayBuffer(3), byteLength: 3, byteOffset: 0, length: 3]

Array.from(encoded).map(n => n.toString(16));
// ['ec', '9c', '84']

UTF-8의 인코딩 방식은

  1. 000000~00007F(아스키 코드 포인트 영역) 까지의 유니코드 코드 포인트는 0xxxxxxx 에 맞춰 저장하며,
  2. 000080~0007FF 까지의 유니코드 코드 포인트는 110xxxxx 10xxxxxx 에 맞춰 저장하며
  3. 000800-00FFFF 까지의 유니코드 코드 포인트는 1110xxxx 10xxxxxx 10xxxxxx 에 맞춰 저장하며