원저자: Soony(fstars@shinbiro.com)
http://club.shinbiro.com/clb/bbs/sbrClbBbs_View.jsp?bbsid=50354&pg=1&artno=422
필요에 따라 일부수정함
[들어가며]
퇴근 시간을 30분 남겨두고 어처구니 없게도 일을 다 마친바람에 여느 때처럼 웹서핑을 하다가
문득 글이 조금 쓰고 싶어졌는데 필자가 아는것은 별로 없는지라 마침 필자가 문자를 다루는
프로그램 회사에 다녔을때 배웠던 것을 혹시나 모르는 분들을 위해서 미숙하지만 이야기를
해볼까 한다.
[주의]
이 글은 정말 초보를 대상으로 작성된 글로써 필자는 이글에서 논의되는 내용의 좀더 심층적인
문제나 어투등을 문제 삼는 리플을 정중히 사양합니다. 단, 잘못된 점의 지적은 환영합니다.^^
표현의 원할함을 위해서 존칭은 생략했습니다.
[1. 멍청한 컴퓨터 문자에 눈을 뜨다]
1970년대 트랜지스터 컴퓨터를 넘어 IC 칩을 이용한 컴퓨터로 하드웨어가 발전하게 됨에 따라
당시로서는 더욱 다양한 전자기기의 정보의 교류가 필요하게된다. 그런데 실상은 알다싶이
컴퓨터는 0과 1밖에 모르는 바보였으니.. 한번 상상을 해보자.
컴퓨터가 문자를 알아먹고 문자로 표현할 줄 안다면?
데이터의 입력과 출력도 기존처럼 천공카드에 구멍뚫어서 0과 1을 표현하여 집어넣는거 보다
사람이 표현하기 쉬운 글로 입력하고 컴퓨터도 그걸 그대로 알아먹고 출력할 것이 있으면
사람이 알아보게 문자로 출력하는 ~
아~ 정말 당시로서는 꿈만 같은 이야기였다...
그래서 미국에서는 70년대 말 전자 정보에서의 문자에 관한 규격을 세우고 컴퓨터에게 문자를
가르치는 일을 맘먹기에 이른다..
그럼, 이제 컴퓨터에게 문자를 가르치는 과정을 간단히 설명해보자.
이를테면 이런거다.. 디지털, 디지털 요새 참 이 단어 많이 듣는데 컴퓨터가 알아먹는 디지털
신호는 이진수 즉, 0과 1 뿐이다. 할아버지 컴퓨터도 손주 컴퓨터도 지금 이시간 당신이 가지고
있는 컴퓨터도 모든 컴퓨터는 0과 1밖에 모른다. 아닌거 같다고?
근데 어쩌나 여러분이 늘상듣는 바이트, 비트등의 데이터 단위 그게 다 0과 1의 조합이다.
자꾸 아니라는 생각이 들어도 일단은 필자를 믿어주자.
자 중요한건 컴퓨터는 문자를 모른다!
0과 1의 조합 밖에는 아는게 없다. 그러나 사람은 모니터에 문자를 표현하고 싶다는 거다.
그럼 이제 이런 가정을 해보자
1개의 비트는 0과 1, 이 2가지를 표현할 수 있다.
이때 0은 'a', 1은 'b' 라고 정하자. (정하는 거다 - 일단 필자를 믿어주자)
사람이 키보드에서 a 라고 치면 중간에서 이를 정해진 기준표에서 조회해보고
아 이거 0이군.. 해서 0으로 바꿔서 데이터를 저장한다.
b도 마찬가지..
그럼 01101 이라고 데이터가 들어가 있는 상태에서 만약 문자 1개당 1비트다 라고 정의되어
있고 지금 저 데이터를 모니터에 문자로 뿌려라 하면 컴퓨터는 있는 그대로 01101을
보여주는게 아니고 'abbab' 라고 문자로 보여주면 되는 것이다.
이게 컴퓨터에서 비트 데이터들을 문자와 매칭시켜서 표현하는 것으로 이런식으로 알파벳의
26개 문자를 어디서나 통일성 있게 순서를 두어 표준을 정하면 우리는 원하는대로 글자로
입력하여 데이터를 입력할 수 있고 출력도 할 수 있게 되는것이다.
여기서 중요한것은 무엇? "컴퓨터는 0과1의 조합밖에 아는게 없다는거다!!"
자, 근데 앞의 예제에서 보았듯이 1비트 가지고는 표현할 수 있는게 고작 2개다..
그러나 알파벳은 일단 문자가 26개, 거기다가 대문자는 안써먹나? 그래서 2배하니
52개, 음... 거기가다 간단한 부호도 쓰니 이것두 몇개 넣자 (이런거 말이다. " !$#%^ ")
음.. 또 뭐있을까.. 아.. 이녀석 한칸띄우기나 줄 새로 시작하기 뭐 이런것두 모르겠다..
(누차 강조하지만 컴퓨터는 0과1의 조합인 바이트 흐름밖에 아는게 없으며 공백이란것두 어떤
특별한 조합에 대응시켜야 알아먹지 데이터가 끊겼다고 공백이 아니다. -_- 음.. 설명이 어렵군)
그래서 공백, 라인바꾸기, 한칸 지우기 등등의 특수문자도 몇개 넣어두자..
이렇게 저렇게 잡다하게 좀 집어넣었더니 어느덧 표현해야할 가지수가 128가지나 되었다.(많이도 넣었네..ㅡ_ㅡ)
일단 128가지를 표현해야하니 비트 묶음이 7개가 필요하다. (2의 7제곱 = 128)
즉, 7비트를 하나의 묶음으로 보고 0~127까지의 표현수중 어느것이냐만 따지면 일단 알파벳과
대충 기호들을 표현할 수 있겠다
이렇게 정의된것이 ASCII 이다..
ASCII 코드표는 여기서 확인이 가능하다.
http://www.asciitable.com/
하드웨어의 조건상 처리할 데이터 크기는 적으면 적을수록 좋은거다.
1개의 문자를 표현하는데 꼭 7비트가 필요하다면 거기까지 수용하는거고 굳이 8비트씩
다룰 이유가 없다. 따라서 ASCII 는 처음에는 7비트를 1문자씩 처리하였다.
[마침]
음.. 술을 먹은것도 아니고 너무 두서없이 쓴거 같다.. 뭔 시리즈처럼 1이라고 쓰긴 했는데
사실 2가 언제 나올지는 장담 못하겠다. 반응 않좋으면 안나올지도...ㅎㅎ
암튼 기회가 된다면 다음에는 Latin1 로 넘어가면서 8비트를 1개의 문자로 다루게 됨과 더불어
일본어를 비롯한 동아시아 문자셋 얘기를 해볼까 한다.
[들어가며]
오호 통재라~ 어찌 오늘도 할일 없이 웹서핑이란 말이냐..ㅡ_ㅡ;
지난번에 이어서 이야기를 서둘러 시작해보자.. "약주한잔하고 집필하라"는 고마운 말씀도
있었으나 회사인 관계로 약주는 생략하자.
[주의]
이 글은 정말 초보를 대상으로 작성된 글로써 필자는 이글에서 논의되는 내용의 좀더 심층적인
문제나 어투등을 문제 삼는 리플을 정중히 사양합니다. 단, 잘못된 점의 지적은 환영합니다.^^
표현의 원할함을 위해서 존칭은 생략했습니다.
[2. 문자 1개는 1Byte~]
이전글의 기억을 조금 상기시켜보자. 이진 Bit 흐름 밖에 알아먹지 못하는 컴퓨터에게 문자를
다루도록 하기 위해서 미국넘들은 ASCII Code 라는걸 기준으로 채택하였으며 이 코드표에는
총 128가지의 약속이 있어서 이를 표현하려면 7비트의 경우의 수가 필요하다고 했다.
그런데 사실 7비트는 맘에 안들기는 하다. 나누고 붙이고를 좋아하는 비트 연산의 입장에서는
짝수가 맘에 들었나보다. 그래서 우리는 1Byte = 8Bit 라고 알고 있는것처럼 기본 단위는
8비트이니 7비트의 ASCII 코드를 8비트에서도 판독이 가능하도록 조정하고 이후 모든 컴퓨터
에서는 1바이트 단위로(즉, 한번에 8Bit씩) 읽어들이게 하면 읽어들인 1바이트마다 1개의 문자를
표현할 수 있게 되는것이다.
그럼 조정은 어떻게 하느냐..
예를 들면
0100001 --> 'A' (자릿수 하나당 비트 하나씩 즉, 7비트이며 현재 십진수로는 65를
나타내고 이는 ASCII Code 에서는 대문자 A를 나타낸다)
이 7비트의 앞에 0값의 비트 하나를 더 추가한다.
00100001 --> 'A' (자릿수가 하나늘어난 8비트가 되었다. 그러나 앞에 붙은게 겨우 0이
므로 십진수로 변환하면 여전히 65의 값을 가진다. 그러므로 대문자
A를 나타낸다.)
이해가 될려나..-_-; 즉, 7비트 오리지날 ASCII 로 작성된 글을 한문자씩(7비트씩) 읽어서 그
읽은것에 0인 Bit 하나를 추가하면 8비트 단위의 ASCII 로 변환이 가능한것이다.
(사실 이거 별 필요는 없다. 요새 7비트 인코딩 전송은 특별한 경우가 아니면 사용하지 않기
때문이다. 요즘엔 한 문자는 1Byte, 즉 8Bit 라고 널리 인정되고 있기 때문이다.)
[3. 문자, 서유럽으로 확장되다]
ASCII Code는 미국넘들이 자국 내에서의 정보 통신을 위해 만든것이다. 당연히 지들 쓸것만
집어넣은 것이니 미국넘들에게는 필요없는 움라우트찍은 O (즉, 이거 "Ö") 라든지 것들은
ASCII Codeset 128가지 문자에는 없는것이다. 아무리 영어가 세계어라지만 독일이나 기타
유럽어를 사용하는 나라 애덜이 기왕이면 자기나라의 문자도 표현되었으면 좋겠다고 생각할
것은 당연한 일...
컴퓨터가 미국에서만 쓸거라면 상관없지만 어디 그러한가.. 이제 세계는 바야흐로 컴퓨터 세상
인것을.. -_-;
그러나 전 강좌에서도 이야기 했지만 128가지는 이미 7Bit의 경우의 수를 다채운 것이다.
만약 이보다 더 문자를 넣고 싶다면 Bit가 늘어나야한다.
다행히 기본 단위는 7비트가 아니고 8비트 이므로 맨 앞 1비트가 비어있다.
7비트는 128가지 , 그러나 8비트는 2의 8제곱이므로 256가지
즉, 비트 하나가 더 추가 됨으로서 나머지 뒤쪽 128가지의 경우를 더 적용할 수 있는 여유가
생긴것이다.
여기서 한가지 집고 넘어갈것은 그렇게 가능하면 Bit수를 줄이려고 노력하던 예전 하드웨어
시절에서 움라우트 글자나 몇개 집어넣을거면 ASCII Code 에서 부호몇개 움라우트 글자로
대체해서 128가지를 새롭게 자기들 방식으로 맞추면 되는거 아니냐 하시는 분들은 "호환성"
이라는 글자를 가슴에 집어넣어주자..-_-;
그렇다.. 호환성이다.. 위의 가정대로 만약 독일이 자기 나름대로의 새로운 글자조합 128가지를
만들었다면 이는 독일 내에서만 사용되어야 하지 미국넘이 ASCII Code 로 작성해서 보낸
문서는 오류가 나타나게 된다.
즉, ASCII Code 에서는 33번째 문자에 "!"를 할당하였는데 독일 넘들은 우린 느낌표안써! -_-;
라며 대신 거기다 움라우트 A 를 집어넣으면 어떻게 될까.
미국넘이 본문에 "A!" 라는 2글자를 전자메일로 독일에 보냈다.
A! 라는 글자는 ASCII Code 테이블에 맞추어 00100001 00010001 요렇게 2개의 바이트로
변환되고 이것이 독일쪽으로 전송된다.
받는쪽 독일 컴퓨터에도 00100001 00010001 라는 바이트는 변함이 없다.
그러나 여기서 독일쪽 컴퓨터는 이를 문자로 변환할때 ASCII Code를 사용하는게 아니고
자체 코드를 사용하여 "AÅ" 이라고 표현해 버린다.
이게 몬가.. 전달하려는 의미를 완전히 무시해 버린게 된것이다. -_-;
한술 더떠서 ASCII Code 와는 기본 알파벳 순서 마저 다르다면?
그래서 호환성이 필요한 것이다.
미국 표준협회에서 관장하던 ASCII Code는 어느덧 하드웨어가 발달하고 컴퓨터를 사용하는
지역이 전세계로 확장됨에 따라 ISO (국제 표준 협회) 라는 기관에서 표준 글자 코드를 관장
하게 되었다.
ISO는 기본 ASCII Code를 충분히 호환하면서 서유럽 언어까지 사용가능한 새로운 문자셋을
채택하니 이른바 ISO-8859-1/Latin1 이다.
Latin1 문자셋은 앞쪽 128 (즉, 0~127까지) 에는 기본 ASCII Code를 그대로 계승하여 호환을
유지하고 뒤쪽 128 (즉, 128~255까지) 에 움라우트 붙은 글자들과 같은 서유럽 고유의 문자들
을 배치하여 문자셋을 정의하였다.
이제부터 문서 인코딩을 서유럽어(ISO-8859-1/Latin1)으로 세트하면 미국에서 작성한 문서나
독일에서 작성한 문서나 가리지 않고 같은 내용을 표현할 수 있게 된것이다.
세월은 흘러 1980년대 초 ....
동아시아에도 컴퓨터가 제법 보급되기 시작한다.
그당시에는 가장 발달 순서가 높았던 일본넘들이 일본어를 컴퓨터로 표현하고 싶어했다..
(아마 다음 강좌나 다다음 강좌에 표현하고 싶어 할것이다. -_-;)
[마침]
뭔가 할말은 많으나 꼭 쓰다보면 논지가 흐려지는 것이 아무래도 글쓰기에는 별다른 재주가
없나보다. 그나마 태클없이 이 부족한 글을 읽어주시는 몇몇 자월분들에게 고마울 뿐이다.
[들어가며]
오호.. 하루에 2개나 올리다니 너무 열정적인 강의 아닌가..>_<
필자도 바쁠땐 바쁘다.. 오해 마시길.. 오후에 잠깐 업무가 밀려서 정신이 없었다..
이 정신 없는 마음으로 그럼 3강도 시작해보자..^^
[주의]
이 글은 정말 초보를 대상으로 작성된 글로써 필자는 이글에서 논의되는 내용의 좀더 심층적인
문제나 어투등을 문제 삼는 리플을 정중히 사양합니다. 단, 잘못된 점의 지적은 환영합니다.^^
표현의 원할함을 위해서 존칭은 생략했습니다.
[4. 문자?, 문자셋?, 인코딩?, 폰트?]
틀렸다.. 원래부터 계획을 세우고 진행한 강의도 아니고 즉흥적으로 쓰다보니 강의의 순서가
틀려져 버렸다. 초보를 위해 글을 쓴다고 하고선 "문자셋" 이나 "인코딩" 의 명확한 뜻도
전달하지 않고 강의 내용에 등장했으니 얼마나 이해가 어려우셨으랴.. -_-;
그렇다고 서적에 있는 사전적 정의를 쓰겠다는 것은 아니다.. 그러나 개념은 잡고 가야하지
않겠는가? (잡을건 잡고 가자.. 갈길이 멀어도 할건 해야하는 거다 -_-)
-- 문자?
문자를 모르시는 분이야 있겠냐만은 이분야에서 중요한것은 우리가 생각하는 문자는
Case-Sensitive (대소문자 구별 즉, 대문자 A와 소문자 a 는 다름) 하다는 거다.
전 강의에서도 이야기했지만 표현할 때 구별이 되어야 한다면 A 와 a 는 다른 것이고
그래서 영어 문자는 26개가 아니고 52개라 했다. 이러한 현상은 대부분의 라틴계 알파벳을
사용하는 언어권에 다 포함되며 일본어도 그러하다. (히라가나 와 가타가나 문제가 아니고
같은 "あ" 라 하여도 작은거와 큰게 있다. 당연히 구별한다.)
-- 문자셋?
하나의 언어권에서 사용하는 언어를 표현하기 위한 모든 문자의 모임을 문자셋(Character Set 또는 Charset) 이라한다. 영어는 일단 대소문자 통틀어 56개를 일렬로 모으면 영어 문자셋이 된다. 물론 ASCII Code에서는 이외에도 부호와 공백 등과 같은 특수 문자를 더 추가하여 ASCII Character Set 으로 확정했지만 어찌되었든 주된 내용은 표현 가능 문자들의 모임이다.
그렇다면 우리의 자랑스런 한글 문자셋은 어떻게 모으면 될까?
자음 14 + 5(5는 뭐냐고? ㄲㄸㅃㅆㅉ ^^ , ㄱ 2번 연타한다고 ㄲ 되는거 아님을 안다면 이의제기 하지말고 필자를 믿어주자) 로 19개, 모음은 10 + ㅐㅒㅔㅖㅘㅙㅚㅝㅞㅟㅢ 로 21개 ... 더 있나..?
우리나라는 대소문자가 있는것도 아니고 (한글도 작은게 있다고? 그건 소문자가 아니고 글자 폰트 크기가 작은거다. 부디 혼동하지 말자-_-) 이정도면 골라쓰겠지? 대충잡아 우리도 40개정도면 한글 문자셋이라 할 수 있겠네...?
ㅡ.,ㅡ 안타깝게도 틀렸다.. 문자셋은 하나의 글자로서 준비된 문자의 모임이어야 한다. "가" 를
표현하기 위해 키보드로는 "ㄱ +ㅏ"를 순서대로 입력하지만 우리 한글은 영어처럼 순서대로 한글자씩 불러오면 되는게 아니기 때문이다. 키보드로 "ㄱ+ㅏ" 를 순서대로 입력하면 1글자폭의 준비된 "가" 라는 글자로 표현되어야 하며 그러기 위해서 문자셋에 "가" 라는 모양이 들어있어야 하는것이다. 그럼 우리 한글 문자셋의 문자는 총 몇개나 될까 ?
"가" 부터 시작하여 "각" 을 거쳐 "꾹꾼꾿꿀꿈" 등등을 지나 주루룩 ~ "힣" 까지 준비되어야 한다.
여기다 한글 언어권은 한글만 사용하는게 아니고 한자도 사용한다. 그러므로 한글언어권의 사용한자도 몇만개 준비해서 넣어두자.. 어이구야.. 이게 몇개여? ㅡ_ㅡ;
그래서 동아시아 (한자때문에라도) 언어권의 문자셋은 글자수가 많다..(참 많다.. 몇만개씩 한다.)
-- 인코딩?
인코딩이란 문자셋과 바이트 순서와의 매칭 방법이다. 예를 들어보자.. 1강의 에서 ASCII Code 의 테이블이 나와있는 주소를 링크시킨적이 있다. 이때 ABCDE... 이런것들의 모임은 문자셋이고 A는 65번 B는 66번 이렇게 바이트 순서와 매칭시킨 방법을 인코딩이라 한다.
(인코딩 ... 요새 많이 들어보는 단어 아닌가? 어디서 들어봤지? 아~~ 동영상..~
그렇다.. 동영상 파일들을 제작할때도 인코딩이라는 말을 사용한다. Wave 파일에서 Mp3로 변환하는 작업도 인코딩이라 한다. 인코딩의 사전적 의미는 문장을 암호화 한다거나 기호화 하는것을 의미한다. 동영상 인코딩은 아날로그 영상신호를 디지털 바이트 흐름으로 기호화 하는것을 의미하며 우리의 인코딩은 글자를 바이트 흐름으로 기호화 하는것이다.)
따라서 ASCII 는 인코딩 방법의 한 종류일 뿐이다. ABCDEF... 요 같은 문자셋을 가지고 필자가
A는 100번 B는 101번 ... 이렇게 순서를 정해서 "SOONY-2004-1/FUHEHE" 라는 규칙을 만들수도 있는것이다. 그러면 새로운 인코딩이 되는 것이다. 다만 아무도 알아주지 않아서 그렇지-_-;
(아무도 알아주지 않는다는 것은 위에서는 -_- 이거 하나로 넘어갔지만 사실 문제가 심각한거다
인코딩 규칙이 남과 호환되지 않는다면 전달하려는 내용이 달라진다고 2번째 강의에서 설명한바 있다. 따라서 국제 표준을 따르는 것이다.)
-- 폰트?
필자는 디자이너가 아니다. -_-; 폰트에 관한 해박한 지식이 있는것도 아니지만 어찌되었든 폰트에 대해서 우리와 연결된 내용을 설명하면 폰트는 인코딩에 의존한다는 것이다.
컴퓨터는 00100001 이라는 바이트를 만나면 ASCII Code 인코딩 테이블에 대조하여 대문자 A라고 판별하며 동시에 Arial 폰트에서 Code 65번째에 해당하는 그림을 가져오는데 그 그림이 A 라는 모양의 그림이 되는것이다. 위에도 설명했지만 "SOONY-2004-1/FUHEHE" 인코딩은 기존 ASCII 인코딩과 차별된 인코딩으로서 이 기법으로 A를 입력하면 00110010 이렇게 변환되는데
이 인코딩을 지원하는 폰트가 없이 일반 ASCII 순서에 맞춘 폰트를 사용하면 컴퓨터가 Code 100번째 에 해당하는 그림을 가져와서 뿌리니 ... "d" 윽.. -_-;
이러므로 글자그림 즉, 폰트를 만들때는 인코딩의 순서를 지켜주어야 하는것이다. 당연히 각각의 폰트는 자신이 순서를 맞춘 인코딩을 가지고 있으며 기준 인코딩이 아닌 다른 인코딩상에서 그 폰트를 억지로 로드하면 이른바 "깨지는" 글자 또는 소시적부터 게임 조금 하신다 하셨던 분들이 예전에 일본어로 된 게임들 한글 인코딩 상에서 돌릴때 즐겨보시던 "꿇뎰닳뺣" 뭐 .. 이런식으로
의미전달 기능을 완전히 잃어버리게 되는것이다.
그러므로 폰트 또한 인코딩을 탄다라는 것을 기억해두자..
(여담이지만 필자는 지금 웹 개발을 하고 있는데 언젠가 일본어로 된 홈페이지를 개발할 필요가 있었다.. 그런데 디자이너가 스타일 시트를 작성해 왔는데 모든 폰트 패밀리가 버젓이 "굴림", "돋움" 이었다는 -_-; 외국어에 대응되는 개발에 종사하시는 분들은 자신이 대응해야할 언어의 인코딩과 폰트 정도는 알아두자.. 주로 일본과 중국이 문제가 될텐데..
일본어는 MS_Gothic 또는 MS_Mincho 폰트를 사용해야 바로 보이며, 중국은 SimSun 또는 PSimsun 폰트가 각각의 인코딩에 맞춰진 폰트이다.)
[마침]
역쉬 주절이 주절이 늘어놓으니 이번 강의는 인코딩 역사 진도는 한걸음도 못나갔다. -_-;
그래도 개념을 잡는데에는 조금이나마 도움이 되었으면 한다. 혹시나 아직도 이해가 안간다면
필자의 무능함을 원망하라. 글재주가 이게 한계인듯하다.
들어가며]
필자가 다니는 회사는 점심시간이 오후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(0x80)~255(0xFF) 까지의 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 이야기 까지 가면 이제 읽을 사람만 읽으려나...ㅎㅎ
들어가며]
엇그제 한주의 시작을 알리는 월요일인거 같더니 벌써 금요일이 되었다. 주5일 근무하시는
분들이 부러울 따름이다. 필자는 요새 회사가 제품 개발의 마지막 단계에 있기 때문에 토요일
까지 근무하게되는 어처구니 없는 생활중이다. 아 부러버라~
[주의]
이 글은 정말 초보를 대상으로 작성된 글로써 필자는 이글에서 논의되는 내용의 좀더 심층적인
문제나 어투등을 문제 삼는 리플을 정중히 사양합니다. 단, 잘못된 점의 지적은 환영합니다.^^
표현의 원할함을 위해서 존칭은 생략했습니다.
[7. Big Endian? Little Endian? ]
이번에도 잠시 인코딩 역사에 대해서 한걸음 물러나 다른 이야기를 해볼까 한다. 위 제목의 단어
를 이해하시는 분이나 또는 "나는 평생 Intel 또는 AMD CPU 와 Windows OS 상에서만 놀꺼야"
라는 분들은 이 부분은 Skip 하고 넘어가셔도 된다. -_-;
눈치 빠른 분들은 느끼셨을테지만 이번에 이야기할 부분은 Platform Independent
(쉽게 말해 내가 작성한 프로그램이 Solaris, Linux, Windows 등 어떤 하드웨어나 OS의 특성과 무관하게 일관된 기능이 동작 될 수 있도록 작성된 프로그램)
한 프로그램을 작성할 때 주의해야 할 부분에 대한 이야기 이다.
자.. 가령 이러한 프로그램을 만들려고 한다고 치자.
"일본어 히라가나를 카타가나로 변환하는 프로그램"
즉, "あいうえお"(아이우에오) 라는 문장을 이 프로그램을 통과하면
"アイウエオ"(역시 아이우에오) 이렇게 바뀌는 거다.
오호~ 흥미진진한걸~ 시작해 볼까?
(참고로 필자는 지금은 어떠어떠한 이유로 웹 프로그래머가 되었지만 원래는 C 프로그래머 였다.
따라서 강의 중에도 아마 C 문법을 이용한 예가 많이 나올듯 하다. 물론 C 문법을 모르시는 분들
을 위해서 가능하면 C 문법으로 설명하는 내용을 줄이려 노력하겠지만 역으로 아직도 C 문법을
모르시는 프로그래머가 있다면 기회가 된다면 꼭 C 는 한번쯤 공부해 보시길 권한다.)
쉽게쉽게 가기 위해서 입력되는 문장은 ASCII 가 섞이지 않은 절대적인 MBCS 문자열만 들어온다고 가정하자. 즉, 한번에 2바이트씩 읽고 그걸 1개 문자라고 생각해도 무방하다는 것이다.
여러분 같으면 어떻게 작성하겠는가?
가장 쉽게 떠오르는 것은 (물론 생각이 쉽다는 것이지 방법적으로 쉬운것이 아니다.)
"あ" -> "ア" 로 매칭시키는 코드 테이블을 미리 준비하여 읽은 데이터를 코드 테이블에
대조한 후 결과를 대치시키는 방법이다. 쉽다. 아주 좋다. 히라가나 50개 데이터의 변환표만
준비되어 있다면 이 방법을 사용해도 된다.
그러나 역시 또 우리의 눈치 빠른 독자분들 께서는 느끼셨겠지만 이 방법이 아닌 다른게 있으니까 필자가 이야기 하지 않을까?
EUC_JP 인코딩에서...
(전 강의에서도 잠깐 등장했지만 EUC_ 어쩌구 하는 인코딩은 Unix 계열에서 원래 사용되던 인코딩 방법으로 EUC_JP(일본어), EUC_KR(한국어), EUC_CN(중국어) 등등이 있고 이 인코딩들은 서유럽어의 ISO-8859-1 인코딩이 확정되기 전부터 사용되던 것이라서 서유럽어와 충돌을 피하기 위한 "예약 범위" 라는 것이 전 강의에 이야기한 범위와 다르다.
즉, 이 인코딩 들은 서유럽어와 충돌이 있다. 이 인코딩들에 대한 좀더 자세한 이야기는 아마 다음에 또 할 기회가 있으리라.-_-;)
암튼 EUC_JP에서 "あ" -> 0xA1A2 일 것이다. (윽, 기억이 가물가물하다. 정확한 값은 장담못한다. 첫 강의에서 이야기 했듯이 필자가 전 직장에서 배웠던 것을 이야기하는거라서 정확한 자료들은 이젠 없다. -_-)
"あ" -> 0xA1A2
"い" -> 0xA1A4
"う" -> 0xA1A6
"え" -> 0xA1A8
"お" -> 0xA1AA
한편,
"ア" -> 0xA3A2
"イ" -> 0xA3A4
"ウ" -> 0xA3A6
"エ" -> 0xA3A8
"オ" -> 0xA3AA
자.. 이렇다.. 이쯤되면 정확한 값은 논외로 하더라도 필자가 무엇을 말하려는지 알것이다.
그렇다. 문자셋은 아무렇게나 모인게 아니다. 각 언어의 고유 알파벳 순서 대로 모여있는 것이기
때문에 순서가 뒤죽박죽이라면 매칭 테이블이 필요하겠지만 히라가나와 카타가나의 순서가
같으므로 간단한 연산으로 변환이 가능하다.
게다가 인코딩을 정할 때도 아무렇게나 여유공간에 배치시킨게 아니다. 가능하면 구별이 확실히
될 수 있도록 상위바이트가 "0xA1" 인 곳은 히라가나 전용, "0xA3" 인곳은 카타가나 전용 구역으로 설정해놓은 것이다.
히라가나가 50개 정도 밖에 안되므로 충분히 "0xA105" 라는 구역도 비어있을 터....
그래도 그 구역은 더이상 다른 글자를 배치시키지 않는다.
생각해 보시라. 어차피 2바이트를 1글자로 쓰기로 정했기 때문에 공간이 많이 남는다.
기왕이면 구역별로 고유 공간을 만들어 주는게 좋지 않을까?
이러한 특성을 안다면 이제 우리가 해야할 일은 요렇게 정리된다.
1. 2바이트를 읽어(즉, 1글자를 읽어) 일단 상위 바이트가 "0xA1" 인지 비교한다.
(맞으면 2단계로 진입, 틀리면 히라가나가 아니므로 무시하고 다음 글자 읽음)
2. 읽은 글자가 히라가나면 뒤쪽 바이트는 그대로 두고 앞쪽 상위 바이트 값에 2를 더한다.
(즉, 0xA1A2 에서 0xA3A2로 )
3. 변환한 내용을 다시 저장하고 다음 글자를 읽는다.
어떤가? 말로 썼지만 이 방법대로 프로그래밍하는거야 간단하겠지? 특별히 테이블도 필요없다.
자.. 끝....ㅡ_ㅡ;
(아 .. 돌 날라오는 소리 여기저기서 들린다. 그렇다.. 지금까지 내용중에서 Endian에 대한 이야기는 한번도 없었지 않나.. 오늘 제목이 뭔데 필자가 여기서 강의를 마친단 말인가 -_-;)
자자 흥분 가라앉히시고...이제 본격적으로 Endian에 대한 이야기를 해보자
일단 위에 말한 내용을 실제로 짜본다고 생각해보자.
C 언어가 나올것이다. 이해해 주시라.
일단 한번에 2바이트씩 읽어들일 것이므로 char 변수가 아닌 2바이트짜리 unsigned short 를
사용한다. 한글자씩 글자수대로 처리하기 위함이다. short 변수는 2바이트의 저장 공간을 갖는다
읽어들인 short 변수에서 앞쪽 1바이트 부분에만 +2 를 시킬것이다.
그리고 변경된 short 변수를 다시 데이터 저장한다.
자 여기서 문제가 발생한다.
원래 의도라면 0xA1A2 가 읽어지면 나중에 저장되는 녀석은 0xA3A2 가 되어야 한다.
그런데 결과는?
어떤 컴퓨터에서는 우리의 의도대로 0xA3A2 라는 값으로 저장되지만
다른 곳에서는 0xA1A4 라고 저장된다. 헉... -_-;
무슨 소리인지 이해가 가는가?
우리가 상위 바이트라고 생각했던 부분이 실제로 상위 바이트가 아닐 수 있다는 것이다.
즉, 파일에 0xA1A2 라는 데이터를 메모리로 읽어들일때...
순서대로 메모리에 상위 바이트가 앞으로 가도록 배치되는 컴퓨터가 있는 반면(Big Endian),
거꾸로 상위 바이트가 뒤로 가게 배치되는 컴퓨터가 있다. (Little Endian)
따라서 무턱대고 2바이트중 앞의 것이 상위 바이트 이려니 생각하고 +2를 하면
Big Endian 의 경우
메모리 상 : 0xA1 0xA2 ---> 더하기 연산 ---> 0xA3 0xA2 ----> 파일 저장 ---> 0xA3A2
Little Endian 의 경우
메모리 상 : 0xA2 0xA1 ---> 더하기 연산 ---> 0xA4 0xA1 ----> 파일 저장 ---> 0xA1A4
이렇게 작업이 이루어진다.
보면 알다시피 순서의 바뀜은 오직 메모리상에서 이루어진다. 파일에 저장될 때는 원래의 순서
대로 컴퓨터 차원에서 알아서 순서를 돌려놓는다.
Little Endian 에서 멀티 바이트 크기를 가지는 변수들의 바이트 순서가 다라진다는 것이다.
(한가지 주의 할 점은 변수 내부의 바이트 순서가 달라질 뿐 개개의 변수 순서는 달라지지 않는다.
즉, 0xA1A2A1A4 이렇게 2글자를 Little Endian 에서 short 를 이용하여 순차적으로 2개 읽으면
메모리 상에는 이렇게 올라간다.
메모리 상 : 0xA2 0xA1 | 0xA4 0xA1
위와 같이 short 라는 변수 내부에서는 바이트 순서가 달라졌지만 short 라는 2바이트 묶음으로 봤을때의 순서는 달라진게 아니다. 이점은 상당히 중요하다.
즉, 한글자를 처리하고 다음 글자를 처리하기 위해서 short 크기만큼 진행하면 다음글자에 제대로 도착한다는 의미이다. )
그럼 왜 혼동되게 어디는 Big Endian 을 쓰고 어디는 Little Endian을 쓸까?
원래 컴퓨터는 모두 Big Endian 이었다. 사람이 글을 왼쪽에서 오른쪽으로 쓰듯이 당연히 처음
설계할 때는 모두 Big Endian으로 메모리 에서도 왼쪽부터 시작하게 설계된 것이다.
그런데 다음의 예를 보자.
메모리 공간 1바이트에 다음과 같은 값이 있었다.
00010000 --> 0x10 즉, 십진수 16 이다.
그런데 컴퓨터는 하는일이 숫자 계산이 다라고 할 정도로 계산밖에 하는일 없는 녀석이다.
저기 16에 256을 더한다고 치자. 십진수로는 이제 272라는 값이 된다. 비트로는 ?
00000001 00010000 --> 값이 256이 넘기에 하나의 바이트로는 안되고 앞에 바이트가
하나더 늘어나야 한다.
바로 이거다.. 컴퓨터가 다루는 무수한 계산 과정에서 자리수가 늘어나거나 줄어드는 일은 비일비재하다. 그러나 만약 자리수가 늘어날때 마다 앞쪽에 바이트를 배치해야 하는 Big Endian이라면 먼저 있던 바이트를 뒤에 복사하고 앞에 새로운 바이트를 복사하는 작업이 필요하게 된다.
그러나 Little Endian 이라면?
십진수 272를 나타낼때 이렇게 배치된다.
00010000 00000001 --> 요렇게 원래 있던 녀석은 가만히 있고 늘어난 자리수를 표시할 바이트를 뒤에 새로 붙이면 되는 것이다. 자리수가 늘어날때 마다 뒤에 붙이고 자리수가 줄면 다시 뒤에 있던걸 없애고 Big Endian이 자리수의 변동에 따라 전체 데이터를 왔다갔다 해야하는 것보다 훨씬 나은 방법이 아니겠는가?
그래서 비교적 최근에 설계된 컴퓨터들이 계산상의 성능 향상이라는 목적으로 Little Endian을
채택하고 있는 것이다.
("이봐요 강사, 그래서 우리가 조심해야하는 것은 무엇입니까?"
특별히 없다. -_-; 이 바이트 순서 뒤집기는 메모리 상에서만 일어나는 현상이다. 기본적인 입출력시에는 컴퓨터가 알아서 다시 순서를 뒤집는다. 사용자는 메모리상에서 바이트 순서가 어떻든 전혀 신경쓸 필요가 없다. CPU와 메모리가 지들 계산 편하게 뒤집어 놓은걸 왜 사용자가 일일이 신경쓰겠는가? 알아서 돌려놓기만 하면 속에서 무엇을 하든 컴퓨터 맘이다. 우린 계산 결과만 잘나오면 장땡인것이다.
다만 예시로 작성해 보려했던 프로그램과 같이 변수와 변수의 관계가 아닌 하나의 변수속에서 바이트 순서를 직접 다루려고 하는 그러한 프로그램을 짜려면 Endian 문제를 지켜줘야 한다는 것이다. 당연하게도 컴퓨터 머리속에 있는 걸 직접 들어가서 조작하겠다 하면 순서 정도는 지켜줘야 할 것이다. )
마지막으로 누구는 Big Endian 이고 누구는 Little Endian 일까?
비교적 전통이 오래된 Sun Solaris 같은 컴퓨터는 Big Endian 을 사용한다.
일반적인 여러분 컴퓨터 즉, Intel, AMD CPU들은 Little Endian 이다.
즉, Windows 는 당연히 Little Endian 으로 처리한다.
Linux도 Intel CPU위에서 돌아가다면 Little Endian 이다.
[마침]
오늘의 내용은 인코딩과 별로 상관 없는 이야기 였지만 필자가 Endian 이라는 문제를 접한것이 바로 오늘의 예제와 같은 프로그램을 짜다가 실수한 것이라 생각나서 한번 기술해 보았다.
그런데 Little Endian 이라는 단어만 보면 필자는 자꾸 왜 Little Indian 이라는 동요가 생각나는지..-_-
[들어가며]
늘 그렇듯이 초반에는 필받아서 나름대로 열심히 하려는 의욕이 앞섰으나 다른 일에 신경을 집중하다보면 원래 건드렸던 일은 관심에서 뒷전이 되기 쉽다. 인간의 뇌는 완벽한 멀티 태스킹이 잘 안되고 또 된다 해도 멀티 태스킹을 하다보면 양쪽의 일을 다 망치기 쉽상이라....
한쪽에 집중하는 것이 좋은가 보다. 암튼 그래서 이번 강의는 상당히 늦었다는 필자의 핑계..
ㅡ.,ㅡ
[주의]
이 글은 정말 초보를 대상으로 작성된 글로써 필자는 이글에서 논의되는 내용의 좀더 심층적인
문제나 어투등을 문제 삼는 리플을 정중히 사양합니다. 단, 잘못된 점의 지적은 환영합니다.^^
표현의 원할함을 위해서 존칭은 생략했습니다.
[8. 동아시아 문자들]
오늘은 동아시아 문자셋과 인코딩에 대해서 간단히 훑어보자.
1. Japan
동아시아 국가중 가장 먼저 고유 문자셋을 정한 일본. 그렇기에 그들이 초창기 고민해서 어렵사리 구축해 놓은 방안들을 이후 한국, 중국 등등을 그대로 갖다가 자기들 글자로 바꾸어 쓰게된다. ㅡ.ㅡ
(1) JIS X 0201 - 반각 카타가나가 포함된 문자셋이다. 앞쪽 128개는 ASCII를 호환하며 뒤쪽 128개의 영역중 카타가나를 배치해서 쓰이던 초창기 일본어 문자셋.
(2) JIS X 0208 - 가장 지금 널리 쓰이고 있는 일본어 문자셋이다. 대부분 2바이트를 엮어 쓰는 MBCS이며 이를 기반으로 하는 인코딩이 EUC_JP 와 Shift_JIS 가 있다. EUC 란 (Extended Unix Coding) 이라 하여 유닉스계열에서 문자수가 많은 나라의 문자셋을 지원하기 위해 쓰이는 인코딩 기법이고 이는 MS가 주도하는 MBCS의 "예약 범위" 기준이 있기 전에 부터 쓰던것이라 서유럽어와는 충돌이 있다. (주로 문자들이 0xA1부터 시작한다.)
이 EUC방식을 충실히 따라서 일본어 문자셋을 인코딩한것이 EUC_JP 이고 반각카타가나의 1바이트 호환성 및 MS측의 MBCS 예약범위 호환성을 지켜서 배치가 EUC와는 다르게 이상해져버린 인코딩이 Shift_JIS이다. (당연 MS측은 Shift_JIS만 지원한다. ㅡ.ㅡ)
참고로 일본에서는 EUC_JP보다는 Shift_JIS를 더 많이 쓴다.
(3) JIS X 0212 - JIS X 0208 이 주로 사용하는 문자들을 모은거라면 이건 말하자면 학술논문 같은데서나 가끔보는 한자들 같은 주로 쓰이는 문자는 아닌것들을 모아놓았다. EUC_JP에서는 이걸 지원하며 Shift_JIS는 이걸 지원하지 않는다.
(4) JIS X 0213 - 최신 일본어 문자셋이다. 거의 사용치 않는 문자를 좀더 추리고 빈도높은 문자는 다시 재정렬해서 나온 새로운 문자셋.......이나.... MS가 아직 지원 계획이 없다하여 의미가 많이 퇴색했다. 다행히 MacOS X 은 얼마전부터 지원하기로 결정했다.
2. Korea (Republic of)
위에도 이야기했지만 우리나라는 일본어 문자셋 구조를 많이 본떠 왔다. ㅡ.ㅡ 그러나 나름대로 고민하여 개발한 것도 있다. 대표적인게 조합형 한글이다.
(1) KS X 1001 - 현재 우리가 쓰고 있는 문자셋이다. 한국어 처리는 대부분 이 문자셋 하나로 다 처리되며 문자수는 한글, 한자, 기호, 영문, 그리스 문자, 키릴자모, 히라가나, 카타가나 등등을 합해서 약 8천자 정도 된다. 이 문자셋은 EUC_KR, 조합형, CP949등의 인코딩이 지원한다.
참고로 좀더 설명하자면 MS측은 KSC-5601-1987 이라는 이상한 이름을 사용할때가 있는데 이 이름은 KS X 1001 의 옛날 이름이다. 우리가 완성형이라 부르는 한글은 EUC_KR이며 조합형은 문자셋은 이걸 쓰지만 인코딩 방식이 EUC_KR과 달라서 조합형이라 부른다. (하나의 문자셋으로도 인코딩은 여러개가 나올 수 있다 했다. 대표적인게 EUC_JP와 Shift_JIS)
또한 CP949는 확장 완성형이라 해서 MS가 지들 멋대로 EUC_KR에서 몇몇 글자들을 추가 및 위치 변경을 하여 거의 EUC_KR이라 생각해도 되지만 조금은 틀린 녀석이다.
(CP란 CodePage 라고 하여 IBM과 Microsoft 가 같이 사용하던 OS 내부적으로 돌아가는 문자셋 및 인코딩 번호를 의미하는데 그나마 요새는 IBM과 Microsoft 가 갈라져서 새로 지정되는 것은 번호가 양쪽이 틀리다 ㅡ.ㅡ 그래도 아직은 상당부분 같은 번호가 많다. 이 CP에 대한 내용은 나중에 설명할 기회가 있을 것이다.)
(2) KS X 1002 - 마치 JIS X 0212 처럼 자주 쓰이지 않는 옛 글자 및 사용빈도가 드문 한자들을 모아놓은 문자셋이다. 차이점은 EUC_JP는 JIS X 0212를 지원하지만 EUC_KR은 KS X 1002를 지원하지 않는다.. (즉, 이건 지원하는 인코딩이 없다. 사장되었다는 의미이다. 한때 우리 한글 인코딩이 완성형이냐 조합형이냐 로 .... 주로 사용할 인코딩이 뭐냐고 싸운적이 있는데 이때 논쟁에 밀려서 이건 빛도 보지 못했다. ㅡ.ㅡ)
(3) KS X 1005-1 - 유니코드 2.0 이상에서 표현되는 한국어에 대한 문자셋이다. 기본적으로 완성형과 같다고 보면된다. 다만 유니코드 버전이다.
3. China (Peoples Republic of)
중국 본토에서는 GB로 시작하는 문자셋, 인코딩을 사용한다. GB란 Guo-Biao(国标)를 줄여쓴 말로 국가표준이라는 뜻. 참고로 중국어 한자는 크게 2가지로 분류하는데 "나라 국" 자를 줄여서 "国" 이렇게 간략하게 표시한걸 "간체 (Simplified Chinese)" 라 하고 중국 본토에서 많이 쓰이며, "國" 이렇게 제대로 획수 다 그어 표시한걸 "번체 (Traditional Chinese)" 라 하여 대만 홍콩 싱가폴 한국 등지에서 사용되는 모양이다. 일본은 대부분 번체를 사용하지만 간혹 간체처럼 쓰는 한자도 있는데 그게 중국 본토의 간체랑 모양이 틀릴때도 있어서 일본 한자를 "간체"라고 부르지는 않는다.
(1) GB2312 - 중국 본토에서 대부분 경우에 사용하는 간체 중국어 문자셋 이다. 이게 약간 버그가 있어서 수정본이 몇개 있지만 그냥 무시하고 GB2312를 많이 사용한다. 많이 사용하는 한자 7400 자 정도가 포함되어 있고 이 한자들의 번체 버전은 GB/T12345 가 있다.
(2) GB7589 - 마찬가지로 주로 사용하지 않는 좀 드문 한자 7200개 정도의 모임인데 우리처럼 이걸 지원하는 MBCS 인코딩은 없고 단지 유니코드에는 들어가 있다.
(3) GB18030 - 2000년에 확정되어진 중국에서 사용되는 거의 대부분의 한자를 다 밀어넣은 세계 최대 문자셋이다. (유효 코드 문자수만 따지면 ISO-10646-2가 최대지만..)
중국정부는 2001년 9월부터 중국에서 발매되는 모든 OS는 저 GB18030을 반드시 지원해야한다고 강압적으로 확정시켰다. ㅡ0ㅡ
이 문자셋은 GB2312 와 완벽한 호환에 한글자당 1~4바이트의 가변적으로 길이가 변한다.
UTF-8 이 한글자에 1~6바이트 까지 변하는것에 비해 훨씬 효율이 좋으므로 중국어의 입장에서만 봐서는 더 낫다.
아무튼 이건 중국정부의 강제 규정이므로 MS도 부랴부랴 유니코드에서부터 GB18030 으로 변환하는 BytesToUnicode, UnicodeToBytes 라는 함수를 제공하여 해결했는데 좀... 이름이 이상하지? GB18030에 대한건데. Bytes라니..
4. China (Republic of , Taiwan)
요즘 본토와 사이가 더욱 나빠진 대만이다.
(1) Big5 - 대만은 글자수가 많기로 유명하다. 위에서 이야기 했듯이 전통 번체를 사용하며 글자수 약 13500개의 번체 글자로 이루어진 문자셋이다. 문제는 이 Big5는 버그가 있어서 같은 글자가 2군데 배치된 경우가 2가지 있다 하지만... 워낙 버그 있는채로 사용된지 오래되다보니 걍 무시하고 사용한다. ㅡ.ㅡ
이 Big5는 확장버전이 있는데 Big5 Plus 라고 8천자 더 추가해서 약 2만자 정도를 표현하는 문자셋도 있다.
(2) CNS11643 - 대만이 Big5 의 버그도 없애도 좀더 잘, 많이 정리하여 총 16개의 Plane을 가지는 문자셋을 제작하겠다고 야심차게 발표했던 문자셋이다. 완성만 된다면 무려 14만 글자를 가지게되는 무시무시한 녀석인데.. 그러나 아직도 확정 중 단계이고 이미 MS 나 Mac 에서는 기다리기 지루해서 Big5를 대만판 OS 표준 인코딩으로 잡았기 때문에 이게 쓰이는 일은 극히 드문일이 되버렸다. ㅡ.ㅡ
5. Korea (Democratic Peoples Republic of)
하하.. 북한도 고유의 문자셋을 가지고 있다. 모르시는 분들도 많을 듯..^^
(1) KPS-9566 - 북한의 유일한 문자셋. 다른 CJK(중국, 일본, 한국) 문자셋 들과 비슷한 구조로 만들었는데..... 한글모양이 우리보다 300글자 정도 많고 대신 한자는 200글자 정도 적다.
아.. 그리고 한가지 재미있는 사실은 한글 부분의 시작이 "가" 가 아니고 "김일성김정일" 이렇게 6글자가 먼저 배치되어 있다. ㅡ.ㅡ (우헤헤.. 이게 모냐면 한글을 순서대로 정렬하면 "김일성김정일" 이 맨 먼저 나온다는 것이다. 이넘들 뭐하는 짓인지..)
그리고 우리 한글과는 북한은 정렬 순서가 다르다. 일례로 자음의 정렬 순서가
"ㄱㄴㄷㄹㅁㅂㅅㅈㅊㅋㅌㅍㅎㄲㄸㅃㅆㅉㅇ" 으로 "ㅇ"이 젤 뒤로간다... 아마도 두음법칙이 없는 구조라서 그런가보다.
암튼 이렇게 고유 문자셋이 있지만 MS측은 KPS-9566을 지원하지 않고 있어서 실제로는 EUC_KR과 UTF-8을 이용하는 경우가 많다. 또한 유니코드도 우리측 정렬을 따르고 있으므로 만약 북한 글자를 다룰일이 있으면 정렬은 따로 함수를 만들어 다시 해줘야 할 것이다. ㅡ.ㅡ
[마치며]
참 많다.. 나라마다 쓰는 문자가 다르고 같은 언어권이라도 정책의 차이, 역사적 이유 등등으로 문자셋과 인코딩이 다 틀리다... ㅡ.ㅡ 여러분 같으면 모든 글자들을 다 지원하는 하나의 거대한 문자셋 표준을 정하고 모두 그걸로 통일 시키고 싶지 않은가? 그럼 더이상 인코딩으로 고민하고 자시고 할 것이 없지 않겠는가? 표준이 모두 커버되는 1개라면...
그렇다.. 이런 생각 이미 머리 높으신 분들이 지내시다 보니 하셨나 보다..
그게 UNICODE라는 것이다.
[들어가며]
세상엔 다양한 언어들이 있다. 이 언어의 장벽은 비단 실생활에서만 있는것이 아니고 디지털 세상에서도 분명히 존재한다. 비록 아직은 소프트웨어 기술이 언어의 장벽을 완전히 허물수는 없지만 언젠가는 자국어 하나만 알아도 모든 언어로 알아서 번역해주는 프로그램이 나오길 기대해보자... ^^ 그럴려면 일단 모든 언어를 표시는 할 줄 알아야 겠지...?
이제 UNICODE 의 시작이다.
[주의]
이 글은 정말 초보를 대상으로 작성된 글로써 필자는 이글에서 논의되는 내용의 좀더 심층적인
문제나 어투등을 문제 삼는 리플을 정중히 사양합니다. 단, 잘못된 점의 지적은 환영합니다.^^
표현의 원할함을 위해서 존칭은 생략했습니다.
[9. 세계의 문자를 하나로... ISO-10646 & UNICODE]
소시적 DOS시절에 일본어판으로 나온 삼국지를 하기 위해 필자는 DOS의 config.sys 파일을 수정하여 일본어폰트를 로딩하고 삼국지를 즐겼던 적이 있다. 그럴때 마다 불편했던 것이 일반적인 다른 프로그램을 돌릴때는 config.sys 를 원래대로 돌려놓아야 한글 환경으로 로딩되기 때문에 한창 삼국지를 잼있게 하다가 이제 다른거 해야지라는 생각이 들면 꼭 재부팅을 해야했다. ㅡ.ㅡ
DOS 6.0 시절 부터인가 여러개의 설정을 골라서 부팅 할 수 있는 멀티 부팅 기법이 적용되었지만 근본적으로 시스템이 사용하는 인코딩을 하나로 고정하여 만약 다른 언어 인코딩에 대응하고 싶다면 관련 파일을 교체하여 로딩되도록 재부팅을 하는것은 마찬가지 일이다.
우리가 텍스트 파일에 글을 입력하여 정보를 저장하면 컴퓨터는 0xA1 0x65 0xB4 ... 등과 같이 단지 이진 바이트로 정보를 저장한다. 이 정보는 어느 나라 사용자의 컴퓨터에서나 모두 0xA1 0x65 0xB4 ... 이렇게 동일한 바이트 정보로 전달될 수 있다. 단지 그 글을 사용자가 제대로 해석할 수 있느냐 없느냐는 문자셋과 인코딩에 달린것이다.
같은 바이트 정보라도 문자셋과 인코딩에 따라 다르게 표현될 수 있다는 내용은 이전 강의에서 수차례 언급한 적이 있다. 그러므로 이러한 혼동을 없애기 위해서는 세계의 문자를 다 표현할 수 있는 크고 표준적인 문자셋과 인코딩이 필요하다.
안타깝게도 쌀나라 인류가 너무 좁게만 생각하여 문자의 단위를 1바이트로 잡아버리고 동아시아에서는 어떻게든 충돌을 피하려고 상위 비트로 구별하는 등 별별 방법을 써왔지만.. 일단 인코딩 방법은 무시하고 문자셋이라도 모아보자는 생각에 80년대 중반부터 국제적인 정보표현의 표준을 담당하는 기관들의 협력으로 국제 표준 문자셋을 만들려는 노력이 시도된다.
여기서 역사 공부를 조금 해보자..
ISO-10646은 원래 국제 표준기구(ISO) 와 국제 전자 기술 위원회(IEC) 의 산하 위원회인 ISO/IEC JTC1 SC2 WG2 라는 위원회에서 제정중인 국제 표준이었다.
이 표준은 한글자를 4바이트 단위로 할당하면서 문자셋과 인코딩이 결합되던 기존의 방식을 탈피하여 하나의 문자셋으로 인코딩만 다르게 해주면 어느 언어 체계에서도 사용이 가능하도록 고안되었다. 그런데 그 구조가 복잡하고 한 글자에 4바이트씩 소모된다는게 그리 쉽게 수용할 만한 일은 아닌것이다. 생각을 해보자 . 대문자 'A' 라는 글자 하나 찍을때 0x41 한 바이트면 전세계 어디서나 알아듣는 판국인데 이걸 0x00 0x00 0x00 0x41 라는 4바이트로 꼭 표기해야하는가 말이다.
한편, ISO-10646의 4바이트 표준 제정에 대한 불만 및 확정에 대한 지지부진에 반하여 1989년
Apple, Metaphor, RLG, Sun, Xerox 등은 자신들의 OS에 다국어 지원에 대한 부분을 강화하기 위해서 Unicode Working Group 이라는 걸 조직한다.
이후 Unicode Working Group은 이름을 Unicode.Inc. 로 바꾸고 1991년 ISO-10646의 다국어 부분에 대한 표준 제정이 지지부진하니까 UNICODE 를 가져다 쓰는게 어떻겠냐고 국제 표준 위원회에 제안하여 ISO가 이를 받아들인다.
첨에 ISO-10646이 한글자를 4바이트로 하려 했던것은 현대 뿐만 아니라 학술적 이용가치가 있는 고대 언어 문자 및 추가로 제정될 지 모르는 문자까지 대비하여 공간 영역을 크게 잡은 것이었다. 그러나 비록 1바이트 ASCII 시절에 동아시아 문자를 대비하지 못해 애로사항이 많았던 과거가 있다 할지라도 4바이트 영역은 너무 크게 잡은 것이다. 4바이트가 가질 수 있는 경우의 수는 약 42억개가 된다. ㅡ.ㅡ 지구상에 아무리 많은 언어와 문자들이 있다해도 42억개를 채울 만큼은 아닐것이다. 물론 저 4바이트가 모두 문자만 할당되는 것은 아니고 구조가 복잡하긴 하지만 적어도 현대에 사용되고 있는 문자들 게다가 흔히 사용되지 않는 문자들을 제외하고 실용적인 각국의 문자들을 모으면 충분히 2바이트에 다 담을 수 있으니 ISO가 학술적 표준에서 문자셋을 접근했다면 Unicode.Inc 는 실용적 측면에서 문자셋을 접근했다 하겠다.
ISO-10646 에서 구조상 Group 00 및 Plane 00 인 부분을 BMP(Basic Multiingual Plane) 이라하는데 구조적 용어는 제쳐두고 일단 실용적으로 현재 쓰이는 문자가 할당된 영역이라 생각하자.
이 BMP 영역은 그 자체로 2바이트 코드 부호화 될 수 있는데 이 부분에 대해 Unicode.Inc 가 문자셋을 제안한 것이고 ISO 가 이를 받아들여 ISO-10646의 2바이트 실제 사용 영역은 UNICODE 문자셋과 같다.
이후 1992년 세계의 문자를 한군데 모으려는 노력을 양쪽에서 진행하는 것은 노력 낭비라 여겼는지 ISO와 UNICODE 는 통합되며 ISO/IEC JTC1/SC2/WG2 제 22차 회의에서 ISO-10646을 확정 국제 표준으로 제정되었다. 그러나 ISO-10646이란 이름은 일반인들에게는 쉽게 와 닿는 이름이 아니기에 우리에겐 일반적으로 UNICODE 라는 이름으로 더 잘알려져 있다.
[마침]
UNICODE 에 대한 강의가 본격적으로 시작되었다. 어려운 구조적 내용은 최대한 자제하고 실용적이며 이해하기 쉬운 정도에서 강의를 진행하려고 한다. 세상 모든일이 그렇듯 빠삭하게 알려고 하면 덩달아 알아야 하는 것들이 한 두개가 아니다. 우린 쉽게쉽게 개괄적인 내용만 이해하여 프로그래밍 및 실제 컴퓨터 생활에 약간의 도움이 되면 그걸로 만족하자. ^^