HTTP 심층 탐구: 헤더, 캐시, 쿠키와 콘텐츠 협상

Murhyun2·2025년 5월 7일
0

네트워크

목록 보기
7/7

안녕하세요! 웹 개발의 기초가 되는 HTTP에 대해 더 깊이 알아보는 시간을 가져보겠습니다. 오늘은 HTTP 헤더의 다양한 종류와 역할, 웹 성능을 최적화하는 캐시, 사용자의 상태를 기억하는 쿠키, 그리고 사용자에게 최적의 콘텐츠를 제공하기 위한 콘텐츠 협상까지 자세히 살펴보겠습니다.

HTTP 헤더 (HTTP Headers)

HTTP 메시지는 헤더(Header)와 본문(Body)으로 구성되며, 헤더에는 해당 요청 또는 응답에 대한 부가 정보가 담겨있습니다. 이 정보들은 클라이언트와 서버 간의 원활한 통신을 돕는 중요한 역할을 합니다. 헤더는 여러 필드들로 구성되며, 각 필드는 이름과 값을 가집니다.

HTTP 요청 시 주로 사용되는 헤더

클라이언트가 서버로 요청을 보낼 때 주로 사용되는 헤더들입니다.

  • Host: 요청하는 서버의 도메인 이름과 포트 번호를 명시합니다. 예를 들어 Host: www.example.com과 같이 사용됩니다. 포트 번호가 표준 포트(HTTP의 경우 80, HTTPS의 경우 443)가 아닐 경우 함께 포함될 수 있습니다 (예: Host: www.example.com:8080).
  • User-Agent: 요청하는 클라이언트(예: 웹 브라우저, 모바일 앱)의 정보를 담습니다. 운영체제, 브라우저 종류 및 버전, 렌더링 엔진 등 다양한 정보를 포함할 수 있습니다. 서버는 이 User-Agent 정보를 보고 클라이언트의 접속 환경을 판단하여 최적화된 응답을 제공할 수 있습니다.
    • 예: User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36
  • Referer: 현재 요청을 보내게 된 이전 웹 페이지의 URL을 명시합니다. 예를 들어, 사용자가 https://en.wikipedia.org 페이지에 있는 링크를 클릭하여 현재 페이지로 이동했다면, Referer 헤더 값은 https://en.wikipedia.org가 됩니다. 이를 통해 유입 경로 분석 등에 활용될 수 있습니다. ('Referrer'가 올바른 철자이지만, 역사적인 이유로 'Referer'로 사용됩니다.)
  • Authorization: 클라이언트의 인증 정보를 서버에 전달할 때 사용됩니다. 다양한 인증 방식이 있으며, 대표적으로 Basic 인증 방식이 있습니다.
    • Basic 인증: username:password 형태의 문자열을 Base64로 인코딩하여 인증 정보로 사용합니다.
      • 예: minchul:1234 → (Base64 인코딩) → bWluY2h1bDoxMjM0
      • 헤더 예: Authorization: Basic bWluY2h1bDoxMjM0
      • 참고: Base64 인코딩은 암호화가 아니므로, Basic 인증은 반드시 HTTPS와 함께 사용되어야 안전합니다.

HTTP 응답 시 주로 사용되는 헤더

서버가 클라이언트로 응답을 보낼 때 주로 사용되는 헤더들입니다.

  • Server: 응답을 생성한 웹 서버의 소프트웨어 관련 정보를 나타냅니다.
    • 예: Server: Apache/2.4.41 (Unix) (Unix 운영체제에서 동작하는 아파치 HTTP 서버)
  • Allow: 해당 리소스에 대해 클라이언트에게 허용된 HTTP 메서드 목록을 알려주기 위해 사용됩니다.
    • 예: Allow: GET, HEAD, POST
  • Retry-After: 서비스가 일시적으로 사용 불가능할 때 (예: 상태 코드 503 Service Unavailable 응답 시) 클라이언트에게 얼마 후에 다시 시도해야 하는지를 알려줍니다. 값은 구체적인 날짜/시간 또는 초 단위로 지정할 수 있습니다.
    • 날짜/시간 예: Retry-After: Fri, 23 Aug 2024 09:00:00 GMT (2024년 8월 23일 금요일 09시 이후에 사용 가능)
    • 초 단위 예: Retry-After: 120 (120초 이후에 사용 가능)
  • Location: 클라이언트에게 요청한 자원이 다른 위치로 이동되었음을 알리거나(예: 301 Moved Permanently, 302 Found 응답 시), POST 요청 후 새로운 리소스의 위치를 알려줄 때 사용됩니다. 브라우저는 이 헤더 값을 보고 해당 URL로 자동 리디렉션합니다.
    • 예: Location: /new-page.html
  • WWW-Authenticate: 리소스에 접근하기 위해 필요한 인증 방식을 클라이언트에게 알릴 때 사용되며, 주로 상태 코드 401 Unauthorized 응답과 함께 전송됩니다.
    • 예: WWW-Authenticate: Basic realm="My Application" (Basic 인증을 요구하며, 인증 영역(realm)의 이름은 "My Application"임을 알림)

HTTP 인증 과정 (Authorization & WWW-Authenticate)

  1. 클라이언트가 보호된 리소스에 인증 정보 없이 접근을 시도합니다.
  2. 서버는 401 Unauthorized 응답과 함께 WWW-Authenticate 헤더를 전송하여 필요한 인증 방식(예: Basic)을 알립니다.
  3. 클라이언트는 사용자로부터 인증 정보(예: 아이디, 비밀번호)를 입력받아, WWW-Authenticate 헤더에서 지정한 방식에 따라 인증 정보를 가공하여 (예: Base64 인코딩) Authorization 헤더에 담아 다시 요청합니다.
  4. 서버는 Authorization 헤더의 인증 정보를 검증하고, 유효하면 요청된 리소스를 제공합니다.

HTTP 요청과 응답 모두에서 주로 사용되는 헤더

요청과 응답 양쪽 모두에서 사용될 수 있는 일반적인 헤더들입니다.

  • Date: HTTP 메시지가 생성된 날짜와 시각 정보를 나타냅니다. (RFC 1123 형식)
    • 예: Date: Tue, 06 May 2025 12:00:00 GMT
  • Connection: 현재의 전송이 완료된 후 네트워크 접속을 유지할지 말지를 제어합니다.
    • Connection: keep-alive (지속 연결을 희망)
    • Connection: close (연결 종료를 희망)
  • Content-Length: 메시지 본문(payload)의 길이를 바이트 단위로 나타냅니다.
  • Content-Type, Content-Language, Content-Encoding: 이들은 표현 헤더(Representation Headers)의 일종으로, 메시지 본문의 내용에 대한 구체적인 정보를 제공합니다.
    • Content-Type: 본문의 미디어 타입(MIME 타입)을 명시합니다.
      • 예: Content-Type: text/html; charset=utf-8, Content-Type: application/json, Content-Type: image/jpeg
    • Content-Language: 본문이 표현하는 자연어를 명시합니다.
      • 예: Content-Language: ko-KR, Content-Language: en-US
    • Content-Encoding: 본문에 적용된 압축 또는 변환 방식을 명시합니다. 클라이언트는 이 정보를 바탕으로 본문을 올바르게 디코딩할 수 있습니다.
      • 예: Content-Encoding: gzip, Content-Encoding: deflate

캐시 (Cache)

캐시는 불필요한 네트워크 트래픽을 줄이고, 웹 페이지 로딩 속도를 향상시키기 위해 정보의 사본을 임시로 저장하는 기술입니다. 한 번 받아온 데이터를 재사용함으로써 응답 지연을 방지하고 더 빠르게 데이터에 접근할 수 있게 해줍니다.

캐시의 종류

  • 개인 전용 캐시 (Private Cache): 특정 사용자 전용으로 사용되는 캐시입니다. 웹 브라우저에 저장되는 캐시가 대표적이며, 해당 사용자만 접근할 수 있습니다.
  • 공용 캐시 (Public Cache): 여러 사용자가 공유할 수 있는 캐시입니다. 클라이언트와 원 서버 사이에 위치한 프록시 서버나 CDN(Content Delivery Network)에 저장되는 캐시가 이에 해당합니다.

캐시의 유효 기간 설정

서버는 응답 헤더를 통해 캐시의 유효 기간을 설정할 수 있습니다. 예를 들어, Cache-Control 헤더의 max-age 지시자를 사용하거나 Expires 헤더를 사용하여 캐시가 얼마나 오랫동안 유효한지를 명시할 수 있습니다.

  • 예시: 캐시의 유효 시간을 2024년 2월 6일 화요일 12:00:00까지로 설정하거나, Cache-Control: max-age=1200 (1200초 동안 유효)으로 설정할 수 있습니다.

캐시 신선도 검사 방법

캐시된 데이터가 여전히 유효한지(신선한지) 확인하는 과정입니다. 유효 기간이 지난 캐시는 원 서버에 변경 사항이 있는지 확인해야 합니다.

  1. 날짜를 이용한 검사 (If-Modified-Since):
    클라이언트는 캐시된 리소스의 마지막 변경 날짜를 If-Modified-Since 요청 헤더에 담아 서버에 보냅니다.

    • 예: If-Modified-Since: Fri, 23 Aug 2024 09:00:00 GMT
      서버는 이 날짜 이후에 리소스가 변경되었는지 확인합니다.
    • 변경되지 않았다면: 서버는 304 Not Modified 응답을 보내고, 클라이언트는 캐시된 버전을 사용합니다.
    • 변경되었다면: 서버는 200 OK 응답과 함께 새로운 리소스를 본문에 담아 보냅니다.
  2. 엔티티 태그 (Entity Tag - Etag)를 이용한 검사 (If-None-Match):
    Etag는 특정 버전의 리소스를 식별하는 고유한 문자열입니다. 서버는 리소스를 제공할 때 Etag 응답 헤더에 이 값을 포함시킵니다.

    • 예: Etag: "abc"
      클라이언트는 캐시된 리소스의 Etag 값을 If-None-Match 요청 헤더에 담아 서버에 보냅니다.
    • 예: If-None-Match: "abc"
      서버는 현재 리소스의 Etag와 클라이언트가 보낸 Etag를 비교합니다.
    • 일치한다면 (변경되지 않음): 서버는 304 Not Modified 응답을 보냅니다.
    • 일치하지 않는다면 (변경됨): 서버는 200 OK 응답과 함께 새로운 리소스 및 새로운 Etag를 보냅니다.

쿠키는 서버가 사용자의 웹 브라우저에 저장하는 작은 데이터 조각입니다. HTTP는 기본적으로 상태를 유지하지 않는(stateless) 프로토콜이기 때문에, 쿠키는 이러한 한계를 보완하여 사용자의 로그인 상태, 장바구니, 사이트 설정 등과 같은 정보를 클라이언트 측에 저장하고 재사용할 수 있도록 합니다.

쿠키의 동작 방식

  1. 서버에서 클라이언트로 쿠키 전송: 서버는 Set-Cookie 응답 헤더를 통해 클라이언트에게 쿠키의 이름과 값, 그리고 만료일, 경로 등의 속성을 전달합니다.
    • 예: Set-Cookie: sessionId=38afes7a8; HttpOnly; Secure
  2. 클라이언트의 쿠키 저장 및 전송: 브라우저는 서버로부터 받은 쿠키를 저장해두었다가, 동일한 서버(또는 쿠키에 명시된 도메인/경로 조건에 맞는)에 요청을 보낼 때마다 Cookie 요청 헤더에 해당 쿠키들을 담아 자동으로 전송합니다.
    • 예: Cookie: sessionId=38afes7a8; anotherCookie=value

쿠키의 주요 속성 및 제한

쿠키는 다양한 속성을 통해 동작을 제어할 수 있습니다.

  • 도메인(Domain) 및 경로(Path) 제한: 쿠키가 전송될 서버의 도메인과 URL 경로를 지정하여, 특정 사이트나 경로에서만 쿠키가 사용되도록 제한할 수 있습니다.
  • 유효 기간(Expires/Max-Age): 쿠키의 만료 날짜(Expires)나 최대 수명(Max-Age)을 설정하여 쿠키가 얼마나 오랫동안 유지될지를 정할 수 있습니다. 설정하지 않으면 세션 쿠키로 동작하여 브라우저가 닫힐 때 삭제됩니다.
  • Secure: 이 속성이 설정된 쿠키는 HTTPS 프로토콜을 통해서만 전송됩니다. 암호화되지 않은 HTTP 연결에서는 전송되지 않아 중간자 공격으로부터 쿠키를 보호합니다.
  • HttpOnly: 이 속성이 설정된 쿠키는 JavaScript와 같은 클라이언트 측 스크립트를 통해 접근할 수 없습니다. document.cookie 등으로 쿠키를 읽거나 수정하는 것을 막아, XSS(Cross-Site Scripting) 공격을 통해 쿠키가 탈취되는 것을 방지하는 데 도움을 줍니다.

콘텐츠 협상과 표현 (Content Negotiation and Representation)

콘텐츠 협상(Content Negotiation)은 클라이언트와 서버가 동일한 URL(URI)에 대해 여러 가지 버전의 리소스가 존재할 때, 클라이언트에게 가장 적합한 형태의 리소스를 제공하기 위한 메커니즘입니다. 예를 들어, 같은 콘텐츠라도 한국어 버전과 영어 버전이 있거나, HTML 형식과 JSON 형식이 있을 수 있습니다.

표현(Representation)은 서버와 클라이언트 간에 실제로 전송되는 자원의 특정 형태를 의미합니다. 이는 특정 언어, 미디어 타입, 문자 인코딩 등으로 구체화될 수 있습니다.

클라이언트는 요청 헤더(주로 Accept, Accept-Language, Accept-Encoding 등)를 사용하여 자신이 선호하는 표현 형식을 서버에 알립니다.

콘텐츠 협상 예시

  • 선호하는 언어: 클라이언트가 Accept-Language 헤더를 통해 선호하는 언어를 서버에 전달합니다.

    • Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
      • 의미: 한국어(ko-KR 또는 ko)를 가장 선호하지만(q=0.9), 가능하다면 미국 영어(en-US, q=0.8)나 일반 영어(en, q=0.7)도 받을 용의가 있다. (q값은 상대적인 선호도를 나타내며 0에서 1 사이의 값을 가집니다.)
  • 선호하는 미디어 타입: 클라이언트가 Accept 헤더를 통해 선호하는 문서 타입을 서버에 전달합니다.

    • Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
      • 의미: HTML 문서(text/html) 또는 XHTML 문서(application/xhtml+xml)를 가장 선호한다. 그 다음으로는 XML 문서(application/xml, q=0.9)를 선호하고, 그 외 이미지나 다른 모든 타입(*/*, q=0.8)도 받을 수 있다.

서버는 이러한 클라이언트의 선호도와 서버가 제공할 수 있는 리소스의 형태를 비교하여 가장 적절한 표현을 선택하고 응답합니다.

마무리

이렇게 HTTP 헤더, 캐시, 쿠키, 그리고 콘텐츠 협상에 대해 자세히 알아보았습니다. 웹의 동작 방식을 이해하는 데 도움이 되셨기를 바랍니다!
혹시 잘못된 내용이나 추가하고 싶은 의견이 있다면 댓글로 편하게 남겨주세요!

profile
왜?를 생각하며 개발하기

0개의 댓글