[Troubleshooting] JPA DataException: 설계 최적화로 컬럼 길이 제한 해결하기

유자·2026년 3월 1일

multi-modal-fraud-project

목록 보기
12/16

1. 문제 상황

다중 이미지 업로드 기능을 구현하던 중, 이미지들의 Supabase URL을 하나의 문자열로 합쳐 DB에 저장하려다 다음과 같은 에러가 발생했다.

org.hibernate.exception.DataException: could not execute statement 
[ERROR: value too long for type character varying(255)] 

원인은 JPA @Column의 기본 길이 제한(255자)을 초과했기 때문이다. 파일 3개만 합쳐도 300자가 훌쩍 넘어가면서 트랜잭션이 롤백되는 현상이 발생했다.


2. 원인 분석

  • 현상: String.join(",", uploadedUrls)로 만든 문자열이 너무 길어 DB가 거부함.
  • 근본적인 문제: DB에 불필요하게 길고 중복되는 전체 URL 주소를 굳이 다 저장하려고 함.

3. 해결 방법: "안 저장하는 게 가장 좋은 저장이다"

단순히 컬럼 길이를 늘리는 임시방편 대신, 기존에 생성해둔 verificationId(UUID)를 폴더명으로 활용하는 설계를 채택했다.

핵심 아이디어

  1. DB 컬럼 삭제: 에러의 주범인 imageUrl 컬럼을 아예 삭제한다.
  2. 규칙 기반 조회: 모든 이미지는 버킷명/verificationId/파일명 구조로 저장되므로, UUID만 알면 나중에 경로를 조립해서 불러올 수 있다.
  3. 데이터 최소화: DB에는 고유 ID인 verificationId만 남겨 데이터 중복을 제거한다.

4. 코드 반영

엔티티 수정

불필요한 변수를 제거하고 깔끔하게 UUID만 관리한다.

@Entity
@NoArgsConstructor
@Getter
public class DetectionResult {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String verificationId;

    @Enumerated(EnumType.STRING)
    @Column(nullable = false)
    private FraudStatus  status;

    public DetectionResult(String verificationId, FraudStatus status) {
        this.verificationId = verificationId;
        this.status = status;
    }
}

서비스 로직 수정

URL을 합치던 지저분한 로직을 걷어내고, ID 기반으로 저장한다.

// DB에 ID와 상태값만 저장
DetectionResult result = new DetectionResult(verificationId, status);
repository.save(result);

5. 트러블슈팅 결과

  • DB 에러 완벽 해결: 저장하는 데이터가 짧아졌으므로 길이 제한 에러가 원천 차단됨.
  • 유지보수성 향상: 나중에 스토리지 도메인 주소가 바뀌어도 DB 데이터를 일일이 수정할 필요 없이 코드 한 줄로 대응 가능하다.

0개의 댓글