Spring/문제 해결 (Troubleshooting)

@LastModifiedDate 와 DB의 ON UPDATE CURRENT_TIMESTAMP 동시 사용 문제

가지코딩 2025. 5. 23. 13:33

updatedAt 필드를 자동으로 관리하는 방법 2가지

  • JPA Auditing의 @LastModifiedDate: 엔티티가 변경될 때 JPA가 Java 객체의 필드를 수정
  • DB의 ON UPDATE CURRENT_TIMESTAMP: DB에서 직접 updated_at 값을 자동 변경

 

이 둘을 동시에 사용하면 시간 값이 충돌하거나 예상치 못한 동작이 발생할 수 있다.


발생 가능한 문제

문제 유형 설명
값 불일치 애플리케이션에서 설정한 @LastModifiedDate 값과 DB에서 자동 설정한 값이 다를 수 있음
엔티티 변경 감지 실패 DB에서 자동 갱신한 값이 영속성 컨텍스트에 반영되지 않아 dirty checking에 영향을 줄 수 있음
무한 업데이트 루프 DB에서 업데이트된 시간 값으로 인해, 엔티티가 계속 변경되었다고 인식되어 저장을 반복할 수 있음 (특히 auditing + dirty checking 같이 쓸 때)
JPA Auditing 무력화 @LastModifiedDate로 설정된 값이 persist 되기 전에 DB에서 다른 값으로 덮어쓸 수 있음

해결 방법 및 권장 사항

1. 둘 중 하나만 사용하기

  • Spring Auditing만 사용
    • @LastModifiedDate를 활용하고, DB 제약 조건 제거
    • 모든 시간 변경은 Java 측에서 통제
  • DB 제약 조건만 사용
    • @LastModifiedDate 제거하고, ON UPDATE에 맡김
    • DB에서 시간 통제 (e.g., 외부 시스템과 통합되어 DB 레벨 제약 필요 시)

 

2. JPA에서 DB 트리거 무시하기

  • DB에서 ON UPDATE CURRENT_TIMESTAMP를 쓰되, JPA에서는 해당 필드를 insertable = false, updatable = false로 설정
@Column(name = "last_modified", insertable = false, updatable = false)
private LocalDateTime lastModified;

Spring Auditing vs DB 제약 조건

구분 Spring Auditing (@LastModifiedDate)  DB 제약 조건 (ON UPDATE CURRENT_TIMESTAMP)
적용 위치 애플리케이션(Java) 데이터베이스(MySQL 등)
테스트 용이성 ✅ 시간 mocking 가능, 단위 테스트 친화적 ❌ DB 의존, mocking 어려움
시간 정확성 ❌ 서버 시간 기준 (NTP 불일치 시 문제 가능) ✅ DB 시간 기준으로 일관성 보장
외부 시스템 호환성 ❌ 외부에서 직접 DB 수정 시 시간 불일치 우려 ✅ DB가 시간 통제 → 일관성 유지
유지보수성 ✅ Java 코드로 제어 가능, DB 종속 낮음 ❌ DB마다 문법 상이 → 이식성 낮음
클라우드/이식성 ✅ DB 트리거 없이 어디서나 동일 동작 ❌ 특정 DB에 종속됨 (예: MySQL 전용 문법)
엔티티 일관성 ✅ 엔티티 변경과 시간 갱신이 함께 처리됨 ❌ DB가 시간 설정하므로 엔티티 객체엔 반영 안 됨
무결성 보장 ❌ 애플리케이션 오류 시 잘못된 시간 저장 가능 ✅ DB 단독으로 보장됨 (신뢰성 높음)
사용 권장 시점 - Spring 기반 단일 애플리케이션
- 테스트/이식성 중시
- 도메인 중심 설계
- 외부 시스템과 DB 공유
- 데이터 신뢰성/무결성 중요
- 레거시 또는 DB 중심 구조

 

시스템의 구조와 요구사항에 따라 한 가지 방식을 선택하고 일관성 있게 적용하는 것이 중요하다 !

  • 애플리케이션 중심의 설계테스트 용이성을 중시한다면 → @LastModifiedDate
  • 데이터 무결성과 외부 시스템과의 통합이 핵심이라면 → ON UPDATE CURRENT_TIMESTAMP