๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

ํ”„๋กœ์ ํŠธ/๊ณ ๋ฏผ ์ƒ๋‹ด ํ”Œ๋žซํผ

OpenFeign์— INFO ๋ ˆ๋ฒจ ๋กœ๊ทธ ์ถ”๊ฐ€ํ•˜๊ธฐ (1/2): WireMock์„ ํ™œ์šฉํ•œ ์™ธ๋ถ€ ์„œ๋ฒ„ ๋ชจํ‚น

** ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ํ…Œ์ŠคํŠธ์—์„œ WireMock์„ ํ™œ์šฉํ•˜์—ฌ ์™ธ๋ถ€ ์„œ๋ฒ„๋ฅผ ๋ชจํ‚นํ•˜๋Š” ๊ณผ์ •์„ ์„ค๋ช…ํ•˜๋ฉฐ, ๋‹ค์Œ ๊ธ€์—์„œ๋Š” INFO ๋ ˆ๋ฒจ ๋กœ๊ทธ ์„ค์ • ๋ฐฉ๋ฒ•์„ ๋‹ค๋ฃฐ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ** 

Clova AI์˜ ๋ฐ˜๋ณต์ ์ธ ์‘๋‹ต ์˜ค๋ฅ˜ ๋ฌธ์ œ

๊ณ ๋ฏผ ์ƒ๋‹ด ํ”Œ๋žซํผ ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ๋„ค์ด๋ฒ„ Clova AI์— ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ Clova AI๋กœ๋ถ€ํ„ฐ ์˜ค๋Š” ์‘๋‹ต์ด ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ง€ ์•Š์•„ ๋นˆ๋ฒˆํ•˜๊ฒŒ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค. ์ด์— ๋”ฐ๋ผ, Clova AI ๊ฐ€ ์–ด๋–ค ์‘๋‹ต์„ ์ฃผ๊ณ , ์–ด๋–ค ์˜ค๋ฅ˜๋ฅผ ์œ ๋ฐœํ•˜๋Š”์ง€ ์ •ํ™•ํžˆ ํ™•์ธํ•  ํ•„์š”๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ณผ์ •์—์„œ OpenFeign์˜ ๋กœ๊น… ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•˜๋ ค ํ–ˆ์ง€๋งŒ, ๊ธฐ์กด ๋ฐฉ์‹์œผ๋กœ๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ถˆํŽธํ•จ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

logger-level : FULL ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ด์œ 

1. ์‹ค์ œ ์šด์˜ ์„œ๋ฒ„์—์„œ Feign ๊ด€๋ จ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด docker logs๋ฅผ ์‚ฌ์šฉํ•ด ๋กœ๊ทธ๋ฅผ ์ˆ˜๋™์œผ๋กœ ๊ฒ€์ƒ‰ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

2. OpenFeign ๋กœ๊ทธ ์ถœ๋ ฅ์„ ์œ„ํ•ด ์„œ๋ฒ„์˜ ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ DEBUG๋กœ ์„ค์ •ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

3. ์„œ๋ฒ„์—์„œ logback-spring.xml์„ ์‚ฌ์šฉํ•ด INFO ๋ ˆ๋ฒจ๊ณผ ERROR ๋ ˆ๋ฒจ ๋กœ๊ทธ๋งŒ ๋ณ„๋„ ํด๋”๋กœ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์–ด, DEBUG ๋กœ๊ทธ๋ฅผ ํ™œ์„ฑํ™”ํ•˜๋Š” ๊ฒƒ์ด ๋ถ€์ ํ•ฉํ–ˆ์Šต๋‹ˆ๋‹ค.

 

INFO ๋ ˆ๋ฒจ ๋กœ๊ทธ ์ถœ๋ ฅ์„ ์œ„ํ•œ Feign ์ปค์Šคํ„ฐ๋งˆ์ด์ง• ๊ณ„ํš

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด OpenFeign ๋กœ๊ทธ๋ฅผ INFO ๋ ˆ๋ฒจ์—์„œ๋„ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๋„๋ก ์ปค์Šคํ„ฐ๋งˆ์ด์ง•์„ ๊ณ„ํšํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ์‹ค์ œ Clova AI ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ด๋ฉฐ ์ž‘์—…ํ•  ๊ฒฝ์šฐ ๋น„์šฉ์ด ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ Clova AI ์„œ๋ฒ„๋ฅผ ๋ชจํ‚นํ•˜๊ณ , @FeignClient๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•˜๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

 

1. WireMock์„ ํ™œ์šฉํ•ด Clova AI ์„œ๋ฒ„๋ฅผ ๋ชจํ‚น

2. INFO ๋ ˆ๋ฒจ ๋กœ๊ทธ ์„ค์ • ํ›„, WireMock์„ ํ˜ธ์ถœํ•˜์—ฌ @FeignClient ํ˜ธ์ถœ ์‹œ ๋กœ๊ทธ๊ฐ€ INFO ๋ ˆ๋ฒจ์—์„œ๋„ ์ถœ๋ ฅ๋˜๋Š”์ง€ ํ™•์ธ

 

WireMock vs MockRestServiceServer

OpenFeign์„ ์‚ฌ์šฉํ•˜์—ฌ ์™ธ๋ถ€ ์„œ๋ฒ„๋ฅผ ๋ชจํ‚น(Mock)ํ•˜๋ ค๋ฉด ์ž์ฃผ ๋“ฑ์žฅํ•˜๋Š” ๋„๊ตฌ ์ค‘ ํ•˜๋‚˜๊ฐ€ WireMock์ž…๋‹ˆ๋‹ค.

ํ•œํŽธ, ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” RestTemplate์„ ์‚ฌ์šฉํ•˜์—ฌ ์™ธ๋ถ€ ์„œ๋ฒ„๋ฅผ ํ˜ธ์ถœํ•œ ๊ฒฝํ—˜์ด ์žˆ์—ˆ๊ณ , ์ด๋ฅผ ํ…Œ์ŠคํŠธํ•  ๋•Œ MockRestServiceServer๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝํ—˜์—์„œ ์ถœ๋ฐœํ•ด WireMock๊ณผ MockRestServiceServer์˜ ์ฐจ์ด๋ฅผ ์•Œ์•„๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

 

- MockRestServiceServer

MockRestServiceServer์˜ Javadoc์— ๋”ฐ๋ฅด๋ฉด, ์ด ๋„๊ตฌ๋Š” RestTemplate์„ ํ†ตํ•ด ์ˆ˜ํ–‰๋  ์˜ˆ์ƒ ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ์„ค์ •ํ•˜๋ฉฐ, ์‹ค์ œ ์„œ๋ฒ„ ์—†์ด๋„ ํ…Œ์ŠคํŠธ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, HTTP ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ ๋„ RestTemplate ์š”์ฒญ์„ ๋ชจ์˜(Mock)๋กœ ์„ค์ •ํ•˜๊ณ , ์ด์— ๋Œ€ํ•œ ์‘๋‹ต์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

MockRestServiceServer ์˜ Javadoc ์ผ๋ถ€

 

- WireMock

๋ฐ˜๋ฉด, WireMock์€ ์‹ค์ œ ์›น ์„œ๋น„์Šค์™€ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” HTTP ์„œ๋ฒ„๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. WireMock์€ ํ…Œ์ŠคํŠธ ์‹œ ๋ณ„๋„์˜ ํฌํŠธ๋ฅผ ์ง€์ •ํ•ด ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํฌํŠธ๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ๊ฐ’์ธ 8080 ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. (๋งŒ์•ฝ, ์ง€์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด 8080ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋‹ˆ, ๋ถ€ํŠธ์˜ ๊ธฐ๋ณธ ํฌํŠธ์™€ ์ถฉ๋Œ๋‚˜์ง€ ์•Š๋„๋ก ๋ฐ”๊พธ๋Š” ๊ฒƒ์ด ์ข‹์•„๋ณด์ž…๋‹ˆ๋‹ค.) ๊ทธ๋ž˜์„œ, WireMock ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์‹ค์ œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ๊ณผ ์œ ์‚ฌํ•œ ๋™์ž‘์„ ํ…Œ์ŠคํŠธํ•  ๋•Œ ์žฅ์ ์ด ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

- ์ •๋ฆฌ

MockRestServiceServer

  • RestTemplate์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์ ํ•ฉ.
  • ์‹ค์ œ HTTP ์„œ๋ฒ„ ์—†์ด ์š”์ฒญ๊ณผ ์‘๋‹ต์„ ๋ชจ์˜ํ•˜์—ฌ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰.

 WireMock

  • OpenFeign ๋ฐ ์‹ค์ œ HTTP ์„œ๋ฒ„์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒฝ์šฐ ์ ํ•ฉ.
  • HTTP ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์‹ค์ œ ๋„คํŠธ์›Œํฌ ์š”์ฒญ๊ณผ ์œ ์‚ฌํ•œ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰.

 

๋ณธ๋ก  : ํ…Œ์ŠคํŠธ์—์„œ Clova AI(์™ธ๋ถ€) ์„œ๋ฒ„ ๋ชจํ‚น ๊ณผ์ •

๋ณธ๋ก ์œผ๋กœ ๋Œ์•„์™€, WireMock ์„ ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก @OpenFeign ๊ณผ Test Code ๋ฅผ ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

- ์˜์กด์„ฑ ์ถ”๊ฐ€

Spring ์—์„œ ์ œ๊ณตํ•˜๋Š” openfeign ๊ณผ wiremock ์„ ์‚ฌ์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

WireMock์˜ ๋ฒ„์ „ ๊ด€๋ฆฌ๋Š” Spring Boot์˜ dependency-management์—๊ฒŒ ๋งก๊ธฐ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

testImplementation 'org.springframework.cloud:spring-cloud-contract-wiremock'

 

- OpenFeign ํด๋ผ์ด์–ธํŠธ ์ค€๋น„

@FeignClient๋ฅผ ์„ค์ •ํ•˜์—ฌ ์™ธ๋ถ€ ์„œ๋ฒ„ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. URL์€ ์™ธ๋ถ€ ์„ค์ • ํŒŒ์ผ(.yml)์—์„œ ์ฝ์–ด์˜ค๋„๋ก ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.
ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ๋Š” ์‹ค์ œ Clova AI ์„œ๋ฒ„๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด์ง€ ์•Š๋„๋ก, ํ…Œ์ŠคํŠธ ์‹œ์ ์— URL์„ ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

@FeignClient(name = "clova-service", url = "${feign.clova.url}")
public interface ClovaFeignClient {

    @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, 
                 produces = MediaType.APPLICATION_JSON_VALUE)
    ClovaResponseDto sendToClova(
            @RequestHeader("X-NCP-CLOVASTUDIO-API-KEY") String apiKey,
            @RequestHeader("X-NCP-APIGW-API-KEY") String apigwKey,
            @RequestHeader("X-NCP-CLOVASTUDIO-REQUEST-ID") String requestId,
            @RequestBody ClovaRequestDto clovaRequestDto
    );
}

 

- ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ

@ActiveProfiles("test")
@SpringBootTest   // ํ†ฐ์บฃ๊ณผ ๊ฐ™์€ HTTP ์„œ๋ฒ„๋ฅผ ๋„์šธ ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ํŒ๋‹จํ•ด์„œ, Mock ์†์„ฑ์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
@TestPropertySource(properties = "feign.clova.url=http://localhost:${wiremock.server.port}")
@AutoConfigureWireMock(port = 0)
class ClovaFeignClientTest {

    @Autowired
    private ClovaService clovaService;

    @DisplayName("WireMock์„ ์‚ฌ์šฉํ•˜์—ฌ @FeignClient ํ˜ธ์ถœ ์‹œ logger-Level : full์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.")
    @Test
    void test() {
        // given, #import static com.github.tomakehurst.wiremock.client.WireMock.*;
        stubFor(post("/")
                .willReturn(aResponse()
                        .withStatus(200)));

        // when
        ClovaResponseDto result = clovaService.send("message");

        // then
        assertThat(result).isNull();
    }
}

 

@ActiveProfiles("test")

  • ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์— ๋งž๋Š” test.yml ์„ค์ • ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

@TestPropertySource

  • @FeignClient์˜ URL ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ http://localhost:${wiremock.server.port}๋กœ ์ฃผ์ž…ํ•˜๊ธฐ ์œ„ํ•œ ์„ค์ •์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ${wiremock.server.port}๋Š” ๋ณ„๋„๋กœ .yml ์— ์ž‘์„ฑํ•˜์ง€ ์•Š์•„๋„, WireMock์ด ์‹คํ–‰๋  ๋•Œ ๋ชจํ‚น๋œ ์„œ๋ฒ„์˜ ํฌํŠธ๊ฐ€ ์ž๋™์œผ๋กœ "wiremock.server.port" ์†์„ฑ์— ๋ฐ”์ธ๋”ฉ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ…Œ์ŠคํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ์—์„œ ํ•ด๋‹น ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@AutoConfigureWireMock(port=0)

  • WireMock ์„œ๋ฒ„๋ฅผ ๋žœ๋ค ํฌํŠธ์—์„œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • Spring Application Context์˜ ์ผ๋ถ€๋กœ WireMock ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•˜๋ ค๋Š” ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์— ๋Œ€ํ•œ ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค.

AutoConfigureWireMock ์˜ Javadoc

 

ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜๋“ค์„ ์™œ ์‚ฌ์šฉํ–ˆ๋Š”์ง€๋Š” Spring Cloud Contract WireMock Docs๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

 

ํ•ด๋‹น ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•˜์˜€๊ณ , OpenFeign์˜ logger-level: FULL ์„ค์ •์œผ๋กœ ์ธํ•ด DEBUG ๋ ˆ๋ฒจ์˜ ์ž์„ธํ•œ ๋กœ๊ทธ๊ฐ€ ์ถœ๋ ฅ๋จ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

* feign log ๋ฅผ debug ๋กœ ์ถœ๋ ฅํ•˜๋Š” ๋ฐฉ๋ฒ• -> feign logging Docs

2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] ---> POST http://localhost:12410 HTTP/1.1
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] Accept: application/json
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] Content-Length: 5571
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] Content-Type: application/json
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] 
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] 5571์— ํ•ด๋‹นํ•˜๋Š” body
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] ---> END HTTP (5571-byte body)

...(์ค‘๋žต)

2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] <--- HTTP/1.1 200 OK (196ms)
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] matched-stub-id: f1b4d2e2-83eb-4138-9554-4fa7934d42d8
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] transfer-encoding: chunked
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] vary: Accept-Encoding, User-Agent
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] 
2024-12-21 DEBUG 16948 --- [ClovaFeignClient#sendToClova] <--- END HTTP (0-byte body)

 

์ •๋ฆฌ

์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ WireMock์„ ์‚ฌ์šฉํ•˜์—ฌ Clova AI(์™ธ๋ถ€) ์„œ๋ฒ„๋ฅผ ๋ชจํ‚นํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋‹ค๋ค˜์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด Feign ํด๋ผ์ด์–ธํŠธ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ํ…Œ์ŠคํŠธํ•˜๊ณ , logger-level: FULL ์„ค์ •์œผ๋กœ DEBUG ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๊ธ€์—์„œ๋Š” INFO ๋ ˆ๋ฒจ์—์„œ๋„ Feign ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜๋„๋ก ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ถœ์ฒ˜

- Spring Cloud Contract WireMock Docs

- Baeldung ์˜ Introduction WireMock

- ์šฐ์•„ํ•œ๊ธฐ์ˆ ๋ธ”๋กœ๊ทธ : ์•ผ, ๋„ˆ๋‘ WireMock ์œผ๋กœ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์–ด

https://devnm.tistory.com/34 

 

์ถ”๊ฐ€๋กœ, WireMock์„ ํ™œ์šฉํ•˜๋ฉฐ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ณผ์ •์—์„œ ๋‹ค์–‘ํ•œ ํ…Œ์ŠคํŠธ ์–ด๋…ธํ…Œ์ด์…˜์„ ์ ‘ํ•˜๊ฒŒ ๋˜์—ˆ๊ณ , ์ด๋ฅผ ์ •๋ฆฌํ•˜์—ฌ ๊ณต์œ ํ•˜๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.


@TestInstance

@TestInstance๋Š” JUnit 5์—์„œ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ๋ผ์ดํ”„์‚ฌ์ดํด์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
๋‹ค์Œ ๋‘ ๊ฐ€์ง€ ์˜ต์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

PER_METHOD (DEFAULT)

  • ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑ
  • ๊ฐ ํ…Œ์ŠคํŠธ๋Š” ๋…๋ฆฝ์ ์œผ๋กœ ์‹คํ–‰
  • ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์— ์ ํ•ฉ

PER_CLASS

  • ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋‹น ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋งŒ ์ƒ์„ฑ
  • ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ๊ฐ€ ํด๋ž˜์Šค์˜ ์ƒํƒœ๋ฅผ ๊ณต์œ ํ•ด์•ผ ํ•  ๋•Œ.
  • ํ…Œ์ŠคํŠธ๊ฐ€ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉฐ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ
  • @BeforeAll๊ณผ @AfterAll์„ ์‚ฌ์šฉํ•  ๋•Œ static์„ ๋ถ™์ด์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

์ฐธ๊ณ  : @TestInstance Annotation in JUnit 5

 

@SpringBootTest

WebEnvironment.MOCK (DEFAULT)

  • ๋ชจ์˜(Mock) ์„œ๋ธ”๋ฆฟ ํ™˜๊ฒฝ์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…์ŠคํŠธ๋ฅผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
  • ์‹ค์ œ HTTP ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š๊ณ , ์š”์ฒญ๊ณผ ์‘๋‹ต์€ MockMvc์™€ ๊ฐ™์€ ๋„๊ตฌ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  • ์ปจํŠธ๋กค๋Ÿฌ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ๋˜๋Š” ํŠน์ • ์›น ๊ณ„์ธต ๋™์ž‘๋งŒ ํ…Œ์ŠคํŠธํ•  ๋•Œ ์ ํ•ฉ.

WebEnvironment.RANDOM_PORT

  • ์‹ค์ œ HTTP ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜์ง€๋งŒ, ์ถฉ๋Œ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๋žœ๋ค ํฌํŠธ์—์„œ ๊ตฌ๋™ํ•ฉ๋‹ˆ๋‹ค.
  • Spring Boot์˜ ๋‚ด์žฅ ์„œ๋ฒ„(Tomcat, Jetty ๋“ฑ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • TestRestTemplate์™€ ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•ด HTTP ์š”์ฒญ ๋ฐ ์‘๋‹ต์„ ํ…Œ์ŠคํŠธ.
  • Mock๋ณด๋‹ค ์‹คํ–‰ ์‹œ๊ฐ„์ด ๊ธธ ์ˆ˜ ์žˆ์Œ.

WebEnvironment.DEFINED_PORT

  • ์‹ค์ œ HTTP ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๋ฉฐ, application.properties ๋˜๋Š” application.yml์— ์ •์˜๋œ ๊ณ ์ • ํฌํŠธ์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ์™ธ๋ถ€ ํด๋ผ์ด์–ธํŠธ๋‚˜ ์„œ๋น„์Šค๊ฐ€ ํŠน์ • ํฌํŠธ๋กœ ํ…Œ์ŠคํŠธ ์„œ๋ฒ„์™€ ์ƒํ˜ธ์ž‘์šฉํ•ด์•ผ ํ•  ๋•Œ.
  • ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ ํฌํŠธ ์ถฉ๋Œ ๊ฐ€๋Šฅ์„ฑ ์กด์žฌ.

WebEnvironment.NONE

  • ์›น ํ™˜๊ฒฝ์„ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ณ , ์ˆœ์ˆ˜ํ•œ ApplicationContext๋งŒ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
  • ๋‚ด์žฅ HTTP ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜์ง€ ์•Š์œผ๋ฉฐ, ์›น ๊ด€๋ จ ๋นˆ(@Controller, @RestController ๋“ฑ)์€ ์ƒ์„ฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  • Spring์˜ ์›น ๊ณ„์ธต ๋นˆ์€ ํ…Œ์ŠคํŠธ ์ปจํ…์ŠคํŠธ์— ํฌํ•จ๋˜์ง€ ์•Š์Œ.

์ฐธ๊ณ  : Difference between webEnvironment = RANDOM_PORT and webEnvironment = MOCK