Elasticsearch 활용한 검색서비스 만들기 4편 (Elasticsearch Testcontainers 활용한 테스트)

2025. 3. 20. 01:05·Backend/프로젝트
목차
  1. 1. 테스트 환경에서의 Elasticsearch: Testcontainers 활용하기
  2. 2. Testcontainers란?
  3. 3. Testcontainers를 사용하는 이유
  4. 4. 설정
  5. 4-1 Testcontainers 의존성 추가
  6. 4-2 테스트 컨테이너 설정
  7. 5. 테스트 코드
반응형

1. 테스트 환경에서의 Elasticsearch: Testcontainers 활용하기

최근 검색 서비스를 개발하면서 엘라스틱서치(Elasticsearch)를 활용하고 있었습니다. 기본적인 개발 환경에서는 문제가 없었지만, 테스트를 진행하는 과정에서 몇 가지 불편함이 있었습니다.

 

실제 운영 중인 Elasticsearch를 테스트에 사용해야 한다?
→ 테스트 데이터가 운영 데이터에 영향을 줄 위험이 있음.

테스트를 위한 별도의 Elasticsearch를 도커 환경에서 띄워야 한다?
→ 컨테이너 실행 여부를 확인하고 관리하는 과정이 번거로움.

CI/CD 환경에서 테스트 시 Elasticsearch 인스턴스를 어떻게 관리할 것인가?
→ CI 환경마다 Elasticsearch를 설치하는 것은 비효율적이며, 환경에 따라 테스트 결과가 달라질 수 있음.

 

이러한 문제를 해결하기 위해 테스트컨테이너(Testcontainers) 를 도입하게 되었습니다.

 

 

2. Testcontainers란?

Testcontainers는 통합 테스트를 지원하기 위해 개발된 오픈 소스 Java 라이브러로, 도커 컨테이너를 활용하여 외부 의존성들을 포함한 테스트 환경을 구축하고 관리하는 것을 간편하게 해 줍니다. 이를 통해 애플리케이션의 통합 테스트를 더 쉽고 빠르게 작성하고 실행할 수 있습니다.

 

엘라스틱서치를 사용할 때 테스트컨테이너를 활용하면 실제 운영 환경과 유사한 테스트 환경을 손쉽게 구축할 수 있으며, 테스트 종료 후 컨테이너를 자동으로 정리하여 깨끗한 상태를 유지할 수 있습니다. 

 

3. Testcontainers를 사용하는 이유

그렇다면 테스트컨테이너를 사용하는 이유는 무엇일까요? 그 이유는 다음과 같습니다.

 

1. 테스트 환경을 일관되게 유지

  • 테스트마다 동일한 환경을 보장하며, 운영 환경과 최대한 유사한 조건에서 테스트를 수행할 수 있어 배포 후 발생할 수 있는 문제를 최소화 할 수 있습니다.

 

2. 엘라스틱서치 실행이 필요한 경우에만 실행

  • 로컬에 엘라스틱서치를 직접 설치하지 않아도 됩니다.
  • 도커 컨테이너로 필요한 경우에만 실행하므로, 개발 환경을 깔끔하게 유지할 수 있습니다.

 

3. CI/CD와 연동이 용이

  • CI/CD환경에서 매 테스트시 깨끗한 엘라스틱서치 컨테이너를 실행하여 테스트 신뢰도를 높일 수 있습니다.
  • Elasticsearch 버전이 변경되어도 이미지만 변경하면 되므로 유지보수가 편리합니다.

 

4. 자원 효율성 및 유지보수 용이

  • 테스트가 끝나면 컨테이너가 자동으로 종료되므로, 별도의 정리 과정이 필요하지 않습니다.
  • 로컬에서 직접 Elasticsearch를 실행할 경우 발생할 수 있는 포트 충돌 문제를 방지할 수 있습니다.

 

지금부터 Testcontainers를 활용한 Elasticsearch 테스트 환경 구축하고, 테스트코드를 작성해 실제로 잘 작동되는지 확인해보도록 하겠습니다.

 

 

4. 설정

4-1 Testcontainers 의존성 추가

Spring Boot에서 testcontainers를 사용하기 위해 gradle 의존성을 추가해줍니다.

    testImplementation "org.testcontainers:elasticsearch:1.20.6"
    testImplementation "org.testcontainers:junit-jupiter:1.20.6"

 

 

4-2 테스트 컨테이너 설정

@Testcontainers
@TestConfiguration
@EnableElasticsearchRepositories(basePackageClasses = TicketElasticsearchRepository.class)
public class ElasticSearchTestContainer {

    private static final String ELASTICSEARCH_IMAGE = "docker.elastic.co/elasticsearch/elasticsearch:8.6.0";

    @Container
    private static final ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)
            .withEnv("discovery.type", "single-node")
            .withEnv("xpack.security.enabled", "false")
            .withEnv("xpack.security.http.ssl.enabled", "false")
            .withCommand("sh", "-c", "elasticsearch-plugin install analysis-nori && elasticsearch");

    static {
        container.start();
    }

    @DynamicPropertySource
    static void setElasticsearchProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.elasticsearch.uris", container::getHttpHostAddress);
    }

    @Bean
    public RestClient restClient() {
        return RestClient.builder(HttpHost.create(container.getHttpHostAddress())).build();
    }

    @Bean
    public ElasticsearchClient elasticsearchClient(RestClient restClient) {
        return new ElasticsearchClient(new RestClientTransport(restClient, new JacksonJsonpMapper()));
    }
}
  • @Testcontainers를 사용하여 테스트 컨테이너를 관리합니다.
  • withEnv()를 사용하여 보안 설정을 false로 설정해줬습니다.
  • 저는 Nori 형태소 분석기를 사용중이기 때문에 한글 형태소 분석기(Nori) 설치 커맨드를 추가해줬습니다.
  • @DynamicPropertySource를 활용하여 스프링 속성을 동적으로 등록합니다.
  • RestClient와 ElasticsearchClient를 빈으로 등록하여 스프링 컨텍스트에서 관리할 수 있도록 설정합니다.

이 때 기본으로 사용하던 elasticsearch 설정의 빈과 충돌하지 않도록 기존 Config 파일에 @Profile("!test") 설정을 추가해줬습니다.

(테스트 환경에서는 해당 빈을 사용하지 않음)

 

5. 테스트 코드

테스트 컨테이너를 활용해 실제 통합테스트를 진행합니다.

@SpringBootTest
@Import({ElasticSearchTestContainer.class})
@ActiveProfiles("test")
@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class)
@SuppressWarnings("NonAsciiCharacters")
public class TicketElasticsearchTest {

    @Autowired
    private TicketSearchService ticketSearchService;

    @Autowired
    private TicketElasticsearchRepository elasticsearchRepository;

    @Test
    void 타이틀이_일치하면_티켓을_반환한다() {
        TicketDocument ticket = new TicketDocument(
                1L,
                "모차르트",
                "모차르트의 연주",
                "120분",
                LocalDateTime.now(),
                LocalDateTime.now(),
                "세종문화회관",
                "뮤지컬");
        elasticsearchRepository.save(ticket);

        Page<TicketDocument> result = ticketSearchService.searchTicketsByFilter("모차르트", null, null, null, 0, 10);

        assertThat(result).hasSize(1);
        assertThat(result.getContent().get(0).getTitle()).isEqualTo("모차르트");
        assertThat(result.getContent().get(0).getContent()).isEqualTo("모차르트의 연주");
    }

    @Test
    void 타이틀이_일치하지_않으면_빈페이지를_반환한다() {
        TicketDocument ticket = new TicketDocument(
                1L,
                "리버풀 vs 레알마드리드",
                "축구 경기가",
                "120분",
                LocalDateTime.now(),
                LocalDateTime.now(),
                "수원경기장",
                "스포츠");
        elasticsearchRepository.save(ticket);

        Page<TicketDocument> result = ticketSearchService.searchTicketsByFilter("바르셀로나", null, null, null, 0, 10);

        assertThat(result).isEmpty();
    }
}

 

 

도커 환경에 정상적으로 컨테이너가 띄워진 것을 확인할 수 있습니다.

 

 

테스트를 마치면 해당 컨테이너는 자동으로 종료 및 제거됩니다.

 

 

테스트가 성공적으로 수행된 것을 확인할 수 있습니다.

 

테스트컨테이너를 활용하면 다양한 장점이 있지만, 도커 컨테이너를 실행해야 하므로 테스트 속도가 다소 느려질 수 있다는 단점도 있습니다. 하지만 운영 환경과 유사한 환경에서 테스트할 수 있다는 점에서 충분한 가치가 있다고 생각합니다!!

 

참고

https://testcontainers.com/

 

Testcontainers

Testcontainers is an opensource library for providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.

testcontainers.com

 

반응형

'Backend > 프로젝트' 카테고리의 다른 글

K6 + InfluxDB + Grafana를 활용한 부하테스트 진행하기(docker)  (2) 2025.04.20
Elasticsearch 활용한 검색서비스 만들기 3편(검색어 자동완성 기능 + 검색 고도화하기)  (0) 2025.03.14
Elasticsearch 활용한 검색서비스 만들기 2편(feat. Spring Boot)  (0) 2025.03.12
Elasticsearch 활용한 검색 서비스 만들기 1편 (Docker로 Elasticsearch + Kibana 구축)  (0) 2025.03.10
무중단 배포 적용하기  (1) 2025.01.01
  1. 1. 테스트 환경에서의 Elasticsearch: Testcontainers 활용하기
  2. 2. Testcontainers란?
  3. 3. Testcontainers를 사용하는 이유
  4. 4. 설정
  5. 4-1 Testcontainers 의존성 추가
  6. 4-2 테스트 컨테이너 설정
  7. 5. 테스트 코드
'Backend/프로젝트' 카테고리의 다른 글
  • K6 + InfluxDB + Grafana를 활용한 부하테스트 진행하기(docker)
  • Elasticsearch 활용한 검색서비스 만들기 3편(검색어 자동완성 기능 + 검색 고도화하기)
  • Elasticsearch 활용한 검색서비스 만들기 2편(feat. Spring Boot)
  • Elasticsearch 활용한 검색 서비스 만들기 1편 (Docker로 Elasticsearch + Kibana 구축)
여포개발자
여포개발자
여포개발자
어제보다 오늘 더
여포개발자
전체
오늘
어제
  • 분류 전체보기 (141)
    • Backend (41)
      • 프로젝트 (18)
      • MSA 전환 (10)
      • spring (6)
      • JPA (7)
    • JAVA (11)
    • Kotlin 정리 (11)
    • 알고리즘 (59)
      • 프로그래머스 LV0 (5)
      • 프로그래머스 LV1 (12)
      • 프로그래머스 LV2 (17)
      • 프로그래머스 LV3 (8)
      • 백준 (14)
      • 소프티어 (3)
    • 네트워크 (3)
    • Docker (3)
    • SQL (5)
    • Kafka (6)
    • 일상 (1)
    • .NET (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • MSA
  • #JAVA #프로그래머스
  • JAVA #프로그래머스 #LV0
  • #JAVA #프로그래머스 #LV1 #모두화이팅
  • #프로그래머스
  • HTTP
  • 프로젝트
  • 프로그래머스LV1
  • 모니터링
  • Spring
  • 오블완
  • docker #MySQL
  • #JAVA #프로그래머스 #LV1
  • 자바 #백준
  • 네트워크
  • java
  • docker
  • TroubleShooting #JPA
  • 티스토리챌린지
  • 프로그래머스
  • #JPA #JAVA
  • Kotlin
  • JPA
  • #프로그래머스 #자바
  • Kotiln
  • 백준

최근 댓글

최근 글

반응형
hELLO· Designed By정상우.v4.5.2
여포개발자
Elasticsearch 활용한 검색서비스 만들기 4편 (Elasticsearch Testcontainers 활용한 테스트)
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.