아무것도 모르고 보내고 있었던 HTTP 메시지 - HTTP 완벽 가이드 3장

Broccolism·2023년 6월 6일
11
post-thumbnail

HTTP 완벽 가이드: 웹은 어떻게 동작하는가

3장. HTTP 메시지

웹 개발을 하면서 HTTP 메시지는 수도 없이 보내봤다. 내가 적은 코드에서 적어도 N만번의 HTTP 트랜잭션이 일어났을 것이다. 하지만 과연 나는 HTTP 메세지의 A to Z까지 모든 것을 알고 그런 코드를 적었을까? 3장을 읽으면서 든 생각은 '전혀 그렇지 않다' 이다.

3장 내용을 다 정리하기엔 내용도 많고 재미도 없을테니 그중에서 신선했던 내용만 적으려 한다. (사실 내 재미를 위해서다.^^)

먼저, 모든 HTTP 메세지는 요청이거나 응답이란 사실을 떠올리자.

HTTP 메시지의 구성

= 시작줄 + 헤더 (+ 본문)

  • 시작줄: 이 메세지의 정체가 무엇인지 보여준다.
  • 헤더: 이 메세지의 속성을 알려준다.
  • 본문: 이 메세지에서 전달하려는 데이터를 넣는다.

시작줄에 적혀있는 HTTP 버전은 사실

한가지 흥미로웠던건 시작줄이다. HTTP 시작줄은 이렇게 생겼는데...

----- 클라이언트의 요청 메세지 -----
GET /test/hello-world.txt HTTP/1.1
...

----- 서버의 응답 메세지 -----
HTTP/1.0 200 OK
...

여기서 HTTP/1.1, HTTP/1.0은 각각 '나는 HTTP 버전 1.1, 1.0로 작성된 메세지야'의 의미가 아니다. 이건 메세지에 대한 버전이 아니라 메세지를 전송한 서버에 대한 버전이다. 해당 서버가 지원하는 가장 높은 버전을 알려주기 위한 것이다. 즉, 위 상황은 '클라이언트는 HTTP 1.1까지, 서버는 1.0까지 지원한다.'라고 해석하는게 맞다.

메세지의 전달 방향과 용어

이번 기회에 확실히 짚고 넘어간 용어다. 서버 개발을 하다 보면 마이크로 서비스 아키텍처를 마주치게 되고 MSA를 만나면 아주 자연스럽게 이런 용어를 만나게 된다. 업스트림과 다운스트림, 그리고 인바운드와 아웃바운드. 이 둘은 모두 HTTP 메세지 전달과 관련있고 뭔가 비슷해보이지만 아주 다른 의미를 갖고 있다.

인바운드와 아웃바운드

서버 1대의 입장에서 바라본 HTTP 메세지의 흐름이다. 나는 서버다. 클라이언트가 내게 요청을 하나 보냈다. 이 요청은 내게로 들어온 요청이기 때문에 인바운드 메세지다. 그리고 내가 클라이언트에게 응답 메세지를 보낸다. 이 응답은 내 자신 밖으로 내보낸 요청이기 때문에 아웃바운드 메세지다.

업스트림과 다운스트림

이번에는 서버의 입장이 아닌 HTTP 메세지 입장에서 보자. HTTP 메세지는 항상 업스트림에서 다운스트림쪽으로 흐른다. 나는 클라이언트가 보낸 HTTP 요청 메세지이다. 내가 시작된 곳은 클라이언트고 도착한 곳은 서버다. 그래서 클라이언트는 서버의 업스트림이 되고 서버는 클라이언트의 다운스트림이 된다.

만약 목적지 서버까지 도달하기 전에 N개의 프록시 서버를 거쳤다면 이런 관계도 추가로 성립한다: 1번째 프록시 서버는 2번째 프록시 서버의 업스트림이고 2번째 프록시 서버는 1번째 프록시 서버의 다운스트림이다. .. (N-1)번째 프록시 서버는 N번째 프록시 서버의 업스트림이고 N번째 프록시 서버는 (N-1)번째 프록시 서버의 다운스트림이다. 물론 N번째 서버의 업스트림은 (N-1)번째 프록시 서버만 있는게 아니라 그 전에 거쳤던 모든 서버가 될 수 있다. 메세지는 업스트림에서 다운스트림으로 흐르기 때문이다.

이제 서버에서 응답을 보냈다고 해보자. 나는 HTTP 응답 메세지이다. 내가 시작된 곳은 서버고 도착한 곳은 클라이언트다. 이 때 업스트림은 서버, 다운스트림은 클라이언트가 된다. 즉, 같은 서버와 클라이언트더라도 업스트림이 될 수도 다운스트림이 될 수도 있다. 업/다운스트림을 결정하는 것은 '어느 쪽에서 이 HTTP 메세지를 보냈는가' 하는 것이다. HTTP 메세지는 항상 업스트림에서 다운스트림쪽으로 흐른다.

HTTP 메서드

다 아는 얼굴이구만

  • API 개발하면서 써먹은 메서드들. 아주 낯이 익다: GET, POST, DELETE, PUT, PATCH

...근데 얘네는 빼고 ㅎ

  • 잘 안 써본 메서드들: HEAD, TRACE, OPTIONS

잠시 이 책 원서의 출판 년도를 보자. 2002년도에 만들어진 이 책은 내가 딱 3살 때 나왔다. 어쩌면 이 글을 읽고 있는 몇몇 사람들보다 더 나이가 많은 책일 것이다. 현재 범용적으로 쓰이는 HTTP 버전은 2015년도에 나온 2.0이다. 그래서 이 사실을 잊지 말아야 한다: HTTP 기본을 다루고 있지만 현재는 쓰이지 않고 있을 수도 있다.

라고 적어놓고 잠깐 구글링을 하고 오니 다행히 저 위에 있는 메소드 중 없어진 메소드는 없는 것 같다. HTTP 2.0의 목표 중에 'HTTP/1.1 과의 호환성 유지'도 있기 때문인 것 같다.

안전한 메서드 - GET, HEAD

= 클라이언트의 요청이 서버의 리소스에 아무런 영향을 미치지 않는 메소드. 즉, GET 과 HEAD를 말한다.

HEAD 는 언제 쓰일까

GET은 알겠고 HEAD를 좀 더 보자. 서버는 HEAD 요청을 받으면 HTTP 메세지 구성 중 본문 부분을 제외하고 시작줄과 헤더만 보내야 한다. 이런식으로.

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 617

그러면 클라이언트는 실제 리소스를 받지도 않을거면서 HEAD 요청은 왜 보내는걸까? 메타데이터만 궁금하기 때문이다.

  • 리소스가 존재 여부만 필요할 때: 응답의 상태 코드를 통해 확인
  • 리소스의 변경 여부만 궁금할 때: content-type, content-length 로 확인
  • 리소스의 타입과 크기만 알고싶을 때: content-type, content-length 로 확인

메타데이터만으로도 생각보다 많은 정보를 얻을 수 있다.


여담으로 현재 Postman에서는 GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS 메소드만 들어가있는데 이건 왜인지 모르겠다. TRACE 메소드는 왜 없을까? 물론 저 창에다가 키보드로 TRACE를 입력하면 TRACE 요청도 보낼 수 있지만 왜 기본값에 안 들어있는지는 나중에 찾아봐야겠다.🤔

HTTP 응답 코드

응답 코드를 보면서 조금 궁금한게 생겨서 적었다. 바로 402 Payment Required 이다. 이 코드의 의미는 다음과 같다.

현재 이 상태 코드는 쓰이지 않지만, 미래에 사용될 가능성을 위해 준비해 두었다.

흠... 그러니까 HTTP 응답 코드 목록을 정할 당시에 이런 생각을 했다는걸까? - "지금은 무료로 HTTP 요청을 보낼 수 있지만 언젠가 그렇지 않게 될거란다." 그러니까 모든 HTTP 트랜잭션 하나하나가 유료화 되는 그런 상황말이다.

(그러면 이렇게 페이지 1개 들어갈 때마다 HTTP 트랜잭션이 여러개 생기는 홈페이지에는 아무도 들어가지 않으려 하지 않을까? 😇)

혹은 그냥 우리가 사용하고 있는 그 결제 시스템을 얘기하는걸까? 쇼핑몰에서 옷을 사거나 구독 서비스 결제를 할 때 돈을 내는 그런 것 말이다.

아쉽게도 여기에 대한 답은 찾지 못했다. 402 코드에 대해 찾아보면 '비공식적인 응답 코드'라면서 다들 알아서 사용하겠지~~ 라는 식의 답변이나 글이 많이 보인다. 개인적으로 내 지갑 사정을 생각하면 후자였으면 하지만, 전자를 의미한거라면 그거대로 꽤 재밌는 일이 벌어질 것 같다. HTTP 트랜잭션을 최소화 하기 위한 새로운 기술이 생겨나거나 이걸로 수익을 얻는 어둠의 단체가 등장하거나.. 뭐 이런 일이 벌어지지 않을까?

정리

오늘은 이런 내용을 집중적으로 살펴봤다.

  • HTTP 메세지 시작줄의 버전
  • HTTP 메세지의 흐름에 관한 용어
  • HTTP 메세지의 HEAD 메소드
  • HTTP 메세지의 402 응답 코드
profile
코드도 적고 그림도 그리고 글도 씁니다. 넓고 얕은 경험을 쌓고 있습니다.

0개의 댓글