유니코드와 UTF-8, 그리고 자바...


[ Follow Ups ] [ Post Followup ] [ 자바 묻고 답하기 ]

Posted by 김덕태 on July 02, 1997 at 10:01:40:

Gil wrote:
>
> >: "F900-FFDF 에 CJK Unified Ideographs 라고해서 유니코드에 있는데 이미
> >: 4E00~9FA5 까지 (모두 20902개 , 계산이 맞는지..) 이미 한자 영역이 있습니다.
> >: 그런데 왜 저 곳에 또 무슨 "호환성문자" 라고 해서 넣었는지 모르겠습니다."
> >
> >: 라고 질문했었는데 아직도 모르겠습니다, 다시한번 여기에 :)
> >
> >Compatibility는 말 그대로 호환성이죠.
> >이는 기존의 encoding을 unicode에 대부분 수용하면서 있는 부분입니다.
> >
> >일례로 한글 완성형의 경우 한자가 음을 기준으로 나열이 되어 있습니다.
> > 그래서 중복되는 한자가 있습니다. 이를 수용하기 위해서 이러한 영역이 있습니다.
>
> 그렇네요, 惡를 예로들면,
>
> 악할 악(惡) : 완성형에서 E4C2 : 유니코드에서 60E1
> 미워할 오(惡) : 완성형에서 E7F7 : 유니코드에서 F9B9
>
> 악할 악字가 먼저나와서 그런지 그 다음에 나오는것이 호한성문자영역으로
> 들어가는군요.
>
> 읽어보니 268개의 그런 중복된 경우가 있고 Big5의 경우에는 2개 있고 나머지는
> 잘 모르겠습니다.
> GIL
> http://soback.kornet.nm.kr/~chlang



질문하신 문제에 대하여 그 의미 및 문제점을 파악하기 위해서는
유니코드의 기본 목적을 먼저 확실히 이해하는 것이 중요합니다.


==== 유니코드의 소개 ==========
다음에서 기술하는 유니코드의 목적은 첨부하는 참고문헌의 내용과
상이하며, 제가 나름대로 생각하기에 정말 중요하다고 생각되는 목적만을
나름대로 정리한 것이므로 이점 착오없으시기 바랍니다.

첫째, 통합 문자 세트.
다양한 나라가 서로 동일한 혹은 비슷한 의미의 문자를 저마다 다른 인코딩
방식을 사용함으로써, 자료 및 프로그램의 호환성 및 확장성에 문제를
일으키는 관계로 이를 하나의 문자 세트인 유니코드로 통합시켜
표현함으로써 해결한다는 것입니다.


둘째, 문자 세트 변환의 중심 역할.
기존 문자 세트 표준 (KS C 5601 혹은 일본의 JIS X 0208등등)이 N개가
존재한다고 할 경우, 다양한 문자 세트 표준사이의 변환을 위해서는 N *
(N-1)개의 변환 테이블이 필요하나 이는 구현상 상당한 부담으로
작용합니다. 따라서, 기존 문자 세트 표준사이의 변환을 할 때, 일단
유니코드로 변환한 후 다른 문자 세트 표준으로 변환하게 되면, 변환
테이블이 2 * N개만 필요하게 되므로, 문자 세트 변환을 다루는
프로그래밍이 상당히 간편해진다는 것입니다. 유니코드가 이와같이 문자
세트 변환의 중심을 차지하기위해서는, 기존 문자 세트의 문자를
유니코드로 변환한 후 다시 원래의 문자 세트로 변환하여도 원래의 자료가
변경되지 않고 그대로 복구되어야 한다는 것입니다. 이를 round-trip
conversion compatibility 혹은 source separation rule이라고 합니다.



======= 기존 표준 문자 세트와의 호환성 ==========
참고문헌의 페이지 2-8과 2-9의 내용을 인용하면,
``The Unicode Standard avoids duplicate encoding of characters by
unifying them within scripts across languages; characters that are
equivalent in form are given a single code.
... (중략) ...
The Unicode Standard avoids duplication of characters due to specific
usage in different languages, duplicating characters to support
compatiblity with base standards.
... (중략) ...
In determining whether or not to unifiy variant ideograph forms across
standards, the Unicode Standard follows the principles described in
Section 6.4, CJK Ideographs Area. Where these principles determine
that two forms constitue a trivial (wazukana) difference, the Unicode
Standard assigns a single code. Otherwise, separate codes are assigned.
... (중략) ...
Identifying a character A as a compatibility variant of another
character B implies that generally A can be remapped to B without loss
of information other than formatting. Such remapping cannot always
take place because many of the compatibility characters are in place
just to allow systems to maintain one-to-one mappings to existing code
sets. In such cases, a remapping would lose information that is felt
to be important in the original set. Compatiblility remappings are
called out in Section 7.1, Character Names List. Because replacing a
character by its compatibly equivalent character or character sequence
may change the information in the text, implementation has to proceed
with due caution. A good use of these mappings may not be in
transcoding, but in providing the correct equivalence for searching
and sorting.''


질문하신 문제와 위 인용된 문구와 연관시켜 해석해보면 다음과 같습니다.


KS C 5601에는 한자가 우리나라 한자 발음순으로 배열되어 있습니다.
따라서, `수레 차'를 의미하는 한자의 경우, `수레 거'로 읽을 수 있으므로
실제로는 동일한 한자에 대하여, KS C 5601에서는 이들을 인위적으로
`수레 거' 와 `수레 차'로 나누어 각각 0xCBE7, 0xF3B3으로 인코딩되어
있습니다.


이와 같이 인위적으로 나눈 이유는, 한자의 정렬 (sorting) 및
해당 한자 발음의 한글과의 변환에 모호성이 없어지기 때문으로 보입니다.


그러나, 한중일 통합 한자 영역에는 `수레 차'와 `수레 거'가 동시에
들어갈 수는 없습니다. 이러한 구분은 우리나라에서만 의미 있는 것이므로
`수레 차'의 의미와 `수레 거'의 의미를 구분하지 않는 대표적인 한자
한개만이 들어가야합니다.


KS C 5601과 유니코드의 대응 테이블을 찾아보면, KS C 5601의 `수레 차'는
유니코드의 한중일 통합 한자 영역에 있는 0x8ECA에 대응되고, `수레 거'는
KS C 5601 표준과의 호환 한자 영역내에 있는 0xF90E로 대응되어 있습니다.
즉, `수레 차'는 해당 한자를 대표하는 것으로 간주되고, (아마, `수레
차'가 더 일반적인 발음이므로 그렇게 선택한 것으로 생각됩니다.) `수레
거'는 유니코드로부터 KS C 5601로 다시 역변환해도 round-trip conversion
compatiblity에 의해서 그대로 복구되기 위해 존재하는 것입니다.


하지만, 때로는 `수레 거,차' 구분없이 하나의 유니코드 문자 (0x8ECA)로
대응 (compatibility remapping)시킬 필요가 있습니다. 즉, 구분없이 해당
한자를 탐색 (search)하거나, 어떤 순서 (가령 부수순)로 정렬 (sorting),
혹은 다른 문자 세트 표준과의 보다 적절한 변환이 필요한 경우입니다.
가령, JIS X 0208과 유니코드와의 변환 테이블을 찾아보면 `수레 차'에
대응하는 유니코드 값이 JIS X 0208의 해당 한자에 대응되어 있으나,
`수레 거'에 대응하는 유니코드 값은 해당 한자에 대응되어 있지 않습니다.
(이유는, 2개의 유니코드 값이 하나의 JIS X 0208로 대응될 경우,
1:1 대응이 깨져서 약간 다른 의미의 round-trip conversion
compatibility를 유지하지 못하기 때문으로 보입니다.)
즉, KSC 5601과 JIS X 0208사이의 한자 변환은 compatibility remapping을
하여야만 `수레 거'도 변환이 된다는 것입니다.
이러한 remapping된 값은 참고문헌의 페이지 7-470의 테이블을 보시면,
`수레 거'에 대응하는 유니코드 값이 0xF903이지만 바로 위에 compatiblity
remapping된 유니코드 값인 0x8ECA (KS C 5601의 `수레 차'에 대응하는
유니코드 값)가 적시되어 있습니다.
(시스템마다 다르겠지만, 이런 remapping을 해주는 함수가 제공될 가능성이
있습니다.)


그러나, compatibility remapping을 하게 되면 `수레 거'와 `수레 차'를
구분한 본래의 의미를 상실하게 되어서 무조건 이와 같이 remapping할 수는
없는 것이므로, 특정 application이 상황에 맞는 경우에만 remapping을
하는 것이 적절하여 보통의 변환 함수를 사용하게 되면 remapping을 하지
않을 것입니다.


그런데, 여기서 한가지 주의 해야할 점이 있는데,
유니코드 값 0x8ECA만이 주어졌을 때,
`수레 거'와 구분 되는 `수레 차'의 의미를 갖는 것으로 볼 수도 있고,
`수레 거' 혹은 `수레 차' 2개를 대표하여 이 둘 사이를 구분하지
않는 의미를 갖는 것으로 볼 수도 있는 약간 상반된 2가지 의미론을 동시에
갖는다고 해석됩니다.
제가 이해하기 곤란한 부분이 바로 여기에 있습니다.
유니코드가 이와 같이 모호한 의미론을 갖고 있는 것인지,
아니면, 제가 참고문헌을 제대로 이해하지 못했다거나 더 엄밀한 문서가
혹시 있는 지, 저로서는 모르겠습니다.


또, 정부에서 제정한 KS C 5700이 유니코드 사양과 완전히 동일한 것인지,
아니면 보다 구체적인 사양이 추가되어있는 지, 그래서, 유니코드의
KS C 5601 호환 한자 영역은 가능하면 사용하지 말고 mapping시키도 말
것을 권장하는 지침같은 것이 있는 지도 모르겠습니다.
아시는 분이 계시면 posting 바랍니다.


하지만, 제 개인적인 소견으로는, 유니코드가 다루고 있는 한자의 수
(2만여자)가 KS C 5601 (4888자)보다 휠씬 많고, KS C 5601에 포함되지
않은 한자 중에서, 2개이상의 우리나라 발음을 갖는 한자가 많이 있을
것이므로, 이들에 대하여 모두 호환 한자 유니코드 값을 새로이 할당할
계획이 없다면 (아마, 없겠죠?), 유니코드의 사용이 확대되는 시점에
이르렀을 때, 호환 한자 영역의 사용을 자제하도록 (즉, compatibility
remapping이 default 변환이 되도록) 하고, 따라서, 유니코드 값 0x8ECA의
의미론을 `수레 차', `수레 거'를 대표하는 것으로 의미론을 고정시키는
것이 바람직하다고 봅니다.



============== 유니코드와 UTF-8 인코딩 ====================
한가지 더 제 의견을 개진하고 싶은 것은, 유니코드는 여러가지로
따져보았을 때 프로그램 내부에서 사용하거나 특정 프로그램만이 이해하는
화일 혹은 교환되는 자료의 인코딩으로 적당할 뿐, 일반 텍스트 문서의
인코딩, 혹은 다양한 프로그램 사이에 전달되는 텍스트 자료의
인코딩으로서는 부적당하다는 것입니다. 따라서, 현재와 같이
우리나라에서 일반화된 인코딩 표준인 KS C 5601 (좀더 정확히는 EUC-KR)을
대체하기는 곤란하며, 유니코드와 1:1 대응할 뿐만 아니라, 여러가지
우수한 성질을 갖는 UTF-8 인코딩이 KS C 5601의 대체 인코딩 방법이라는
것입니다. 따라서, 우리나라가 가능하면 빨리 UTF-8로 이행하는 것이
바람직하다고 생각합니다.



============== 참고문헌 ========================


[1] ``The Unicode Standard, Version 2.0,'' The Unicode
Consortium, Addison Wesley, 1996
(평가) 유니코드에 대하여 자세하고 전반적인 설명과 함께, 모든 정의된
유니 코드 문자의 일반적인 특징 및 출력된 모양이 소개되어
있다.



p.s. 유니코드에 대한 오해의 소지를 최소화하고 논의를 활성화하기
위하여 Unicode, Inc. 및 Addison Wesley의 허락 없이 함부로 인용한
점에 대하여 Unicode, Inc. 및 Addison Wesley에 사과의 뜻을
표합니다.



================== 첨부 ============================================
첨부하는 프로그램은 유니코드와의 변환을 제공하는 자바 프로그램입니다.
(JDK1.1 버전)
char 자료형 및 String 자료형이 모두 유니코드이므로, 유니코드의 첫째 및
둘째 목적에 부합하는 프로그래밍이 자연스럽고 손쉽습니다.


-------- HanjaTest.java ----------
// KSC5601내의 한자 범위: 0xCAA1 ~ 0xFDFE (4888 자 = 52 * 94)
public class HanjaTest
{   public static void main(String args[])
        throws java.io.UnsupportedEncodingException
    {
        for( int high =  0xCA; high <= 0xFD; ++high )
            for( int low =  0xA1; low <= 0xFE; ++low )
            {
                String unicode = new String(
                    new byte[] {(byte) high, (byte) low}, "KSC5601");
                byte[] eucjis = unicode.getBytes("EUCJIS");

System.out.print( Integer.toHexString(high) + Integer.toHexString(low) + " (" + unicode + ") ==> " + Integer.toHexString((int) unicode.charAt(0)));

if ( eucjis.length == 1 && (eucjis[0] & 0xFF) == '?' ) System.out.println( ", 없음" ); else System.out.println( ", " + Integer.toHexString(eucjis[0] & 0xFF) + Integer.toHexString(eucjis[1] & 0xFF) ) ; } } } -------------- end of HanjaTest.java ----------------

C:> java HanjaTest | more (KSC5601, 유니코드, EUCJIS순으로 해당 코드 값을 출력)

... 전략 ... cbe7 (車) ==> f902, 없음 // 수레 거 ... 중략 ... f3b3 (車) ==> 8eca, bcd6 // 수레 차 ... 후략 ...

--
Deogtae Kim (김덕태)
CA Lab. CS Dept. KAIST
E-Mail : dtkim@camars.kaist.ac.kr
Phone : +82-42-869-3569
Fax : +82-42-869-3510



Follow Ups:



이어서 글올리기(답하기)

이름:
E-Mail:
제목:
내용:
관련 URL(선택):
URL 제목(선택):
관련 이미지 URL:


[ Follow Ups ] [ Post Followup ] [ 자바 묻고 답하기 ]