본 게시물은 모든 개발자를 위한 HTTP 웹 기본 지식 강의를 보고 작성하였습니다.
요청과 응답의 구조와 HTTP 헤더와 쿠키의 동작 원리를 제대로 이해하는 건 웹 개발자로서 필수 역량입니다.
이번 포스팅에서는 HTTP 헤더의 구조와 종류, 전송 방식, 그리고 상태 유지 기술인 쿠키까지 자세히 알아보는 시간을 가져봅시다.
HTTP 헤더란?
요청과 응답 메시지에 추가 정보를 담아 전달하는 영역입니다.
메시지 본문(body) 외에 HTTP 전송에 필요한 모든 부가정보를 전달합니다.
예) 메시지 바디의 내용, 메시지 바디의 크기, 압축, 인증, 요청 클라이언트, 서버 정보, 캐시 관리 정보 등
HTTP 헤더 구조
GET /search?q=hello&hl=ko
HTTP/1.1 Host: www.google.com
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 3423
<html>
<body>...</body>
</html>
- header-field = field-name ":" OWS field-value OWS 형식 (OWS: 띄어쓰기 허용)
- field-name은 대소문자 구분 없음
표현 헤더 (Representation Header)
메시지 본문(message body)을 통해 표현 데이터를 전달합니다.
메시지 본문 = 페이로드(payload)
표현은 요청이나 응답에서 전달할 실제 데이터를 말합니다.
표현 헤더는 표현 데이터를 해석할 수 있는 정보를 제공합니다. (데이터 유형, 데이터 길이, 압축 정보 등등)
표현 헤더는 전송과 응답 둘 다 사용합니다. 종류는 아래와 같습니다.
- Content-Type: 표현 데이터의 형식
- Content-Encoding: 표현 데이터의 압축 방식
- Content-Language: 표현 데이터의 자연 언어
- Content-Length: 표현 데이터의 길이
1. Content-Type
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 3423
<html>
<body>...</body>
</html>
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 16
{"data":"hello"}
- 표현 데이터의 형식 설명
- 미디어 타입, 문자 인코딩
- 예)
- text/html; charset=utf-8
- application/json
- image/png
2. Content-Encoding
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Encoding: gzip
Content-Length: 521
lkj123kljoiasudlkjaweioluywlnfdo912u34lj ko98udjkl
- 표현 데이터 인코딩
- 표현 데이터를 압축하기 위해 사용
- 데이터를 전달하는 곳에서 압축 후 인코딩 헤더 추가
- 데이터를 읽는 쪽에서 인코딩 헤더의 정보로 압축 해제
- 예)
- gzip
- deflate
- identity
3. Content-Language
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Language: ko
Content-Length: 521
<html>
안녕하세요.
</html>
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Language: en
Content-Length: 521
<html>
hello
</html>
- 표현 데이터의 자연 언어를 표현
- 예)
- ko
- en
- en-US
4. Content-Length
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 5
hello
- 표현 데이터의 길이
- 바이트 단위
- Transfer-Encoding(전송 코딩)을 사용하면 Content-Length를 사용하면 안됨
콘텐츠 협상 (콘텐츠 네고시에이션)
콘텐츠 협상이란?
클라이언트가 선호하는 표현을 요청하는 방식입니다.
서버는 클라이언트가 보낸 요청 헤더를 참고해서, 가장 적절한 데이터를 골라서 응답합니다.
협상 헤더는 요청시에만 사용합니다.
콘텐츠 협상에 사용되는 헤더 종류
헤더 | 의미 | 예시 |
Accept | 선호하는 미디어 타입 | text/html, application/json |
Accept-Charset | 선호하는 문자 인코딩 | utf-8, euc-kr |
Accept-Encoding | 선호하는 압축 인코딩 방식 | gzip, deflate |
Accept-Language | 선호하는 언어 | ko, en, en-US |
Accept-Language 예시 (언어 협상)
한국어 브라우저를 사용하는 사용자가 /event 페이지에 접속했을 때,
서버는 기본 언어 설정 값인 영어(en)로 응답을 보냅니다.
서버는 한국어 브라우저를 쓰지만, 서버는 그걸 모르는 상태
하지만, Accept-Language를 적용하면,
클라이언트가 HTTP 요청 헤더에 Accept-Language: ko 를 추가해서 "나는 한국어를 원해요" 라고 명시적으로 요청합니다.
서버는 이를 보고 한국어 지원이 가능하므로 한국어로 응답합니다.
그런데, 서버가 클라이언트가 원하는 언어를 모두 지원하지 않는 경우가 발생할 수 있습니다.
이럴 때 사용하는 것이 바로 우선순위(Quality Value, q값) 입니다.
Http 콘텐츠 협상에서는 클라이언트가 여러 데이터를 요청할 때 서버가 어떤 데이터를 우선 제공할지 기준이 필요합니다.
<우선순위 원칙 3단계>
원칙 단계 | 우선 기준 | 설명 |
1단계 | q 값 비교 | 숫자가 클수록 우선순위 높음 (0 ~ 1) |
2단계 | 구체성 비교 | 구체적인 조건일수록 우선 |
3단계 | 미디어 타입 비교 | 미디어 타입을 기준으로 최종 결정 |
<1단계>
GET /event
Accept-Language: ko-KR, ko;q=0.9, en-US;q=0.8, en;q=0.7
(우선순위: ko-KR -> ko -> en-US -> en)
<2단계>
GET /event
Accept: text/*, text/plain, text/plain;format=flowed, */*
(우선순위: text/plain;format=flowed -> text/plain -> text/* -> /)
<3단계>
GET /event
Accept: text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5
(우선순위: text/html;level=1 -> text/html -> text/html;level=2 -> / -> text/*)
전송 방식
HTTP에서는 데이터를 클라이언트에게 전달할 때 상황에 맞는 전송 방식을 사용합니다.
대표적인 전송 방식은 아래 4가지가 있습니다.
1. 단순 전송 (Content-Length)
데이터 크기가 정해져 있을 때 사용하는 기본 전송 방식
서버는 Content-Length 헤더에 데이터 길이를 명시하고 전송합니다.
2. 압축 전송 (Content-Encoding)
데이터 용량이 클 때 압축해서 전송하는 방식
서버는 Content-Encoding 헤더에 압축 방식을 명시합니다.
클라이언트는 해당 방식으로 압축 해제 후 사용합니다.
3. 분할 전송 (Transfer-Encoding)
데이터의 총 크기를 알 수 없거나 스트리밍 방식으로 보낼 때 사용
Content-Length를 사용하지 않고 Transfer-Encoding: chunked 를 사용해 데이터를 여러 덩어리(chunk)로 나눠서 전송합니다.
4. 범위 전송 (Range, Content-Range)
클라이언트가 원하는 데이터 일부분만 전송하는 방식
주로 동영상 스트리밍, 파일 다운로드 재개 등에서 사용합니다.
클라이언트가 Range 헤더로 범위를 요청하면 서버는 Content-Range 헤더로 응답합니다.
일반 정보 헤더
클라이언트나 서버의 일반적인 정보를 담아서
로그, 통계, 추적 등에 활용할 수 있는 헤더
헤더 | 역할 | 사용 위치 |
From | 유저 에이전트 이메일 정보 | 요청 헤더 |
Referer | 이전 웹 페이지 주소 | 요청 헤더 |
User-Agent | 클라이언트의 애플리케이션 정보 (브라우저, 운영체제 등) |
요청 헤더 |
Server | 서버 소프트웨어 정보 | 응답 헤더 |
Date | 메시지가 생성된 날짜와 시간 | 응답 헤더 |
특별한 정보 헤더
HTTP 동작에 있어 중요한 역할을 하는 헤더
헤더 | 역할 | 사용 위치 |
Host | 요청 호스트 도메인 정보 (필수) (Host: www.example.com) |
요청 헤더 |
Location | 페이지 리다이렉트 주소 (Location: /new-page) |
응답 헤더 |
Allow | 허용 가능한 HTTP 메서드 (Allow: GET, HEAD, PUT) |
응답 헤더 |
Retry-After | 다음 요청까지 대기 시간 (Retry-After: 120) |
응답 헤더 |
Authorization | 클라이언트 인증 정보를 서버에 전달 (Authorization: Basic xxxxxxxxxxxxxxxx) |
요청 헤더 |
WWW-Authenticate | 리소스 접근시 필요한 인증 방법 정의 | 응답 헤더 |
쿠키 (Cookie)
HTTP는 기본적으로 Stateless(무상태) 프로토콜입니다. 서버와 클라이언트는 서로 상태를 유지하지 않습니다.
클라이언트와 서버가 요청과 응답을 주고 받으면 연결이 끊어지고, 클라이언트가 다시 요청하면 서버는 이전 요청을 기억하지 못합니다. 그래서, 사용자의 로그인 상태, 장바구니 정보 등을 유지하기 위해 사용하는 기술이 바로 "쿠키(Cookie)"입니다.
<쿠키 미사용 경우>
쿠키 없이 그냥 요청을 보낸다면, 서버 입장에선 이 사용자가 로그인을 했는지 안했는지 알 방법이 없습니다.
<쿠기 사용 경우>
클라이언트(웹 브라우저)가 로그인 정보를 담아 서버에 요청을 보냅니다.
서버는 로그인 성공 후 Set-Cookie 헤더를 통해 쿠키를 클라이언트에게 전달합니다.
웹 브라우저는 전달받은 쿠키를 내부 저장소에 저장합니다.
사용자가 다른 페이지(/welcome)에 접근할 때, 브라우저는 자동으로 저장해둔 쿠키를 서버에 전송합니다.
서버는 쿠키 정보를 읽어 사용자 상태를 파악한 후 응답합니다.
사용자가 다른 페이지(/board, /order, /xxx..)로 이동하더라도 브라우저는 쿠키를 자동으로 포함해서 서버에 요청합니다.
쿠키의 특징
- 예) set-cookie: sessionId=abcde1234; expires=Sat, 26-Dec-2020 00:00:00 GMT; path=/; domain=.google.com; Secure
- 사용처
- 사용자 로그인 세션 관리
- 광고 정보 트레킹
- 쿠키 정보는 항상 서버에 전송됨
- 네트워크 트래픽 추가 유발
- 최소한의 정보만 사용 (세션 id, 인증 토큰)
- 서버에 전송하지 ㅇ낳고, 웹 브라우저 내부에 데이터를 저장하고 싶으면 웹 스토리지 참고
- 주의!
- 보안에 민감한 데이터는 저장하면 안됨 (주민번호, 신용카드 번호 등등)
쿠키 속성 정리
- 생명주기
- Expires
- Set-Cookie: expires=Sat, 26-Dec-2020 04:39:21 GMT
- 만료일이 되면 쿠키 삭제
- Max-Age
- Set-Cookie: max-age=3600 (3600초)
- 0이나 음수를 지정하면 쿠키 삭제
- 세션 쿠키
- 만료 날짜를 생략하면 브라우저 종료시 까지만 유지
- 영속 쿠키
- 만료 날짜를 입력하면 해당 날짜까지 유지
- Expires
- 도메인 (Domain)
- 예) domain=example.org
- 명시: 명시한 문서 기준 도메인 + 서브 도메인 포함
- domain=example.org를 지정해서 쿠키 생성
- example.org는 물론이고, dev.example.org도 쿠키 접근
- 생략: 현재 문서 기준 도메인만 적용
- example.org 에서 쿠키를 생성하고 domain 지정을 생략
- example.org에서만 쿠키 접근
- dev.example.org에서는 쿠키 미접근
- 경로 (Path)
- 예) path=/home
- 이 경로를 포함한 하위 경로 페이지만 쿠키 접근
- 일반적으로 path=/ 루트로 지정
- 예)
- path=/home 지정
- /home -> 가능
- /home/level1 -> 가능
- /home/level1/level2 -> 가능
- /hello -> 불가
- 보안
- Secure
- 쿠키는 http, https를 구분하지 않고 전송
- Secure를 적용하면 https인 경우에만 전송
- HttpOnly
- XSS 공격 방지
- 자바스크립트에서 접근 불가(document.cookie)
- HTTP 전송에만 사용
- SameSite
- XSRF 공격 방지
- 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키 전송
- Secure
이번 글을 정리하면서 느낀 건, HTTP 헤더는 웹 개발에서 정말 많이 보았지만 평소에 깊게 생각해보지 않았던 영역이라는 거였습니다. 그냥 요청을 보내고 응답 받는 게 끝이 아니라, 헤더를 어떻게 구성하느냐에 따라 데이터 전달 방식도 달라지고, 쿠키를 어떻게 설정하느냐에 따라 사용자 경험과 보안 수준까지 바뀔 수 있다는 걸 다시 한 번 깨달았습니다.
앞으로 개발을 할 때 단순히 동작만 확인하는 게 아니라
"이 부분은 어떤 의미가 담겨있는지", "어떻게 동작하는지", "어떤 방식을 사용해야 더 안전하고 효율적인지"
이런 부분까지 고민해보는 습관을 가져야겠다고 생각이 듭니다.
'공부 메모' 카테고리의 다른 글
[HTTP] 웹 성능 최적화를 위한 캐시와 조건부 요청 (1) | 2025.04.16 |
---|---|
[HTTP] 상태 코드 쉽게 정리해보기 (2xx, 3xx, 4xx, 5xx) (0) | 2025.04.10 |
[HTTP] 데이터 전송 방식과 API 설계 활용 (2) | 2025.04.09 |
[HTTP] HTTP 메서드 총정리: API 설계를 위한 필수 개념 (1) | 2025.04.04 |
[HTTP] HTTP 기본 개념 정리: 구조, 특징, 메시지 이해하기 (0) | 2025.04.03 |