[SpringBoot] 2024 게시판 만들기 Q&A ③ - BaseTimeEntity

SihoonCho·2023년 2월 24일
1
post-thumbnail

※ 읽기에 앞서


본 시리즈는 작성자의 이해와 경험을 바탕으로 실습 위주의 설명을 제공하고자 작성되었습니다.
실습 중심의 이해를 목표로 작성되었기 때문에, 다소 과장되거나 생략된 부분이 있을 수 있습니다.
따라서, 이론적으로 미흡한 부분이 있을 수 있는 점에 유의하시고 양해 부탁드립니다.

또한, Spring Boot 기반의 Backend 개발에 중점을 두고 설명하고 있으므로,
Frontend와 관련된 내용은 별도의 참고자료를 검색/활용하실 것을 권장드립니다.


📌 Hibernate vs BaseTimeEntity


과거 Java 8, Spring Boot 2.x 를 사용하던 시절에는, JPA를 사용하는 경우 JPA Auditing 기능을 활용해 엔티티의 생성 시간과 수정 시간을 자동으로 관리했습니다. 이 방식은 특히, BaseTimeEntity라는 공통 상속 클래스를 만들어, 여러 엔티티에서 상속받아 사용함으로써, 중복 코드를 제거하는데 매우 유용했습니다.

그러나, 시간이 흘러 Spring Boot 2.x의 지원이 종료되고, Java 17, Spring Boot 3.x의 시대로 넘어오며, HibernateSpring Boot와 좀 더 밀접히 통합되면서, Hibernate에서 제공하는 @CreationTimestamp@UpdateTimestamp 널리 사용되기 시작했습니다.

하지만, 오래된 시스템이나 Hibernate가 사용되지 않는 시스템 등 JPA Auditing 기능을 활용한 BaseTimeEntity는 지금도 여전히 많이 사용되는 패턴 중 하나입니다.

따라서, 이번 글에서는 JPA AuditingBaseTimeEntity의 사용 방식과
Hibernate 어노테이션 기반 방식의 차이와 각각의 장단점을 알아보겠습니다.


📌 JPA Auditing



📖 패키지 구조


├── src
│   ├── main
│   │   ├── java
│   │   │   └── com.companyname.projectname
│   │   │       ├── common
│   │   │       │   └── model
│   │   │       │       └── BaseTimeEntity.java    # 공통 상위 엔티티
│   │   │       ├── post
│   │   │       │   └── model
│   │   │       │       └── Post.java
│   │   │       └── ProjectNameApplication.java
│   │   └── resources
│   └── test

📖 BaseTimeEntity.java


package com.companyname.projectname.common.model;

import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseTimeEntity {
    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdDate;

    @LastModifiedDate
    @Column(updatable = true)
    private LocalDateTime updatedDate;
}

LombokJPA Auditing을 사용한 추상화 클래스로 구현되었으며,
날짜/시간 등의 데이터는 거의 대부분의 데이터에 포함되는 공통 속성으로
여러 엔티티에서 상속받아 시간 관리 로직을 중복 코드 없이 재사용 가능합니다.


📖 Post.java


package com.companyname.projectname.post.model;

import com.companyname.projectname.common.model.BaseTimeEntity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Post extends BaseTimeEntity {	// 상속
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String content;
}

@Entity로 명시된 엔티티 클래스에서 BaseTimeEntity를 상속받습니다.


📖 MainApplication.java


package com.companyname.projectname;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing 			// JPA Auditing 활성화
@SpringBootApplication
public class ProjectNameApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProjectNameApplication.class, args);
    }
}

JPA Auditing을 사용하려면 메인 클래스에서 JPA Auditing을 활성화해야 합니다.

Spring Boot 프로젝트의 메인 클래스는 ProjectNameApplication.java이며,
@SpringBootApplication 어노테이션이 기본으로 작성되어있습니다.
여기에 @EnableJpaAuditing를 추가합니다.


📌 Hibernate



📖 패키지 구조


├── src
│   ├── main
│   │   ├── java
│   │   │   └── com.companyname.projectname
│   │   │       ├── post
│   │   │       │   └── model
│   │   │       │       └── Post.java
│   │   │       └── ProjectNameApplication.java
│   │   └── resources
│   └── test

📖 Post.java


package com.companyname.projectname.post.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.LocalDateTime;

@Entity
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String content;

    @CreationTimestamp
    private LocalDateTime createdDate;
    @UpdateTimestamp
    private LocalDateTime updatedDate;
}

Hibernate@CreationTimestamp, UpdateTimestamp 어노테이션을 추가합니다.


📌 결론


데이터 삽입/수정 작업 실행 결과, 연결된 데이터베이스에 Post 테이블이 생성되고,
상속 받은 BaseTimeEntity 객체에 의해 '날짜/시간' 속성도 생성됩니다.


📖 JPA Auditing


  • 장점
    • 시간 관리 로직을 중복 코드 없이 재사용 가능
    • 유지보수가 간편하고, 코드 가독성이 좋아지는 효과
    • Spring Data JPAJPA Auditing 기능을 활용해 엔티티의 생명주기와 연동
  • 단점
    • 모든 엔티티가 BaseTimeEntity를 상속받아야 하므로, 상속 구조의 강제성 발생
    • 상속 외에는 사용할 수 없어, 특정 엔티티에서만 시간 필드를 사용할 경우
      불필요한 의존성이 생김

📖 Hibernate


  • 장점
    • 유연성: 필요한 엔티티에서만 필요시 적용 가능
    • 간결성: 추가 상속 없이 엔티티 클래스에 바로 선언 가능
    • 직관적: 어노테이션 이름만으로 필드의 역할을 쉽게 이해할 수 있음
  • 단점
    • Hibernate를 사용하지 않는 환경에서는 사용할 수 없음
    • Spring Data JPAJPA Auditing만큼 엔티티 생명주기를 세밀하게 다루기는 어려움

이 방식은 JPA 표준이 아니지만, 간결하고 유연한 시간 관리가 가능하다는 장점이 있습니다.


📖 Hibernate vs JPA Auditing


Hibernate를 사용하는 프로젝트라면 @CreationTimestamp@UpdateTimestamp를 사용하는 것이 더 간단하고 현대적인 선택입니다.

그러나, 오래된 시스템이거나 Hibernate를 사용하지 않는 시스템이라면,
Spring Data JPAJPA Auditing 기능을 활용하는 BaseTimeEntity 방식이 여전히 유효합니다.

결론적으로, 선택의 기준에 따라 다릅니다.

최근 개발 환경은 간결함과 유연함을 추구하고 요구하고 있습니다.
필자는 개인적으로 코드의 가독성과 유지보수성, 확장성 등을 고려하여
Hibernate@CreationTimestamp@UpdateTimestamp 방식을 권장합니다.

JPA AuditingBaseTimeEntity는 여전히 유효한 방식이지만, Hibernate@CreationTimestamp@UpdateTimestamp`를 사용하는 코드들이 늘어나고 있습니다.

그러나, 개발 트렌드는 항상 변화합니다. 늘 프로젝트의 요구 사항과
기술 스택에 맞는 적절한 방식을 선택하는 것이 가장 중요합니다.



본 시리즈는 작성자의 이해와 경험을 바탕으로 실습 위주의 설명을 제공하고자 작성되었습니다.
실습 중심의 이해를 목표로 작성되었기 때문에, 다소 과장되거나 생략된 부분이 있을 수 있습니다.
따라서, 이론적으로 미흡한 부분이 있을 수 있는 점에 유의하시고 양해 부탁드립니다.

또한, Spring Boot 기반의 Backend 개발에 중점을 두고 설명하고 있으므로,
Frontend와 관련된 내용은 별도의 참고자료를 검색/활용하실 것을 권장드립니다.
profile
개발을 즐길 줄 아는 백엔드 개발자

0개의 댓글