본문 바로가기

Server

Unicode vs UTF-8 차이점 및 golang rune이란? 쉽게 이해하기

 Unicode vs UTF-8 비교는 도커 vs VM 만큼 바보같은 비교이다. 이는 Unicode, UTF-8에 대해 제대로 이해하지 못하고 있다는 증거이며 인코딩에 대한 개념이 부족한 것이다. 이와 관련하여 설명해 본다.

 우선, Unicode는 모든 문자를 정리해두고 이 문자에 순번을 매겨둔 표이다. ASCII가 영어만을 고려해서 1Byte로 만들었다면 Unicode는 4Byte로 훨씬 넓은 범용성을 제공한다. 또한 ASCII에 대한 하위호환성을 유지한다. (무슨 뜻이냐면 ASCII에는 '김'에 해당하는 순번이 없지만 Unicode에는 있음.)

 이에 반해 UTF-8은 인코딩, 디코딩 방식이다. 인코딩에 대한 사전적인 정의는 정보의 형태나 형식을 변환하는 처리나 처리 방식이라고 나와있는데, 쉽게 생각하면 컴퓨터가 이해할 수 있는 바이너리 형태로 변환하는 방법이다. 예를 들어서, 1010101001010101 이런식으로 컴퓨터에 입력이 들어오면 컴퓨터는 이 바이너리 데이터를 10101010 // 01010101 이렇게 독립된 두 가지의 데이터로 처리를 할 것인지, 아니면 10101010+01010101 이렇게 10101010, 01010101 두 데이터에 대한 정보를 합쳐서 하나의 데이터로 처리를 할 것인지 판단할 수가 없다. 따라서 이에 대한 규칙을 설정하고, 컴퓨터에게 해석하는 방법을 알려주는 것이 바로 인코딩, 디코딩이다.

 Unicode 표나 UTF-8과 관련된 상세 내용은 다른 블로그에도 많이 있어서 해당 내용은 생략하고, 이해를 돕기 위해 코드로 예시를 들어본다. 예시는 Golang을 사용한다.

 1. Unicode 표 순번 확인

Golang에서 a := '김' 이런식으로 ''로 변수에 할당할 경우 해당 타입은 rune 즉, int32 타입으로 정해진다. 

a := '김'

fmt.Println(reflect.TypeOf(a)) // int32 (rune) -> golang에서 rune은 unicode 순번표를 나타내기 위한 자료형이라고 생각하면 된다.

fmt.Println(a) // 44608 -> unicode 순번표에서 '김'은 44608.

 2. Unicode 표 순번을 UTF-8 방식으로 인코딩.

e := make([]byte,3)

f := utf8.EncodeRune(e,b)

fmt.Println(f) // [234 185 128]

234, 185, 128 => 11101010 10111001 10000000 (utf-8 방식에 대해 정리해둔 다른 블로그 글을 보면 3byte를 사용하는 글자의 경우 첫 번째 바이트에서는 앞에 4자리, 두 번째 바이트 및 세 번째 바이트에서는 앞에 2자리를 실제 데이터가 아닌 총 몇 바이트를 사용하는 데이터인지 컴퓨터에게 알려주는 용도로 사용하는 것을 알 수 있음.  실제 데이터는 이를 제외한 데이터를 합쳐야함.)

=> 1010111001000000(1010+111001+000000)=> 44608

 

A application에서 B application으로 데이터를 전송한다고 할 때, A컴퓨터에서는 1110101010111001100000000 이렇게 B 컴퓨터로 전송, B 컴퓨터에서는 utf-8로 이 데이터를 decode한다고 정의해주면 받은 데이터를 utf-8 방식으로 해석하게 되는데 11101010 부분에서 1110은 하나의 데이터가 총 몇 바이트인지 알려주는 지표이므로 실제 데이터 부분이 아니라서 제외, 10111001 부분에서 10도 마찬가지, 10000000에서 10도 마찬가지. 즉, 1010 + 111001 + 000000 합쳐서 1010111001000000 이거를 10진수로 표현하면 44608이고 유니코드 표에 따라 B application은 44608을 '김'이라고 인식한다.

'Server' 카테고리의 다른 글

Prepared statment란? (golang)  (0) 2020.09.28