일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- jacoco
- useMutation
- useQuery
- 클래스
- 프리코스
- 블로그 병행
- 계층별 구조
- 메서드명
- BalancedTree
- DeleteAll
- 카카오 2차 코딩테스트
- InnoDB 버퍼 풀
- 백기선 스터디
- 주간회고
- 기능별 구조
- 어댑티브 해시 인덱스
- B+TREE
- 우테코
- 멀티쓰레드 프로그래밍
- SQL 실행순서
- 도커
- db
- Blue-Green
- mysql
- 회고
- 월간회고
- java
- Jenkins
- ci/cd
- N+1
- Today
- Total
Haneul's Blog
[Spring Reactive] WebClient 간단한 사용법(Feat: 카카오 2차 코딩테스트) 본문
어쩌다 보니 카카오 코딩 테스트 1차를 합격하고 2차를 준비해야 하는 상황이 오게 되었습니다.
2차 테스트는 카카오에서 API를 제공하고 그 값을 호출해야 하는 상황이 있어서 API를 호출하는 로직이 필요합니다.
Python이나 javascript 같은 경우에는 이 방법이 매우 쉽지만 Java의 경우에는 HttpConnection으로 처리를 해줘야 하기 때문에 시간이 걸리고 조금 번거롭다는 단점이 생깁니다.
Python이나 javascript를 사용하지 못하는 것은 아니지만 주력 언어인 Java를 통해서 시험을 보고 싶었기 때문에 관련해서 잘 찾아보니 카카오 2차 코딩 테스트에서 Spring Webflux의 WebClient를 사용하여 API통신을 해도 된다는 블로그 포스팅을 보게 되어 이를 사용하면 되겠다 싶었습니다.
2차 테스트를 보기 전에 간단하게 WebClient를 통해서 GET, POST, PUT, DELETE 메서드를 사용하는 방법에 대해 정리하면 좋을 것 같아 글을 쓰게 되었습니다.
시작하기에 앞서 필요한 gradle 설정
plugins {
id 'com.google.osdetector' version '1.7.0'
}
dependencies {
// m1맥북일 경우 native library를 로드하지 못해서 오류가 발생하는데
// 위의 플러그인 설정과 해당 설정을 추가해주면 해결된다.
if (osdetector.arch.equals("aarch_64")) {
implementation "io.netty:netty-all"
}
// 이건 필수
implementation 'org.springframework.boot:spring-boot-starter-webflux'
}
WebClient란 무엇이고 왜 사용을 할까?
WebClient란 HTTP Request를 간편하게 수행할 수 있게 해주는 Client라고 할 수 있습니다.
스레드, 동시성 문제들을 다룰 필요가 없이 비동기 로직의 선언적인 형태로 사용이 가능하다는 장점이 있고,
완벽한 논 블러킹 형태이며, 스트리밍을 지원해줍니다.
GET 사용법
public class API{
WebClient webClient = WebClient.create();
public static final String BASE_URL = "요청하고 싶은 주소의 BaseURL";
public ResponseDto getApi(String authKey) {
String endpoint = "BaseURL의 엔드포인트";
Mono<ResponseDto> response = webClient
.get()
.uri(BASE_URL + endpoint)
.accept(MediaType.APPLICATION_JSON) // application/json 형식만을 받아들인다.
.headers(httpHeaders -> httpHeaders.set(AUTHORIZATION, authKey)) // 헤더 세팅
.retrieve()
.bodyToMono(ResponseDto.class);
return response.block();
}
}
POST 사용법
public class API{
WebClient webClient = WebClient.create();
public static final String BASE_URL = "요청하고 싶은 주소의 BaseURL";
public ResponseDto postApi(String authKey) {
String endpoint = "BaseURL의 엔드포인트";
Mono<ResponseDto> response = webClient
.post()
.uri(BASE_URL + endpoint)
.accept(MediaType.APPLICATION_JSON) // application/json 형식만을 받아들인다.
.body(BodyInserters.fromFormData("데이터", 데이터))
// .bodyValue(JSONObject 타입을 넣을 수 있다.)
.headers(httpHeaders -> httpHeaders.set(AUTHORIZATION, authKey)) // 헤더 세팅
.retrieve()
.bodyToMono(ResponseDto.class);
return response.block();
}
}
PUT 사용법
public class API{
WebClient webClient = WebClient.create();
public static final String BASE_URL = "요청하고 싶은 주소의 BaseURL";
public ResponseDto putApi(String authKey) {
String endpoint = "BaseURL의 엔드포인트";
Mono<ResponseDto> response = webClient
.put()
.uri(BASE_URL + endpoint)
.accept(MediaType.APPLICATION_JSON) // application/json 형식만을 받아들인다.
.body(BodyInserters.fromFormData("데이터", 데이터))
// .bodyValue(JSONObject 타입을 넣을 수 있다.)
.headers(httpHeaders -> httpHeaders.set(AUTHORIZATION, authKey)) // 헤더 세팅
.retrieve()
.bodyToMono(ResponseDto.class);
return response.block();
}
}
DELETE 사용법
public class API{
WebClient webClient = WebClient.create();
public static final String BASE_URL = "요청하고 싶은 주소의 BaseURL";
public ResponseDto deleteApi(String authKey) {
String endpoint = "BaseURL의 엔드포인트";
Mono<ResponseDto> response = webClient
.delete()
.uri(BASE_URL + endpoint)
.accept(MediaType.APPLICATION_JSON) // application/json 형식만을 받아들인다.
.headers(httpHeaders -> httpHeaders.set(AUTHORIZATION, authKey)) // 헤더 세팅
.retrieve()
.bodyToMono(ResponseDto.class);
return response.block();
}
}
사실은 구분할 필요도 없이 거의 다 비슷합니다.
GET이나 DELETE부분에는 requestBody를 사용하지 않고(사용할 순 있지만 권장되는 방법은 아니고 안 되는 경우도 많음) PUT, POST에는 body를 사용한다는 부분만 다르고 사용법은 비슷하다고 할 수 있습니다.
위의 코드에서 공통적으로 나오는 부분들 중 생소한 것들을 찾아보면 Mono, retrieve(), bodyToMono()가 있는데 이 친구들을 가볍게 짚고 넘어가겠습니다.
Mono
Spring Webflux에서 사용하는 reactive library가 Reactor이고 Reactor가 Reactive Streams의 구현체입니다.
여기서 Mono는 Reactive Streams의 Publisher 인터페이스를 구현하는 구현체이고, Mono 말고도 Publisher의 구현체가 Flux가 있습니다.
둘의 차이점은 Flux는 0~N개의 데이터를 처리하지만 Mono는 0~1개의 데이터를 처리한다는 점이 다릅니다.
retrieve()
HTTP 호출 결과를 가져오는 방법으로 retrieve()를 이용하면 바로 ResponseBody를 처리할 수 있습니다.
그렇다면 retrieve()와 다르게 Body값뿐만 아니라 더 자세하게 처리할 수 있는 무언가가 있을 것만 같습니다.
맞습니다. 바로 exchange()라는 것이 존재하고 requestBody 뿐만 아니라 세세한 컨트롤이 필요하다면 exchange()를 사용하면 됩니다.
종합하면 HTTP 호출 결과를 가져오는 방법에는 retrieve(), exchange()가 있고 RequestBody만 처리하려면 retrieve() 그 외에는 exchange()를 사용하면 됩니다.
bodyToMono()
위에서 Mono와 Flux라는 개념을 봤을 텐데 bodyToMono()는 가져온 객체를 이 중 Mono 객체로 바꿔주는 역할을 하고,
Flux 객체로 바꿔주는 것은 bodyToFlux()입니다.
참고 자료
- https://devuna.tistory.com/120
[WebFlux] Mono와 Flux 개념과 구현
[WebFlux] Mono와 Flux 개념과 구현 💡 WebFlux란? Spring WebFlux는 Spring 5에서 새롭게 추가된 모듈이다. WebFlux는 클라이언트, 서버에서 reactive 스타일의 어플리케이션 개발을 도와주는 모듈이며, reac..
devuna.tistory.com
- https://devjjsjjj.tistory.com/m/entry/Spring-WebClient-%EC%82%AC%EC%9A%A9%EB%B2%95
[Spring] WebClient 사용법
Spring 어플리케이션에서 HTTP 요청을 할 땐 주로 RestTemplate 을 사용했었습니다. 하지만 Spring 5.0 버전부터는 RestTemplate 은 유지 모드로 변경되고 향후 deprecated 될 예정입니다. RestTemplate ..
devjjsjjj.tistory.com
OSX - M1 개발환경 오류 - could not load a native library: netty_resolver_dns_native_macos_aarch_64
지난번 포스팅과 비슷한 내용입니다. OSX - M1 개발환경 오류 - [FAILED_TO_LOAD_NATIVE_LIBRARY] no native library is found for os.name=Mac and os.arch=aarch6. #g 얼마 전 지급받은 M1맥북에서 개발환경을..
junho85.pe.kr