보이지 않는 문자들의 연합: 유니코드 이야기

2025. 3. 21. 16:44개발/개념 및 기법

728x90
반응형

옛날엔 나라별로 문자 인코딩이 다 달랐다.

영어는 ASCII, 한국어는 EUC-KR, 일본어는 Shift-JIS...

그래서 문자 하나 복붙만 해도 깨지고 뭉개지고 난리 난리~

 

그래서 등장한 유니코드 !!

 

“전 세계 모든 문자를 한 표준으로 다 담아버리자 !!!!”


 

1. 유니코드란?

전 세계의 모든 문자를 하나의 표준으로 통합한 문자 체계 !!!!

특징

  • 각 문자는 고유 코드포인트를 가짐 → 예: ‘A’ = U+0041, ‘가’ = U+AC00
  • 이모지, 한글, 일본어, 아랍어 전부 포함
  • 인코딩 방식: UTF-8, UTF-16, UTF-32 등 (저장 방식 차이)
  • 15만 개 이상의 문자를 지원하며 현재도 계속 증가

 

2. 인코딩 (UTF-8, UTF-16, UTF-32)

유니코드는 “문자를 숫자로 바꾸는 표준”이고,

인코딩은 그 숫자를 바이트로 저장하는 방법이다.

항목 UTF-8 UTF-16 UTF-32
인코딩 방식 가변 (1~4바이트) 가변 (2 or 4바이트) 고정 (4바이트)
기본 크기 영어: 1B, 한글: 3B, 이모지: 4B 대부분 2B, 희귀 문자 4B 모든 문자 4B
용량 효율 최고 (영어 위주면 특히 좋음) 보통 최악 (모든 문자가 4B)
랜덤 접근 ❌ 어려움 (가변 길이 때문) ❌ surrogate 때문에 제한적 ✅ 가능 (고정 길이라 쉬움)
ASCII 호환 ✅ 완벽 ❌ 불가능 ❌ 불가능
일반 사용처 웹, 파일 저장, 네트워크 Java, Windows 내부 처리 실험용, 특수 목적
안전성 깨져도 앞뒤만 손상 깨지면 복구 어려움 깨져도 파악 쉬움
장점 요약 작고 빠름, 범용성 최고 다국어 혼합 시 적당 인덱싱 용이, 단순한 구조
단점 요약 인덱싱 복잡 이모지 처리 복잡 공간 낭비 큼

가장 많이 사용하는 것은 UTF-8이며, 현실에서 쓸거면 그냥 UTF-8 사용 권장 !!

근데 Java String 내부는 UTF-16,

C#이나 Windows API도 대부분 UTF-16을 사용한다.

UTF-32는 디버깅/실험용에 가깝다.

 

3. 보이지 않는 문자

유니코드는 보이는 문자 뿐만 아니라, 보이지 않는 문자들도 포함되어 있다.

  • \\u200B: Zero Width Space → 눈에 안 보이는 공백 (폭이 0인 공백)
  • \\u200C: Zero Width Non-Joiner → 붙지 않게 하는 투명 문자
  • \\u2063: Invisible Separator → 시각적으로 완전 은닉됨
  • \\uFEFF: Byte Order Mark (BOM) → 눈에도 안 보이고 줄바꿈도 안 생김

화면에는 절대 안 찍히지만, 문자열 안에는 정확히 존재한다.

val s1 = "개발새발"
val s2 = "개발\\u200B새발" // Zero Width Space 추가됨!

println(s1 == s2) // ❌ false!
println(s2)       // 개발새발 ← 눈으로 보면 똑같음
println(s2.length) // 👉 5 (보이지 않는 문자가 1개 더 있음!)

 

print로 s1과 s2를 찍어보면 똑같이 “개발새발” 이라는 출력값이 나온다.

하지만 둘은 엄연히 다르다.

s1의 길이는 4, s2의 길이는 5.

 

\u200B라는 보이지 않는 공백이 존재한다.

활용 예시

  • 국제 언어 처리 (아랍어, 히브리어 등) → 결합/비결합 조절
  • PDF, 웹, 워드포맷용 은닉 처리
  • 워터마크/스팸 방지용 문자열 난독화

 

 

728x90
반응형