Spring Boot 3 프로젝트에서 S3에 이미지를 업로드한 후, 해당 이미지의 URL을 MySQL에 저장하려는 과정에서 예상치 못한 에러가 발생했습니다.
{
"status_code": 500,
"error_message": "could not execute statement [Data truncation: Data too long for column 'image_url' at row 1] [insert into image (image_url) values (?)]; SQL [insert into image (image_url) values (?)]"
}
테스트할 때마다 어떤 이미지는 잘 저장되는데, 어떤 이미지는 위와 같은 에러가 발생하더군요.
콘솔 로그를 보면:
2025-06-26T09:41:13.722+09:00 WARN 15478 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1406, SQLState: 22001
2025-06-26T09:41:13.723+09:00 ERROR 15478 --- [nio-8080-exec-2] o.h.engine.jdbc.spi.SqlExceptionHelper : Data truncation: Data too long for column 'image_url' at row 1
org.springframework.dao.DataIntegrityViolationException: could not execute statement [Data truncation: Data too long for column 'image_url' at row 1] [insert into image (image_url) values (?)]; SQL [insert into image (image_url) values (?)]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:293)
에러 해석
(1) SQL Error: 1406
MySQL 에러 코드 1406번은 Data too long for column 오류로,
입력한 데이터가 컬럼의 길이보다 너무 길다는 의미이다.
(2) SQLState: 22001
SQL 표준 코드 22001은 "String data, right truncation"으로
오른쪽 일부가 잘리는 상황이 발생했고, DB는 이걸 에러로 처리한 것이다.
(3) Data too long for column 'image_url' at row 1
image_url 컬럼에 너무 긴 URL 문자열이 들어가 저장에 실패한 것이다.
맨 처음 Image 엔티티를 만들 때, imageUrl 필드를 아무 애너테이션 없이 그냥 String으로 선언했기 때문에,
JPA는 이를 기본적으로 VARCHAR(255)로 매핑했다.
private String imageUrl;
하지만 S3에 업로드된 이미지 URL은 300자 이상이 되는 경우도 있어,
255자 제한을 초과하면서 저장에 실패하는 경우가 생겼습니다.
→ 이로 인해 일부 이미지는 정상 저장되고, 일부는 Data too long for column 오류가 발생한 것입니다.
(1) 테이블 컬럼 타입 변경 (DDL)
ALTER TABLE image MODIFY image_url TEXT;
TEXT는 65,535 바이트까지 저장 가능하므로 긴 URL도 문제 없다.
(2) JPA에서 매핑 변경
@Lob
private String imageUrl;
@Lob은 문자열 타입에 붙이면 JPA가 해당 필드를 DB의 TEXT 컬럼으로 매핑한다.
@Column(columnDefinition = "TEXT")
private String imageUrl;
직접 TEXT라고 지정해줄 수도 있다.
단, 이 설정은 JPA가 DDL을 자동 생성할 때만 적용된다.
이미 생성된 테이블에는 자동 반영되지 않으므로,
위의 ALTER TABLE 같은 수동 DDL 실행이 반드시 필요하다.
이미 데이터를 다 넣은 상태라서 application.yml에서 ddl-auto: create로 바꾸고 테이블을 재생성할 수는 없었다.
그래서 선택한 방법은 첫번째 방법인 직접 컬럼 타입을 TEXT로 변경하는 것이다.
(1) 해당 데이터베이스 클릭
(2) 좌측 상단 SQL 버튼 클릭하면 스크립트 창이 뜬다.
(3) 아래 명령어 입력 후 한 줄 선택 실행
ALTER TABLE image MODIFY image_url TEXT;


데이터가 19개 있던 상태라서 updated rows value에 19가 들어간다!
문제가 되었던 이미지를 다시 등록해보면
{
"status_code": 201,
"result": {
"locationId": 29,
// 생략
"images": [
{
"imageId": 23,
"imageUrl": "https://tripbuddy-1030.s3.ap-northeast-2.amazonaws.com/bd50acb3-501c-4708-aa7b-b19df5cc227a-%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-05-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2012.13.21.png"
},
{
"imageId": 24,
"imageUrl": "https://tripbuddy-1030.s3.ap-northeast-2.amazonaws.com/ad74df31-8d30-43fe-9df7-b52985d82b04-%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-06-25%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.10.26.png"
}
]
},
"status_message": "지역저장이 성공적으로 되었습니다."
}
짠 위와 같이 잘 실행된다.
VARCHAR(255)는 짧을 수 있다!
긴 문자열(특히 URL)은 TEXT로 처리하는 것이 안전하다
이미 생성된 테이블은 반드시 ALTER TABLE로 직접 수정하자