HTTP · 웹 · 네트워크

HTTP 요청과 응답

요청과 응답 메시지를 읽고 브라우저가 웹 자원을 가져오는 흐름을 확인합니다.

무료 공개 · 최근 수정

소켓에 직접 흘려보내는 원시 텍스트

웹 브라우저의 주소창에 주소를 입력하거나 프로그램에서 외부 API를 호출할 때, 운영체제의 네트워크 소켓을 통해 전송되는 날것의 데이터는 의외로 단순한 영문 텍스트입니다.

GET /v1/chat/completions HTTP/1.1
Host: api.example.com
User-Agent: agent-client/2.1
Accept: application/json
Authorization: Bearer test-key-9921
 

이 다섯 줄의 텍스트가 바로 웹 통신의 근간인 HTTP(Hypertext Transfer Protocol)의 실제 모습입니다. 첫 번째 줄은 무엇을 원하는지 나타내는 시작줄이며, 둘째 줄부터 넷째 줄까지는 통신에 필요한 메타데이터를 담은 헤더입니다. 그리고 마지막에 위치한 빈 줄 하나가 헤더의 끝을 알립니다.

인터넷에 연결된 컴퓨터들은 이 약속된 형식에 맞춰 문자를 직렬화하여 전송합니다. 클라이언트가 서버에 작업을 요구하는 요청(Request)을 전달하면, 서버는 그 의미를 해석해 결과를 담은 응답(Response)을 돌려줍니다. 웹 브라우저 화면에 화려한 페이지가 렌더링되는 과정도 내부를 들여다보면 HTML 문서, CSS 스타일시트, 자바스크립트 코드, 이미지를 가져오기 위해 수십 번의 원시 텍스트 요청과 응답을 교환한 결과물입니다.

요청과 응답의 4계층 해부

클라이언트와 서버가 주고받는 두 메시지는 서로 마주 보듯 대칭적인 계층 구조를 갖추고 있습니다. 독자가 전송 단위의 내부 배치를 파악할 수 있도록 요청과 응답의 구성 요소를 층별로 분해해 확인합니다.

HTTP 요청 메시지와 응답 메시지가 시작줄과 헤더, 빈 줄, 본문의 대칭적인 층으로 이루어진 계층 구조

그림: 요청과 응답 메시지를 이루는 네 계층의 구조적 대응

두 메시지 모두 네 가지 핵심 영역으로 구분됩니다.

  1. 시작줄(Start-line): 요청 메시지에서는 목적을 나타내는 메서드(GET, POST, PUT, DELETE 등)와 요청 경로(URI), 프로토콜 버전이 들어갑니다. 응답 메시지에서는 프로토콜 버전과 함께 처리 결과를 나타내는 숫자 코드와 사유 구문이 들어갑니다.
  2. 헤더(Headers): 이름과 값이 콜론(:)으로 구분된 키-값 쌍의 집합입니다. 클라이언트 식별 정보, 수신 가능한 데이터 형식, 압축 방식, 인증 토큰 같은 전송 제어 정보를 담습니다.
  3. 빈 줄(CRLF): 줄바꿈 문자(\r\n)만으로 이루어진 빈 줄로, 헤더 영역이 끝나고 데이터 본문이 시작됨을 엔진에 명확히 알리는 필수 경계선입니다.
  4. 본문(Body): 실제로 주고받는 데이터 페이로드입니다. GET 요청처럼 본문이 없는 경우도 많지만, POST나 PUT 요청을 보낼 때와 서버가 결과를 반환할 때는 JSON 문자열, HTML 문서, 이미지 바이너리가 이 영역에 실립니다.

상태 코드로 작업 결과 파악하기

서버는 요청을 수신한 뒤 처리 상태를 요약한 세 자리 숫자, 즉 상태 코드(Status Code)를 응답 시작줄의 첫머리에 실어 보냅니다. 클라이언트는 본문을 일일이 파싱하지 않고도 이 세 자리 숫자만으로 작업의 성공 여부를 즉시 판단할 수 있습니다.

  • 2xx (성공): 클라이언트의 요청이 서버에 정상적으로 수신되어 처리되었음을 뜻합니다. 200 OK는 가장 널리 쓰이는 표준 성공 응답이며, 201 Created는 새로운 자원이 성공적으로 생성되었음을 알립니다.
  • 3xx (리다이렉션): 요청을 완료하기 위해 클라이언트가 추가 조치를 취해야 함을 나타냅니다. 301 Moved Permanently나 308 Permanent Redirect는 대상 자원의 주소가 영구히 바뀌었으므로 새 주소로 다시 요청하라는 신호입니다.
  • 4xx (클라이언트 오류): 클라이언트가 보낸 요청 문법이나 권한에 문제가 있음을 가리킵니다. 400 Bad Request는 잘못된 매개변수나 형식 오류를 뜻하고, 401 Unauthorized는 인증 정보 누락, 403 Forbidden은 접근 권한 부족, 404 Not Found는 지정한 경로에 자원이 없음을 알립니다.
  • 5xx (서버 오류): 클라이언트의 요청은 유효했으나 서버 내부 처리 과정에서 예외가 발생한 상황입니다. 500 Internal Server Error는 처리되지 않은 서버 애플리케이션 예외를 나타내며, 502 Bad Gateway와 504 Gateway Timeout은 프록시나 게이트웨이 서버가 상류 서버와 통신하지 못할 때 반환됩니다.

curl로 관찰하는 실제 전송 패킷

터미널에서 널리 쓰이는 curl 도구에 -i 옵션을 부여하면, 브라우저 뒤에 숨겨진 응답 헤더와 본문의 경계를 직접 확인할 수 있습니다.

curl -i -s https://httpbin.org/get

테스트용 공용 엔드포인트에 위 명령을 전송하면 다음과 같은 예시 출력이 터미널에 나타납니다.

HTTP/2 200 
date: Sat, 03 Oct 2026 05:30:00 GMT
content-type: application/json
content-length: 258
server: gunicorn
 
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/8.5.0"
  }, 
  "url": "https://httpbin.org/get"
}

첫 번째 줄의 200 상태 코드는 서버가 요청을 정상 처리했음을 나타냅니다. 이어지는 content-type: application/json 헤더는 본문이 JSON 형식임을 알려주며, 빈 줄 뒤에 실제 서버가 반환한 JSON 데이터가 나타납니다.

무상태 프로토콜의 한계와 세션 유지

HTTP의 가장 결정적인 아키텍처 특성은 상태 비저장성(Statelessness)입니다. 서버는 이전 요청에서 어떤 일이 일어났는지 독립적으로 기억하지 않습니다. 방금 전 요청에서 사용자가 누구였는지, 어떤 페이지를 보았는지 기록해 두지 않고 모든 요청을 완전히 새로운 독립 작업으로 취급합니다. 이 설계 덕분에 서버는 수많은 클라이언트의 접속 상태를 메모리에 무겁게 유지할 필요가 없고, 트래픽이 폭증할 때 수십 대의 서버로 요청을 분산하기가 매우 수월합니다.

그러나 로그인 유지, 쇼핑몰 장바구니, 결제 절차처럼 연속된 사용자 흐름을 구현하려면 상태 보존이 필수적입니다. 웹 기술은 이 간극을 메우기 위해 쿠키(Cookie), 세션(Session), 토큰(JWT) 기술을 도입했습니다. 클라이언트가 최초 로그인 시 서버로부터 발급받은 식별 토큰을 보관해 두었다가, 이후 보내는 모든 요청의 Cookie 또는 Authorization 헤더에 실어 전송함으로써 무상태 규약 위에서 상태를 안정적으로 유지합니다.

이러한 텍스트 기반 무상태 규약은 최신 분산 시스템과 AI 에이전트 환경에서도 도구를 연결하는 전송 표준으로 활발하게 쓰입니다. 예를 들어 Model Context Protocol로 도구 연결하기 규격은 전송 계층 중 하나로 Streamed HTTP를 공식 지원하며, 에이전트 클라이언트가 표준 HTTP POST 요청과 서버 전송 이벤트(SSE)를 통해 외부 도구에 JSON-RPC 명령을 전달하고 실행 결과를 돌려받을 수 있게 설계되었습니다. 기존 웹 인프라의 라우터, 프록시, 보안 방화벽을 그대로 통과할 수 있어 별도의 전용 네트워크 장비 없이도 에이전트 도구 생태계를 구축할 수 있습니다.

[참고] 바이너리 프레이밍과 프로토콜 발전

HTTP/1.1은 줄바꿈과 텍스트로 메시지 경계를 구분하지만, HTTP/2와 HTTP/3은 바이너리 프레임 단위로 메시지를 쪼개어 단일 연결 위에서 다중화(Multiplexing)합니다. 전송 계층의 효율이 극대화되었음에도 시작줄, 헤더, 상태 코드라는 논리적 메시지 구조는 그대로 보존됩니다.

참고 문서

설명이 어렵거나 잘못된 부분을 발견하셨나요?

문서 수정 의견 보내기