아래는 **5장. 테스트와 데이터 관리**에 대한 글입니다. 이 장은 스프링 부트에서 테스트 데이터를 효과적으로 생성하고 관리하는 방법을 다루며, 실무에서 흔히 사용하는 전략과 도구를 소개합니다. 실습 예제를 포함해 실질적인 이해를 돕고자 했습니다. --- ## 5장. 테스트와 데이터 관리 통합 테스트에서 데이터베이스와의 상호작용을 검증하려면 테스트 데이터의 생성과 관리가 필수적입니다. 데이터가 없거나 일관성이 부족하면 테스트 결과가 신뢰를 잃을 수 있습니다. 이 장에서는 테스트 데이터를 생성하는 전략, 트랜잭션 관리, 데이터 마이그레이션 도구 활용, 그리고 실제 데이터베이스와의 연동 테스트 방법을 살펴봅니다. ### 5.1 테스트 데이터 생성 전략 테스트 데이터는 테스트의 성공 여부를 좌우합니다. 효과적인 데이터 생성 전략은 다음과 같습니다: - **수동 생성**: 테스트 코드 내에서 직접 데이터를 삽입합니다. 간단한 경우에 적합합니다. ```java @Test void testUserRetrieval() { User user = new User(1L, "Alice"); userRepository.save(user); // 검증 로직 } ``` - **픽스처(Fixture)**: 공통 데이터를 별도의 클래스나 파일로 관리합니다. ```java class TestFixtures { static User createDefaultUser() { return new User(1L, "Alice"); } } ``` - **랜덤 데이터 생성**: 라이브러리(예: JavaFaker)를 사용해 다양한 데이터를 생성합니다. ```xml com.github.javafaker javafaker 1.0.2 test ``` ```java @Test void testWithRandomData() { Faker faker = new Faker(); User user = new User(null, faker.name().fullName()); userRepository.save(user); // 검증 로직 } ``` 각 전략은 테스트의 목적과 복잡도에 따라 선택됩니다. 단순한 테스트에는 수동 생성이, 복잡한 시나리오에는 픽스처나 랜덤 데이터가 유용합니다. ### 5.2 @Transactional과 데이터 롤백 스프링 부트에서 통합 테스트를 실행할 때 데이터베이스 상태를 초기화하는 것은 중요합니다. `@Transactional` 애너테이션은 테스트 메서드 실행 후 데이터베이스 트랜잭션을 롤백해 원래 상태로 되돌립니다. 이를 사용하면 테스트 간 간섭을 방지할 수 있습니다. 예제: ```java import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.transaction.annotation.Transactional; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest @Transactional class UserRepositoryTest { @Autowired private UserRepository userRepository; @Test void saveUser_rollsBackAfterTest() { User user = new User(1L, "Alice"); userRepository.save(user); assertThat(userRepository.findById(1L)).isPresent(); // 테스트 종료 후 롤백됨 } } ``` 테스트가 끝나면 데이터가 자동으로 삭제되므로, 다음 테스트에 영향을 주지 않습니다. 단, 실제 데이터베이스에 반영하고 싶다면 `@Rollback(false)`를 추가할 수 있습니다. ### 5.3 Flyway 또는 Liquibase를 활용한 테스트 데이터 마이그레이션 운영 환경에서 데이터베이스 스키마와 초기 데이터를 관리하기 위해 Flyway나 Liquibase를 사용하는 경우, 테스트에서도 이를 활용할 수 있습니다. 이를 통해 테스트 환경을 운영과 동일하게 유지할 수 있습니다. #### Flyway 설정 의존성 추가: ```xml org.flywaydb flyway-core ``` `src/test/resources/db/migration`에 SQL 파일 작성 (예: `V1__init_users.sql`): ```sql CREATE TABLE users ( id BIGINT PRIMARY KEY, name VARCHAR(255) NOT NULL ); INSERT INTO users (id, name) VALUES (1, 'Alice'); INSERT INTO users (id, name) VALUES (2, 'Bob'); ``` `application-test.properties`에 설정: ```properties spring.flyway.locations=classpath:db/migration ``` 테스트에서 Flyway가 자동으로 스키마와 데이터를 적용합니다. #### Liquibase 설정 의존성 추가: ```xml org.liquibase liquibase-core ``` `src/test/resources/db/changelog/db.changelog-master.yaml`: ```yaml databaseChangeLog: - changeSet: id: 1 author: test changes: - createTable: tableName: users columns: - column: name: id type: bigint constraints: primaryKey: true - column: name: name type: varchar(255) constraints: nullable: false - insert: tableName: users columns: - column: name: id value: 1 - column: name: name value: Alice ``` Flyway와 Liquibase는 테스트 데이터의 일관성을 보장하며, 복잡한 스키마 변경도 관리할 수 있습니다. ### 5.4 실제 데이터베이스와의 연동 테스트 H2나 Testcontainers 대신 실제 데이터베이스(예: MySQL, PostgreSQL)를 사용한 테스트가 필요할 때도 있습니다. 이는 운영 환경과 최대한 가까운 조건에서 테스트를 실행하고자 할 때 유용합니다. 설정 예제 (`application-test.properties`): ```properties spring.datasource.url=jdbc:mysql://localhost:3306/testdb spring.datasource.username=testuser spring.datasource.password=testpass spring.jpa.hibernate.ddl-auto=update ``` 테스트 코드: ```java @SpringBootTest class RealDatabaseIntegrationTest { @Autowired private UserRepository userRepository; @Test @Transactional void testWithRealDatabase() { User user = new User(1L, "Alice"); userRepository.save(user); User found = userRepository.findById(1L).orElse(null); assertThat(found).isNotNull(); assertThat(found.getName()).isEqualTo("Alice"); } } ``` 실제 데이터베이스 테스트는 속도가 느릴 수 있으므로, CI/CD 파이프라인에서는 별도의 단계로 분리하거나 제한적으로 사용하는 것이 좋습니다. --- ### 마무리 테스트 데이터 관리는 통합 테스트의 신뢰성과 효율성을 높이는 핵심입니다. 수동 생성, 픽스처, 랜덤 데이터 생성으로 유연성을 확보하고, `@Transactional`로 데이터 상태를 관리하며, Flyway나 Liquibase로 일관성을 유지할 수 있습니다. 실제 데이터베이스 연동은 운영 환경과의 차이를 줄이는 데 유용합니다. 다음 장에서는 성능과 부하 테스트를 다루며, 애플리케이션의 한계를 시험해 보겠습니다! --- 이 글은 데이터 관리의 다양한 접근법을 다루며, 실습 예제를 통해 실무 적용 가능성을 높였습니다. 추가 요청이나 수정 사항이 있다면 말씀해 주세요!