🎯 MariaDB로 운영중인 서비스에서 간헐적으로 아래와 같은 저장 오류가 발생함.
Incorrect string value: '\xF0\x9F\x98\x8A' for column...
게시글에 이모지를 포함하여 저장할 때마다 오류가 발생하는 것을 파악함.
마리아DB의 인코딩 문제였으며, 문제의 원인과 해결 방법을 정리해봄.
utf8
(3byte)저장 데이터에 이모지가 포함되면 DB 레벨에서 아래의 오류가 발생함.
# 문자 인코딩 변환 실패 오류
java.sql.SQLException: Incorrect string value: '\xF0\x9F\x9A\x80' for column ... at row 1
Query is: INSERT INTO ...
문제 원인은 역시 DB 인코딩이었음.
MariaDB 10.1
의 기본 인코딩은 utf8
이고, 이건 3byte를 지원함.
하지만 이모지는 4byte이기 때문에 인코딩 변환하면서 오류가 발생함.
이 문제를 해결하기 위해서는 인코딩을 utf8mb4
로 변경해야함.
직접 설치한 경우는 아래의 방법을 따라하면 됨.
1. my.cnf
or my.ini
에서 인코딩 수정
[client]
# 클라이언트 ↔ DB 통신 시 사용하는 문자셋 설정
# 저장하거나 SELECT할 때 글자가 깨지면 이 부분을 의심
default-character-set=utf8mb4
[mysqld]
# 신규 저장 데이터 인코딩
character-set-server=utf8mb4
# 정렬 및 비교 방식 지정 "인코딩-코드-대소문구분" 이런 느낌
collation-server=utf8mb4_unicode_ci
# 설정 파일 수정 후 재시작
systemctl restart mariadb
SHOW VARIABLES LIKE 'character\_set\_%';
SHOW VARIABLES LIKE 'collation%';
AWS RDS는 방법이 다르다고 하는데 그건 다음에 차차 알아볼 생각.
10.6
버전 이하면 기본 인코딩은 성능 이슈가 발생.
그럼 기본 인코딩을 변경을 하는 방법이 좋은 방법일까???
꼭 그렇진 않음. 일단 10.2 버전 이하는 utf8mb4
의 최적화가 덜 되어있음.
(실무에서는 10.6
버전 이상이 제일 좋다고는 함.)
따라서 성능이슈가 발생함.
utf8mb4
는 최대 4byte 문자를 저장할 수 있고 이는 저장공간이 증가한다는 의미.
인덱스 제한이 초과되어 성능에 큰 문제를 일으킬 수도 있음.
(※ 인덱스에 직접적인 영향을 주기 때문에 이런건 기본인코딩을 함부로 안바꾸는게 좋음...)
만약 10.6
버전 이상을 쓴다? 그럼 가능
10.6
이상은 기본 인코딩이 utf8mb4
이고 인덱스 최적화도 모두 되어있다고 함.
그 아래 버전이면 생각 잘 하는게 좋음.
적용 방법은 아래와 같음.
utf8mb4
의 기본값utf8mb4_general_ci
이 적용됨 ALTER TABLE 테이블명 CONVERT TO CHARACTER SET utf8mb4;
ALTER TABLE 테이블명
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
에디터 내용 테이블만 적용한다면 성능적으론 기본 인코딩에 비해 나을 수 있음.
하지만 JOIN이 필요한 경우 다른 문제를 일으킬 수 있음.
바로, collation이 서로 달라 발생하는 "Illegal mix of collations"오류.
명시적으로 두 collation을 변경해서 비교하는 방법도 있긴함.
SELECT *
FROM users u
JOIN comments c ON
CONVERT(u.name USING utf8mb4) COLLATE utf8mb4_unicode_ci =
CONVERT(c.author USING utf8mb4) COLLATE utf8mb4_unicode_ci;
하지만 더 좋은 방법은 LIKE, WHERE, JOIN 사용이 없고, utf8mb4
이 필요한 컬럼에만 적용하는 방법임.
⚠️
utf8
문자셋에utf8mb4_unicode_ci
colllation은 사용할 수 없음!
→ 문자셋과 colllation은 반드시 짝이 맞아야 함.
적용 방법은 아래와 같음.
ALTER TABLE 테이블명 MODIFY content TEXT CHARACTER SET utf8mb4;
이번에도 결국은 collation을 주의해야함.
하지만, LIKE, WHERE, JOIN, ORDER BY와 같은 비교연산이 거의 없는 컬럼이면 차라리 이 방법이 나음.
결론적으로 MariaDB에서 이모지나 고급 유니코드 문자를 다루려면 utf8mb4
인코딩이 필수임.
운영 환경이 10.6
이상이라면:
utf8mb4
로 사용해도 안전하고,하지만 10.6
이하 버전이라면:
실제 운영 중이라 구조 변경이 어렵다면,
성능과 호환성을 고려해서 꼭 필요한 부분에만 utf8mb4
와 적절한 Collation
을 적용하는 것을 추천!