• 티스토리 홈
starryeye
  • 프로필사진
    starryeye
    • 분류 전체보기 (189)
      • C++ (17)
      • Java (24)
      • OOP (5)
      • Spring Reactive Stack (12)
        • Reactive Streams (3)
        • Netty (4)
        • Reactor (1)
        • Webflux (3)
        • DB, Cache 연동 (1)
      • Spring (90)
        • Core (17)
        • MVC (33)
        • Client (2)
        • Security (4)
        • DB, Cache 연동 (33)
      • DataBase (12)
        • RDBMS (2)
        • NoSQL (10)
      • Message Broker (6)
      • Web (4)
      • Network (4)
      • 대규모 시스템 설계 (15)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • Spring 6의 REST Clients 3가지
        2023년 03월 13일
        • starryeye
        • 작성자
        • 2023.03.13.:07

        이번 포스팅에서는 Spring 6 의 REST Clients 3가지를 예제를 통해 알아보겠다.
         
        Spring 공식 문서에 따르면 아래와 같이 소개하고 있다.
        The Spring Framework provides the following choices for making calls to REST endpoints:
        1. RestTemplate - synchronous client with template method API.
        2. WebClient - non-blocking, reactive client w fluent API.
        3. HTTP Interface - annotated interface with generated, dynamic proxy implementation.
         
        하나씩 예제로 다뤄보자..
        예제에서 사용할 외부 API는 아래와 같다.
        https://open.er-api.com/v6/latest 
        -> USD 기준의 다른 통화와의 환율 정보를 조회 한다.
         
         
        1. RestTemplate
        RestTemplate 은 Spring 3.0 버전 부터 존재 했었다.
        현재 Spring 6 버전 기준으로 deprecated 되어있지 않다.(과거에 잠시 deprecated 였으나 바뀜)
        특징
        - 멀티 쓰레드 방식을 지원하여, RestTemplate 객체를 쓰레드간 공유가 가능하다.
        - 동기 방식
        - RestTemplate 생성 시 어떤 HttpClient, ClientHttpRequestFactory 를 사용하여
        생성 할 것인지 선택 할 수 있다.
        (기본 생성자를 사용하면 SimpleClientHttpRequestFactory 가 선택된다.)
         
        Spring은 기본적으로 ClientHttpRequestFactory 로 아래를 제공한다.
        - Apache HttpComponents
        - Netty
        - OkHttp
         
        예를 들어 Apache HttpComponents 를 통해 생성한다면 아래와 같다.

          HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
          factory.setReadTimeout(5000);  // 최대 읽기 시간, ms
          factory.setConnectTimeout(3000); // 최대 연결 시간, ms
          
          HttpClient httpClient = HttpClientBuilder.create()
              .setMaxConnTotal(100) // connection pool, 최대 연결 유지 갯수
              .setMaxConnPerRoute(50) // connection pool, 특정 경로당 최대 연결 유지 갯수
              .build();
          
          factory.setHttpClient(httpClient); // HttpClient Set
          
          RestTemplate restTemplate = new RestTemplate(factory);

        HttpClient 로 Connection Pool 관련 옵션 셋팅이 가능하다.
         
        외부 환율 API 예제 코드

        RestTemplate rt = new RestTemplate();
        
        Map<String, Map<String, Double>> res = rt.getForObject("https://open.er-api.com/v6/latest", Map.class);
        
        
        System.out.println(rest.get("rates").get("KRW"));
        //출력 : 1318.986681

        위와 같이 RestTemplate 로 동기식 통신을 하여 응답을 받을 수 있다.
        (예제에선 HTTP GET Method 를 사용하여 객체로 바인딩하여 리턴되는 getForObject 를 사용했다.)
         
        RestTemplate Method

         
         
        2. WebClient
        Spring 5.0 버전에서 추가된 인터페이스이다.
        특징
        - Non-blocking I/O
        - Reactive Streams back pressure
        - High concurrency with fewer hardware resources
        - Functional-style, fluent API that takes advantage of Java 8 lambdas
        - Synchronous and asynchronous interactions
        - Streaming up to or streaming down from a server
        - Webflux 의존성을 추가해야한다.
         
        더 디테일한 설명은 추후 포스팅 하겠다.
         
        외부 환율 API 예제 코드

        WebClient client = WebClient.create("https://open.er-api.com");
        Map<String, Map<String, Double>> res = client.get()
                .uri("/v6/latest")
                .retrieve()
                .bodyToMono(Map.class)
                .block();
        
        System.out.println(res.get("rates").get("KRW"));
        //출력 : 1318.986681

        retrieve() : 실제 exchange 가 실행된다(서버에 요청). 응답의 Body를 가져온다.
        bodyToMono(Map.class) : 응답의 body 를 Reactor 의 Mono 객체로 바꿈
        Mono : 0 ~ 1 개의 결과를 처리
        Flux : 0 ~ N 개의 결과를 처리
        block() : 현재의 스레드를 block 시킨 상태로.. 요청하겠다는 의미이다.
        -> 이로 인해 RestTemplate 처럼 동기식으로 동작
         
        <참고>
        WebClient 는 뒤에서 별도의 쓰레드로 동작한다. 기본이 Netty Client 가 동작된다.
        WebClient 는 Netty Client 의 worker thread 에서 동작한다.
        block() 은 Netty Client 의 worker thread 에 비동기적으로 요청해놓고
        현재의 쓰레드는 단순 block 상태로 대기하다가 응답을 받아오는 형식이다.
         
        RestTemplate vs WebClient

          Non-blocking 가능 여부 Asynchronous 가능 여부
        RestTemplate N N
        WebClient Y Y

        <참고>
        WebClient 가 나오기 전에는 Asynchronous 를 지원하기 위해
        지금은 Deprecated 된 AsyncRestTemplate 이 있었다..
         
         
        3. Http Interface
        Spring 6 에서 최초로 추가 되었다.
        마치 Spring Data Jpa 의 JpaRepository 를 상속받아 인터페이스 만으로
        repository를 사용할 수 있는 방식과 유사하다.
         
        @HttpExchange 어노테이션이 적용되어 있는 메서드를 가진 자바 인터페이스를
        Http Service 로 만들어준다.
        즉, 해당 인터페이스를 구현은 따로할 필요 없으며 Spring Framework 가
        exchange를 수행할 수 있는 해당 인터페이스를 구현한 프록시를 생성해준다.
         
        바로 환율 예제 코드로 알아보자.

        interface ErApi {
            
            @GetExchange("/v6/latest")
            Map getLatest();
        }
        
        @Bean
        ErApi erApi() {
            
            WebClient client = WebClient.create("https://open.er-api.com");
            
            HttpServiceProxyFactory httpServiceProxyFactory = HttpServiceProxyFactory
                    .builder(WebClientAdapter.forClient(client))
                    .build();
            
            return httpServiceProxyFactory.createClient(ErApi.class);
        }
        
        void Caller(ErApi api) {
            
            Map<String, Map<String, Double>> res = api.getLatest();
            
            System.out.println(res.get("rates").get("KRW"));
            //출력 : 1318.986681
        }

         
        사용하는 입장(Caller)에서 보면 굉장히 직관적이고 추상적이다.
        따라서 확장성이 상당하다고 볼 수 있다. (DIP, OCP 관점)
        (Rest 를 쓰는지.. DB에 접근하는지.. 모르겠고 ~ 받아와 ~)
         
        <참고>
        Client 를 생성해주는 작업도 어노테이션으로 추후 전환 될 가능성이 보인다고 한다.. (토비님..)
        WebClient 를 사용하여 WebFlux 의 의존성이 필요하다.
         
         
        Reference
        https://docs.spring.io/spring-framework/docs/current/reference/html/integration.html#spring-integration
        https://youtu.be/Kb37Q5GCyZs

        'Spring > Client' 카테고리의 다른 글

        Spring Cloud OpenFeign, Synchronization  (0) 2023.06.17
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바