김영한님의 모든 개발자를 위한 HTTP 웹 기본 지식을 공부하고 정리하는 포스트입니다.
문서 간의 링크(HyperText)를 통해 연결할 수 있는 HTML을 전송하는 프로토콜로 시작되었다. 하지만 지금은 거의 모든 형태의 데이터(text, HTML, image, video, JSON 등)를 HTTP 메시지로 전송한다. 심지어 서버 간에 데이터를 주고 받을 때에도 대부분 HTTP를 사용한다.
HTTP는 클라이언트와 서버를 개념적으로 분리해놓은 구조이다. 클라이언트가 메시지를 통해 서버에 요청을 보낸 후 서버에서 응답이 올 때까지 대기한다. 서버가 요청에 대한 결과를 만들어서 응답하면 클라이언트는 응답 메시지를 열어서 동작한다.
과거에는 클라이언트와 서버가 한 곳에 몰려있는 구조였다. 하지만 개념적으로 분리하여 비즈니스 로직이나 데이터는 서버로, UI와 사용성은 클라이언트로 집중시켜 양쪽이 독립적으로 진화가 가능해졌다.
HTTP는 무상태 프로토콜을 지향한다. 서버가 클라이언트의 상태를 보존하지 않는다는 것이다. 아직도 이해가 되지 않아 상태 유지와 무상태를 예제로 이해해보자.
상태 유지 - Stateful
- 고객 : 이 노트북 얼마인가요?
- 점원 : 100만원 입니다. (노트북 상태 유지)
- 고객 : 2개 구매하겠습니다.
- 점원 : 200만원 입니다. 신용카드, 현금 중에 어떤 걸로 구매하시겠어요? (노트북, 2개 상태 유지)
- 고객 : 신용 카드로 구매하겠습니다.
- 점원 : 200만원 결제 완료 되었습니다. (노트북, 2개, 신용카드 상태 유지)
상태 유지 - Stateful, 점원이 중간에 바뀌면?
- 고객 : 이 노트북 얼마인가요?
- 점원 A : 100만원 입니다.
- 고객 : 2개 구매하겠습니다.
- 점원 B : ? 무슨 제품을 2개 구매하시겠어요?
- 고객 : 신용 카드로 구매하겠습니다.
- 점원 C : ? 무슨 제품을 몇 개 신용카드로 구매하시겠어요?
무상태 - Stateless
- 고객 : 이 노트북 얼마인가요?
- 점원 : 100만원 입니다.
- 고객 : 노트북 2개 구매하겠습니다.
- 점원 : 노트북 2개는 200만원 입니다. 신용카드, 현금 중에 어떤 걸로 구매하시겠어요?
- 고객 : 노트북 2개를 신용카드로 구매하겠습니다.
- 점원 : 200만원 결제 완료되었습니다.
무상태 - Stateless, 점원이 중간에 바뀌면?
- 고객 : 이 노트북 얼마인가요?
- 점원 A : 100만원 입니다.
- 고객 : 노트북 2개 구매하겠습니다.
- 점원 B : 노트북 2개는 200만원 입니다. 신용카드, 현금 중에 어떤 걸로 구매하시겠어요?
- 고객 : 노트북 2개를 신용카드로 구매하겠습니다.
- 점원 C : 200만원 결제 완료되었습니다.
상태 유지에서는 점원이 바뀌면 문맥이 사라져서(다른 점원으로 바뀔 때마다 상태 정보를 다른 점원에게 미리 알려줘야 함) 의사소통에 문제가 생기지만, 무상태에서는 고객이 필요한 정보를 매번 점원에게 넘기기 때문에 의사소통에 문제가 생기지 않는다. 따라서 갑자기 고객이 증가하는 경우, 점원을 대거 투입할 수 있다.
즉, 무상태는 서버에서 상태 유지를 하지 않고 요청 메시지에 상태를 저장하여 아무 서버나 호출이 가능하다.
이는 클라이언트 - 서버 아키텍처에서 무상태 프로토콜의 경우, 갑자기 클라이언트 요청이 증가해도 서버를 대거 투입할 수 있음을 알 수 있다. 무상태는 응답 서버를 쉽게 바꿀 수 있기 때문에 엄청난 확장성을 가져서 서버의 무한 증설이 가능하다.
TCP/IP 연결의 경우는 기본적으로 연결을 유지한다. 즉 서버 자원을 계속해서 소모하고 있다는 것이다. 반면 비 연결성 모델의 경우 클라이언트와 서버는 연결을 유지하지 않아 최소한의 자원을 사용할 수 있다.
요청 메시지의 경우 요청 방식, 쿼리, 버전이 들어있는 시작 라인과 호스트 정보가 들어있는 헤더, 필수로 있어야하는 공백 라인이 있다.
반면 응답 메시지의 경우 요청 메시지와 시작 라인이 다르다. 시작라인에는 HTTP 버전, 요청 받은 값이 있으며 헤더에는 content의 정보가 들어있다. 응답 메시지 또한 공백 라인이 필수로 있어야하고 메시지 바디라인에는 응답할 메시지(HTML 등)가 온다.
HTTP-message = start-line
* (header-filed CRLF)
CRLF //공백
[ message-body ]
start-line = request-line과 status-line으로 구성되어 있다.
request-line(요청 메시지) = method
SP(공백)
request-tartget(path, 요청할 대상)
SP
HTTP-version
CRLF(엔터)
=> GET
/search?q=hello&hl=ko
HTTP/1.1
http://...?x=y
와 같이 다른 유형의 경로 지정 방법도 있음status-line(응답 메시지) = HTTP-version
SP
status-code(상태 코드)
SP
reason-phrase(이유 문구)
CRLF
클라이언트가 보낸 요청에 대한 상태를 서버가 보내줄 때 사용, 요청 성공과 실패를 나타냄
사람이 이해할 수 있는 짧은 상태 코드 설명 글
header-field = field-name(대소문자 구분 안함)
:
OWS(띄어쓰기 허용)
field-value
OWS
=> Host
:
www.google.com