JPA Auditing이란?
JPA Auditing은 Spring Data JPA에서 제공하는 기능 중 하나로, 엔티티가 생성되거나 수정될 때 자동으로 생성일, 수정일, 생성자, 수정자를 기록하는 기능입니다. 이 기능을 사용하면 데이터베이스 테이블에 발생하는 변화 내역을 쉽게 추적할 수 있습니다.
1. 의존성추가
Spring Data JPA 의존성을 추가합니다.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
}
2. 엔티티 클래스에 Auditing 필드 추가
엔티티 클래스에
@CreatedDate, @LastModifiedDate, @CreatedBy, @LastModifiedBy
어노테이션을 추가하여 자동으로 값을 기록합니다.
@Entity
@EntityListeners(AuditingEntityListener.class)
public class YourEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime modifiedDate;
@CreatedBy
private String createdBy;
@LastModifiedBy
private String modifiedBy;
}
3. Auditing 활성화
@EnableJpaAuditing 어노테이션을 사용하여 Auditing 기능을 활성화합니다.
@SpringBootApplication
@EnableJpaAuditing
public class SampleApplication {
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
}
주요 어노테이션
@CreatedDate | 엔티티가 생성된 시각을 기록 |
@LastModifiedDate | 엔티티가 마지막으로 수정된 시각을 기록 |
@CreatedBy | 엔티티가 생성된 사용자를 기록 |
@LastModifiedBy | 엔티티가 마지막으로 수정된 사용자를 기록 |
4. AuditorAware 구현
@CreatedBy와 @LastModifiedBy와 같은 필드를 채우려면 AuditorAware 인터페이스를 구현해야 합니다.
JPA Auditing을 통해 엔티티가 생성되거나 수정될 때 자동으로 날짜, 시간, 그리고 현재 작업 중인 사용자 정보를 기록할 수 있습니다. 이때, AuditorAware 인터페이스는 현재 사용자의 정보를 제공하는 역할
1) 고정된 사용자 반환
기본적으로, 특정 사용자 정보를 반환하도록 설정할 수 있습니다. 이는 주로 테스트 환경에서 사용
@Component
public class AuditorAwareImpl implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
return Optional.of("Admin"); // 항상 "Admin"이라는 고정된 사용자 반환
}
}
위 코드에서는 고정된 "Admin" 값을 반환하며, 이는 엔티티가 생성되거나 수정될 때 "Admin"이 작업한 것으로 기록됩니다. 하지만, 실제 애플리케이션에서는 현재 로그인한 사용자 정보를 반환
2) Spring Security와 연동하여 현재 사용자 반환
실제 애플리케이션에서는 보통 Spring Security와 연동하여 현재 로그인한 사용자를 getCurrentAuditor()에서 반환하도록 설정
@Component
public class AuditorAwareImpl implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
// Spring Security의 인증 정보를 가져옴
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 인증된 사용자가 없거나 익명 사용자일 경우
if (authentication == null || !authentication.isAuthenticated() || authentication.getPrincipal().equals("anonymousUser")) {
return Optional.empty(); // 인증되지 않은 경우, 아무 것도 반환하지 않음
}
// 인증된 사용자의 이름을 반환
return Optional.of(authentication.getName());
}
}
SecurityContextHolder.getContext().getAuthentication(): Spring Security에서 현재 인증된 사용자의 정보를 가져옵니다.
authentication.getName(): 현재 로그인한 사용자의 이름을 반환합니다.
이 값이 @CreatedBy 또는 @LastModifiedBy에 자동으로 저장됩니다.
구현된 AuditorAware 클래스가 사용되는 방식
1. 엔티티 클래스에 Auditing 설정
엔티티 클래스에 @CreatedBy, @LastModifiedBy 필드를 추가하고
@EntityListeners(AuditingEntityListener.class)를 통해 JPA Auditing 기능을 활성화
@Entity
@EntityListeners(AuditingEntityListener.class)
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@CreatedBy
private String createdBy;
@LastModifiedBy
private String modifiedBy;
// 기타 필드들
}
2. Auditing 활성화
Spring Boot 설정 클래스에서 @EnableJpaAuditing을 추가하여 JPA Auditing 기능을 전역적으로 활성화합니다.
아까 위의 코드와 동일합니다.
@SpringBootApplication
@EnableJpaAuditing
public class SampleApplication {
public static void main(String[] args) {
SpringApplication.run(SampleApplication.class, args);
}
}
auditorAwareRef는 AuditorAware 구현체의 빈 이름을 지정합니다.
이 설정을 통해 Spring Boot는 getCurrentAuditor() 메서드를 호출하여 자동으로 현재 사용자를 추적하고,
엔티티의 createdBy와 modifiedBy 필드를 업데이트합니다.
전체 흐름 요약
- AuditorAware 인터페이스 구현: 현재 사용자 정보를 반환하는 getCurrentAuditor() 메서드를 구현합니다.
- Auditing 활성화: Spring Boot 설정 클래스에서 @EnableJpaAuditing으로 Auditing을 활성화합니다.
- 엔티티에서 사용자 정보 기록: 엔티티에서 @CreatedBy와 @LastModifiedBy를 설정하고, 이 필드에 자동으로 현재 사용자 정보를 기록합니다.
이를 통해 데이터베이스에 기록되는 데이터를 누가 생성하고 수정했는지 쉽게 추적할 수 있으며, 주로 로그인 시스템과 연동하여 사용됩니다.
@MappedSuperClass
JPA에서 공통 엔티티 속성을 상속하기 위해 사용되는 어노테이션
@MappedSuperclass를 @EntityListeners와 함께 사용하면,
여러 엔티티에서 공통적으로 사용하는 필드를 한 번에 정의하고 해당 필드에 대한 감사(auditing) 기능을 손쉽게 적용할 수 있습니다.
즉, 공통된 속성(예: createdDate, createdBy, modifiedDate, modifiedBy)을 여러 엔티티에 반복하지 않고, 공통 상위 클래스에 정의한 후 상속받아 사용할 수 있습니다.
@MappedSuperclass의 역할
@MappedSuperclass는 다른 엔티티 클래스들이 상속받아 사용할 공통 속성을 정의할 때 사용됩니다.
직접 데이터베이스 테이블로 매핑되지 않고, 상속받는 엔티티 클래스에 매핑됩니다.
예를 들어, 여러 엔티티에 동일한 createdDate, modifiedDate, createdBy, modifiedBy 같은 필드가 있다면, 이를 각 엔티티에 개별적으로 정의하는 대신, @MappedSuperclass로 상위 클래스에 정의하고 상속하여 사용하면 코드가 간결해집니다.
@EntityListeners의 역할
@EntityListeners는 엔티티의 생명 주기(생성, 수정 등) 이벤트를 감지하여 특정 동작을 실행할 수 있게 합니다. 이를 통해 JPA Auditing 기능을 적용할 수 있습니다. @CreatedDate, @LastModifiedDate, @CreatedBy, @LastModifiedBy 필드에 값을 자동으로 넣는 것이 대표적인 사용 사례입니다.
@PrePersist | Persist(Insert) 메서드가 호출되기 전에 실행되는 메서드 |
@PreUpdate | Merge(Update) 메서드가 호출되기 전에 실행되는 메서드 |
@PreRemove | Remove(Delete) 메서드가 호출되기 전에 실행되는 메서드 |
@PostPersist | Persist(Insert) 메서드가 호출된 후에 실행되는 메서드 |
@PostUpdate | Merge(Update) 메서드가 호출된 후에 실행되는 메서드 |
@PostRemove | Remove(Delete) 메서드가 호출된 후에 실행되는 메서드 |
@PostLoad | Select 조회가 실행된 직후에 실행되는 메서드 |
@MappedSuperclass + @EntityListeners 함께사용하는 경우
1. 공통 상위 클래스 정의 (@MappedSuperclass + @EntityListeners)
먼저, 여러 엔티티에 공통으로 적용할 필드와 Auditing 기능을 가진 상위 클래스를 정의합니다.
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.MappedSuperclass;
import javax.persistence.EntityListeners;
import java.time.LocalDateTime;
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class) // Auditing 기능 활성화
public abstract class BaseEntity {
@CreatedDate
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime modifiedDate;
@CreatedBy
private String createdBy;
@LastModifiedBy
private String modifiedBy;
// Getters and Setters
public LocalDateTime getCreatedDate() {
return createdDate;
}
... 생략
}
@MappedSuperclass: 이 클래스는 데이터베이스에 직접 매핑되지 않고, 이를 상속하는 엔티티들이 상속받은 필드만 매핑됩니다.
@EntityListeners(AuditingEntityListener.class): AuditingEntityListener를 사용하여 Auditing 기능을 활성화합니다.
이를 통해 createdDate, modifiedDate, createdBy, modifiedBy 필드가 자동으로 채워집니다.
2. 엔티티 클래스에서 상속 사용
이제 각 엔티티 클래스는 BaseEntity 를 상속받아 공통 필드를 재사용 할 수 있습니다.
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class User extends BaseEntity {
@Id
private Long id;
private String name;
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
생략...
}
User 엔티티는 BaseEntity를 상속받음으로써 createdDate, modifiedDate, createdBy, modifiedBy 같은 공통 필드를 자동으로 포함하게 됩니다.
이때, @CreatedBy, @LastModifiedBy 등의 필드는 AuditorAware 인터페이스 구현체에 의해 값이 채워집니다.
'개발관련' 카테고리의 다른 글
[Spring Security] @EnableMethodSecurity와 @EnableGlobalMethodSecurity (0) | 2024.09.10 |
---|---|
DDD란? (1) | 2024.09.06 |
[Spring Security] canAccessUser 메서드 (0) | 2024.09.04 |
[Spring Security] @Secured, @PreAuthorize, @PostAuthorize (0) | 2024.09.04 |
CI/CD 란 무엇인가 ? (0) | 2024.08.19 |