[jpa] BaseEntity와 JPA Auditing - 동작 원리 , 중복필드 제거 (예시코드)

2025. 10. 18. 15:59·공부일기../JPA

1. BaseEntity를 만드는 이유

프로젝트를 진행하다 보면 모든 테이블에 created_at, updated_at 같은 생성일/수정일 컬럼이 반복된다. 매번 직접 추가하면 코드 중복도 많고, 수정 시점 관리도 번거롭다.

이런 반복을 없애고 일관성 있는 엔티티 구조를 유지하기 위해 BaseEntity를 만든다.

 

 


1-1. BaseEntity 코드

package com.serverCommerce.smzShop.common.domain;

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 class BaseEntity {

    @CreatedDate
    @Column(nullable = false, updatable = false, name = "created_at")
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
}

 

 


2. BaseEntity가 필요한 이유

2-1. 모든 엔티티에 공통적으로 필요한 필드 관리

거의 모든 테이블에 생성일, 수정일이 존재한다. 이걸 엔티티마다 중복 선언하면 유지보수가 어렵고 실수도 많아진다.

BaseEntity를 공통 부모 클래스로 만들어 상속시키면 모든 엔티티에 자동으로 이 필드가 포함된다.

@Entity
@Table(name = "users")
public class Users extends BaseEntity {
    // ...
}

이렇게 상속만 해도 users 테이블에는 자동으로 created_at, updated_at 컬럼이 포함된다.

 


 

2-2. 생성일/수정일 자동 입력

그냥 필드만 두면 개발자가 직접 세팅해야 하지만, @CreatedDate와 @LastModifiedDate를 붙이면 JPA가 자동으로 값을 채워준다.

  • 엔티티가 처음 저장될 때: created_at 자동 입력
  • 엔티티가 수정될 때: updated_at 자동 갱신

개발자가 일일이 시간을 넣지 않아도 스프링이 알아서 현재 시간을 넣어준다.

 

 


 

 

3. BaseEntity가 동작하는 원리

이 자동 기록 기능은 내부적으로 "Auditing"이라는 기능을 통해 동작한다.

스프링이 엔티티의 생성/수정 이벤트를 감시하면서 필요할 때 LocalDateTime.now()를 넣어주는 것이다.

이 기능이 작동하려면 세 가지 조건이 필요하다.

 

 


3-1. @MappedSuperclass

해당 클래스의 필드를 자식 엔티티에 그대로 포함시켜라!

  • BaseEntity 자체는 테이블로 만들지 않는다.
  • 대신 Users, Product, Order 같은 엔티티들이 상속받을 때 created_at, updated_at 필드가 함께 매핑된다.

DB에 BaseEntity라는 테이블은 생기지 않는다.

 

 


3-2. @EntityListeners(AuditingEntityListener.class)

해당 클래스의 필드를 자동으로 감시하고, 엔티티 생성/수정 시점에 특정 동작을 수행해라!

  • AuditingEntityListener는 엔티티가 저장되거나 업데이트될 때 호출된다.
  • 그때 @CreatedDate, @LastModifiedDate가 붙은 필드를 찾아서 자동으로 값을 넣는다.

이게 바로 감사(Auditing) 기능이다.

 


 

3-3. @CreatedDate, @LastModifiedDate

해당 시점에 현재 시간을 기록해라!

  • @CreatedDate: 최초 INSERT 시 현재 시간 자동 입력
  • @LastModifiedDate: UPDATE 시 현재 시간 자동 갱신

save() 시 createdAt, update() 시 updatedAt이 자동 반영된다.

 


 

4. JPAConfig는 왜 필요한가

4-1. @EnableJpaAuditing이 Auditing 기능 활성화

BaseEntity에 @EntityListeners(AuditingEntityListener.class)를 붙였다고 자동으로 동작하는 건 아니다.

이 기능은 꺼져 있는 스위치라서 명시적으로 활성화해줘야 한다.

 

그걸 켜는 게 바로 JpaConfig다.

package com.serverCommerce.smzShop.common.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@Configuration
@EnableJpaAuditing
public class JpaConfig {
}

 


 

4-2. 내부 동작 원리

  1. 스프링이 프로젝트 시작 시 @EnableJpaAuditing을 찾는다.
  2. AuditingBeanFactoryPostProcessor가 등록된다.
  3. AuditingEntityListener가 엔티티 라이프사이클 이벤트를 구독한다.
  4. 엔티티가 저장(persist)되면 @CreatedDate 필드에 현재 시간 기록
  5. 엔티티가 수정(update)되면 @LastModifiedDate 필드에 시간 갱신

JpaConfig는 Auditing 기능을 전역적으로 활성화 하는 설정 파일이다.

이게 없으면 BaseEntity의 어노테이션이 있어도 createdAt, updatedAt이 null로 들어간다.

 

 

 


5. 전체 흐름

구분 설명
@MappedSuperclass BaseEntity를 테이블로 만들지 않고, 자식 엔티티에 필드만 상속
@EntityListeners(AuditingEntityListener.class) 엔티티 변경 감시 기능 연결
@CreatedDate 엔티티가 처음 저장될 때 자동 시간 기록
@LastModifiedDate 엔티티 수정 시 자동 시간 갱신
@EnableJpaAuditing (in JpaConfig) 위의 기능을 전체 프로젝트에 활성화

 

 


6. 실제 동작 예시

Users user = new Users("seoungmin", "1234");
userRepository.save(user);

 

저장 후 DB에는 이렇게 들어간다.

username password created_at updated_at
seoungmin 1234 2025-10-18 14:35:00 null

 

그리고 나중에 수정하면

username password created_at updated_at
seoungmin 12345 2025-10-18 14:35:00 2025-10-18 14:40:21

이렇게 updated_at이 자동으로 갱신된다.


 

7.  정리

  • BaseEntity는 모든 엔티티의 공통 엔티티 역할을 한다.
  • JPAConfig는 그 공통엔티티가 실제로 작동하게 하는 역할을 한다.
  • 둘은 세트로 사용해야 자동 시간 기록(Auditing)이 완성된다.

BaseEntity로 공통 필드를 관리하고

JpaConfig로 Auditing 기능을 활성화하여 생성일/수정일을 자동으로 관리한다.

'공부일기.. > JPA' 카테고리의 다른 글

[JPA] Spring Data JPA 페이징 (3/3) - 성능 최적화와 테스트  (0) 2025.12.13
[JPA] Spring Data JPA 페이징(2/3) - 실무 패턴과 동적 쿼리  (0) 2025.12.11
[JPA] Spring Data JPA 페이징 (1/3) - 기본 개념과 핵심 객체  (0) 2025.12.08
[JPA] JPA의 필수개념_2 (식별자 전략 (@Id, @GeneratedValue))  (1) 2025.06.26
[JPA] JPA의 필수개념_1 (JPA정의, Projection)  (0) 2025.06.26
'공부일기../JPA' 카테고리의 다른 글
  • [JPA] Spring Data JPA 페이징(2/3) - 실무 패턴과 동적 쿼리
  • [JPA] Spring Data JPA 페이징 (1/3) - 기본 개념과 핵심 객체
  • [JPA] JPA의 필수개념_2 (식별자 전략 (@Id, @GeneratedValue))
  • [JPA] JPA의 필수개념_1 (JPA정의, Projection)
s0-0mzzang
s0-0mzzang
공부한것을 기록합니다...
  • s0-0mzzang
    승민이의..개발일기..🐰
    s0-0mzzang
  • 전체
    오늘
    어제
    • 전체~ (108)
      • 마음가짐..! (10)
      • 공부일기.. (76)
        • weekly-log (6)
        • Spring (19)
        • Java (18)
        • DataBase (10)
        • git (2)
        • JPA (6)
        • kafka (1)
        • Backend Architecture (3)
        • Troubleshooting (삽질..ㅋ) (2)
        • Cloud (1)
        • Docker (2)
        • 알고리즘 (1)
        • 리액트 (2)
        • Infra (3)
      • 하루일기.. (22)
        • 그림일기 (8)
        • 생각일기 (14)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 깃허브
  • 공지사항

  • 인기 글

  • 태그

    ERD
    자바
    TDD
    MySQL
    ADC 환경
    항해플러스
    스프링부트
    SpringBoot
    항해99
    React
    BufferedReader
    Paging
    다짐
    리팩토링
    spring
    swagger
    StringTokenizer
    spring boot
    JPA
    인프라 기초
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
s0-0mzzang
[jpa] BaseEntity와 JPA Auditing - 동작 원리 , 중복필드 제거 (예시코드)
상단으로

티스토리툴바