어제 오늘 내일

[JavaAPI] String 클래스 메소드와 예제(2) - Unicode 처리(1) 본문

IT/Java

[JavaAPI] String 클래스 메소드와 예제(2) - Unicode 처리(1)

hi.anna 2016. 6. 11. 21:51



java.lang.String 클래스의 메소드


public int length()

Returns the length of this string. The length is equal to the number of Unicode code units in the string.



String 클래스의 length() 메소드는 말 그대로 String의 길이를 리턴하는 메소드이다.

그런데...Unicode code units? 이건 뭐지?

이걸 알기 위해서는 먼저 Java에서 Unicode를 어떻게 표현하는지 알아야 한다.




Unicode / Code Point

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

- Wikipedia(https://ko.wikipedia.org/wiki/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C)


유니코드에서는 값을 나타내기 위해 코드 포인트(Code Point)를 사용하는데, 보통 U+를 붙여서 표현한다.

예를 들어, 'U+0041'은 'A'를 나타낸다. 붉은 색으로 표시한 0041이 코드 포인트이며, 16진수이다. 현재는 유니코드는 U+0000 ~ U+10FFFF 범위의 코드들을 정의하고 있다. (각 코드 포인트에 대한 맵핑은  http://www.unicode.org/chart/ 참조.)

유니코드의 정의 범위인 0000~10FFFF를 2진수로 변환하면 0~100001111111111111111로, 유니코드의 문자들을 모두 표현하려면 최대 21비트가 필요하다.


 

 Basic Multilingual Plane(BMP)

Supplementary Characters 

 16진수

 U+0000 ~ U+FFFF

U+FFFF이상 (~U+10FFFF)

 2진수

 0~1111111111111111 (최대 16bit)

10000000000000000 ~ 100001111111111111111 (최대 21bit)


Unicode의 코드범위는 위의 표처럼 크게 Basic Multilingual Plane(최대 16bit)과 Supplementary Characters(16bit이상) 영역으로 나뉜다. 처음 Unicode가 만들어질 당시 모든 문자 체계를 16bit 코드로 표현하도록 설계했지만, 점점 표현해야 하는 문자가 많아져, 16bit로는 모든 문자를 표현할 수 없게 되었다(주로 한자 및 기호). 그래서 결국 Supplementary Charaters가 등장하게 되었고, 21bit까지 사용하게 된 것!





Java에서는 Unicode를 어떻게 표현할까?

원래 Java는 16bit 유니코드를 사용하도록 설계되었다. 즉, Java의 char type의 사이즈는 2byte, 즉, 16bit이다. 그렇다면, Java에서는 Supplementary Character 영역의 문자들을 표현할 방법이 없다. 


그래서 Java에서는 이 유니코드들을 UTF-16방식으로 표현하여 char type에 표현한다.



UTF-16?

UTF-16(16-bit Unicode Transformation Format)은 유니코드 문자 인코딩 방식의 하나이다. 주로 사용되는 기본 다국어 평면 (BMP, Basic multilingual plane)에 속하는 문자들은 그대로 16비트 값으로 인코딩이 되고 그 이상의 문자는 특별히 정해진 방식으로 32비트로 인코딩이 된다.

- Wikipedia(https://ko.wikipedia.org/wiki/UTF-16)

위의 정의와 같이 UTF-16의 인코딩 방식에서는 유니코드의 CodePoint가 16비트 이하인 경우(Basic Multilingual Plane)에는 16비트값 그대로 인코딩을 하고, 16비트 이상인 경우(Supplementary Characters)에는 UTF-16 고유의 방식으로 32비트로 인코딩한다. (https://ko.wikipedia.org/wiki/UTF-16)


* Basic Multilingual Plane 문자 인코딩(16bit)

대문자 'A'를 표현하는 'U+0041'은 '0000000000101001'로 16bit를 채워서 그대로 표현된다.(8자리를 구분하기 쉽도록 색깔로 표시하였다.)


* Supplementary Characters 문자 인코딩(32bit)

코드 포인 '1F0A1'을 가지는 아래와 같은 카드모양의 문자를 예로 들어보자.


16진수인 '1F0A1'을 2진수로 변환하면 '11111000010100001'이고, 아래와 같이 32비트로 표현할 수 있다.

 0

 0

 0

 0

 0

 0

 0

 0

 0

 0

 0

 z

 z

 z

 z

 z

 x

 x

 x

 x

 x

 x

 y

 y

 y

 y

 y

 y

 y

 y

 y

 y

 0

 0

 0

 0

 0

 0

 0

 0

 0

 0

 0

 0

 0

 0

 0

 1

 1

 1

 1

 1

 0

 0

 0

 0

 1

 0

 1

 0

 0

 0

 0

 1


UTF-16에서는 이 32비트의 문자를 High-Surrogate와 Low-Surrogate로 변환하여 표현한다.


High-Surrogate

110110 (6bit) + ZZZZ (4bit)xxxxxx (6bit)

(ZZZZ = zzzzz - 1)

이렇게 총 16bit(2byte)로 구성되며 위의 예제를 대입하면 아래와 같다.


 1

 1 

 0

 1

 1

 0

 Z

 Z

 Z

 Z

 x

 x

 x

 x

 x

 x

 1

 1

 0

 1

 1

 0

 0

 0

 0

 0

 1

 1

 1

 1

 0

 0


Low-Surrogate

110111 (6bit) + yyyyyyyyyy(10bit)로 구성되면 위의 예제를 대입하면 아래와 같다.


 1

 1

 0

 1

 1

 1

 y

 y

 y

 y

 y

 y

 y

 y

 y

 y

 1

 1

 0

 1

 1

 1

 0

 0

 1

 0

 1

 0

 0

 0

 0

 1



그래서, '1F0A1'은 UTF-16에서 High-Surrogate 1101100000111100(2진수)와 Low-Surrogate 1101110010100001(2진수)를 합친 32bit 11011000001111001101110010100001로  표현된다.



1101100000111100을 16진수로 변환하면 D83C, 10진수로 변환하면 55356 !

1101110010100001을 16진수로 변환하면 DCA1, 10진수로 변환하면 56481 !

이 각각의 16진수를 Unicode Code Unit이라 한다.




다시 Java에서 32bit의 유니코드를 16bit의 char type으로 어떻게 표현하는지 돌아오면,

Java에서는 위의 두개의 Unicode code unit 한쌍을 char 값으로 표현한다.


정리하면,

Basic Multilingual Plane 문자는 2byte로 표현하고,

Supplementary Characters 문자는 두개의 Unicode code unit(HighSurrogate + LowSurrogete)를 이용하여 4byte로 표현한다.


영문자와 한글은 모두 Basic Multilingual Plane에 속하여 16bit로 표현되기 때문에,

일반적으로 영문자와 한글만 처리할 때는 위 사항들을 신경쓸 필요가 없다.

하지만, 한자어를 포함한 다국어 처리를 할 때는, Java에서 어떻게 문자를 처리하는지 알 필요가 있다.


실제로 유니코드가 Java에서 어떻게 표현되는 지는, 다음 포스팅에서 예제를 통해 살펴보도록 하겠다. 





반응형
Comments