본문으로 건너뛰기

[오류 해결] SQL ERROR 1406: Data too long for column at row 1

2024년 3월 11일에 작성되었고, 블로그를 이전하며 옮겨온 포스트입니다.
여기에서 원본을 확인할 수 있습니다.

문제 상황

GPT-4 응답 결과와 토큰 사용량에 대해 데이터베이스에 저장하려고 얼마 전에 코드를 수정했다. 수정 전에는 GPT-4에 대한 응답 결과를 따로 저장하지 않고 바로 응답 값을 출력하도록 해두었으나, 수정 후에 갑자기 500(Internal Server Error)가 발생한다는 소식에 확인을 시작했다.

백엔드 코드를 확인해 보니 아래 오류가 발생한 것을 확인할 수 있었다.

2024-03-10 10:49:04.949 ERROR 1 --- [nio-8080-exec-5] o.h.engine.jdbc.spi.SqlExceptionHelper   : (conn=605) Data too long for column 'answer' at row 1
2024-03-10 10:49:04.968 ERROR 1 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not execute statement] with root cause

java.sql.SQLException: Data too long for column 'answer' at row 1
	at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readErrorPacket(AbstractQueryProtocol.java:1694) ~[mariadb-java-client-2.7.4.jar!/:na]
	at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.readPacket(AbstractQueryProtocol.java:1556) ~[mariadb-java-client-2.7.4.jar!/:na]
	at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.getResult(AbstractQueryProtocol.java:1519) ~[mariadb-java-client-2.7.4.jar!/:na]

대충 해석하면 answer 컬럼에 데이터가 너무 길어서 저장을 못 한다는 것이다.

원인

GPT-4 응답 결과를 저장하는 엔티티 중 answer 은 아래처럼 되어있다.

@Entity
public class AssistantLog {
	...
	
    @Column(nullable = false)
    private String answer;

    ...
}

MariaDB에 AssistantLog 테이블을 확인해 본 결과, answer 컬럼은 VARCHAR (255)로 설정되어 있었다. 즉, String으로 선언된 컬럼은 JPA에서 VARCHAR (255) 로 변환시켜 주는 것이였고, answer 컬럼에는 255바이트, 즉 한국어 255자 정도까지만 입력될 수 있던 것이였다. 그래서 내용이 긴 GPT-4의 응답은 255 바이트 설정에 걸려버렸기 때문에 저장될 수 없었던 것이다.

오류 해결하기

TINYTEXT = 255 바이트
TEXT = 64 킬로바이트
MEDIUMTEXT = 16 메가바이트
LONGTEXT = 4 기가바이트

TINYTEXT는 기존과 저장할 수 있는 용량이 동일하기 때문에 변경할 이유가 없고, TEXT 정도로만 변경하면 좋을 것 같다. MEDIUMTEXT나 LONGTEXT는 너무 용량이 크기 때문에 부담될 수 있다고 판단했기 때문이다.

@Entity
public class AssistantLog {
	...
	
	@Column(nullable = false, columnDefinition = "TEXT")
  	private String answer;
  
	...
}

위와 같이 해주면, TEXT로 타입 설정이 완료된다. 다른 타입 설정을 원한다면, columnDefinition = "TINYTEXT" 와, columnDefinition = "MEDIUMTEXT"를 사용하면 된다. 만약, LONGTEXT 타입을 사용하고 싶다면 아래와 같이 수정해 주면 된다.

@Entity
public class AssistantLog {
	...
	
	@Lob
  	private String answer;
  
	...
}