๊ณต๋ถ€/TIL

[20250217] webclient ๊ธฐ๋ณธ ์˜ˆ์‹œ๋กœ ์‚ฌ์šฉ๋ฐฉ๋ฒ• ์•Œ์•„๋ณด๊ธฐ!

dvlpsy๐ŸŒผ 2025. 2. 17. 17:53
๋ฐ˜์‘ํ˜•

WebClient ์™„์ „ ์ •๋ณต ๊ฐ€์ด๋“œ: ์ดˆ๋ณด์ž๋„ ์ดํ•ดํ•˜๋Š” ํ•ต์‹ฌ ๊ฐœ๋…๊ณผ ํ™œ์šฉ๋ฒ•

WebClient๋Š” Spring 5๋ถ€ํ„ฐ ์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€๋œ ๋น„๋™๊ธฐ ๋ฐฉ์‹์˜ HTTP ํด๋ผ์ด์–ธํŠธ์ž…๋‹ˆ๋‹ค. ๊ธฐ์กด์˜ RestTemplate์— ๋น„ํ•ด Non-Blocking ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜์—ฌ ๋†’์€ ์„ฑ๋Šฅ์„ ์ œ๊ณตํ•˜๋ฉฐ, ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์Šคํƒ€์ผ์„ ์ง€์›ํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ๊ฐ„๊ฒฐํ•˜๊ณ  ์œ ์—ฐํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

1. WebClient๋ž€?

WebClient๋Š” HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. RestTemplate์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ GET, POST, PUT, DELETE ๋“ฑ ๋‹ค์–‘ํ•œ HTTP ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•˜๋ฉฐ, ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ํ•˜์—ฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

2. WebClient ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

 

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

WebClient๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Spring WebFlux ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Maven ํ”„๋กœ์ ํŠธ์˜ ๊ฒฝ์šฐ pom.xml ํŒŒ์ผ์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

XML
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

 

Gradle ํ”„๋กœ์ ํŠธ์˜ ๊ฒฝ์šฐ build.gradle ํŒŒ์ผ์— ๋‹ค์Œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.  

Gradle
implementation 'org.springframework.boot:spring-boot-starter-webflux'

 

2.2. WebClient ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ

WebClient๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋จผ์ € WebClient ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด WebClient.create() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Java
WebClient webClient = WebClient.create();

 

2.3. HTTP ์š”์ฒญ ๋ณด๋‚ด๊ธฐ

WebClient ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ ํ›„์—๋Š” ๋‹ค์–‘ํ•œ HTTP ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ GET ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

Java
Mono<String> response = webClient.get()
        .uri("https://example.com/api/data")
        .retrieve()
        .bodyToMono(String.class);

์œ„ ์ฝ”๋“œ๋Š” https://example.com/api/data URL์— GET ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ , ์‘๋‹ต ๊ฒฐ๊ณผ๋ฅผ String ํƒ€์ž…์œผ๋กœ Mono์— ๋‹ด์•„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. Mono๋Š” ๋น„๋™๊ธฐ ์ŠคํŠธ๋ฆผ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ์ฒด๋กœ, ์‘๋‹ต์ด ๋„์ฐฉํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

2.4. ์‘๋‹ต ์ฒ˜๋ฆฌ

Mono ๋˜๋Š” Flux ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‘๋‹ต ๊ฒฐ๊ณผ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ Mono ๊ฐ์ฒด์—์„œ ์‘๋‹ต ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

Java
response.subscribe(data -> {
    System.out.println("์‘๋‹ต ๊ฒฐ๊ณผ: " + data);
});

์œ„ ์ฝ”๋“œ๋Š” Mono ๊ฐ์ฒด์— subscribe() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‘๋‹ต ๊ฒฐ๊ณผ๋ฅผ ๊ตฌ๋…ํ•˜๊ณ , ์‘๋‹ต์ด ๋„์ฐฉํ•˜๋ฉด data ๋ณ€์ˆ˜์— ๋‹ด์•„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

3. WebClient ๊ธฐ๋ณธ ์˜ˆ์ œ

๋‹ค์Œ์€ WebClient๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GET, POST ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‘๋‹ต์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

Java
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

public class WebClientExample {

    public static void main(String[] args) {
        WebClient webClient = WebClient.create();

        // GET ์š”์ฒญ
        Mono<String> getResponse = webClient.get()
                .uri("https://jsonplaceholder.typicode.com/todos/1")
                .retrieve()
                .bodyToMono(String.class);

        getResponse.subscribe(data -> System.out.println("GET ์‘๋‹ต: " + data));

        // POST ์š”์ฒญ
        Mono<String> postResponse = webClient.post()
                .uri("https://jsonplaceholder.typicode.com/todos")
                .bodyValue("{\"title\": \"foo\", \"body\": \"bar\", \"userId\": 1}")
                .retrieve()
                .bodyToMono(String.class);

        postResponse.subscribe(data -> System.out.println("POST ์‘๋‹ต: " + data));
    }
}

์œ„ ์ฝ”๋“œ๋Š” https://jsonplaceholder.typicode.com API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ GET ์š”์ฒญ๊ณผ POST ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ , ๊ฐ๊ฐ์˜ ์‘๋‹ต ๊ฒฐ๊ณผ๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

 

4. WebClient ์ถ”๊ฐ€ ๊ธฐ๋Šฅ

WebClient๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  • ํ—ค๋” ์„ค์ •: ์š”์ฒญ์— ํ•„์š”ํ•œ ํ—ค๋”๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ฟ ํ‚ค ์„ค์ •: ์š”์ฒญ์— ํ•„์š”ํ•œ ์ฟ ํ‚ค๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํƒ€์ž„์•„์›ƒ ์„ค์ •: ์š”์ฒญ์— ๋Œ€ํ•œ ํƒ€์ž„์•„์›ƒ ์‹œ๊ฐ„์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์—๋Ÿฌ ์ฒ˜๋ฆฌ: ์‘๋‹ต ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.