HTTP 공부

DNS

amazon.com을 주소창에 입력하면 브라우저는 어떻게 처리할까요?

 https://www.amazon.com이라고 전체 URL을 입력하지 않아도 알고리즘을 통해 온전한 URI를 유추하고 DNS에서 적합한 IP를 매핑하여 접속합니다.
 보안 이슈로 요즘은 HTTP(포트 번호 80)이 거의 없고 HTTPS(포트 번호 443)이 표준이 됐습니다. 하지만 그렇다고 모든 웹이 HTTPS를 강제하진 않으며, DNS는 IP만 응답합니다. 그 때문에 개발자는 클라이언트가 HTTP로 요청을 보내도 HTTPS로 리다이렉트하도록 설정합니다.

엔트리

그러면 https://www.amazon.com나, 정확한 IP를 입력하면 무슨 응답이 올까요?

 웹은 "요청과 응답의 연속"입니다. 리소스를 요청하면 리소스를 응답합니다. 사이트마다 엔트리(진입점)은 다르지만, 흔히 index.html과 main.js를 가져와서 실행합니다. 웹은 결국 HTML, CSS, JS로 이루어져 있기 때문입니다. 웹사이트에 접속한다는 것은 CSS로 꾸며, JS로 동작하는 HTML을 보는 것입니다.
 URI는 스킴, 사용자 이름, 비밀번호, 호스트, 리소스 경로, 파라미터, 쿼리 등의 구조로 나뉘지만 일반 사용자는 호스트 정도만 사용합니다. 일반 사용자가 리소스 경로나 쿼리를 알기는 어려울 뿐더러, 안다고 해도 기억하거나 입력하는 건 불편하기 때문입니다.
 따라서 호스트만 입력해도 연결되는 리소스는 필수입니다. 그래서 amazon.com라고 입력해도 https://www.amazon.com/index.html로 접속하게 됩니다.

TCP

웹에서 텍스트는 어떻게 온전히 전달될까요?

예시 1

 서버가 "어서오세요!" 라는 메시지를 보낸다고 가정합시다. 어떤 상황에서도 "어서오요!"라는 깨진 글자를 받는 일은 없습니다.

예시 2

 느린 인터넷으로 블로그를 보려면 시간이 상당히 걸립니다. 우리는 4초간 화면이 멈췄다가 한 번에 불러와지는 것보다, 7초가 걸리더라도 순차적으로 화면이 불러와지는 사이트를 선호합니다. 이러한 사용자 경험은 중요합니다.
 그런데, 초반이나 중간 화면은 중간중간 깨지지만 최종 화면은 언제나 일정합니다. 어떻게 이런 무결성을 보장할까요?

TCP 연결

 이처럼 데이터 안정성은 중요한 문제입니다. 따라서 브라우저는 자신과 서버 포트 사이에 연결 통로를 구축해서 데이터를 주고받고, 체크합니다. 이를 TCP 연결이라 부릅니다.

  1. 서버가 소켓을 만들고 포트에 바인딩.
  2. 소켓에 대해 연결을 허용하고, 연결을 대기
  3. 클라이언트가 IP와 포트를 알아내면 소켓을 만들고 서버와 연결 시도
  4. 서버가 연결을 허가
  5. 클라이언트는 요청을 보내고 기다리다가 서버 응답을 받는다

데이터 순서 보장

 데이터는 한 번에 크게 오가지 않고 아주 작게 나뉘어 수많은 조각으로 전송됩니다. 이 때 패킷에 데이터 순번과 무결성이 적혀있고, 수신자는 데이터가 제대로 올 경우 잘 받았다고 응답하고, 안 오거나 잘못 온 것은 잘못됐다고 응답합니다. 이를 통해 송신자는 그 응답을 통해 데이터를 온전하게 보냅니다.

 이 방식은 연결을 만드는 절차 때문에 시간이 걸린다는 특징이 있고, 짤막한 요청이 수 백, 수 천 개가 될 경우 연결 구축에 시간 낭비는 엄청날 것입니다. 그러나 데이터의 무결성, 데이터의 순서, 데이터의 재전송 등을 보장한다는 강점이 있습니다. 일부 서비스에선 UDP처럼 속도 우선 프로토콜이 중요합니다만, 대부분 서비스에서는 TCP를 이용합니다.

타입

 모든 데이터에는 아래와 같은 MIME(Multipurpose Internet Mail Extesions) 라벨이 붙습니다.

Content-type: image/jpeg
Content-type: text/html

브라우저는 MIME을 보고 자신과 호환되는지 판단합니다. 예를 들면 IE 구버전에서 AVIF를 보려고 하면 못 읽는 것처럼요.

요청 메시지

 요청 메시지는 "누구에게", "무엇을", "어떻게" 해달라는 요청문입니다.

  • 요청 라인:
    GET www.literal.com/index.html HTTP/2.0(요청 메소드, URI, 통신 버전)
  • 헤더:
    User-agent: Mozilla/....(클라이언트의 어플 정보)
    Host: www.literal.com (호스트 이름)
    Accept: text/html, image/gif, /image/jpeg...
    Accept-Language: ko, en(한국어 -> 영어 순서로 응답해달라)

응답 메시지

 응답 메시지는 "무엇을", "어떻게" 보내겠다는 설명문입니다.

  • 응답 라인:
    HTTP/2.0 200 OK
  • 헤더:
    Date: 2024/02/02/15:22:32(서버가 응답한 시각)
    server: Apache/....(오리진 서버)
    Content-type: text/html
    Content-length: 1221(바이트)
    Last-modified: 2024/01/01(리소스가 최근에 수정된 시각)
  • 본문:
    <HTML><HEAD>...</BODY></HTML>

프록시

 프록시는 중개인이라는 뜻입니다. 클라이언트와 오리진 서버 사이에서 요청과 응답을 중개합니다. 필터링, 캐시, 분배 등 여러 역할을 수행하는 일종의 서버입니다.

세션

 세션은 브라우저 컨텍스트(새 탭으로 열기 할 때의 탭)를 가리키기도 하지만, 일반적으로 서버에 보관하는 임시적인 사용자 정보를 일컫습니다. 세션에는 쿠키보다 보안이 더 중요한 사용자 정보를 보관합니다. 주로 장바구니나 로그인 상태 등 사용자와의 소통 상태를 파악하는 동적이고 임시적인 정보를 보관합니다. 영구적이거나 민감한 개인 정보 등은 제외합니다.

로컬 스토리지, 세션 스토리지, indexedDB

 세션 스토리지는 임시적인 데이터 보관소입니다. 쿠키는 4kb 이하의 간결한 정보만 보관하고, 세션 스토리지는 내가 작성중이던 양식 내용, 이전 페이지 상태를 저장하는 등 좀 더 많은 용량이 요구되거나 더욱 일시적인 것들을 저장합니다. 세션(탭)을 종료할 시 사라집니다.
 로컬 스토리지는 브라우저를 종료해도 데이터를 계속 보관하며, 사용자 개인 설정 등 계속 사용되는 정보들을 저장합니다.
 indexedDB는 좀 더 대용량의 정보를 저장할 수 있으며 스토리지들보다 좀 더 자유로운 형태의 데이터를 보관합니다. 스토리지는 문자열 형태의 키-값만 저장하기 때문에 파싱과 직렬화가 필요하지만, indexedDB는 그런 과정을 거치지 않고 바로 저장이 가능합니다.
 GPT같은 AI 채팅에선 개인 맞춤화를 위해 indexedDB에 20만 자가 넘는 객체를 저장하기도 하는데, 이러한 데이터는 용량 제한이 작은 곳에 보관하기 힘들겠죠.

캐시 스토리지

 캐시 API 혹은 캐시 스토리지는 PWA(Progressive Web Application)을 위해 자주 사용되는 것으로, 오프라인 상태일 때에도 웹페이지를 온전히 보여주도록 기여합니다. 예를 들면 인스타그램은 피드들을 보는 중에 인터넷 연결이 끊기면 캐시한 피드와 사진들을 보여줌으로서 마치 인터넷이 여전히 연결된 것만 같은 사용자 경험을 제공합니다.
 PWA는 말 그대로 진보적인 웹 앱으로서, 전용 앱을 사용하는 듯한 경험을 제공하는 웹 앱입니다. 앱은 사용이 편리하지만 근래에는 설치가 귀찮다는 인식이 많아졌습니다. 이에 서비스 제공자들은 웹으로도 충분한 UX를 제공해야겠다는 생각으로 웹 앱을 개발합니다.
 캐시 스토리지는 오프라인 상황에만 대비하는 것은 아닙니다. 필요한 것들을 캐시해서 온라인에서 좀 더 빠른 반응을 할 수 있도록 돕기도 합니다.

리다이렉션

 리다이렉션은 여러 이유로 필연적입니다.

  1. 웹 서비스는 안정성 & 정확성 필요
  • 웹사이트 구조가 바뀌어도 올바른 페이지로 안내합니다.
  • HTTP로 시도해도 HTTPS로 자동 전환합니다.
  • 사용자 인증이 필요하면 인증 페이지부터 이동시킵니다.

2. 웹 페이지는 빠르게 로드돼야 함.

  • 사용자를 가까운 서버로 안내하여 로딩 시간을 줄입니다.
  • 캐시된 콘텐츠나 CDN으로 리다이렉트하여 응답 속도를 높입니다.
  • 모바일 기기용 최적화된 페이지로 자동 전환하여 로딩 속도를 개선합니다.

3. 데이터 전송량은 최소화하여 효율성 제고.

  • 불필요한 중복 콘텐츠 요청을 방지합니다.
  • 최적화된 리소스(예: 압축된 이미지)로 리다이렉트하여 데이터 사용량을 줄입니다.
  • 로드 밸런싱을 통해 서버 부하를 분산시키고 전체적인 네트워크 효율성을 높입니다.