[java] UTF-8, UTF-16과 java 문자형

UTF-8, UTF-16 이란?

UTF 뒤에 붙는 숫자의 의미는 유니코드 문자 하나를 표현할 때 사용하는 최소 bit를 의미한다
이게 무슨말이냐 하면은, UTF-8의 경우 최소 1byte로 유니코드 문자를 하나 담을 수 있고, UTF-16의 경우 최소 2byte로 유니코드 문자를 하나 담을 수 있다는 의미이다

이 두 인코딩 방식을 이용해 유니코드에서 기본 다국어 평면에 해당하는 BMP 영역의 문자를 담는다고 생각해보자

BMP의 경우 일반적인 다국어 문자 대부분을 포함하며, 범위는 0000 ~ FFFF 까지이다
https://namu.wiki/w/유니코드

UTF-16의 경우 자신이 가지고 있는 최소 공간에 BMP 영역의 모든 문자를 다 담을 수 있지만,
UTF-8의 경우 FF 의 범위가 넘어가는 문자의 경우 자신의 영역을 추가 확장한 뒤 해당 문자를 담아야 한다

이러한 특징으로 봤을때는 무조건 UTF-8이 좋아보인다
00 ~ FF 범위는 1byte를 사용해서 저장할것이고, 100 ~ FFFF 범위는 2byte를 사용해서 저장하면 되기 떄문이다
반면에 UTF-16의 경우 무조건 2byte니 낭비인 것 처럼 보인다

하지만 UTF-8 같은 가변 비트의 경우, 고정된 공간이 아니기 때문에 어디가 문자의 시작인지, 어디가 문자의 끝인지를 표시하는 영역이 추가로 필요하게 된다
이와 같은 이유로 UTF-8은 1byte의 경우 7bit, 2byte는 11bit, 3byte는 16bit 만을 문자저장에 사용할 수 있다
즉, 똑같은 BMP 문자를 저장하더라도 UTF-8은 최대 3byte가 필요하게 되는 것이다

그러므로 처음 인코딩 방식을 선택할때는 이러한 특징을 이용해 인코딩 방식을 선택해야 한다
예를 들어 영문자가 많이 사용되는 시스템에서는 UTF-8을 사용하는 것이 좋고, 다국어가 많이 사용되는 시스템에서는 UTF-16을 사용하는 것이 좋을 것이다
(확실하진 않지만 UTF-16의 경우 문자열 검색에서 더 빠르다고 한다)

웹의 경우 대부분 아스키코드를 사용하므로, UTF-8을 채택했다

그렇다면 java는?

java는 인코딩 방식으로 UTF-16을 채택했다
(이유는 모르겠지만 아마도 ascii 문자의 비율이 웹만큼 높지 않아서가 아닐런지… 그리고 문자열 처리 속도도 이유가 될 수 있을 것 같다)
그러므로 java에서 문자를 저장하기 위해 사용되는 char형의 경우, 2byte의 용량을 차지한다

BMP 영역을 넘어가는 문자(emoji 같은)는 char 형에 저장할 수 없다
String 에 char 배열로 저장하는 것 같다
이 과정에서 4byte 를 쓰게 될 것 같다(char 가 2byte 이므로)
이모지가 4 byte 가 필요하다는 것은 utf8 기준인 것 같다
어쩌피 utf16 은 최소용량이 2 byte 이므로 똑같이 4byte 가 쓰일 것 같긴 하지만…

뭐 이 이상 얘기할 것은 없는것 같고, char형과 관련된 몇가지 특징들은 아래와 같다

  • 문자의 경우 결국 다 유니코드 숫자값이기 때문에 숫자로 저장 가능하다

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    char a1 = 'a';
    char a2 = '97';
    char a3 = '\u0061';

    /**
    출력
    a
    a
    a
    **/
  • 문자와 숫자를 저장하면 숫자가 문자로 형 변환되어 연산된다

    7 + “7” == “77”

  • String의 경우 char의 배열이다