- 출처: HTTP 절대 가이드
- HTTP 개요
HTTP 는 신뢰성 있는 데이터 전송 protocol 을 사용하여 손상없이 순서를 보장하면서 메시지를 전송한다. HTTP 가 웹 트래픽을 어떻게 전송하는지 알아보도록 하자.
- 리소스
웹 리소스라는 말을 들어봤을것이다. 리소스는 서버가 갖고 있는 웹 컨텐츠라고 할 수 있다. 리소스는 정적 리소스와 동적 리소스로 나눌 수 있다.
- 정적 리소스: text, HTML, jpeg, avi, 등이 있다. 이런 리소스들은 같은 이름으로 내용물을 변경하지 않는다면 같은 url 에 대해 항상 같은 컨텐츠를 반환한다.
- 동적 리소스: 사용자가 요청 시각에 따라 다른 컨텐츠를 생성하는 리소스를 말한다. 예를 들어 주식 거래 그래프의 경우 시간 흐름에 따라 다른 컨텐츠를 사용자에게 보여준다.
- 미디어 타입
인터넷은 단순한 text 부터 이미지, 동영상 등 수천가지 유형의 데이터를 다룬다. 그래서 이를 잘 지원하기 위해 각 객체에 MIME Type 이라는 데이터 형식 라벨을 붙이고 있다.
MIME(Multi purpose Internet Mail Extensions) Type 은 원래 각각 다른 메일 시스템의 문제를 해결하기 위해 도입되었는데 워낙 잘 동작하여 HTTP 에서도 채택하였다. 용어가 생소하게 들릴 수도 있지만 사실 우리가 사용하고 있는 지금 이 브라우저도 MIME Type을 적극 활용하고 있다.
크롬에서 F12 개발자 도구를 켜고 https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types 에 접속하면 페이지의 뼈대인 HTML 을 가져오면서 안에 내용들 및 필요한 여러 image 들을 요청한다. 이중 favicon 요청을 보면 서버가 Content-Type 응답 헤더로 image/png 라는 형식으로 반환한것을 확인할 수 있다. 이것이 바로 MIME Type 이며, 브라우저는 이 MIME Type 을 기준으로 화면에 사진을 뿌릴 지, 동영상을 보여줄지 등을 결정한다.
MIME Type은 아래처럼 2 가지 부분으로 나눌 수 있다. 그래서 여러 이미지의 MIME Type을 확인해보면 image/jpeg, image/png, image/gif 처럼 image 유형에서도 jpeg, png, gif 처럼 세부 유형으로 나눌 수 있다.
- 주 타입: image/png 에서 "/"의 앞부분인 image에 해당
- 부 타입: image/png 에서 "/"의 뒷부분인 png에 해당
- URI
HTTP 를 따로 공부하지 않았어도 URL 이라는 단어를 한번쯤 접해봤을것이다. 그리고 만약 Rest API 를 조금 정성스럽게 설계해본 경험이 있다면 URI 라는 단어도 들어봤을것이다. 각각의 정의를 아는것도 중요하지만 처음접하면 가장 헷갈리는 부분은 도대체 언제 URI 를 사용하고 언제 URL 이라는 용어를 사용하냐는 사실이다.
URI와 URL은 엄연히 다르지만 실질적으로 URI == URL 이라고 봐도 무방하다. URI 하위에 URL, URN 이 존재한다.
- URI: 서버의 특정 리소스를 지목하는 이름
- URL: http://test-host.com/logo.png 와 같이 위치(location) 기반으로 리소스를 지정하는 방법중 하나이다. 앞서 "실질적으로 URI == URL" 이라고 언급했던것은 현재 대부분의 URI 가 URL 이기 때문이다. 일반적으로 웹서핑을 하다가 URN 으로 지정하는 리소스를 본적이 있는지 한번 생각해보길 바란다.
- URN: URL 은 위치를 이동하면 영향을 받는다. 따라서 위치에 영향을 받지 않도록 고유한 이름을 지정하는 방식이다.
- 트랜잭션
HTTP 트랜잭션은 요청명령과 응답결과로 나눌 수 있다. 클라이언트는 서버로 요청 메시지를 보내며, 서버는 클라이언트에게 요청 메시지에 대한 응답을 한다.
naver.com 으로 test 라는 문자열을 검색하는 curl 요청을 날려보자. 굉장히 복잡한 text 들이 나오지만 맨 아래로 쭉 내려서 > 화살표와 < 화살표만 주목하면 된다. > 화살표는 내가 naver.com 으로 보낸 요청 메시지이며, < 부분은 naver.com 에서 나한테 준 응답 메시지이다.
~ % curl -o body.html -v "https://search.naver.com/search.naver?ie=UTF-8&query=test&sm=chr_hty"
...
> GET /search.naver?ie=UTF-8&query=test&sm=chr_hty HTTP/2
> Host: search.naver.com
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/2 200
< date: Sat, 29 Jun 2024 15:41:19 GMT
< content-type: text/html; charset=UTF-8
< vary: Accept-Encoding
< set-cookie: page_uid=iosrcwqo1SCssFhcntRssssstpR-223609; path=/; domain=.naver.com
< set-cookie: _naver_usersession_=Vuk/PCpSjYhsWErCX9zKoQ==; path=/; expires=Sat, 29-Jun-24 15:46:19 GMT; domain=.naver.com
< x-frame-options: SAMEORIGIN
< x-xss-protection: 1; report=/p/er/post/xss
< cache-control: no-cache, no-store, must-revalidate, max-age=0
< pragma: no-cache
< referrer-policy: unsafe-url
< vary: Accept-Encoding
< server: nxg
< accept-ch: Sec-CH-UA, Sec-CH-UA-Arch, Sec-CH-UA-Bitness, Sec-CH-UA-Form-Factors, Sec-CH-UA-Full-Version-List, Sec-CH-UA-Mobile, Sec-CH-UA-Model, Sec-CH-UA-Platform, Sec-CH-UA-Platform-Version, Sec-CH-UA-WoW64
<
{ [12300 bytes data]
요청 메시지를 분석해보면 아래와 같다.
- GET: HTTP 메서드이며, POST, PUT 등의 기타 메서드도 존재한다. 모든 HTTP 요청은 1개의 메서드를 가지며 만약 Rest API를 심각하게 설계하고자 한다면 메서드에 대해서도 잘 알아야 한다.
- /search.naver? ~ chr_thu: naver.com 으로 보낸 URI
- HTTP/2: HTTP version
- Host: search.naver.com ~ Accept: */*: HTTP 요청 header
응답 메시지는 아래와 같다.
- HTTP/2 200: HTTP/2 version 이며, HTTP 상태코드로 정상 응답(200)을 반환하였다. HTTP 상태코드 역시 Rest API를 잘 설계하고자 한다면 잘 알아야 하는 부분이다.
- 그외 ":" 으로 구분된 행들: HTTP 응답 header
- [12300 bytes data]: curl에서 -o body.html 로 결과를 html 파일로 저장하라고 했기 때문에 간략히 표시되었다. 원래 해당 option이 없다면 naver.com 에서 반환한 html 문자열이 모두 출력된다.
- TCP 커넥션
HTTP 와 더불어 TCP 라는 말을 들어본적이 있을것이다. TCP (Transmission Control Protocol) 는 어떻게 메시지가 TCP 커넥션을 통해 다른곳으로 가는지에 대한 전송 제어 수준의 protocol 이다.
이쯤되면 HTTP 와 어떤 차이가 있는지 헷갈리게 되는데 HTTP는 Application 계층 protocol 이며, 네트워크 통신의 핵심 세부사항에 대해서는 신경쓰지 않는다.
종합해보면 Application 계층인 HTTP는 자신의 메시지를 전송하기 위해 전송 계층인 TCP 를 사용하며, TCP는 네트워크 계층인 IP 위의 계층이다.
메시지를 전송하기 전에 클라이언트는 IP 주소와 port 번호로 서버에 접속하게 된다. 그런데 브라우저와 같은 클라이언트로 naver 에 접속해서 검색할 때 IP 주소로 접속한적이 있는가? IP 주소는 Host 인 naver.com 으로 알아낼 수 있는데 DNS 를 거치면 IP를 획득할 수 있다. 웹 브라우저가 서버에 접속하는 과정은 아래와 같다.
- 서버의 URL 에서 Host 명 추출
- Host -> IP 변환 및 Port 번호 추출
- IP와 Port 번호로 서버와 TCP Connection 연결
- 웹 브라우저가 서버로 HTTP 요청 전송
- HTTP 응답 수신
- Connection close
댓글