본문 바로가기
공부하는 하스씨/안드로이드

[펌강좌] 문자셋, 인코딩 이야기 #4

by 박하스. 2010. 2. 23.
728x90
반응형

신비로 JAVA월드 의 Soony(fstars@shinbiro.com) 님의 강좌글 펌

http://club4.shinbiro.com/clb/bbs/sbrClbBbs_View.jsp?bbsid=50354&pg=2&dbsts=A&artno=427


[들어가며]

필자가 다니는 회사는 점심시간이 오후1시부터 이다. 뭐 세상일이란게 다 장단점이 있지만

일단 1시부터라고 하면 가장 피크시간을 좀 비껴가기 때문에 식당이 붐비는 일은 드물어서

좋지만 결정적으로 아침에 너무 오래 버티기 때문에 12시쯤 벌써 배가 고픈걸 어쩌랴~

점심을 먹고 왔다.. 배부른 김에 다음 강의를 시작해 보자.

 

[주의]

이 글은 정말 초보를 대상으로 작성된 글로써 필자는 이글에서 논의되는 내용의 좀더 심층적인

문제나 어투등을 문제 삼는 리플을 정중히 사양합니다. 단, 잘못된 점의 지적은 환영합니다.^^

표현의 원할함을 위해서 존칭은 생략했습니다.

 

[5. 컴퓨터, 태평양을 건너 새로운 문자를 만나다.]

80년대 초 전자 정보 통신에 대해 동아시아 지역중 가장 먼저 발빠르게 움직인건 역시 일본이었다. 근대로 부터 오늘날 까지 지리적 여건 때문인지는 몰라도 꼭 바다 건너오는 서양의 문물은 왜 일본넘들이 먼저 받아들이나 모르겠다. -_-; (뭐 물론 요즈음에는 이런 불평이 무색할 정도로 우리 나라가 1등 먹는 것도 많이 있지만..ㅎㅎ)

 

또 옆길로 샛다. -_-; 암튼 서유럽 녀석들이 자기 언어를 인코딩해서 컴퓨터 문자로 표현하고 싶어했던 그 마음은 일본넘들이라고 다르랴.. 사실은 ISO-8859-1/Latin1 이 확정되기 전에 이미 일본넘들도 일본어를 전자 정보 통신에 표현하기 위해서 고유 문자셋과 인코딩을 연구하여 표준을 정하려고 노력하였다. 

 

초기에는 이랬다.. 아직 ASCII Code 밖에 없던 시절 문자는 1바이트라는 고정관념에서 벗어나지 못하던 시절이라 서유럽 애들의 고민과 같이 앞에 비어있는 비트 (혹시나 하는 마음이지만 잊으신 독자분들을 위해서 간단히 기억을 상기시키면 ASCII 는 128문자로 1바이트 즉, 8비트의 경우의 수 중 앞쪽 0~127번 까지를 사용한다고 했다.) 를 1로 시작해버리는 뒤쪽 128~255 까지의 공간을 활용하려고 한다. 그러나 128개의 여유공간이지만 생각보다 공간이 너무 적었다. 일본어는 가나라고 하는 표기법을 사용하는데 이게 "히라가나" 와 "카타가나" 라는 2개의 방식이 있다. 

"히라가나"는 글자가 부드럽고 둥글둥글..^^ (あいうえお)

반면 "카타가나"는 글자가 직선적이고 주로 외래어(일본의 입장에서 외래어이다)를 표기하는데 사용된다. (アイウエオ) 

이외에 여유공간의 제약을 받지 않는다면야 한자를 넣고 싶었겠으나 한자는 너무 많다.

히라가나와 카타가나도 둘 중 하나만 있으면 어차피 발음은 같으니 의미 전달에는 큰 무리가 없어보인다. 거기다 문자셋과 인코딩을 정하면 그에 따른 폰트를 그려야 하는데 히라가나는 둥글둥글해서 그리기가 힘들다. (직선이 그리기 쉽다.-_-)

 

따라서 뒷쪽 128개의 여유공간에 적당히 카타가나 (가나는 50음도라하여 대충 50개 글자가 있다고 생각하면 된다. 정확히는 50개가 채 안된다.) 와 조금의 부호를 집어넣은 문자셋을 정의하고 인코딩을 정해 사용하였으며 당시는 글자의 폭은 영어 한글자의 폭 (즉 지금의 한글 한글자의 폭의 절반) 을 맞추기 위해서 작게 카타가나가 그려진 폰트를 사용하였는데 이렇게 사용된 글자들을 "반각(半角)문자 , Half-Width Katakana" 라고 부른다.

(반각문자의 반대되는 개념으로 전각문자라는게 있다. 전각문자는 오늘날의 일본어 인코딩에서 사용되는 폰트가 그리는 즉, 한글자가 영어 폭의 2배가 되게 표현된 글자들이다.) 

 

반각문자 사용의 예 : ユウナ  (필자 파판 팬이다보니 FFX의 여주인공 "유우나"를 표기했다. -_-;)

전각문자 사용의 예 : ユウナ 

 

(보면 확실히 글자의 폭이 차이가 남을 알 수 있다. 반각의 경우는 일반 영어 글자의 폭과 같다.

기본적인 글자의 폭 자체가 틀리다는 것이다. 같은 폰트 크기인데 크기가 확연히 틀리다. 편집기 가지고 장난친게 아님을 알아주자.ㅡ_ㅡ;)

 

(그러나 반각과 전각의 구별은 글자의 폭으로 구별함을 원칙으로 해야한다. 반각글자라 해서 반드시 1바이트 일꺼라고 생각하지는 말자. 필자도 오래되어서 기억이 가물가물하지만 필자가 예전에 반각문자를 알아보았을때 의외의 결과가 있었다는 것만은 기억하는 것으로 보아 반각문자가 꼭 1바이트는 아니었던것 같다. -_- 이런 무책임한)

 

(한가지 더 참고적으로 이야기하면 전각문자는 모두 한글자를 표현하기 위해 2바이트를 필요로하는 MBCS 이다. 밑에서 설명할 것이다. 또한 위에서 반각문자에는 카타가나만 채택되었다고 했다. 따라서 반각 히라가나 라는 것은 없다. 그러나 재미있는 사실은 전각 영문자도 있다는 사실이다. 일반적인 ABCD 말고 "ABCD"  <-- 요기 표기된게 전각 영문자이다. 웹에서는 폰트의 문제로 잘 알아보기 힘들지만 메모장 실행해서 한글 "ㅍ" 을 누르고 그상태에서 한자키를 눌러보면 알반 영어폭의 2배되는 영어 알파벳을 입력할 수 있음을 알것이다. ^^)

 

[6. 공간이 없다면 공간을 만든다. MBCS - Multi Byte Character Set ]

첨엔 그런대로 쓸만했다. 카타가나 밖에 표현 못하지만 그래도 그게 어디냐.. 컴퓨터가 일본어를 표현할 수 있다니 세상 많이 발전했구나...... 라고만 생각하기엔 일본넘들의 욕심이 허락하지 않았나 보다. 그래서 일단 일본내에서 표기에 사용되는 문자들을 모아서 문자셋을 만들기 시작했다. 히라가나 + 카타가나 + 기존의 호환성을 위한 반각 카타가나 + 한자들...

정말 드물게 쓰이는 한자들을 제외한다고 해도 만여개 이상이나 공간이 필요했다.

 

이건 도저히 1개의 바이트로는 해결이 안되는 문제이다. 그래서 1개의 바이트가 1개의 문자라는 기존의 틀을 벗어나서 2개의 바이트가 1개의 문자를 나타낸다는 MBCS의 형태를 고안하게 된다.

 

2개의 바이트가 수용할 수 있는 경우의 수는 얼마나 될까?

1개의 바이트는 2의 8제곱 = 256가지

2개의 바이트는 2의 8제곱을 다시 제곱하는 것 = 2의 16제곱 = 65536 가지

 

와~!  2개의 바이트를 이용하면 6만5천개의 문자를 수용가능하게 된다. 1개의 바이트가 하나의 문자다 라는 개념만 버리면 글자가 아무리 많아도 수용이 가능하게 되는것이다.

 

그런데 정말 아무렇게나 써도 될까?

 

인코딩에서 늘 가슴깊이 새겨둬야 할 것은 이미 널리 쓰이고 있는 인코딩과의 호환성을 지켜야 한다는 것이다. 즉, 문서에 항상 일본어만 사용하는것이 아니므로 영어와 일본어가 병행되어 사용될텐데.. 문제는 그러면 어떤 글자는 1바이트 만으로도 글자가 되고 어떤 글자는 2바이트 읽어야 글자가 된다는 이야기이다..

 

즉, 이는 컴퓨터가 1개의 바이트를 읽었을때 이게 1개의 글자로 끝날 녀석인지 아니면 그 다음 바이트까지 읽어야 하는 녀석인지 구분해야 한다는 것이다.

 

가장 간단한 구분은 뭘까..?

그것은 최초 1바이트를 읽었을때 최 상위 비트가 0이면 이녀석은 일반 ASCII 이므로 영어로 출력하고 최 상위 비트가 1이면 그 다음 바이트를 읽어 2개를 묶어서 일본어 문자셋에서 찾아 1개의 일본어 글자를 표시하는 것이다.

(1바이트는 8개의 비트 조합이다.    00000000    왼쪽과 같은 상태를 0 이라하고

                                                    00000001    요건 1이다

                                                    00000100    요건 4다

                                                   ↑

                                                   젤앞에 요길 최상위 비트라고 한다. 

저 최상위 비트를 0으로 고정시킨 상태에서 나머지7비트가 가질 수 있는 숫자는 ASCII Code 범위와 같은 0~127까지이다.  그러므로 최상위 비트가 0이면 그건 ASCII 가 되겠다.)

 

(참고로 16진수 표기법에 대해 알아보자.

1개의 바이트는 십진수로는 0~255까지의 표현 범위를 가진다. - 물론 unsigned 일 때다. C나 비슷한 종류의 언어를 다루는 프로그래머들은 무슨 소리이지 이해하실 거다. 모르면 "음수는 생각지 않는" 정도로 넘어가자 -_-;

 

항상 1개의 바이트가 어떤 값을 가지는지 표현할때 십진수를 사용하면 적게는 한자리 (0~9) , 많게는 3자리 (100~255) 까지 변환시켜 놓고 본 십진수의 자리수가 일정치 않게 된다.

 

그래서 1개의 바이트를 뚝 절반 자르자 ㅡ.,ㅡ

 

절반 자르면 4개의 비트가 되고 4개의 비트는 16가지를 표현가능하다.

그래서 16진수 2자리로 표현하면 항상 일정한 자리수로 바이트의 값을 표시할 수 가 있다.

중 고등학교 시절에는 십진수가 아닌 녀석들은 오른쪽 아래에 조그만 괄호로 몇진수인지 표시하지만 이건 워드도 아니고 수학 공책도 아니다. ㅡ_ㅡ; 

그래서 이녀석이 16진수이다 라는걸 표시하는 것이 C 언어 및 C 문법을 계승하는 대부분의 프로그래밍 언어에서는 "0x"   라는 걸 붙이고 뒤에 16진수로서의 값을 기입한다. 

따라서 0x00     --->     0000 0000               십진수 0

           0x09     --->     0000 1001               십진수 9

           0x0A     --->     0000 1010               십진수 10

           0x0F     --->     0000 1111               십진수 15

           0x10     --->     0001 0000               십진수 16

           0xFF     --->     1111 1111               십진수 255

           0xFFFF  --->     1111 1111 1111 1111       십진수 65535   (16진수 2자리가 1바이트이므로 이건 2바이트를 표기한것이고 각각 FF 라는 값을 가지며 요 2바이트를 1개의 묶음이라고 생각하면 65535라는 값을 가진다는 것이다. 만약 요 2바이트는 별개의 것이다 라면 각각 255 라는 값을 가지는 서로 상관 없는 바이트가 되겠다.) 

 

요런 식이다.

 

프로그래밍 언어에서는 그렇게 표기하지만 HTML 상에서는 약간 다르다

HTML 상에서는 "&#x" 를 붙인다.

 

이제부터 필자가 0x80 이라고 표기하면 이는 십진수 80이 아니고 16진수 80이므로 십진수로는

128이라는 값을 나타냄을 의미한다. 부디 혼동하지 말찌어다 ㅡ.ㅡ)

 

 

구분이 간단하지 않은가?

 

연습해 보자

 

0xA172A37052A2A3

일단 너무 기니까 바이트 단위로 끊자.

 

0xA1 0x72 0xA3 0x70 0x52 0xA2 0xA3

 

자 이제 1바이트씩 읽으면서 싱글바이트 문자인 ASCII 인지 멀티 바이트 문자인 MBCS 인지 판독하도록 하자. (기준은 0x80  즉, 128과 같거나 크면 일단 ASCII 가 아니니까 다음 바이트와 합쳐서 1개의 글자가 되는 것이다.)

 

해석하면

0xA1 0x72 0xA3 0x70 0x52 0xA2 0xA3

   -----         -----     --       ----

A1 이 0x80보다 큰값이므로 0xA172 까지 한글자로 봐야 한다.

0xA370 도 마찬가지로 한글자, 요기까지 읽고 다음 만나는게 0x52 인데 이건 0x80을 넘지못했다

그러므로 0x52는 한글자 영어일 것이다.

다음 0xA2A3 가 한글자 이다.

 

자 이제 마지막 주의 사항만 지키면 된다. 

뭐냐면 서유럽어 인코딩과 호환성을 가져야 한다. 서유럽어 인코딩에서는 128 이상의 값들을 가지는 바이트가 나올 수 있다 그러기에 무턱대고 128이상의 바이트라고 2바이트씩 읽어대면 서유럽어 문서를 제대로 읽어올 수 없는 것이다. 

 

다행히 동아시아 MBCS들은 서유럽어 인코딩과 호환 관계를 유지하기 위해서 128~255 까지의 ASCII 와 구별되는 공간에 서로 다른 구역만 사용키로 정의했다. 

 

따라서 하나의 바이트를 읽었는데 0x00 ~ 0x7F (0~127)까지의 값이라면 ASCII 문자 이고

서유럽어는 0x80 ~ 0xA0 까지 (128 ~ 160) 공간을 동아시아 MBCS 를 위해서 비워놓았다.

바로 이자리를 MBCS 인코딩이 사용하면 되는 것이다.  (왜냐 서유럽어 인코딩도 0x80 이상의 값을 가질 수 있지만 0x80 ~ 0xA0 까지는 사용하지 않으므로 가령 0x99 라는 바이트는 서유럽어가 아니고 동아시아 MBCS 글자중 상위 바이트라고 생각하면 되기 때문이다.)

 

이렇게 앞쪽 상위 바이트가 항상 지켜야 하는 범위를 "예약 범위" 라고 하며 일본어와 한국어의 실제 예약 범위 지역은 조금 다르지만 아무튼  0x80 ~ 0xA0 까지  라는 저 예약 범위는 동아시아 모든 MBCS 가 지켜야 한다.

 

(즉, 쉽게 얘기하면 상위 바이트는 항상 저범위 안에 있어야 한다는 이야기다. 하위 바이트는 괜찮지만.. 아 그리고 이것은 EUC 계열 인코딩에는 해당 되지 않는 문제이다. EUC계열 인코딩은 다음에 이야기 하자.)

 

자.. 너무 많이 돌아왔지만... 정리하면 하나의 바이트가 ASCII 가 아니라는 값으로 힌트를 주어 그러면 2개의 바이트의 결과 값으로 문자를 정의해서 만여개 내지는 2만여개에 달하는 문자셋을 모두 커버할 수 있도록 규정한 것이 MBCS 이다.

     

 

[마침]

슬슬... 내용이 어려워지는 것 같다.. ㅎㅎ 필자인들 어쩌겠는가 어려워 지고 싶어서 어렵게 쓴게 아닌것을 ... 필자의 전문분야도 아니며 나름대로는 쉽게 쓴다고 했는데 역시 이 부분 부터는 좀 어려울 듯 하다. 아마 한글 인코딩과 UNICODE 이야기 까지 가면 이제 읽을 사람만 읽으려나...ㅎㅎ

728x90
반응형