[MySQL/MariaDB] utf8mb4 언어셋 소개 및 표현범위. (charset, collation)

HYEONG HWAN, MUN/ 3월 2, 2015/ 미분류/ 27 comments

https://blog.lael.be/post/917

기술이 매우 빠르게 발전한다.

배워도 배워도 계속 배워야 한다.

 

최근에 라엘이가 앞으로 100년동안은 나타나지 않을 것이라고 예상했던,

4 Byte UTF-8 문자열을 보고 여러 깨닳은 바가 있었고

여러분에게 도움이 될만한 정보가 있어 공유하려고 한다.

 

데이터베이스를 구축하다보면 텍스트 데이터(Text Data)를 취급해야 할 때가 있다.

이때 반드시 고민해야 하는 것이 있는데, 바로 문자셋(character set)을 선택하는 것이다.

 

핵심 단어의 뜻

먼저 중요한 두 단어 CharsetCollation 의 뜻에 대해서 알고 가자.

구글 번역기를 이용하여 단어 자체의 뜻을 알아보자.

스크린샷 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 에 추가됨)

(관련 : https://dev.mysql.com/doc/relnotes/mysql/5.5/en/news-5-5-3.html )

스크린샷 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 / AuroraDB-MySQL 에서만 일어납니다.

 

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 를 사용하지 않아도 됩니다. (이 경우 데이터베이스에 텍스트 값 저장 전에 필터링을 하기 바랍니다.)

 

27 Comments

  1. 좋은 정보 감사합니다. ^^

  2. 안녕하세요..

    현재 호스팅하고 있는 DB 는 Charset = utf8, Collation = utf8_general_ci 입니다.

    제 컴은 Collation 이 utf8mb4_general_ci 로 되어있어서 호스팅하는 것과 맞추려고 별 수단을 써도 안바뀌던데요.

    그래도 혹시 하는 생각에

    프로그램하고 DB를 백업해서 설치를 하면, 각 페이지는 잘 넘어갑니다.

    그런데, 로그인이 안돼요. 관리자 페이지로 들어가야 페이지를 추가할 수 있는데 로그인 자체가 안됩니다.

    홈페이지 템플릿은 그누보드로 제작했습니다.

    그대로 제 PC에 복구할 수 있는 방법이 있을까요?

    1. utf8mb4 가 utf8 + 확장속성 이라서
      utf8 -> utf8mb4 전환(migration)은 아무작업하지 않아도 손실없이 동작합니다.
      로그인이 안되는 것은 PHP 세션이 올바르게 동작하지 않은 것으로 보입니다.

  3. Pingback: [MariaDB] utf8mb4 란? | Window of Andrew, JEON

  4. 인터넷에 검색만하면 늘 라엘님의 블로그가 나오네요!
    많은 도움 받아갑니다

    대단하신 분 같아요!!
    앞으로도 잘 부탁드립니다

    1. 하하핫
      인터넷상에 바이러스를 퍼트려서 제 블로그만 나오도록 조치해두었습니다.

      1. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

  5. 글을 작성했는데 저장이 안되서 이모지인걸 서버문제인줄 알았었고 그냥 때려칠까 생각했었는데요
    우연치 않게 텍스트큐브 리퍼러검색기록 그 플러그인 주소로 들어왔는데 도움되는 글들이 많아 잘 읽고갑니다.

    1. 기술의 발전이 너무 빠른것 같아요.
      텍스트큐브가 너무 업데이트 지원이 없어서 큰맘먹고 워드프레스로 옮겼습니다.
      제가 텍큐를 안쓰므로 해당플러그인 유지보수를 하지않고 있는데, 지금도 잘 동작하나요?

  6. 유익하네요 잘 보고 갑니다^^

  7. DB문자셋에 의문이 있었는데 도움이 되는 글이었습니다.

    저의 경우는 제작중인 홈페이지가 다국어 지원을 위해 UTF8환경에서 만들고 있는데
    입력된 중국어와 몽골어의 몇몇 문자들이 ???형태로 DB에 저장되고 있어서 해결책을 찾고 있는중입니다.
    (브라우저화면상에서는 잘 쓰여지고 보여지는 문자들이 DB에 저장되고 나면 중간중간 ??문자로 바뀝니다)

    님의 글을보니 Emoji 같은 새로나온 문자가 아니라면 기존의 언어들은 모두 표현되어야 하는게 아닌가요?
    왜 저의 경우는 ???로 바뀔까요?
    Mysql 버전이 5.1.45라서 3Byte까지만 지원되는 UTF8 환경이긴합니다만
    한자나 몽골문자가 특수문자는 아니기에 의문이 생깁니다.
    물론 HTML페이도 UTF8을 기반으로 만들어져 있습니다(meta tag charset도 utf8, HTML문서 인코딩도 UTF8)

    1. 새로 추가되는 문자들이 4바이트 영역을 사용하기도 합니다.
      예를들어 중국어의 경우 계속해서 간자체(음과 뜻이 같은데 획이 간략화된 문자)를 추가하고 있으며 해당 확장중국어 문자는 4바이트 영역을 사용합니다.
      http://www.i18nguy.com/unicode/supplementary-test.html 페이지를 참고하세요.

      1. 그렇군요. 답변 감사합니다.

  8. 정말 감사합니다.
    제 블로그로 가져가려고 합니다.

    출처는 반드시 남겨놨으며, 작성하신 글을 한번 더 정리하면서 작성했습니다.

    문제 발생 및 요청 시 자삭 하겠습니다.
    감사합니다!!!

  9. ????????????

    실제로 에모지를 나타나게 하는 방법이 따로 있을까요

    그누보드에 DB 다 바꿔줬는데 표현이 안되네요 흐흑

    1. 안녕하세요. DB의 저장공간도 설정되었고 문자도 올바르게 보냈으나,
      연결 설정이 utf8 로 되어 있으므로 전송중에 깨지는 것입니다.

      그누보드/common.php 파일의 139번째 줄을 다음과 같이 변경해보세요.
      sql_set_charset(‘utf8mb4’, $connect_db);

      1. https://www.wsgvet.com/home/520

        여기저기 참조해서 그누보드5에 성공했습니다.

        적용하는데는 얼마 안걸렸는데 글 쓰는데 시간이 더 오래걸리는군요. ㅎㅎ

        common.php에 먼저 적용해보고 여기오니 댓글에 달려있었네요. ^^;;

  10. 유용한 정보 감사드려요~
    이렇게 자세한 정보를 보니 너무 좋네요~ ^^
    오늘도 이렇게 하나 배워갑니다~ ㅎㅎ

  11. 좋은 정보 감사합니다!

    감히 허락받지 않고 쓰신 글 일부를 제 블로그에도 가져가려고 합니다.

    출처는 남겼습니다!

    1. 복사하신다음 본인의 생각을 살짝 넣어주세요. 다른분에게 도움이 될 수 있습니다.

  12. Pingback: 개발용 local wordpress 추가하기 - bekseju군

  13. 블로그로 가져갈려고하는데 괜찮을까요? 🙂
    출처 남기겠습니다!!!!
    너무 잘 정리해주셧네요 ㅠ
    문제시 자삭하겠습니다!!.

    1. 퍼가서 한번 더 읽어주세요~
      감사합니다.

  14. 설명과 정리가 정말 잘되어있어 이해가 쉬었습니다.
    고맙습니다.

  15. 쉽게 이해할 수 있는 글이네요! 감사합니다.

    1. 개념을 이해하고 코드를 짜는 멋진 개발자가 되어주세요~

Leave a Comment

작성하신 댓글은 관리자의 수동 승인 후 게시됩니다.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
*
*