· 오늘 공부한 것

JPA심화 4일 차

  • JPA와 오해 풀기
  • TestContainer로 배포환경과 동일한 DB에서 테스트하기
  • Transactional 심화

 

 

· 공부한 내용, 궁금한 내용, 부족한 내용

쿼리 최적화가 안 되는 경우 아래 3가지를 확인해야 한다.

  1. 먼저 해당 함수나 클래스가 Transaction 안에 포함되고 있는지 봐야 합니다.
    1. **@Transactional** 으로 함께 감싸져 있어야만 쿼리 최적화가 동작합니다.
    2. Transaction으로 포함되어있지 않으면 repository 메서드 내부에서만 Transcation 이 최적화됩니다.
    3. Transaction Propagation (전파) 전략 체크해봐야 합니다. (심화)
  2. 두 번째로, 해당 엔티티의 ID 식별자 생성전략을@GeneratedValue(strategy = GenerationType.IDENTITY)로 사용한 건 아닌지 확인해봐야 합니다.
    1. **GenerationType.IDENTITY** 로 키필드가 설정되어 있으면 데이터베이스에 실제로 저장을 해야 유일한 식별자를 구할 수 있으므로 Insert 쿼리가 즉시 데이터베이스에 전달됩니다.
    2. GenerationType.SEQUENCE 설정하길 추천드립니다. 이렇게 하면 DB에 select nextval('thread_seq') 쿼리만 날아갑니다.
    3. GenerationType.AUTO 설정해서 DB에서 선호하는 방식으로 자동적용시켜 줄 수도 있습니다.
  3. 마지막으로, orphanRemoval() 영속성 전이에 의해 자식의 삭제작업이 이루어지는 건 아닌지 확인해봐야 합니다.
    1. 이런 경우 1차 캐시 최적화가 아닌 삭제쿼리가 쓰기 지연 저장소에 저장되어 동작하게 되므로 후처리로 발생하게 됩니다.

Test 클래스에 애너테이션(@)이 많아서 헷갈리는 경우

1. Spring 전체 빈을 사용해야 하는 Spring 통합 테스트

@SpringBootTest   
// SpringApplication 띄울때의 빈들을 모두 생성해줍니다.
@Transactional    
// 테스트 메소드들이 모두 트랜잭션에 포함되어 최적화 되도록 합니다. 
// 테스트 대상 함수의 실행환경에서는 Transaction이 안걸려 있을 수 있으니 실무에 사용시 주의
@Rollback(value = false) // 테스트 데이터가 롤백되지 않고 실제 DB에 반영되도록 합니다.

2. JPA 관련 빈 만 사용하는 JPA 슬라이스 테스트

@DataJpaTest      
// SpringDataJpa 테스트에 필요한 빈들만 생성해줍니다.
@Transactional    
// 테스트 메소드들이 모두 트랜잭션에 포함되어 최적화 되도록 합니다. 
// 테스트 대상 함수의 실행환경에서는 Transaction이 안걸려 있을 수 있으니 실무에 사용시 주의
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)  
// 테스트 용 DB를 따로 설정하지 않고 main 환경 DB를 그대로 사용하도록 합니다.
@Import(JPAConfiguration.class) 
// JPAQueryFactory와 같이 테스트시 필요한 빈들을 정의해놓은 Configuration 설정합니다.
@Rollback(value = false)
// 테스트 데이터가 롤백되지 않고 실제 DB에 반영되도록 합니다.

위에 두 개중에 슬라이스 테스트를 추천한다.

  • 실제 구동되는 애플리케이션의 설정, 모든 Bean을 로드하기 때문에 시간이 오래 걸리고 무겁다.
  • 테스트 단위가 크기 때문에 디버깅이 어려운 편이다.
  • 결과적으로 웹을 실행시키지 않고 테스트 코드를 통해 빠른 피드백을 받을 수 있다는 장점이 희석된다.

 

TestContainer로 배포환경과 동일한 DB에서 테스트하기 (실습)

  • 단위 테스트
    • 각 계층(클래스) 별로 테스트 케이스 작성
  • 통합 테스트
    • 실행될 때마다 랜덤 하게 변경되는 시나리오를 만들고 그에 따른 데이터를 미리 생성(Docker 환경의 데이터베이스)
    • 모든 엔드포인트에 대해서 테스트
    • 사전에 데이터를 미리 만들어둔 것을 통해서, 결과를 예측하고 검증할 수 있음
  • 단위테스트는 Pull Request에서 검증하는 용도(CI)
  • 통합테스트는 정기 배포 당일 생성한 브랜치에 대해서 검증하고 검증이 완료된다면 자동으로 배포하는 프로세스(CD)

Propagation (전파 전략)

@RunWith(SpringRunner.class)
@SpringBootTest
public class TransTest {

    @Autowired
    Parent parent;


    @Test
    @Transactional(propagation = Propagation.NOT_SUPPORTED) // 트랜잭션 생성 방지
    public void transactionalPropagationTest() {
        parent.parentMethod(); // 부모 메서드 실행
    }

}

@Component
public class Parent {

    @Autowired
    Child child;


    @Transactional
    public void parentMethod() {
        System.out.println("Parent");
        child.calledMethod();
    }
}

@Component
public class Child {

    @Transactional(propagation = ?) // <- 여기에 하나씩 넣어보세요.
    public void calledMethod() {
        System.out.println("Child");
    }
}

1. PROPAGATION_REQUIRED ( JpaTransactionManager Default )

  • 부모 트랜잭션이 존재할 경우
    • 부모 트랜잭션에 참여한다.
  • 부모 트랜잭션이 없을 경우
    • 새 트랜잭션을 시작한다.

일반적으로 사용되는 트랜잭션의 전파유형이다.

즉, 어떻게 해서든 (상속받서든, 내가 새로 만들든) Transaction을 시작하는 전파 유형

2. PROPAGATION_SUPPORTS

  • 부모 트랜잭션이 존재할 경우
    • 부모 트랜잭션에 참여한다.
  • 부모 트랜잭션이 없을 경우
    • non-transactional 하게 동작한다.

부모 따라서 전파되는 유형

3. PROPAGATION_MANDATORY

  • 부모 트랜잭션이 존재할 경우
    • 부모 트랜잭션에 참여한다.
  • 부모 트랜잭션이 없을 경우
    • Exception이 발생한다.

트랜잭션에 참여하도록 강제하는 유형

4. PROPAGATION_REQUIRES_NEW

  • 부모 트랜잭션 유무에 상관없이
    • 새 트랜잭션을 시작한다.
  • 부모 트랜잭션이 존재할 경우
    • 부모 트랜잭션을 중지시킨다.

무조건 새 트랜잭션을 생성하도록 강제하는 유형

5. PROPAGATION_NOT_SUPPORTED

  • 부모 트랜잭션 유무에 상관없이
    • non-transactional 하게 동작한다.
  • 부모 트랜잭션이 존재할 경우
    • 부모 트랜잭션을 중지시킨다.

6. PROPAGATION_NEVER

  • 부모 트랜잭션이 존재할 경우 Exception이 발생한다.

항상 non-transactional 하게 동작하는 유형

 

 

 

 

 

 

· 오늘 서칭 한 자료

강의 자료 대체

https://github.com/thesun4sky/jpa/tree/day-4

 

GitHub - thesun4sky/jpa

Contribute to thesun4sky/jpa development by creating an account on GitHub.

github.com

 

· 느낀 점

- JPA를 가지고 DB를 다룰 때 실행문에서 어떤 쿼리가 나가는지 항상 확인을 했었는데 내가 적은 코드가 어떤 쿼리를 발생하냐를 자주 보았다.

- 예상하지 못한 쿼리가 나간 경험이 있었는데 이번에 그 의문을 해결할 수 있었다.

- 그리고 역시나 @(애너테이션)은 알고 사용하면 좋기는 하지만 역시 많아서 헷갈리기도 하다. 그렇기 때문에 자주 사용해 보고 직접 모르는 부분을 찾아서 정리해야 할 거 같다.

반응형

'Today I Learned' 카테고리의 다른 글

2023-12-27 TIL 업무 관리 시스템 팀프로젝트(2)  (0) 2023.12.28
2023-12-26 TIL 업무 관리 시스템 팀프로젝트(1)  (0) 2023.12.26
2023-12-11(BA클럽 KPT 회고)  (0) 2023.12.11
2023-12-07 TIL  (0) 2023.12.07
2023-12-06 TIL  (1) 2023.12.06

+ Recent posts