본문 바로가기
혼자 공부하는 것들/Spring

spring-data-envers로 데이터 변경 이력(히스토리)을 관리해보자!

by applepick 2022. 9. 4.
반응형

Spring Boot + JPA로 상품 주문 프로세스 주제로 사이드 프로젝트를 하고 있었습니다. 이때 상품 주문에 대한 히스토리를 어떻게 관리해야 할지 고민을 했었습니다. 첫 번째 방법으로 직접 주문 히스토리 테이블을 설계하여 상품 주문, 취소 등등... 데이터가 변경될 때 하나하나 직접 테이블에 넣어주는 방식으로 설계하다 보니 정확한 시점에 못 넣는 일이 발생하고 사람이 코드로 직접 넣는 거다 보니 데이터에 적합성도 떨어졌습니다. 또한, 똑같은 코드가 반복해서 들어가는 보일러 플레이트 코드가 생산되는 단점이 있었습니다. 찾아보다가 spring-data-envers라는 데이터 변경을 쉽게 관리할수있도록 도와주는 것이 있다고 하여 학습하여 적용시켰습니다.

https://github.com/hygl/spring-data-envers

 

GitHub - hygl/spring-data-envers: Envers extension of the Spring Data JPA module

Envers extension of the Spring Data JPA module. Contribute to hygl/spring-data-envers development by creating an account on GitHub.

github.com

 

사용방법 

build.gradle dependencies 안에 해당 내용을 추가해줍니다.

dependencies {
   implementation 'org.springframework.data:spring-data-envers'
}

DB connection이 하나일 경우 Application에 아래 코드를 추가해줍니다.

@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)
@SpringBootApplication
public class ShopApplication {

만약 다중 DB connection일 경우 해당 코드를 connection config에 추가해줍니다.

@Configuration
@EnableJpaRepositories(
      repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class, // 설정 추가
      entityManagerFactoryRef = "",
      transactionManagerRef = "",
      basePackages = {
            //repository package 경로
      })

데이터의 변경 이력을 관리하고싶은 테이블에 아래와 같이 @Audited를 설정해줍니다.

@Entity
@Table(name = "orders")
@Audited
@Getter @Setter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Order {

만약 관계맺은 테이블의 변경이력을 관리하고 싶지 않다면 @NotAudited를 적용해주면 됩니다.

아래의 사진을 통해 테이블 생성 방식을 설명해보겠습니다.

위와 같이 기본 주문테이블이 생성되고 

orders_aud라는 테이블을 생성해줍니다. 테이블 생성 명칭을 변경해줄 수 있지만, 기본적으로 _aud라는 테이블로 생성됩니다.

주문 테이블과 주문 이력 테이블의 차이점으로는 이력 테이블에 rev와 revtype이 생긴 것을 확인할 수 있습니다.

rev는 말그대로 revision을 관리하고 revtype은 0(추가),1(수정),2(삭제)로 관리됩니다. 주문 생성을 통해 확인해보겠습니다.

위와 같이 주문을 요청하게 되면

주문 테이블에 정상적으로 주문 데이터가 insert 되는 것을 확인할 수 있습니다.

주문과 동시에 이력 테이블에 revtype으로 0(추가)으로 들어가는 것을 확인할 수 있습니다. 하지만 여기서 주문 취소 시 문제가 있습니다.

제가 설계한 방식에서 주문 취소를 한다면 데이터를 삭제하는 것이 아닌 주문 테이블의 상태를 ORDER -> CANCEL로 변경되게 되고, 주문 테이블의 데이터는 삭제되는 것이 아닙니다. envers에서는 데이터가 삭제되었을 경우만 2(삭제)로 이력 테이블에 들어가게 됩니다. 이렇게 값이 변경될 경우 이력 테이블에는 2(삭제)가 아닌 1(수정)로 들어가게 됩니다.

확인해볼까요?

위와 같이 요청을 보내보겠습니다.

정상적으로 주문 취소가 완료되었습니다.

해당 주문 상태가 CANCEL로 변경된 것을 확인할 수 있습니다.

주문 이력 테이블을 확인해보면

REVTYPE가 1(수정)로 들어가게 됩니다. 물론 이력 테이블에 주문 상태를 같이 저장하여 CANCEL로 판별이 가능하지만, REVTYPE으로 주문이 취소되었는지 판별하지 못합니다. 이 부분은 데이터 상태를 어떻게 바라보냐의 따라 설계 방식을 바꿔야 할 것 같습니다. 이렇게 envers를 적용하여 프레임워크에 데이터 변경 점을 저장하는 것을 위임하여 만들어보았습니다.

반응형

댓글