배치와 온라인 시스템이 분리되어 있어서, 스프링 배치에서 온라인 API를 호출해야 되는 상황이 있었다.
타 시스템을 호출하기 위해 사용했던 방법을 적어보려고 한다.
API 호출하기에 많은 방법들이 있지만, Spring에서 제공하는 http 클라이언트를 사용하여 API를 호출하려고 한다.
대표적으로, RestTemplate와 WebClient가 있다.
POST MAN으로 테스트하듯 API 호출할 수 있으며, ui없이 java로만 요청/응답 파싱 후 처리하는 느낌이었다.
1. 실무에서 외부 API URL 호출 구현 방법 - 대표적인 방법들
(Java 기준, 백엔드에서 외부 API 호출)
1) HttpURLConnection (JDK 기본)
장점: 라이브러리 추가 필요 없음.
단점: 코드가 장황하고 불편함. 커넥션/스트림 관리 직접 해야 함. 유지보수성 떨어짐.
용도: 거의 안 씀. 정말 경량, 의존성 없는 상황에서만 사용.
2) RestTemplate (Spring 전통)
장점: Spring에서 기본적으로 제공, 사용법 간단, ResponseEntity 등 스프링의 편의성 활용 가능.
단점: 동기 방식(Non-blocking 아님), 스프링 5 이후로는 권장 X(Deprecated 아님, 유지보수만).
용도: 실무에서 가장 많이 씀(특히 스프링 4,5 환경), 비동기 필요 없으면 OK.
3) WebClient (Spring 5 이후, Reactive)
장점: 비동기/논블로킹 지원, 최신 방식, 응답 스트림 처리에 강점.
단점: 러닝커브, 복잡해질 수 있음, Spring WebFlux 필요.
용도: 비동기 처리, 대량 호출, 성능이슈 있을 때.
4) 외부 라이브러리(OkHttp, Apache HttpClient 등)
장점: 범용성, 기능 풍부, 커넥션 풀/비동기 등 세부 설정 유리.
단점: 스프링과 통합 불편할 수 있음, 추가 의존성 필요.
용도: 스프링 안 쓰는 프로젝트, 특별히 고성능/특정 기능 요구할 때.
2. RestTemplate 예시 (실제 코드)
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
@Service
public class ExternalApiService {
private final RestTemplate restTemplate = new RestTemplate();
public String callExternalApi(String url, Map<String, String> paramMap, String token) {
// 1. 헤더 세팅
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // x-www-form-urlencoded
headers.setBearerAuth(token); // Authorization: Bearer {token}
// 또는 headers.add("Authorization", "Bearer " + token);
// 2. 바디 생성 (MultiValueMap으로 변환)
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.setAll(paramMap);
// 3. 엔티티 생성
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(body, headers);
// 4. POST 호출
ResponseEntity<String> response = restTemplate.exchange(
url,
HttpMethod.POST,
entity,
String.class
);
return response.getBody();
}
}위 코드는 예시이며, HttpEntity에 바디와 헤더를 담아서 요청만 하면 된다.
중요하게 확인해야 될 부분은
1. 요청타입/응답타입 (온라인 웹 서비스가 있다면 API 요청하고 개발자도구에서 네트워크 들어가서 바로 알 수 있음.)
예를 들어, 나는 요청타입이 JSON이 아니라 x-www-form-urlencoded 타입이어서 LinkedMultiValueMap에 담아 보내줬다.
2. 액세스토큰 값 헤더에 넣어주기(필요시) -> 토큰값을 가져와서 헤더타입에 맞게 넣어줘야 됨.
(URL 지정은, 테스트하면서 진행할거라 공통적인 url인 로컬, 개발, 운영 url을 상수로 박아둬서 LOCAL_URL, DEV_URL, PROD_URL 로 호출하고 뒤에 호출 경로 넣는 방식으로 두면 편함)
3. 응답 검증/타입에 따라 파싱
위에 절차만 진행하면 RestTemplate으로 API호출이 쉽게 가능하다.
3. WebClient 예시 (위와 동일한 기능)
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.util.Map;
@Service
public class ExternalApiService {
private final WebClient webClient = WebClient.builder().build();
public String callExternalApi(String url, Map<String, String> paramMap, String token) {
// x-www-form-urlencoded 바디 준비
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.setAll(paramMap);
// POST 요청
return webClient.post()
.uri(url)
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.header("Authorization", "Bearer " + token)
.bodyValue(body)
.retrieve()
.bodyToMono(String.class)
.block(); // 동기 결과 반환
}
}
참고로
웹클라이언트는 스프링5+ 버전 이후로도 관리되는 http 클라이언트라서
RestTemplate(deprecated)와 비교한다면 WebClient를 사용하는 것을 권장한다고 공식문서에 나와있다.
없어진다는 건 아니며, 권장하지 않는다고 한다. (추가 버전 업데이트를 하진 않을 예정인듯?)
그리고 위와 같이 웹클라이언트는 메서드체이닝 방식으로 (빌더패턴느낌) 가독성이 너무 좋아서
굳이 RestTemplate을 사용할 것 같지는 않다.