| 실습 환경: Spring Boot 3.2.1 / Java 17 / Gradle
1. HttpURLConnection 실습
❓ HttpURLConnection
- HTTP와 관련된 기능을 지원하는 URLConnection
- URLConnection은 Java 애플리케이션과 URL 간의 연결 관련한 모든 클래스의 수퍼 클래스
- Spring 같은 프레임워크 없이도 사용이 가능하다는 장점!
🔌 코드
private String baseUrl = "https://dapi.kakao.com/v2/local/search/keyword.JSON";
private String header = "Authorization";
@GetMapping("/http-url-connection")
public JSONObject httpUrlConnection(@RequestHeader("Authorization") String auth,
@RequestParam("query") String query) throws IOException, ParseException {
// URL 객체 생성
URL url = new URL(baseUrl + "?query=" + encode(query));
// connection 생성
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
StringBuilder sb = new StringBuilder();
if (conn != null) {
conn.setConnectTimeout(10000); // 10초 동안 기다린 후 응답이 없으면 종료
conn.setRequestMethod("GET"); // Http 메서드 설정
conn.setRequestProperty(header, auth); // Http 헤더 설정
conn.setDoInput(true);
conn.setDoOutput(true);
int resCode = conn.getResponseCode(); // 요청 전송
if (resCode == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while (true) {
line = reader.readLine();
if (line == null)
break;
sb.append(line);
}
reader.close();
}
conn.disconnect();
}
// json 변환 후 반환
return stringToJson(sb.toString());
}
private String encode(String str) throws UnsupportedEncodingException {
return URLEncoder.encode(str, "UTF-8");
}
private JSONObject stringToJson(String str) throws ParseException {
JSONParser parser = new JSONParser();
JSONObject jsonObject = (JSONObject) parser.parse(str);
return jsonObject;
}
URLEncoder.encode(query, "UTF-8");
- 쿼리 파라미터 한글 처리!
JSONParser
- String to Json
- 스트링 빌더에 저장되어 있는 문자열을 json으로 변환시켜서 반환한다.
- build.gradle에 dependency 추가해줘야 함.
implementation 'com.googlecode.json-simple:json-simple:1.1.1'
💡 결과값
2. RestTemplate 실습
❓ RestTemplate
- HttpURLConnection과 같은 기본적인 HTTP 클라이언트 대신에 사용할 수 있는 동기식 클라이언트
- HTTP 서버와의 통신을 단순화하고 RESTful 원칙을 지킨다.
- 템플릿 API를 노출해서 일반적인 시나리오에 대한 HTTP 메서드를 제공
🔌 코드
@GetMapping("/rest-template")
public JSONObject restTemplate(@RequestHeader("Authorization") String auth,
@RequestParam("query") String query) throws UnsupportedEncodingException, ParseException {
// RestTemplate 객체 생성
RestTemplate restTemplate = new RestTemplate();
// HttpHeader 설정
HttpHeaders headers = new HttpHeaders();
headers.add(header, auth);
// HttpEntity 생성
HttpEntity entity = new HttpEntity<>(headers);
// API 호출
ResponseEntity response = restTemplate.exchange(
getUri(query),
HttpMethod.GET,
entity,
String.class);
// json 변환 후 반환
return stringToJson(response.getBody().toString());
}
private URI getUri(String query) {
return UriComponentsBuilder.fromHttpUrl(baseUrl)
.queryParam("query", query)
.encode(Charset.forName("UTF-8"))
.encode()
.build()
.toUri();
}
- URI 설정
- RestTemplate을 이용하면
URLEncoder.*encode*(query, "UTF-8");
을 통한 쿼리 파라미터 한글 처리가 되지 않는다.UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(baseUrl).queryParam("query", encode(query));
- 따라서 URI를 설정하면서 인코딩을 해주자.
.encode(Charset.forName("UTF-8"))
- RestTemplate을 이용하면
💡 결과값
3. WebClient 실습
❓ WebClient
- 웹으로 API를 호출하기 위해 사용되는 HttpClient
- RestTemplate은 Multi-Thread와 Blocking 방식으로 동작하는 반면, WebClient는 Single-Thread와 Non-Blocking 방식으로 동작
- Multi-Thread & Blocking : 1요청 당 1스레드가 할당되고 응답이 올 때까지 그 스레드는 다른 요청에 할당되지 않는다.
- Single-Thread & Non-Blocking : 각 요청은 Event Loop에 Job으로 등록되고 Event Loop는 각 Job을 제공자에게 요청한 후, 결과를 기다리지 않고 다른 Job을 처리할 수 있다. 제공자로부터 Callback 응답이 오면 그 결과를 요청자에게 제공한다.
- 이벤트에 대해서 반응형으로 설계되어 있다.
🔌 코드
@GetMapping("/web-client")
public JSONObject webClient(@RequestHeader("Authorization") String auth,
@RequestParam("query") String query) throws ParseException {
String response = WebClient.create()
.get() // GET 방식
.uri(getUri(query)) // URI 설정
.header(header, auth) // 헤더 설정
.retrieve()
.bodyToMono(String.class)
.block();
return stringToJson(response);
}
- build.gradle에 dependency 추가
implementation 'org.springframework.boot:spring-boot-starter-webflux'
- 1개의 값을 리턴할 때는 bodyToMono, 복수의 값을 리턴할 때는 bodyToFlux를 사용
- String으로 변환하기 위해서는
bodyToMono
를 사용하고,.block();
처리를 해줘야 한다.
- String으로 변환하기 위해서는
💡 결과값
전체 코드
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.util.UriComponentsBuilder;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
@RestController
public class TestController {
private String baseUrl = "https://dapi.kakao.com/v2/local/search/keyword.JSON";
private String header = "Authorization";
@GetMapping("/http-url-connection")
public JSONObject httpUrlConnection(@RequestHeader("Authorization") String auth,
@RequestParam("query") String query) throws IOException, ParseException {
// URL 객체 생성
URL url = new URL(baseUrl + "?query=" + encode(query));
// connection 생성
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
StringBuilder sb = new StringBuilder();
if (conn != null) {
conn.setConnectTimeout(10000); // 10초 동안 기다린 후 응답이 없으면 종료
conn.setRequestMethod("GET"); // Http 메서드 설정
conn.setRequestProperty(header, auth); // Http 헤더 설정
conn.setDoInput(true);
conn.setDoOutput(true);
int resCode = conn.getResponseCode(); // 요청 전송
if (resCode == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while (true) {
line = reader.readLine();
if (line == null)
break;
sb.append(line);
}
reader.close();
}
conn.disconnect();
}
// json 변환 후 반환
return stringToJson(sb.toString());
}
@GetMapping("/rest-template")
public JSONObject restTemplate(@RequestHeader("Authorization") String auth,
@RequestParam("query") String query) throws UnsupportedEncodingException, ParseException {
// RestTemplate 객체 생성
RestTemplate restTemplate = new RestTemplate();
// HttpHeader 설정
HttpHeaders headers = new HttpHeaders();
headers.add(header, auth);
// HttpEntity 생성
HttpEntity entity = new HttpEntity<>(headers);
// API 호출
ResponseEntity response = restTemplate.exchange(
getUri(query),
HttpMethod.GET,
entity,
String.class);
// json 변환 후 반환
return stringToJson(response.getBody().toString());
}
@GetMapping("/web-client")
public JSONObject webClient(@RequestHeader("Authorization") String auth,
@RequestParam("query") String query) throws ParseException {
String response = WebClient.create()
.get() // GET 방식
.uri(getUri(query)) // URI 설정
.header(header, auth) // 헤더 설정
.retrieve()
.bodyToMono(String.class)
.block();
return stringToJson(response);
}
private String encode(String str) throws UnsupportedEncodingException {
return URLEncoder.encode(str, "UTF-8");
}
private URI getUri(String query) {
return UriComponentsBuilder.fromHttpUrl(baseUrl)
.queryParam("query", query)
.encode(Charset.forName("UTF-8"))
.encode()
.build()
.toUri();
}
private JSONObject stringToJson(String str) throws ParseException {
JSONParser parser = new JSONParser();
JSONObject jsonObject = (JSONObject) parser.parse(str);
return jsonObject;
}
}
'* > Spring' 카테고리의 다른 글
[Spring Boot] 동시성 제어 (1) - 동시성 문제, 재고 감소 시스템 구현 및 테스트 (1) | 2024.11.09 |
---|---|
[JPA] 엔티티 equals 메서드 구현 시 주의할 점 (0) | 2024.11.08 |
[JPA] Join Fetch 시 MultipleBagFetchException (0) | 2024.11.07 |
[Spring] OpenFeign 사용해보기 (0) | 2024.05.22 |
[JPA] 엔티티 생성 시 생겼던 문제들 (식별관계 문제) (0) | 2024.03.17 |