HTTP
HTTP의 목적은 애플리케이션의 다양한 자원을 네트워크를 통해 송수신하는 것이다. 다소 일반적이고 범용적인 목적이지만, 그것이 바로 HTTP의 핵심이다. 다시 말해, 데이터의 형식에 구애받지 않고 다양한 애플리케이션 데이터의 송수신을 가능하게 하는 것이 HTTP의 주된 목적이다.
HTTP의 특징
HTTP에는 주요한 특징 4가지가 있는데, 아주 중요하기 때문에 모든 특징을 기억해 두는 것이 좋다.
1.
요청과 응답을 기반으로 동작한다. (요청 응답 기반 프로토콜)
2.
미디어 독립적이다. (미디어 독립적 프로토콜)
3.
상태를 유지하지 않는다. (스테이트리스 프로토콜)
4.
지속 연결을 지원한다. (지속 연결 프로토콜)
요청 응답 기반 프로토콜
•
HTTP는 클라이언트-서버 구조 기반의 요청-응답 프로토콜이다.
•
같은 HTTP 메시지라도 HTTP 요청 메시지와 HTTP 응답 메시지의 형태가 다르다.
미디어 독립적 프로토콜
•
HTTP는 주고받을 미디어 타입에 특별히 제한을 두지 않고 동작하는 미디어 독립적 프로토콜이다.
◦
미디어 타입(media type): HTTP에서 메시지로 주고받는 자원의 종류 → 네트워크 세상의 확장자
▪
미디어 타입 = MIME 타입(Multipurpose Internet Mail Extensions Type)
•
타입/서브타입 형식으로 구성
◦
타입(type): 데이터의 유형
◦
서브타입(subtype): 주어진 타입에 대한 세부 유형
타입 | 타입 설명 | 서브타입 |
text | 일반 텍스트 형식의 데이터 | text/plain
text/html
text/css
text/javascript |
image | 이미지 형식의 데이터 | image/gif
image/png
image/jpeg
image/webp |
video | 비디오 형식의 데이터 | video/mp4
video/ogg
video/webm |
audio | 오디오 형식의 데이터 | audio/midi
audio/wav |
application | 바이너리 형식의 데이터 | application/octet-stream
application/x-www-form-urlencoded
application/xml
application/pdf
application/json |
multipart | 각기 다른 미디어 타입을 가질 수 있는 여러 요소로 구성된 데이터 | multipart/form-data
multipart/encrypted |
미디어 타입의 추가 표기 방법
미디어 타입에 별표 문자(*)가 사용되는 경우도 있다. 별표는 여러 미디어 타입을 통칭하기 위해 사용된다. 예를 들어 text/*는 text 타입의 모든 서브타입을 나타낸다. 또 */*는 모든 미디어 타입을 나타낸다.
또한 미디어 타입에는 부가 설명을 위해 선택적으로 매개변수를 포함할 수도 있다. 매개변수는 타입/서브타입;매개변수=값 형식으로 표현된다. 예를 들어, type/html;charset=UTF-8은 미디어 타입이 HTML 문서 타입이며, HTML 문서 내에서 사용된 문자가 UTF-8로 인코딩되었음을 의미한다.
스테이트리스 프로토콜
•
HTTP는 상태를 유지하지 않는 스테이트리스(stateless) 프로토콜이다.
◦
즉, 서버는 HTTP 요청을 보낸 클라이언트 관련 상태를 기억하지 않는다.
◦
그렇기 때문에 클라이언트의 모든 HTTP 요청은 기본적으로 독립적인 요청으로 간주된다.
•
왜 상태를 유지하지 않는가?
◦
서버는 많은 클라이언트와 동시에 상호작용한다.
◦
이런 상황에서 모든 클라이언트의 상태 정보를 유지하는 것은 서버에 큰 부담이 된다.
◦
또 서버는 여러 대로 구성될 수도 있는데, 클라이언트의 상태를 유지해야 한다면 모든 서버가 이를 공유할 수 있어야 한다.
◦
만일 모든 서버가 클라이언트의 상태 정보를 공유하지 못하면 클라이언트는 결국 자신의 상태를 기억하는 특정 서버하고만 상호작용하게 된다.
◦
그러다 어느 한 서버에 문제가 발생하면 해당 서버에 종속된 클라이언트는 직전까지의 HTTP 통신 내역을 잃어버리는 상황이 발생할 수도 있다.
•
상태를 유지하지 않으면 어떤 이점이 있는가?
◦
HTTP 서버가 지켜야 할 가장 중요한 설계 목표에는 확장성(scalability)과 견고성(robustness)이 있다.
◦
서버가 클라이언트의 모든 요청을 독립적인 요청으로 처리하면 특정 클라이언트가 특정 서버에 종속되지 않는다.
◦
따라서 서버의 추가나 대체가 쉬워진다.
◦
즉, 상태를 유지하지 않는 스테이트리스한 특성은 필요한 경우 언제든 쉽게 서버를 추가할 수 있어 확장성을 높이고, 서버 중 하나에 문제가 생기더라도 쉽게 다른 서버로 대체할 수 있어 견고성을 높일 수 있다.
지속 연결 프로토콜
•
HTTP에는 버전이 존재하고, 신뢰성 있는 데이터 전송을 위해 TCP 위에서 동작한다.
•
초기의 HTTP 버전(HTTP 1.0 이하)
◦
TCP 연결 수립한 후, 요청에 대한 응답을 받으면 연결 종료
◦
추가적인 요청-응답을 하기 위해서는 다시 TCP 연결 수립부터 반복
◦
이를 비지속 연결이라고 한다.
•
오늘날 HTTP 버전(HTTP 1.1 이상)
◦
하나의 TCP 연결상에서 여러 개의 요청-응답을 주고받을 수 있는 기술
◦
이를 지속 연결(persistent connection) 또는 킵 얼라이브(keep-alive)라고 한다.
HTTP 메시지 구조
•
HTTP 메시지는 시작 라인(start-line), 헤더(headers), 메시지 본문(body)으로 구성된다.
•
먼저, 시작 라인과 헤더가 어떤 역할을 하는지 알아보자.
시작 라인(start-line)
•
시작 라인으로 HTTP 메시지가 요청 메시지인지 응답 메시지인지를 구분할 수 있다.
◦
요청 메시지 → 요청 라인(request-line)
◦
응답 메시지 → 상태 라인(status-line)
•
요청 라인과 상태 라인은 다음과 같은 형식으로 구성되어 있다.
•
요청 라인(request-line)
메서드 (공백) 요청 대상 (공백) HTTP 버전 (줄바꿈)
Plain Text
복사
필드 이름 | 설명 |
메서드(method) | 클라이언트가 서버의 자원에 대해 수행할 작업의 종류를 나타낸다.
(예) GET |
요청 대상(request-target) | 요청을 보낼 서버의 자원을 명시한다.
일반적으로 쿼리 문자열이 포함된 URL의 path가 명시된다.
(예1) /hello?q=network
(예2) / |
HTTP 버전(HTTP-version) | 사용된 HTTP 버전을 나타낸다.
(예) HTTP/1.1 |
•
상태 라인(status-line)
HTTP 버전 (공백) 상태 코드 (공백) 이유 구문 (줄바꿈)
Plain Text
복사
필드 이름 | 설명 |
HTTP 버전(HTTP-version) | 사용된 HTTP 버전을 나타낸다.
(예) HTTP/1.1 |
상태 코드(status code) | 요청에 대한 결과를 나타내는 3자리 정수를 나타낸다.
(예) 200 |
이유 구문(reason phrase) | 상태 코드에 대한 문자열 형태의 설명이다.
(예) OK |
(예) HTTP/1.1 200 OK
(예) HTTP/1.1 404 Not Found
Plain Text
복사
헤더(headers)
•
HTTP 헤더는 HTTP 메시지 전송과 관련한 부가 정보이자 제어 정보이다.
•
일반적으로 하나의 HTTP 메시지에는 여러 헤더가 포함되어 있다.
•
HTTP 헤더는 콜론(:)을 기준으로 헤더 이름(header-name)과 그에 대응하는 헤더 값(header-value)으로 구성되어 있다.
HTTP/1.1 200 OK
Content-Type: text/html // 헤더
Content-Length: 648 // 헤더
...
Plain Text
복사
HTTP 메서드
HTTP 메서드에서 자주 사용되는 중요한 메서드는 다음과 같다.
HTTP 메서드 | 설명 |
GET | 자원을 습득하기 위한 메서드 |
POST | 서버로 하여금 특정 작업을 처리하게끔 하는 메서드 |
PUT | 자원을 대체하기 위한 메서드 |
PATCH | 자원에 대한 부분적 수정을 위한 메서드 |
DELETE | 자원을 삭제하기 위한 메서드 |
GET
•
자원을 조회하는 용도의 메서드
•
서버에 전달할 데이터는 query string을 통해 전달한다.
•
요청 메시지 예시
GET /example-page HTTP/1.1
Host: www.example.com
Accept: *
Plain Text
복사
POST
•
서버로 하여금 특정 작업을 처리하도록 요청하는 용도의 메서드
◦
주로, 클라이언트가 서버에 새로운 자원을 생성하거나 프로세스를 처리할 때 사용
▪
예1) 회원 등록 → 자원 생성
▪
예2) 배달 시작 → 프로세스 처리
•
메시지 바디를 통해 서버로 요청 데이터를 전달하면 해당 데이터를 처리한다.
•
요청 메시지 예시
POST /posting HTTP/1.1
Host: www.example.com
... (헤더 후략) ...
{
"Id": 1,
"Title": "컴퓨터 네트워크",
"Contents": "너무 중요한 과목!!"
}
Plain Text
복사
PUT vs PATCH
•
PUT 메서드와 PATCH 메서드는 둘의 차이점에 유의하는 것이 좋다.
◦
PUT 메서드는 ‘덮어쓰기’를 요청하는 메서드
◦
PATCH 메서드는 ‘부분적 수정’을 요청하는 메서드
•
예를 들어, 서버에 다음과 같은 형태의 자원이 있다고 가정해보자.
{
"Id": 1,
"Title": "컴퓨터 네트워크",
"Contents": "너무 중요한 과목!!"
}
Plain Text
복사
•
PUT 메서드를 요청할 경우
PUT /posting HTTP/1.1
Host: www.example.com
... (헤더 후략) ...
{
"Id": 1,
"Title": "수정된 제목입니다.",
}
Plain Text
복사
◦
위 요청 메시지가 성공적으로 수행될 경우, 서버의 자원은 결과적으로 다음과 같은 형태가 된다.
{
"Id": 1,
"Title": "수정된 제목입니다.",
}
Plain Text
복사
•
PATCH 메서드를 요청한 경우
PATCH /posting HTTP/1.1
Host: www.example.com
... (헤더 후략) ...
{
"Id": 1,
"Title": "수정된 제목입니다.",
}
Plain Text
복사
◦
위 요청 메시지가 성공적으로 수행될 경우, 서버의 자원은 결과적으로 다음과 같은 형태가 된다.
{
"Id": 1,
"Title": "수정된 제목입니다.",
"Contents": "너무 중요한 과목!!"
}
Plain Text
복사
DELETE
•
특정 자원의 삭제를 요청할 때 사용되는 메서드
•
요청 메시지 예시
DELETE /texts/a.txt HTTP/1.1
Host: www.example.com
Plain Text
복사
◦
위 메시지는 www.example.com이라는 호스트의 /texts/a.txt를 삭제하도록 요청하는 메시지의 예시이다.
HTTP 메서드의 속성 정리
•
안전(Safe Methods)
◦
호출해도 리소스가 변경되지 않는다.
◦
GET, OPTIONS, TRACE등은 조회의 성격을 가지고 있기에 리소스를 변경하지 않고, 그렇기에 안전하다.
◦
이 때, 안전의 범위는 해당 리소스에만 해당되며 그 외적인 요소는 고려하지 않는다.
▪
리소스 호출시마다 로그가 남는다 하여도 이는 리소스에 대한 영향은 아니기 때문에 고려하지 않는다.
•
멱등(Idempotent Methods)
◦
메서드를 반복해서 호출하더라도 결과가 동일해야 한다.
◦
GET, PUT, DELETE같은경우 여러번 호출하더라도 GET은 같은 데이터를 조회, PUT은 대치된 값을 반환하기에 동일, DELETE도 결과를 삭제하기에 같은 요청을 하더라도 삭제된 내용이 복구되지는 않기에 멱등성을 성립한다.
◦
POST의 경우 회원 등록을 두 번하거나 주문을 두 번할 경우 에러가 발생하거나 주문 중복이 생길 수 있기에 멱등성이 성립하지 않는다.
•
캐시 가능(Cacheable Methods)
◦
표에서는 GET, HEAD, POST, PATCH가 캐시가능이라 되있지만, 실제로는 GET, HEAD정도만 캐시로 사용된다.
◦
POST, PATCH는 본문 내용(Message Body)까지 캐시 키로 고려해야하는데 구현이 쉽지 않다.
HTTP 상태 코드
HTTP API에 대해 클라이언트가 요청을 보내면 서버측에선 응답 메시지를 돌려주는데, 이 상태코드를 통해서 서버에서 어떻게 처리되었는지를 추측할 수 있다.
상태 코드 | 설명 |
100번대(1xx) | 정보성 상태 코드 |
200번대(2xx) | 성공 상태 코드 |
300번대(3xx) | 리다이렉션 상태 코드 |
400번대(4xx) | 클라이언트 에러 상태 코드 |
500번대(5xx) | 서버 에러 상태 코드 |
100번대(Informational)
•
요청이 수신되어 처리중이다.
•
이제 거의 사용되지 않는다.
200번대(Successful)
•
요청이 정상적으로 처리되었다.
상태 코드 | 이유 구문 | 설명 |
200 | OK | - 조회 요청에 성공적으로 응답하는 경우 |
201 | Created | - POST와 같은 생성요청으로 리소스가 정상적으로 생성된 경우
- 응답 메시지(헤더)에는 생성된 리소스 식별자가 Location 필드에 추가되어 응답된다. |
202 | Accepted | - 요청을 서버에서 받았으나 아직 처리가 되지 않은 경우
- (예) 배치 프로세스 |
204 | No Content | - 서버에서 요청은 성공적으로 수행했지만, 응답시 메시지 바디에 담을 데이터가 없는 경우 |
300번대(Redirection)
•
요청을 완료하기 위해 추가 행동이 필요하다. (리다이렉션)
•
영구 리다이렉션: 특정 리소스의 URL가 영구적으로 이동한다.
상태 코드 | 이유 구문 | 설명 |
301 | Moved Permanently | - 리다이렉트시 요청 메서드가 GET으로 변한다.
- 본문이 변경될 수 있다. |
308 | Permanet Redirect | - 301 상태코드와 기능은 동일하다.
- 응답 메시지의 본문과 요청 메서드가 유지된다. |
•
일시 리다이렉션: 리소스의 URL가 일시적으로 변경된다.
상태 코드 | 이유 구문 | 설명 |
302 | Found | - 리다이렉트시 요청 메서드가 GET을 변한다. |
303 | See Other | - 302와 기능은 같다.
- 리다이렉트시 요청 메서드가 GET으로 변한다. |
307 | Temporary Redirect | - 302와 기능은 같다.
- 응답 메시지의 본문과 요청 메서드가 유지된다. |
304 | Not Modified | - 캐시를 목적으로 사용한다.
- 클라이언트에 리소스가 수정되지 않았음을 알린다.
- 304 응답은 응답에 메시지 바디를 사용하면 안된다.
- 조건부 GET, HEAD 요청시 사용한다. |
PRG(Post Redirect Get) Pattern
페이지 새로고침시 동일 메서드(POST)로 서버에 전달되면 안되는 경우에 사용하는 패턴. 즉, 멱등성을 가지지 못하는 메서드의 경우에는 모두 해당 패턴을 사용하는게 좋다. 응답 코드로 302, 303등을 사용하면 자연스럽게 리다이렉션시 메서드가 GET으로 변경되며 문제를 해결한다.
400번대(Client Error)
•
클라이언트에서 잘못된 스펙으로 데이터를 보냈거나 인증, 인가가 만족되지 않아 서버에서 요청을 수행할 수 없다.
상태 코드 | 이유 구문 | 설명 |
400 | Bad Request | - 클라이언트가 보내는 포맷이나 데이터에 문제가 있을 경우 발생 |
401 | Unauthorized | - 인증(Authentication)이 되지 않은 클라이언트에서 접근하는 경우 |
403 | Forbidden | - 인증자격은 있지만, 권한(Authorization)이 없는 경우 응답
- (예) 일반 회원이 관리자 페이지에 접근하려는 경우 |
404 | Not Found | - 요청 리소스를 찾을 수 없을 경우 |
405 | Method Not Allowed | - 요청 메서드가 지원하지 않을 경우 |
인증(Authentication) vs 인가[권한](Authorization)
인증이란 ‘자신이 누구인지를 증명하는 작업’을 의미하고, 인가 혹은 권한은 ‘인증된 주체에게 허용된 작업’을 의미한다. 로그인된 모든 유저는 인증된 유저라고 할 수 있지만, 로그인된 모든 유저가 관리자 페이지에 들어갈 수는 없다. 다시 말해, 인증이 되었더라도 권한은 충분하지 않을 수 있다. 둘의 차이점을 잘 기억해두자.
500번대(Server Error)
•
서버에서 에러가 발생해서 요청을 정상적으로 처리할 수 없다.
상태 코드 | 이유 구문 | 설명 |
500 | Internal Server Error | - 서버 내부 문제로 오류가 발생하는 경우
- 서버측의 로직에서 발생하는 대다수의 예외나 에러
- 정말 서버에 오류가 있을때만 발생해야 한다. 비즈니스 로직과 같이 시스템이 아닌 로직상의 문제가 발생할 때 500 응답코드를 반환해서는 안된다. |
503 | Service Unavailable | - 서버에 트래픽문제 혹은 점검으로 잠시 요청을 처리할 수 없는 경우
- Retry-After 헤더 필드로 얼마 뒤 복구되는지 보낼 순 있지만, 예측 불가능한 경우가 대부분이기에 잘 사용되지 않는다. |
HTTP 주요 헤더
HTTP 요청 메시지에서 주로 활용되는 대표적인 HTTP 헤더로는 Host, User-Agent, Referer가 있다.
요청 메시지에서 주로 활용되는 HTTP 헤더
Host
요청을 보낼 호스트가 명시되는 헤더입니다. 도메인 네임이나 IP 주소로 표현되며, 포트 번호가 포함될 수도 있다. Host 헤더와 요청 라인을 조합하면 요청을 보낸 URL을 짐작할 수 있는 경우가 많다. 가령 다음과 같은 HTTP 메시지는 ‘http://info.cern.ch/hypertext/WWW/TheProject.html’에 GET 요청 메시지를 보낼 때의 HTTP 요청 메시지이다.
GET /hypertext/WWW/TheProject.html HTTP/1.1
Host: info.cern.ch
Plain Text
복사
User-Agent
개발에서 유용하게 사용되는 대표적인 HTTP 요청 헤더이다. 본래 유저 에이전트(user-agent)라는 용어는 HTTP 요청을 시작하는 클라이언트 측의 프로그램을 말하며, 이러한 프로그램에는 웹 브라우저가 대표적이다.
다음 User-Agent 헤더의 예시를 살펴보면 사용된 브라우저의 종류와 운영체제 및 아키텍처의 정보, 웹 브라우저 렌더링 엔진의 종류 등이 명시되어 있는 것을 볼 수 있다.
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36
Plain Text
복사
구성 요소 | 설명 |
Mozilla/5.0 | 호환성을 위한 문자열로, 거의 모든 브라우저에서 포함됩니다.
역사적 이유로 남아 있음. |
(Windows NT 10.0; Win64; x64) | 운영 체제 정보: Windows 10, 64비트 |
AppleWebKit/537.36 | 렌더링 엔진 정보: 크롬 및 사파리에서 사용하는 WebKit 기반 |
(KHTML, like Gecko) | 과거 Gecko 엔진과의 호환성 명시 |
Chrome/114.0.0.0 | 브라우저 종류 및 버전 |
Safari/537.36 | 사파리 호환성 표시 |
Referer
Referer는 클라이언트(주로 브라우저)가 현재 요청을 보내기 직전에 머물렀던 웹 페이지의 URL을 나타내는 HTTP 요청 헤더이다. 이 헤더는 사용자가 어떤 링크를 클릭해서 현재 요청이 발생했는지를 서버에 알려주는 역할을 한다.
아래 요청은 사용자가 https://example.com/page1 페이지에 있다가, 그 페이지의 링크를 클릭하여 현재 요청이 발생했음을 의미한다.
Referer: https://example.com/page1
Plain Text
복사
응답 메시지에서 주로 활용되는 HTTP 헤더
HTTP 응답 메시지에서 주로 활용되는 대표적인 HTTP 헤더로는 Server, Allow, Location이 있다.
Server
Server 헤더는 클라이언트에게 응답을 보낸 서버 소프트웨어의 정보를 전달하는 HTTP 응답 헤더이다.
예를 들어 다음과 같은 Server 헤더를 통해 우분투 운영체제에서 동작하는 아파치 HTTP 서버에서 응답 메시지를 보냈음을 알 수 있다.
Server 정보를 통해 해커가 특정 취약점을 노리는 공격을 할 수 있어, 보안상 최소화하거나 제거하기도 한다.
Server: Apache/2.4.41 (Ubuntu)
Plain Text
복사
Allow
Allow 헤더는 클라이언트에게 해당 리소스에 대해 어떤 HTTP 메서드들이 허용되는지를 알려주는 응답 헤더이다.
Allow 헤더는 주로 405 Method Not Allowed 응답과 함께 사용되며, 허용되지 않는 메서드 요청에 대해 안내한다.
HTTP/1.1 405 Method Not Allowed
Allow: GET, POST
Bash
복사
Location
Location 헤더는 클라이언트에게 다른 URL로 리디렉션할 위치를 명시하는 헤더이다. 보통 3xx 상태 코드와 함께 사용된다.
HTTP/1.1 201 Created
Location: /users/123
Bash
복사
요청과 응답 메시지 모두에서 활용되는 HTTP 헤더
HTTP 요청, 응답 메시지 모두에서 주로 활용되는 대표적인 HTTP 헤더로는 Date, Content-Length, Content-Type, Content-Language, Content-Encoding, Connection이 있다.
Date
Date 헤더는 HTTP 메시지가 생성된 날짜와 시간을 명시하는 헤더로, 요청과 응답 모두에 사용될 수 있다.
이는 메시지의 시점을 기록하고, 캐싱이나 시간 기반 처리에 활용된다.
Date: Tue, 28 May 2025 12:34:56 GMT
Bash
복사
•
HTTP/1.1 표준에 따라 GMT(그리니치 평균시) 기준으로 표기된다.
•
형식은 RFC 1123 날짜 형식을 따른다.
Content-Length
Content-Length 헤더는 HTTP 메시지의 본문(body)의 크기(길이)를 바이트 단위로 나타낸다.
Content-Length: 348
Bash
복사
Content-Type, Content-Language, Content-Encoding
이 3개의 헤더는 메시지 본문이 어떻게 ‘표현’되었는지와 관련된 헤더라서 표현 헤더(representation header)라고 부르기도 한다.
Content-Type: application/json
Content-Type: text/html; charset=UTF-8
Plain Text
복사
Content-Language 헤더는 본문이 사용하고 있는 자연어의 언어 및 지역(locale) 정보를 명시한다.
주로 다국어 콘텐츠 제공 시 사용자의 언어 설정에 맞게 콘텐츠를 제공하고, 브라우저나 번역 도구에서 어떤 언어인지 판단하는 데 도움을 준다.
Content-Language: ko-KR
Content-Language: en-US
Plain Text
복사
Content-Encoding 헤더는 본문이 어떤 압축 방식으로 인코딩되었는지를 나타낸다.
클라이언트는 해당 인코딩 방식에 따라 본문을 디코딩하여 사용해야 한다.
주로 서버에서 대용량 응답 데이터를 압축하여 전송 속도를 최적화할 때 사용한다.
Content-Encoding: gzip
Content-Encoding: b44
Plain Text
복사
Connection
Connection 헤더는 클라이언트와 서버 간 TCP 연결을 어떻게 관리할지에 대한 설정을 나타낸다.
즉, 이 연결을 유지할지 끊을지, 혹은 특정 헤더만 현재 연결에 적용할지를 제어한다.
Connection: keep-alive
Connection: close
Plain Text
복사