Http Header
Intro
모든 개발자를 위한 HTTP 웹 기본 지식 강의를 수강하고 Http Header에 대한 내용을 자세히 정리해보겠습니다.
1. HTTP Header
- 정의
- HTTP 헤더는 클라이언트와 서버가 요청 또는 응답으로 부가적인 정보를 전송할 수 있도록 합니다.
- 용도
- HTTP 전송에 필요한 모든 부가 정보를 포함
- 메시지 바디의 내용, 메시지 바디의 크기, 압축 방식, 인증, 요청 클라이언트의 정보, 서버 정보, 캐시 관리와 관련한 정보 등을 포함
- 전달할 데이터를 추가로 헤더에 붙여 전달이 가능합니다.
- 구성
- Message Body (Payload) : 메시지 본문을 통해 표현 데이터를 전달합니다.
- Representation (표현) : 요청 또는 응답에서 전달할 실제 데이터
- 표현 : 표현 메타데이터 (표현 헤더) + 표현 데이터
- 표현 헤더 : 표현 데이터를 해석할 수 있는 정보를 제공합니다.
- 표현 데이터 : 요청 및 응답의 메시지 본문을 뜻합니다.
- 표현 헤더
- Content-Type : 표현 데이터 형식입니다.
- Content-Encoding : 표현 데이터의 압축 방식입니다.
- Content-Language : 표현 데이터의 자연 언어입니다.
- Content-Length : 표현 데이터의 길이입니다.
- HTTP/1.1 : 현재 웹 페이지의 HTTP 버전을 뜻합니다.
- 200 OK : HTTP의 상태코드를 뜻합니다. (200의 경우 요청이 정상 처리 되었음을 뜻합니다.)
- Content-Type 과 Content-Length는 표현 헤더입니다.
- html 태그와 JSON 형태의 데이터는 표현 데이터입니다.
- Content-Type
- 표현데이터를 보낼 타입을 정의하거나 문자 인코딩을 정의합니다.
- text/html; charset=utf-8 : 데이터의 text형식은 html 이고 utf-8 방식으로 인코딩 한다는 의미입니다.
- application/json : 파일 형태가 JSON 임을 뜻합니다.
- image/png : 이미지가 png 형태임을 뜻합니다.
- Content-Encoding
- 데이터를 압축하는데 사용하는 방식을 뜻합니다.
- 데이터를 읽는 쪽에서 해당 타입을 참고해 압축 해제를 할 수 있습니다.
- identity 타입의 경우 압축을 하지 않는다는 의미 입니다.
- Content-Language
- ko
- en
- en-US
2. 협상 (콘텐츠 네고시에이션)
- 클라이언트가 선호하는 표현 요청입니다.
- Accept : 클라이언트가 선호하는 미디어 타입입니다.
- 협상 헤더의 경우 요청시에만 사용됩니다.
- Accept-Charset : 클라이언트가 선호하는 문자 인코딩입니다.
- Accept-Language : 클라이언트가 선호하는 자연 언어입니다.
- 다중 언어를 지원하는 서버에서 기본 타입의 언어를 en으로 지정하고 있다면, 클라이언트의 요청 헤더에 Accept와 관련한 정보를 담고 있지 않을 경우 다중 언어 지원 서버에서는 en으로 구성된 내용으로 응답을 해줍니다.
- Accept-Language:ko를 헤더에 담아 클라이언트가 다중 언어 서버에 요청을 한다면, 서버에서는 en을 기본으로 지원하고 있지만 해당 요청 헤더 사항을 보고 ko로 구성된 내용을 응답 해줍니다.
- 클라이언트가 Accept-Language:ko 를 헤더에 담아 요청했지만 다중 언어를 지원하는 서버에서 ko를 지원하지 않는다면, de(독일어) 보다는 en(영어)를 지원해주기를 바랄 것입니다.
- 이러한 경우에 의해 협상의 우선순위가 필요하게 됩니다.
3. 우선순위
1. Quality Values (q)
- Quality Values (q) 값을 사용합니다.
- 0 ~ 1 의 값을 가지며, 1에 가까울 수록 높은 우선순위를 가집니다.
- 생략할 경우 1의 값을 가지게 됩니다.
-
우선순위
- ko-KR
- ko;q=0.9
- en-US;q=0.8
- en;q=0.7
2. Quality Values (q)
- 구체적으로 명시할 수록 더 높은 우선순위를 가집니다.
Accept: text/*, text/plain, text/plain;format=flowed, */*
-
우선순위
- text/plain;format=flowed
- text/plain
- text/*
*/*
3. Quality Values (q)
- 구체적인 것을 기준으로 미디어 타입을 맞춥니다.
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의 미디어 타입을 제공하므로 해당 협상 헤더의 우선순위는 1의 값을 가집니다.
- 서버에서 text/plain의 미디어 타입을 제공하지만, 협상 헤더에 존재하지 않으므로 text/*과 매칭되어 0.3의 q 값을 가집니다.
4. 전송 방식
단순 전송 Content-Length
- 클라이언트가 서버에 요청을 하면 서버는 Content-Length를 포함해서 응답 데이터의 길이를 알 수 있도록 합니다.
압축 전송 Content-Encoding
- 서버에서 응답을 보낼 시 메시지 바디 부분을 압축해서 보냅니다.
- Content-Encoding에 압축 방식 정보를 헤더에 담아 보냅니다.
분할 전송 Transfer-Encoding
- 데이터의 용량이 너무 클 경우 데이터를 분할 해서 보냅니다.
- Transfer-Encoding: chunked를 헤더에 담아 보냅니다.
- 분할 전송 방식을 선택할 경우 Content-Length 정보는 헤더에 담을 수 없습니다.
범위 전송 Range, Content-Range
- 특정 범위를 지정해서 요청에 대한 응답을 받는 전송 방식입니다.
- 클라이언트의 요청 헤더에는 Range 키워드로 범위를 지정해서 요청합니다.
- 서버의 응답 헤더에는 Content-Range 키워드로 응답 데이터의 범위와 전체 데이터의 크기를 나타냅니다.
5. Referer
- 현재 표시하는 웹 페이지가 어떤 웹 페이지에서 요청되었는지 알 수 있는 정보입니다.
Referer의 중요성
- 사이트 유입 분석
- 어떤 외부 사이트나 광고 링크를 통해서 사용자가 유입되는지 분석하여 마케팅 효과를 측정하거나 개선 방향을 설정 할 수 있습니다.
- 보안
- 특정 기능이나 페이지에 대한 접근을 통제할 수 있습니다.
- “상품 구매” 기능을 “상품 상세페이지” 에서만 접근할 수 있도록 설정할 수 있습니다.
Referer 제어
<a href="https://example.com" rel="noreferrer">링크<a>
- “noreferrer” 키워드를 통해 referer헤더를 제거 할 수 있습니다.
6. User-agent
- Http 요청을 보내는 사용자의 식별 정보를 담고 있습니다.
- 클라이언트의 요청 헤더에 포함되는 String 값으로 이루어져 있습니다.
- 디바이스의 Application, Operating System, Vendor, Browser Version 등의 정보를 포함합니다.
- 클라이언트에 대한 기본적인 정보를 파악하여 최적화된 콘텐츠를 제공하는데 유용하게 사용될 수 있습니다.
형식
User-Agent: <product> / <product-version> <comment>
- 예시
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
- Mozilla/5.0 : 접속한 브라우저가 Mozilla에 호환된다는 의미입니다. 일반적으로 모든 웹 브라우저가 사용하는 공통 표시입니다.
- X11; Linux x86_64 : 윈도우 시스템과 플랫폼을 의미합니다. X11의 경우 리눅스 시스템에서의 그래픽 서버 시스템을 나타내며, Linux x86_64는 리눅스의 64비트 x86 아키텍처를 의미합니다.
- AppleWebKit/537.36 : 웹킷 렌더링 엔진에 대한 정보를 제공합니다. 웹킷은 많은 웹 브라우저에서 사용되는 렌더링 엔진 중 하나입니다. 대표적으로 Safari, Chrome등이 이 엔진을 사용하고 있습니다. “537.36”은 웹킷 버전을 나타냅니다.
- 렌더링 엔진 : HTML, XML, CSS 등을 읽어들여 사용자가 읽을 수 있는 문서 형태로 표시하는 하나의 소프트웨어를 의미합니다.
- Gecko : Mozilla FireFox의 렌더링 엔진으로 KHTML을 지원한다는 의미입니다.
- KHTML : HTML 레이아웃 엔진입니다.
- Chrome/51.0.2704.103 : Chrome 브라우저의 버전 정보를 제공합니다.
- Safari/537.36 : Safari 브라우저와 호환성을 유지하기 위한 정보입니다.
7. Host
- 클라이언트가 요청한 호스트에 대한 정보입니다.
- 하나의 서버가 여러 도메인을 처리할 경우 해당 헤더 정보를 통해 어떤 도메인에 대한 요청인지를 파악하는데 사용됩니다.
8. Authorization
- 클라이언트의 인증 정보입니다.
Authorization: <type> <credentials>
- type
- 인증 타입이며 다른 말로는 인증 schema라고 부릅니다.
- 보통의 타입은 Basic입니다.
- credentials
- 인증 정보입니다.
- type이 Basic이라면, 사용자명과 비밀번호가 콜론을 이용해 합쳐집니다.
- 해당 결과 문자열을 base64로 인코딩합니다.
9. Cookie
- Http는 기본적으로 무상태 프로토콜이며, 클라이언트가 요청하고 응답 받았던 내용을 저장하지 않습니다.
- 로그인 상태의 경우 무상태 프로토콜 통신으로 인해 저장되지 않습니다.
- 이러한 상태를 보완하기 위해 사용되는 것이 쿠키 입니다.
- 쿠키는 서버가 클라이언트에게 전송하는 작은 데이터 조각입니다.
- 클라이언트가 사용하고 있는 브라우저는 이 데이터 조각들을 저장해 놓았다가 동일한 서버에 재 요청을 할 때 저장된 데이터를 함께 전송합니다.
- 서버는 쿠키를 보낼 때 쿠키의 만료시간을 정해서 전송합니다.
Cookie 만료시간
- 세션 쿠키 : 만료시간을 생략할 경우에 해당되며, 클라이언트가 사용하는 브라우저가 종료될 때까지 유지됩니다.
- 영속적인 쿠키 : “expires” , “max-age”를 통해 만료일을 지정할 경우 해당 날짜까지 유지됩니다.
- 사용자가 서버에 연결 요청을 보냅니다.
- 서버는 쿠키를 “set-cookie” 키워드를 통해 생성하여 응답합니다.
- 사용자는 응답받은 쿠키를 포함하여 다음 연결 수행시 요청합니다.
- 서버는 쿠키를 확인하고 사용자를 인증하며 그 후 응답합니다.
Cookie Scope
- 어떤 요청에 쿠키를 사용해야 하는지에 대한 정보를 가지고 있습니다.
- Domain : 명시한 도메인과 서브 도메인을 포함하여 쿠키로 접근이 가능함을 의미합니다.
- Path : 하위 경로를 일괄적으로 지정할 수 있습니다.
- /dev라고 path를 지정했다면, /dev 뒤에 따라오는 모든 path들에 쿠키로 접근이 가능함을 의미합니다.
Cookie 보안
- 쿠키의 담겨있는 정보를 보호하기 위해 사용합니다.
- Secure
- 쿠키는 Http와 Https를 구분하지 않지만, 해당 키워드를 통해 Https의 경우에만 쿠키를 전송할 수 있도록 제한합니다.
- HttpOnly
- Http에서만 전송이 가능하며, 자바스크립트에서의 접근을 막습니다.
- 악성 자바스크립트를 활용한 XSS 공격 방식을 방지할 수 있습니다.
- SameSite
- 클라이언트가 요청한 도메인과 설정된 도메인이 같은 경우만 쿠키를 전송합니다.
- B라는 사이트에 접근하여 A라는 사이트에 요청을 공격하는 XSRF 방식을 방지할 수 있습니다.
Cache
- 자주 사용하는 데이터에 더 빠르게 접근하기 위해 사용됩니다.
- 이미지, JS, CSS와 같은 파일들에 보통 사용합니다.
- 캐시를 사용하지 않아 요청마다 데이터를 새롭게 다운로드 받아야 한다면, 불필요한 네트워크 비용이 발생하며 웹 페이지 로딩 속도가 느려집니다.
Cache 유효시간
- Cache-Control : Max-age를 통해 캐시의 최대 수명을 설정할 수 있습니다.
Cache-Control: max-age=60
- 응답 결과를 웹 브라우저에 60초 동안 유지 한다는 의미입니다.
- 캐시의 유효시간이 만료되면 서버가 응답시에 데이터를 다시 보내게 되는 구조이며 이는 기존에 캐시에 담겼던 데이터가 변하지 않았어도 새로 데이터를 받아 저장하는 수행을 하게 됩니다.
Cache 유효성 검증 및 조건부 요청
- 캐시의 유효 시간이 지난 다음 서버에 데이터를 요청하면 이전과 같은 데이터를 응답 받거나, 다른 데이터를 응답 받게 될 것입니다.
- 이전과 같은 데이터를 받게되는 경우와 같은 트래픽 낭비를 줄이기 위해, 실제 원본 데이터가 수정 되었을 때만 데이터를 받는 방법으로 캐시 유효성 검증 및 조건부 요청을 사용해야 합니다.
Cache 검증 헤더
- Last-Modified, If-Modified-Since : 데이터의 마지막 갱신 시간으로 검증하는 방식입니다. 밀리 세컨드 단위로 시간을 설정할 수 없습니다.
- ETag, If-None-Match : 데이터의 식별자를 기준으로 검증하는 방식입니다. 위 방식의 단점을 극복할 수 있습니다.
데이터의 마지막 갱신 시간으로 검증하는 방식 최초 응답
Last-Modified: Sun, 03 Nov 2023 00:00:00 GMT
두번째 요청
If-Modified-Since: Sun, 03 Nov 2023 00:00:00 GMT
- 데이터가 마지막으로 수정된 일자를 Last-Modified 헤더에 붙여 응답합니다.
- 캐시의 유효시간이 끝나게 되면, 최초 요청시 응답 받았던 데이터 마지막 수정일을 If-Modified-Since 헤더에 붙여 요청합니다.
- 데이터에 변경이 일어나지 않았다면 서버에서는 304 Not Modified 상태 코드를 응답합니다.
데이터의 식별자를 기준으로 검증하는 방식 최초 응답
ETag: "test"
두번째 요청
If-None-Match: "test"
- 최초 응답시에 ETag 헤더에 데이터의 현재 상태에 대한 식별자를 담아 응답합니다.
- 캐시의 유효시간이 끝나게 되면, 최초 요청시 응답 받았던 ETag 헤더의 식별자 값을 If-None-Match 헤더에 붙여 요청합니다.
- 데이터에 변경이 일어나지 않았다면 서버에서는 304 Not Modified 상태 코드를 응답합니다.
Cache 제어 헤더
- Cache-control : max-age = 캐시 유효 시간을 의미합니다. 초 단위로 유효시간을 설정할 수 있습니다.
- Cache-control : no-cache = 데이터에 대한 캐시를 생성하지만, 데이터를 요청할 때 원 서버에 항상 캐시 유효성 검증을 해야합니다.
- Cache-control : no-store = 데이터에 민감한 정보가 포함되어 있어서 캐시를 생성하지 않겠다는 것입니다.
Cache 프록시 캐시
- 프록시 : 클라이언트와 서버 사이에 대리로 통신을 수행하는 것을 의미합니다.
프록시 캐시를 사용하는 이유 - 한국에 있는 클라이언트가 외국의 원 서버에 있는 특정 데이터가 필요한 상황에서 정보를 가져오기 위해 많은 시간이 소요될 것입니다. 이 때 외국의 원 서버와 한국 클라이언트의 서버 중간에 위치한 한국의 캐시 서버가 있다면 데이터를 가져오는 시간을 줄일 수 있습니다. - 이렇듯 클라이언트에서 사용하고 저장하는 캐시를 private 캐시라고 하며, 프록시 캐시를 public이라고 합니다.
- Cache-Control : public = 응답이 public 캐시에 저장되어도 된다는 의미입니다.
- Cache-Control : private = 응답이 해당 사용자만을 위한 것으로 private 캐시에 저장되어야 한다는 의미입니다.
- Cache-Control : s-maxage = 프록시 캐시에만 캐시 유효시간을 지정한다는 의미입니다.
Cache 무효화
- Cache-Control : no-cache = 데이터는 캐시해도 되지만, 항상 원 서버에 검증하고 사용해야 한다는 의미입니다.
- Cache-Control : no-store = 데이터에 민감한 정보가 있으므로 캐시를 저장하면 안된다는 의미입니다.
- Cache-Control : must-revalidate = 캐시 만료 후 최초 요청 시에 원 서버에 검증을 무조건 받아야 합니다. 원 서버 접근이 실패할 경우 504(Gateway Timeout)를 응답합니다.
no-cache와 must-revalidate의 차이점
- 원 서버와의 어떤 네트워크 통신이 원활하지 않을 경우 no-cache는 오래된 데이터를 프록시 캐시로 응답을 해주지만, must-revalidate의 경우 504에러를 응답합니다.
- 예를들어 통장 잔고와 같은 금융과 관련된 데이터의 경우 오래된 데이터를 보여주게 되어서는 안됩니다.
- 캐시를 완전히 무효화 시키려면 no-cache,no-store,must-revalidate 모두 명시하여 캐시를 무효화 시켜야 합니다.
Leave a comment