웹서비스를 구축할 때 데이터베이스는 주로 utf-8 을 사용해 왔다.
요즘은 웹과 모바일 앱을 동시에 사용하다 보니, 입력란에 모바일 이모지들을 함부로(?) 입력하는 유저들 덕분에 앱이 종료되거나 오류가 발생하는 일이 생긴다.
이것은 모바일 내장 이모지들이 4byte 문자열이고, DB collation 이 3byte 집합인 UTF8 을 사용하기 때문이다.
그로 인해 아래와 흡사한 오류들을 마주할 수 있다.
### Error updating database.
Cause: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x83 \xF0...' for column 'comment' at row 1
해결 방법은 어렵지 않다. DB 옵션의 character_set / collation 과 테이블을 UTF8 에서 UTF8MB4 로 변경하면 된다.
Mysql 에서는 2010년 MYSQL 5.5.3 버전에 4byte 집합인 utf8mb4 charset 을 추가하였다.
기존 utf8 시스템을 utf8mb4 로 바꾸어도 값의 손실은 없으며, DB 용량이 조금 늘어날 것이다.
난 아래의 순서대로 기존 UTF8 코드를 UTF8MB4 로 변경했다.
(환경 : java / RDS mysql)
1. JDBC
connect.url=jdbc:mysql://db_domains.rds.amazonaws.com:3306/test?useUnicode=true&characterEncoding=utf8 | cs |
소스에서 DB 연결에 jdbc characterEncoding 을 지정하는데 이것을 utf8 에서 utf8mb4 로 바꾸면 되는줄 알았지만 MySQL Connector/J 문서에 보면 utf8mb4 는 지원하지 않는다.
그냥 characterEncoding 파라미터를 삭제해 버리면 DB 의 기본 인코딩대로 작동한다. 이거 수정하고 그냥 배포!
요고 안하면 조~기 맨 위에 오류가 발생한다.
2. Parameter Groups
RDS mysql 의 Parameter Groups 은 my.ini 파일과 같다. 각종 옵션들을 수정할 수 있다. 여기서 인코딩을 전부 바꿔준다.
(참고로 character_set_server 만 바꿔주고, 나머지는 default 로 내비둬도 utf8mb4 적용되었음.)
3. Table Column
이모지를 저장할 테이블의 컬럼들을 utf8mb4 로 수정한다.
table 전체를 바꿔도 무방하지만 난 이모지가 저장될 컬럼에만 utf8mb4 를 적용했다.
ALTER TABLE `oops4u`.`article` CHANGE COLUMN `title` `title` VARCHAR(255) CHARACTER SET 'utf8mb4' NOT NULL COMMENT '제목 ' , CHANGE COLUMN `content` `content` VARCHAR(255) CHARACTER SET 'utf8mb4' NOT NULL COMMENT '내용' ; ... | cs |
4. DB reboot
Parameter groups 의 인코딩 관련한 옵션들은 바로 적용이 되지 않는다. 재부팅이 필요하다.
Parameter groups 가 적용되지 않으면 테이블 collation 변경 덕분에 오류 없이 데이터는 들어오지만 이모지 대신 ??? 문자로 도배될 것이다.
재부팅하고 자알~ 되는지 확인한다.
위 이미지는 ios 에서 입력한 이모지를 android 와 web 에서 확인한 것이다.
http://getemoji.com/ 의 이모지 리스트처럼 웹에서 ㅁ형태로 깨져보이는 이모지도 꽤 있지만 뭐...
그건 내 힘으로 해결할 수 있는건 아닌듯 하고...
유의사항
Mysql 에서 한 컬럼의 최대 key 사이즈는 767 byte 이다.
그래서 index 가 문자열일 경우 utf8 에서는 255 까지 지정이 가능했다 (767 / 3 byte = 255...)
만약 utf8mb4 로 변경한 컬럼이 문자열 index 로 사용되고 있다면, 그 컬럼의 자료형은 varchar(191) 로 수정되어야 한다. (767 / 4 byte = 191...)
그렇지 않으면 아마도 이런 오류를 만나게 될 것이다.
ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes
혹은 innodb_large_prefix=1 로 시스템 변수를 설정하면 key 길이가 3072 byte 까지 확장되므로 위 오류를 막을 수 있다.
WRITTEN BY
- 손가락귀신
정신 못차리면, 벌 받는다.