밤빵's 개발일지
[TIL]20241219 RestTemplate과 WebClient 본문
프로젝트에서 외부 API 데이터를 가져오는 기능을 구현하면서 RestTemplate과 WebClient 두 가지 방법을 비교해 보았다.현재 WebClient를 사용하고 있지만, "만약 원래 사용하던 방식처럼 RestTemplate으로 구현했다면 어땠을까?"라는 궁금증이 생겨서 비교해 보았고, 두 방법의 차이를 이해하면서 또 하나 배웠다. 이번에 리액티브 프로그래밍이라는 개념도 제대로 접하게 되어서, 간단히 정리하기로했다.
1. 리액티브 프로그래밍
리액티브 프로그래밍은 데이터를 비동기적이고 이벤트 기반으로 처리하는 프로그래밍 방식이다.
비동기적 처리
프로그램이 어떤 작업을 수행하는 동안 다른 작업이 병렬적으로 진행될 수 있도록 한다.
이벤트 기반
데이터의 변경이나 외부 이벤트가 발생했을 때 자동으로 반응하도록 설계된다.
리액티브 프로그래밍을 적용하면 애플리케이션이 데이터를 기다리지 않고, 데이터가 준비되었을 때 처리하는 방식으로 동작한다.
2. Mono와 Flux
WebClient에서 사용하는 Mono와 Flux는 리액티브 프로그래밍의 대표적인 데이터 타입이다.
Mono
0개 또는 1개의 데이터를 비동기적으로 처리할 때 사용된다.
ex.특정 사용자의 정보를 가져오는 API 호출
Mono<String> monoExample = Mono.just("Hello, Mono!");
monoExample.subscribe(System.out::println);
[출력: Hello, Mono!]
Flux
0개 이상의 데이터를 스트림형태로 비동기 처리할 때 사용된다.
ex.여러 사용자 목록을 가져오는 API 호출
Flux<String> fluxExample = Flux.just("User1", "User2", "User3");
fluxExample.subscribe(System.out::println);
[출력:
User1
User2
User3]
3. RestTemplate과 WebClient
RestTemplate
동기 방식의 HTTP 클라이언트로, 요청-응답이 완료될 때까지 호출한 스레드가 대기 상태가 된다.
사용법이 간단하지만, 비동기적 처리가 요구되는 환경에서는 성능상의 한계가 있다.
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject("https://api.pubg.com/shards/kakao/seasons", String.class);
System.out.println(response);
WebClient
Spring WebFlux에서 제공하는 비동기 방식의 HTTP 클라이언트로, 리액티브 프로그래밍을 지원한다.
Mono와 Flux를 반환하며 대규모 트래픽 처리에 적합하다.
WebClient webClient = WebClient.create("https://api.pubg.com");
String response = webClient.get()
.uri("/shards/kakao/seasons")
.retrieve()
.bodyToMono(String.class)
.block(); // [동기 방식으로 결과 기다림]
System.out.println(response);
4. SeasonsService에서의 구현 차이
SeasonsService는 PUBG API로부터 시즌 데이터를 가져오는 기능을 담당한다. 현재는 WebClient를 사용하고 있지만, 만약 RestTemplate을 사용했다면 구현 방식과 동작 방식이 어떻게 달라졌을지 비교해 보았다.
RestTemplate으로 구현
@Service
public class SeasonsService {
private final RestTemplate restTemplate;
public SeasonsService() {
this.restTemplate = new RestTemplate();
}
public SeasonsDto getSeasonData(String seasonId) {
String url = "https://api.pubg.com/seasons/" + seasonId;
return restTemplate.getForObject(url, SeasonsDto.class);
}
}
장점: 간단하고 직관적이다.
단점: 다량의 요청을 처리할 때 스레드 리소스가 부족해질 가능성이 있다.
RestTemplate은 요청과 응답을 동기적으로 처리한다. 호출한 스레드는 응답이 올 때까지 대기 상태가 된다.
현재 WebClient로 구현
@Service
public class SeasonsService {
private final WebClient webClient;
public SeasonsService() {
this.webClient = WebClient.create("https://api.pubg.com");
}
public SeasonsDto getSeasonData(String seasonId) {
return webClient.get()
.uri("/seasons/" + seasonId)
.retrieve()
.bodyToMono(SeasonsDto.class)
.block();
}
}
장점: 비동기와 동기 방식을 모두 선택할 수 있다.
단점: 리액티브 프로그래밍에 익숙하지 않으면 초기에 이해하기 복잡하다.
WebClient는 기본적으로 비동기 처리를 지원하고, 리소스를 효율적으로 사용할 수 있다. 하지만 block() 메서드를 사용해 동기적으로 처리하면 RestTemplate과 비슷한 방식으로 동작한다.
5. 고민과 배운 점
고민
비동기와 리액티브 프로그래밍이 아직 익숙하지 않아 WebClient를 동기 방식으로만 사용하고 있다. 비동기의 장점을 살리지 못한다는 점이 아쉽다. 앞으로 Mono와 Flux를 활용해 비동기 처리를 구현해보고 싶다.
배운 점
RestTemplate은 간단한 프로젝트에서 유용하지만, 대규모 트래픽을 처리하거나 리소스 최적화가 필요한 프로젝트에서는 WebClient가 더 적합하다는 것을 알게됐다.
이번 비교를 통해 RestTemplate과 WebClient의 차이뿐만 아니라, 리액티브 프로그래밍의 기본 개념을 이해하게 되었다. 다른 방법으로 각각 구현하면서 100개씩 호출하는 테스트를 진행했는데 뭘 잘못한건지 테스트 결과가 이상하게 나와서 아쉽다. 차이가 명확히 났다면 이해가 더 쉬웠을텐데... 아직 리액티브 프로그래밍이 어렵게 느껴지지만, 개념을 익혀가면서 애플리케이션의 성능을 최적화할 수 있는 방법을 고민하게 되었다. 초보 개발자로서 성장의 과정이 계속되고 있구나 체감하고 있다.
'개발Article' 카테고리의 다른 글
[TIL]20241218 멱등성 처리 설계 초안 (0) | 2024.12.18 |
---|---|
[TIL]20241217 Observability (2) | 2024.12.17 |
[TIL]20241216 벨루가 추천 시스템 (1) | 2024.12.16 |
[TIL]20241215 DDD 이해하기 (0) | 2024.12.15 |
[TIL]20241214 내 시각에서 이해한 클러스터링 개념 (0) | 2024.12.14 |