Spring WebClient

์ด๋ฏธ์—ฐยท2024๋…„ 8์›” 1์ผ

[spring]

๋ชฉ๋ก ๋ณด๊ธฐ
2/7

๐Ÿ”Ž Spring WebClient

WebClient๋Š” Spring 5์—์„œ ๋„์ž…๋œ ๋น„๋™๊ธฐ์ ์ด๊ณ  ๋…ผ๋ธ”๋กœํ‚น ๋ฐฉ์‹์˜ HTTP ํด๋ผ์ด์–ธํŠธ์ž…๋‹ˆ๋‹ค. RestTemplate์˜ ํ˜„๋Œ€์ ์ธ ๋Œ€์•ˆ์œผ๋กœ, ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ์ฃผ์š” ํŠน์ง•:

๋น„๋™๊ธฐ ๋ฐ ๋™๊ธฐ ์ž‘์—… ๋ชจ๋‘ ์ง€์›
ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์Šคํƒ€์ผ์˜ API
์ŠคํŠธ๋ฆฌ๋ฐ ์ง€์›
ํšจ์œจ์ ์ธ ๋ฆฌ์†Œ์Šค ๊ด€๋ฆฌ

๐Ÿ’ก WebClient ์„ค์ •ํ•˜๊ธฐ

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

pom.xml์— ๋‹ค์Œ ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:

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

2.2. WebClient Bean ์ƒ์„ฑ

@Configuration
public class WebClientConfig {
    
    @Bean
    public WebClient webClient() {
        return WebClient.builder()
            .baseUrl("https://api.example.com")
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .build();
    }
}

๐Ÿ’ก WebClient ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•

3.1. GET ์š”์ฒญ

Mono<User> userMono = webClient.get()
    .uri("/users/{id}", 1)
    .retrieve()
    .bodyToMono(User.class);

userMono.subscribe(user -> System.out.println(user.getName()));

3.2. POST ์š”์ฒญ

User newUser = new User("John Doe", "john@example.com");
Mono<User> createdUserMono = webClient.post()
    .uri("/users")
    .body(Mono.just(newUser), User.class)
    .retrieve()
    .bodyToMono(User.class);

createdUserMono.subscribe(user -> System.out.println("Created user ID: " + user.getId()));
  

3.3. PUT ์š”์ฒญ

User updatedUser = new User("John Updated", "john@example.com");
Mono<Void> updateMono = webClient.put()
    .uri("/users/{id}", 1)
    .body(Mono.just(updatedUser), User.class)
    .retrieve()
    .bodyToMono(Void.class);

updateMono.subscribe(null, error -> System.err.println("Error updating user: " + error.getMessage()));
  

3.4. DELETE ์š”์ฒญ

Mono<Void> deleteMono = webClient.delete()
    .uri("/users/{id}", 1)
    .retrieve()
    .bodyToMono(Void.class);

deleteMono.subscribe(null, error -> System.err.println("Error deleting user: " + error.getMessage()));

๐Ÿ’ก WebClient ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ

4.1. ํ—ค๋” ์„ค์ •

Mono<User> userMono = webClient.get()
    .uri("/users/{id}", 1)
    .header("Authorization", "Bearer " + token)
    .retrieve()
    .bodyToMono(User.class);
  

4.2. ์—๋Ÿฌ ์ฒ˜๋ฆฌ

Mono<User> userMono = webClient.get()
    .uri("/users/{id}", 1)
    .retrieve()
    .onStatus(HttpStatus::is4xxClientError, response -> 
        Mono.error(new RuntimeException("API not found")))
    .onStatus(HttpStatus::is5xxServerError, response -> 
        Mono.error(new RuntimeException("Server error")))
    .bodyToMono(User.class);

userMono.subscribe(
    user -> System.out.println(user.getName()),
    error -> System.err.println("Error: " + error.getMessage())
);

4.3. ์‘๋‹ต ์ŠคํŠธ๋ฆฌ๋ฐ

Flux<User> userFlux = webClient.get()
    .uri("/users")
    .retrieve()
    .bodyToFlux(User.class);

userFlux.subscribe(
    user -> System.out.println(user.getName()),
    error -> System.err.println("Error: " + error.getMessage()),
    () -> System.out.println("Completed")
);

4.4. ํƒ€์ž„์•„์›ƒ ์„ค์ •

Mono<User> userMono = webClient.get()
    .uri("/users/{id}", 1)
    .retrieve()
    .bodyToMono(User.class)
    .timeout(Duration.ofSeconds(5));

๐Ÿ’ก WebClient vs RestTemplate

WebClient์˜ ์žฅ์ :

๋น„๋™๊ธฐ ๋ฐ ๋…ผ๋ธ”๋กœํ‚น ๋ฐฉ์‹์œผ๋กœ ํšจ์œจ์ ์ธ ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ
ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์Šคํƒ€์ผ๋กœ ๊ฐ€๋…์„ฑ ํ–ฅ์ƒ
์ŠคํŠธ๋ฆฌ๋ฐ ์ง€์›์œผ๋กœ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์— ์œ ๋ฆฌ
๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ๊ณผ์˜ ํ†ตํ•ฉ์ด ์šฉ์ด

RestTemplate์˜ ์žฅ์ :

๋™๊ธฐ์‹ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ์ต์ˆ™ํ•œ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋” ์ง๊ด€์ 
๋ ˆ๊ฑฐ์‹œ ์‹œ์Šคํ…œ๊ณผ์˜ ํ†ตํ•ฉ์ด ์‰ฌ์›€

๐Ÿ’ก ์‹ค์ œ ์‚ฌ์šฉ ์˜ˆ์ œ

GitHub API๋ฅผ ์‚ฌ์šฉํ•œ ์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ:

WebClient client = WebClient.create("https://api.github.com");

Mono<GitHubUser> userMono = client.get()
    .uri("/users/{username}", "octocat")
    .retrieve()
    .bodyToMono(GitHubUser.class);

userMono.subscribe(
    user -> System.out.println("Name: " + user.getName() + ", Followers: " + user.getFollowers()),
    error -> System.err.println("Error: " + error.getMessage())
);

๐Ÿ’ก ์„ฑ๋Šฅ ์ตœ์ ํ™” ํŒ

์ปค๋„ฅ์…˜ ํ’€๋ง: HttpClient ์„ค์ •์„ ํ†ตํ•ด ์ปค๋„ฅ์…˜ ํ’€ ์‚ฌ์šฉ
์žฌ์‹œ๋„ ๋ฉ”์ปค๋‹ˆ์ฆ˜ ๊ตฌํ˜„: Retry ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ
์บ์‹ฑ: Spring์˜ ์บ์‹ฑ ์ถ”์ƒํ™” ํ™œ์šฉ

1๊ฐœ์˜ ๋Œ“๊ธ€

comment-user-thumbnail
2024๋…„ 8์›” 2์ผ

์˜ˆ์ œ๋ฅผ ํ™œ์šฉํ•ด์„œ TIL์„ ์ž˜ ์ž‘์„ฑํ•ด์ฃผ์…จ๋„ค์š” ๐Ÿ‘๐Ÿป

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ