티스토리 뷰
아스키코드? 유니코드가 뭐지?
- 컴퓨터가 처음 발명되었을 때 표현 가능한 문자는 128개였다. 이를
ASCII
코드라고 한다. 영어 알파벳과 통화를 포함한 여러 기호를 표현할 수 있었기에 미국을 중심으로 한 영어권에서는 사용하는데 아무 문제가 없었다. - 컴퓨터가 보다 대중화되면서 대부분의 서유럽 언어의 알파벳을 추가하여 256개의 문자를 표현할 수 있게 되었다. 이를
ISO-8859-1
코드라고 한다. 유명한 오픈 소스 서블릿 컨테이너인 Apache Tomcat의 기본 언어 코드가 바로 ISO-8859-1이다. 이 문제로 쿼리 스트링에 포함된 한글 문자열이 깨지는 것을 누구나 경험해봤을 것이다. 초창기 HTML의 표준 언어 코드였기 때문에 아직도 서유럽의 적지 않은 웹사이트들이 이 코드로 제공된다. - 초창기 컴퓨터 산업은 미국을 비롯한 서유럽이 이끌었기에 아무 문제 없었다. 문제는 그 외의 다른 언어를 사용하는 지역이다. 결국 독자적인 코드를 만들어 사용하게 된다. 한국의 경우
KSC5601-1987
을 사용하였다. Unicode
(유니코드)는 파편화된 전세계의 언어 코드를 하나의 코드로 통일하기 위해 나왔다. 유니코드는 총 1,114,112개의 문자를 표현할 수 있다. Plane이라 불리는 17개의 영역이 각각 65536개의 문자를 표현할 수 있으며 이모티콘(Emoji
) 또한 개별 유니코드 문자로 제공한다.
\uAC00이 뭐지?
- 유니코드(와 모든 언어 코드)의 각 문자는 식별 가능한 Code Point라는 숫자를 가진다.(데이터베이스의 PK를 생각하면 된다.) 예를 들어 유니코드의 0번째 문자는 0번째 Code Point라고 부른다. 유니코드에서는 아래 형식으로 표현한다.
// 한글 문자인 '가'를 가리키는 유니코드의 Code Point 문자열이다.
U+AC00
- 첫번째 문자
U
는 이 문자열이 유니코드의 Code Point임을 알려준다.+
이후의 4개 문자는 Code Point를 16진수로 표현한 것이다.AC00
은 44032를 의미하는 16진수이다. - 전세계가 모두 유니코드를 사용한다면 아무런 문제가 없을 것이다. 하지만 때때로 과거에 개발되어 운영 중인 시스템이나 프로토콜 등의 호환성 문제로 유니코드를 ASCII로 표현해야 하는 상황이 생길 수 있다. 이런 문자열을 Unicode Escape Sequence라고 부른다. 형식은 아래와 같다.
// 한글 문자인 '가'를 의미하는 Unicode Escape Sequence이다.
\uAC00
- Java에서는 아래와 같이 Unicode 문자열과 Unicode Escape Sequence 문자열을 손쉽게 상호 변환할 수 있다. (
StringEscapeUtils
을 사용하기 위해서는 Apache Commons Lang,ObjectMapper
를 사용하기 위해서는 Jackson 라이브러리가 필요하다.)
// Unicode Escape Sequence는 char 타입의 변수에 바로 저장할 수 있다.
char gaChar = '\uAC00';
// 문자의 최소값인 '\u0000'을 저장한다.
char charMin = Character.MIN_VALUE;
// 문자의 최대값인 '\uFFFF'를 저장한다.
char charMax = Character.MIN_VALUE;
// "\uAC00\uB098\uB2E4\uB77C\uB9C8\uBC14\uC0AC"를 출력한다.
StringEscapeUtils.escapeJava("가나다라마바사");
// "가나다라마바사"를 출력한다.
StringEscapeUtils.unescapeJava("\uAC00\uB098\uB2E4\uB77C\uB9C8\uBC14\uC0AC");
// Jackson 라이브러리 사용시 Unicode Escape Sequence로 표현된 JSON 문자열로 변환할 수 있다.
ObjectMapper mapper = new ObjectMapper();
mapper.getFactory().configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
- 앞서 언급했듯이 유니코드는 1,114,112개의 문자를 표현할 수 있으며 Code Point 범위는 U+0000부터 U+10FFFF가 된다.
UTF-8은 뭐지?
- Unicode와 Code Point는 국제적인 표준 언어 코드를 설명하는 논리적 단위일 뿐이다. 같은 유니코드라도 실제로 컴퓨터에 어떻게 저장하느냐에 따라 여러가지 방식으로 나뉘어 진다. 이를 인코딩(Encoding) 또는 캐릭터셋(Charset)이라고 부르며
UTF-8
,UTF-16
등 다양한 인코딩 방식이 존재한다. 인터넷 세계에서는 1999년 HTML4 표준이 등장한 이래 UTF-8을 표준 인코딩 방식으로 권장하고 있으며 오늘날 대부분의 텍스트는 UTF-8로 저장되고 있다. UTF-8 인코딩은 1개 문자를 Code Point에 따라 1~4 바이트로 가변적으로 저장하는 방식이다.
Java와 UTF-8
- Java는 기본적으로 유니코드를 완벽히 지원하는 언어이며 내부적으로는 1개 문자를 UTF-16 인코딩으로 저장한다. 유니코드의 0번 플레인(U+0000부터 U+FFFF 코드포인트)까지는 1개 char 타입(2바이트)으로 표현하고 나머지 1~16번 플레인(U+10000부터 U+10FFFF 코드포인트)은 2개의
char
타입을 묶어(4바이트) 1개 문자로 표현한다. 예를 들어 U+20000 코드포인트는 2개의 char를 묶음으로 하여 \uD840\uDC00와 같이 UTF-16 인코딩으로 저장한다. 이와 같이 1개 유니코드 문자가 항상 1개의 char 타입으로 대응되지 않는다는 사실을 인지하고 있어야 한다. char 타입의 배열인String
문자열 타입의 크기(length())가 유니코드 문자의 개수와 일치하지 않는 이유이다. - 위와 같이 Java는 내부적으로 UTF-16 인코딩으로 유니코드를 지원하지만 인터넷 세계에서는 UTF-8 인코딩을 표준으로 사용한다. 아래와 같이 String 문자열 타입을 UTF-8 형식으로 변환할 수 있다.
// "가나다" 문자열을 UTF-8 인코딩의 바이트 배열로 저장한다.
byte[] bytes = "가나다".getBytes(StandardCharsets.UTF_8);
// UTF-8 인코딩된 바이트 배열을 문자열로 저장한다.
String text = new String(bytes, StandardCharsets.UTF_8);
// 문자열을 UTF-8 인코딩된 파일로 저장한다. Apache Commons IO 라이브러리를 사용하였다.
FileUtils.writeStringToFile(new File("C:\\utf8.txt"), "가나다", StandardCharsets.UTF_8);
MySQL과 UTF-8
- MySQL 5.5.3 이전 버전이 제공하는
utf8
인코딩은 Unicode의 0번 플레인(BMP: Basic Multilingual Plane)의 65536개의 문자만 수용할 수 있다. 가변형으로 문자 1개당 1~3바이트 공간을 차지한다. 대부분의 문자를 수용할 수 있지만 다른 플레인(1~16)에 속하는 일부 중국어 및 특수문자(Emoji)의 수용이 불가능하다. - MySQL 5.5.3부터 제공하는
utf8mb4
인코딩은 Unicode의 0~16번까지의 모든 플레인의 문자를 수용할 수 있다. utf8mb4는 utf8에 대한 완벽한 하위 호환성을 제공하며 어떠한 추가 공간도 차지하지 않는다.(0번 플레인 이후의 문자만 4바이트를 차지한다.) 따라서 UTF-8을 지원하는 테이블 및 컬럼은 반드시 utf8mb4로 인코딩되어야 한다. [관련 링크] - 테이블 생성시 아래와 같이 utf8mb4 인코딩을 지정할 수 있다.
CREATE TABLE some_table (
...
)
DEFAULT CHARACTER SET utf8mb4;
DEFAULT COLLATE utf8mb4_unicode_ci;
참고글
- Why do we need Unicode?
- UTF-8 is the default encoding for Web documents since HTML4 in 1999
- Plane (Unicode))
- Announcing The Unicode® Standard, Version 9.0
- UNICODE EMOJI
- Full Emoji List, v5.0
- Java Unicode encoding
- 10.1.9.3 The utf8mb4 Character Set (4-Byte UTF-8 Unicode Encoding)
- MySQL driver does not support full UTF-8 (emojis, asian symbols, mathematical symbols)
댓글
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Kendo UI
- bootstrap
- Docker
- Spring Boot
- DynamoDB
- Kendo UI Web Grid
- jsp
- 로드 바이크
- MySQL
- 태그를 입력해 주세요.
- jstl
- 자전거
- maven
- Eclipse
- java
- 알뜰폰
- JHipster
- graylog
- CentOS
- 로드바이크
- 평속
- spring
- chrome
- 구동계
- Spring MVC 3
- jpa
- kotlin
- JavaScript
- Tomcat
- node.js
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
글 보관함