유니코드와 문자 인코딩
유니코드는 전세계 모든 문자를 2바이트(+4비트)로 구성된 문자 인코딩 표준
- 흔히 유니코드라고 부르는건 표준 그 자체를 말하는 것으로 문자 인코딩이 아니다
- 유니코드의 문자 인코딩에는
UTF-8
,UTF-16
등 이 존재한다 ascii
의 경우 그 자체가 문자열 집합과 인코딩을 포함 하고있는 것유니코드 문자
라고 부르는거는 보통 유니코드 포인트 를 의미하거나
코드 포인트 안에 포함된 문자 그 자체를 의미
문자 데이터 / 바이너리 데이터
- 문자도 결국은 바이너리
- 그러나 웬만한 프로그래밍 언어들에서는 둘을 구분하여 씀
- 문자열은 다양한 인코딩이 존재하여 인코딩 마다 바이너리를 처리하는 것이 재각각임
- 그래서 다루기 쉽게하기 위해서 바이너리의 문자 인코더를 추가하여 추가적인 API 를 구성하고 있음
문자 인코딩
예제는 java 이지만 다른 언어도 마찬가지
참고
String 객체
String
객체 생성을 통한 인코딩의 잘못된 예
String str = new String("안녕".getBytes("UTF-8"), "UTF-8");
- 해당 코드는 정말 의미 없는 코드이다
안녕
이라는 글자의UTF-8
로 인코딩된byte[]
로 반환 받는다- 그리고
String
객체는UTF-8
로 인코딩된byte[]
를UTF-8
로 해석 하여 문자열안녕
을 얻는다
- 얼핏 봐서는 문자열
안녕
을UTF-8
로 인코딩 한다고 생각할 수 있지만 new String()
이 하는 건 어떤 것으로 인코딩 된byte[]
문자열을 같은 인코딩으로 해석하여 올바르게String
으로 불러올 수 있게 하는 것 뿐이다
String str = new String("안녕".getBytes("UTF-8"), "EUC-KR");
- 그렇다고 둘을 다르게 설정한다고 의미 있어지는 것도 아니다
UTF-8
로 인코딩된byte[]
를String
객체가EUC-KR
로 해석 하겠다는건데- 이러면 당연히 문자열이 깨지게 된다. 그래서 깨진 문자열 그대로
str
에 저장된다. - 당연하지만 잘못된 인코딩으로 원본 정보가 손실 되어
UTF-8
로 변환한다 해서 복원 할 수 없다
원래 용도
String str = new String(reader.readLine().getBytes("EUC-KR"), "EUC-KR");
InputStream
이나 기타 파일 I/O 객체를 통해 읽은 데이터에 인코딩을 결정하는데 쓰인다- 어떤 파일이
EUC-KR
인코딩 셋을 사용하여 그냥 읽을 경우 문자열이 깨지는데 이걸 EUC-KR
로 읽고String
이EUC-KR
로 해석하여str
에 올바른 문자열이 저장되도록 한다
쓰기
outputStream.write("안녕".getBytes("UTF-8"));
- 만약
outputStream
의 해당되는 프로그램의 인코딩 셋이 깨지는 경우 byte
로 변환할때 해당 프로그램과 동일한 인코딩 셋을 적용해야 한다
유니코드 포인트
전세계 모든 유니코드 (149,878개) 를 하나의 특수코드로 표기한 것
https://en.wikipedia.org/wiki/List_of_Unicode_characters
- 알려진것과 다르게 실제론 2바이트가 아닌
21
비트 즉2바이트+4비트
표기법
U+AC00
: 가,U+D7A3
: 힣- 보통 코딩에서 한글인지 판단할 때
가~힣
까지의 문자인지 판단해야하는게 - 바로 이 유니코드 포인트 규칙에 있음
- 보통 코딩에서 한글인지 판단할 때
Supplementary Planes
원래 유니코드 포인트는 2바이트로 즉
65535
까지 밖에 존재 할 수 없다
그래서 문자열을 확장하려고 만든 것
- 추가적으로
4
비트를 확장하여 U+10000
~U+10FFFF
까지의 문자열 범위를 말한다
프로그래밍 에서
- 보통은 유니코드 문자열을
UTF-16
형태로 유니코드 포인트를 메모리에 저장하여 - 원하는 인코딩으로 바이너리를 쓰는 형태임
- 대부분에 문자는 2바이트 자료형(Char)로 저장 할 수 있지만
Supplementary Planes
의 존재 때문에 해당 범위에 해당하는 문자열은 4바이트 까지 확장할 필요가 있다
유니코드 이스케이프 시퀀스
특정 문자를 명시적으로 표현 할 수 없을때 16진수 형태로 표현하는 방법
종류: https://learn.microsoft.com/ko-kr/cpp/c-language/escape-sequences?view=msvc-170
- 주로 문자열을
\uC11D
이런 식으로 유니코드 포인트로 표기를 할 수 있는- 해당 문자는
석
이다 - 유니코드 포인트 상에서는
U+C11D
- 해당 문자는
\n
,\t
등 이런 문자열도 포함이다- java 에서 소스코드 컴파일 시 유니코드가 포함된 문자열은 전부 이스케이프 처리된다