🔸 기존에 많이 사용한 RestTemplate과 WebClient의 가장 큰 차이점은 RestTemplate는 Blocking이고, WebClient는 Non-Blocking 방식이라는 것
- Blocking은 호출되는 함수가 호출하는 함수에게 제어권을 넘기지 않고 대기하게 함
- Non-Blocking은 제어권을 바로 넘김
현재 RestTemplate는 Spring 5.0 이후부터 Deprecated되었고, WebClient는 앞서 설명하였듯 블로킹되지 않아 성능이 더 좋기 때문에 WebClient를 사용하는 것이 권장됨
: Spring에서 제공하는 HTTP Client로 REST API를 호출하기 위한 함수를 제공하는 클래스
💡 동기
동기는 데이터 요청의 결과를 기다림 👉 요청과 결과가 한 자리에서 동시에 일어남
ex)
카페에 방문해 커피를 주문할 때, 직원이 한 명 뿐이라면
→ 직원에게 커피를 주문
→ 주문을 받은 직원은 즉시 커피를 제조
→ 제조된 커피 수령
이러한 프로세스가 진행되고 이처럼 요청과 결과가 동시에 일어나는 것을 동기라고 함
💡 비동기
비동기는 데이터를 요청한 후 결과를 기다리지 않음 👉 요청과 결과가 동시에 일어나지 않음
ex)
카페에 방문해 커피를 주문할 때, 주문을 받는 직원과 커피를 내리는 직원이 있다면
→ 주문을 받는 직원에게 커피를 주문
→ 주문을 받은 직원은 커피를 내리는 직원에게 주문 전달
→ 이후 새로운 주문을 받음
이처럼 요청과 결과가 동시에 일어나지 않는 것을 비동기라고 합니다.
- getForObject() : 주어진 URL 주소로 HTTP GET 메소드로 객체 결과를 반환받음
- getForEntity() : 주어진 URL 주소로 HTTP GET 메소드로 ResponseEntity로 결과를 반환받음
- postForLocation() : POST 요청을 보내고 결과로 헤더에 저장된 URI를 결과로 반환받음
- postForObject() : POST 요청을 보내고 객체로 결과를 반환받음
- postForEntity() : POST 요청을 보내고 결과로 ResponseEntity로 반환받음
- delete() : 주어진 URL 주소로 HTTP DELETE 메소드를 실행
- headForHeaders() : 헤더의 모든 정보를 얻을 수 있으며 HTTP HEAD 메소드를 사용
- put() : 주어진 URL 주소로 HTTP PUT 메소드를 실행
- patchForObject() : 주어진 URL 주소로 HTTP PATCH 메소드를 실행
- optionsForAllow() : 주어진 URL 주소에서 지원하는 HTTP 메소드를 조회
- exchange() : HTTP 헤더를 새로 만들 수 있고 어떤 HTTP 메소드도 사용 가능
- execute() : Request/Response 콜백을 수정할 수 있음
🔹 getForObject → 응답 body만 있으면 될 때
public void getBeerObject() {
RestTemplate restTemplate = new RestTemplate();
// 랜덤으로 세계 맥주에 대한 정보를 주는 url
String url = "https://random-data-api.com/api/v2/beers";
BeerGetDto responseBody = restTemplate.getForObject(url, BeerGetDto.class);
log.info(responseBody.toString());
}
👉 getForObject는 응답을 지정한 타입으로 변환해서 받아줌
🔹 getForEntity → 응답을 좀더 상세하게 받을 때 사용
public void getBeerEntity() {
RestTemplate restTemplate = new RestTemplate();
// 랜덤으로 세계 맥주에 대한 정보를 주는 url
String url = "https://random-data-api.com/api/v2/beers";
ResponseEntity<BeerGetDto> response =
restTemplate.getForEntity(url, BeerGetDto.class);
log.info(response.getStatusCode().toString());
log.info(response.getHeaders().toString());
}
🔹 postForObject → Request Body를 DTO의 형태로 포함해서 요청
public void postBeerObject() {
RestTemplate restTemplate = new RestTemplate();
// 랜덤으로 세계 맥주에 대한 정보를 주는 url
String url = "https://random-data-api.com/api/v2/beers";
BeerPostDto dto = new BeerPostDto();
dto.setName("Stella Artois");
dto.setCc(2000L);
dto.setAlcohol(5.0);
// POST 요청 보낼 때 requestBody를 같이 전달
MessageDto responseBody = restTemplate.postForObject(
url, // 요청 URL
dto, // request Body
MessageDto.class // 응답 해석 타입
);
log.info(responseBody.toString());
}
🔺 응답 Body가 없을 경우, Void 클래스를 활용
url = "http://localhost:8081/give-me-beer-204";
ResponseEntity<Void> response = restTemplate.postForEntity(
url,
dto,
Void.class // void 의 클래스 (객체화 불가)
);
log.info(response.getStatusCode().toString());
🔹 exchange() 메소드
restTemplate.exchange(
url,
HttpMethod.Post,
new HttpEntity<>(dto),
Void.class
);
: Blocking 동기방식인 RestTemplate와 달리 Non-Blocking 방식
→ 현재는 Spring에서 WebClient의 사용을 강력히 권고함
implementation 'org.springframework.boot:spring-boot-starter-webflux'
@Service
@Slf4j
public class BeerClientService {
public void getBeer() {
// WebClient는 Builder 패턴 처럼 사용
WebClient webClient = WebClient.builder().build();
String url = "https://random-data-api.com/api/v2/beers";
// 어떤 HTTP 메소드로 요청 보낼지를 get(), post() 메소드 등으로 결정
// 만일 다른 메소드를 쓰고 싶다면, method()
String response = webClient.get() // webClient.method(HttpMethod.GET)
.uri(url) // 요청 경로 설정
.header("x-test", "header") // 요청 헤더 추가
// body도 메소드에 따라 추가
.retrieve() // 여기 전까지가 요청을 정의 한 부분
// 여기부터 정의하는건 응답을 어떻게 처리할 것인지
.bodyToMono(String.class) // 응답이 한번 돌아오고, 응답의 body를 String으로 해석
.block(); // 동기식으로 처리
log.info(response);
}
}
public void postBeer() {
WebClient webClient = WebClient.builder().build();
String url = "https://random-data-api.com/api/v2/beers";
BeerPostDto dto = new BeerPostDto();
// POST 요청
MessageDto responseBody = webClient.post()
.uri(url) // url 정의
.bodyValue(dto) // requestBody 정의
.retrieve() // 응답 정의 시작
.bodyTOMono(MessageDto.class) // 응답 데이터 정의
.block(); // 동기식 처리
log.info(responseBody.toString());
}
잘읽고갑니다