🎯 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_cicolllation은 사용할 수 없음!
→ 문자셋과 colllation은 반드시 짝이 맞아야 함.
적용 방법은 아래와 같음.
ALTER TABLE 테이블명 MODIFY content TEXT CHARACTER SET utf8mb4;
이번에도 결국은 collation을 주의해야함.
하지만, LIKE, WHERE, JOIN, ORDER BY와 같은 비교연산이 거의 없는 컬럼이면 차라리 이 방법이 나음.
결론적으로 MariaDB에서 이모지나 고급 유니코드 문자를 다루려면 utf8mb4 인코딩이 필수임.
운영 환경이 10.6 이상이라면:
utf8mb4로 사용해도 안전하고,하지만 10.6 이하 버전이라면:
실제 운영 중이라 구조 변경이 어렵다면,
성능과 호환성을 고려해서 꼭 필요한 부분에만 utf8mb4와 적절한 Collation을 적용하는 것을 추천!