시작하며

캐릭터 표현은 여러모로 개발에 있어서 굉장히 까다로운 문제중에 하나입니다. 특히 영어가 기본어가 아닌 우리나라에서는 더욱 신경써야 할 때가 많습니다. euc-kr 로 인해서 고통 받는 사람들도 많았었죠.

지금은 대부분의 시스템이 기본적으로 모든 캐릭터 표현이 가능한 UTF-8 을 사용하고 있는데 여기서 MySQL 사용자들에게 한가지 문제가 있습니다. 실제 UTF-8 유니코드에서 가변4바이트를 쓰는것과 달리 MySQL 에서의 utf8 은 가변 3바이트로 , 표현할 수 있는 캐릭터제한이 있었습니다. 처음 설계할때는 21bit 정도로 모든 언어가 표현이 가능하니 스토리지 최적화를 위해 설계한 모양입니다.

하지만,,, 이모지등이 키보드로 쓸 수 있게 등장하면서 상황이 달라졌습니다. 단순한 한글 표시까지는 utf8 만 써도 되지만, 요즘 많이 사용되는 기본이모지등은 utf8mb4 를 사용해야 표현이 가능합니다.

DB나 테이블 설정이utf8 로만 되어있는데 이모지를 입력하려면 아래와 비슷한 오류가 당신을 막아설 것입니다.

java.sql.SQLException: Incorrect string value: '\xEA\xB9\x80\xEC\x9C\xA4...' for column 'content' at row 1

자 그러니 DB를 utf8mb4 로 시원하게 세팅해 보는 법을 AWS RDS 에서 해보도록 하겠습니다.

  • 추가적으로 기본 timezone 도 한국시각에 맞게 바꿔봅니다

주의 : 시작하기에 앞서 이미 연결된 커넥션을 모두 꺼버리시는게 좋습니다. AWS 의 DB서버 파라미터를 수정하고 재부팅했는데, 기존 연결된 커넥션에서 파라미터를 계속 조회하면 제대로 변경이 안되어있을 때가 있습니다.

RDS parameter group setting

  • RDS - 데이터베이스 - 구성 에 가면 위처럼 파라미터그룹을 볼 수 있습니다. default 로 되어있다면, 새로 하나 생성한 뒤, 그 파라미터 그룹을 사용할 DB 에 적용하면 됩니다.
  • 파라미터 그룹 선택 후 편집에서 char 로 치면 character set 에 대한 설정들이 나옵니다. collation 이라고 치면 collation 설정(데이터의 정렬기준을 위한 설정) 이 나옵니다.
    • 여기서 해당 값들을 utf8mb4utf8mb4_unicode_ci 로 맞춰줍니다.
      • 왜 unicode_ci 인가요?
        • utf8mb4_general_ci 로 맞춰줘도 상관없습니다 (한글,영어,일본어 등에선 문제 없음. 불어 등에서 정렬이 좀 다릅니다) 다만 unicode_ci 가 조금 더 사람이 인지할때 더 친숙한 기준으로 정렬해준 다고 생각하시면 됩니다. 자세한 건 레퍼런스 링크에서 확인해보세요~
    • 단, character_set_filesystem = binary 값 그대로 둬야 합니다.
    • skip-character-set-client-handshake 는 1 로 해줘서 클라이언트에서 접속할 때 옵션으로 전달해주는 값을 막아버리는 것이 관리에 용이할 수 있습니다.
    ```java
    -- 단, 아래처럼 useUnicode=true  는 클라이언트 접속시 꼭 넣어주셔야 합니다.
    jdbc:mysql://yourRdsEndpoint.[rds.amazonaws.com:3306/foodin_master?useUnicode=true&serverTimezone=Asia/Seoul](http://rds.amazonaws.com:3306/foodin_master?userUnicode=true&serverTimezone=Asia/Seoul)

    -- mySql5.7 부터는 serverTimezone 값도 꼭 넣어야 합니다. 파라미터 그룹에서 time_zone 검색해서 동일하게 Asia/Seoul 로 세팅해두면 now() 등 사용시 현재 한국 시각으로 표시 됩니다.
    ```

다 되었으면, 파라미터 그룹 적용 하고, 꼭 DB 를 재부팅 해주시기 바랍니다. RDS 자체적인 오류인지 파라미터 그룹이 동기화를 명시적으로 수행해도 잘 안되는 경우가 있습니다. 재부팅 후 아까 구성 부분에 다시 갔을때 동기화 라고 써있어야 적용이 잘 된것입니다.

다시 client 툴 등을 사용해서 해당 DB 에 접속 한 뒤,show variables where variable_name like 'c%'; 를 날려줍니다.

이 부분이 아직 남아있는 작은 의문인데, 파라미터그룹에선 다 utf8mb4 로 세팅해주었는데 몇몇 값은 여전히 utf8 로 남아있습니다. collation 도 그렇습니다... 재부팅 아무리 해봐도 동일하네요.

그래도 일단 문제는 없습니다.

만약 이 작업 전에 이미 디비 스키마와 테이블등을 만들어 두셨다면, 그 테이블들은 일일히 수작업을 해줘야 합니다. 해당 작업이 귀찮다면 아래 링크를 보고 활용해보세요. 저는 덕분에 쉽게 해결했습니다.

[MYSQL] 테이블, 컬럼 charset 변경

utf8mb4 로 잘 세팅되어있는 테이블에 직접 insert into 를 통해 한글과 이모지등을 입력해봅니다. latin1 등의 기본값이 었을 경우엔 해당 컬럼에 ???? 등이 입력이 되어버렸습니다. 만약 방금전 세팅이 잘 되었다면 한글이 제대로 들어갈것입니다.

결론

캐릭터셋 (charset) 은 테이블에 데이터가 채워지고 나서부터는 바꾸려고 하면 손이 많이 가거나 데이터의 손실이 우려되는 경우가 많습니다. 그렇기에 처음 데이터 설계하고 DB 를 만드실 때, 위와 같이 세팅을 잘 잡아두신 채로 하는 것이 좋습니다. 더해서 타임존을 통한 시간값도 처음 잘 테스트해서 적절한 timestamp 값과 모든 언어가 사용가능한 형태인지를 확인하시면 편리하게 데이터베이스를 이용하실 수 있습니다.

참고

AWS RDS parameter group을 이용해 character-set 변경(utf8), 타임존 변경하기

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

Brown
Head of Solution Biz. & CCO
강남언니팀을 더 멋지게, 더 즐겁게 일할 수 있도록 만드는 일을 하고 있습니다. 마치 매일 새로운 회사를 다니는듯 하게 만드는 것이 꿈입니다.