그림으로 배우는 Http&Network Basic 정리 - 6장. HTTP 헤더(6.4)
6.4.1.Accept 헤더 필드
Accept 헤더는 클라이언트(브라우저 또는 HTTP 요청을 보내는 애플리케이션)가 서버로부터 받을 수 있는 콘텐츠 타입(MIME 타입)을 지정하는 HTTP 요청 헤더입니다.
1. 기본 형식
Accept: <MIME 타입>, <MIME 타입>;q=<우선순위>
//NAVER Accept 리퀘스트 헤더
Accept: text/html,application/xhtml+xml,
application/xml;q=0.9,image/avif,
image/webp,image/apng,
*/*;q=0.8,
application/signed-exchange;v=b3;q=0.7
- 여러 개의 MIME 타입을 쉼표(,)로 구분하여 나열한다.
- q(quality factor,품질계수) 값을 사용하여 우선순위(0~1 사이의 값)를 지정할 수 있다.
- q값을 사용한 우선순위 설정( 디폴트 값은 q=1.0 )
- q=1.0이 가장 높은 우선순위이며, q=0.0이면 해당 타입을 원하지 않는다는 의미.
- application/signed-exchange : Signed HTTP Exchange (SXG) 형식으로 서명된 HTTP 응답을 의미한다. 이는 구글의 Web Packing 기술 중 하나로, 서명된 콘텐츠를 캐싱하고 다른 도메인에서 안전하게 제공할 수 있도록 하기 위한 형식이다.
- 참고 사이트 : https://web.dev/articles/signed-exchanges?hl=ko#tooling
- 과거에는 CDN이나 서드파티 서버를 통해 콘텐츠를 배포 할때 문제점이 존재( CDN을 사용하면 URL 이 변경, 원본 URL을 유지하려면 SSL 인증서 공유가 필요)
- SXG에서는 사이트(출처 사이트)가 HTTP 응답에 서명(Signature)을 추가하여, 브라우저가 원본을 검증할 수 있도록 한다
이 방식 덕분에 브라우저는 콘텐츠를 제공한 서버(CDN)이 아니라 원본 사이트(example.com)에서 온 것으로 인식할 수 있다. - 또, SXG 인증을 사용 시 웹사이트의 주요 콘텐츠가 더 빨리 로드가 된다..?
* Content-type 헤더와 Accept Header의 차이점
Content-Type 헤더 | Accept 헤더 | |
역할 | 전송하는 데이터의 알려주는 용도 | 받고 싶은 데이터의 형식 지정 |
사용 위치 | 요청 & 응답 | 요청에서만 사용 |
6.4.2. Accept-Charset 헤더 필드
Accept-Charset은 클라이언트(웹 브라우저 또는 애플리케이션)가 서버로부터 받고 싶은 문자 인코딩(Charset)을 지정하는 HTTP 요청 헤더이다.
Accept-Charset: <문자셋1>, <문자셋2>;q=<우선순위>
Accept-Charset: utf-8
- 여러 개의 문자 인코딩을 지정할 수 있으며, q(quality factor)를 사용하여 우선순위(0~1 사이의 값)를 설정할 수 있습니다.
- 일반적으로 현재 UTF-8이 가장 많이 사용됩니다.
헤더 필드 | 의미 | 예제 | 역할 |
Accept | 클라이언트가 받고 싶은 콘텐츠 타입(MIME 타입) | Accept: application/json | 서버가 JSON, HTML, XML 중 어떤 형식으로 응답할지 결정 |
Accept-Charset | 클라이언트가 받고 싶은 문자 인코딩(Charset) | Accept-Charset: UTF-8, ISO-8859-1 | 서버가 UTF-8, ISO-8859-1 중 어떤 인코딩을 사용할지 결정 |
- Accept → 파일 형식(콘텐츠 타입, MIME 타입)을 지정 (예: HTML, JSON, XML, 이미지 등)
- Accept-Charset → 파일의 문자 인코딩(UTF-8, ISO-8859-1 등)을 지정
- 대부분의 경우 현대 웹에서는 UTF-8이 표준이기 때문에 Accept-Charset을 굳이 명시할 필요는 없다.
- 대신 서버는 Content-Type : text/html; charset=utf-8 을 사용하여 응답할 때 인코딩을 명확히 지정하는 것이 일반적이다.
- 하지만, Accept는 중요! (예: Accept: application/json 없으면 서버가 기본 형식인 HTML로 응답할 수도 있음)
6.4.3. Accept-Encoding 헤더 필드
Accept-Encoding은 클라이언트가 서버로부터 받을 수 있는 압축 방식(Encoding 방식)을 지정하는 HTTP 요청 헤더이다.
압축된 데이터를 받을 수 있으면 네트워크 트래픽을 줄이고, 로딩 속도를 개선할 수 있다
Accept-Encoding: <압축 방식1>, <압축 방식2>;q=<우선순위>
//구글 리퀘스트 헤더
Accept-Encoding: gzip, deflate, br, zstd
- 보통 웹 브라우저와 API 클라이언트는 여러 개의 압축 방식을 지원하며, 서버는 적절한 방식을 선택하여 응답합니다
- br이 gzip보다 압축률이 높아서 더 효율적이다.
- 아래 사진와 같이 AWS CloudFront 에서 자동으로 Gzip, Broili를 지원할 수 있도록 설정이 가능하다.
Accept-Encoding이 중요한 이유
- 네트워크 최적화: 압축된 데이터는 용량이 작아져 페이지 로딩 속도가 빨라짐.
- 트래픽 절감: 데이터 크기가 줄어들어 서버 비용 절감.
- 브라우저 & API 최적화: 웹 브라우저와 API는 일반적으로 gzip, br을 기본적으로 요청하여 성능을 최적화함.
6.4.4. Accept-Language 헤더 필드
Accept-Language는 클라이언트(웹 브라우저 또는 애플리케이션)가 서버로부터 받고 싶은 언어(또는 지역 설정)를 지정하는 HTTP 요청 헤더이다.
이 헤더는 다국어 지원 웹사이트에서 중요한 역할을 하며, 사용자의 선호 언어에 따라 적절한 콘텐츠를 제공하는 데 사용된다.
Accept-Language: <언어 코드1>, <언어 코드2>;q=<우선순위>
accept-language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
Accept vs. Accept-Charset vs. Accept-Encoding vs. Accept-Language 차이
헤더 필드 | 의미 | 예제 |
Accept | 콘텐츠 타입 지정 (HTML, JSON 등) | Accept: application/json |
Accept-Charset | 문자 인코딩 지정 (UTF-8 등) | Accept-Charset: UTF-8 |
Accept-Encoding | 압축 방식 지정 (gzip, br 등) | Accept-Encoding: gzip, deflate |
Accept-Language | 언어 및 지역 설정 지정 | Accept-Language: ko, en-US;q=0.8 |
6.4.5. Authorization 헤더 필드
Authorization은 클라이언트(사용자 또는 애플리케이션)가 서버에 인증 정보를 제공하는 HTTP 요청 헤더이다.
이 헤더는 API, 웹사이트 로그인, 인증 시스템에서 사용됩니다.
Authorization: <인증 타입> <인증 정보>
Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
- <인증 타입>: 사용되는 인증 프로토콜 (예: Basic, Bearer, Digest Auth 등)
- <인증 정보>: 보통 사용자명:비밀번호을 Base64로 인코딩 한 값, 토큰, 해시값 등이 포함됨
6.4.6. Expect 헤더 필드
Expect 헤더는 클라이언트가 서버에게 특정한 동작을 기대한다고 알리는 헤더이다.
✔ 주로 대용량 데이터 업로드 또는 특정한 인증이 필요한 요청에서 사용됨.
✔ 서버가 Expect 조건을 충족하면 요청을 정상 처리하고, 아니면 오류(417 Expectation Failed)를 반환함.
✔ 대용량 데이터 전송 시, 서버가 받을 수 있는지 먼저 확인할 필요가 있기 때문에 불필요한 네트워크 사용 방지하고, 네트워크 성능 최적화를 유지 할 수 있다.
//1️⃣ 클라이언트가 서버에게 요청
POST /upload HTTP/1.1
Host: example.com
Content-Length: 50000000 # 50MB 파일 업로드
Expect: 100-continue
//2️⃣ 서버 응답- 서버 업로드 허용
HTTP/1.1 100 Continue
//3️⃣ 서버 응답 - 서버가 거부
HTTP/1.1 417 Expectation Failed
✅ 즉, Expect는 서버가 준비되었는지 확인하고, 불필요한 데이터 전송을 방지하는 데 유용한 헤더야! 🚀
6.4.7. From 헤더 필드
From 헤더는 HTTP 요청을 보낸 클라이언트의 이메일 주소를 나타내는 헤더이다.
주로 자동화된 봇, 크롤러, 검색 엔진이 자신을 식별할 때 사용되는데 서버 상에 문제를 일으키고 있다면 이메일로 연락한다.
보안 문제(스팸, 가짜 이메일 등) 때문에 요즘은 거의 쓰지 않는다.
From: <유저 에이전트의 이메일 정보>
From: bot@example.com
6.4.8. Host 헤더 필드란
Host 헤더는 클라이언트(브라우저, 앱, API)가 요청을 보낼 때, 요청 대상 서버의 도메인(호스트)을 명시하는 HTTP 요청 헤더이다.
즉, 서버가 여러 개의 도메인을 운영할 때, 클라이언트가 "이 요청은 어느 사이트에 대한 것이야"라고 알려주는 역할을 한다.
HTTP/1.1에서는 서버가 여러개의 도메인을 운영하는 경우(가상호스팅), 서버가 특정 도메인에 따라 다른 응답을 제공할때 이런 경우들이 존재하면서 Host 헤더가 반드시 포함되어야 했다.
하지만, 참고로 HTTP/2, HTTP/3에서는 Host 대시 : authority 사용해서 그런지 naver, google 보면 host 헤더가 없다.
HTTP/1.1 | Host 헤더 사용 (Host: example.com) |
HTTP/2 | :authority: 헤더 사용 (:authority: example.com) |
HTTP/3 | :authority: 헤더 사용 (:authority: example.com) |
6.4.9. If-Match
웹에서 여러 사용자가 같은 데이터를 동시에 수정할 수 있을 때, 데이터의 충돌을 방지하려면, 현재 내가 수정하는 데이터가 최신 버전인지 확인해야한다. 이를 위해 HTTP 요청을 보낼 때 if-Match 헤더를 사용하면, 서버가 해당 데이터가 여전히 최신버전인지 확인한 후 요청을 처리하도록 강제 할 수 있다.
- 서버의 ETag(Entity Tag) 와 비교하여 요청을 허용하거나 거부하는 역할
- ETag : 서버가 특정 리소스의 버전을 식별하기 위해 생성하는 고유한 값으로, 파일이 변경 될 때마다 새로운 ETag가 생성된다.
- 클라이언트가 요청을 보낼 때, If-Match 에 ETag 값을 포함시키면, 서버는 현재 리소스의 Etag와 비교하여 일치하면 요청을 수행하고, 다르면 412 Preconditional Failed 라는 오류를 반환한다.
- 클라이언트가 서버에 데이터를 변경하는 요청 (PUT, PATCH, DELETE 등) 을 보낼 때 사용된다.
If- Match 가 중요한 이유
- 데이터 무결성을 유지하기 위한 낙관적 동시성 제어(Optimistic Concurrency Control, OCC) : 여러 사용자가 같은 데이터를 수정할 때, 최신 버전인지
If-Match: <etag_value>, <etag_value>, …
If-Match: "bfc13a64729c4290ef5b2c2730249c88ca92d82d"
If-Match: "67ab43", "54ed21", "7892dd"
If-Match: *
🔥 If-Match vs. If-None-Match 정리
헤더사용 | 목적 | 동작 방식 | 주로 쓰이는 HTTP 메서드 |
If-Match | 리소스 동시 수정 방지 (낙관적 동시성 제어) | ETag가 일치하면 요청 수행, 다르면 412 오류 | PUT, PATCH, DELETE |
If-None-Match | 캐시 재검증 & 리소스 중복 방지 | ETag가 다르면 요청 수행, 같으면 304 응답 | GET (캐시 재검증) |
6.4.10. If-Modified-Since
If-Modified-Since는 서버의 리소스가 특정 날짜 이후에 변경되었는지 확인하는 HTTP 헤더이다.
- 리소스가 변경되지 않았으면 → 304 Not Modified 응답 (데이터 재전송 안 함, 캐시 사용)
- 리소스가 변경되었으면 → 200 OK 응답과 함께 최신 데이터 반환
즉, If-Modified-Since는 ETag 없이도 캐시 최적화와 네트워크 트래픽 절약을 도와주는 기능이다.
If-Modified-Since: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT
// 1️⃣ 요청 - 데이터가 변경되지 않았는 경우
GET /resource HTTP/1.1
Host: example.com
If-Modified-Since: Mon, 05 Feb 2024 12:00:00 GMT
//데이터 변경 없음
HTTP/1.1 304 Not Modified
// 2️⃣ 요청 - 리소스가 변경된 경우
GET /resource HTTP/1.1
Host: example.com
If-Modified-Since: Mon, 05 Feb 2024 12:00:00 GMT
//데이터 변경된 경우
HTTP/1.1 200 OK
Last-Modified: Wed, 07 Feb 2024 14:30:00 GMT
Content-Type: application/json
{
"data": "updated content"
}
🔥 Last Modified vs If-Modified-Since
- Last Modified는 리소스가 마지막으로 수정된 날짜를 나타내는 서버의 응답헤더인 반면,
If-Modified-Since는 클라이언트가 특정 날짜 이후로 변경된 데이터만 받을 때 사용하는 요청 헤더이다. - Last Modified는 서버는 내부적으로 리소스 수정 날짜를 저장하고, 응답 헤더로 보낸다.
If-Modified-Since는 서버는 If-Modified-Since 값과 현재 Last-Modified 값을 비교한다. - Last-Modified는 무조건 200 OK와 함게 데이터 반환하고,
If-Modified-Since는 변경 없으면 304 Not Modified, 변경되었으면 200 OK 반환한다.
6.4.11. If -None-Match
If-None-Match는 ETag(Entity Tag) 값을 기반으로 캐시된 리소스가 여전히 유효한지 확인하는 데 사용된다.
If-None-Match: "<etag_value>", "<etag_value>", …
If-None-Match: *
🔥 If-Modified-Since vs. If-None-Match (캐시 재검증)
헤더 | If-Modified-Since | If-None-Match |
사용 목적 | 시간 기준 캐시 재검증 | ETag 기반 캐시 재검증 |
기준 값 | 날짜( Last-Modified ) | ETag (해시값) |
정확도 | 초 단위로 비교 (시간 오차 가능) | ETag는 데이터가 바뀔 때마다 달라짐 (더 정확함) |
사용 용도 | 브라우저 캐시, 정적 파일 | API 응답, 동적 데이터 |
단점 | 초 단위까지만 비교 가능하기에 정확한 변경 감지 어려움 | ETag는 파일 해시(hash) 기반으로 생성되므로, 1초 이내 변경도 감지 가능. |
- If-Modified-Since는 시간 기반으로 변경 여부를 확인하는 헤더
- GET 요청에서 캐시 최적화 용도로 가장 많이 사용됨
- 뉴스, 블로그, RSS 피드, 데이터 API에서 네트워크 트래픽 절약을 위해 활용 가능
- 하지만 초 단위 이하의 변경을 감지할 수 없으며, If-None-Match(ETag 기반)보다 정확도가 떨어질 수 있다.
최적의 캐싱을 위해 If-None-Match(ETag)와 함께 사용하면 더 강력한 캐시 관리가 가능하다!🚀
6.4.12. If -Range
If-Range는 조건부 범위 요청(Conditional Range Request)을 수행할 때 사용된다.
파일이 변경되지 않았다면 Range 요청을 유지하고, 변경되었다면 전체 파일을 받는다는 것이기에 항상 Range 와 함께 사용해야한다.
If-Range 헤더는 HTTP-date(Last-Modified 값), 또는 ETag와 함께 사용될 수 있지만, 동시에 사용은 불가능하다.
If-Range: <etag>
If-Range: <HTTP-date>
GET /file.zip HTTP/1.1
Host: example.com
Range: bytes=500-1000
If-Range: "abc123"
- 파일이 변경되지 않았을 경우 ( Etag 값이 “abc123” 유지 ) : 206 Partial Content (500에서 1000바이트만 응답)
- 파일이 변경되었을 경우( Etag값이 변경되었을경우 ) : 200 OK ( 파일을 전체 다시 보냄 )
🔥 If-Match&Range vs If-Range&Range 사용 비교
파일이 변경되지 않았을 경우(ETag 값이 일치)에는 If-Range와 동일하게 206 Partial Content 응답을 줄수 있다.
하지만, 파일이 변경되었을 경우에는, If-Match의 경우 412 Preconditional Failed 를 준다. 그렇기에 2번의 요청, 2번의 응답의 상호 교환이 필요하다.
반면, If-Range를 사용할 경우, 파일이 변경된 경우 자동으로 전체 파일을 받을 수 있어서 추가 요청을 줄일 수 있다.
헤더 조합 | 파일이 변경되지 않았을 경우 | 파일이 변경되었을 경우 | 장점 | 단점 |
If-Match + Range | 변경되지 않으면 Range 유지 (206 Partial Content), | 변경되면 요청 거부 (412 Precondition Failed) -> 요청 다시 보내고 응답 받기 |
캐시된 파일이 유효할 때만 부분 요청 가능 | 변경되면 412 응답을 받고, 클라이언트가 새로운 요청을 다시 보내야 함 |
If-Range + Range | 변경되지 않으면 Range 유지 (206 Partial Content) | 변경되면 전체 파일 (200 OK) 전송 | 변경 시 자동으로 전체 파일을 받을 수 있어 추가 요청 불필요 | 불필요한 전체 다운로드가 발생할 수 있음 |
🔥 If-Modified-Since vs If-None-Match vs If-Range
헤더 | 사용 목적 | 파일 변경 된 경우 | 파일 변경되지 않았을 경우 |
If-Modified-Since | 파일 변경 여부 확인 (날짜 기준) | 전체 파일 재전송 (200 OK) | 304 응답 |
If-None-Match | 파일 변경 여부 확인 (ETag 기반) | 전체 파일 재전송 (200 OK) | 304 응답 |
If-Range | 파일 변경 여부 확인 + 부분 다운로드 지원 | 206 Partial Content로 부분 다운로드 가능 | 전체 파일 다운로드 (200 OK) |
6.4.13. If-Unmodified-Since
If-Unmodified-Since는 파일이 지정된 날짜 이후로 변경되지 않았을 경우에만 요청을 허용하는 조건부 요청 헤더이다.
파일이 변경되지 않은 경우에만 정상 응답 (200 OK)을 받고, 변경된 경우 요청이 거부 (412 Precondition Failed) 됩니다
If-Unmodified-Since: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
If-Unmodified-Since: Wed, 21 Oct 2015 07:28:00 GMT
🔥 If-Modified-Since vs. If-Unmodified-Since 차이
헤더 | 사용 목적 | 주요 차이점 | 응답 |
If-Modified-Since | 캐시 재검증 (GET 요청) | "이 날짜 이후 변경된 경우만 응답을 줘!" | 200 OK(변경됨) or 304 Not Modified(변경 없음) |
If-Unmodified-Since | 안전한 데이터 변경 (PUT, DELETE 요청) | "이 날짜 이후로 변경되지 않았다면 요청을 수행해!" | 200 OK(성공) or 412 Precondition Failed(데이터가 변경됨) |
6.4.14. Max-Forwards
Max-Forwards는 TRACE 또는 OPTIONS 요청이 네트워크를 통해 전달될 수 있는 최대 횟수(Hop 수)를 제한하는 HTTP 헤더입니다.
- HTTP 프록시나 게이트웨이를 여러 개 거치는 경우, 요청이 무한 루프에 빠지는 것을 방지하기 위해 사용됩니다.
- Max-Forwards 값이 0에 도달하면, 요청을 더 이상 전달하지 않고 현재 서버에서 응답을 반환합니다.
- http2에서는 안쓰이는 헤더
6.4.15. Proxy-Authorization
Proxy-Authorization 헤더는 프록시 서버를 통과하기 위해 클라이언트가 인증 정보를 제공할 때 사용되는 HTTP 헤더입니다.
- 프록시 서버가 인증을 요구하는 경우, 클라이언트는 Proxy-Authorization 헤더를 추가하여 사용자 이름과 비밀번호 또는 인증 토큰을 포함해야 함.
- 프록시 서버는 Proxy-Authorization 값을 확인하고, 인증이 성공하면 요청을 원래 목적지(Origin Server)로 전달.
- 일반적으로 프록시가 407 Proxy Authentication Required 응답을 반환할 때 사용됨.
Proxy-Authorization vs Authorization 차이
헤더 | 사용 목적 | 인증 대상 |
Authorization | 원래 서버(Origin Server)에 인증 | 기본 HTTP 인증 (Basic, Bearer, Digest 등) |
Proxy-Authorization | 프록시 서버를 통과할 때 인증 | 프록시 인증 (407 Proxy Authentication Required) |
6.4.15. Range
📌 If-Range vs. Range 핵심 차이점
Range | 요청한 범위만 반환 (206 Partial Content) | 요청한 범위만 반환 (206 Partial Content) |
If-Range | 요청한 범위만 반환 (206 Partial Content) | 전체 파일을 다시 반환 (200 OK) |
6.4.16 Referer 헤더란?
👉 "이 요청을 보낸 페이지(이전 페이지)의 URL을 포함하는 HTTP 헤더"
- 클라이언트(웹 브라우저)가 서버에 요청을 보낼 때, 사용자가 이전에 방문했던 페이지의 URL을 Referer헤더에 포함하여 전달.
- 웹 사이트 간의 링크 추적, 보안 검사, 분석(Analytics) 등에 사용됨.
- 예를 들어, example.com/page1.html에서 example.com/page2.html로 이동할 때,
page2.html의 요청 헤더에 Referer: example.com/page1.html 이 포함됨.
✅ 1️⃣ 트래픽 분석 & 리퍼러 로그
- 웹사이트 운영자는 어떤 페이지에서 사용자가 유입되었는지 추적 가능
- 예를 들어, 어떤 광고 또는 검색 엔진을 통해 방문했는지 확인 가능.
✅ 2️⃣ 보안 검사 (CSRF 방지)
- Referer를 사용하여 외부 사이트에서 유입된 요청인지 확인 가능
- 예를 들어, CSRF(Cross-Site Request Forgery) 공격 방어에 활용할 수 있음.
✅ 3️⃣ 콘텐츠 보호 (핫링크 방지)
- 이미지, 동영상 등 자신의 서버에서만 로드해야 하는 리소스에 대해,
Referer를 확인하여 외부 사이트에서 무단 사용(핫링킹)을 방지할 수 있음.
ex. 광고성 링크 => 쿠팡, 무신사 이런거에 사용한다.
📌 Referer vs Origin 차이점
헤더포함 정보사용 목적예제
헤더 | 포함 정보 | 사용 목적 | 예제 |
Referer | 이전 페이지의 전체 URL (경로 포함) | 트래픽 분석, CSRF 방어, 핫링킹 방지 | Referer: https://example.com/page1.html |
Origin | 출처 (프로토콜 + 도메인 + 포트만 포함) | 보안 강화, CSRF 방어 | Origin: https://example.com |
🚀 즉, Referer는 상세 URL을 포함하지만, Origin은 도메인 정보만 포함함