[Database] MySQL utf8 과 utf8mb4

MySQL character set에 대해 좋은 자료가 있어 링크 함.

[MySQL/MariaDB] utf8mb4 언어셋 소개 및 표현범위.


기술이 매우 빠르게 발전한다.
배워도 배워도 계속 배워야 한다.

최근에 라엘이가 앞으로 100년동안은 나타나지 않을 것이라고 예상했던,
4 Byte UTF-8 문자열을 보고 여러 깨닳은 바가 있었고
여러분에게 도움이 될만한 정보가 있어 공유하려고 한다.

데이터베이스를 구축하다보면 텍스트 데이터(Text Data)를 취급해야 할 때가 있다.
이때 반드시 고민해야 하는 것이 있는데, 바로 문자셋(character set)을 선택하는 것이다.

핵심 단어의 뜻

먼저 중요한 두 단어 Charset 과 Collation 의 뜻에 대해서 알고 가자.
구글 번역기를 이용하여 단어 자체의 뜻을 알아보자.
스크린샷 2015-03-03 오후 11.08.08

스크린샷 2015-03-03 오후 11.08.18

charset 은 문자 집합collation 은 정렬을 뜻한다.

자료형이 왜 필요하나?

먼저 자료형이 왜 필요할지부터 생각해보자.

컴퓨터 프로그램은 프로그래머가 의도한 대로 동작한다.
이 때 같은 목적의 프로그램이라고 할지라도 효율적으로 동작하는 것이 더 좋은 프로그램이 된다.
컴퓨터 알고리즘(Computer Algorithm)” 학문에서는 이를 평가(Performance Analysis)하기 위해서,
시간복잡도(time complexity)“와 “공간복잡도(space complexity)“의 개념을 사용한다.
(참고로 이것을 평가하는 대회가 [ACM-ICPC;International Collegiate Programming Contest;대학생알고리즘대회] 이다.
라엘이도 두번정도 참가해보았으며 컴퓨터 알고리즘의 중요성을 알 수 있게 된다. 관련글 : https://blog.lael.be/post/136 )

같은 이유로 데이터베이스 학문도
더 작은 공간을 사용하면서
더 빠르게 처리할수 있는
방향으로 발전되었고 해당 목적을 위해서 데이터 자료형을 사용하게 되었다.

예를 들어 어떤 프로그램에서 사용자의 선택여부를 저장하고자 할때
1) boolean 자료형의 true/false
2) int 자료형의 0, 1
3) char 자료형의 0,1
모두 같은 동작을 하는데 boolean 으로 저장하는 것이가장 작은 공간을 사용하고제일 빠르다.

UTF-8 이란?

실생활의 대부분의 데이터는 텍스트기반(text-centric)이다.
당연히 실생활의 모든 텍스트 데이터를 저장할 수 있는 자료형이 필요로 하게 되었다.

이것을 위해서 나온 charset이 UTF-8 이다.
UTF-8 문자 집합은 1~4 바이트까지 저장이 가능하게 설계되었다. (가변 바이트)
관련 자세한 자료는 라엘이가 쓴 글인 https://blog.lael.be/post/77 을 참고하기 바란다.

MySQL/MariaDB 에서도 UTF-8 을 지원한다.
이때! 간과한 사실이 있는데, 전세계 모든 언어가 21bit (3바이트가 조금 안됨)에 저장되기 때문에
MYSQL 에서 utf8 을 3바이트 가변 자료형으로 설계하였다.

그렇기 때문에 최근에 나온 4바이트 문자열(Emoji 같은것)을 utf8 에 저장하면 값이 손실되는 현상이 발생한다!
기존에 널리 사용되던 MySQL 구축(설계)에서 환경이, charset 은 utf8 , collation 은 utf8_general_ci 인데 이러한 대부분의 환경에서 문제를 일으키는 것이다.

4바이트 UTF-8 문자열

MySQL에서 부랴부랴 원래의 설계대로 가변-4바이트 UTF-8 문자열을 저장할 수 있는 자료형을 추가했다.
2010년 3월 24일에 utf8mb4 라는 charset을 추가하였다. (MYSQL 5.5.3 에 추가됨)
스크린샷 2015-03-07 오후 6.51.19
> 한글 해석 : utf8mb4 가 추가되었습니다. 이것은 utf8 과 비슷하지만 확장된 문자를 지원하기 위해서 4바이트까지 저장할 수 있습니다.

더 자세한 이론을 원하면 Wikipedia 의 Plane 항목을 읽어보길 바란다.
(어려움. 그냥 쓰윽 읽어보세요. http://en.wikipedia.org/wiki/Plane_(Unicode) )
대충 이런 뜻이다.
- utf8 : Basic Plane.
- utf8mb4 : Basic Plane + Supplementary Plane.

그리고 중요한 것!!! Emoji 문자열이 모두 4 Byte 이다!!
요즘 스마트폰에서 이미 있는 문자이고, 라엘이의 경우 운영체제로 Mac OS X 를 사용하는데,
Mac 에서 커멘드+컨트롤+스페이스를 입력하면 나오는 키보드이다.
-- 참고 이미지 --
스크린샷 2015-03-07 오후 7.05.17
-- 참고 이미지 --

즉 이러한 SMP (Supplementary Multilingual Plane) 를 처리하기 위해서
당신의 DBMS 가 utf8mb4 를 지원한다면 반드시 이것으로 지정하길 바란다.


Collation (정렬 방식).

latin1 (2바이트), utf8 (가변3바이트), utf8mb4 (가변4바이트)는 저장공간의 크기이다.
위의 것들은 charset 이라고 부른다.
(웹)프로그램과 데이터베이스가 문자를 주고 받을 때는 charset 만 설정하면 된다.
내가 보낼 문자열은 utf8mb4 에요!” 라고 알려주고 text stream 을 전송하면 알맞게 처리하기 때문이다.

Collation 은 텍스트 데이터를 정렬(ORDER BY)할 때 사용한다. 즉 text 계열 자료형에서만 사용할 수 있는 속성이다.
int 형 : 1500 < 1700  으로 명확하다.
date 형 : 2013-10-20 < 2015-12-20 으로 명확하다.
- 그렇다면 text 형 :
a  와  b  중 어느 것이 더 큰가?
a 와 A 중 어느 것이 더 큰가?
a 와 á 중 어느 것이 더 큰가?

- 주로 많이 사용하는 collation 3가지 비교.
ORDER BY `text` ASC
* utf8_bin (or utf8mb4_bin)
바이너리 저장 값 그대로 정렬한다.
hex 코드(16진수)로 A 는 41, B 는 42, a 는 61, b 는 62 이기 때문에 다음 순서로 출력된다.
스크린샷 2015-04-15 오전 11.15.00

* utf8_general_ci (or utf8mb4_general_ci)
텍스트 정렬할 때 a 다음에 b 가 나타나야 한다는 생각으로 나온 정렬방식. 일반적으로 널리 사용된다.
라틴계열 문자를 사람의 인식에 맞게 정렬한다.
바이너리를 한번 가공한 것이다.
스크린샷 2015-04-15 오전 11.30.44
* utf8_unicode_ci (or utf8mb4_unicode_ci)
general_ci 보다 조금 더 사람에 맞게 정렬한다.
한국어, 영어, 중국어, 일본어 사용환경에서는 general_ci 와 unicode_ci 의 결과가 동일하다.
뭔가 더 특수한 문자의 정렬 순서가 변경된다.  다음의 스크린샷을 참조하여라.


tab1

스크린샷 2015-03-07 오후 7.16.58
<위의 예시는 상당히 많은 의미를 가지고 있다. 자세히 살펴보도록 하자.>

다음은 권장하는 charset 과 collation 설정 값이다.
1) MySQL 5.5.3 이전 = utf8 charset 에, utf8_general_ci collation 사용.
2) MySQL 이 최신일 때 = utf8mb4 charset 에, utf8mb4_unicode_ci collation 사용.



요약 : 이 문제는 MYSQL / MariaDB 에서만 일어납니다.

1) 다국어를 처리할 수 있는 UTF-8 이라는 저장방식이 있음. 원래 설계는 가변4바이트임.
2) 전세계 모든 언어문자를 다 카운트 해봤는데 3 바이트가 안됨.
3) MYSQL/MariaDB 에서는 공간절약+속도향상 을 위해서 utf8 을 가변3바이트로 설계함.
4) Emoji 같은 새로나온 문자가 UTF-8의 남은 영역을 사용하려함 (4바이트 영역).
5) MYSQL/MariaDB 에서 가변4바이트 자료형인 utf8mb4 를 추가함.  (2010년 3월에).

기존 utf8 시스템을 utf8mb4 로 바꾸어도 값의 손실은 없습니다.
Emoji 문자열의 저장을 지원하지 않으려면 굳이 utf8mb4 를 사용하지 않아도 됩니다. (이 경우 데이터베이스에 텍스트 값 저장 전에 필터링을 하기 바랍니다.)

댓글

이 블로그의 인기 게시물

[Protocol] WIEGAND 통신

Orange for Oracle에서 한글 깨짐 해결책

[UI] GNB·LNB·SNB·FNB 용어 설명