Dev Framework/Spring

[Spring][JPA] 스프링 데이터 JPA Auditing 완전 정복

개발자 성현 2025. 4. 28. 23:17

🌟 스프링 데이터 JPA Auditing 완전 정복

– 데이터의 생성과 변경을 자동으로 기록하는 가장 깔끔한 방법

 

1. Auditing이란 무엇인가?

  • Auditing(감사, 기록)은 쉽게 말하면,

"이 데이터가 언제 생성되었는지, 언제 수정되었는지, 누가 수정했는지를 자동으로 기록하는 기능"입니다.

우리가 실제 서비스를 운영하다 보면, 거의 대부분의 테이블에 이런 칼럼들이 존재합니다.

칼럼명 의미
created_at 데이터가 처음 생성된 시간
updated_at 데이터가 마지막으로 수정된 시간
created_by 데이터를 처음 만든 사용자
updated_by 마지막으로 데이터를 수정한 사용자

처음에는 직접 setCreatedAt() 하면서 채우겠지만,

규모가 커지면 매번 이런 코드를 반복하는 것은 비효율적이고, 오타, 실수도 잦아집니다.

👉 그래서 Spring Data JPA는 Auditing 기능을 통해 자동으로 이런 필드를 관리할 수 있도록 지원합니다.

2. Auditing의 핵심 원리

Spring Data JPA의 Auditing은

Entity를 저장하거나 수정하는 이벤트가 발생할 때,

스프링이 자동으로 엔티티의 필드 값을 채워주는 방식으로 작동합니다.

이를 위해 내부적으로는

  • 엔티티 리스너(EntityListener)를 등록하고,
  • JPA의 라이프사이클 이벤트(PrePersist, PreUpdate 등)를 활용합니다.

쉽게 말해,

"DB에 insert/update 직전에, 알아서 시간이나 사용자 정보를 꽂아 넣는 리스너를 등록해주는 것"입니다.

 

3. Auditing을 적용하는 방법

이제 실제로 Auditing을 사용하는 방법을 단계별로 정리해봅니다.

 

📌 Step 1. 설정 활성화

@EnableJpaAuditing을 메인 애플리케이션 클래스나 설정 파일에 추가해야 합니다.

@EnableJpaAuditing
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

🔥 주의:

@EnableJpaAuditing은 Bean이 다 올라온 이후 작동하므로, 보통 @SpringBootApplication 클래스에 함께 둡니다.

 

📌 Step 2. 공통 BaseEntity 만들기

모든 엔티티가 공통으로 상속받을 BaseTimeEntity 같은 추상 클래스를 하나 정의합니다.

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
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime updatedAt;
}

설명

  • @MappedSuperclass : 이 클래스를 직접 테이블로 만들지 않고, 자식 엔티티가 필드를 상속받게 합니다.
  • @EntityListeners(AuditingEntityListener.class) : 엔티티 저장/수정 시 자동으로 리스너가 동작하도록 연결합니다.
  • @CreatedDate : insert 시 자동으로 시간 채워줌
  • @LastModifiedDate : update 시 자동으로 시간 채워줌

 

📌 Step 3. 실제 엔티티에 적용하기

모든 엔티티는 BaseTimeEntity를 상속하면 끝입니다.

@Entity
public class Post extends BaseTimeEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;
    private String content;
}

이제 Post를 저장하거나 수정할 때, createdAt, updatedAt은 자동으로 관리됩니다.

 

4. createdBy, updatedBy처럼 "작성자"까지 기록하고 싶다면?

시간만 기록하는 게 아니라,

"누가 만들었는지" 까지 남기고 싶을 수도 있습니다.

이 경우에는 추가로 @CreatedBy, @LastModifiedBy를 사용할 수 있습니다.

@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {

    @CreatedDate
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime updatedAt;

    @CreatedBy
    private String createdBy;

    @LastModifiedBy
    private String updatedBy;
}

 

단, 작성자(createdBy) 정보는 스프링이 알아서 채워줄 수 없기 때문에,

AuditorAware라는 인터페이스를 구현해줘야 합니다.

 

5. AuditorAware 구현하기

import org.springframework.data.domain.AuditorAware;
import org.springframework.stereotype.Component;

import java.util.Optional;

@Component
public class AuditorAwareImpl implements AuditorAware<String> {

    @Override
    public Optional<String> getCurrentAuditor() {
        // 예: 스프링 시큐리티를 사용하는 경우, 현재 로그인한 사용자 ID 반환
        return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication().getName());
    }
}
  • 이 AuditorAware 빈을 만들어두면, Spring Data JPA가 자동으로 감지해서 createdBy, updatedBy에 값을 채워줍니다.
  • 로그인 정보가 없을 때 예외 방지를 위해 Optional을 사용합니다.

Tip

  • 보통 실무에서는 회원 ID, 이메일, 시스템 계정 등을 넣습니다.

 

6. Auditing 필드 초기화 타이밍

어노테이션 적용 타이밍
@CreatedDate insert(처음 저장) 시 1번만
@LastModifiedDate insert + update 모두
@CreatedBy insert 시 1번만
@LastModifiedBy insert + update 모두

즉,

  • createdAt, createdBy는 처음 생성할 때만 세팅되고,
  • updatedAt, updatedBy는 수정할 때마다 계속 업데이트됩니다.

 

7. 실무에서 자주 나오는 실수들

실수 문제점 해결법
@EnableJpaAuditing 빼먹음 아예 동작 안 함 꼭 메인 클래스에 추가
기본 생성자 없는 엔티티 Hibernate가 insert/update 시 실패 엔티티에 protected 기본 생성자 추가
AuditorAware 설정 안 함 createdBy, updatedBy가 null로 저장 AuditorAware 빈 등록 필수
날짜 타입 잘못 사용 LocalDateTime 대신 String 쓰면 에러 가능 꼭 LocalDateTime, Instant 같은 타입 사용

 

최종 요약

Spring Data JPA Auditing = 엔티티의 생성/수정 시간, 작성자/수정자를 자동으로 관리하는 기능.

@EnableJpaAuditing을 켜고, BaseEntity를 상속해서 적용. 추가로 작성자 기록은 AuditorAware을 구현.

 

 

✨ 마무리

Auditing을 제대로 설정해두면,

  • 코드가 훨씬 깔끔해지고
  • 수정 실수가 줄어들고
  • 데이터 변경 이력을 쉽게 추적할 수 있습니다.

작은 프로젝트에도 습관처럼 적용하는 걸 추천합니다.

"기록은 시스템을 살린다"는 말처럼, 데이터는 시간이 지남에 따라 반드시 추적 가능성을 가져야 합니다.

 

Auditing 심화편으로 이어집니다.