🌟 스프링 데이터 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 심화편으로 이어집니다.
'Dev Framework > Spring' 카테고리의 다른 글
[Spring][JPA] N+1 문제의 발생부터 해결까지 (0) | 2025.05.01 |
---|---|
[Spring][JPA] 스프링 데이터 JPA Auditing 심화편 (1) | 2025.04.28 |
[Spring][JPA] Hibernate에서 FROM 절 서브쿼리를 만들 수 없는 이유 (0) | 2025.04.28 |
[Spring] 트랜잭션 예외에 따른 커밋(Commit)과 롤백(Rollback) (0) | 2025.04.22 |
[Spring] MessageConverter (0) | 2025.04.07 |