본문으로 건너뛰기
개발 머꼬
개발 노트SQL
hohyeon.dev15

이모지가 들어간 글을 저장했더니 Incorrect string value 오류가 난 이유

  • #Encoding
  • #Engineering Note
  • #MariaDB
  • #SQL

문제 발생

사용자가 제목에 이모지를 넣자 저장이 실패했습니다.

ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x8E\x89' for column 'title'

테이블은 CHARACTER SET utf8로 만들어져 있었습니다. 이름이 utf8이니 유니코드는 다 되는 줄 알았습니다.

원인 분석

MySQL의 utf8utf8mb3의 별칭이고, 이름 그대로 한 문자를 최대 3바이트까지만 저장합니다. 3바이트로 표현되는 범위는 유니코드의 기본 다국어 평면(BMP, U+0000~U+FFFF)까지입니다.

이모지는 그 바깥의 보충 평면에 있어 4바이트가 필요합니다. 그래서 들어가지 않습니다. 같은 이유로 일부 희귀 한자와 확장 CJK 문자도 저장되지 않습니다. 오류 메시지의 \xF0\x9F\x8E\x89가 바로 그 4바이트입니다.

MySQL 문서는 이 점을 분명히 합니다 — 권장 문자셋은 utf8mb4이고 모든 새 애플리케이션은 이것을 써야 하며, utf8mb3은 deprecated로 향후 제거될 예정입니다.

해결 방안

  1. 테이블과 컬럼을 utf8mb4로 바꿉니다.
ALTER TABLE posts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

새로 만들 때는 처음부터 지정합니다. 이 저장소도 DB 생성 시점에 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci를 씁니다.

  1. 인덱스 키 길이를 함께 확인합니다. 이게 실제로 발목을 잡는 부분입니다. 한 문자가 최대 4바이트이므로 VARCHAR(255)는 최악의 경우 1020바이트를 차지합니다. 인덱스 키 길이 한계(InnoDB 기준 보통 3072바이트)에 걸리면 ALTER가 실패합니다.
  • 인덱스를 걸 컬럼은 길이를 줄입니다(예: slug는 VARCHAR(220)).
  • 복합 인덱스라면 컬럼들의 합이 한계를 넘지 않는지 확인합니다.
  1. 연결 문자셋도 바꿔야 합니다. 테이블만 바꾸고 클라이언트 연결이 utf8mb3이면 전달 과정에서 다시 깨집니다. 드라이버의 접속 설정에 charset=utf8mb4를 명시합니다.
  2. utf8이라고 쓰지 않습니다. 의미가 애매하고 향후 제거 대상입니다. 스키마·설정 파일·마이그레이션 전부에서 utf8mb4라고 명시적으로 적습니다.
  3. 콜레이션도 함께 정합니다. 문자셋이 "무엇을 저장할 수 있는가"라면 콜레이션은 "어떻게 비교·정렬하는가"입니다. 대소문자·악센트 구분 여부가 여기서 결정되므로, 검색과 유니크 제약의 동작에 직접 영향을 줍니다.

공식 문서

마지막 수정

좋아요북마크

댓글0

아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.