HTTP란 HypertText Transfer Protocol의 약자다.
해석하면 하이퍼텍스트 전송 규약이다.
하이퍼텍스트는 링크를 통해 이어지는 비선형 텍스트다.
기존의 책과 같은 문서에서는 1장에서 5장으로 넘어가기 위해서는
2장 ~ 4장을 지나가야 한다. 이를 선형적 텍스트라 한다.
그러나 인터넷 환경에서는 링크를 통해 중간 과정 없이 다닐 수 있다.
이를 비선형 텍스트라 한다.
초기에는 HTML(HypertText Mark up Language)을 주고받기 위해 만들어졌으나,
현재는 이미지, 음성파일, json 등 거의 모든 형태의 데이터를 주고받는다.
HTTP의 특징은 다음과 같다.
http는 클라이언트 서버 구조에서 사용하는 프로토콜이다.
http 메시지는 요청 메시지와, 응답 메시지가 있다.
클라이언트는 요청 메시지를 서버측으로 보내고,
서버는 요청 메시지를 해석하여 응답 메시지를 보낸다.
서버는 과거의 클라이언트의 요청 메시지를 기록하지 않는다.
우리가 일상생활에서 하는 대화는 상태 유지 프로토콜이다.
항상 상대방이 했던 말을 기억하고 있다.
그러나 http를 이용해 메시지를 주고받는 경우, 서버는 이전의 요청을
모른다는 것을 전제로 해야 한다.
http는 메시지를 주고받기 위해 잠깐 연결(Connection)을 유지한 후 해제한다.
이는 메시지를 주고받지 않을 때, 다른 클라이언트의 요청을 처리할 수 있도록 하기 위함이다.
http 메시지는 요청과 응답이 있으며 아래와 같다.
___________________
|method URL version | // 시작 라인
|header field: value| // 헤더
|헤더 정보... |
| | // 공백 라인
|message body | // message body
|___________________|
요청 메시지 구조
method : GET, POST, PUT등 http의 메소드를 나타낸다.
URL : 요청하는 URL을 나타낸다.
version : 사용하는 http 버전을 표기한다.
header field : 메시지에 필요한 부가정보의 이름을 나타낸다.
value : header field에 해당하는 값을 나타낸다.
message body : 요청에 필요한 내용을 담아 보낸다.
_______________________________________
|HTTP-version status-code reason-phrase | // 시작 라인
|header field: value | // 헤더
|헤더 정보... |
| | // 공백 라인
|message body | // message body
|_______________________________________|
응답 메시지 구조
HTTP-version : 사용하는 http 버전을 표기한다.
status-code : 상태코드를 나타낸다.
reason-phrase : 상태메시지를 나타낸다.
나머지는 요청 메시지와 같다.
좋은 HTTP API를 설계하기 위한 원칙은 다음과 같다.
URI로 리소스를 식별하고, 메소드로 행위를 표현한다.
이와 같이 설계하는 이유는 직관적인 표현을 하기 위해서다.
리소스란 서버가 가지고 있는 모든 자원을 의미한다.
이미지 파일, 영상 파일, 데이터베이스 레코드 등이 될 수 있다.
메소드는 http 요청으로 무엇을 할 것인지를 나타낸다.
자주 사용하는 http 메소드는 5가지가 있다.
리소스를 가져온다.
해당 자원을 요청 데이터로 처리한다.
리소스를 대체하거나 생성한다.
리소스를 변경한다.
리소스를 삭제한다.
유저를 생성해라 -> method : POST, URI : /Users
1번 유저의 나이를 변경해라 -> method : PATCH, URI : /Users/1
1번 유저를 삭제해라 -> method : DELETE, URI : /Users/1
1번 유저의 정보를 가져와라 -> method : GET, URI : /Users/1
test.txt 파일에 덮어씌우기 -> method : PUT, URI : /Files/test.txt
URI로 리소스를 식별하기 위해 계층 구조를 활용한다.
Users, Files와 같이 리소스는 복수형으로 표현하고, 뒤에 식별자를 표현한다.
요청시 메소드로 해당 리소스에 무엇을 할지를 표현한다.
하지만 위의 원칙으로 표현할 수 없는 경우를 만날 수 있다.
이때에는 URI 식별자 뒤에 해당 요청을 표현하는 동사를 붙인다.
이를 컨트롤 URI 라고 한다.
http 메소드는 아래와 같은 속성을 가진다.
메소드가 가진 속성을 이해하면,
같은 요청을 계속 해도 되는지? 캐시해도 되는지? 판단할 수 있다.
호출시 리소스를 변경하지 않는 경우이다.
GET 메소드만 안전 속성을 가진다.
나머지 메소드는 호출시 리소스가 변경될 가능성이 있다.
f(f(x)) = f(x)인 경우를 멱등이라고 한다.
여러번 호출해도 같은 결과를 응답받는 경우이다.
GET, PUT, DELETE가 멱등의 속성을 가진다.
POST는 주문 요청시, 중복되어 여러번 주문이 들어가는 경우와,
PATCH는 현재 조회수에서 1을 증가시키는 경우와 같은 반례가 존재한다.
응답 결과를 캐시해서 사용해도 되는지 여부를 나타낸다.
캐시가능한 메소드가 여러개 있지만 실제로는 GET만 응답결과를 캐시해서 사용한다.
HTTP는 응답 메시지에 상태 코드를 포함하여 응답한다.
서버는 상태 코드로 클라이언트에게 처리 결과를 알려줘야 한다.
대표적인 상태코드는 다음과 같다.
요청이 성공적으로 처리되었다는 것을 나타낸다.
300번대 상태코드는 요청을 완료하기 위해 추가 조치가 필요함을 나타낸다.
예를 들어 리소스의 경로가 바뀐경우가 있다.
이 경우에 서버는 300번대 코드와 바뀐 경로를 응답 메시지에 포함하여 클라이언트에게 알려줘야 한다.
300번대 상태 코드의 특징으로는 응답 메시지에 'Location' 헤더가 있다면,
브라우저가 자동으로 'Location'에 포함된 경로로 리다이렉트 한다.
400번대 상태코드는 클라이언트측에서 오류가 있음을 나타낸다.
잘못된 경로를 입력하는 경우가 대표적이다.
500번대 상태코드는 서버에 에러가 발생하여 응답을 할 수 없는 경우를 나타낸다.
데이터베이스 에러, NULL 발생 등이 대표적이다.
컴퓨터 분야에서 캐시 메모리는 빠른 응답을 위해 많이 사용한다.
또 캐시를 사용하면, 불필요한 네트워크 낭비를 줄일 수 있다.
클라이언트는 GET 메소드의 '캐시 가능' 속성을 이용하여 빠른 응답과,
네트워크 낭비 최소화를 가능하게 한다.
서버는 해당 자원을 응답할 때, 캐시의 유효기간, 캐시 사용 가능 여부를 클라이언트 측에 알려줘야 한다.
이를 위해 사용하는 헤더들이 있다.
cache-control
cache-control 헤더는 응답 메시지에 포함되는 헤더로 캐시의 유효기간을 나타낸다.
예를 들어 응답 메시지 헤더에 'cache-control: max-age=60'이면,
캐시가 60초 동안 유효하다는 것을 나타낸다.
Last-Modified, ETag
위의 헤더 또한 응답 메시지에 포함되는 헤더로 캐시의 마지막 상태를 나타낸다.
클라이언트측은 Last-Modified, ETag값을 캐시에 저장하여,
아래에서 캐시가 유효한지를 확인할 때 사용한다.
if-modified-since, if-None-Match
위의 헤더는 클라이언트가 캐시의 유효기간이 지났을 경우,
서버측에 해당 리소스의 변경이 일어났는지 확인할 때 사용한다.
이를 조건부 요청(Conditional GET)이라 한다.
서버측은 해당 리소스의 변화가 없다면 304 Not Modified를 응답하며,
이때 해당 리소스는 포함하지 않는다.
만약 해당 리소스의 변화가 발생하였다면 200 OK와 리소스를 포함하여 응답한다.
참고
모든 개발자를 위한 HTTP 웹 기본 지식 - 김영한 개발자님
컴퓨터 네트워크 - 이화여대 이미정 교수님
Computer Networking: A Top-Down Approach 6th ed. J.F. Kurose and K.W. Ross