Today I Learned_220822
HTTP
HTTP
HTTP의 특징
- 클라이언트 서버 구조
- 무상태 프로토콜
- 비연결성
- HTTP 메시지 사용
HTTP로 할 수 있는 것들
HTTP : HyperText Transfer Protocol
처음에는 하이퍼텍스트를 전송하기 위한 프로토콜로 시작 -> 지금은 모든 것을 전송한다
HTML, TEXT, 이미지, 음성, 영상, 파일, JSON, XML 등등
서버간에 데이터를 주고 받을 때 HTTP 사용 (서버간에 TCP를 이용하여 직접 통신한다거나 그런 경우는 없음 - 게임 서버와 같은 특수한 경우)
HTTP 역사
- HTTP/1.1 : 1997년에 등장. 가장 많이 사용되며 가장 중요한 버전. 여기에 대부분의 기능이 있다.
- RFC2068 (1997) -> RFC2616 (1999) -> RFC7230~7235 (2014) 버전이 잘게 쪼개짐
- RFC2616버전으로 설명되어 있는 것이 많다.
- HTTP/2 : 2015년. 성능 개선에 초점
- HTTP/3 : 2022년. 성능 개선에 초점
HTTP/1.1에 대해 공부하는 것이 가장 중요하다.
HTTP/1.1과 HTTP/2 -> TCP 기반으로 개발. 속도에 최적화되지는 않은 프로토콜
HTTP/3 -> UDP 기반으로 개발
클라이언트 서버 구조
클라이언트가 HTTP 메시지를 통해 서버에 요청을 보냄 -> 클라이언트는 서버의 응답이 올 때 까지 기다림
응답이 오면 응답을 열어서 클라이언트가 동작
클라이언트와 서버가 분리되어 있음 (예전에는 분리되어 있지 않음)
비즈니스 로직은 서버에 넣고, UI와 사용성 등 사용자에 가까운 것은 클라이언트에 집중 -> 서버와 클라이언트가 각각 독립적으로 진화할 수 있다. 각자의 역할에 집중할 수 있다.
무상태 프로토콜(stateless)
HTTP는 무상태 프로토콜을 지향한다.
- 서버가 클라이언트의 상태를 보존하지 않는다
- 장점 : 서버 확장성 높음
- 단점 : 클라이언트가 추가 데이터를 전송해야 함
stateful : 서버가 클라이언트의 이전 상태(문맥)을 보존한다.
stateless : 중간에 요청을 받는 자가 다른 자로 바뀌어도 문맥 유지를 할 수 있다 - 서버 입장에서는 확장성이 커진다.
stateful vs. stateless
- stateful : 중간에 다른 서버로 바뀌면 안 된다 (중간에 다른 서버로 바뀔 때 상태 정보를 다른 서버에게 미리 전달해줘야 한다.)
- stateless : 중간에 다른 서버로 바뀌어도 된다 (갑자기 클라이언트 요청이 증가해도 서버를 대거 투입할 수 있다)
- stateless는 응답 서버를 쉽게 바꿀 수 있다 -> 무한한 서버 증설 가능 (scale out - 수평 확장에 유리)
stateless의 한계
- 무상태로 설계할 수 없는 경우가 존재 (ex. 로그인)
- 브라우저의 쿠키와 서버의 세션을 이용하여 상태 유지
- 상태 유지는 꼭 필요한 경우에만 최소한으로 사용하자
- 데이터를 너무 많이 전송한다
최대한 무상태로 설계하되, 어쩔 수 없는 경우만 상태 유지로 설계하자.
비연결성
TCP/IP는 기본적으로 연결을 유지한다 - 클라이언트가 놀고있음에도 연결을 계속 유지하므로 서버 자원을 계속해서 소모한다.
연결을 유지하지 않는 모델 - 서버가 유지하는 자원을 최소한으로 줄일 수 있다는 장점이 있음
- HTTP는 연결을 유지하지 않는 모델
- 일반적으로 초 단위 이하의 빠른 속도로 응답
- 1시간 동안 수천 명이 서비스를 사용해도 실제 서버에서 동시에 처리하는 요청은 수십개 이하로 매우 작음 -> 서버 자원을 효율적으로 사용할 수 있음
비연결성의 단점
- TCP/IP 연결을 새로 맺어야 함 -> 3-way handshake 시간 추가
- 웹 브라우저로 사이트를 요청하면 HTML, JS, css, 추가 이미지 등 수 많은 자원이 함께 다운로드
- HTTP 지속 연결(Persistent Connections)로 문제 해결
- 예 : 이전에는 클라이언트와 서버와 연결하려면, 연결-HTML응답-종료, 연결-JS 응답-종료… 와 같이 이루어짐
- 지속 연결 : 연결-HTML응답-JS응답-이미지응답-종료
- 몇십초 동안 유지하는 등 내부 메커니즘에 의해 지속 연결을 유지
- HTTP/2와 HTTP/3에서는 이를 보완함
최대한 stateless하게 설계해야 한다.
HTTP 메시지
요청 메시지와 응답 메시지의 구조가 다르다. (시작 라인부터 다름)
기본 구조
- start-line
- header
- emply line(CRLF) -> 반드시 들어가야 함
- message body
rfc 7230 공식 스펙
HTTP-message = start-line
*( header-field CRLF )
CRLF
[ message-body ]
start-line
크게 request-line과 status-line으로 되어 있음
요청 메시지(request-line)
- request-line : HTTP-method SP(공백) request-target SP HTTP-version(HTTP 버전) CRLF(엔터)
- HTTP-method : GET, POST, PUT, DELETE
- GET : 리소스 조회
- POST : 리소스를 줄 테니까 요청 내역을 처리
- request-target : absolute-path[?query]의 형식
- absolute-path이므로 “/”로 시작한다
응답 메시지(status-line)
- status-line : HTTP-version SP status-code SP reason-phrase CRLF
- status code : 매우 중요. 클라이언트가 보낸 요청이 성공했는지, 실패했는지를 나타냄
- 200 : 성공
- 400 : 클라이언트 요청 오류
- 500 : 서버 내부의 오류
- reason-phrase : 사람이 이해할 수 있는 짧은 상태 코드 설명 글(200 OK에서 OK)
header-field
field-name “:” OWS field-value OWS
field-name은 대소문자 구분이 없다.
field-name 옆에 있는 “:”는 띄어쓰기를 하지 않음에 유의
OWS : 띄어쓰기 허용. 띄어쓰기를 해도 되고 안 해도 된다
request message
GET /search?q=hello&hl=ko HTTP/1.1
Host: www.google.com
response message
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 3423
<html>
<body>...</body>
</html>
HTTP 헤더의 용도
- HTTP 전송에 필요한 모든 부가정보
- 메시지 바디의 내용(HTML인지? XML인지?), 메시지 바디의 크기, 압축 여부, 인증 정보, 요청 클라이언트의 브라우저 정보, 서버 애플리케이션 정보, 캐시 정보 등…
- body 빼고 필요한 메타데이터 정보가 다 들어가 있음
- 표준 헤더 : https://en.wikipedia.org/wiki/List_of_HTTP_header_fields
- 필요 시 임의의 헤더 추가 가능 (약속된 클라이언트와 서버만 이해 가능함)
message-body
실제 전송할 데이터 - HTML 문서, 이미지, 영상, JSON 등등 byte로 표현할 수 있는 모든 데이터 전송 가능
압축해서 보내면 압축된 데이터가 들어간다.
TCP와 HTTP의 관계
HTTP는 TCP 기반 프로토콜인데 비연결성이다? - https://www.inflearn.com/questions/313406 해당 링크 참조