JAVA/JAVA Basic

[ JAVA ] JVM이 문자열을 UTF-16 방식으로 저장하는 이유

IT록흐 2021. 7. 6. 01:21
반응형

 

 

포스팅 전 이 글은 아래 사이트 글을 토대로 한 저의 추측임을 알립니다.

 

 

 

Why Java char uses UTF-16?

Recently I read lots of things about Unicode code points and how they evolved over time and sure I read http://www.joelonsoftware.com/articles/Unicode.html this also. But something I couldn't find...

stackoverflow.com

 

 

윈도우는 기본적으로 MS사가 자체 개발한 EUC-KR의 확장형인 MS949 인코딩 방식을 사용한다.  그래서 윈도우 OS에 설치된 이클립스는 파일 인코딩 방식이 디폴트로 MS949가 지정되어 있다. ( UTF-8 인코딩 방식으로도 변경가능하다. )

 

그러나

 

JVM은 문자(Char)나 문자열(String)을 메모리에 저장할 때 UTF-16 인코딩 방식을 사용한다. 

 

 

 

 

문자나 문자열을 저장할 때  왜 굳이 UTF-16 방식으로 바꾸는 걸까?

문자 인코딩에 대해서 지난 포스팅에서 다루었었다.

 

 

[ JAVA ] 문자 인코딩(Character Encoding)이란?

인간과 컴퓨터가 대화하려면 어떻게 할까? 인간의 언어는 문자, 이미지, 동영상, 소리 등이 있다. 그러나 컴퓨터는 1과 0밖에 모른다. 그러므로 우리는 문자, 이미지, 동영상, 소리를 1과 0에 대응

lordofkangs.tistory.com

 

UCS-2나 UTF-8 그리고 UTF-16은 모두 16bit 문자표인 유니코드를 따른다. 초기 JVM은 UCS-2를 사용하여 문자를 표현하였다. 그러나 UCS-2는 데이터 크기가 16bit로 고정되어 있어 65536가지의 문자가 넘어가면 추가되는 문자를 수용하지 못했다. 그래서 2004/2005년에 데이터 길이를 가변적으로 바꿀 수 있는  UTF-16 인코딩 방식이 도입되었다.

 

UTF-8을 선택하지 않은 이유는 무엇일까?

 

UTF-8은 메모리효율과 임의 접근(Random Access)에 비효율적이다.

 

 

7bit로 표현가능한 아스키코드 문자를 16bit로 표현하면 메모리 낭비이다.

 

A : 0000 0000 0100 0001  
걁 : 1010 1100 0100 0001

 

아스키코드를 주로 사용하는 영어권국가는 UTF-16 인코딩은 메모리 낭비이다. UTF-8은 이런 이유로 탄생했다. 그러나 이런 결정에는 희생이 따랐다. 16bit 유니코드표를 보자.

 

유니코드표

 

'A'를 7bit로 표현하면 0100 0001이다.

 

 

한글 유니코드표

 

한글 '걁'은 16진수로 U+AC41이므로 1010 1100 0100 0001이다. 문제는 여기서 발생한다.

 

A : 0100 0001

걁 : 1010 1100 / 0100 0001

 

빨간 부분이 겹친다. UTF-8은 8bit단위로 끊어서 문자를 해석한다. 그래서 0100 0001이 A의 8bit인지, 걁의 8bit인지 혼동이 생긴다. 한글 '걁'을 표현하고 싶은데 뒤의 8bit가 'A'와 동일하므로 문자를 인식하는 과정에서 오류가 발생할 수 있는 것이다. 그래서 UTF-8은 8bit를 넘어가는 문자를 구분하기 위해, '구분자'가 추가된다.

 

UTF-8

 

 

아스키 코드를 제외한 다른 문자들은 110이나 10같은 '헤더'가 부착된다. 


UTF-16 걁 : 1010 1100 0100 0001
UTF-8 걁 : 1110 1010 1011 0001 1000 0001

 

헤더로 인해, 16bit에서 24bit로 늘어났다.  UTF-16에서 한글은 2byte이다. 그러나 UTF-8에서 한글은 헤더가 추가되어 3byte를 차지한다. 아스키코드가 주로 사용되는 환경에서는 UTF-8이 유리할 수 있지만 다양한 문자가 사용되는 공간이라면 메모리 효율이 떨어진다.

 

 

 

 

 

 

이와같이, UTF-8 인코딩은 헤더규칙이 있기에 변환과정이 필요하여 성능도 떨어진다.

 

유니코드 문자표는 16bit를 기준으로 설정되어 있기에 UTF-16 인코딩 방식은 변환과정이 필요없다.  물론 UTF-16인코딩 방식도 가변적으로 길이가 바뀐다. UTF-16은 BMP(기본언어판)에 있는 65536가지의 문자가 16bit로 표현가능하므로 그 이상의 문자를 표현하고 싶으면 변환과정이 필요하다. 그래도 가장 자주 사용되는 문자는 6만자 안에서 해결된다. 한글도 이 안에 포함된다. UTF-8 인코딩 방식은 헤더를 탈부착하는 과정을 거쳐야 하므로 다양한 문자가 사용되는 환경에서 비효율을 초래할 수 있다.

 

그러므로 JVM은 문자나 문자열을 메모리에 저장할 때, UTF-16 인코딩 방식을 사용하여 저장한다.

 

 

 

반응형