Auditing

2024. 10. 22. 19:01Spring Boot/Spring Data JPA

Spring Data JPA는 엔티티가 언제, 누구에 의해 생성되거나 수정되었는지를 투명하게 추적할 수 있도록 고급 지원을 제공합니다. 이를 위해 엔티티 클래스에 감사 메타데이터를 추가해야 하며, 이 메타데이터는 어노테이션을 사용하거나 인터페이스를 구현하여 정의할 수 있습니다. 또한 감사 기능을 활성화하려면 어노테이션 구성 또는 XML 구성을 통해 필요한 인프라 구성 요소를 등록해야 합니다.

Annotation-based Auditing Metadata

Spring Data JPA에서는 @CreatedBy, @LastModifiedBy, @CreatedDate, @LastModifiedDate 어노테이션을 사용하여 엔티티의 생성자와 수정자, 그리고 변경 시점을 캡처할 수 있습니다.

예시: 감사 메타데이터가 포함된 엔티티

import javax.persistence.*;
import java.time.Instant;

@Entity
public class Customer {

    @CreatedBy
    private User user; // 생성한 사용자

    @CreatedDate
    private Instant createdDate; // 생성 일시

    // 기타 속성 생략
}

위의 코드에서 볼 수 있듯이, 감사 정보를 캡처할 필드에 해당 어노테이션을 적용하여 필요한 정보만 캡처할 수 있습니다. 이 어노테이션은 JDK8의 날짜 및 시간 타입, long, Long, 구식 Java Date 및 Calendar 타입의 속성에 사용할 수 있습니다.

임베디드 엔티티의 감사 메타데이터

감사 메타데이터는 루트 엔티티에만 존재할 필요는 없으며, 임베디드 엔티티에도 추가할 수 있습니다.

예시: 임베디드 엔티티의 감사 메타데이터

@Entity
public class Customer {

    private AuditMetadata auditingMetadata; // 감사 메타데이터

    // 기타 속성 생략
}

@Embeddable
class AuditMetadata {

    @CreatedBy
    private User user; // 생성한 사용자

    @CreatedDate
    private Instant createdDate; // 생성 일시
}

 

Interface-based Auditing Metadata

 

어노테이션을 사용하지 않고 감사 메타데이터를 정의하려면, 도메인 클래스가 Auditable 인터페이스를 구현하도록 할 수 있습니다. 이 인터페이스는 모든 감사 속성에 대한 setter 메서드를 노출합니다.

AuditorAware

@CreatedBy 또는 @LastModifiedBy를 사용할 경우, 현재 사용자를 인식할 수 있도록 AuditorAware<T> SPI 인터페이스를 구현해야 합니다. 이 인터페이스는 감사 메타데이터에서 사용할 속성의 타입을 정의합니다.

예시: Spring Security 기반 AuditorAware 구현

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.data.domain.AuditorAware;

import java.util.Optional;

public class SpringSecurityAuditorAware implements AuditorAware<User> {

    @Override
    public Optional<User> getCurrentAuditor() {
        return Optional.ofNullable(SecurityContextHolder.getContext())
                .map(SecurityContext::getAuthentication)
                .filter(Authentication::isAuthenticated)
                .map(Authentication::getPrincipal)
                .map(User.class::cast);
    }
}

위 구현에서는 Spring Security에서 제공하는 Authentication 객체를 사용하여 현재 사용자를 조회합니다. 여기서 UserDetailsService에서 생성한 사용자 세부 정보를 가져올 수 있습니다.

ReactiveAuditorAware

반응형 인프라를 사용하는 경우 ReactiveAuditorAware<T> SPI 인터페이스를 구현하여 현재 사용자를 인식할 수 있습니다.

예시: Spring Security 기반 ReactiveAuditorAware 구현

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.data.domain.ReactiveAuditorAware;
import reactor.core.publisher.Mono;

public class SpringSecurityAuditorAware implements ReactiveAuditorAware<User> {

    @Override
    public Mono<User> getCurrentAuditor() {
        return ReactiveSecurityContextHolder.getContext()
                .map(SecurityContext::getAuthentication)
                .filter(Authentication::isAuthenticated)
                .map(Authentication::getPrincipal)
                .map(User.class::cast);
    }
}

이 구현은 반응형 Spring Security에서 제공하는 Authentication 객체를 사용하여 현재 사용자를 조회합니다.

감사 기능 일반 구성(General Auditing Configuration)

 Spring Data JPA는 감사 정보를 캡처하는 엔티티 리스너를 제공합니다. 먼저, orm.xml 파일에서 AuditingEntityListener를 등록해야 합니다.

예시 1: orm.xml에서 감사 구성

<persistence-unit-metadata>
    <persistence-unit-defaults>
        <entity-listeners>
            <entity-listener class="org.springframework.data.jpa.domain.support.AuditingEntityListener" />
        </entity-listeners>
    </persistence-unit-defaults>
</persistence-unit-metadata>

또는 특정 엔티티에 대해 @EntityListeners 어노테이션을 사용하여 AuditingEntityListener를 활성화할 수도 있습니다.

예시 2: 특정 엔티티에서 감사 리스너 사용

import javax.persistence.Entity;
import javax.persistence.EntityListeners;

@Entity
@EntityListeners(AuditingEntityListener.class)
public class MyEntity {
    // 엔티티 정의
}

감사 기능은 spring-aspects.jar가 클래스패스에 있어야 합니다. orm.xml 파일을 수정한 후, 다음과 같이 Spring Data JPA 감사 네임스페이스 요소를 추가하여 감사 기능을 활성화할 수 있습니다.

예시 3: XML 구성을 통한 감사 기능 활성화

<jpa:auditing auditor-aware-ref="yourAuditorAwareBean" />

Spring Data JPA 1.5부터는 다음과 같이 구성 클래스를 어노테이션으로 사용하여 감사 기능을 활성화할 수 있습니다.

예시 4: Java 구성을 통한 감사 기능 활성화

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

@Configuration
@EnableJpaAuditing
class Config {

    @Bean
    public AuditorAware<User> auditorProvider() {
        return new SpringSecurityAuditorAware(); // AuditorAware 구현체
    }
}

ApplicationContextAuditorAware 타입의 빈을 노출하면, 감사 인프라가 이를 자동으로 감지하고 도메인 타입에 설정할 현재 사용자를 결정합니다. 만약 여러 구현체가 등록된 경우, @EnableJpaAuditingauditorAwareRef 속성을 통해 사용할 구현체를 명시할 수 있습니다.

 

Spring Data JPA의 감사 기능은 데이터 변경의 원인과 시점을 효과적으로 추적할 수 있는 기능을 제공합니다. 이를 통해 애플리케이션의 데이터 무결성을 보장하고, 감사 로그를 작성하는 데 유용하게 활용할 수 있습니다.

'Spring Boot > Spring Data JPA' 카테고리의 다른 글

Spring Data JPA  (0) 2024.10.24
JPA Query Methods  (0) 2024.10.23
OPTIMISTIC, OPTIMISTIC_FORCE_INCREMENT  (0) 2024.10.22
PESSIMISTIC_READ, PESSIMISTIC_WRITE  (0) 2024.10.22
Locking  (0) 2024.10.22