jdk 1.2부터 내장되어 있으며 java.net 패키지에 있다. URL의 내용을 읽어오거나 URL 주소에 대해 HTTP 통신 및 GET, POST로 데이터를 전달할 때 사용한다.
URLConnection 클래스를 사용하는 방법은 아래와 같다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class URLConnectionExample {
public static void main(String[] args) throws IOException {
URL url = new URL("https://httpbin.org/get");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try {
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000); // 연결 타임아웃 설정 (5초)
connection.setReadTimeout(5000); // 읽기 타임아웃 설정 (5초)
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
if (responseCode >= 200 && responseCode < 300) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
System.out.println("Response Body: " + response.toString());
}
} else {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()))) {
String line;
StringBuilder errorResponse = new StringBuilder();
while ((line = reader.readLine()) != null) {
errorResponse.append(line);
}
System.err.println("Error Response Body: " + errorResponse.toString());
}
}
} finally {
connection.disconnect();
}
}
}
HTTP 프로토콜을 손쉽게 사용할 수 있도록 도와주는 Apache HTTP 컴포넌트이다.
HttpClient httpClient = new DefaultHttpClient(); 처럼 HttpClient 객체 생성
메소드에 따라 new HttpGet("http://..." URL 정보)
응답받기 위한 객체 생성
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
Steam 처리
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
public class HttpClientExample {
public static void main(String[] args) throws IOException {
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("https://httpbin.org/get");
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000)
.setSocketTimeout(5000)
.build();
httpGet.setConfig(requestConfig);
HttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null) {
String responseBody = EntityUtils.toString(entity);
System.out.println("Response: " + responseBody);
EntityUtils.consume(entity); // 스트림 비우기
}
}
}
스프링에서 제공하는 http통신에 유용하게 쓸 수 있는 템플릿이며, HTTP 서버와의 통신을 단순화하고 RESTful 원칙을지킨다. RestTemplate는 기계적이고 반복적인 코드들을 깔끔하게 정리해준다.
☑️ 장점
어플리케이션이 RestTemplate를 생성하고, URI, HTTP 메소드 등의 헤더를 담아 요청한다.
RestTemplate 는 HttpMessageConverter 를 사용하여 requestEntity 를 요청메세지로 변환한다.
RestTemplate 는 ClientHttpRequestFactory 로 부터 ClientHttpRequest 를 가져와서 요청을 보낸다.
ClientHttpRequest 는 요청메세지를 만들어 HTTP 프로토콜을 통해 서버와 통신한다.
RestTemplate 는 ResponseErrorHandler 로 오류를 확인하고 있다면 처리로직을 태운다.
ResponseErrorHandler 는 오류가 있다면 ClientHttpResponse 에서 응답데이터를 가져와서 처리한다.
RestTemplate 는 HttpMessageConverter 를 이용해서 응답메세지를 JSON으로 변환하여 어플리케이션에 반환되기에 아주 좋다.
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class RestTemplateExample implements CommandLineRunner {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(java.time.Duration.ofMillis(5000))
.setReadTimeout(java.time.Duration.ofMillis(5000))
.build();
}
public static void main(String[] args) {
SpringApplication.run(RestTemplateExample.class, args);
}
@Override
public void run(String... args) throws Exception {
RestTemplate restTemplate = restTemplate(new RestTemplateBuilder());
String response = restTemplate.getForObject("https://httpbin.org/get", String.class);
System.out.println("Response: " + response);
}
}
스프링 5.0에서 추가된 인터페이스다. 스프링 5.0 이전에는 비동기 클라이언트로 AsyncRestTemplate를 사용했었다.
하지만 스프링 5.0 이후부터는 WebClient를 사용할 것을 권장한다.
☑️ 사용하기 위해선 webflux 의존성을 추가해줘야 한다.
implementation 'org.springframework.boot:spring-boot-starter-webflux'
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@SpringBootApplication
public class WebClientExample implements CommandLineRunner {
@Bean
public WebClient webClient(WebClient.Builder builder) {
return builder
.baseUrl("https://httpbin.org")
.build();
}
public static void main(String[] args) {
SpringApplication.run(WebClientExample.class, args);
}
@Override
public void run(String... args) throws Exception {
WebClient client = webClient(WebClient.builder());
Mono<String> result = client.get()
.uri("/get")
.retrieve()
.bodyToMono(String.class);
result.subscribe(response -> System.out.println("Response: " + response));
// 비동기 작업이므로 결과를 기다리기 위해 잠시 대기 (실제 애플리케이션에서는 더 적절한 방법 사용)
Thread.sleep(2000);
}
}
RestTemplate와 WebClient의 가장 큰 차이점은 Non-Blocking과 비동기화 가능 여부이다.
이러한 이유때문에 스프링에서는 WebClient 사용을 권장하는 이유다.
RestTemplate WebClient
Non-Blocking 불가능 가능
비동기화 불가능 가능
블로킹은 말 그대로 하나의 작업이 진행중일 때 끝날때까지 작업이 중단된다는 의미이다.
하나의 작업이 진행되고 완료될 때까지 모든 일을 중단한 상태로 대기해야 하는 것을 블로킹 방식이라고 한다.
블로킹 방식의 소켓통신은 결과가 올 때까지 다른 작업을 중단하고 하염없이 대기중이게 된다.
Bloking과 반대로 하나의 작업이 진행중일 때 끝날때까지 작업이 중단되지 않고 다른 작업을 진행한다는 의미이다.
하나의 작업을 진행하면서 다른 작업도 진행할 수 있으므로 효율이나 반응속도가 더 뛰어나다.
하지만 설계가 복잡해진다는 단점이 있습니다.
알려주신 내용에 대한 수정 사항과 비교표, 그리고 보충 코드 예시를 아래와 같이 Markdown 형식으로 제공합니다.
기능 | URLConnection | HttpClient (Apache) | RestTemplate (Spring) | WebClient (Spring WebFlux) |
---|---|---|---|---|
블로킹 여부 | 블로킹 | 블로킹 | 블로킹 | 논블로킹 |
비동기 지원 | 제한적 | 제한적 | 불가능 | 가능 (Reactive) |
에러 처리 | 4xx, 5xx 응답 시 IOException 발생 (기본) | 모든 응답 코드 접근 가능 | 편리한 에러 핸들링 메커니즘 제공 (ResponseErrorHandler ) | Reactive Streams 기반 에러 처리 |
타임아웃 설정 | 가능 (setConnectTimeout() , setReadTimeout() ) | 가능 (RequestConfig 설정) | 가능 (RestTemplateBuilder 또는 ClientHttpRequestFactory 설정) | 가능 (java.time.Duration 설정) |
쿠키 관리 | 가능 (CookieHandler , CookieManager ) | 가능 (CookieStore , CookieSpec ) | 가능 (자동 쿠키 관리) | 가능 (자동 쿠키 관리) |
응답 데이터 변환 | 스트림 처리 필요 | 스트림 처리 및 컨텐츠 타입별 처리 필요 | JSON, XML 자동 변환 (HttpMessageConverter 활용) | JSON, XML 자동 변환 (Codec 지원) |
외부 의존성 | 없음 (JDK 내장) | Apache HttpClient | Spring Framework | Spring WebFlux |
간결성 | 상대적으로 복잡 | URLConnection보다 간결하지만 RestTemplate보다 복잡 | 매우 간결 | 간결하고 함수형 스타일 |
사용 시점 | 간단한 HTTP 통신, JDK만 필요한 경우 | 복잡한 HTTP 통신 설정, 세밀한 제어 필요 시 | Spring 기반 애플리케이션에서 RESTful API 호출 시 | Spring WebFlux 기반 비동기/반응형 애플리케이션에서 RESTful API 호출 시 |