본문 바로가기

기타/알아두면 좋은 CS 지식

유니코드 , UTF-8 , EUC-KR

조엘 온 소프트웨어의 [유니코드와 문자집합에 대한 고찰] 절을 읽고,
컴퓨터에서 문자를 어떤식으로 다루는지 정리 할 필요가 있다고 느껴졌다.

 

책에서는 이 주제를 얘기하기 위해 ASCII 에 관한 얘기부터 시작한다.

ASCII 코드

위키에 나온 정의에 따르면 다음과 같다.

미국정보교환표준부호(영어: American Standard Code for Information Interchange),
또는 줄여서 ASCII( /ˈæski/, 아스키)는 영문 알파벳을 사용하는 대표적인 문자 인코딩이다

쉽게 말하면 총 7개의 비트로 영문 알파벳, 숫자, 기타 부호를 표현하기 위한 문자 인코딩 방식이다.
7bit 로 이루어져 있어서 총 128개의 문자를 표현할 수 있다.

 

정확히는

  • 33개의 출력 불가능한 제어 문자들
  • 공백을 포함한 95개의 출력 가능한 문자들
    (영문 알파벳 대소문자 + 10개의 숫자 + 32개의 특수문자 + 하나의 공백문자)

로 이루어져 있다.

여기서 제어 문자들은 역사적인 이유로만 남아있고, 대부분은 더 이상 사용되지 않는다고 한다.

ASCII 코드표

https://ko.wikipedia.org/wiki/ASCII 참고

표를 보면 실제 출력 가능한 문자들은 십진수 기준으로 32 ~127 까지이다.

코드 페이지

대다수의 컴퓨터는 8bit 인 바이트 단위를 사용한다.
문자를 표현할 때 ASCII 는 7bit 만 사용하므로 1bit 는 자유자재로 쓸 수 있게 된것이다!
128 ~ 255 사이의 글자의 정의는 각자의 용도에 맞게 정의 되었다.

 

지역에 따라 128 이상의 문자를 다루는 방식이 달랐고, 이런 시스템을 코드 페이지 라고 부른다.
영어는 코드 페이지 437, 한국은 949 를 사용한다.
각 코드 페이지는 128 미만에 위치한 글자는 모두 동일하지만, 128 이상의 글자들은 국가별로 모두 다르다.

주로 MS-DOS 같은 OS 에서 쓰인다고 한다.

 

그러나 이 8bit 로도 각국의 문자들을 모두 표현하기에는 부족했다...
그래서 나온 것이 유니코드 다.

유니코드

위키에 나온 정의를 보자면,

유니코드는 전 세계의 모든 문자를 컴퓨터에서 일관되게 표현하고 다룰 수 있도록 설계된 표준이다.

즉 모든 문자를 컴퓨터에서 표현하기 위해 마련한 1:1 코드표 이다.
각 알파벳, 문자에 존재하는 관념적인 철자마다 고유 번호를 붙여놓았고, U+0645 이런 식으로 표현한다.
여기서 U+ 는 유니코드 를 의미하고, 번호는 코드 포인트 라고 한다. 번호는 16진수로 표현한다.

 

HI 를 유니코드로 표현하면,
U+0048 U+0049 가 된다.

 

그럼 이제 코드 포인트 숫자를 각각 두 바이트로 저장하면 되겠다! 했지만...
이 또한 다른 문제들이 생겼고 (책에서는 리틀엔디안,빅엔디안 방식을 예로 들었다),

이런 문제들은 인코딩 방법들이 나오면서 해결됐다.

인코딩

인코딩은 유니코드 코드 포인트를 따르는 문자열을 컴퓨터에 저장하는 방법을 말한다.
이 인코딩 방식 중 하나가 많이 들어본 UTF-8 이다.

UTF-8

각 글자(코드 포인트) 마다 바이트가 다른 가변 인코딩 방식이다.

 

코드 범위 16진수 최소 ~ 최대 이진수 바이트 배열
00000000 ~ 0000007F 0xxxxxxx
00000080 ~ 000007FF 110xxxxx 10xxxxxx
00000800 ~ 0000FFFF 1110xxxx 10xxxxxx 10xxxxx
00010000 ~ 001FFFFF 11110xxx 10xxxxxx 10xxxxx 10xxxxxx
00200000 ~ 03FFFFFF 111110xx 10xxxxxx 10xxxxx 10xxxxxx 10xxxxx

0 ~ 127 사이 ( ~ U+007F) 의 코드 포인트는 1바이트로 저장한다. (위 표의 첫번째 행 참고)
즉 7bit ASCII 문자와 동일한 방식으로 표현된다.

 

128 이상의 코드 포인트만 2, 3 바이트에서 시작해서 최대 한계인 6 바이트까지 확장해서 저장한다.

원래 UTF-8 은 6바이트를 사용해 U+7FFFFFFF 까지의 코드 포인트를 표현 할 수 있게 했으나,
유니코드에서 실제로 정의하는 U+10FFFF 까지의 문자만을 표시할 수 있도록 제한했다.

실제 인코딩

U+C704 ( 유니코드 상에서 한글 '위' 를 나타낸다.) 를 UTF-8 방식으로 인코딩 하는 방식을 알아보자.

 

1) U+0800 ~ U+FFFF 사이의 영역에 있으므로 표에 따라 1110xxxx 10xxxxxx 10xxxxx 형식으로 인코딩 된다.


2) 16진수 C704 는 2진수로 표현하면 1100 0111 0000 0100 과 같다.


3) 2진수로 바꾼 비트들은 순서대로 x 에 표시된 비트에 들어간다.

11101100 10011100 10000100 

 

4) 결과적으로 3바이트로 인코딩 되며 16진수로 표현하면 EC 9C 84 가 된다.

 

EUC-KR

EUC-KR 은 한글을 표현하기 위해 나온 인코딩 방식이다.

1~127 까지는 ascii 코드와 동일하다.

그 이상은 정해진 문자집합 (한글 포함)을 표현하고, 2byte 로 표현한다.

KS X 1001 문자집합을 사용한다.

ascii 처럼 각 문자에 대응하는 값이 있는 식이다.

예를 들어 '위' 라는 글자는 C0 A7 로 표현된다.

 

보통 웹상에서 한글이 깨지는 이유는 브라우저의 인코딩 방식과 서버에서 준 페이지의 인코딩 방식이 달라서다.

예를 들어 서버는 euc-kr 방식으로 인코딩을 해서 줬는데, 브라우저가 utf-8 방식을 사용하고 있는 식이다.

그러면 브라우저는 utf-8 로 디코딩을 할 것이고, 글자가 다 깨져서 보이는 것이다. 

 

참고

 

피드백 환영 합니다. :)