AI Briefing

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

·2025.08.05 15:39

핵심 내용

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

자세히 보기

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

핵심 원인은 Spring JDBC 내부의 StatementCreatorUtils.setParameterValue()였다. 여기서는 입력값이 LocalDate면 setDate(), 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가 특별 취급하지 않는 사용자 정의 타입으로 감싸면 커스텀 컨버터가 정상 적용되고, CustomLocalDateToStringConverter와 StringToCustomLocalDateConverter를 함께 등록해 저장/조회 양방향 변환을 안정적으로 제어할 수 있다.

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

이 한국어 요약은 AI가 자동으로 만들었습니다. 원문의 주장과 맥락은 원문에서 확인해 주세요. 저작권은 원저작자에게 있습니다.

AI 처리 방식을 확인하거나, 요약 오류와 출처 표기 문제, 삭제 요청을 문의 · 건의로 알려주세요.