[MariaDB] 저장 오류 범인: 이모지 (인코딩)

LSHan·2025년 4월 9일
0

트러블슈팅

목록 보기
2/2
post-thumbnail

이모지 때문에 저장 오류? MariaDB 인코딩 이슈 해결하기

🎯 MariaDB로 운영중인 서비스에서 간헐적으로 아래와 같은 저장 오류가 발생함.
Incorrect string value: '\xF0\x9F\x98\x8A' for column...
게시글에 이모지를 포함하여 저장할 때마다 오류가 발생하는 것을 파악함.
마리아DB의 인코딩 문제였으며, 문제의 원인과 해결 방법을 정리해봄.

오류내용 및 상황

⚙️ 환경

  • MariaDB 10.1
    - 기본인코딩: 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
  1. 적용하기: DB 재시작 필요
      # 설정 파일 수정 후 재시작
      systemctl restart mariadb
  2. 변경내용 확인: 쿼리
      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이고 인덱스 최적화도 모두 되어있다고 함.
그 아래 버전이면 생각 잘 하는게 좋음.

💦 테이블만 적용하기

적용 방법은 아래와 같음.

  • 인코딩 변경: collation 미적용 시 utf8mb4의 기본값utf8mb4_general_ci이 적용됨
      ALTER TABLE 테이블명 CONVERT TO CHARACTER SET utf8mb4;
  • collation도 같이 변경하기
      ALTER TABLE 테이블명 
      CONVERT TO CHARACTER SET utf8mb4 
      COLLATE utf8mb4_unicode_ci;

⁉️ 주의: 서로 다른 colllation으로 인한 오류 주의

에디터 내용 테이블만 적용한다면 성능적으론 기본 인코딩에 비해 나을 수 있음.
하지만 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 문제는 있지않나?

이번에도 결국은 collation을 주의해야함.

하지만, LIKE, WHERE, JOIN, ORDER BY와 같은 비교연산이 거의 없는 컬럼이면 차라리 이 방법이 나음.

마무리

결론적으로 MariaDB에서 이모지나 고급 유니코드 문자를 다루려면 utf8mb4 인코딩이 필수임.

운영 환경이 10.6 이상이라면:

  • 기본 인코딩을 utf8mb4로 사용해도 안전하고,
  • 인덱스 최적화와 성능 문제도 거의 없음

하지만 10.6 이하 버전이라면:

  • 전체 기본 인코딩 변경보다는 특정 컬럼/테이블만 적용하는 전략이 안전
  • 그리고 JOIN, WHERE 등 비교 연산이 필요한 경우엔 반드시 Collation을 통일!

실제 운영 중이라 구조 변경이 어렵다면,
성능과 호환성을 고려해서 꼭 필요한 부분에만 utf8mb4와 적절한 Collation을 적용하는 것을 추천!

profile
궁금했던 것들 혹은 정리가 필요한 내용들을 위해!

0개의 댓글