이전 포스팅에는 HTTP를 알아보기 전에,
먼저 인터넷, 웹 생태계를 이해하고자 인터넷 프로토콜 TCP/IP 4계층을 알아보고
4계층이 각각 어떻게 구성되어 있는지 알아봤다.
애플리케이션 계층에서 사실상 표준으로 사용되는 통신 규약인 HTTP.
HTTP를 사용하기까지의 과정을 알아봤으니, 본격적으로 HTTP에 대해 알아보자.
HTTP는 오랫동안 애플리케이션 계층에서 클라이언트와 서버의 통신을 책임졌던 만큼
당연히 그 모습도 변화하며 진화해왔다.
현재 가장 많이 사용되는 HTTP 버전은 HTTP/1.1 버전이고, TCP 기반이다.
TCP/IP 4계층에서 TCP에는 단점이 있어 UDP를 사용한다고 했는데,
사실 UDP는 HTTP/3 버전으로 비교적 최근에 도입되어 그 영향을 넓혀가고 있는 중이다.
클라이언트와 서버는 통신 시 최선의 버전을 협상하여 사용한다.
또한 TCP를 보완해서 사용하는데 이제부터 자세히 알아보자.
HTTP는 어떤 특징을 가지고 있길래, 사실상 표준 통신 규약이 되었을까?
HTTP의 가장 큰 특징 중 하나는 바로 Stateless(무상태 프로토콜)이다.
무상태 프로토콜이란, 클라이언트의 전송 정보를 유지하지 않는 특징으로 반대는 Stateful이다.
클라이언트의 전송 정보를 유지하지 않는다는 것이 무슨말일까?
클라이언트 전송 정보 중에 대표적인 것이 바로 로그인 정보이다.
클라이언트 전송 정보를 유지하지 않기 때문에, 로그인 정보 또한 유지되지 않는다.
로그인 정보가 유지되지 않기 때문에로그인 후 이용할 수 있는 회원 기능도 이용할 수 없다.
Stateful은 클라이언트 전송 정보를 유지하는데, Stateful이 더 좋은 것이 아닌가?
좋은 것은 반드시 Trade-Off가 있다.
전송 정보를 유지하려면 그 정보를 기억해야하고, 당연히 서버 메모리를 사용한다.
또한 정보가 기록된 서버만이 클라이언트의 요청을 처리할 수 있다.
서버를 여러대로 확장하는 것이 상대적으로 어렵다.
이제 쓸모없어 보이는 Stateless가 달라보이지 않는가?
저장할 정보가 없기 때문에 서버의 메모리 사용이 적다.
또한, 서버가 정보를 저장할 필요가 없기 때문에 여러 대의 서버로 쉽게 확장 가능하다.
참고로 이렇게 서버를 여러 대로 확장하는 것을 Scale-Out,
서버 자체의 성능을 향상하는 것을 Scale-Up이라고 한다.
하지만 서버가 여러 대인 만큼, 네트워크 부하가 크다는 점은 단점으로 작용한다.
HTTP는 서버와 클라이언트가 네트워크 연결을 유지하지 않는다.
네트워크 연결을 유지하지 않고 필요할 때만 사용하기 때문에 효율적으로 사용이 가능하지만,
연결이 필요할 때마다 TCP/IP 연결(3 way handshaking)을 해야한다는 점이 단점이다.
HTTP는 이 점을 보완하기 위해 연결 후에 일정 시간 동안은 연결을 유지하는
HTTP 지속 연결을 사용하고 있다.
HTTP가 무엇이고 어떤 특징을 가지고 있는지 간단히 살펴보았다.
HTTP 규약은 결국 HTTP Message를 작성하는 것인데, 총 4개의 구성으로 이루어져 있다.
start line은 클라이언트가 요청할 때와 서버가 응답할 때 2가지로 분류할 수 있다.
클라이언트가 요청하는 Request Message의 start line의 구성은 다음과 같다.
[HTTP Method] [request-target] [HTTP Version]
request-target은 URL에서 파생된 절대경로와 query로 이루어진 문자열이다.
참고로 절대 경로는 항상 동일한 위치를 가리키는 경로이고,
상대 경로는 현재 작업 위치에 따라 달라질 수 있는 경로이다.
HTTP Version은 위에서 학습한 HTTP 버전이다. 보통 HTTP/1.1을 사용한다.
중요한 것은 HTTP Method이다.
Resource를 다루는 행위마다 request-target을 구분하는 것이 아니라,
HTTP Method를 통해서 구분해야 한다.
HTTP Method에는 여러 종류가 있지만 가장 많이 사용하는 것들을 위주로 알아보자.
Resource를 조회하는 메서드이다.
전달하고 싶은 데이터는 query로 전달한다.
message body로도 전달 가능하지만, 지원하지 않는 경우가 많아 query 사용을 권장한다.
GET 메서드로 Request를 요청하여도 서버의 데이터가 변하지 않는 안전 특성을 가진다.
또한, 몇번을 수행해도 결과가 같은 멱등 특성을 가진다.
GET 메서드는 캐시 사용이 가능하다.
데이터를 전송하고 처리하도록 하는 메서드이다.
전송한 데이터로 회원 가입하거나, 댓글을 등록하는 등 데이터 처리 방식은 사전에 정의한다.
데이터는 message body를 통해서 전달한다.
GET 메서드는 query를 통해서 데이터를 전달하는데,
query가 아닌 message body를 사용할 땐 POST 메서드를 사용해야 한다.
POST 메서드는 데이터를 처리하므로 안전하지도, 멱등하지도 않다.
데이터를 수정하는데, 기존 데이터를 완전히 삭제하고 수정하는 메서드이다.
데이터가 없으면 생성하고, 일부 필드가 없는 경우에는 기본값으로 대체한다.
따라서 일부 필드만 수정하는 것이 불가능하다.
수정하는 데이터에 접근하는 것이기 때문에 처리할 URL 경로를 정확히 알고 있는 경우이다.
데이터를 변경하기 때문에 안전하지는 않지만, 몇번을 수행해도 결과는 같아 멱등하다.
데이터를 수정하는데, PUT과 달리 일부 수정이 가능한 메서드이다.
일부 필드가 없는 경우에는 기존 값을 유지한다.
PATCH 메서드를 지원하지 않는 경우 POST 메서드를 사용한다.
데이터를 변경하므로 안전하지 않고, 기존 데이터를 유지하며 변경하므로 멱등하지 않다.
데이터를 삭제하는 메서드이다.
데이터를 변경하므로 안전하지 않지만, 멱등하다.
앞서 URL에서 query를 배우고, message body까지 학습했다.
데이터는 이렇게 query 또는 message body 방식을 통해 클라이언트와 서버 사이에 교환된다.
HTTP 메서드와 함께 데이터를 요청하는 유형은 크게 4가지로 나눌 수 있다.
변화하지 않는 정적 데이터를 조회하는 유형이다.
데이터를 호출하기 위해 별도의 데이터를 요구하지 않는다.
GET 메서드로 단순 호출한다.
전달한 데이터에 따라 결과가 달라지는 동적 데이터를 조회하는 유형이다.
데이터를 조회하기 때문에 POST가 아닌 GET 메서드를 사용한다.
(POST는 데이터를 받아 처리할 때에 사용하며 조회는 GET 메서드를 사용한다)
GET 메서드와 함께 필요한 데이터는 query로 전달한다.
HTML 형식에서 데이터를 전달하는 유형이다.
HTML 형식은 Header에 Content-Type: applcation/x-www-form-urlencoded가 추가된다.
key=value 형식으로 데이터를 전송하며,
URL에 사용할 수 없는 문자는 %기호와 16진수로 변환하는 url encoding을 수행한다.
조회의 경우 GET 메서드와 함께 query에 추가하여 요청할 수 있고,
데이터 변경은 POST 메서드와 함께 message body에 추가하여 요청할 수 있다.
HTML 형식은 GET과 POST만 지원하기 때문에 HTTP Method 만으로 구분할 수 없고,
URL에 데이터 사용을 표현하는 컨트롤 URL을 사용한다.
HTML FORM은 이미지와 같은 Binary 파일을 다룰 수 있는데,
Header에 Content-Type: multipart/form-data; boundary={boundaryString}이 추가된다.
이 때 boundaryString을 구분자로 특수한 message body가 작성된다.
HTTP API란 HTTP를 사용하여 클라이언트와 서버가 약속한 형식으로 통신하는 것을 의미한다.
주로 JSON 형식 통신으로 Header에 Content-Type: application/json이 추가된다.
GET 메서드와 query 형태로 전달하거나,
POST, PUT, PATCH 메서드와 message body를 사용하여 데이터를 전달한다.
데이터를 받아 데이터를 등록하는 상황에서 URL을 새롭게 설계하는 경우
서버가 URL을 생성해서 관리하면 컬렉션 패턴,
클라이언트가 URL을 알고 관리하는 경우 스토어 패턴이라고 부른다.
서버가 응답하는 Response Message의 구성은 다음과 같다.
[HTTP Version] [HTTP Status Code] [reason-phrase]
HTTP Version의 경우 앞서 설명한 HTTP 버전과 같고 보통 HTTP/1.1을 사용한다.
reason-phrase는 status-code의 이유 또는 간단한 부연 설명이 작성된다.
Request Message에서 중요한 것이 HTTP Method였다면
Response Message에서 중요한 것은 HTTP Status Code이다.
HTTP Status Code는 클라이언트 Request에 따른 서버의 처리 결과를 나타내는 코드로,
이 코드를 통하여 클라이언트가 대략적인 결과를 인식할 수 있다.
HTTP Status Code에는 1xx, 2xx, 3xx, 4xx, 5xx가 있는데
대표적으로 사용되는 번호를 살펴보자.
요청이 수신되어 처리중인 상태를 의미한다.
거의 사용하지 않는다.
요청이 정상 처리된 것을 의미한다.
요청이 완료되기 위해 추가적인 행동이 필요한 것을 의미한다.
응답에 Location Header가 있으면 Location URL로 자동으로 이동한다.
이를 Redirection이라 하는데, Request → 3XX → Location URL 재요청 → 2XX로 진행된다.
서버 주소 자체 이전과 같이 첫 Request의 URL이 영구적으로 변경된 것을 영구 리다이렉션,
재고 소진과 같이 일시적으로 변경된 것이라면 일시 리다이렉션이라고 부른다.
캐시를 위해 사용되는 304 특수 리다이렉션도 있는데 이것은 캐시에서 알아보자.
특수 리다이렉션에는 304 Not Modified가 있는데 캐시 목적으로 사용된다.
요청한 Resource가 수정되지 않았으므로 캐시를 사용하도록 지시한다.
message body 없이 응답해야한다.
캐시를 알아볼 때 자세히 살펴보자.
클라이언트 측에서 오류가 발생한 것을 의미한다.
재시도 시 실패하며, 클라이언트는 수정 후 데이터를 다시 Request 해야한다.
서버 측에 오류가 발생한 것을 의미한다.
재시도 시 성공할 수도 있다.
Request, Response에 모두 사용되며 HTTP 전송에 필요한 모든 부가정보를 포함한다.
다양한 표준 헤더가 있으며 필요 시에 임의의 헤더를 추가할 수 있다.
헤더 형식은 다음과 같다.
headerName: headerValue
HTTP/1.1의 핵심 요소는 RFC7230에 명세되어 있다.
RFC7230을 확인하면 HTTP 헤더들을 더욱 자세히 확인할 수 있다.
자주 사용되는 몇 가지 헤더들을 살펴보자.
인증이 필요한 페이지에 접근할 때,
인증이 되어있지 않거나 자격이 적합하지 않은 경우 응답 시 관련 Header를 추가할 수 있다.
클라이언트가 선호 표현을 사전에 요청하는 것을 협상이라고 한다.
협상과 관련된 헤더 몇 가지를 살펴보자.
headers와 message body 사이에는 반드시 공백 1줄이 있어야 한다.
실제 전송할 데이터가 포함된다.
HTML, JSON 등이 담겨질 수 있다.
데이터 전송에는 크게 4가지가 있다.
HTTP Message를 사용하기 전에 웹의 계층 구조를 알아보면서
HTTP Message가 통신되는 웹의 생태계에 대해 이해했고
이번에는 본격적으로 HTTP Message 내부 구조에 대해 알아봤다.
이제 HTTP Message를 읽을 때에 철저히 분석해볼 수 있겠다.
HTTP 특징에 대해 이해하고 HTTP Method, HTTP Status Code를 고려하여
실제로 사용하면서 HTTP에 대해 더 심도있게 학습해보자.