Todo API를 만들어보기 시작하면서 Entity의 생성 시간을 기록할 필요성이 생겼다.
이에 검색을 좀 해보니 주로 @CreatedTimestamp 와 @CreatedDate가 생성 시간을 기록하는 데 쓰이는 것 같았다.
두 어노테이션 모두 생성시간을 기록하는 목적을 가지고 있지만 사용 방식이 조금 달랐다.
@CreatedDate는 Spring Data JPA에 포함된 어노테이션으로 @EnableJpaAuditting을 사용하여 JPA Auditing을 활성화 시키는 과정이 필요하다. 거기에 추가로 @CreatedDate를 사용하고 싶은 Entity Class에 @EntityListeners(AuditingEntityListener.class)를 설정해줘야 동작한다.
@CreatedDate
@Column(name = "createdAt", nullable = false, updatable = false)
val createdAt: Instant = Instant.now(),
위와 같은 식으로 사용하며 Instant 외에 LocalDateTime, LocalDate, Date 등을 지원한다.
@CreationTimestamp는 Hibernate에 포함된 어노테이션으로 별도의 추가 설정 없이 Hibernate만 사용하고 있다면 바로 사용가능하다.
@field:CreationTimestamp(source = SourceType.DB)
@Column(name = "createdAt", nullable = false, updatable = false)
val createdAt: ZonedDateTime? = null,
위와 같은 식으로 사용하며 java.sql.Timestamp, java.time.LocalDateTime, ZonedDateTime 등을 지원한다. SourceType은 timestamp 생성의 주체를 설정하는 것으로 기본 값은 VM으로 hibernate가 생성하는 것이고 DB로 설정해두면 db에서 생성된다.
일반적으로 @CreatedDate가 더 많이 사용되며 그 이유는 다음과 같다.
프레임워크 통합성: @CreatedDate는 Spring Data JPA의 Auditing 기능의 일부로, Spring 생태계에서 자연스럽게 통합된다. 아직 @CreatedDate 외에는 사용해보지는 않았지만 다른 JPA Auditing 기능을 사용할 것을 고려한다면 하나의 프레임워크 내에서 이뤄지는 것이 좋다.
확장성 및 유지보수: 앞서 언급한 Spring Data JPA의 Auditing 기능은 수정 시간@LastModifiedDate, 생성자@CreatedBy, 수정자@LastModifiedBy 등의 기능도 함께 제공한다. 이로 인해 Entity의 변경 이력을 추적할 때 더 유연하고 강력한 기능을 제공한다.
JPA 표준 준수: @CreatedDate는 Spring Data JPA의 명확한 Auditing 용도로 설계된 어노테이션이다. 반면, @CreationTimestamp는 Hibernate에 종속적인 기능으로, 표준 JPA 기능보다는 특정 ORM 구현체에 의존적이다.
따라서, Spring Data JPA를 사용하는 프로젝트에서는 주로 @CreatedDate를 사용하는 것이 일반적이다.
처음에는 @CreationTimestamp가 설정이 따로 필요없고 간편하길래 사용해봤다. 그런데 코드를 다 짜고 보니 nullcheck면도 좀 이상하고 SourceType을 DB로 하는게 아니라면 UTC timezone을 쓴다고 명시하는 것이 코드 내부가 아니라 application.yml인 점 등이 좀 마음에 안들어서(이 부분은 다른 방식으로 해결할 수 있었을지도 모른다.) @CreatedDate 를 쓰는 쪽으로 리팩토링했다.