CS 스터디

[웅's HTTP 완벽 가이드] 3장(1편) - HTTP 메시지 ( 메서드 총정리 )

CodeBoyEd 2021. 10. 17. 02:05

'HTTP 완벽 가이드' 책을 읽고 정리한 내용입니다.

 

출저: 인터넷 교보 문고

 

1장 HTTP 기초 링크 : https://codeboyed.tistory.com/17

2장 URL과 리소스 링크 :  https://codeboyed.tistory.com/19

 

3장은 HTTP 요청과 응답 시 사용되는 HTTP 메시지에 관한 내용입니다. 

내용이 상대적으로 많아서 1편과 2편으로 구성했습니다.

 

개발자 도구의 네트워크 탭을 열어, HTTP 메시지에 어떤 요소가 있는 지 한 번 보는 것도 좋을 것 같습니다.


3.1 메시지의 흐름

3.1.1 메시지는 원 서버 방향을 인바운드로 하여 송신된다.

HTTP는 인바운드와 아웃바운드라는 용어를 사용한다. 이는 트랜잭션의 방향을 표현하기 위함이다. 원 서버로 향하는 것은 인바운드로 이동하는 것이고( 서버가 경계를 치고 있으면, 그 경계 안으로 들어간다고 생각했다 ), 메시지가 사용자 에이전트로 돌아오는 것은 아웃바운드로 이동하는 것이다.

  • 인바운드 : 클라이언트 => 서버 방향
  • 아웃바운드 : 서버 => 클라이언트 방향

 

3.1.2 다운스트림으로 흐르는 메시지

HTTP 메시지는 강물과 같이 흐른다. 요청이든 응답이든 모든 메시지는 다운스트림 방향으로 흐른다. 즉, '업스트림'이나 '다운스트림'은 발송자와 수신자를 구별하기 위한 방향이지, 메시지가 서버를 향하냐 클라이언트를 향하냐에 대한 것이 아니다. 어느 방향이든 메시지가 보내지는 방향을 다운 스트림이라고 하고, 그 반대를 업스트림이라고 한다.

  • 클라이언트 => 서버 요청 : 서버로 가는 것이 "다운스트림" ( 반대가 업스트림 )
  • 서버 => 클라이언트 응답 : 클라이언트로 가는 것이 "다운스트림" ( 반대가 업스트림 )

 

3.2 메시지의 각 부분

HTTP 메시지는 클라이언트로부터의 요청이나 서버로부터의 응답 중 하나를 포함한다. 메시지는 시작줄, 헤더블록, 본문 이렇게 세 부분으로 이루어진다. 시작줄과 헤더는 줄 단위로 분리된 ASCII 문자열이다. 각 줄은 "캐리지 리턴"(ASCII 13)과 "개행 문자"(ASCII 10)로 구성된 "줄바꿈 문자열"로 끝난다. 이 줄바꿈 문자열은 "CRLF" 라고 쓴다. 하지만 견고한 애플리케이션이라면 그냥 개행 문자도 받아들일 수 있어야 한다. 오래되거나 잘못 만들어진 HTTP 애플리케이션들 중에서는 캐리지 리턴과 개행 문자 모두를 항상 전송하지는 않는 것들도 있다.

본문은 단순히 선택적인 데이터 덩어리이다. 시작줄이나 헤더와는 달리, 본문은 텍스트나 이진 데이터를 포함할 수도 있고 그냥 비어있을 수도 있다.

  • 예시
Content-type: text/plain

위 Content-Type 줄은 본문이 무엇인지 말해준다.

 

3.2.1 메시지 문법

모든 HTTP 메시지는 요청 메시지나 응답 메시지로 분류된다. 요청 메시지는 웹 서버에 어떤 동작을 요구한다. 응답 메시지는 요청의 결과를 클라이언트에게 돌려준다. 

 

요청 메시지의 형식은 다음과 같다.

 

응답 메시지의 형식은 다음과 같다. ( 시작줄에서만 문법이 다르다! )

 

 

3.2.2 시작줄

요청메시지의 시작줄은 무엇을 해야 하는지 말해준다. 응답메시지의 시작줄은 무슨 일이 일어났는 지 말해준다.

 

요청줄

요청줄에는 서버에서 어떤 동작이 일어나야 하는지 설명해주는 메서드와 그 동작에 대한 대상을 지칭하는 요청 URL이 들어있다. 또한 요청줄은 클라이언트가 어떤 HTTP 버전으로 말하고 있는지 서버에게 알려주는 HTTP 버전도 포함한다.

 

응답줄

응답 메시지는 수행 결과에 대한 상태 정보와 결과 데이터를 클라이언트에게 돌려준다. 응답 메시지에 쓰인 HTTP 버전, 숫자로 된 상태 코드, 수행 상태에 대해 설명해주는 사유 구절이 들어 있다.

 

시작줄에서는 필드 구분을 "공백"으로 한다.

 

메서드

요청의 시작줄에 위치한다.

'GET  /specialsaw.gif  HTTP/1.0' 이라는 줄에서 메서드는 'GET'이다. 아래는 HTTP 명세에서 정의하는 공통의 메서드 목록이다. 메서드에 따라 요청 메시지에 본문이 있는 경우도 있고 아닌 경우도 있다.

메서드 설명 메시지 본문이 있는가?
GET 서버에서 어떤 문서를 가져온다. 없음
HEAD 서버에서 어떤 문서에 대해 해더만 가져온다. 없음
POST 서버가 처리해야 할 데이터를 보낸다. 있음
PUT 서버에 요청 메시지의 본문을 저장한다. 있음
TRACE  메시지가 프락시를 거쳐 서버에 도달하는 과정을 추적한다. 없음
OPTIONS 서버가 어떤 메서드를 수행할 수 있는지 확인한다. 없음
DELETE 서버에서 문서를 제거한다. 없음

 

HTTP는 쉽게 확장할 수 있도록 설계되었기 때문에, 다른 서버는 그들만의 메서드를 추가로 구현했을 수도 있다. 이러한 추가 메서드는 HTTP 명세를 확장하는 것이기 때문에 확장 메서드라고 불린다.

 

상태코드

응답의 시작줄에 위치한다.

상태 코드는 클라이언트에게 무엇이 일어났는 지 말해준다. 'HTTP/1.0 200 OK'라는 줄에서 상태 코드는 200이다. 숫자로 된 코드는 사람이 읽기는 어렵지만 프로그램이 에러를 처리하기 쉽다. 아래 표는 상태 코드의 종류를 보여준다.

전체 범위 정의된 범위 분류
100 - 199 100 - 101 정보
200 - 299 200 - 206 성공
300 - 399 300 - 305 리다이렉션
400 - 499 400 - 415 클라이언트 에러
500 - 599 500 - 505 서버 에러

 

만약 우리가 인식할 수 없는 상태 코드를 받게 되면, 누군가가 현재 프로토콜의 확장으로 그것을 정의했을 가능성이 있다. 그 상태 코드를 그것이 포함되는 범주의 일반적인 구성원으로 가정하고 다뤄야 한다. 예를 들어, 상태 코드 515를 받게 되면 그 응답을 다른 5XX 메시지들과 마찬가지로 서버 에러를 의미한다고 생각해야 한다.

 

아래는 우리가 만나는 가장 흔한 상태 코드 몇 가지를 나열한 것이다.

상태 코드 사유 구절 의미
200 OK 성공! 요청한 모든 데이터는 응답 본문에 들어있다.
401 Unauthorized 사용자 이름과 비밀번호를 입력해야 한다.
404 Not Found 서버는 요청한 URL에 해당하는 리소르를 찾지 못했다.

 

사유 구절

사유 구절은 응답 시작줄의 마지막 구성 요소이다. 상태 코드와 일대일로 대응하며, 상태코드를 사람이 읽기 쉽게 글로 된 설명을 제공하는 부분이라고 생각하면 좋다. HTTP 명세는 사유 구절이 어때야 한다는 어떤 엄격한 규칙도 제공하지 않는다.

 

버전 번호

버전 번호는 요청과 응답메시지 양쪽 모두에 기술된다. HTTP 애플리케이션들이 자신이 따르는 프로토콜 버전을 상대방에게 말해주기 위한 수단이 된다. 버전 번호는 어떤 애플리케이션이 지원하는 가장 높은 HTTP 버전을 가리킨다. 때때로 이는 혼란을 일으키는데, HTTP/1.0 애플리케이션이 버전 번호가 HTTP/1.1로 된 응답을 받았을 때, 이를 HTTP/1.1 메시지라고 해석하는 경우가 있기 때문이다. 응답의 프로토콜 버전이 HTTP/1.1 이라는 것은 사실 응답으로 보낸 애플리케이션이 HTTP/1.1 까지 이해할 수 있음을 의미하는 것이다. 버전 번호는 소수점을 포함해서 크기를 비교하지 않는다. 무슨 말이냐면 HTTP/2.22 는 HTTP/2.3 보다 크다. 왜냐하면, 22는 3보다 큰 숫자이기 때문이다.

 

3.2.3 헤더

시작줄 다음에는 0개, 1개 혹은 여러개의 HTTP 헤더가 온다. HTTP 헤더 필드는 요청과 응답 메시지에 추가 정보를 더한다. 그들은 기본적으로 이름/값 쌍의 목록이다. 

 

각 HTTP 헤더는 간단한 문법을 가진다. 이름, 쉼표, 공백, 필드 값, CRLF  순서가 온다.

헤더의 예 설명
Date: Tue, 3 Oct 1997 02:16:03 GMT 서버가 응답을 만들어 낸 시각
Content-length: 15040 15,040 바이트의 데이터를 포함한 엔터티 본문
Content-type: image/gif 엔터티 본문은 GIF 이미지다.
Accept: image/gif, image/jpeg, text/html 클라이언트는 GIF, JPEG 이미지와 HTML을 받아들일 수 있다.

 

긴 헤더 줄은 그들을 여러 줄로 쪼개서 더 읽기 좋게 만들 수 있는데, 추가 줄 앞에서는 최소 하나의 스페이스 혹은 탭 문자가 와야 한다. 

 

예:

HTTP/1.0 200 OK

Content-Type: image/gif

Content-length: 85722

Server: Test Server

    Version 1.0

 

헤더의 환전한 값은 'Test Server Version 1.0'이다

 

3.2.4 엔터티 본문

엔터티 본문은 HTTP 메시지의 화물이라고 할 수 있다. HTTP 메시지는 이미지, 비디오, HTML 문서, 소프트웨어 어플리케이션, 신용카드 트랜잭션, 전자우편 등 여러 종류의 디지털 데이터를 실어 나를 수 있다.

 

3.3 메서드

모든 서버가 모든 메서드를 구현하지는 않는 다는 것에 주의하라. 서버는 자신의 리소스에 대해 GET과 HEAD 메서드만을 구현하는 것으로 충분한다. 예를 들어, DELETE와 PUT을 지원하는 서버는 아무나 저장된 리소스를 삭제할 수 있길 바라지는 않을 것이다. 이 제한은 일반적으로 서버 설정에 의해 정해지며, 따라서 사이트마다 또 서버마다 다를 수 있다.

 

3.3.1 안전한 메서드

GET과 HEAD 메서드는 안전하다고 할 수 있는데, 이는 GET이나 HEAD 메서드를 사용하는 HTTP 요청의 결과로 서버에 어떤 작용도 없음을 의미한다. 안전한 메서드가 서버에 작용을 유발하지 않는다는 보장은 없다. 안전한 메서드의 목적은, 서버에 어떤 영향을 줄 수 있는 안전하지 않은 메서드가 사용될 때 사용자들에게 그 사실을 알려주는 HTTP 애플리케이션을 만들 수 있도록 하는 것에 있다. 예를 들어 안전하지 않은 메서드를 담은 요청이 만들어졌고, 그 결과 서버에서 어떤 일이 일어날 수 있음을 알려주는 경고 메시지를 띄울 것이다. 

 

3.3.2 GET

GET은 가장 흔히 쓰이는 메서드이다. 주로 서버에게 리소스를 달라고 요청하기 위해 쓰인다. HTTP/1.1은 서버가 이 메서드를 구현할 것을 요구한다.

 

3.3.3 HEAD

HAED 메서드는 정확히 GET처럼 행동하지만, 서버는 응답으로 헤더만을 돌려준다. 엔터티 본문은 결코 반환되지 않는다.

  • 리소스를 가져오지 않고도 그에 대해 무언인가를 알아낼 수 있다.
  • 응답의 상태 코드를 통해, 개체가 존재하는지 확인할 수 있다.
  • 헤더를 확인하여 리소스가 변경되었는지 검사할 수 있다.

서버 개발자들은 반드시 반환되는 헤더가 GET으로 얻는 것과 정확히 일치함을 보장해야 한다. 또한 HTTP/1.1 준수를 위해서는 HEAD 메서드가 반드시 구현되어 있어야 한다.

 

3.3.4 PUT

PUT 메서드는 서버에 문서를 쓴다. PUT 메서드의 의미는, 서버가 요청의 본문을 가지고 요청 URL의 이름대로 새 문서를 만들거나, 이미 URL이 존재한다면 본문을 사용해서 교체하는 것이다. PUT은 콘텐츠를 변경할 수 있게 해주기 때문에, 많은 웹 서버가 PUT을 수행하기 전에 사용자에게 비밀번호를 입력해서 로그인을 하도록 요구할 것이다.

 

3.3.5 POST

POST 메서드는 서버에 입력 데이터를 전송하기 위해 설계되었다. 실제로, HTML 폼을 지원하기 위해 흔히 사용된다. 채워진 폼에 담긴 데이터는 서버로 전송되며, 서버는 이를 모아서 필요로 하는 곳 ( 예를 들면, 그 데이터를 처리할 서버 게이트웨이 프로그램 )에 보낸다.

 

3.3.6 TRACE

클라이언트가 어떤 요청을 할 때, 그 요청은 방화벽, 프락시, 게이트웨이 등의 애플리케이션을 통과할 수 있다. 이들에게는 원래의 HTTP 요청을 수정할 수 있는 기회가 있다. TRACE 메서드는 클라이언트에게 자신의 요청이 서버에 도달했을 때 어떻게 보이게 되는 지 알려준다.

TRACE 요청은 목적지 서버에서 '루프백' 진단을 시작한다. 요청 전송의 마지막 단계에 있는 서버는 자신이 받은 요청 메시지를 본문에 넣어 TRACE 요청을 되돌려 준다. 클라이언트는 자신과 목적지 서버 사이에 있는 모든 HTTP 애플리케이션의 요청/응답 연쇄를 따라가면서 자신이 보낸 메시지가 망가졌거나 수정되었는지, 만약 그렇다면 어떻게 변경되었는지 확인할 수 있다.

TRACE 메서드는 주로 진단을 위해 사용된다. 예를 들면 요청이 의도한 요청/응답 연쇄를 거쳐가는지 검사할 수 있다. 또한 프락시나 다른 애플리케이션들이 요청에 어떤 영향을 미치는 지 확인해보고자 할 때도 좋은 도구다.

 

3.3.7 OPTIONS

OPTIONS 메서드는 웹 서버에게 여러 가지 종류의 지원 범위에 대해 물어본다. 서버에게 특정 리소스에 대해 어떤 메서드가 지원되는 지 물어볼 수 있다. ( 몇몇 서버는 특정 종류의 객체에 대해 특정 동작만을 지원한다 )

 

3.3.8 DELETE

서버에게 요쳥 URL로 지정한 리소스를 삭제할 것을 요청한다. 그러나 클라이언트는 삭제가 수행되는 것을 보장하지 못한다. 왜냐하면 HTTP 명세는 서버가 클라이언트에게 알리지 않고 요청을 무시하는 것을 허용하기 때문이다. 

 

3.3.9 확장메서드

HTTP는 필요에 따라 확장해도 문제가 없도록 설계되어 있으므로, 새로 기능을 추가해도 과거에 구현된 소프트웨어들의 오작동을 유발하지 않는다. 확장 메서드는 HTTP/1.1 명세에 정의되지 않은 메서드다. 아래는 대표적인 예시이다.

메서드 설명
LOCK 사용자가 리소스를 잠글 수 있게 해준다. 예를 들어, 문서를 편집하는 동안 다른 사람이 동시에 같은 문서를 편집하지 못하도록 문서를 잠글 수 있다.
MKCOL 사용자가 문서를 생성할 수 있게 해준다.
COPY 서버에 있는 리소스를 복사한다.
MOVE 서버에 있는 리소스를 옮긴다.

 

만약 당신이 어떤 확장 메서드를 정의한다면, 그것은 대부분 HTTP 애플리케이션이 이해할 수 없을 것이다. 마찬가지로, 당시의 HTTP 애플리케이션이 이해할 수 없는 확장 메서드를 사용하는 에플리케이션과 마주칠 수도 있다.

 

프락시는, end-to-end 행위를 망가뜨리지 않을 수 있다면, 알려지지 않은 메서드가 담긴 메시지를 다운스트림 서버로 전달하려고 시도한다. 그렇지 않다면 프락시는 501 Not Implemented 상태 코드로 응답해야 한다.