반응형
Notice
Recent Posts
Recent Comments
관리 메뉴

간단한 개발관련 내용

Java UTF-16 히스토리 본문

Computer Science/Java

Java UTF-16 히스토리

vincenzo.dev.82 2025. 1. 31. 21:40
반응형

Java는 처음부터 UTF-16을 사용했을까?

네, Java는 1.0부터 UTF-16을 내부 문자 인코딩 방식으로 사용했음.
즉, Java의 char 타입과 String 클래스는 초기부터 UTF-16을 기반으로 동작했어.

하지만, Java의 문자 처리 방식은 유니코드(Unicode) 표준이 발전하면서 약간의 변화가 있었어.


1. Java 1.0 (1996) - Unicode 1.1 기반

🔹 Java 1.0 초기 문자 시스템

  • Java 1.0에서는 char 타입이 16비트(2바이트) 정수형 (unsigned short) 로 설계됨.
  • 당시 유니코드(Unicode 1.1)는 U+0000 ~ U+FFFF (BMP, 16비트)만 사용했기 때문에 2바이트만으로 모든 문자를 표현할 수 있었음.
  • 따라서 Java 1.0에서는 "한 개의 char = 한 개의 문자" 라는 개념이 성립됨.

✅ 당시에는 UTF-16이 아니라 "16비트 유니코드"

  • Java 1.0 시절에는 UTF-16이 아니라, 그냥 "유니코드 문자 집합(16비트 기반)" 이라고 불렀음.
  • UTF-16은 이후 유니코드 표준이 발전하면서 등장한 개념.

2. Java 2 (JDK 1.1, 1997) - UTF-16 도입

🔹 유니코드 확장 (U+10000 ~ U+10FFFF)

  • 유니코드가 발전하면서 BMP (U+0000 ~ U+FFFF) 밖의 문자가 추가됨.
  • 즉, 한 개의 char (16비트)로는 일부 문자를 표현할 수 없게 됨.
  • 이를 해결하기 위해 UTF-16 인코딩이 표준으로 채택됨.
  • Java 1.1부터 내부적으로 UTF-16 인코딩을 사용하여 보충 문자(Supplementary Characters)를 표현하기 시작함.

✅ Java 1.1 이후 주요 변화

  • UTF-16을 기본 문자 인코딩으로 채택
  • 서러게이트 페어(Surrogate Pair) 개념 도입 (char 2개로 4바이트 문자 표현 가능)
  • Character 클래스의 보충 문자 처리 메서드 추가
    • Character.isSurrogate(char c)
    • Character.highSurrogate(int codePoint)
    • Character.lowSurrogate(int codePoint)

3. Java 5 (2004) - 코드포인트 API 추가

  • Java 1.1부터 UTF-16을 사용했지만, 기존 API(charAt(), length())는 여전히 "한 개의 char = 한 개의 문자" 라고 가정함.
  • 하지만 UTF-16에서는 서러게이트 페어 문자(4바이트 문자)가 등장하여, 기존 API로는 보충 문자를 제대로 다룰 수 없는 문제가 발생함.
  • Java 5부터 codePointAt(), codePointCount() 등의 메서드가 추가됨.

🔹 주요 추가된 API

String str = "𐍈"; // U+10348 (4바이트 문자)
System.out.println("length(): " + str.length()); // 2 (서러게이트 페어라서 2개 char 차지)
System.out.println("codePointCount(): " + str.codePointCount(0, str.length())); // 1 (실제 문자 개수)
System.out.println("codePointAt(0): U+" + Integer.toHexString(str.codePointAt(0))); // U+10348

4. Java 9 (2017) - Compact Strings (최적화)

🔹 Compact Strings 최적화

  • Java 9부터 String 내부적으로 UTF-16이 아니라 "Compact Strings"을 사용.
  • ASCII(ISO-8859-1) 문자만 포함된 경우 1바이트 배열로 저장하여 메모리 사용량 최적화.
String asciiStr = "Hello";  // 내부적으로 1바이트 배열 사용
String utf16Str = "안녕";    // UTF-16 (2바이트 배열) 사용
  • Java 9 이후 String의 실제 저장 방식은 UTF-16이지만, 내부적으로 ASCII는 1바이트 배열로 저장하여 최적화됨.

5. 결론

✅ Java는 1.0부터 UTF-16을 사용

하지만 다음과 같은 변화가 있었음:

  1. Java 1.0 (1996)
    • char를 16비트로 설계 (당시 유니코드 BMP(U+FFFF)까지만 지원)
    • 사실상 UTF-16 개념 없이 "16비트 유니코드 문자 집합"을 사용했음.
  2. Java 1.1 (1997, JDK 1.1)
    • UTF-16을 표준 문자 인코딩으로 채택.
    • 보충 문자(U+10000 이상)를 표현하기 위해 서러게이트 페어 개념 도입.
  3. Java 5 (2004)
    • 보충 문자 처리를 위한 새로운 API 추가 (codePointAt(), codePointCount() 등)
  4. Java 9 (2017)
    • "Compact Strings" 최적화 (ASCII 문자만 포함된 경우 1바이트 배열 사용)

💡 즉, Java는 초창기부터 16비트 기반의 유니코드를 사용했고, Java 1.1부터 공식적으로 UTF-16을 채택하여 현재까지 유지되고 있음!

 

반응형