2장 간단한 프로토콜 HTTP
HTTP 특징
- 클라이언트 서버 구조
- 무상태 프로토콜(stateless), 비연결성
- HTTP 메시지를 통해 통신
- 단순함, 확장 가능
클라이언트 서버 구조
- 클라이언트와 서버 간의 통신을 한다.
- 클라이언트 - 텍스트와 이미지 등과 같은 리소스를 요구
- 서버 - 리소스를 제공
예전에는 클라이언트와 서버라는 개념이 분리되어 있지 않았다.
하지만 분리 후
서버는 비즈니스 로직과 데이터 관리에 집중한다.
클라이언트에는 UI와 사용성에 집중한다.
⇒ 양쪽이 독립적으로 진화할 수 있다!
ex) 웹, 모바일 등이 만들어져도 서버엔 변화가 적고, 트래픽이 증가해서 서버를 증설해도 클라이언트엔 변화가 적다.
무상태 프로토콜(스테이스리스), 비연결성
- HTTP는 상태를 유지하지 않는 stateless 프로토콜이다.
- 과거의 리퀘스트나 리스폰스 정보를 전혀 가지고 있지 않다.
- 장점: 서버 확장성 높음
- 단점: 클라이언트가 추가 데이터 전송
서버 확장성?
- 중간에 다른 응답 서버로 바뀌어도 된다.
- 트래픽이 증가할 때 서버도 대거 증설할 수 있다.
- → 무상태는 응답 서버를 쉽게 바꿀 수 있다.
Stateless 한계
- 모든 것을 무상태로 설계할 수 없는 경우도 있다.
- 로그인은 상태 유지가 필요
- 쿠키와 서버 세션 등을 사용해 상태를 유지할 수 있음
- 상태 유지는 최소한만 사용
지속 연결
HTTP는 기본이 연결을 유지하지 않는다.
HTTP 초기에는 통신을 한 번 할 때마다 TCP에 의해 연결과 종료를 할 필요가 있었다.
여러 데이터를 주고 받는 경우 리퀘스트 한 번 보낼 때마다 매번 TCP 연결을 종료하면 통신량이 늘어나게 된다.
지금은 HTTP 지속 연결(Persistent Connections) 로 해결
HTTP/1.1와 일부 1.0에서 지속 연결을 사용하기 시작
HTTP/2, HTTP/3에서 더 많은 최적화
지속 연결
- 1회의 TCP 커넥션 연결로 리퀘스트와 리스폰스 교환을 여러 번 한다.
- 지속 연결은 파이프라인화를 가능하게 한다.
- 파이프라인 - 리퀘스트 송신 후에 리스폰스를 기다리지 않고 바로 다음 리퀘스트를 보냄
- 일반적으로 특정 시간까지 연결을 유지한다. (보통 60초)
- 클라이언트가 연결을 끊지 않아도 서버에서 연결을 제거한다.
리퀘스트 URI
HTTP는 URI를 사용하여 인터넷 상의 리소스를 지정한다.
URI를 지정하는 방법에 여러 종류가 있다.
모든 URI를 리퀘스트 URI에 지정
- GET http://hackr.jb/index.htm HTTP/1.1
HOST 헤더 필드에 네트워크 로케이션 포함
GET /index.htm HTTP/1.1
Host: hackr.jp
HTTP 메소드
GET
- URI로 식별된 리소스를 가져올 수 있도록 요구한다.
- 서버에 데이터를 query(쿼리 파라미터, 쿼리 스트링)를 통해서 전달
- 메시지 바디를 사용할 수도 있지만 지원하지 않는 곳이 많아 권장하지 않음
POST
- 요청 데이터 처리
- 엔티티를 전송하기 위해 사용된다.
- 주로 전달된 데이터로 신규 리소스 등록, 프로세스 처리에 사용
- 보통 신규로 리소스를 생성되면 201 created로 응답을 보내고 Location 헤더에 리소스가 생성된 경로를 보내준다.
- 등록된 리소스도 바디에 담아 보낸다.
리소스 생성 외 POST로 할 수 있는 것
- 프로세스 처리
- 주문 -> 결제 완료 -> 배달 시작 -> 배달 완료처럼 단순히 값 변경을 넘어 프로세스 상태가 변경되는 경우
- POST의 결과로 새 리소스가 생성되지 않을 수도 있음
- ex) POST /orders/{orderId}/start-delivery
- URI를 리소스만으로 설계해야하지만 어쩔 수 없는 경우도 있다.
- 위 예처럼 /start-delivery 같은 동사(행위)를 컨트롤 URI라고 함
- 다른 메서드로 처리하기 애매한 경우
- JSON으로 조회 데이터를 넘겨야 하는데, GET 메서드를 사용하기 어려운 경우
- 애매하면 POST
PUT
파일을 전송하기 위해서 사용된다.
리퀘스트 중에 포함된 엔티티를 리퀘스트 URI로 지정한 곳에 보존하도록 요구한다.
단지 HTTP/1.1 PUT 자체에 보안 기능이 없어 일반적인 웹 사이트에선 사용되지 않는다.
인증 기능과 짝을 이루거나 REST와 같이 웹끼리 연계하는 설계 양식을 사용할 때 이용한다.
리소스를 대체할 때 사용한다.
- 리소스가 있으면 대체
- 리소스가 없으면 생성
- 쉽게 얘기해서 덮어버림
중요! 클라이언트가 리소스를 식별
POST 요청과 달리 클라이언트가 리소스 위치를 알고 URI 지정
- PUT /members/100 {"username":"does", "age":25}
- POST /members {"username":"does", "age":25}
100번 리소스에 대해 PUT 요청을 보내면 리소스의 데이터가 완전히 대체된다.
- 먄약 위 데이터에서 "age"를 제외하고 PUT 요청을 보낸다면 원래 데이터에 "age"가 있었어도 사라지고 "username" 데이터만 남음
PATCH
- 리소스 부분 변경
- PUT이랑 달리 일부만 변경하기 때문에 위 예에서 "age"를 빼고 보닌다고 해도 "username"의 변경 부분만 적용되고 "age"의 원래 데이터는 남아 있음
- PATCH가 지원 안되는 서버도 있다. 그럴 땐 POST를 사용하자
DELETE
- 파일을 삭제하기 위해 사용된다.
- PUT과 마찬가지로 인증 기능이 없어 인증 기능이나 REST를 사용하는 경우에 사용되는 경우가 있다.
HTTP 메서드 속성
- 안전하다
- 멱등하다
- 캐시 가능하다
안전 (safe)
- 호출해도 리소스를 변경하지 않는다.
- GET은 안전
멱등 (Idempotent)
- f(f(x)) = f(x)
- 한 번 호출하든 n번 호출하든 결과가 똑같다.
- 멱등 메서드
- GET: 한 번 조회하든, 두 번 조회하든 결과가 같다.
- PUT: 결과를 대체한다. 몇 번 대체하든 최종 결과물은 같다.
- DELETE: 결과를 삭제한다. 여러 번 삭제해도 결과는 같다.
- POST: 멱등이 아니다! 데이터가 중복 저장될 수 있다.
- 활용
- 자동 복구 메커니즘
- 서버가 TIMEOUT 등으로 정상 응답을 못 주었을 때 클라이언트가 중복 요청 보내도 되는가에 대한 판단 근거
Q. 재요청 중간에 다른 곳에서 리소스를 변경해버리면?
- GET → username:A, age:20
- PUT → username:B, age:30
- GET → username:A, age:20
A. 멱등은 외부 요인으로 중간에 리소스가 변경되는 것까지는 고려하지 않음
캐시 가능
- 응답 결과 리소스를 캐시해서 사용해도 되는가?
- GET, HEAD, POST, PATCH 스펙상 캐시 가능
- 실제로는 GET, HEAD 정도만 캐시로 사용
- 캐시를 사용하려면 캐시키를 이용해야 한다.
- GET은 URL만 키로 잡고 구현하면 된다.
- POST, PATCH는 본문 내용까지 캐시 키로 고려해야 하는데 구현이 쉽지 않음
쿠키
- 스테이트리스 프로토콜의 특징은 남겨둔 채 상태를 유지하기 위해 쿠키 시스템 도입
- 쿠키는 서버에서 리스폰스에 Set-Cookie 헤더 필드에 의해 클라이언트에 보존됨
- 다음에 클라이언트가 같은 서버로 리퀘스트를 보낼 때 쿠키를 넣어서 송신
- 서버는 쿠키와 서버 상의 기록을 확인해서 이전 상태를 알 수 있다.
참고
- 그림으로 배우는 HTTP & Network
- 모든 개발자를 위한 HTTP 웹 기본 지식
'네트워크' 카테고리의 다른 글
쿠키, 세션, 토큰 (0) | 2022.06.02 |
---|---|
HTTP 상태 코드 정리 (0) | 2022.05.22 |