Test


title: 2026-03-07 author: 강병호 (이름) date: 2026-03-07 (날짜) category: TIL/강병호/2026/03 (파일 경로 : TIL/{이름}/{연}/{월}) layout: post (자유) —

Spring Boot 환경에서의 테스트 격리 전략

테스트 격리(Test Isolation)는 각 테스트가 독립적으로 실행됨을 보장하는 원칙입니다. 특정 테스트의 실행 결과가 다른 테스트의 성공 여부에 영향을 주지 않아야 하며, 이를 통해 비결정적(Non-deterministic) 테스트의 발생을 방지할 수 있습니다.

비결정적 테스트는 동일한 코드임에도 실행 환경이나 순서에 따라 결과가 달라지는 현상을 의미하며, 이는 테스트 결과에 대한 신뢰도를 떨어뜨리고 유지보수 비용을 증가시킵니다. 특히 데이터베이스와 같은 공유 자원을 사용하는 Spring 통합 테스트에서는 적절한 격리 전략이 필수적입니다.


1. @DirtiesContext 활용

Spring의 테스트 컨텍스트 캐싱 기능을 강제로 종료하고, 테스트 메서드나 클래스 종료 후 새로운 컨텍스트를 재생성하는 방식입니다.

  • 장점: 매번 새로운 컨텍스트를 로드하므로 완벽한 격리가 보장됩니다.
  • 단점: 컨텍스트 로딩은 비용이 매우 큰 작업이므로, 테스트 전체 실행 시간이 급격히 늘어나 성능 저하를 초래합니다.

2. @Sql을 이용한 데이터 초기화

테스트 실행 전후에 특정 SQL 스크립트(예: TRUNCATE)를 실행하여 데이터베이스 상태를 초기화하는 방식입니다.

  • 장점: 공유 데이터베이스를 사용하더라도 테이블을 비움으로써 데이터 간섭을 방지할 수 있습니다.
  • 단점: 테이블 구조가 변경되거나 새로운 테이블이 추가될 때마다 초기화 스크립트를 수동으로 수정해야 하므로 유지보수 번거로움이 있습니다.

3. @Transactional을 통한 롤백

테스트 메서드에 @Transactional을 선언하여 테스트 완료 후 데이터를 자동으로 롤백하는 방식입니다. 가장 흔히 사용되지만, 다음과 같은 주의사항이 존재합니다.

주요 제약 사항 및 부작용

  • 거짓 음성(False Negative)의 위험: 실제 운영 환경에서는 LazyInitializationException이 발생할 코드임에도, 테스트 환경에서는 트랜잭션이 유지되어 테스트가 통과될 수 있습니다.
  • WebEnvironment 설정 이슈: RANDOM_PORTDEFINED_PORT를 사용하여 별도 스레드에서 서블릿 컨테이너가 구동될 경우, HTTP 클라이언트의 요청과 테스트 메서드의 트랜잭션 스레드가 서로 달라 롤백이 적용되지 않습니다.
  • 전파 레벨(Propagation): 프로덕션 코드에서 REQUIRES_NEW를 사용할 경우, 테스트 트랜잭션과 별개의 트랜잭션이 생성되므로 해당 변경분은 롤백되지 않습니다.
  • 비동기 작업: @Async 등을 통해 별도의 스레드에서 실행되는 작업은 테스트 스레드의 트랜잭션 범위에 포함되지 않습니다.

요약 및 비교

전략 격리 수준 성능 유지보수 편의성
@DirtiesContext 매우 높음 낮음 보통
@Sql (Truncate) 높음 보통 낮음
@Transactional 보통 높음 높음

테스트 격리는 신뢰할 수 있는 테스트 환경을 구축하기 위한 핵심 요소입니다. 프로젝트의 규모와 테스트의 특성에 맞춰 적절한 격리 방식을 선택하되, 특히 @Transactional 사용 시 발생할 수 있는 부작용을 명확히 인지하고 대응해야 합니다.

results matching ""

    No results matching ""