이 문서의 과거 버전 (r1)을 보고 있습니다. 수정일: 2026.02.12 22:09
HTTP(Hypertext Transfer Protocol)는 월드 와이드 웹(WWW)에서 데이터를 주고받기 위해 사용되는 통신 프로토콜이다. 주로 HTML 문서, 이미지, 동영상, JSON 데이터 등 다양한 형태의 자원을 전송하는 데 쓰인다. HTTP는 인터넷 프로토콜 스위트(TCP/IP)의 응용 계층 프로토콜로, 일반적으로 TCP 포트 80번을 사용하여 통신한다.
HTTP의 핵심은 클라이언트-서버 모델에 기반한 요청-응답 프로토콜이라는 점이다. 사용자의 웹 브라우저와 같은 클라이언트가 서버에게 특정 자원을 요청하면, 서버는 해당 요청을 처리하고 적절한 응답을 돌려준다. 이 프로토콜은 본래 하이퍼텍스트 문서를 교환하기 위해 설계되었지만, 오늘날에는 웹을 구성하는 모든 형태의 데이터 교환에 광범위하게 활용된다.
HTTP는 상태 비저장 프로토콜(Stateless Protocol)로 설계되었다. 이는 각각의 요청이 독립적으로 처리되며, 서버가 이전 요청의 상태를 유지하지 않음을 의미한다. 이러한 특성은 서버의 부하를 줄이고 확장성을 높이는 장점이 있지만, 사용자의 상태(예: 로그인 정보)를 관리하기 위해서는 쿠키나 세션과 같은 추가 메커니즘을 필요로 한다.
HTTP의 발전은 웹의 진화와 궤를 같이한다. 초기 버전인 HTTP/0.9부터 시작하여, 표준화된 HTTP/1.0, 지속 연결과 호스트 헤더를 도입한 HTTP/1.1, 성능을 대폭 개선한 HTTP/2, 그리고 TCP 대신 QUIC 프로토콜을 사용하는 HTTP/3까지 지속적으로 진화해왔다. 또한 보안 강화를 위해 HTTP에 암호화와 인증 계층을 추가한 HTTPS가 현재 웹의 표준으로 자리 잡았다.
HTTP는 월드 와이드 웹에서 데이터를 주고받기 위해 사용되는 애플리케이션 계층 프로토콜이다. 이 프로토콜의 핵심은 클라이언트-서버 모델 위에서 동작하는 요청(Request)과 응답(Response)의 상호작용이다. 클라이언트(일반적으로 웹 브라우저)가 서버에게 특정 자원을 요청하면, 서버는 해당 요청을 처리하고 적절한 응답을 돌려준다. 이 통신은 기본적으로 TCP/IP 연결을 통해 이루어지며, 80번 포트를 기본으로 사용한다.
통신의 기본 단위는 요청 메시지와 응답 메시지이다. 요청 메시지는 수행할 동작을 나타내는 HTTP 메서드(예: GET, POST), 요청 대상의 URL, 그리고 HTTP 헤더로 구성된다. 응답 메시지는 요청의 성공 여부를 나타내는 상태 코드(Status Code), 상태 메시지, 응답 헤더, 그리고 요청된 자원(본문)을 포함한다. 상태 코드는 200(성공), 404(찾을 수 없음), 500(서버 내부 오류)과 같이 세 자리 숫자로 표현되며, 응답의 결과를 빠르게 파악할 수 있게 한다.
HTTP는 기본적으로 무상태(Stateless) 프로토콜이다. 이는 각 요청이 독립적으로 처리되며, 서버가 이전 요청의 상태를 유지하지 않음을 의미한다. 이는 서버의 설계를 단순하게 하지만, 사용자의 로그인 상태나 장바구니 정보와 같은 연속적인 상태를 관리하기 위해서는 쿠키(Cookie)나 세션(Session)과 같은 추가 메커니즘이 필요하다. 또한, 전송되는 데이터가 평문으로 노출될 수 있어 보안에 취약하므로, 중요한 정보를 교환할 때는 TLS 암호화를 적용한 HTTPS를 사용한다.
HTTP는 기본적으로 클라이언트-서버 모델을 따르는 프로토콜이다. 이 모델에서 통신은 항상 요청을 보내는 클라이언트와 그 요청에 대한 응답을 제공하는 서버라는 두 개의 구별된 역할로 구성된다. 일반적으로 클라이언트는 사용자 에이전트, 즉 웹 브라우저나 모바일 앱과 같은 소프트웨어를 말한다. 서버는 웹 서버라고 불리며, 클라이언트가 요청한 HTML 문서, 이미지, 스타일시트, 자바스크립트 파일 등의 자원을 호스팅하고 제공하는 역할을 담당한다.
이 모델의 핵심은 통신이 항상 클라이언트의 요청으로 시작된다는 점이다. 서버는 클라이언트의 요청 없이 자발적으로 데이터를 보내지 않는다[1]. 이는 단방향적인 요청-응답 사이클로, 하나의 요청에는 하나의 응답이 대응된다. 이러한 구조는 인터넷 초기의 단순한 문서 검색 목적에 잘 부합했으며, 웹의 기본적인 작동 방식을 정의한다.
클라이언트와 서버는 서로 다른 호스트 머신에서 실행되며, 일반적으로 인터넷이나 인트라넷과 같은 네트워크를 통해 연결된다. 이들의 관계는 다대일(n:1) 구조를 형성할 수 있다. 즉, 수많은 클라이언트가 동시에 하나의 서버에 접속하여 자원을 요청할 수 있다. 서버는 이러한 동시 요청들을 처리하고 적절한 응답을 각 클라이언트에게 독립적으로 반환해야 한다.
역할 | 설명 | 주요 예시 |
|---|---|---|
클라이언트 | 서버에게 자원을 요청(HTTP 요청)하는 주체 | 웹 브라우저, 모바일 앱, API 호출 프로그램 |
서버 | 클라이언트의 요청을 받아 처리하고 응답(HTTP 응답)을 반환하는 주체 | 아파치 HTTP 서버, Nginx, Microsoft IIS |
이 모델은 웹 아키텍처의 근간을 이루며, RESTful API와 같은 현대적인 웹 서비스 설계의 기본 원칙이 된다.
HTTP 통신은 클라이언트-서버 모델을 기반으로 하며, 이 상호작용의 핵심은 요청과 응답이라는 두 가지 기본 메시지로 구성된다. 클라이언트(예: 웹 브라우저)가 서버에게 자원을 요청하면, 서버는 이에 대한 결과를 응답으로 돌려보낸다. 이 교환은 항상 클라이언트의 요청으로 시작되며, 서버는 단독으로 클라이언트에게 데이터를 보낼 수 없다.
HTTP 요청 메시지는 다음과 같은 구조를 가진다.
* 요청 라인: 사용할 HTTP 메서드(예: GET, POST), 요청 대상이 되는 자원의 경로(URL), 그리고 사용 중인 HTTP 버전을 명시한다.
* 요청 헤더: 요청에 대한 부가 정보를 담는다. 예를 들어, 클라이언트의 종류(User-Agent), 선호하는 언어(Accept-Language), 서버에 전송할 데이터의 형식(Content-Type) 등을 포함할 수 있다.
* 본문: 요청에 실어 보낼 데이터가 위치한다. POST나 PUT 메서드로 서버에 데이터를 제출할 때 주로 사용되며, GET 요청은 일반적으로 본문을 가지지 않는다.
서버는 요청을 처리한 후 HTTP 응답 메시지를 생성하여 클라이언트에게 보낸다. 응답 메시지의 구조는 다음과 같다.
* 상태 라인: 사용 중인 HTTP 버전과 가장 중요한 상태 코드 및 상태 문구를 포함한다. 상태 코드는 요청의 성공(200), 클라이언트 오류(404), 서버 오류(500) 등을 즉시 알려준다.
* 응답 헤더: 응답에 대한 메타데이터를 제공한다. 서버 정보(Server), 응답 데이터의 형식(Content-Type), 데이터 크기(Content-Length), 캐시 지시사항(Cache-Control) 등이 여기에 해당한다.
* 본문: 요청된 자원의 실제 데이터가 담겨 있다. HTML 문서, JSON 데이터, 이미지, 동영상 등이 이에 해당하며, 상태 코드가 오류를 나타낼 경우에는 오류 메시지가 본문에 포함될 수 있다.
구성 요소 | 요청(Request) | 응답(Response) |
|---|---|---|
시작 라인 | 메서드, 경로, HTTP 버전 (예: | HTTP 버전, 상태 코드, 상태 문구 (예: |
헤더 |
|
|
본문 | 요청된 자원(HTML, JSON 등) 또는 오류 메시지 |
이러한 요청-응답의 단순한 구조는 HTTP를 유연하고 확장 가능하게 만들었으며, 웹의 폭발적인 성장을 가능하게 한 기반이 되었다. 모든 웹 페이지 로딩, API 호출, 파일 업로드 등은 수많은 이러한 요청과 응답의 연속으로 이루어진다.
HTTP 상태 코드는 서버가 클라이언트의 요청에 대한 처리 결과를 세 자리 숫자로 나타낸다. 상태 코드는 응답의 첫 번째 줄에 위치하며, 주로 다섯 가지 클래스로 구분된다. 각 클래스의 첫 번째 숫자가 그 범주를 정의한다.
코드 범위 | 클래스 | 의미 |
|---|---|---|
1xx | 정보 응답 | 요청을 받았으며, 프로세스를 계속 진행한다. |
2xx | 성공 | 요청이 성공적으로 수신되고 이해되었다. |
3xx | 리다이렉션 | 요청을 완료하기 위해 추가 조치가 필요하다. |
4xx | 클라이언트 오류 | 요청에 문법 오류가 있거나 처리할 수 없다. |
5xx | 서버 오류 | 서버가 유효한 요청을 수행하는 데 실패했다. |
가장 일반적으로 사용되는 상태 코드 몇 가지를 살펴보면 다음과 같다. 성공을 의미하는 200 OK는 요청이 정상적으로 처리되었음을 알린다. 리다이렉션의 대표적인 예로 301 Moved Permanently는 요청한 리소스의 URL이 영구적으로 이동되었음을, 302 Found는 일시적으로 이동되었음을 나타낸다. 클라이언트 측 오류인 404 Not Found는 서버가 요청한 리소스를 찾을 수 없을 때 사용된다. 서버 내부 오류를 나타내는 500 Internal Server Error는 서버가 요청을 처리하는 과정에서 예상치 못한 상황을 맞았을 때 발생한다.
상태 코드는 HTTP 헤더와 함께 작동하여 클라이언트에게 다음에 취할 행동을 지시한다. 예를 들어, 3xx 코드는 대개 Location 헤더와 함께 제공되어 클라이언트가 자동으로 새로운 주소로 요청을 보내게 한다. 4xx 오류는 주로 요청의 형식이나 권한에 문제가 있음을 의미하므로, 클라이언트가 요청을 수정해야 한다. 반면 5xx 오류는 서버의 문제이므로, 클라이언트는 동일한 요청을 재시도하기보다는 일정 시간 후에 시도하는 것이 일반적이다.
HTTP 메서드는 클라이언트가 서버에 요청하는 동작의 종류 또는 의도를 나타내는 동사이다. 이를 통해 서버는 클라이언트가 수행하고자 하는 작업을 이해하고 그에 맞는 적절한 처리를 한다. 주요 메서드로는 자원을 조회하는 GET, 새로운 자원을 제출하는 POST, 자원을 전체 교체하는 PUT, 자원을 삭제하는 DELETE 등이 있다.
각 메서드는 고유한 의미와 특성을 가지며, 안전성과 멱등성이라는 속성으로 분류된다. 안전한 메서드는 서버의 상태를 변경하지 않는 읽기 전용 작업을 의미하며, GET과 HEAD, OPTIONS가 이에 해당한다. 멱등성은 같은 요청을 여러 번 보내도 한 번 보낸 것과 같은 효과를 보장하는 속성이다. GET, PUT, DELETE는 멱등하지만, POST는 일반적으로 멱등하지 않다.
메서드 | 의미 | 주요 특징 |
|---|---|---|
자원 조회 | 안전함, 멱등함, 캐시 가능 | |
자원 제출/생성 | 일반적으로 멱등하지 않음, 요청 본문 포함 | |
자원 전체 교체/생성 | 멱등함, 요청 본문 포함 | |
자원 삭제 | 멱등함 | |
GET과 동일하지만 본문 없이 헤더만 응답 | 안전함, 멱등함 | |
대상 자원에 대한 통신 옵션 설명 | 안전함 | |
자원의 부분적 수정 | 일반적으로 멱등하지 않음 |
이 외에도 TRACE나 CONNECT와 같은 메서드도 존재한다. 현대의 웹 애플리케이션과 RESTful API 설계에서는 이러한 메서드의 의미론적 특성을 준수하는 것이 중요하며, 이를 통해 표준화되고 예측 가능한 인터페이스를 제공한다.
GET 메서드는 지정된 URI의 리소스를 조회하는 데 사용된다. 서버에 전송할 데이터는 쿼리 문자열 형태로 URL에 포함되며, 이는 주소창에 직접 노출된다. GET 요청은 멱등성을 가지며, 동일한 요청을 여러 번 수행해도 서버의 상태가 변하지 않는다. 주로 웹 페이지를 불러오거나 검색 결과를 요청할 때 활용된다.
POST 메서드는 서버에 데이터를 제출하여 새로운 리소스를 생성하거나 기존 프로세스를 처리하도록 요청한다. 전송할 데이터는 요청의 본문에 담겨 보내지며, URL에 노출되지 않는다. POST 요청은 멱등하지 않으며, 동일한 요청을 반복하면 새로운 리소스가 반복적으로 생성될 수 있다. 게시글 작성이나 파일 업로드와 같은 작업에 주로 사용된다.
PUT 메서드는 요청에 포함된 데이터를 사용하여 지정된 URI에 리소스를 생성하거나 완전히 대체한다. 전체 리소스를 업데이트하는 데 사용되며, 요청 본문에 새 리소스의 전체 표현을 담아 보낸다. PUT 요청은 멱등성을 가진다. 동일한 PUT 요청을 여러 번 수행해도 최종 결과는 동일하다.
DELETE 메서드는 지정된 URI의 리소스를 삭제하도록 서버에 요청한다. 성공적인 삭제 후 일반적으로 클라이언트는 해당 리소스에 더 이상 접근할 수 없다. DELETE 요청도 멱등성을 가진다. 이미 삭제된 리소스에 대해 DELETE 요청을 다시 보내더라도, 리소스가 없다는 결과를 받을 뿐 서버 상태는 추가로 변하지 않는다.
이 네 가지 메서드는 RESTful API 설계의 기본을 이루며, 각각의 고유한 의미와 특성에 따라 적절하게 사용되어야 한다.
HTTP 메서드 중 GET, POST, PUT, DELETE 외에도, 리소스에 대한 메타정보를 얻거나 서버의 기능을 확인하는 데 사용되는 보조적인 메서드들이 존재한다. 대표적으로 HEAD, OPTIONS, PATCH가 이에 해당한다.
HEAD 메서드는 GET 요청과 동일한 형태로 요청을 보내지만, 서버는 응답 본문을 제외한 상태 코드와 HTTP 헤더만을 반환한다. 이는 리소스의 실제 내용을 다운로드하지 않고도 해당 리소스의 존재 여부, 최종 수정 시간, 크기, 미디어 타입 등의 메타데이터를 확인할 때 유용하다. 예를 들어, 큰 파일의 다운로드 전에 파일 크기를 확인하거나, 캐시 유효성을 검사할 때 사용된다.
OPTIONS 메서드는 특정 URI에 대해 서버가 지원하는 통신 옵션을 확인하는 데 사용된다. 주로 특정 리소스에 대해 허용된 메서드(GET, POST 등) 목록을 확인할 때 활용된다. 서버는 응답 헤더의 Allow 필드에 지원하는 메서드 목록을 포함하여 응답한다. 이 메서드는 CORS(Cross-Origin Resource Sharing) 사전 요청에서도 핵심적인 역할을 한다[2].
PATCH 메서드는 리소스의 부분적인 수정을 위해 사용된다. PUT 메서드가 리소스를 전체 교체하는 것과 달리, PATCH는 리소스의 일부 필드만을 변경하는 데 적합하다. 클라이언트는 변경하고자 하는 부분에 대한 지시 사항을 JSON Patch나 JSON Merge Patch와 같은 특정 형식으로 본문에 담아 서버에 보낸다. 서버는 이 지시에 따라 리소스를 부분적으로 업데이트한다.
HTTP 헤더는 HTTP 요청과 응답에 부가적인 정보를 담는 부분이다. 이 정보는 클라이언트와 서버가 통신을 어떻게 처리해야 하는지에 대한 지시사항이나, 전송되는 데이터(엔티티) 자체에 대한 메타데이터를 포함한다. 헤더는 콜론(:)으로 구분된 이름-값 쌍의 형태로 구성되며, 각 헤더는 고유한 목적과 의미를 가진다.
헤더는 그 역할과 사용되는 컨텍스트에 따라 크게 네 가지 범주로 분류된다. 일반 헤더는 요청과 응답 모두에서 사용될 수 있는 헤더로, 메시지 전체에 적용되는 정보를 담는다. 대표적으로 메시지의 날짜와 시간을 나타내는 Date, 연결 관리 방식을 지정하는 Connection 등이 있다. 요청 헤더는 클라이언트가 서버에게 보내는 요청에만 포함되는 헤더로, 클라이언트의 정보나 요청의 조건을 서버에 알린다. 사용자의 브라우저와 운영체제를 식별하는 User-Agent, 선호하는 언어를 나타내는 Accept-Language, 조건부 요청을 위한 If-Modified-Since 등이 이에 속한다.
응답 헤더는 서버의 응답에 포함되어, 응답에 대한 부가 정보를 제공한다. 서버 소프트웨어를 식별하는 Server, 클라이언트가 이후 요청에 포함시켜야 하는 세션 식별자인 Set-Cookie, 리소스의 새 위치를 알려주는 Location 등이 응답 헤더의 예시이다. 마지막으로 엔티티 헤더는 요청 또는 응답의 본문(바디)에 해당하는 리소스 자체에 대한 설명을 담는다. 본문 데이터의 미디어 타입(MIME 타입)을 정의하는 Content-Type, 데이터의 길이(바이트 단위)를 나타내는 Content-Length, 데이터가 마지막으로 수정된 시간을 알리는 Last-Modified 등이 핵심적인 엔티티 헤더에 해당한다.
헤더 유형 | 주요 역할 | 대표적인 헤더 예시 |
|---|---|---|
일반 헤더 | 요청과 응답 모두에서 사용 가능한 공통 정보 |
|
요청 헤더 | 클라이언트의 정보와 요청 조건 전달 |
|
응답 헤더 | 서버의 정보와 응답에 대한 지시사항 제공 |
|
엔티티 헤더 | 전송되는 데이터(본문)의 메타데이터 설명 |
|
이러한 헤더들은 캐싱 정책을 제어하고, 인증 정보를 전달하며, 콘텐츠 협상을 수행하고, CORS 정책을 관리하는 등 웹 통신의 거의 모든 측면을 조율하는 데 핵심적인 역할을 한다.
일반 헤더는 HTTP 요청과 응답 메시지 모두에서 사용될 수 있는 헤더 필드이다. 이 헤더들은 메시지의 전송 자체와 관련된 정보를 담고 있으며, 특정 요청이나 응답의 콘텐츠보다는 메시지 처리를 위한 일반적인 제어 데이터를 제공한다.
주요 일반 헤더에는 다음과 같은 것들이 있다.
헤더 필드 | 설명 |
|---|---|
| 메시지가 생성된 날짜와 시간을 나타낸다. |
| |
| 현재 연결에 대한 옵션을 제어한다[4]. |
| HTTP/1.0과의 하위 호환성을 위한 캐시 제어 지시어로, 주로 |
| 메시지 본문 뒤에 추가 헤더 필드가 올 것임을 알린다. |
| 메시지 본문의 안전한 전송을 위해 적용된 인코딩 형식을 지정한다[5]. |
| 클라이언트가 다른 프로토콜로 업그레이드하도록 제안한다. |
|
이러한 헤더들은 클라이언트와 서버 간의 통신 흐름을 관리하는 데 중요한 역할을 한다. 예를 들어, Cache-Control은 네트워크 트래픽을 줄이고 성능을 향상시키는 캐시 동작을 결정하며, Connection은 TCP 연결의 생명주기를 관리한다. Transfer-Encoding: chunked는 서버가 응답 본문의 전체 크기를 미리 알지 못하는 상황에서 데이터를 스트리밍 방식으로 전송할 수 있게 해준다.
요청 헤더는 클라이언트가 서버에게 요청을 보낼 때 부가적인 정보를 제공하는 데 사용된다. 이 헤더들은 요청의 컨텍스트, 클라이언트의 선호도, 처리 조건 등을 서버에 알려주어, 서버가 더 적절한 응답을 생성할 수 있도록 돕는다.
주요 요청 헤더는 다음과 같이 분류할 수 있다.
헤더 이름 | 주요 역할 |
|---|---|
| 요청이 전송되는 서버의 도메인 이름과 포트 번호를 지정한다. HTTP/1.1에서는 필수 헤더이다. |
| 요청을 보내는 클라이언트 애플리케이션(브라우저, 운영체제 등)에 대한 정보를 담는다. |
| 클라이언트가 이해할 수 있는 콘텐츠 MIME 타입을 서버에 알린다. (예: |
| 클라이언트가 선호하는 자연 언어를 나타낸다. (예: |
| 클라이언트가 이해할 수 있는 콘텐츠 압축 방식을 지정한다. (예: |
| |
| |
| 현재 요청을 보내기 직전에 클라이언트가 머물렀던 웹 페이지의 주소를 나타낸다. |
| 조건부 요청에 사용되며, 지정된 날짜 이후에 리소스가 변경되었을 때만 응답을 보내도록 서버에 요청한다. |
이 외에도 Content-Type(요청 본문의 미디어 타입 지정, POST나 PUT 요청 시 사용)이나 Content-Length(요청 본문의 크기 표시)와 같은 헤더는 요청에 본문이 있을 때 중요한 역할을 한다. 또한 Cache-Control 헤더를 통해 클라이언트는 캐싱 정책을 서버에 힌트로 제공할 수 있다. 이러한 헤더들을 조합하여 클라이언트는 서버에게 자신의 상태, 능력, 의도를 효과적으로 전달한다.
응답 헤더는 서버가 클라이언트에게 보내는 HTTP 응답 메시지의 일부로, 응답에 대한 부가 정보를 담고 있다. 이 헤더들은 응답의 상태, 서버 정보, 응답 본문에 대한 메타데이터, 그리고 클라이언트가 응답을 어떻게 처리해야 하는지에 대한 지시 사항을 포함한다. 응답 헤더는 클라이언트가 서버로부터 받은 데이터를 올바르게 해석하고 처리하는 데 필수적인 역할을 한다.
주요 응답 헤더는 다음과 같이 분류할 수 있다.
헤더 이름 | 설명 |
|---|---|
| 요청을 처리한 서버 소프트웨어의 이름과 버전 정보를 나타낸다. 예: |
| 응답 메시지가 생성된 날짜와 시간을 GMT 기준으로 표시한다. |
| 주로 HTTP 상태 코드 3xx(리다이렉션) 응답에서 사용되며, 클라이언트가 요청을 재시도해야 할 새로운 URL을 지정한다. |
| 서버에서 클라이언트에게 쿠키를 설정하도록 지시한다. 이 헤더를 통해 세션 관리나 사용자 선호도 저장이 이루어진다. |
| 응답과 관련된 캐싱 정책을 정의한다. 예를 들어 |
| 특정 버전의 리소스를 식별하는 고유한 식별자(엔티티 태그)를 제공한다. 클라이언트가 이후 요청 시 |
| 서버에서 해당 리소스가 마지막으로 수정된 날짜와 시간을 나타낸다. 클라이언트는 이후 요청 시 |
| 응답 본문의 미디어 타입(MIME 타입)을 명시한다. 예: |
| 응답 본문의 크기를 바이트 단위로 나타낸다. |
| CORS 정책을 구현할 때 사용되며, 어떤 출처(도메인)에서 이 리소스에 접근할 수 있는지를 지정한다. |
이 외에도 WWW-Authenticate 헤더는 401 응답과 함께 사용되어 필요한 인증 방식을 알려주고, Retry-After 헤더는 서비스가 일시적으로 불가능할 때(503 상태 코드) 클라이언트가 재요청을 시도하기까지 기다려야 할 시간을 안내한다. 응답 헤더의 적절한 설정은 웹 성능 최적화, 보안 강화, 클라이언트와 서버 간 효율적인 통신을 보장하는 데 결정적인 요소가 된다.
엔티티 헤더는 HTTP 메시지의 본문, 즉 엔티티 바디에 포함된 리소스 자체에 대한 메타데이터를 설명하는 데 사용된다. 이 헤더들은 요청이나 응답에서 전송되는 실제 데이터(예: HTML 문서, 이미지 파일, JSON 데이터)의 특성, 예를 들어 콘텐츠 유형, 길이, 최종 수정 시간 등을 나타낸다. 엔티티 헤더는 HTTP/1.1 명세에서 정의되었으나, 이후 HTTP/2와 HTTP/3에서 이 개념은 '표현 헤더'로 진화했지만, 여전히 동일한 목적으로 기능한다.
주요 엔티티 헤더로는 Content-Type, Content-Length, Content-Encoding, Last-Modified 등이 있다. Content-Type 헤더는 엔티티 바디의 미디어 타입(예: text/html; charset=UTF-8, application/json)을 지정하여 클라이언트가 콘텐츠를 어떻게 해석해야 하는지 알려준다. Content-Length 헤더는 바디의 크기를 바이트 단위로 나타내어 전송의 완료 시점을 판단하는 데 중요하다. Content-Encoding은 데이터가 어떤 방식(예: gzip, deflate)으로 압축되었는지 표시하며, Last-Modified는 서버에서 해당 리소스가 마지막으로 수정된 날짜와 시간을 제공한다.
이 헤더들은 캐싱 및 조건부 요청과 밀접한 관계가 있다. 예를 들어, Last-Modified 헤더와 함께 사용되는 If-Modified-Since 요청 헤더는 클라이언트가 캐시에 저장된 리소스의 최신 여부를 확인할 수 있게 한다. 또한 Content-Length는 지속 연결에서 여러 메시지의 경계를 명확히 구분하는 데 필수적이다. 엔티티 헤더의 정확한 설정은 리소스의 효율적인 전송, 정확한 렌더링, 그리고 효과적인 캐시 관리를 보장한다.
다음은 대표적인 엔티티 헤더와 그 역할을 정리한 표이다.
헤더 | 설명 | 예시 값 |
|---|---|---|
| 엔티티 바디의 미디어 타입과 문자 인코딩을 지정한다. |
|
| 엔티티 바디의 크기(바이트)를 나타낸다. |
|
| 엔티티 바디에 적용된 압축 방식을 지정한다. |
|
| 엔티티 바디의 대상 청중을 위한 자연 언어를 지정한다. |
|
| 리소스가 서버에서 마지막으로 수정된 날짜와 시간을 나타낸다. |
|
| 응답이 더 이상 신선하지 않다고 간주되는 날짜/시간을 제공한다. |
|
HTTP는 1990년대 초 팀 버너스리에 의해 월드 와이드 웹의 핵심 프로토콜로 제안된 이후, 지속적인 발전을 거듭하며 여러 주요 버전을 통해 진화해왔다. 각 버전은 성능, 기능, 보안 측면에서 이전 버전의 한계를 극복하고 웹의 새로운 가능성을 열었다.
초기 버전인 HTTP/0.9는 극도로 단순한 프로토콜이었다. 단일 메서드인 GET만을 지원했으며, 헤더도 존재하지 않았다. 서버는 요청을 받으면 HTML 문서만을 평문으로 전송하고 연결을 닫았다. 1996년 공식적으로 명세가 발표된 HTTP/1.0은 프로토콜의 기초를 다졌다. 요청과 응답에 버전 번호, 상태 코드, HTTP 헤더 개념이 도입되었고, POST와 HEAD 메서드가 추가되었다. 또한 Content-Type 헤더를 통해 HTML 외의 다른 문서 형식(이미지, 동영상 등) 전송이 가능해지면서 웹이 멀티미디어 매체로 발전하는 계기가 되었다.
1997년 등장한 HTTP/1.1은 현재까지도 광범위하게 사용되는 표준 버전이다. 가장 중요한 개선점은 지속 연결과 파이프라이닝이다. 지속 연결은 하나의 TCP 연결을 통해 여러 요청과 응답을 주고받을 수 있게 하여 연결 설정/해제에 따른 오버헤드를 크게 줄였다. 또한 호스트 헤더가 필수가 되어 하나의 서버가 여러 도메인을 호스팅하는 가상 호스팅이 가능해졌다. 캐시 제어 메커니즘도 강화되었다. 그러나 요청을 순차적으로 처리해야 하는 HOL 블로킹 문제는 근본적으로 해결되지 않았다.
이러한 성능 병목 현상을 해결하기 위해 2015년 표준화된 HTTP/2는 프로토콜의 효율성을 혁신적으로 높였다. 텍스트 기반이 아닌 바이너리 프레이밍 계층을 도입하여 메시지를 더 작은 단위의 프레임으로 나누어 전송하고 다중화했다. 이를 통해 단일 연결 내에서 여러 요청과 응답을 병렬로 주고받을 수 있어 HOL 블로킹 문제를 해결했다. 또한 서버가 클라이언트 요청 없이 미리 리소스를 푸시할 수 있는 서버 푸시 기능과 헤더 압축을 지원한다. HTTP/2의 근본적인 변화는 전송 계층이 아닌 애플리케이션 계층에서 이루어졌다.
가장 최신 버전인 HTTP/3은 전송 계층 프로토콜 자체를 교체했다. 기존의 TCP 대신 구글이 개발한 QUIC 프로토콜을 사용한다. QUIC은 TLS 보안 계층을 기본적으로 내장하고, 연결 설정 시 발생하는 지연을 크게 줄였다. 가장 큰 장점은 TCP의 HOL 블로킹 문제를 전송 계층에서 해결한다는 점이다. 패킷 손실이 발생하더라도 다른 스트림의 데이터 전송에 영향을 주지 않아 불안정한 네트워크 환경에서도 더 나은 성능을 보인다. HTTP/3은 아직 도입 단계이지만, 점차 지원 범위가 확대되고 있다.
버전 | 발표 연도 | 주요 특징 |
|---|---|---|
HTTP/0.9 | 1991 | 단일 GET 메서드, 헤더 없음, HTML만 전송 |
HTTP/1.0 | 1996 | 버전 번호, 상태 코드, 헤더 도입, 메서드 확장 |
HTTP/1.1 | 1997 | 지속 연결, 호스트 헤더, 강화된 캐시 제어 (현재의 표준) |
HTTP/2 | 2015 | 바이너리 프레이밍, 멀티플렉싱, 헤더 압축, 서버 푸시 |
HTTP/3 | 2022 | QUIC 프로토콜 기반, TLS 내장, 전송 계층 HOL 블로킹 제거 |
HTTP/0.9는 1991년 팀 버너스리에 의해 제안된 최초의 HTTP 프로토콜 버전이다. 이 버전은 극도로 단순한 설계를 가지고 있었다. 클라이언트는 단일 GET 메서드만을 사용하여 요청을 보낼 수 있었고, 응답은 오직 HTML 문서의 본문만으로 구성되었다. HTTP 헤더나 상태 코드와 같은 개념이 존재하지 않았으며, 연결은 단일 요청-응답 후에 즉시 닫혔다.
1996년에 공개된 HTTP/1.0은 RFC 1945로 표준화되며 프로토콜을 크게 확장했다. 가장 중요한 변화는 요청(Request)과 응답(Response)에 HTTP 헤더를 도입한 것이다. 이를 통해 클라이언트와 서버가 교환하는 데이터에 대한 메타정보를 전달할 수 있게 되었다. 또한, 상태 코드가 추가되어 요청의 성공 또는 실패 원인을 클라이언트가 알 수 있게 되었고, POST와 HEAD와 같은 새로운 HTTP 메서드가 지원되기 시작했다.
HTTP/1.0은 멀티미디어 콘텐츠 처리 능력도 갖추게 되었다. Content-Type 헤더를 통해 HTML 외에도 이미지, 음악 파일 등 다양한 형식의 데이터를 주고받을 수 있게 되었고, Content-Length 헤더는 응답 본문의 크기를 미리 알려주어 연결 종료를 더 정확하게 관리할 수 있도록 했다. 그러나 여전히 주요한 한계는 남아있었는데, 기본적으로 각 요청마다 새로운 TCP 연결을 수립해야 했기 때문에 웹 페이지에 여러 리소스가 포함될 경우 성능 저하가 심각했다.
버전 | 주요 특징 | 한계 |
|---|---|---|
HTTP/0.9 | 단일 GET 메서드, HTML 본문만 응답, 헤더 없음 | 기능이 극히 제한적, 현대적 웹 사용 불가 |
HTTP/1.0 | 요청/응답 헤더 도입, 상태 코드 추가, 새로운 메서드(POST, HEAD) 지원, Content-Type으로 다양한 콘텐츠 지원 | 기본적으로 요청마다 새로운 연결 필요(비지속적 연결), 성능 이슈 존재 |
HTTP/1.1은 1997년 RFC 2068로 처음 표준화되었으며, 1999년 RFC 2616으로 개정되었다. 이 버전은 HTTP/1.0의 주요 한계를 해결하고 웹의 폭발적 성장을 뒷받침하는 핵심 프로토콜로 자리 잡았다. 가장 중요한 개선점은 지속 연결과 파이프라이닝을 공식적으로 도입한 것이다. 이를 통해 단일 TCP 연결을 통해 여러 요청과 응답을 순차적으로 처리할 수 있게 되어, 매번 연결을 설정하고 종료하는 데 드는 오버헤드를 크게 줄였다.
HTTP/1.1은 호스트 기반 가상 호스팅을 공식적으로 지원하기 위해 Host 헤더를 필수 항목으로 지정했다. 이는 하나의 서버(하나의 IP 주소)가 여러 도메인을 호스팅할 수 있게 하는 데 결정적이었다. 또한 캐시 제어 메커니즘을 강화하여 Cache-Control, ETag, If-None-Match 같은 새로운 헤더를 도입해, 콘텐츠의 신선도 검증과 효율적인 캐싱을 가능하게 했다.
프로토콜의 신뢰성과 기능을 높이기 위해 새로운 HTTP 메서드인 OPTIONS, PUT, DELETE, TRACE, CONNECT가 추가되었고, 범위 요청을 위한 Range와 Accept-Ranges 헤더도 지원되기 시작했다. 이로 인해 대용량 파일의 일부만 요청하거나 다운로드를 중단한 지점에서 재개하는 것이 가능해졌다.
그러나 HTTP/1.1에도 근본적인 문제점이 남아 있었다. 특히 HOL 블로킹으로 인해, 하나의 연결 내에서 요청과 응답이 반드시 순차적으로 처리되어 앞선 요청의 처리가 지연되면 뒤의 요청들도 대기해야 했다. 이 성능 한계를 해결하기 위한 다양한 우회 기술(예: 도메인 샤딩, 이미지 스프라이트)이 등장했으며, 결국 이러한 문제들은 후속 버전인 HTTP/2와 HTTP/3의 개발 동기가 되었다.
HTTP/2는 2015년 공식 표준으로 채택된 HTTP 프로토콜의 주요 개정판이다. 이전 버전인 HTTP/1.1의 한계를 해결하고 현대 웹의 성능 요구사항을 충족시키기 위해 설계되었다. 핵심 목표는 지연 시간을 줄이고 처리량을 높이는 것이었다.
주요 기술적 특징은 다음과 같다. 첫째, 단일 TCP 연결 내에서 여러 요청과 응답을 동시에 다중화할 수 있는 이진 프레이밍 계층을 도입했다. 이로 인해 HTTP/1.1의 연결당 하나의 요청-응답 처리 방식에서 발생하는 헤드 오브 라인 블로킹 문제가 해소되었다. 둘째, 서버가 클라이언트의 요청 없이도 리소스를 사전에 푸시할 수 있는 서버 푸시 기능을 제공한다. 이를 통해 관련된 추가 자산(예: 스타일시트, 스크립트)을 예측하여 전송함으로써 페이지 로딩 시간을 단축할 수 있다. 셋째, 헤더 압축을 위해 HPACK 방식을 사용하여 반복되는 헤더 필드의 오버헤드를 크게 줄였다.
특징 | 설명 | 이점 |
|---|---|---|
텍스트 기반이 아닌 이진 형식으로 메시지를 프레이밍한다. | 파싱이 빠르고 효율적이며 오류 가능성이 낮다. | |
단일 연결 내 독립적인 양방향 바이트 스트림. | 다중화를 통해 지연을 줄이고 효율성을 높인다. | |
HPACK 알고리즘을 사용한 헤더 압축. | 중복 헤더 제거로 오버헤드를 대폭 감소시킨다. | |
클라이언트 요청을 기다리지 않고 서버가 리소스를 푸시한다. | 추가 왕복 시간을 제거하여 로딩 성능을 향상시킨다. |
이러한 개선으로 HTTP/2는 웹 페이지 로드 시간을 현저히 단축시켰으며, 특히 많은 수의 작은 리소스를 요구하는 현대 웹사이트에 적합하다. 그러나 여전히 TCP 계층의 혼잡 제어 및 패킷 손실 시의 지연에 영향을 받는다는 한계가 존재했으며, 이는 이후 QUIC 프로토콜을 기반으로 한 HTTP/3의 개발로 이어지는 동기가 되었다.
HTTP/3은 월드 와이드 웹에서 정보를 교환하기 위한 HTTP의 세 번째 주요 버전이다. 2022년 6월 IETF에 의해 RFC 9114로 표준화되었다. 이전 버전들과의 가장 근본적인 차이는 하위 전송 계층 프로토콜로 TCP 대신 QUIC을 사용한다는 점이다.
QUIC은 UDP 위에 구축된 프로토콜로, TCP의 핸드셰이크 지연과 HOL 블로킹 문제를 해결하도록 설계되었다. HTTP/3 연결은 일반적으로 TCP와 TLS를 결합한 방식보다 빠른 초기 연결 설정을 제공한다. 이는 QUIC이 보안 연결 설정을 핸드셰이크 과정에 통합했기 때문이다. 또한, 멀티플렉싱된 스트림 간의 독립성으로 인해 패킷 손실이 발생해도 다른 스트림의 데이터 전송이 차단되지 않는다.
주요 특징은 다음과 같다.
특징 | 설명 |
|---|---|
전송 프로토콜 | |
연결 설정 | TLS 1.3이 기본으로 통합되어 지연 시간 감소 |
멀티플렉싱 | 스트림 간 HOL 블로킹 제거 |
연결 마이그레이션 | 네트워크가 변경되어도(예: Wi-Fi에서 셀룰러로) 연결 유지 |
오류 수정 |
HTTP/3은 점진적으로 도입되고 있으며, 많은 주요 CDN 및 브라우저 벤더들이 이미 지원한다. 그러나 네트워크 중간 장치(방화벽, 로드 밸런서 등)가 UDP 기반의 QUIC 트래픽을 제대로 처리하지 못할 경우 연결 문제가 발생할 수 있다. 이전 버전과의 호환성을 위해 서버는 종종 HTTP/1.1, HTTP/2, HTTP/3을 모두 지원하는 방식으로 배포된다.
상태 관리와 세션은 HTTP가 기본적으로 상태를 유지하지 않는 무상태 프로토콜이라는 특성을 보완하기 위한 기술이다. 웹 애플리케이션에서 사용자의 로그인 상태나 장바구니 정보처럼 여러 요청에 걸쳐 데이터를 유지해야 할 필요가 있을 때 사용된다. 이를 구현하는 주요 수단은 쿠키와 세션이다.
쿠키는 서버가 사용자의 웹 브라우저에 저장하는 작은 데이터 조각이다. 서버는 HTTP 응답의 Set-Cookie 헤더를 통해 쿠키를 전송하면, 브라우저는 이를 저장한 후 이후 같은 서버로 보내지는 모든 HTTP 요청에 Cookie 헤더를 자동으로 포함시킨다. 쿠키는 주로 세션 식별자(Session ID), 사용자 선호 설정, 추적 정보 등을 저장하는 데 사용된다. 그러나 클라이언트 측에 저장되기 때문에 보안에 민감한 정보는 저장하지 않는 것이 원칙이다.
반면 세션은 주로 서버 측에서 상태 정보를 관리하는 메커니즘이다. 일반적인 흐름은 다음과 같다.
1. 클라이언트가 로그인 등의 요청을 보낸다.
2. 서버는 고유한 세션 ID를 생성하고, 이를 키로 사용하여 서버의 메모리나 데이터베이스에 사용자 상태 정보를 저장한다.
3. 서버는 생성된 세션 ID를 클라이언트의 쿠키로 전송한다.
4. 클라이언트는 이후 요청마다 이 쿠키(세션 ID)를 서버에 보낸다.
5. 서버는 받은 세션 ID를 확인하여 해당 사용자의 상태 정보를 찾아 요청을 처리한다.
쿠키와 세션의 주요 차이점은 다음과 같다.
특성 | 쿠키 | 세션 |
|---|---|---|
저장 위치 | 클라이언트(웹 브라우저) | 서버 |
저장 형식 | 텍스트 파일 | 서버 메모리 또는 데이터베이스 |
용량 제한 | 도메인당 약 4KB, 개수 제한 있음 | 서버 리소스에 따라 다름 |
보안 | 상대적으로 낮음(사용자 조작 가능) | 상대적으로 높음(정보가 서버에 있음) |
생명주기 | 브라우저 설정에 따라 만료일 지정 가능 | 일반적으로 브라우저 종료 시 또는 타임아웃 |
이 두 기술은 상호 보완적으로 사용되며, 현대의 대부분의 웹 애플리케이션은 세션 ID를 쿠키에 담아 전송하는 방식을 채택하여 상태를 관리한다.
쿠키는 HTTP가 기본적으로 무상태(Stateless) 프로토콜이라는 한계를 보완하기 위해 도입된 상태 정보 관리 메커니즘이다. 웹 서버가 사용자의 웹 브라우저를 통해 클라이언트의 로컬에 작은 데이터 조각을 저장하고, 이후 동일 서버에 대한 요청 시 그 데이터를 함께 전송하도록 한다. 이를 통해 서버는 여러 요청에 걸쳐 사용자를 식별하거나 세션을 유지할 수 있다.
쿠키의 동작은 주로 HTTP 헤더를 통해 이루어진다. 서버는 클라이언트에게 응답을 보낼 때 Set-Cookie 헤더를 포함시켜 쿠키를 생성하거나 갱신하도록 지시한다. 이후 해당 클라이언트는 동일 도메인에 대한 모든 요청에 자동으로 Cookie 헤더를 포함시켜 저장된 쿠키 데이터를 서버로 전송한다. 쿠키는 일반적으로 다음과 같은 속성을 가진다.
속성 | 설명 |
|---|---|
이름(Name)과 값(Value) | 쿠키를 식별하는 키와 저장된 데이터 값이다. |
도메인(Domain) | 쿠키를 전송해야 하는 호스트를 지정한다. 지정된 도메인과 그 하위 도메인에서 유효하다. |
경로(Path) | 쿠키를 전송하기 위해 요청되는 URL 경로의 범위를 제한한다. |
만료 시간(Expires/Max-Age) | 쿠키의 유효 기간을 지정한다. 세션 쿠키는 브라우저를 닫으면 삭제된다. |
보안 플래그(Secure) | 이 속성이 설정되면 쿠키는 HTTPS 프로토콜을 통한 연결에서만 전송된다. |
HttpOnly 플래그 | 이 속성이 설정되면 클라이언트 측 자바스크립트를 통해 쿠키에 접근할 수 없어 XSS 공격으로부터 보호하는 데 도움이 된다. |
SameSite 플래그 | CSRF 공격을 완화하기 위해, 쿠키가 교차 사이트 요청과 함께 전송되는 조건을 제한한다. 값은 |
쿠키는 주로 사용자 로그인 상태 유지, 장바구니 정보 저장, 사용자 선호도 또는 테마 기억, 사용자 행동 추적 등에 널리 사용된다. 그러나 클라이언트 측에 저장되며 매 요청마다 서버로 전송되므로, 과도한 데이터를 저장하면 성능에 부정적 영향을 미칠 수 있다. 또한 보안 속성을 적절히 설정하지 않으면 중요한 정보가 노출되거나 다양한 공격에 악용될 위험이 있다. 이러한 이유로 민감한 정보는 쿠키 대신 서버 측 세션 저장소에 저장하고, 쿠키에는 세션을 식별하는 키만 담는 방식이 일반적이다.
세션은 클라이언트와 서버 간의 상태 정보를 유지하기 위한 메커니즘이다. HTTP는 기본적으로 상태를 저장하지 않는 Stateless 프로토콜이기 때문에, 여러 요청에 걸쳐 사용자의 상태(예: 로그인 정보, 장바구니 내용)를 관리하려면 별도의 수단이 필요하다. 세션은 이러한 상태 정보를 서버 측에 저장하고, 각 클라이언트를 식별하기 위한 고유한 세션 ID를 부여하여 상태를 유지한다.
세션의 일반적인 동작 흐름은 다음과 같다. 먼저, 클라이언트가 서버에 최초 요청을 보내면 서버는 해당 클라이언트를 위한 고유한 세션 ID를 생성한다. 이 ID와 연결된 상태 정보는 서버의 메모리나 데이터베이스와 같은 저장소에 보관된다. 서버는 생성된 세션 ID를 응답 시 Set-Cookie 헤더를 통해 클라이언트에게 전달한다. 이후 클라이언트는 이 세션 ID를 쿠키에 저장하고, 다음 요청부터는 Cookie 헤더에 이 ID를 포함시켜 서버로 보낸다. 서버는 수신한 세션 ID를 통해 저장된 상태 정보를 찾아 해당 요청을 처리한다.
세션과 쿠키는 모두 상태 관리를 위해 사용되지만, 정보가 저장되는 위치와 보안 측면에서 차이가 있다. 주요 비교는 아래 표와 같다.
특성 | 세션 (Session) | 쿠키 (Cookie) |
|---|---|---|
정보 저장 위치 | 서버 측 | 클라이언트 측 (사용자 브라우저) |
식별자 전달 방식 | 주로 쿠키를 통해 세션 ID 전달 | 쿠키 자체에 데이터가 포함됨 |
보안성 | 비교적 높음 (중요 데이터가 서버에 있음) | 비교적 낮음 (데이터가 클라이언트에 노출됨) |
저장 용량 제한 | 서버 자원에 따라 다름 | 도메인당 제한 존재 (약 4KB) |
생명주기 | 서버 설정(일정 시간 미사용 시 만료 등)에 따름 | 클라이언트 측에서 만료일 설정 가능 |
세션 관리는 서버에 부하를 줄 수 있다는 단점이 있다. 많은 수의 활성 사용자가 있을 경우 서버는 그에 상응하는 세션 데이터를 관리해야 하며, 이는 메모리와 저장 공간을 소비한다. 또한, 서버를 여러 대로 확장하는 로드 밸런싱 환경에서는 세션 정보를 모든 서버가 공유할 수 있도록 별도의 세션 저장소(예: Redis, Memcached)를 구성해야 하는 추가적인 복잡성이 발생한다.
보안은 월드 와이드 웹에서 정보를 안전하게 교환하기 위한 HTTP의 핵심 고려사항이다. 초기 HTTP는 평문으로 데이터를 전송했기 때문에 도청, 변조, 사칭 등의 위험이 컸다. 이를 해결하기 위해 전송 계층 보안 프로토콜 위에서 HTTP를 실행하는 HTTPS가 등장했다. HTTPS는 통신 경로를 암호화하여 데이터의 기밀성과 무결성을 보장하며, 공개 키 인증서를 통해 서버의 신원을 확인한다[7]. 오늘날 대부분의 주요 웹사이트는 기본 프로토콜로 HTTPS를 사용한다.
인증은 사용자나 클라이언트의 신원을 확인하는 메커니즘이다. HTTP는 기본 인증과 다이제스트 인증 같은 기본적인 인증 스킴을 정의한다. 그러나 보다 강력하고 유연한 인증을 위해 쿠키와 세션을 활용한 방식이나, OAuth, JWT 같은 토큰 기반의 현대적 인증 프로토콜이 널리 사용된다. 이러한 인증 정보는 일반적으로 HTTP 헤더를 통해 전달된다.
교차 출처 리소스 공유는 웹 보안 모델의 중요한 부분이다. 동일 출처 정책에 따라 웹 브라우저는 기본적으로 다른 도메인의 스크립트가 현재 페이지의 리소스에 접근하는 것을 차단한다. CORS는 서버가 특정 출처에서의 접근을 허용하도록 HTTP 헤더를 사용하여 이 정책을 완화하는 메커니즘을 제공한다. 이는 현대 웹 애플리케이션이 여러 도메인의 API를 안전하게 활용할 수 있게 한다.
보안 요소 | 설명 | 관련 HTTP 헤더 예시 |
|---|---|---|
전송 암호화 | HTTPS를 통한 통신 경로 암호화 |
|
인증 | 사용자/클라이언트 신원 확인 |
|
접근 제어 | 리소스에 대한 권한 부여 및 CORS 정책 |
|
내용 보안 | 주입 공격 방지 |
|
HTTPS는 HTTP에 암호화 계층을 추가하여 데이터 통신의 기밀성과 무결성을 보장하는 보안 프로토콜이다. 기본적으로 SSL이나 그 후속 프로토콜인 TLS를 사용하여 클라이언트와 서버 간의 연결을 암호화한다. 이를 통해 중간에서 데이터를 가로채는 도청이나 변조를 방지하며, 특히 로그인 정보, 결제 데이터, 개인정보 등 민감한 정보를 전송할 때 필수적으로 사용된다.
HTTPS 연결은 핸드셰이크 과정을 통해 수립된다. 클라이언트가 서버에 연결을 요청하면, 서버는 자신의 디지털 인증서를 클라이언트에게 전송한다. 이 인증서는 신뢰할 수 있는 인증 기관에 의해 발급되며, 서버의 공개 키와 신원 정보를 포함한다. 클라이언트는 이 인증서를 검증한 후, 서버의 공개 키를 사용하여 대칭 암호화에 사용될 세션 키를 암호화하여 서버로 보낸다. 이후 양측은 이 세션 키를 사용하여 실제 데이터 통신을 암호화한다.
특징 | 설명 |
|---|---|
암호화 | 전송 데이터를 암호화하여 기밀성을 유지한다. |
무결성 | 메시지 인증 코드 등을 통해 데이터가 변조되지 않았음을 보장한다. |
인증 | |
표준 포트 | HTTP의 기본 포트 80과 달리, HTTPS는 443번 포트를 기본으로 사용한다. |
HTTPS의 사용은 웹 표준의 핵심이 되었다. 주요 웹 브라우저들은 HTTPS가 아닌 사이트에 대해 '안전하지 않음' 경고를 표시하며, 검색 엔진 SEO 랭킹에도 HTTPS 사용이 긍정적인 요소로 작용한다. 또한 HTTP/2 및 HTTP/3와 같은 최신 프로토콜의 기능 대부분은 사실상 HTTPS 위에서만 동작한다.
HTTP 기반 시스템에서 인증은 클라이언트의 신원을 서버가 확인하는 과정이다. 서버는 보호된 자원에 대한 접근을 제어하기 위해 클라이언트에게 신원을 증명할 것을 요구한다. 가장 기본적인 형태는 HTTP 기본 인증(Basic Authentication)이다. 이 방식에서는 클라이언트가 사용자 ID와 비밀번호를 콜론(:)으로 연결한 후 Base64로 인코딩하여 Authorization 요청 헤더에 담아 전송한다[9]. 그러나 인코딩만 사용할 뿐 암호화는 하지 않으므로, 평문 전송과 다름없어 보안에 취약하다. 이를 보완하기 위해 HTTPS와 함께 사용해야 한다.
보다 안전한 대안으로는 다이제스트 인증(Digest Authentication)이 있다. 이 방식은 클라이언트가 비밀번호를 직접 보내지 않고, 서버가 제공한 넌스(nonce) 값과 비밀번호 등을 조합해 해시 함수로 계산한 값을 전송한다. 이는 비밀번호 자체가 네트워크를 통해 유출되는 것을 방지하지만, 여전히 중간자 공격(MITM)에 취약할 수 있다. 현대의 웹 애플리케이션에서는 주로 폼 기반 인증(Form-based Authentication)을 사용한다. 사용자는 HTML 폼을 통해 자격 증명을 제출하면, 서버는 이를 검증한 후 일반적으로 세션 ID를 쿠키에 담아 응답한다. 이후 클라이언트는 이 쿠키를 요청마다 함께 보내 인증 상태를 유지한다.
API와 같은 비브라우저 클라이언트 환경에서는 토큰 기반 인증이 널리 사용된다. 대표적인 표준이 OAuth와 JWT(JSON Web Token)이다. OAuth는 제3자 애플리케이션에 사용자의 자원에 대한 제한된 접근 권한을 부여하는 위임 인증 프레임워크이다. JWT는 클레임 정보를 JSON 객체로 표현하고 디지털 서명을 통해 검증 가능한 토큰을 생성한다. 클라이언트는 이 토큰을 Authorization: Bearer <token> 형식의 헤더에 담아 서버에 전송한다. 서버는 토큰의 서명을 검증하여 신원을 확인하고, 토큰 자체에 정보가 포함되어 있어 서버 측 세션 저장소가 필요 없다는 장점이 있다.
CORS는 웹 애플리케이션이 자신이 서비스된 오리진과 다른 오리진(도메인, 프로토콜, 포트)으로부터 리소스를 요청할 수 있도록 허용하는 메커니즘이다. 이 정책은 기본적으로 동일 출처 정책(Same-Origin Policy)에 의해 제한되는 교차 출처 HTTP 요청을 브라우저가 안전하게 수행할 수 있게 한다. 서버는 특정 HTTP 헤더를 사용하여 어떤 오리진, 메서드, 헤더를 허용할지 명시적으로 선언함으로써 CORS를 구현한다.
교차 출처 요청은 단순 요청과 사전 요청으로 구분된다. 단순 요청은 GET, POST, HEAD 메서드와 특정 허용된 헤더만을 사용하는 경우로, 브라우저가 바로 요청을 보내고 서버의 응답 헤더를 확인한다. 반면, 사전 요청은 PUT, DELETE 메서드나 사용자 정의 헤더를 포함하는 등 조건에 해당할 때 발생한다. 이 경우 브라우저는 실제 요청 전에 OPTIONS 메서드를 사용한 "사전 요청"을 먼저 보내 서버의 허용 여부를 확인한다.
서버는 CORS 정책을 응답 헤더를 통해 제어한다. 주요 헤더는 다음과 같다.
헤더 | 설명 |
|---|---|
| 요청을 허용하는 오리진을 지정한다. |
| 사전 요청에 대해 허용되는 HTTP 메서드를 나열한다. |
| 사전 요청에 대해 허용되는 요청 헤더를 나열한다. |
| 쿠키나 인증 정보를 포함한 요청을 허용할지 여부를 나타낸다. |
CORS 오류는 주로 서버의 응답에 필요한 Access-Control-Allow-Origin 헤더가 없거나, 클라이언트의 오리진이 허용 목록에 포함되지 않을 때 브라우저 콘솔에 나타난다. 이는 보안 상의 이유로 브라우저가 교차 출처 응답을 차단했기 때문이다. 개발 중에는 프록시 서버를 구성하거나 서버 측 코드를 수정하여 적절한 CORS 헤더를 추가함으로써 이 문제를 해결할 수 있다.
웹 캐시는 클라이언트나 중간 서버(예: 프록시 서버, CDN)에 리소스의 사본을 저장하여 동일한 요청에 대한 응답 속도를 높이고 서버의 부하를 줄이는 메커니즘이다. 캐싱은 네트워크 대역폭 사용을 감소시키고 사용자에게 더 빠른 웹 경험을 제공하는 핵심 기술이다. 캐시는 브라우저 캐시, 프록시 캐시, 게이트웨이 캐시 등 여러 위치에 존재할 수 있으며, 각각의 유효성은 HTTP 헤더를 통해 제어된다.
캐시의 동작은 크게 캐시 적중(Cache Hit)과 캐시 부적중(Cache Miss)으로 구분된다. 요청된 리소스의 유효한 사본이 캐시에 존재하면 캐시 적중으로, 저장된 사본을 즉시 반환한다. 사본이 없거나 만료된 경우에는 캐시 부적중으로, 원본 서버로 요청을 전달하여 새로운 응답을 받아 캐시에 저장한 후 클라이언트에게 전달한다. 캐시의 유효성을 판단하는 주요 기준에는 만료 시간(Expiration Time)과 유효성 검사(Validation)가 있다. 만료 시간은 Cache-Control의 max-age나 Expires 헤더로 설정된 기간 동안 캐시를 신선(Fresh)한 상태로 유지한다. 유효성 검사는 캐시가 부실(Stale)해졌을 때, Last-Modified/If-Modified-Since나 ETag/If-None-Match 헤더를 사용하여 서버에 리소스 변경 여부를 확인하고 변경되지 않았다면 새로 다운로드하지 않고 기존 캐시를 재사용한다.
캐싱 정책은 HTTP 헤더를 통해 세밀하게 제어된다. 주요 캐시 제어 헤더는 다음과 같다.
헤더 | 사용 위치 | 주요 지시자(Directive)와 역할 |
|---|---|---|
| 요청/응답 |
|
| 응답 | 리소스가 만료되는 절대적인 날짜와 시간을 지정함. |
| 응답 | 서버에서 리소스가 마지막으로 수정된 시간을 알림. 유효성 검사에 사용됨. |
| 응답 | 리소스의 버전을 식별하는 고유한 문자열(엔티티 태그). |
| 응답 | 캐시된 응답이 어떤 요청 헤더(예: |
효과적인 캐싱 전략은 정적 리소스(이미지, CSS, JS 파일)에는 긴 max-age를 설정하고 파일명이나 경로에 버전 해시를 포함시켜 변경 시 강제로 새로 가져오게 하며, 동적 콘텐츠에는 no-cache나 짧은 max-age를 적용하는 방식으로 구성된다. 이를 통해 웹 애플리케이션의 전반적인 성능과 확장성을 크게 향상시킬 수 있다.
캐싱은 웹 성능과 효율성을 크게 향상시키는 핵심 메커니즘이다. 이는 클라이언트나 중간 프록시 서버가 서버로부터 받은 응답의 복사본을 일정 기간 동안 저장해 두고, 이후 동일한 요청이 발생했을 때 서버에 다시 접근하지 않고 저장된 복사본을 제공하는 기술이다. 이를 통해 네트워크 대역폭 사용을 줄이고, 서버 부하를 감소시키며, 최종 사용자에게는 더 빠른 응답 시간을 제공한다.
캐싱은 주로 브라우저(사설 캐시), 콘텐츠 전송 네트워크(CDN) 또는 프록시 서버(공유 캐시)와 같은 여러 위치에서 이루어진다. 캐시의 유효성을 판단하는 주요 기준은 캐시 유효성이다. 저장된 응답이 아직 최신 상태인지, 즉 서버의 원본 자원과 동일한지 확인하는 과정이 필요하다. 이를 위해 Last-Modified와 ETag(Entity Tag) 같은 검증자(Validator) 헤더가 사용된다. 클라이언트는 캐시된 자원을 재사용하기 전에 서버에 조건부 요청을 보내 이 검증자들을 제공하고, 서버는 자원이 변경되지 않았다면 '304 Not Modified'라는 간단한 응답으로 캐시 사용을 허용한다.
캐시의 동작은 서버가 응답과 함께 보내는 다양한 캐시 제어 헤더에 의해 세밀하게 관리된다. 주요 제어 지시어는 다음과 같다.
지시어 | 역할 |
|---|---|
| 응답이 최신 상태로 간주될 수 있는 최대 시간(초)을 지정한다. |
| 캐시에 저장은 가능하지만, 사용 전 반드시 서버에 재검증을 요구한다. |
| 응답을 어떠한 형태로도 캐시에 저장하지 않도록 지시한다. |
| 응답이 공유 캐시(예: 프록시 서버)에 저장될 수 있음을 나타낸다. |
| 응답이 특정 사용자용(예: 브라우저 캐시)으로만 저장되어야 함을 나타낸다. |
효과적인 캐싱 전략은 자원의 특성에 따라 다르게 적용된다. 자주 변경되지 않는 정적 자원(예: 로고 이미지, CSS 파일)은 max-age 값을 길게 설정하여 장기간 캐싱한다. 반면, 실시간 정보나 사용자별 데이터는 no-cache나 짧은 max-age를 사용하여 항상 최신 상태를 유지하도록 한다.
캐시 제어는 주로 Cache-Control HTTP 헤더를 통해 이루어진다. 이 헤더는 요청과 응답 모두에서 사용될 수 있으며, 캐시 가능 여부, 유효 기간, 재검증 조건 등을 지시한다. 주요 지시어(directive)로는 max-age(캐시 유효 시간), no-cache(캐시 저장 전 서버 재검증 필요), no-store(캐시 저장 금지), public(공유 캐시 저장 가능), private(사용자 전용 캐시만 저장 가능) 등이 있다.
조건부 요청을 위한 헤더도 캐시 갱신에 중요한 역할을 한다. 클라이언트는 캐시된 리소스의 최신 여부를 확인하기 위해 If-Modified-Since(날짜 기반) 또는 If-None-Match(ETag 값 기반) 헤더를 포함한 요청을 보낸다. 서버는 리소스가 변경되지 않았다면 304 Not Modified 상태 코드로 응답하여 대역폭을 절약하고, 변경되었다면 새로운 리소스와 함께 200 OK로 응답한다.
다음은 주요 캐시 제어 헤더와 그 역할을 정리한 표이다.
헤더 | 적용 위치 | 주요 역할/지시어 예시 |
|---|---|---|
| 요청/응답 | 캐시 정책 지시 ( |
| 응답 | 응답이 만료되는 날짜/시간 지정 (HTTP/1.0 호환) |
| 응답 | 리소스의 버전을 식별하는 고유 문자열 제공 |
| 응답 | 서버상 리소스가 마지막으로 수정된 시간 |
| 요청 | 캐시된 리소스의 |
| 요청 | 캐시된 리소스의 |
| 응답 | 캐시 키를 생성할 때 고려해야 할 요청 헤더를 지정 |
Expires 헤더는 HTTP/1.0에서 도입된 절대 시간 기반의 만료 제어 방식이지만, 서버와 클라이언트 간 시간 동기화 문제가 있을 수 있다. Cache-Control의 max-age는 요청 시점을 기준으로 한 상대 시간을 지정하여 이 문제를 보완한다. 현대적인 웹 애플리케이션에서는 Cache-Control 헤더를 우선적으로 사용하는 것이 권장된다.
성능 최적화는 네트워크 지연과 대역폭 사용을 줄여 웹 애플리케이션의 응답 속도를 향상시키는 것을 목표로 한다. 주요 기법으로는 연결 관리, 압축, 그리고 HTTP 파이프라이닝이 있다. 이러한 최적화는 주로 HTTP/1.1에서 도입된 기능들을 중심으로 발전했으며, 이후 HTTP/2와 HTTP/3에서는 더 근본적인 프로토콜 개선을 통해 성능 문제를 해결한다.
연결 관리의 핵심은 지속 연결과 병렬 연결이다. 지속 연결은 하나의 TCP 연결을 통해 여러 개의 요청과 응답을 교환하여 연결 수립과 해제에 따른 오버헤드를 줄인다. HTTP/1.1에서는 이것이 기본 동작이다. 병렬 연결은 단일 도메인에 대해 여러 개의 지속 연결을 동시에 열어 리소스를 병렬로 다운로드하는 방법이지만, 과도한 연결은 서버와 클라이언트 모두에 부담을 줄 수 있다. HTTP/2에서는 멀티플렉싱을 통해 단일 연결 내에서 여러 요청과 응답을 동시에 처리하여 병렬 연결의 필요성을 크게 줄였다.
압축은 전송되는 데이터의 크기를 줄이는 기법이다. 가장 일반적인 것은 콘텐츠 인코딩을 이용한 엔티티 본문 압축이다. gzip이나 Brotli 같은 알고리즘을 사용하여 HTML, CSS, 자바스크립트 파일 등을 압축하면 전송 시간을 크게 단축할 수 있다. 또한 HTTP/2에서는 헤더 압축을 위해 HPACK 방식을 도입하여 반복되는 헤더 필드의 오버헤드를 줄였다.
HTTP 파이프라이닝은 지속 연결을 기반으로, 클라이언트가 이전 요청에 대한 응답을 기다리지 않고 연속적으로 여러 요청을 보내는 기술이다. 이론적으로는 지연 시간을 줄일 수 있지만, 응답이 순서대로 도착해야 하는 HOL 블로킹 문제와 구현의 복잡성 때문에 널리 채택되지 못했다. 이 문제는 HTTP/2의 스트림과 멀티플렉싱, 그리고 HTTP/3의 QUIC 프로토콜을 통한 UDP 기반 전송으로 근본적으로 해결되었다.
HTTP/1.0에서는 각 HTTP 요청마다 새로운 TCP 연결을 열고 닫는 방식이 기본이었다. 이 방식은 매번 3방향 핸드셰이크와 연결 종료 과정을 거쳐야 하므로 지연과 오버헤드가 크다는 단점이 있었다. 특히 여러 개의 작은 리소스를 로드해야 하는 웹 페이지의 경우 성능 저하가 두드러졌다.
이 문제를 해결하기 위해 HTTP/1.1에서는 지속 연결이 표준으로 도입되었다. 지속 연결은 하나의 TCP 연결을 통해 여러 개의 요청과 응답을 순차적으로 교환할 수 있게 한다. 연결을 재사용함으로써 반복적인 연결 설정 및 해제에 따른 지연과 자원 소모를 줄일 수 있다. HTTP/1.1에서는 기본적으로 모든 연결이 지속 연결로 간주되며, Connection: close 헤더를 명시적으로 보내야 연결을 닫는다.
지속 연결의 효율성을 더욱 높이기 위해 HTTP 파이프라이닝 기술이 등장했다. 파이프라이닝은 첫 번째 요청에 대한 응답을 기다리지 않고, 다음 요청들을 연속적으로 보내는 방식을 말한다. 이론적으로는 대기 시간을 더욱 단축할 수 있지만, HOL 블로킹 문제로 인해 실제 구현과 활용에는 제약이 많았다. HTTP/2에서는 멀티플렉싱을 통해 여러 요청과 응답을 병렬로 처리함으로써 연결 관리의 효율성을 획기적으로 개선했다.
효율적인 연결 관리를 위한 주요 매커니즘은 다음과 같다.
HTTP 압축은 네트워크 대역폭 사용을 줄이고 페이지 로딩 속도를 향상시키기 위해 HTTP 메시지의 본문 크기를 줄이는 기술이다. 주로 텍스트 기반의 리소스(HTML, CSS, JavaScript, JSON, XML 등)에 적용되며, 서버에서 리소스를 압축하여 전송하고 클라이언트가 이를 해제하여 사용한다. 이 과정은 HTTP 헤더를 통해 협상되며, 대역폭 절감과 성능 개선에 직접적인 영향을 미친다.
가장 일반적으로 사용되는 압축 방식은 gzip과 Deflate이다. gzip은 특히 높은 압축률로 널리 채택되었다. 최근에는 더 효율적인 압축 알고리즘인 Brotli(br)이 등장하여 점차 사용이 증가하고 있다. 압축을 적용하려면, 클라이언트는 요청 시 Accept-Encoding 헤더에 지원하는 압축 방식을 명시한다(예: Accept-Encoding: gzip, deflate, br). 서버는 이 요청을 확인하고 해당 방식을 지원하면, 응답 본문을 압축하고 Content-Encoding 헤더에 사용된 방식을 표시하여 클라이언트에 알린다(예: Content-Encoding: gzip).
압축은 성능에 큰 이점을 제공하지만, 고려해야 할 사항도 존재한다. 서버와 클라이언트 모두 압축 및 해제를 위한 추가적인 CPU 연산을 수행해야 한다. 그러나 일반적으로 네트워크 전송 시간의 절감 효과가 CPU 오버헤드보다 훨씬 크기 때문에, 특히 모바일 환경이나 고대역폭 네트워크가 아닌 경우에 유용하다. 이미지, 비디오, PDF 파일 등 이미 자체적으로 압축된 바이너리 포맷에는 추가적인 HTTP 수준의 압축을 적용하지 않는 것이 일반적이다.
HTTP 파이프라이닝은 HTTP/1.1에서 도입된 성능 최적화 기법이다. 이 기법은 클라이언트가 단일 TCP 연결을 통해 여러 HTTP 요청을 응답을 기다리지 않고 연속적으로 보낼 수 있도록 한다. 기존의 방식은 하나의 요청을 보내고 그에 대한 응답을 받은 후에야 다음 요청을 보낼 수 있었는데, 이로 인해 발생하는 대기 시간(지연 시간)을 줄이는 것이 목표이다.
파이프라이닝의 동작 방식은 다음과 같다. 클라이언트는 첫 번째 요청을 서버로 보낸 후, 서버의 응답이 도착하기 전에 두 번째, 세 번째 요청을 차례로 보낸다. 서버는 요청을 받은 순서대로 처리하여 응답을 생성하고, 동일한 순서로 클라이언트에게 응답을 보낸다. 이는 네트워크 왕복 시간을 줄여 전체적인 페이지 로딩 속도를 개선할 수 있다.
특징 | 설명 |
|---|---|
목적 | 네트워크 지연 시간 감소 및 연결 효율성 향상 |
요구 조건 | HTTP/1.1 연결 및 Keep-Alive |
처리 순서 | 서버는 요청을 받은 순서(FIFO)대로 응답해야 함 |
주요 문제점 |
그러나 HTTP 파이프라이닝은 몇 가지 심각한 단점으로 인해 실제로는 널리 채택되지 못했다. 가장 큰 문제는 Head-of-line blocking이다. 파이프라인에서 먼저 보낸 요청의 처리가 오래 걸리면, 뒤이어 보낸 요청들의 응답도 그만큼 지연되는 현상이 발생한다. 또한 중간에 있는 프록시 서버들이 파이프라이닝을 제대로 지원하지 않거나 오동작을 일으킬 가능성이 있었고, 보안상의 이유로 인해 일부 브라우저에서는 기본적으로 비활성화되었다. 이러한 한계들로 인해, 파이프라이닝은 이후 등장한 HTTP/2의 멀티플렉싱 기술로 대체되었다.
관련 프로토콜 및 기술 섹션은 HTTP와 함께 사용되거나, HTTP를 기반으로 발전한 주요 기술들을 다룬다. 이들 기술은 현대 웹 애플리케이션의 기능과 성능을 확장하는 데 핵심적인 역할을 한다.
가장 널리 알려진 개념은 REST 아키텍처 스타일을 따르는 RESTful API이다. RESTful API는 HTTP의 메서드(GET, POST, PUT, DELETE 등)와 URI를 활용하여 자원을 정의하고 조작하는 인터페이스를 설계한다. 이는 클라이언트-서버 모델을 따르며, 무상태성(Stateless)을 원칙으로 하여 확장성과 단순함을 제공한다. 반면, 실시간 양방향 통신이 필요한 경우에는 WebSocket 프로토콜이 사용된다. WebSocket은 단일 TCP 연결을 통해 풀 듀플렉스 통신 채널을 제공하여, HTTP의 요청-응답 주기로는 효율적이지 못한 채팅, 실시간 게임, 주식 시세 표시 등의 애플리케이션을 구현할 수 있게 한다.
HTTP 자체의 발전 또한 새로운 기술을 낳았다. HTTP/2에서 도입된 HTTP/2 Server Push는 서버가 클라이언트의 명시적 요청 없이도 필요한 자원(예: CSS, JavaScript 파일)을 미리 보낼 수 있는 기능이다. 이를 통해 페이지 로딩 지연 시간을 줄이고 성능을 개선할 수 있다. 이 외에도 GraphQL은 클라이언트가 필요한 데이터의 구조를 정확히 지정하여 요청할 수 있는 쿼리 언어로, 전통적인 REST API의 과다 또는 과소 데이터 가져오기 문제를 해결한다. gRPC는 HTTP/2를 기반으로 한 고성능 원격 프로시저 호출 프레임워크로, 효율적인 바이너리 직렬화를 사용한다.
기술 | 주요 목적 | HTTP와의 관계 |
|---|---|---|
자원 지향적 웹 서비스 설계 | HTTP 프로토콜을 아키텍처 스타일로 활용 | |
실시간 양방향 통신 | HTTP 핸드셰이크로 연결을 시작한 후 독립적 프로토콜로 전환 | |
웹 페이지 로딩 성능 개선 | HTTP/2 프로토콜의 내장 기능 | |
효율적이고 유연한 데이터 요청 | 주로 HTTP를 전송 계층으로 사용 | |
고성능 마이크로서비스 통신 | HTTP/2를 전송 프로토콜로 사용 |
REST는 Representational State Transfer의 약자로, 월드 와이드 웹과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처 스타일이다. 로이 필딩이 2000년 그의 박사 논문에서 소개한 이 아키텍처는 HTTP 프로토콜의 설계 원칙을 잘 반영하며, 웹 서비스를 구축하는 하나의 방법론으로 널리 채택되었다. RESTful API는 이러한 REST 원칙을 따르도록 설계된 API를 지칭한다.
RESTful API의 핵심 원칙은 다음과 같다.
* 자원 지향 아키텍처 (ROA): 모든 데이터나 서비스를 고유한 URI를 가진 자원으로 정의한다. 예를 들어, /users는 사용자 목록, /users/123은 ID가 123인 특정 사용자를 나타낸다.
* HTTP 메서드를 이용한 행위 표현: 자원에 대한 행위는 HTTP 메서드로 표현한다. GET은 조회, POST는 생성, PUT은 전체 수정, PATCH는 부분 수정, DELETE는 삭제에 사용된다.
* 무상태성 (Stateless): 각 클라이언트 요청은 서버가 그 요청을 이해하는 데 필요한 모든 정보를 포함해야 한다. 서버는 클라이언트의 상태를 세션 등으로 관리하지 않는다.
* 표현을 통한 자원 조작: 클라이언트는 자원의 표현(예: JSON, XML)을 주고받으며 자원을 조작한다. 동일한 자원에 대해 여러 표현이 존재할 수 있다.
* 하이퍼미디어로서의 애플리케이션 상태 엔진 (HATEOAS): 이상적인 REST 수준에서는 API 응답에 현재 상태에서 가능한 다음 작업에 대한 하이퍼링크가 포함되어, 클라이언트가 애플리케이션 상태를 동적으로 탐색할 수 있게 한다.
RESTful API는 그 단순성과 HTTP의 표준을 활용한다는 점에서 널리 사용된다. SOAP와 같은 복잡한 프로토콜에 비해 가볍고, 캐싱 메커니즘을 활용하기 쉬우며, 다양한 클라이언트(웹, 모바일 앱 등)와의 호환성이 뛰어나다. 그러나 표준화된 오류 처리 방식의 부재나, HATEOAS 원칙의 실질적 구현 난이도, N+1 문제 같은 과도한 요청 발생 가능성 등은 설계 시 고려해야 할 과제이다.
WebSocket은 TCP 연결 위에서 작동하는 양방향 통신 프로토콜이다. HTTP의 단점인 단방향 요청-응답 구조를 극복하기 위해 설계되었으며, 한 번 연결을 수립하면 지속적으로 양방향 데이터 교환이 가능하다는 특징을 가진다.
연결 과정은 HTTP 업그레이드 핸드셰이크로 시작한다. 클라이언트는 특수한 Upgrade: websocket 헤더를 포함한 HTTP 요청을 보낸다. 서버가 이를 수락하면 HTTP 연결이 WebSocket 프로토콜로 전환되며, 이후부터는 HTTP 규약을 따르지 않고 WebSocket 프레임을 사용해 데이터를 주고받는다. 이 연결은 명시적으로 닫힐 때까지 유지된다.
특징 | 설명 |
|---|---|
양방향 통신 | 클라이언트와 서버 모두 임의의 시점에 메시지를 전송할 수 있다. |
지속적 연결 | 핸드셰이크 후 지속적인 TCP 연결을 유지하여 오버헤드를 줄인다. |
경량 프로토콜 | 데이터 오버헤드가 적은 프레임 구조를 사용한다. |
교차 출처 지원 | CORS 제약을 피해 다른 도메인과의 연결을 지원한다. |
주요 적용 분야로는 실시간 알림 시스템, 주식 차트, 실시간 협업 도구, 채팅 애플리케이션, 온라인 게임 등이 있다. HTTP/2의 Server Push도 서버에서 클라이언트로의 단방향 푸시를 가능하게 하지만, WebSocket은 진정한 의미의 양방향 실시간 대화를 위한 표준 프로토콜로 자리 잡았다.
HTTP/2 서버 푸시는 서버가 클라이언트의 명시적인 요청 없이도 관련 리소스를 사전에 클라이언트에게 전송할 수 있는 기능이다. 이는 웹 페이지 로딩 성능을 향상시키기 위해 설계되었다. 기존의 HTTP/1.1에서는 클라이언트가 HTML 문서를 받아 파싱한 후, 문서 내에 포함된 CSS, JavaScript, 이미지 파일 등의 리소스를 발견해야만 각각에 대한 추가적인 요청을 보낼 수 있었다. 이로 인해 여러 번의 왕복 지연이 발생하여 페이지 전체 로드 시간이 길어지는 원인이 되었다.
서버 푸시를 사용하면, 서버는 초기 HTML 문서에 대한 응답과 함께, 해당 문서를 렌더링하는 데 필요한 보조 리소스들(예: 중요한 스타일시트나 스크립트)을 클라이언트가 요청하기도 전에 푸시 스트림을 통해 함께 보낼 수 있다. 이는 클라이언트 측에서 추가 요청을 기다리는 지연 시간을 제거한다. 푸시될 리소스는 서버가 Link 헤더와 rel=preload 힌트를 통해, 또는 서버의 내부 로직을 통해 결정된다.
그러나 이 기술은 몇 가지 주의사항과 함께 사용된다. 서버가 예측하여 푸시한 리소스가 클라이언트에 이미 캐시되어 있을 경우 불필요한 데이터 전송을 초래할 수 있다. 또한, 푸시된 리소스에 대한 클라이언트의 취소 권한은 제한적이었다. 이러한 이유로, 서버 푸시의 구현과 채택은 예상보다 제한적이었으며, 대안적인 성능 최적화 기법들(예: 리소스 힌팅, HTTP/3의 설계)이 더 널리 사용되는 경향을 보인다.
장점 | 단점 및 고려사항 |
|---|---|
왕복 지연(RTT) 감소 | 불필요한 리소스 푸시 가능성 |
클라이언트 요청 전에 리소스 전송 가능 | 클라이언트 캐시를 무시할 수 있음 |
페이지 로드 시간 단축에 잠재적 효과 | 서버 구현 복잡성 증가 |
HTTP/2 연결 설정 초기에만 효과적 |
결과적으로, HTTP/2 서버 푸시는 이론적으로 유망한 개념이었으나, 실제 배포와 효과 측면에서 한계를 드러냈다. 많은 최신 브라우저와 서버가 이 기능을 지원했음에도 불구하고, 복잡한 캐시 관리와 예측의 정확도 문제로 인해 광범위하게 활용되지는 못했다.
HTTP는 기술적 표준으로서의 역할을 넘어, 현대 인터넷 문화와 개발자들의 일상에 깊숙이 스며들어 여러 유의미한 일화와 비공식적 용어를 만들어냈다.
"Hello World" 프로그램과 마찬가지로, 네트워크 프로그래밍 입문자는 종종 HTTP 서버를 구현하는 것을 첫 번째 과제로 삼는다. 이 과정에서 404 Not Found 상태 코드는 단순한 오류 메시지를 넘어, '없는 것'을 의미하는 대중적인 인터넷 밈으로 자리 잡았다. 비슷하게, 418 I'm a teapot 코드는 RFC 문서에 유머러스하게 포함된 사례로, 기술 커뮤니티 내에서 종종 회자된다. 이 코드는 하이퍼 텍스트 커피 포트 프로토콜이라는 만우절 농담 RFC 2324에 정의되어 있다[10].
개발자들 사이에서는 특정 HTTP 메서드가 행동 철학을 비유하는 데 사용되기도 한다. 예를 들어, 새로운 환경에 완전히 자신을 맞추는 것을 PUT 메서드에, 기존 상태를 부분적으로 수정하는 것을 PATCH 메서드에 빗대어 표현한다. 또한, RESTful API 설계 원칙에 대한 논쟁은 개발자 포럼과 컨퍼런스의 지속적인 주제 중 하나이다.