[FRONT] HTTP 헤더 완벽 이해하기

개발자 도구 네트워크 탭의 HTTP 헤더 순서별 완벽 가이드

Posted by lim.Chuck on January 7, 2025

[FRONT]

  1. [FRONT] 프론트엔드 쿠키 이슈 해결하기
  2. [FRONT] Nuxt Proxy 설정과 활용
  3. [FRONT] 웹 캐시 전략과 구현
  4. [FRONT] Next.js와 Nuxt.js 비교 분석
  5. [FRONT] Monorepo vs Multi-repo vs Monolith 아키텍처
  6. [FRONT] mitmproxy를 활용한 디버깅
  7. [FRONT] Storybook 활용 가이드
  8. [FRONT] Vercel Turbopack 소개
  9. [FRONT] 캐시와 캐싱 전략
  10. [FRONT] SWC 컴파일러 이해하기
  11. [FRONT] 인터섹션 옵저버로 인터섹션 여부 감지하기
  12. [FRONT] BroadcastChannel 사용해서 같은 도메인 브라우저 간 통신하기
  13. [FRONT] DOM이벤트 버블링(Bubbling)과 캡처링(Capturing)
  14. [FRONT] XSS와 CSRF
  15. [FRONT] 웹 성능 최적화
  16. [FRONT] 브라우저 렌더링 과정
  17. [FRONT] 웹 접근성
  18. [FRONT] URL과 Domain 정확히 이해하자 (url구조)
  19. [FRONT] HTTP 헤더 이해하기

HTTP의 역사와 진화 📚

  1. HTTP/0.9 (1991) - 원시적인 시작
1
2
# 단순 요청
GET /page.html
  • 단일 라인 프로토콜
  • GET 메서드만 존재
  • 헤더가 없음
  • HTML 파일만 전송 가능
  • “One-line protocol”이라고도 불림
  1. HTTP/1.0 (1996) - 기본 기능 추가
1
2
3
4
5
6
7
8
9
GET /page.html HTTP/1.0
User-Agent: Mozilla/5.0
Accept: text/html

200 OK
Content-Type: text/html
Content-Length: 1024

<html>...
  • 버전 정보 추가
  • 상태 코드 도입
  • HTTP 헤더 개념 도입
  • 다양한 문서 전송 가능 (HTML, 이미지 등)
  • 연결 당 하나의 요청만 처리 (비효율적)
  1. HTTP/1.1 (1997) - 표준의 시작
1
2
3
4
5
6
7
8
GET /page.html HTTP/1.1
Host: www.example.com
Connection: keep-alive

200 OK
Connection: keep-alive
Content-Type: text/html
Transfer-Encoding: chunked
  • 영구 연결 (keep-alive) 도입
  • 파이프라이닝 가능
  • 호스트 헤더 필수화
  • 청크 전송 인코딩
  • 캐시 제어 매커니즘
  • 언어, 인코딩, 타입 협상
  1. HTTP/2 (2015) - 성능 개선
1
2
3
4
:method: GET
:path: /page.html
:authority: www.example.com
:scheme: https
  • 멀티플렉싱 (여러 요청 동시 처리)
  • 헤더 압축
  • 서버 푸시
  • 스트림과 프레임 도입
  • 바이너리 프로토콜
  • HTTPS 권장
  1. HTTP/3 (2022) - 최신 표준
1
2
3
4
# QUIC 프로토콜 기반
:method: GET
:path: /page.html
:authority: www.example.com
  • UDP 기반 QUIC 프로토콜 사용
  • 연결 설정 시간 단축
  • 패킷 손실 감소
  • 모바일 환경 최적화
  • 더 나은 보안
  1. 버전별 성능 비교
1
2
3
4
5
6
7
8
9
10
11
연결 수립 시간:
HTTP/1.0: 매 요청마다 TCP 연결 (느림)
HTTP/1.1: keep-alive로 재사용 (개선)
HTTP/2  : 단일 연결로 다중 요청 (빠름)
HTTP/3  : QUIC으로 초고속 (최적화)

요청 처리:
HTTP/1.0: 1 연결 = 1 요청
HTTP/1.1: 1 연결 = 순차적 여러 요청
HTTP/2  : 1 연결 = 동시 여러 요청
HTTP/3  : 손실에 강한 다중 요청
  1. 실제 사용 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# HTTP/1.1 순차 요청
GET /style.css
GET /script.js
GET /image.jpg

# HTTP/2 동시 요청
:path: /style.css
:path: /script.js
:path: /image.jpg

# HTTP/3 최적화 요청 (QUIC)
:path: /style.css + QUIC
:path: /script.js + QUIC
:path: /image.jpg + QUIC
  1. 현재 사용 현황 (2024)
  • HTTP/1.1: 여전히 광범위하게 사용
  • HTTP/2: 대부분의 최신 웹사이트
  • HTTP/3: 대형 서비스 (Google, Facebook 등)

개발자 도구 네트워크 탭의 HTTP 헤더 순서별 완벽 가이드 🚀

1. General (일반 정보)

1
2
3
4
5
Request URL: https://api.example.com/data
Request Method: GET
Status Code: 200 OK
Remote Address: 3.35.147.134:443
Referrer Policy: strict-origin-when-cross-origin

상세 설명:

  • Request URL: 요청 주소

    • 프로토콜(https://) + 도메인 + 경로
    • “어디로 갈지 알려주는 주소”
  • Request Method: 요청 방식

    • GET: 데이터 조회 (“보여주세요”)
    • POST: 데이터 생성 (“만들어주세요”)
    • PUT/PATCH: 수정 (“바꿔주세요”)
    • DELETE: 삭제 (“지워주세요”)
  • Status Code: 응답 상태

    • 2xx: 성공 (“잘 됐어요”)
    • 3xx: 리다이렉션 (“다른 곳으로 가세요”)
    • 4xx: 클라이언트 오류 (“요청이 잘못됐어요”)
    • 5xx: 서버 오류 (“서버에 문제가 있어요”)
  • Remote Address:

    • AWS 서울 리전 서버 (3.35.147.134)
    • 443: HTTPS 표준 포트
    • “서버의 실제 위치”
  • Referrer Policy:

    • strict-origin-when-cross-origin
    • “다른 사이트로 갈 때 출처만 알려줄게요”

2. Response Headers (응답 헤더)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
access-control-allow-credentials: true
access-control-allow-origin: http://localhost:3000
cache-control: no-cache, no-store, max-age=0, must-revalidate
content-type: application/json
date: Tue, 07 Jan 2025 03:56:29 GMT
expires: 0
pragma: no-cache
server: nginx
set-cookie: SCOUTER=z2lmurtnm7hs5s; Max-Age=2147483647; Expires=Sun, 25 Jan 2093 07:10:36 GMT; Path=/
strict-transport-security: max-age=31536000 ; includeSubDomains
vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 0

상세 설명:

CORS 관련 (교차 출처 리소스 공유)

  • access-control-allow-credentials:

    • true: 인증 정보 포함 허용
    • “쿠키나 인증 정보를 사용해도 돼요”
  • access-control-allow-origin:

    • localhost:3000만 허용
    • “개발 중인 로컬 서버만 접근 가능해요”
  • vary:

    • Origin: “요청 출처에 따라 다르게 응답할 수 있어요”
    • Access-Control-Request-Method: “요청 방식에 따라 다르게 응답해요”
    • Access-Control-Request-Headers: “요청 헤더에 따라 다르게 응답해요”

쿠키 설정

  • set-cookie:
    1
    
    SCOUTER=z2lmurtnm7hs5s; Max-Age=2147483647; Expires=Sun, 25 Jan 2093 07:10:36 GMT; Path=/
    
    • SCOUTER: 성능 모니터링 쿠키 이름
    • z2lmurtnm7hs5s: 쿠키 값
    • Max-Age: 2147483647초 (약 68년) 유효
    • Expires: 2093년 1월 25일 만료
    • Path=/: 전체 사이트에서 사용 가능
    • “웹사이트를 기억하기 위한 정보를 저장해요”

캐시 제어

  • cache-control:

    • no-cache: “사용하기 전에 확인해주세요”
    • no-store: “아예 저장하지 마세요”
    • must-revalidate: “만료되면 꼭 다시 물어보세요”
  • expires: 0

    • “지금 당장 만료됩니다”
  • pragma: no-cache

    • “옛날 브라우저를 위한 캐시 설정”

보안 설정

  • strict-transport-security:

    • max-age=31536000: “1년 동안”
    • includeSubDomains: “하위 도메인도 포함”
    • “HTTPS만 사용하세요”
  • x-content-type-options: nosniff

    • “파일 형식을 임의로 해석하지 마세요”
  • x-frame-options: SAMEORIGIN

    • “같은 출처의 프레임에서만 보여주세요”
  • x-xss-protection: 0

    • “브라우저의 XSS 필터를 사용하지 않아요”
    • “더 나은 보안 방식을 사용할거에요”

3. Request Headers (요청 헤더)

1
2
3
4
5
6
7
8
9
10
11
12
13
:authority: api.example.com
:method: GET
:path: /api/setting/member
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br, zstd
accept-language: ko-KR,ko;q=0.9,en-AS;q=0.8,en;q=0.7,en-US;q=0.6
authorization: Bearer eyJhbGciOiJIUzUxMiIs...
cache-control: no-cache
content-type: application/json
origin: http://localhost:3000
pragma: no-cache
priority: u=1, i

상세 설명:

HTTP/2 기본 정보

  • :authority:

    • api.example.com
    • “서버의 도메인 주소예요”
  • :method: GET

    • “데이터를 조회할거예요”
  • :path: /api/setting/member

    • “회원 설정 정보를 요청할거예요”
  • :scheme: https

    • “보안 연결을 사용할거예요”

콘텐츠 협상

  • accept: */*

    • “어떤 형식이든 받을 수 있어요”
    • 서버가 보내는 모든 타입 수용
  • accept-encoding:

    • gzip: “가장 일반적인 압축 방식”
    • deflate: “기본 압축 방식”
    • br: “구글이 만든 최신 압축 방식”
    • zstd: “페이스북이 만든 빠른 압축 방식”
  • accept-language:

    1
    
    ko-KR,ko;q=0.9,en-AS;q=0.8,en;q=0.7,en-US;q=0.6
    
    1. ko-KR (q=1.0): “한국어가 가장 좋아요”
    2. ko (q=0.9): “한국어면 괜찮아요”
    3. en-AS (q=0.8): “아시아권 영어도 괜찮아요”
    4. en (q=0.7): “영어도 볼 수 있어요”
    5. en-US (q=0.6): “미국식 영어도 가능해요”

인증 정보

  • authorization:
    1
    
    Bearer eyJhbGciOiJIUzUxMiIs...
    
    • Bearer: JWT 토큰 방식
    • 포함 정보:
      • memberSeq: 회원번호
      • birth: 생년월일
      • gender: 성별
      • native: 출신
    • “로그인 정보를 담고 있어요”

캐시 제어

  • cache-control:

    1
    
    Cache-Control: no-cache, private, max-age=3600, must-revalidate
    
    1. 저장 관련
    • no-store: “절대 저장하지 마세요” (민감한 개인정보)
    • no-cache: “저장해도 되지만 사용 전 확인하세요”
    • private: “브라우저만 저장해요 (중간 서버는 안돼요)”
    • public: “모든 곳에서 저장해도 돼요”
    1. 유효 기간
    • max-age=3600: “1시간 동안 유효해요”
    • s-maxage=3600: “중간 서버에서 1시간 유효해요”
    • stale-while-revalidate=60: “검사하는 1분 동안은 오래된 것 보여줘도 돼요”
    • stale-if-error=300: “에러 나면 5분간 오래된 것 보여줘도 돼요”
    1. 검증 관련
    • must-revalidate: “만료되면 꼭 확인하세요”
    • proxy-revalidate: “중간 서버는 꼭 확인하세요”
    • immutable: “절대 안 바뀌는 내용이에요”

    사용 예시:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    # 민감한 개인정보
    Cache-Control: no-store, must-revalidate
    
    # 자주 변하는 API 응답
    Cache-Control: no-cache, private
    
    # 정적 이미지
    Cache-Control: public, max-age=31536000, immutable
    
    # 자주 변하는 데이터
    Cache-Control: private, max-age=0, must-revalidate
    
    # CDN 활용
    Cache-Control: public, max-age=3600, s-maxage=86400
    

    실제 상황별 권장 설정:

    1. 프로필 사진:
    1
    2
    
    Cache-Control: public, max-age=31536000, immutable
    # "1년간 캐시해도 되는 이미지예요"
    
    1. 사용자 데이터:
    1
    2
    
    Cache-Control: private, no-cache, must-revalidate
    # "개인정보라 매번 확인해야 해요"
    
    1. 공지사항:
    1
    2
    
    Cache-Control: public, max-age=3600, stale-while-revalidate=60
    # "1시간 캐시하고, 갱신 중 1분은 이전 내용 보여줘도 돼요"
    
    1. 실시간 데이터:
    1
    2
    
    Cache-Control: no-store
    # "실시간이라 저장하면 안 돼요"
    
    1. 정적 자원(CSS/JS):
    1
    2
    
    Cache-Control: public, max-age=31536000, immutable
    # "변경되면 새 URL을 사용할 자원이에요"
    

4. 브라우저 정보

1
2
3
4
5
6
7
sec-ch-ua: "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
sec-ch-ua-mobile: ?1
sec-ch-ua-platform: "Android"
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Linux; Android 8.0.0; SM-G955U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36

상세 설명:

브라우저 식별

  • sec-ch-ua:

    • Chrome 131 버전
    • Chromium 131 버전
    • “어떤 브라우저를 사용하는지 알려줘요”
  • sec-ch-ua-mobile: 모바일 여부

    1
    2
    3
    4
    5
    
    # 모바일
    sec-ch-ua-mobile: ?1
    
    # 데스크톱
    sec-ch-ua-mobile: ?0
    
  • sec-ch-ua-platform: OS 정보

    1
    2
    3
    4
    5
    
    # 다양한 운영체제
    sec-ch-ua-platform: "Windows"
    sec-ch-ua-platform: "macOS"
    sec-ch-ua-platform: "Android"
    sec-ch-ua-platform: "iOS"
    

보안 관련 정보

  • sec-fetch-dest: 요청 목적

    1
    2
    3
    4
    5
    
    sec-fetch-dest: empty        # API 요청
    sec-fetch-dest: document     # 웹페이지
    sec-fetch-dest: image        # 이미지
    sec-fetch-dest: script       # 자바스크립트
    sec-fetch-dest: style        # CSS
    
  • sec-fetch-mode: 요청 모드

    1
    2
    3
    4
    
    sec-fetch-mode: cors        # 다른 출처 요청
    sec-fetch-mode: navigate    # 페이지 이동
    sec-fetch-mode: no-cors    # 단순 요청
    sec-fetch-mode: websocket  # 웹소켓 연결
    
  • sec-fetch-site: 요청 출처

    1
    2
    3
    4
    
    sec-fetch-site: same-origin   # 같은 사이트
    sec-fetch-site: same-site     # 같은 도메인
    sec-fetch-site: cross-site    # 다른 도메인
    sec-fetch-site: none          # 직접 접속
    

기기 상세 정보

  • user-agent:
    • Android 8.0.0
    • Samsung Galaxy S8+ (SM-G955U)
    • Chrome 116.0.0.0
    • “어떤 기기와 브라우저를 쓰는지 자세히 알려줘요”

기타 정보

  • origin: http://localhost:3000

    • “요청이 시작된 곳이에요”
  • priority: u=1, i

    • u=1: “긴급해요”
    • i: “중요해요”
    • “요청의 우선순위를 나타내요”