HTTP 메시지는 클라이언트와 서버가 데이터를 주고받을 때 사용하는 표준 형식으로 요청(Request) 메시지와 응답(Response) 메시지로 나뉘며, 각각 명확한 구조를 가지고 있다.
HTTP 메시지는 텍스트 기반으로 작성되어 사람이 읽을 수 있으며, 이는 디버깅과 분석을 쉽게 만든다. 개발자 도구나 네트워크 분석 도구로 HTTP 메시지를 직접 확인할 수 있고, 문제가 발생했을 때 원인을 빠르게 파악할 수 있다.
HTTP 메시지의 기본 구조
시작 라인 (Start Line)
헤더 (Headers)
빈 줄 (Blank Line)
본문 (Body)
-
시작 라인: 메시지의 첫 줄로, 요청인지 응답인지 구분하고 기본 정보를 담는다. 요청에서는 메서드와 URL을, 응답에서는 상태 코드를 포함한다.
-
헤더: 메시지에 대한 메타데이터를 담는다. 콘텐츠 타입, 길이, 인코딩, 인증 정보 등을 키-값 쌍으로 표현한다. 여러 줄로 구성되며, 각 헤더는
Key: Value형식을 따른다. -
빈 줄: 헤더의 끝을 나타낸다. CRLF(
\r\n)만 포함하며, 헤더와 본문을 구분하는 역할을 한다. 이 빈 줄이 없으면 메시지 파싱이 실패한다. -
본문: 실제 전송할 데이터를 담으며 HTML 문서, JSON 데이터, 이미지 파일 등이 포함된다. GET 요청의 경우에는 본문이 없다.
HTTP 요청 메시지
HTTP 요청은 클라이언트가 서버에 보내는 메시지로, 서버가 수행할 작업을 지시한다.
GET /api/users/123 HTTP/1.1 => 시작 라인
Host: example.com => 요청 헤더
User-Agent: Mozilla/5.0
Accept: application/json
Authorization: Bearer eyJhbGc...
=> 빈줄
요청 라인 (Request Line)
GET /api/users/123 HTTP/1.1
└┬┘ └──────┬──────┘ └───┬───┘
메서드 URI HTTP 버전
-
HTTP 메서드: 서버가 수행할 동작을 나타낸다.
-
요청 URI: 접근하려는 리소스의 경로로
/api/users/123?sort=name처럼 쿼리 파라미터를 포함한다. 절대 경로 형식으로 작성하며, Host 헤더와 결합하여 완전한 URL을 구성한다. -
HTTP 버전:
HTTP/1.1,HTTP/2,HTTP/3등 사용하는 HTTP 프로토콜 버전을 명시한다.
요청 헤더 (Request Headers)
요청 헤더는 요청에 대한 추가 정보를 제공한다.
-
Host 헤더: 요청을 보낼 서버의 도메인과 포트를 명시한다. HTTP/1.1부터 필수이며, 하나의 IP 주소에 여러 도메인이 호스팅된 경우(가상 호스팅) 서버가 어떤 사이트로 요청을 보낼지 판단한다.
-
User-Agent 헤더: 클라이언트 애플리케이션 정보를 담는다. 브라우저 종류, 운영체제, 버전 등을 포함하며, 서버는 이를 보고 최적화된 응답을 제공할 수 있다.
-
Accept 헤더: 클라이언트가 받아들일 수 있는 콘텐츠 타입을 명시한다. 서버는 이를 참고하여 적절한 형식으로 응답한다.
-
Authorization 헤더: 인증 정보를 담는다. Bearer 토큰, Basic 인증 등 다양한 방식을 사용한다.
-
Content-Type 헤더: 본문의 데이터 형식을 나타낸다. POST, PUT, PATCH 요청에서 사용된다.
-
Content-Length 헤더: 본문의 크기를 바이트 단위로 명시한다. 서버가 본문 끝을 정확히 알 수 있게 해준다.
요청 본문 (Request Body)
요청 본문은 서버로 전송할 데이터를 담는다. GET, DELETE, HEAD 요청은 일반적으로 본문이 없고, POST, PUT, PATCH 요청에서 주로 사용된다.
POST /api/users HTTP/1.1
Host: example.com
Content-Type: application/json
Content-Length: 58
{"name": "John Doe", "email": "john@example.com", "age": 30} => 요청 본문
폼 데이터를 전송할 때는 application/x-www-form-urlencoded 형식을 사용한다.
POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
username=user&password=pass123
파일 업로드는 multipart/form-data를 사용하며, 여러 부분으로 나뉜 데이터를 전송한다.
POST /upload HTTP/1.1
Host: example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="file"; filename="image.png"
Content-Type: image/png
[바이너리 데이터]
------WebKitFormBoundary7MA4YWxkTrZu0gW--
HTTP 응답 메시지
HTTP 응답은 서버가 클라이언트에게 보내는 메시지로, 요청 처리 결과를 담는다.
HTTP/1.1 200 OK => 상태 라인
Content-Type: application/json => 응답 헤더
Content-Length: 58
Cache-Control: max-age=3600
=> 빈줄
{"id": 123, "name": "John Doe", "email": "john@example.com"} => 본문
상태 라인 (Status Line)
상태 라인은 응답 메시지의 첫 줄로, 세 가지 요소로 구성된다.
HTTP/1.1 200 OK
└───┬───┘ └┬┘ └┬┘
HTTP 버전 코드 메시지
-
HTTP 버전: 서버가 사용하는 HTTP 프로토콜 버전이다.
-
상태 코드: 요청 처리 결과를 나타내는 3자리 숫자다. 200은 성공, 404는 찾을 수 없음, 500은 서버 오류를 의미한다.
-
상태 메시지: 상태 코드에 대한 간단한 설명이다. OK, Not Found, Internal Server Error 등이 있으며, 사람이 읽기 쉽도록 제공된다.
응답 헤더 (Response Headers)
-
Content-Type 헤더: 응답 본문의 형식을 명시한다. 클라이언트는 이를 보고 데이터를 올바르게 해석한다.
-
Content-Length 헤더: 응답 본문의 크기를 바이트 단위로 나타낸다.
-
Cache-Control 헤더: 캐싱 정책을 지시하며 응답을 얼마나 오래 캐시할지, 재검증이 필요한지 등을 명시한다.
-
Set-Cookie 헤더: 클라이언트에 쿠키를 저장하도록 지시한다. 세션 관리, 사용자 추적 등에 사용된다.
-
Location 헤더: 리다이렉션할 URL을 명시한다. 301, 302, 307 같은 리다이렉션 상태 코드와 함께 사용된다.
-
Server 헤더: 서버 소프트웨어 정보를 제공한다. 보안상 이유로 상세 버전 정보를 숨기는 것이 권장된다.
응답 본문 (Response Body)
응답 본문은 클라이언트가 요청한 실제 데이터를 담는다. JSON API나 HTML 페이지 형식으로 작성하며, 에러 응답도 본문을 포함할 수 있다.
헤더의 종류
-
일반 헤더(General Headers): 요청과 응답 모두에 사용되는 헤더로
Date,Connection,Cache-Control등이 있다. -
요청 헤더(Request Headers): 요청에만 사용되며
Host,User-Agent,Accept,Authorization,Referer등이 있다. -
응답 헤더(Response Headers): 응답에만 사용되며
Server,Set-Cookie,Location등이 있다. -
엔티티 헤더(Entity Headers): 본문에 대한 정보를 담는다.
Content-Type,Content-Length,Content-Encoding,Content-Language등이 있다. -
커스텀 헤더: 표준이 아닌 사용자 정의 헤더로 일반적으로
X-접두사를 붙였지만, 최근에는 그냥 사용하는 추세다.
HTTP 메시지 흐름
클라이언트가 웹 페이지를 요청하는 전체 과정은 다음과 같다.
-
클라이언트는 TCP 연결을 맺는다. DNS로 도메인을 IP 주소로 변환하고, 3-Way Handshake로 연결을 설정한다.
-
HTTP 요청을 전송한다.
-
서버는 요청을 받아 처리한다. 요청 라인과 헤더를 파싱하고, 요청된 리소스를 찾아 응답을 생성한다.
-
HTTP 응답을 반환한다.
-
클라이언트는 그 응답을 받아 렌더링한다. HTML을 파싱하고, 필요한 리소스(CSS, 이미지)를 추가로 요청한다.
-
연결을 종료하거나 재사용한다. HTTP/1.0은 기본적으로 연결을 닫지만, HTTP/1.1은 Keep-Alive로 연결을 유지한다.
HTTP 메시지는 웹 통신의 기본 단위다. 메시지 구조와 인코딩을 정확히 이해하면 API를 올바르게 설계하고, 성능을 최적화하며, 문제를 빠르게 해결할 수 있다.