❓그럼 WebClient가 없고, RestTemplate만 있었던 시기에는 비동기처리가 불가능 했던 걸까?
이 질문의 답변은 당연히 아니다.
애초에 RestTemplate은 기본적으로 HTTP 요청을 보내고 응답을 받는 데 사용해왔고, RESTful API 호출하기 위해 매번 세팅값을 만들어야하는 불편함에서 만들어진 Template이다. 비동기적인 동작은 고려했던것이 아니다.
그렇기에 비동기처리를 위해 쓰레드(업무를 처리해주는 얘)를 늘려서 동시에 동작하게 만드는 것이다.
이런 쓰레드를 보통 관리하는 것이 쓰레드풀
이라는 것이다.
하지만, Tread클래스를 만들어 사용한다던가, Runnable 인터페이스를 구현한다던가등이 마저도 엄청 번거로운 코드 작업이 되기 때문에, 좀 편하게 쓰라고 라이브러리를 만들어준다.
Java에서 제공하는 동시성(Concurrency) 라이브러리로 멀티스레딩 프로그래밍을 할때 사용하기 좋은 클래스와 인터페이스를 모아져 있다.
논블로킹
(대기안함)한다.supplyAsync
, runAsync
등의 메소드로 주어진 작업을 비동기적으로 처리할 수있다.이 외에도 다양한 비동기적처리를 도와주는 기능이 있다.
❓ 그럼 RestTemplate으로 비동기처리는 어떻게 하는 건데?
내가 알아본 바로는 크게 2가지 방법이 있다. 순수 java로 하는 방식과 Spring Framework에서 제공하는 것을 활용한 방식!(WebClient는 RestTemplate이 아니니 논외)
CompletableFuture<ResponseEntity<String>> future =
CompletableFuture.supplyAsync(() ->
restTemplate.getForEntity("https://example.com/api/v1/users", String.class));
// 비동기 요청이 완료되기를 대기합니다.
ResponseEntity<String> responseEntity = future.get();
위까지 하게되면 기본적으로 설정된 쓰레드 규칙에 맞춰 비동기적으로 처리가 된다.
하지만, 나는 전에 요청받는 API서버 측에서 요청 제안을 걸어 너무 많은 제안을 넣으면 안되는 상황이였고, 그렇게된지라 어쩔수없이 쓰레드를 조정하여 요청수를 조정해야됐다.
ExecutorService executorService = Executors.newFixedThreadPool(4); // 생성
CompletableFuture<ResponseEntity<String>> future =
CompletableFuture.supplyAsync(() ->
restTemplate.getForEntity("https://example.com/api/v1/users", String.class),
executorService); // 인자에 추가
//..중간 생략
executorService.shutdown(); // 닫아줌