AI Briefing

똑같은 코드인데 왜 안 되지? Spring JDBC 컨버터 미로 탈출기

·2025.08.05 15:39

Spring Data JDBC의 LocalDate는 특별 처리돼 커스텀 컨버터가 안 먹혔다.

Spring Data JDBC에서 LocalDate를 문자열로 저장하려고 커스텀 컨버터를 등록했지만, 기대와 달리 동작하지 않았다. 같은 방식으로 만든 LocalDateTime 컨버터는 되는 것처럼 보였지만, 실제로는 컨버터가 아니라 JDBC의 타입 처리 차이 때문에 그렇게 보였던 것이다.

핵심 원인은 Spring JDBC 내부의 StatementCreatorUtils.setParameterValue()였다. 여기서는 입력값이 LocalDatesetDate(), LocalDateTime이면 setTimestamp()를 먼저 타고, 그보다 앞서 등록한 커스텀 컨버터보다 Java 타입별 특별 처리 경로가 우선 적용된다.

이 차이 때문에 결과가 갈렸다.

  • LocalDate + setDate(): Oracle JDBC가 DATE 타입으로 인식해 VARCHAR 컬럼과 충돌하거나 01-AUG-24 같은 Oracle 기본 형식으로 변환된다.
  • LocalDateTime + setTimestamp(): Oracle이 Timestamp를 문자열로 관대하게 변환해 저장하면서 정상 동작처럼 보였다.

문제 해결을 위해 시도한 방법도 정리된다.

  • @DateTimeFormat은 웹 요청 파라미터 바인딩용이라 DB 매핑에는 효과가 없었다.
  • JdbcTemplate 직접 사용은 동작하지만 Spring Data JDBC의 편의성을 잃는다.
  • String 필드로 바꾸는 방식은 가능하지만 엔티티 의미가 흐려진다.

가장 깔끔한 해결책은 CustomLocalDate 래퍼 클래스를 만드는 것이었다. Spring JDBC가 특별 취급하지 않는 사용자 정의 타입으로 감싸면 커스텀 컨버터가 정상 적용되고, CustomLocalDateToStringConverterStringToCustomLocalDateConverter를 함께 등록해 저장/조회 양방향 변환을 안정적으로 제어할 수 있다.

마지막으로, 이런 저수준 동작은 DB 벤더와 JDBC 드라이버 버전에 따라 달라질 수 있으므로, 실제 프로덕션 적용 전에는 저장된 raw value까지 확인하는 테스트가 필요하다.

이 요약은 원문 이해를 돕기 위한 큐레이션입니다. 저작권은 원저작자에게 있으며, 정확한 내용과 맥락은 원문을 확인하세요.

요약 오류, 출처 표기 문제, 삭제 요청은 문의 · 건의로 알려주세요.