[Spring] 서버 간 통신

mingsso·2023년 10월 29일
0

SpringBoot

목록 보기
11/11

최근에 개발되는 서비스는 마이크로서비스 아키텍처(MSA)를 주로 채택하고 있음
MSA는 말 그대로 애플리케이션이 가지고 있는 기능이 하나의 비즈니스 범위만 가지는 형태

따라서 각 애플리케이션은 자신이 가진 기능을 API로 외부에 노출하고, 다른 서버가 그러한 API를 호출해서 사용할 수 있게 구성되므로 각 서버가 다른 서버의 클라이언트가 되는 경우도 많음

1️⃣ RestTemplate

스프링에서 HTTP 통신 기능을 손쉽게 사용할 수 있도록 설계된 템플릿으로, 이 템플릿을 이용하면 RESTful 원칙을 따르는 서비스를 편리하게 만들 수 있음

RestTemplate은 기본적으로 동기 방식으로 처리되며, 비동기 방식으로 사용하고 싶을 경우 AsyncRestTemplate를 사용하면 됨

다만, RestTemplate는 현업에서는 많이 쓰이나 지원 중단(deprecated)된 상태임

RestTemplate의 특징

  • HTTP 프로토콜에 맞는 여러 메소드를 제공함
  • RESTful 형식을 갖춘 템플릿임
  • HTTP 요청 후 JSON, XML, 문자열 등의 다양한 형식으로 응답을 받을 수 있음
  • 블로킹 I/O 기반의 동기 방식을 사용함
  • 다른 API를 호출할 때 HTTP 헤더에 다양한 값을 설정할 수 있음

RestTemplate의 동작 원리

  1. 애플리케이션에서 RestTemplate를 선언하고, URI와 HTTP 메소드, Body 등을 설정함
  1. RestTemplate에서 HttpMessageConverter를 통해 RequestEntity를 요청 메시지로 변환함
  1. RestTemplate에서는 변환된 요청 메시지를 ClientHttpRequestFactory를 통해 ClientHttpRequest로 가져온 후, 외부 API로 요청을 보냄
  1. 외부에서 요청에 대한 응답을 받으면, RestTemplate는 ResponseErrorHandler로 오류를 확인하고 오류가 있다면 ClientHttpResponse에서 응답 데이터를 처리함
  1. 받은 응답 객체가 정상적이라면, 다시 한번 HttpMessageConverter를 거쳐 자바 객체로 변환해서 애플리케이션으로 반환함

RestTemplate 사용하기

일반적으로 RestTemplate는 별도의 유틸리티 클래스로 생성하거나, 서비스 또는 비즈니스 계층에 구현됨

// 서버2의 컨트롤러 
@RestController
@RequestMapping("/api/v1/crud-api")
public class CrudController {

    @GetMapping
    public String getName() {
        return "Flature";
    }

    @GetMapping(value = "/{variable}")
    public String getVariable(@PathVariable String variable) {
        return variable;
    }
}

// 서버1의 GET 형식 RestTemplate
@Service
public class RestTemplateService {

    public String getName(){
    	// UriComponentsBuilder는 여러 파라미터를 연결해서 URI 형식으로 만들어줌 
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/v1/crud-api")
                .encode()
                .build()
                .toUri();

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);

        return responseEntity.getBody();
    }
    
    public String getNameWithPathVariable(){
        URI uri = UriComponentsBuilder
                .fromUriString("http://localhost:9090")
                .path("/api/v1/crud-api/{name}")
                .encode()
                .build()
                .expand("Flature") // 복수의 값을 넣어야 할 경우 ,를 추가하여 구분
                .toUri();
        
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(uri, String.class);
        
        return responseEntity.getBody();
    }
}
// 서버1의 컨트롤러 
@RestController
@RequestMapping("/rest-template")
public class RestTemplateController {

    private final RestTemplateService restTemplateService;

    public RestTemplateController(RestTemplateService restTemplateService){
        this.restTemplateService = restTemplateService;
    }

    @GetMapping
    public String getName(){
        return restTemplateService.getName();
    }

    @GetMapping("/path-variable")
    public String getNameWithPathVariable(){
        return restTemplateService.getNameWithPathVariable();
    }
}



2️⃣ WebClient

WebClient의 특징

  • 논블로킹 I/O를 지원함
  • 리액티브 스트림의 백 프레셔를 지원함
  • 적은 하드웨어 리소스로 동시성을 지원함
  • 함수형 API를 지원함
  • 동기, 비동기 상호작용을 지원함
  • 스트리밍을 지원함






참고자료

도서 '스프링부트 핵심 가이드'

profile
🐥👩‍💻💰

0개의 댓글