24.01.15

서린·2024년 1월 15일

혼자개발

목록 보기
18/82

open api 사용방법 찾아보기

webClient
= Spring WebFlux 라이브러리에 속하는 클라이언트
= HTTP 클라이언트(HTTP 프로토콜을 이용하여 서버와 통신하는 것을 의미, 서버에 API 요청을 보내는 주체) 라이브러리

처리속도가 빠르고 비동기 처리방식을 사용하기 때문에 대용량 처리를 할 때 용이하다


  1. dependency 추가
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-webflux'
}
  1. get 예제 코드
package com.webclient.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class WebClientServiceImpl {

    public void get() {
        String code = "myCode";

        // webClient 기본 설정
        WebClient webClient =
                WebClient
                        .builder()
                        .baseUrl("http://localhost:8080")
                        .build();

        // api 요청
        Map<String, Object> response =
                webClient
                        .get()
                        .uri(uriBuilder ->
                                uriBuilder
                                        .path("/api/get")
                                        .queryParam("code", code)
                                        .build())
                        .retrieve()
                        .bodyToMono(Map.class)
                        .block();

        // 결과 확인
        log.info(response.toString());
    }
}

테스트코드

package com.webclient;

import com.webclient.service.WebClientServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class WebClientApplicationTests {

    @Autowired
    private WebClientServiceImpl webClientService;

    @Test
    void get() {
        webClientService.get();
    }
}

이때 console

INFO 18660 --- [    Test worker] c.w.service.WebClientServiceImpl         : {code=myCode, message=Success}

  1. post 예제 코드
package com.webclient.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class WebClientServiceImpl {
    public void post() {
        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("name", "seorin");
        bodyMap.put("age", 123);

        // webClient 기본 설정
        WebClient webClient =
                WebClient
                        .builder()
                        .baseUrl("http://localhost:8080")
                        .build();

        // api 요청
        Map<String, Object> response =
                webClient
                        .post()
                        .uri("/api/post")
                        .bodyValue(bodyMap)
                        .retrieve()
                        .bodyToMono(Map.class)
                        .block();

        // 결과 확인
        log.info(response.toString());
    }
}

테스트코드

package com.webclient;

import com.webclient.service.WebClientServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class WebClientApplicationTests {

    @Autowired
    private WebClientServiceImpl webClientService;

    @Test
    void post() {
        webClientService.post();
    }
}

이때 console

INFO 15788 --- [    Test worker] c.w.service.WebClientServiceImpl         : {name=seorin, message=Success , age=123

  1. default 설정
    webClient로 코드를 작성하다 보면 하나의 메소드 안에 여러 api 요청이 수행 될 수도 있다
    api에 데이터를 담다 보면 api마다 공통적으로 들어가야 하는 header 값이나 cookie등의 값들이 존재 할 수 있고 요청할 때마다 데이터를 담아서 전달하게 된다
    하지만 매번 요청할 때마다 데이터를 담아주는것은 불편한 반복 작업이기에 이를 위한 개선 방법으로 webClient를 처음 생성할 때 default값을 담아 줄 있다
package com.webclient.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class WebClientServiceImpl {
    public void defaultValue() {
        String code = "myCode";

        // webClient 기본 설정
        WebClient webClient =
                WebClient
                        .builder()
                        .baseUrl("http://localhost:8080")
                        **.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                        .defaultCookie("cookie", "cookieValue")**
                        .build();

        // api 요청 - 1
        webClient
                .get()
                .uri(uriBuilder ->
                        uriBuilder
                                .path("/api/get")
                                .queryParam("code", code)
                                .build())
                .retrieve()
                .bodyToMono(Map.class)
                .block();

        // api 요청 - 2
        webClient
                .get()
                .uri(uriBuilder ->
                        uriBuilder
                                .path("/api/get")
                                .queryParam("code", code)
                                .build())
                .retrieve()
                .bodyToMono(Map.class)
                .block();
    }
}

  1. retrieve return
    get, post 요청을 한 뒤에 .retrieve() 가 붙어있는데,
    retrieve는 일반적으로 webClient로 request를 서버에 전달한 뒤 응답값을 추출하기 위해 사용된다

retrieve의 return 값 3가지(response값 변환)

  • toEntity : response 자체를 얻기 위해 사용
  • bodyToMono : response body 데이터를 얻기 위해 사용
  • bodyToFlux : response body 데이터를 stream으로 활용하기 위해 사용
  1. 동기처리 방식
    공식문서에서는 동기처리 방식을 사용하기 위해 webClient에서 block()을 사용한다고 되어있다
  • block()을 사용하면 비동기처리 방식으로 처리되지않고, 한 메소드에 여러 api를 요청 시 순서대로 처리가 진행된다
  • block()을 사용하지 않고 비동기처리 방식으로 코드를 작성하면 Map에 담겨있는 데이터값을 확인 할 수 없다

이런 상황을 위해 webClient에서는 Mono.zip이라는 메소드를 제공한다

package com.webclient.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WebClientServiceImpl {
    public void getMultiple() {
        String code = "myCode";

        // webClient 기본 설정
        WebClient webClient =
                WebClient
                        .builder()
                        .baseUrl("http://localhost:8080")
                        .build();

        // api 요청 - 1
        Mono<Map> responseMono1 =
                webClient
                        .get()
                        .uri(uriBuilder ->
                                uriBuilder
                                        .path("/api/get")
                                        .queryParam("code", code)
                                        .build())
                        .retrieve()
                        .bodyToMono(Map.class);

        // api 요청 - 2
        Mono<Map> responseMono2 =
                webClient
                        .get()
                        .uri(uriBuilder ->
                                uriBuilder
                                        .path("/api/get")
                                        .queryParam("code", code)
                                        .build())
                        .retrieve()
                        .bodyToMono(Map.class);

        // multiple api 요청
        Map<String, Object> response =
                Mono
                        .zip(responseMono1, responseMono2, (response1, response2) -> {
                            Map<String, Object> map = new HashMap<>();
                            map.put("response1", response1);
                            map.put("response2", response2);

                            return map;
                        })
                        .block();

        // 결과 확인
        log.info(response.toString());
    }
}

0개의 댓글