HTTP 기본 지식
HTTP 기본 지식
-김영한 - 모든 개발자를 위한 HTTP 웹 기본 지식 강의 내용 일부 정리
HTTP
- HTTP는 hypertext를 전송하기 위한 프로토콜
- 현재는 모든 형태의 데이터를 HTTP로 보냄
- 이미지, HTML, JSON, 파일 등등
- HTTP 버전별 역사
- 0.9: 1991년, GET 메서드만 지원, 헤더 X
- 1.0: 1996년, 메서드, 헤더 추가
- 1.1: 1997년, 가장 많이 사용되는 버전, 2014년에 개정
- 2: 2015년, 성능 개선
- 3: 진행 중, UDP 사용해 성능 개선
- HTTP 특징
- 클라이언트 - 서버 구조
- Stateless
- 비연결성
- HTTP 메시지를 활용해 통신
- 단순하고, 확장이 쉬움 (크게 성공한 이유)
- Stateless
- 서버가 클라이언트의 상태(state)를 보존하지 않음
- 중간에 서버가 바뀌어도 되므로 서버 확장성이 높아짐
- 클라이언트가 데이터를 더 보내야 함
- 그러나 실제로는 로그인 등의 상태는 유지되어야 하므로, 쿠키 / 세션등을 활용해 일부 상태는 유지
- 비연결성
- 요청에 대한 응답을 보내고 연결을 끊음
- 서버 자원을 효율적으로 사용 가능
- 그러나 TCP/IP 연결을 매번 새로 맺어야 한다는 단점 존재
- 지금은 HTTP 지속 연결을 사용해 문제를 해결
- HTTP 2, 3에서 더욱 최적화됨
- HTTP 메시지
- 모든 형태의 데이터를 HTTP 메시지에 담아 전송
- 요청 / 응답 메시지가 존재하고, 시작 라인, 헤더, 바디로 구성됨
- 시작 라인: 메시지 가장 윗 줄
- 요청 메시지: HTTP 메서드, 요청 대상, HTTP 버전으로 구성
- 응답 메시지: HTTP 버전, HTTP 상태 코드, 이유 문구로 구성
- 헤더:
필드 이름
:필드 값
의 쌍으로 구성되며, HTTP 전송에 필요한 부가 정보가 담김 - 바디: 실제 전송할 데이터가 들어가며, byte로 표현 가능한 모든 데이터 전송 가능
HTTP Method
- HTTP Method의 필요성
- HTTP로 API를 만들기 위해서는 URI를 설계해야 함
- URI에는 리소스만 매핑하는 것이 좋음
- 리소스로 어떤 행위를 할 지는 HTTP Method로 분리하면 됨
- HTTP Method 종류
- GET: 리소스 조회
- POST: 요청 데이터 처리 (주로 등록)
- PUT: 리소스를 대체
- PATCH: 리소스의 일부분을 변경
- DELETE: 리소스 삭제
- 이외에도 HEAD, OPTIONS, CONNECT, TRACE 등 존재
- GET: 조회
- 서버에 전달하고 싶은 데이터는 쿼리 스트링을 통해 전달
- 메시지 바디를 통해 데이터 전달이 가능은 하지만, 지원하지 않는 서버가 많음
- 그렇기 때문에 쿼리 스트링으로 데이터를 전달해야 함
- POST: 처리
- 메시지 바디를 통해 서버로 요청 데이터를 전달
- 서버는 요청 데이터를 받아 처리
- 주로 신규 등록 및 프로세스 처리 등을 담당. 메드가 애매할 때는 POST를 사용
- 리소스마다 POST 요청을 처리하는 방식이 다를 수 있음
- PUT: 대체
- 리소스가 없으면 생성하고, 있으면 대체하는 메서드
- 기존 리소스를 아예 덮어버림
- 특정 필드만 데이터를 보내서 수정하는 행위는 불가능
- PATCH: 일부 변경
- 리소스를 부분적으로 변경하는 메서드
- PUT과 달리 특정 필드의 데이터를 수정 가능
- DELETE: 제거
- 리소스를 제거
- HTTP 메서드의 속성
- 각 HTTP 메서드는 각 메서드마다 다음과 같은 성질을 가질 수 있음
- 안전, 멱등, 캐시 가능
- 안전: 호출해도 리소스를 변경하지 않는 성질
- GET, HEAD가 해당
- POST, PUT, DELETE 등은 아님
- 멱등: 1번 호출과 여러번 호출의 결과가 같은 성질
- GET, PUT, DELETE등이 해당
- POST는 아님
- 캐시 가능: 응답 결과를 캐시 가능 여부
- GET, HEAD, POST, PATCH 가능
- 그러나 실제로는 POST와 PATCH는 해시하기가 힘듦
- 따라서 GET, HEAD 정도만 캐시함
HTTP Status Code
- HTTP 상태 코드는 클라이언트가 보낸 요청의 처리 상태를 응답에서 알려주는 기능
- 세 자리 정수로 표현됨
- 1XX: Informational, 요청이 수신되어 처리 중
- 2XX: Successful, 요청 정상 처리
- 3XX: Redirection, 요청을 완료하려면 추가 행동 필요
- 4XX: Client Error, 클라이언트 오류로 서버가 요청 수행 불가
- 5XX: Server Error, 서버 오류
- 1XX: 거의 사용할 일이 없음
- 2XX: 성공
- 200 OK
- 요청 성공을 의미
- 정상 처리되는 경우 대부분 200으로 응답
- 201 Created
- 요청에 성공해서 새로운 리소스가 생성됨
- 202 Accepted
- 요청이 접수되었으나 처리가 완료되지 않음
- 배치 처리하는 경우 해당될 수 있음
- 204 No Content
- 요청을 수행했으나 응답 메시지 바디에 보낼 데이터 없음
- Ex) 웹 문서 편집기의 save 버튼
- 200 OK
- 3XX: 리다이렉션
- 300 Multiple Choices: 사용 X
- 301 Moved Permanently
- 리소스의 URI가 영구적으로 이동된 경우
- 새로운 리소스 URI로 이동(리다이렉션)시켜줘야 함
- 리다이렉션시 요청 메서드를 GET으로 바꾸고, 본문이 제거될 수 있음
- 302 Found
- 301과 달리 리소스의 URI가 일시적으로 변경된 경우
- 리다이렉션시 요청 메서드를 GET으로 바꾸고, 본문이 제거될 수 있음
- 원래 302의 목표는 HTTP 메서드를 유지하는 것이지만, 실제로는 GET으로 변경하는 브라우저가 많음
- 이를 확실하게 구분하기 위해 303, 307이 등장했지만, 실제로는 302를 여전히 많이 사용
- GET으로 변해도 문제가 없는 경우에는 302를 주로 사용
- 303 See Other
- 302와 동일하나, 명확하게 요청 메소드를 GET으로 바꿈
- 304 Not Modified
- 클라이언트에게 리소스가 수정되지 않았음을 알려줌
- 클라이언트는 캐시를 재사용 가능
- 응답에는 Body가 없어야 함
- 307 Temporary Redirect
- 302와 동일하나, 요청 메서드와 본문을 유지
- 308 Permanent Redirect
- 301과 동일하나, 요청 메서드와 본문을 유지
- 4XX: 클라이언트 오류
- 400 Bad Request
- 요청 구문, 메시지, 파라미터, API 스펙 등에 오류가 존재할 때
- 요청 자체가 잘못된 것이므로 클라이언트가 수정해야 함
- 401 Unauthorized
- 리소스에 대한 인증이 되지 않은 경우
- 응답 헤더의 WWW-Autehnticate 헤더에 인증 방법을 알려 줌
- Unauthorized는
"인가되지 않음"
을 의미하므로, 이름이 잘못 설계되었음
- 403 Forbidden
- 인증은 되었지만, 접근 권한이 없는 경우
- 404 Not Found
- 요청 리소스가 서버에 없는 경우
- 혹은 권한이 부족한 리소스에 접근할 때도 404 상태 코드를 보내기도 함
- 405 Method Not Allowed
- 요청 메소드가 잘못된 경우
- 400 Bad Request
- 5XX: 서버 오류
- 500 Internal Server Error
- 서버 내부 문제가 있을 때
- 웬만한 서버 문제는 500 상태 코드로 응답
- 서버 내부 문제가 아닌 경우, 특히 클라이언트 오류를 500으로 보내면 안 됨!
- 503 Service Unavailable
- 서버가 일시적 과부하 혹은 예정된 작업으로 요청 처리 불가
- 헤더의 Retry-After 필드에 복구 시기를 보내줄 수 있음
- 504 Gateway Timeout
- 도달하려는 서버가 웹 사이트를 표시하기 위한 다른 서버로부터 응답을 받지 못했을 때
- 프록시 캐시 서버가 origin 서버에 연결하지 못한 경우
- 500 Internal Server Error
- PRG: POST/Redirect/Get
- POST로 요청 후 새로 고침하면, 같은 요청이 2번 나갈 수 있음
- 이런 문제를 막기 위해 POST 요청 후 결과 화면을 GET 메소드로 리다이렉트함
- 이렇게 되면 아무리 새로고침해도 결과가 똑같음
HTTP Header
- HTTP 헤더는 필드이름: 필드 값 으로 구성
- HTTP 전송에 필요한 모든 부가 정보를 포함 (바디의 길이, 압축 방식, 데이터 종류 등등)
- 표현 헤더
- 과거(RFC 2616, 현재는 폐기)에는 데이터에
엔티티
라는 이름을 사용함 - 2014년에 개정되면서
엔티티
대신표현
이라는 이름을 사용 - 메시지 바디를 통해 표현 데이터를 전달함
- 이 표현 데이터를 해석할 수 있는 정보를 제공하는 것이
표현 헤더
- 다음과 같은 필드 존재
Content-Type
: 표현 데이터의 형식 (text/html, application/json, image/png 등)Content-Encoding
: 표현 데이터의 압축 방식 (gzip, identity(압축 X) 등)Content-Language
: 표현 데이터의 언어 (ko, en, en-US 등)Content-Length
: 표현 데이터의 길이 (바이트 단위, Transfer-Encoding 사용하는 경우에는 사용 불가)
- 과거(RFC 2616, 현재는 폐기)에는 데이터에
- 협상 헤더
- 클라이언트가 선호하는 표현을 응답으로 받기 위해 요청 시에 사용하는 헤더
Accept-Language
필드를 이용해 클라이언트가 선호하는 자연 언어를 받을 수 있음- 원하는 컨텐츠의 우선순위를 Quality Values 값(q)을 이용해 설정 가능
- 0 부터 1으로, 높을 수록 우선적으로 요청. 다음과 같이 사용
Accept-Language: ko-KR;q=0.9,en-US;q=0.8,en;q=0.7
- q값이 없는 경우 구체적인 요청을 우선으로 함
- 전송 방식 헤더
- 전송에는 다음과 같은 방법들이 존재
- 단순 전송
- 데이터를 단순히 전송
- 응답 헤더에
Content-Length
만 넣으면 됨
- 압축 전송
- 데이터를 압축해서 전송
- 응답 헤더에
Content-Length
와Content-Encoding
을 넣어 압축 방식을 표기
- 분할 전송
- 데이터를 분할해서 전송,
Content-Length
를 넣으면 안됨! - 응답 헤더에
Transfer-Encoding
을 넣어 분할 전송임을 표시 - 마지막 데이터에 끝을 표시해 줘야 함
- 데이터를 분할해서 전송,
- 범위 전송
- 특정 범위를 요청해서 해당 범위에 대한 데이터를 전송
- 요청 헤더에서는
Range
필드로 요청할 데이터의 범위를 요구 - 응답 헤더에서는
Content-Range
필드로 응답한 데이터의 범위 표시
- 일반 정보 헤더
- From
- 요청에서 사용하는 유저 에이전트의 이메일 정보
- 검색 엔진이 아닌 이상 잘 사용되지 않음
- Referer
- 요청에서 사용하는 현재 요청된 페이지 이전 웹 페이지 주소
- 유입 경로를 분석 가능
- User-Agent
- 요청에서 사용하는 유저 에이전트 애플리케이션 정보
- 웹 브라우저 정보 등이 포함됨
- Server
- 응답에서 사용하는 요청을 처리하는 오리진 서버의 정보
- Date
- 응답에서 사용하는 메시지 생성 날짜
- From
- 특별 정보 헤더
- Host
- 요청에서 사용하는 요청한 호스트 정보
- 하나의 IP 주소에 여러 도메인이 존재할 수 있기 때문에, 필수임
- Location
- 응답에서 사용하는 페이지 리다이렉션 위치
- 브라우저는 응답 코드가 3XX이면서, Location 헤더가 있는 경우, 해당 위치로 리다이렉트
- Allow
- 응답에서 보여주는 허용 가능한 HTTP 메소드를 알려주는 헤더
- 상태코드가 405일때 포함해야 함
- Retry-After
- 응답 코드에서 보내주는 다음 요청까지 기다려야 하는 시간
- 상태코드가 503일때 언제 서비스가 재개될 지 알려줄 수 있음
- Host
- 인증 헤더
- Authorization: 요청에서 클라이언트 인증 정보를 서버에 전달하는 헤더
- WWW-Authenticate: 401 응답에서 리소스 접근시 필요한 인증 방법을 정의
- 쿠키 헤더
- Set-Cookie: 응답에서 클라이언트로 전달해주는 쿠키
expires=Sat, 26-Dec-2020 00:00:00 GMT;
: 2020년 12월 26일이 되면 쿠키 삭제expires=3600
: 3600초가 지나면 쿠키 삭제domain=abc.com
:abc.com
을 포함한 하위 도메인 접근 시 쿠키 사용path=/abcd
:/abcd
하위 경로에서만 쿠키 사용 가능Secure
: 이 값이 있으면 https에서만 전송HttpOnly
: XSS 공격을 방지하기 위한 값. JS에서 접근 불가능하게 만듦SameSite
: XSRF 공격을 방지하기 위한 값. 요청 도메인과 쿠키의 도메인이 같은 경우에만 쿠키 전송
- Cookie: 요청에서 HTTP 서버에 보내는 쿠키
- Set-Cookie: 응답에서 클라이언트로 전달해주는 쿠키
HTTP Cache
- 캐시가 없는 경우
- 데이터가 변경되지 않아도 새로고침시 매번 데이터를 새로 다운로드 받아야 함
- 매우 느리고 비쌈
- 캐시를 적용한 경우
- 응답을 보낼 때 헤더에
cache-control: max-age=60
과 같은 형태로 보냄 - 응답 결과를 브라우저는 캐시에 저장
- 60초간은 새로운 요청을 보내도 캐시에서 조회하게 됨, 빠르고 쌈
- 응답을 보낼 때 헤더에
- 캐시 시간 초과
- 캐시 유효 시간이 초과된 경우 서버에서 기존 데이터가 변경 되지 않았을 때도 있음
- 이런 경우에는 기존 캐시 값 재사용 가능
- 제일 처음 응답을 보낼 때 데이터가 마지막으로 수정된 시간을 보내주면 됨
- 응답에서
Last-Modified: xx
형태로 보내줌 - 캐시가 만료되면
if-modified-since: xx
형태로 브라우저가 요청- xx 시간 이후로 변경이 없으면 304 Not Modified 응답을 보내줌
- 이 경우 기존 데이터를 재활용하기 때문에 바디를 전송하지 않음
- 변경되면 200 OK 응답을 보내주고, 데이터 재전송
- 이 경우는 날짜 기반의 로직이기 때문에 1초 미만의 캐시 조정이 불가능하다는 단점 존재
- ETag: 캐시용 데이터에 고유한 버전 이름을 달아주는 방법
- ETag는 데이터가 변경되면 같이 변경됨
- 단순히 ETag가 같으면 유지, 다르면 다시 데이터를 받으면 됨
- ETag는 응답에서 보내주는 헤더 항목
- 브라우저가 캐시 시간 초과로 요청할때는
If-None-Match: ETag
를 보내면 됨 - 캐시 제어 로직을 서버에서 완전히 관리 가능하다는 장점이 있음
- 애플리케이션을 배포할 때 ETag를 모두 갱신하는 방법도 존재
- 캐시 제어 헤더
- Cache-Control
- 캐시 정책을 결정하는 필드
max-age=60
: 60초 동안 캐시 유지no-cache
: 데이터는 캐시 가능, 그러나 매 번 origin 서버에 검증 후 사용no-store
: 데이터에 민감한 정보가 있으므로 저장 불가 (캐시 X)must-revalidate
: 캐시 만료후 조회시 origin 서버에 검증해야 하고, 실패시 오류가 발생해야 함
- Pragma: Cache-control 하위 호환
- Expires: 만료일을 지정하는 필드. Cache-control 하위 호환이므로 사용 지양
- 외에도 전술한
ETag
,If-None-Match
등의 캐시 제어 필드 존재
- Cache-Control
- 프록시 캐시
- 매 번 origin 서버에 요청하기는 힘드므로 프록시 캐시 서버를 두어 운용
- Cache-control 값이 다음에 따라 프록시 캐시 서버 정책이 달라짐
public
: 응답이 프록시 캐시 서버에 저장되어도 됨private
: 응답이 프록시 캐시 서버에 저장되면 안 됨. Private한 공간에만 저장 가능s-maxage
: 프록시 캐시에 적용되는 max-age
Age: 60
은 프록시 캐시 서버에서 값이 머문 시간을 의미
- 캐시 무효화
- 브라우저가 캐시를 아예 생성하지 않도록 하는 방법
- 헤더에
Cache-Control: no-cache, no-store, must-revalidate
+Pragma: no-cache
를 추가 no-cache
와must-revalidate
를 같이 사용해야 하는 이유no-cache
는 origin 서버에 접근이 불가능한 경우에도, 프록시 캐시 서버에서 200 OK를 반환할 수 있음- 그러나
must-revalidate
는 origin 서버에 접근이 불가능한 경우 504 Gateway Timeout을 보내야 함
References
- 김영한 - 모든 개발자를 위한 HTTP 웹 기본 지식 (https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard)