티스토리 뷰

서버를 운영하다보면 다양한 API Endpoint를 만들게된다. 단순한 DB CRUD만 처리하는 경우도 있지만, 외부 API를 연동해 정보를 가져오는 경우도 있다. 이럴때 서버에서 Request를 만들어 외부 서버에 요청을 보내고 Response를 받아야한다.

자바와 스프링에서는 다양한 HTTP Request 만드는 방법을 제공한다. Java 내부에서도 제공하고, Spring Framework에서도 제공하고, 별도의 외부라이브러리를 쓸 수 도 있다.

우선 자바에서의 내용부터 정리한다.

1. HttpURLConnection

HttpURLConnection은 Java에서 제공하는 표준 라이브러리이다. 때문에 외부 종속성이 필요하지 않다는 큰 장점이 있다. 상대적으로 사용하기 쉽고 요청할 수 있는 요청 유형과 설정할 수 있는 옵션 측면에서 많은 유연성을 제공한다.

1.1 GET 방식

public static void httpGetMethod() throws IOException {
    // Create a URL object for the desired URL
    URL url = new URL("https://httpbin.org/get?id=hello&paswword=1234");

    // Open a connection to the URL using the HttpURLConnection class
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();

    // Set the request method to GET
    connection.setRequestMethod("GET");

    // Add any headers you want to send with the request
    connection.setRequestProperty("Content-Type", "application/json");

    // Set any other options you want to set on the connection
    connection.setDoOutput(true);
    connection.setDoInput(true);

    // Connect to the server
    connection.connect();

    // Read the response from the server
    BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    StringBuilder response = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        response.append(line);
    }
    reader.close();

    // Print the response to the console
    System.out.println(response.toString());

    // Disconnect from the server
    connection.disconnect();
}

https://httpbin.org 라는 사이트에서 Request가 정상적으로 갔는지 Response를 받아 볼 수 있다. 위처럼 get 방식으로 id/password를 파라미터로 넘기면 아래와 같이 Response가 온다.

{
  "args": {
    "id": "hello",
    "paswword": "1234"
  },
  "headers": {
    "Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "Java/11.0.15",
    "X-Amzn-Trace-Id": "Root=1-639d8295-3bfcb71722d0a08349295bad"
  },
  "origin": "[내 IP]",
  "url": "https://httpbin.org/get?id=hello&paswword=1234"
}

내가 보낸 Request가 서버로 정상적으로 들어갔고, 정상적으로 Response가 온것을 확인할 수 있다.

1.2 POST 방식

public static void httpPostMethod() throws IOException {
    // Create a URL object for the desired URL
    URL url = new URL("https://httpbin.org/post");

    // Open a connection to the URL using the HttpURLConnection class
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();

    // Set the request method to GET
    connection.setRequestMethod("POST");

    // Add any headers you want to send with the request
    connection.setRequestProperty("Content-Type", "application/json");

    // Set any other options you want to set on the connection
    connection.setDoOutput(true);
    connection.setDoInput(true);

    // Connect to the server
    connection.connect();

    // Make JsonInputString
    String jsonInputString = "{\"name\": \"Hello\", \"job\": \"Programmer\"}";

    OutputStream os = connection.getOutputStream();
    byte[] input = jsonInputString.getBytes();
    os.write(input, 0, input.length);

    // Read the response from the server
    BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    StringBuilder response = new StringBuilder();
    String line;
    while ((line = reader.readLine()) != null) {
        response.append(line);
    }
    reader.close();

    // Print the response to the console
    System.out.println(response.toString());

    // Disconnect from the server
    connection.disconnect();
}
{
  "args": {},
  "data": "{\"name\": \"Hello\", \"job\": \"Programmer\"}",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2",
    "Content-Length": "38",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "Java/11.0.15",
    "X-Amzn-Trace-Id": "Root=1-639d86b9-4ade572d2676ffac208fdc45"
  },
  "json": {
    "job": "Programmer",
    "name": "Hello"
  },
  "origin": "[내 IP]",
  "url": "https://httpbin.org/post"
}

Get 방식과 Post 방식 외에도 일반적인 Rest API 형태 통신을 모두 제공하며, Response 데이터의 길이 제한이 딱히 없는 것 같다. 요청 방식을 확인 or 설정, redirect 여부 결정, 응답 코드와 메시지를 Read , 프록시 서버가 사용되었는지 여부 확인 메서드 등을 가지고 있다.

또한, 다양한 HTTP 응답 코드에 해당하는 상수 값들이 정의되어 있어서 아래와 같이 방어 코드를 구현하는데도 용이하다.

if(connection.getResponseCode() == connection.HTTP_OK) {
    ...
}

추가적인 내용은 Java Docs 에서 확인할 수 있다.

1.3 단점

단점으로는, 복잡한 Request/Response에 대한 처리가 불편하다.
무엇보다 눈에 띄는 건 서버의 Response를 별도의 객체로 받아서 처리하지 못 하기 때문에 위 코드에서도 while문을 통해 readLine 매서드로 일일히 받은 후 처리해야 했다는 점이다.
또한, 자동 재시도 또는 연결 풀링과 같은 기능을 지원하지 않으므로 원하는 경우 직접 처리해야 한다.

 

2. HttpClient

java.net.http.HttpClient는 Java 11에 도입된 새로운 HTTP 클라이언트이다. 현대적이고 효율적이며 HTTP/2 및 WebSocket을 지원한다. HttpURLConnection은 비동기 처리를 위해 별도의 과정이 필요했는데, HttpClient는 별도의 과정 없이 비동기 처리 기능을 제공한다.

내 PC는 Java 8만 설치되어 있어 예제 코드는 발췌한 내용이다.

2.1 GET 방식

// Create an HttpClient object
HttpClient httpClient = HttpClient.newHttpClient();
// Create an HttpRequest object with the desired request method and URL
HttpRequest request = HttpRequest.newBuilder()
    .GET()
    .uri(URI.create("http://www.example.com"))
    .build();
// Send the request using the send method of the HttpClient object and get the response using the body method of the HttpResponse object:
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
String responseBody = response.body();

2.2 POST 방식

// Create an HttpClient object
HttpClient httpClient = HttpClient.newHttpClient();
// Create an HttpRequest object with the desired request method and URL, and set the request body using the ofString method of the BodyPublishers class:
HttpRequest request = HttpRequest.newBuilder()
    .POST(HttpRequest.BodyPublishers.ofString("{\"key\":\"value\"}"))
    .uri(URI.create("http://www.example.com"))
    .build();
// Send the request using the send method of the HttpClient object and get the response using the body method of the HttpResponse object:
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
String responseBody = response.body();

확실히 HttpURLConnection보다 간결해졌다. 아직까진 Java에서 HttpClient를 우선해서 권장하지는 않는 것 같으니 목적에만 맞으면 어떤 것을 사용해도 괜찮을 것 같다.

3. 외부 라이브러리

자바의 역사가 오래된만큼 HTTP 통신을 위한 외부 라이브러리는 진짜 다양하고 많다. 제일 많이 사용하는 Apache HttpClient와 HttpOk만 간단히 설명하고 넘어가려고 한다.

외부 라이브러리이기 때문에, 라이브러리를 받는 별도의 과정은 필요하다. 구현 방법은 추후에 추가할 예정..

3-1. Apache HttpClient

공식사이트 링크

  • 장점
    1. 다양한 기능 및 커스터마이즈 옵션을 제공한다.
    2. 다양한 HTTP 메서드 및 프로토콜 지원
  • 단점
    1. 다른 라이브러리보다 더 많은 리소스를 사용하고 느리다.
    2. 설치 공간이 더 클 수 있고 더 많은 설정이 필요하다.
    3. 현재 안드로이드에서는 Deprecated 되었다고 한다.

3-2. okHttp

공식사이트 링크

  • 장점
    1. 안드로이드에서도 사용가능
    2. 설치 공간이 작다.
    3. 서버당 단일 연결을 사용하고 자동으로 연결을 재사용하여 연결 생성 및 해제의 오버헤드를 줄였다.
    4. HTTP/2 및 WebSocket을 지원
  • 단점
    1. 다른 라이브러리보다 더 많은 리소스를 사용하고 느리다.
    2. 가벼운 HTTP 통신에는 적합하지 않을 수 있음

앞서 언급한 것과 같이 이 외에도 Retrofit 등 정말 다양한 라이브러리들이 있기 때문에, 본인의 용도와 목적에 맞는 라이브러리를 가져다 쓰면 된다.

4. 마치며

Spring Framework에서도 서버에 Http Request를 보내기 위해 몇 가지 API를 제공한다. 다음 글에선 Spring Framework에서의 HTTP 통신 방식에 대해 다뤄볼 예정이다.


'개발 > JAVA' 카테고리의 다른 글

[JAVA] 함수형 인터페이스  (1) 2023.01.26
[JAVA] TemporalAdjusters  (0) 2023.01.26
[Java] ObjectMapper  (0) 2023.01.22
[JAVA] Thread Safety  (0) 2023.01.21
[JAVA] 난수 생성기 Random, SecureRandom  (0) 2022.12.27
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
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
글 보관함