이모지가 들어간 글을 저장했더니 Incorrect string value 오류가 난 이유
문제 발생
사용자가 제목에 이모지를 넣자 저장이 실패했습니다.
ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x8E\x89' for column 'title'테이블은 CHARACTER SET utf8로 만들어져 있었습니다. 이름이 utf8이니 유니코드는 다 되는 줄 알았습니다.
원인 분석
MySQL의 utf8은 utf8mb3의 별칭이고, 이름 그대로 한 문자를 최대 3바이트까지만 저장합니다. 3바이트로 표현되는 범위는 유니코드의 기본 다국어 평면(BMP, U+0000~U+FFFF)까지입니다.
이모지는 그 바깥의 보충 평면에 있어 4바이트가 필요합니다. 그래서 들어가지 않습니다. 같은 이유로 일부 희귀 한자와 확장 CJK 문자도 저장되지 않습니다. 오류 메시지의 \xF0\x9F\x8E\x89가 바로 그 4바이트입니다.
MySQL 문서는 이 점을 분명히 합니다 — 권장 문자셋은 utf8mb4이고 모든 새 애플리케이션은 이것을 써야 하며, utf8mb3은 deprecated로 향후 제거될 예정입니다.
해결 방안
- 테이블과 컬럼을
utf8mb4로 바꿉니다.
ALTER TABLE posts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;새로 만들 때는 처음부터 지정합니다. 이 저장소도 DB 생성 시점에 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci를 씁니다.
- 인덱스 키 길이를 함께 확인합니다. 이게 실제로 발목을 잡는 부분입니다. 한 문자가 최대 4바이트이므로
VARCHAR(255)는 최악의 경우 1020바이트를 차지합니다. 인덱스 키 길이 한계(InnoDB 기준 보통 3072바이트)에 걸리면ALTER가 실패합니다.
- 인덱스를 걸 컬럼은 길이를 줄입니다(예: slug는
VARCHAR(220)). - 복합 인덱스라면 컬럼들의 합이 한계를 넘지 않는지 확인합니다.
- 연결 문자셋도 바꿔야 합니다. 테이블만 바꾸고 클라이언트 연결이
utf8mb3이면 전달 과정에서 다시 깨집니다. 드라이버의 접속 설정에charset=utf8mb4를 명시합니다. utf8이라고 쓰지 않습니다. 의미가 애매하고 향후 제거 대상입니다. 스키마·설정 파일·마이그레이션 전부에서utf8mb4라고 명시적으로 적습니다.- 콜레이션도 함께 정합니다. 문자셋이 "무엇을 저장할 수 있는가"라면 콜레이션은 "어떻게 비교·정렬하는가"입니다. 대소문자·악센트 구분 여부가 여기서 결정되므로, 검색과 유니크 제약의 동작에 직접 영향을 줍니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.