목차

HTTP

HyperText Transfer Protocol (하이퍼텍스트 전송 프로토콜). 월드 와이드 웹의 기반이 되는 그 프로토콜로, 인터넷 주소창에서 허구한 날 나오는 그 http://의 원천이다(URI스킴 참고). 어떤 리소스(HTML 파일 등등)를 가리키는 URL을 줬을 때 그 URL에 대한 권한이 있는 호스트(authority)를 찾은 뒤(이 부분은 DNS) 그 호스트로부터 실제 리소스를 받아 오는 부분이 HTTP로 이루어진다. 최신 버전은 1999년에 나온 HTTP/1.1.

HTTP는 TCP IP 위에 위치한 어플리케이션 레이어에 속하며, 기본적으로는 TCP포트 80을 사용한다.1) 꼭 80을 써야 할 필요는 없으며, 따라서 종종 여는데 루트 권한이 필요 없는 8000, 8008이나 8080 포트를 대신 사용하는 경우도 볼 수 있다(뒤의 두 개는 IANA에도 "HTTP Alternative"로 등록되어 있다).

고수준 구조

HTTP는 기본적으로 (TCP이니만큼) 클라이언트서버에게 특정한 리소스에 대한 요청(request)을 보내면 그 리소스를 담은 응답(response)을 되돌려 보내는 프로토콜로, FTP 같은 류의 비슷한 프로토콜과는 달리 세션의 개념이 없다(stateless). 다른 말로 하면, 서버가 응답을 보냈을 때 클라이언트의 상태를 절대적으로 바꾸는 방법은 없으며, 단지 클라이언트가 상태가 바뀐 척 행동해 달라고 요청하는 것만 가능하다(대표적인 방법으로 HTTP쿠키 참고). 클라이언트가 이 요청을 무시하면(이를테면, 쿠키를 허용하지 않는 등의 방법으로) 서버는 클라이언트의 상태에 대해 어떤 예상도 할 수 없다. 이런 의미에서 HTTP는 클라이언트보다는 서버에게 더 큰 부담을 지우는 프로토콜로, 여기에는 몇 가지 중요한 장점이 있으니:

물론 현재의 웹에서 이런 특성이 항상 장점인 것만은 아니다:

저수준 구조

HTTP는 텍스트 기반 프로토콜로 그 모습은 첫 줄을 제외하면 흡사 MIME과 유사하게 헤더와 데이터로 이루어져 있다. (사실은 MIME 컨텐트 타입도 함께 쓴다.) 첫 줄은 클라이언트와 서버가 서로 다르며, 클라이언트의 경우 요청하는 URL, 메소드(GET, POST 따위) 및 HTTP 버전이, 서버의 경우 상태 코드(200, 404 따위) 및 HTTP 버전이 들어 간다.

그 뒤에 따르는 HTTP 헤더는 해당 요청 및 응답에 부가적으로 따라 붙는 정보들을 담고 있으며, 이를테면 클라이언트가 보는 서버의 도메인(Host), 뒤에 따를 데이터의 종류 및 길이(Content-TypeContent-Length), 쿠키 정보(CookieSet-Cookie), 클라이언트가 서버 측에게 원하는 데이터의 구체적인 종류(Accept, Accept-Language 등), 클라이언트가 마지막으로 접근한 뒤 서버 쪽에 바뀐 게 있는지 확인하는 데 쓰는 헤더(If-Modified-Since 등), 서버 소프트웨어 정보와 서버 측 시각(ServerDate), 클라이언트 소프트웨어 정보(User-Agent)까지 온갖 것들이 다 들어 가 있다. 이 헤더 및 첫 줄의 내용에 따라서 뒤에 데이터가 올 수도 있고 안 올 수도 있는데, 이를테면 클라이언트가 GET 메소드로 요청을 보낼 경우나, 서버가 클라이언트의 마지막 접근 뒤로 아무 것도 바뀐 게 없음을 알릴 경우(상태 코드가 304인 경우) 등등의 경우에 데이터가 생략될 수 있다.

HTTP 메소드

HTTP 메소드는 크게 "안전한"(safe) 메소드와 안전하지 않은 메소드로, 또는 "반복 가능한"(idempotent) 메소드와 그렇지 않은 메소드로 분류할 수 있다. 전자는 일반적으로 서버의 상태를 변경하지 않는 메소드를 일컫으며, 후자는 말 그대로 여러 번 같은 요청을 보내도 서버의 상태를 바꾸지 않는(아예 안 보내는 것과는 별개이다) 메소드를 일컫는다. 실질적으로 이러한 특성이 제대로 지켜지는가는 미지수이지만(…) 많은 클라이언트가 이 특성에 의존하고 있으므로 웬만하면 서버측이 이 특성에 따르는 것이 후일의 이상한 버그를 방지할 수 있을 것이다.2)

OPTIONS (안전, 반복 가능)
해당 리소스에 적용 가능한 메소드 목록을 나열한다. URL 대신 *을 사용했다면 서버가 지원하는 메소드 목록을 얻을 수 있다.
HEAD (안전, 반복 가능)
해당 리소스를 요청은 하되 실제 데이터는 빼고 헤더만 받아 온다. 디버깅을 한다거나, 리소스의 변경 날짜만 알고 싶은 경우 등에 유용하다.
GET (안전, 반복 가능)
해당 리소스를 요청한다. 리소스는 해당 요청에 의해 크게 변경되어서는 안 된다(하지만 많은 사람들이 이 규칙을 무시하는 경향이 있다). GET 요청에는 데이터가 붙을 수 없으며, 만약 데이터를 넣고 싶다면 URL에만 추가할 수 있기 때문에 큰 데이터를 붙여 넣을 수는 없다(보통 서버 소프트웨어가 제한을 걸기 때문에).
POST
해당 리소스에게 주어진 데이터를 처리할 것을 요청한다. 데이터가 없을 수도 있는데 이 경우 URL만 가지고 무슨 일을 할 지를 결정하게 된다(이를테면 글 삭제라거나). GET과 더불어 매우 자주 쓰이며, 본래 PUT이나 DELETE 등의 메소드가 해야 할 일이 웹 브라우저들의 지원 부족 때문에 POST로 처리되는 경우도 흔히 볼 수 있다.
PUT (반복 가능)
주어진 데이터를 서버에 올릴 것을 요청한다. 해당 리소스가 이미 존재한다면 주어진 데이터로 그 리소스를 갱신한다. 현실에서는 POST에 묻혀서 거의 쓰이지 않는다.
DELETE (반복 가능)
해당 리소스를 삭제할 것을 요청한다. 해당 리소스가 이미 삭제되었든지 아예 원래 없었든지 아무튼 존재하지 않는다면 아무 일도 일어나지 않는다. 현실에서는 POST에 묻혀서 거의 쓰이지 않으며, 심지어 PUT보다도 안 쓰인다.
TRACE (안전, 반복 가능)
주어진 요청을 그대로 되돌려 보낸다. 중간에 프록시 서버가 끼어 있을 경우 중간에 무슨 변경이 일어나는지 확인하는 데 유용하다.
이 밖에도 다른 확장에 의해 HTTP 메소드가 추가되는 경우도 있는데, 예를 들어 HTTP프록시에서 연결을 변경하는 데 사용하는 CONNECT, WebDAV에서 쓰이는 PROPFIND 등등이 있다. 등록된 HTTP 확장 메소드의 목록은 별도의 문서에서 볼 수 있다.

상태 코드

상태 코드는 세 자리 숫자로, 그 범위에 따라서 크게 다섯 개로 나뉜다:

주로 볼 수 있는 상태 코드는 다음과 같다:

200 OK
요청했던 리소스가 응답의 데이터 부분에 들어 있다.
206 Partial Content
요청했던 리소스의 "일부분"이 응답의 데이터 부분에 들어 있다. 이는 요청에 Content-Range 헤더가 들어 있을 경우에 해당하며, 분할다운로드를 할 때 흔히 볼 수 있다.
301 Moved Permanently
요청했던 리소스가 주어진 URL로 영구적으로 이동했으므로 다음부터는 그 URL을 써야 한다.
302 Found
요청했던 리소스가 주어진 URL로 임시로 이동했음을 나타낸다. 그러나 POST 메소드의 경우 대부분의 웹 브라우저들이 표준과는 다른 동작을 하기 때문에, 웬만하면 303이나 307을 대신 써야 한다.
303 See Other
요청했던 리소스가 주어진 URL로 임시로 이동했으며, 다음 요청에 대해서는 항상 GET 메소드를 써야 한다.
304 Not Modified
요청한 리소스는 마지막으로 클라이언트가 기억하고 있던 것에서 변경 사항이 없다.
307 Temporary Redirect
요청했던 리소스가 주어진 URL로 임시로 이동했으며, 다음 요청은 이번 요청과 같은 메소드를 써야 한다.
401 Unauthorized
요청을 수행하려면 인증이 필요하다. 응답에는 WWW-Authenticate 헤더가 포함되며, 후의 요청이 올바른 응답을 Authorization 헤더로 보내 주면 요청을 수행할 수 있다. 그러나 인터페이스를 마음대로 바꿀 수가 없기 때문에 대부분의 로그인 폼에서는 그냥 POST 메소드를 쓰는 경우가 많다(…).
403 Forbidden
요청을 거절한다. 보통 권한이 없어서 나는 오류인 경우가 많다.
404 Not Found
요청한 리소스는 존재하지 않는다. 아마도 가장 유명한(200이나 304보다도 더 유명한) 상태 코드일 것이다. 자세한 내용은 HTTP 404 참고.
500 Internal Server Error
서버 문제로 요청을 처리하지 못 했다. 말 그대로 어떤 서버 문제에 대해서도 쓸 수 있는 만능(…) 상태 코드로, 서버가 부하가 걸려서 사용할 수 없을 때 쓰는 코드 503이 있긴 하지만 보통 그런 상황에서는 그냥 응답이 안 오는 게 보통이다.

표준

HTTP는 크게 세 개의 주요 버전이 존재했다:

현재 거의 모든 소프트웨어는 HTTP/1.0과 HTTP/1.1을 올바르게 처리할 수 있으며, 클라이언트 단에서는 HTTP/1.1이 보편화되었다. HTTP/2.0에 대한 논의는 한동안 존재했으나 대부분의 경우 HTTP/1.1에 대한 확장이나 HTTP의 탈을 쓴 전혀 다른 프로토콜(WebSocket, WAKA, SPDY 등)로 귀결되고 말았다. (그러나 앞으로 후자가 탄력을 얻으면 HTTP/2.0의 일부가 될 가능성도 배제할 수는 없다.)

바깥 링크

1) 인터넷할당번호관리기관(IANA)은 UDP포트 80도 할당해 놓고 있지만, 이건 TCP 포트를 할당하면 가능한한 같은 UDP 포트도 할당해야 한다는 원칙 때문이지 실제로 쓴다는 건 아니다…
2) lifthrasiir는 게시판에 GET 메소드로 글 삭제가 가능하게 만들어서 검색 엔진 봇이 한 번 긁어 갈 때마다 게시판의 모든 글이 삭제되는 사태가 발생했다는 전설을 들은 바가 있다…