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

Data too long for column이 로컬에서는 안 나고 운영에서만 난 이유

  • #Debugging
  • #Engineering Note
  • #SQL

문제 발생

긴 제목을 저장했더니 운영에서만 오류가 났습니다.

ERROR 1406 (22001): Data too long for column 'title' at row 1

로컬에서는 같은 데이터가 저장됐는데, 나중에 보니 뒷부분이 잘려 있었습니다.

원인 분석

1406 (ER_DATA_TOO_LONG, SQLSTATE 22001) 은 값이 컬럼이 허용하는 최대 크기를 넘었다는 뜻입니다.

로컬과 운영이 달랐던 이유는 SQL 모드입니다. 엄격 모드(STRICT_TRANS_TABLES)가 켜져 있으면 오류로 거부하고, 꺼져 있으면 경고만 남기고 잘라서 저장합니다. 즉 로컬에서는 "성공한 것처럼 보였지만 데이터가 손상"되고 있었습니다. 조용히 잘리는 쪽이 오류보다 나쁩니다.

길이 계산도 헷갈리기 쉽습니다.

  • VARCHAR(255)의 255는 문자 수입니다. 바이트가 아닙니다.
  • 다만 저장에는 바이트가 쓰이므로 utf8mb4에서 한 문자가 최대 4바이트, 행 전체 크기와 인덱스 키 길이 한계에는 바이트로 계산됩니다.
  • TEXT류는 바이트 단위 한계를 가집니다(TEXT는 65,535바이트). 한글은 utf8mb4에서 보통 3바이트이므로 문자 수로는 그보다 훨씬 적습니다.

해결 방안

  1. 로컬과 운영의 SQL 모드를 맞춥니다. 환경이 다르면 로컬에서 절대 재현되지 않습니다.
SELECT @@sql_mode;

엄격 모드를 켜 두는 쪽이 맞습니다 — 조용히 자르는 대신 오류로 알려 줍니다.

  1. 입력 길이를 경계에서 검증합니다. DB 오류를 사용자에게 보여 줄 수는 없습니다. 애플리케이션에서 같은 한계를 검사해 알맞은 메시지를 줍니다. 이 저장소도 제목·요약·본문 길이를 Zod 스키마로 제한하고, 그 값이 컬럼 정의와 짝을 이룹니다.
title: z.string().trim().min(2).max(200, "제목은 200자까지 입력할 수 있어요"),
  1. 컬럼 길이는 실제 요구에서 정합니다. "넉넉하게 255"는 근거가 아닙니다. 인덱스를 걸 컬럼이라면 길이가 곧 인덱스 키 크기라 성능에도 영향을 줍니다.
  2. 길이를 늘리는 마이그레이션은 안전한 편입니다. VARCHAR를 늘리는 것은 보통 온라인으로 가능하지만, 줄이는 것은 기존 데이터를 확인해야 합니다. 늘릴 때도 인덱스 키 길이 한계를 넘지 않는지 확인합니다.
  3. 잘린 데이터가 이미 있는지 확인합니다. 엄격 모드를 켜기 전에, 정확히 컬럼 길이와 같은 값들을 조회해 보면 잘림 의심 행을 찾을 수 있습니다.
SELECT id FROM posts WHERE CHAR_LENGTH(title) = 200;

공식 문서

마지막 수정

좋아요북마크

댓글0

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