HTTP Client란?
HTTP 클라이언트는 서버와 통신하기 위해 사용되는 라이브러리로, 클라이언트가 HTTP 프로토콜을 사용하여 웹 서버와 통신할 수 있게 해준다.
HTTP 클라이언트는 서버에 요청을 보내고, 응답을 받아오는 역할을 담당하여 웹 기반 서비스의 상호작용을 가능하게 한다. WebClient, FeignClient가 그 중 대표적인 유형이다.
Rest Template란?
가장 전통적이고 보편적인 방법으로 Spring 3.0 에서부터 제공하는 HTTP Client 라이브러리이다.
Blocking / 동기식 방법으로 멀티 스레딩 방식이다.
Blocking란?
요청하고 응답이 올때까지 기다리는 방식으로, 다른 작업이 시작되면 그 작업이 끝날때까지 기다렸다가 자신의 작업을 다시 시작할 수 있다.
한마디로 제어권을 빼앗겼다고 할 수 있다.
Non-Blocking란?
요청하고 다른 일을 하다가 나중에 응답신호가 오면 결과를 읽어 처리하는 방식으로, 다른 작업에 관련없이 자신의 작업을 할 수 있다.
Blocing과는 반대로 제어권을 빼앗기지 않는다.
Synchronous란?
호출된 작업의 순서와 결과에 신경쓰는 것으로, 요청자와 제공자 사이에 계속 Connection이 맺어져 있어야 한다.
Asynchronous란?
반대로 호출된 작업의 순서와 결과에 신경쓰지 않으며, Connection은 끊어지고 서로간에 이벤트를 통해 통신하는 방식이다.
여기까지 읽어보았다면, 무조건 비동기가 좋지 않을까? 하는 의문이 들 수 있다.
결론을 말하자면, 그건 아니다. 비동기는 스레드 간 데이터를 공유해야하기 때문에 간단한 코드의 경우 오히려 오버헤드가 발생하고 성능이 떨어진다.
동기와 비동기의 방식으로 0부터 999999까지의 숫자를 더하는 간단한 작업을 해보자.
Feign Client란?
선언적으로 사용할 수 있는 Client로, Netflix에서 나온 오픈 소스이다. 기존 Rest Template와 달리 인터페이스를 선언함으로써 어노테이션만 달아서 사용이 가능하다.
장점으로는 코드 가독성이 좋고, 에러처리 핸들링이 간편하다. Enable 어노테이션을 붙이면 실행될 때 어노테이션이 있는 애들을 빈에 등록해준다.
예를 들어 리뷰 MS에서 유저 MS에 존재하지 않는 유저에 대한 요청을 보낸다면, 500에러가 발생한다.
유저 MS에서는 유저를 찾을 수 없기 때문에 잘못된 리소스에 대해 404가 발생하지만, 리뷰 MS 입장에서는 요청에 대한 응답을 받지 못하여 결과를 처리할 수 없으므로 500에러가 발생한다.
하지만 이런 상황에서 리뷰 MS는 500이 아닌 404를 반환해야 한다. 이럴 때 RestTemplate은 try-catch를 이용하여 예외를 처리해줘야 한다. Feign은 예외를 핸들링하기 위한 ErrorDecoder를 제공한다.
ErrorDecoder를 구현하면 try-catch 없이 아래와 같이 깔끔하게 다른 MSA의 API를 호출할 수 있다.
Feign Client란?
비동기식 non block RestTemplate을 보완하기 위한 HTTP requests non-blocking/reactive 클라이언트로, Spring 프레임워크의 WebFlux 모둘에 포함되어 있다. Spring 5.0 부터 사용가능하며, 싱글스레드 방식으로 동작된다.
1. 각 요청은 Event Loop내에 Job으로 등록이 된다.
2. Event Loop는 각 Job을 제공자에게 요청한 후, 결과를 기다리지 않고 다른 Job을 처리한다.
3. Event Loop는 제공자로부터 callback으로 응답이 오면, 그 결과를 요청자에게 제공한다.
"5.0부터 RestTemplate은 유지모드로, 사소한 변경 및 버그에 대한 요청만 허용됩니다. 현대적인 API를 제공하고, 비동기 및 스트리밍 시나리오를 지원하는 WebClient 사용을 고려해보세요."
Feign Client는 기본적으로는 동기식이지만, @Async 어노테이션을 붙여 비동기식으로도 사용할 수 있다.
Async하게 동작하기 위해서 Spring의 도움이 필요한데, 만약 Async하게 동작하기를 희망하는 요청이 있다면
그 요청을 처리할 수 있는 Bean을 Spring이 중간에 Proxy 객체로 Wrapping 하여 Async로 동작할 수 있게 도와준다.
하지만 Spring Container에 있는 Bean을 사용하지 않거나 Direct로 접근하게 되면 Spring의 도움을 받을 수 없으므로 Async하게도 동작할 수 없게 된다.
따라서 어노테이션을 붙여도 Async하게 처리되지 않을 수도 있다. 테스트 코드 작성하거나 로그를 찍어서 서브스레드에서 돌아가는지 확인해주어야 한다!
Web Client와 Feign Clinet를 J-meter를 이용하여 직접 성능을 측정해보자.
spring 6.0 부터 등장한 새로운 HTTP Clinet. 아직 나온지 얼마안되지 않아서, 대중적인 방법은 아니다.
동기, 비동기, 블락, 논블락 4개 조합해서 표로 만들어놓은거 좋군요!
좋은 포스트 감사합니다.