우리가 사용하는 RestTemplate, fetch, axios 같은 HTTP 클라이언트는 단순 호출만으로 요청을 보낼 수 있게 해 주기 때문에 내부에서 어떤 일이 일어나는지 알기 어렵습니다. 하지만 저수준 API인 HttpURLConnection을 직접 보면 HTTP 요청이 어떤 방식으로 구성되고 전송되는지 조금 더 명확하게 이해할 수 있습니다.
1. 저수준 HTTP 요청 코드 예시
아래는 JSON 데이터를 POST로 보내고, 응답을 문자열로 읽어오는 간단한 예시 코드입니다.
public static String sendJsonPost(String targetUrl, String jsonBody) throws IOException {
URL url = new URL(targetUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
conn.setRequestProperty("Accept", "application/json");
conn.setDoOutput(true);
try (OutputStream out = conn.getOutputStream()) {
byte[] data = jsonBody.getBytes(StandardCharsets.UTF_8);
out.write(data);
}
StringBuilder responseText = new StringBuilder();
try (BufferedReader reader =
new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
responseText.append(line);
}
}
return responseText.toString();
}
RestTemplate처럼 한 줄로 끝나는 코드는 내부적으로 이런 흐름을 수행합니다. 직접 구현된 버전을 보면 HTTP가 근본적으로 어떤 방식으로 동작하는지 더 잘 이해할 수 있습니다.
2. 문자열(JSON)을 바이트로 변환하는 이유
HTTP는 텍스트 기반 프로토콜처럼 보이지만, 실제로는 모든 요청과 응답이 바이트 스트림으로 전송됩니다. 따라서 문자열을 그대로 전송할 수 없고, 반드시 바이트 배열로 변환해야 합니다.
byte[] data = jsonBody.getBytes(StandardCharsets.UTF_8);
out.write(data);
이 과정은 다음과 같은 의미를 가집니다.
- 문자열(JSON)을 UTF-8 인코딩으로 바이트 배열로 변환한다.
- 변환된 바이트를 HTTP 요청 바디에 기록한다.
우리가 보던 fetch나 RestTemplate는 이 단계를 내부적으로 자동 처리하기 때문에 직접 이 과정을 볼 일이 거의 없습니다.
3. 응답을 읽는 과정도 결국 바이트 스트림 처리
BufferedReader reader =
new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
서버가 보내는 응답도 네트워크를 통해 바이트 흐름으로 도착합니다. 이를 지정된 문자셋(UTF-8)으로 다시 문자열로 복원하는 과정이 필요합니다.
4. 왜 평소에는 이런 코드를 보기 어려울까?
대부분의 개발 환경은 이미 고수준 HTTP 클라이언트를 제공하기 때문입니다.
- 브라우저:
fetch,axios - Spring:
RestTemplate,WebClient - Android/Java:
OkHttp
이 도구들은 스트림 생성, 바이트 변환, 예외 처리 등 모든 과정을 내부에서 처리하여 개발자가 신경 쓸 필요가 없도록 만들어 줍니다. 그렇기 때문에 실제 HTTP 요청이 어떤 구조인지 직접 볼 일이 많지 않습니다.
정리
- HTTP 통신은 본질적으로 바이트 스트림 교환이다.
- 고수준 라이브러리는 이 사실을 감춘 채 편한 인터페이스만 제공한다.
- 저수준 API를 보면 요청·응답의 실제 동작 원리를 분명하게 이해할 수 있다.
가끔은 이런 내부 동작을 직접 확인해보는 것이 전체 구조를 이해하고, 예상치 못한 네트워크 문제를 해결하는 데에도 도움이 됩니다.
'개발' 카테고리의 다른 글
| GET 방식 API에서 Cache-Control을 중앙 통제로 관리하는 실무 전략 (0) | 2026.01.20 |
|---|---|
| 공간정보 뷰에서 데이터가 없으면 지점이 사라지는 문제와 SQL 튜닝 과정 — KEEP (DENSE_RANK LAST …) 활용하기 (0) | 2026.01.07 |
| Spring Boot(Kotlin) — 12편. 완성된 프로젝트 템플릿 공유 (0) | 2025.11.27 |
| Spring Boot(Kotlin) 기본 셋팅 — 11편. 멀티모듈 + JPA 기본 구조 정리 (0) | 2025.11.27 |
| Spring Boot(Kotlin) — 10편. application.yml 프로필 분리 (local/dev/prod) (0) | 2025.11.27 |