김영한님의 모든 개발자를 위한 HTTP 웹 기본 지식 강의를 듣고 정리한 내용입니다.
https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC
HTTP 메서드
HTTP API를 만들어보자
예시: 회원 정보 관리 API
- 회원 목록 조회
- 회원 조회
- 회원 등록
- 회원 수정
- 회원 삭제
API URI 고민
URI를 설계할 때 가장 중요한 것은 리소스 식별이다.
리소스란? 회원을 등록, 수정, 조회하는 행위가 아니라 회원이라는 개념 자체가 리소스이다.
그렇다면 리소스를 어떻게 식별하는 것이 좋을까? 회원이라는 리소스만 식별하면 되기 때문에 회원 리소스를 URI에 매핑하면 된다.
API URI 설계
위의 회원 정보 관리 API 예시는 아래처럼 URI 설계를 할 수 있다.
- 회원 목록 조회 /members
- 회원 조회 /members/{id}
- 회원 등록 /members/{id}
- 회원 수정 /members/{id}
- 회원 삭제 /members/{id}
참고로 계층 구조 상 상위를 컬렉션으로 보고 복수단어를 사용하기를 권장한다. (member -> members)
하지만 이렇게 리소스로만 설계를 하다보면 같은 리소스에 대해서 조회, 등록, 수정, 삭제를 어떻게 구분할 지 모르게 된다.
-> 이럴 경우 리소스와 행위를 분리해야 한다. 가장 중요한 것은 리소스를 식별하는 것이기 때문이다.
URI는 리소스만 식별하도록 하도, 리소스와 리소스를 대상으로 하는 행위를 분리해야 한다. (리소스는 명사, 행위는 동사라고 생각하면 된다.)
- 리소스: 회원
- 행위: 조회, 등록, 삭제, 변경
HTTP 메서드 - GET, POST
주요 메서드
- GET: 리소스 조회
- POST: 요청 데이터 처리. 주로 등록에 사용
- PUT: 리소스를 대체. 해당 리소스가 없으면 생성
- PATCH: 리소스 부분 변경(회원 이름을 바꾸는 등 특정 필드를 바꿀 때)
- DELETE: 리소스 삭제
기타 메서드
- HEAD: get과 비슷하지만 메시지 부분을 제외하고 상태 줄과 헤더만 반환
- OPTIONS: 대상 리소스에 대한 통신 가능 옵션(메서드)을 설명(주로 CORS에서 사용)
- CONNECT: 대상 자원으로 식별되는 서버에 대한 터널을 설정
- TRACE: 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 진행
(CONNECT와 TRACE는 거의 사용하지 않는다.)
GET
GET 메서드는 리소스를 조회한다.
서버에 전달하고 싶은 데이터는 쿼리(쿼리 파라미터, 쿼리 스트링)를 통해서 전달한다.
메시지 바디를 사용해 데이터를 전달할 수 있지만 지원하지 않는 곳이 많아 권장하지 않는다.
POST
POST 메서드는 요청 데이터를 처리한다.
메시지 바디를 통해 서버로 요청 데이터를 전달하며, 서버는 메시지 바디를 통해 들어온 요청 데이터를 처리한다.
주로 신규 리소스 등록, 프로세스 처리에 사용한다.
보통 신규로 자원을 생성할 경우 서버에서 클라이언트로 보내는 응답 데이터의 상태 코드로 201 Created를 보내고 Location도 함께 보내준다.(Location은 자원이 신규 생성된 경로)
POST 메서드는 주로 3가지 용도로 사용한다.
- 새 리소스 생성(등록)
- 요청 데이터 처리
- 단순히 데이터를 생성, 변경하는 것을 넘어 프로세스를 처리하는 것을 의미
- ex. 주문에서 결제완료 -> 배달 시작 -> 배달 완료와 같이 단순히 값 변경을 넘어 프로세스의 상태가 변경되는 경우
- POST의 결과로 새로운 리소스가 생성되지 않을 수도 있음
- ex. POST orders/{orderId}/start-delivery (이런 URI를 컨트롤 URI라고 한다. 실무에서는 기본적인 리소스로 모든 URI를 설계하기 어렵다. 컨트롤 URI에 보통 POST를 많이 사용한다.)
- 다른 메서드로 처리하기 애매한 경우
- ex. JSON으로 조회 데이터를 넘겨야 하는데 get 메서드를 사용하기 어려운 경우(body를 같이 넘기기 힘들 경우)
- 이런 경우 리소스 조회이지만 POST를 써야 함
- 애매한 상황에서는 대부분 POST를 사용
POST는 모든 작업을 할 수 있지만 기본적으로 조회를 할 경우에는 GET을 쓰는 것이 유리하다. (GET은 캐싱을 하기 때문)
HTTP 메서드 - PUT, PATCH, DELETE
PUT
PUT 메서드는 리소스를 대체한다.
예를 들어 폴더에 파일을 넣는 경우 기존에 해당 파일이 존재하지 않으면 새로 생긴다. 그렇지만 기존에 해당 파일이 존재할 경우 새로운 파일로 기존의 파일을 덮는다. -> PUT도 이런 방식으로 동작한다.
PUT으로 요청을 보낼 때 기존에 없으면 신규로 생성하고, 있으면 기존의 것을 없애고 새로 들어간다. (완전히 대체!)
이 때 중요한 점은 클라이언트가 리소스를 식별한다는 것이다.
POST에서는 요청을 보내면 서버에서 알아서 처리(리소스 위치 모름)하지만, PUT은 클라이언트가 리소스의 위치를 알고 URI를 지정한다는 것이 POST와의 차이점이다.
리소스 완전 대체 예시
기존의 데이터에서 나이만 변경하고 싶은 경우도 있을 것이다. 이럴 때 PUT 요청을 사용해 변경할 정보만 보내게 될 경우에는 기존의 데이터를 완전히 대체하기 때문에 기존의 데이터를 잃을 수 있다.
따라서 이런 의도로 사용하고 싶다면 PATCH를 쓰는 것이 좋다.
PATCH
PATCH 메서드는 리소스를 부분적으로 변경한다.
DELETE
리소스를 제거하는 데 사용한다.
HTTP 메서드의 속성
- 안전(Safe Methods)
- 멱등(Idempotent Methods)
- 캐시 가능(Cacheable Methods)
안전
호출해도 리소스를 변경하지 않는다는 것을 의미한다.
GET은 조회만 하기 때문에 안전하고, POST, DELETE, PUT, PUTCH는 여러 번 호출했을 때 리소스의 변경이 일어나기 때문에 안전하지 않다.
Q. 메서드를 계속 호출해서 서버에 로그가 쌓여 장애가 발생할 경우 안전하지 않은 것이 아닌가?
A. 아니다. 안전은 해당 리소스만 고려하는 것이지 그런 부분까지는 고려하지 않는다.
멱등
한 번 호출하든 여러 번 호출하든 결과가 똑같다는 것을 의미한다.
- GET: 한 번 조회하든, 두 번 조회하든 같은 결과가 조회된다.
- PUT: 결과를 대체. 같은 요청을 여러 번 해도 최종 결과는 같다.
- DELETE: 결과를 삭제. 같은 요청을 여러 번 해도 삭제된 결과는 같다.
POST는 멱등이 아니다. (ex. 두 번 호출하면 같은 결제가 중복해서 발생할 수 있음.)
이런 특성은 자동 복구 메커니즘에서 활용될 수 있다.
만약 DELETE 요청을 보냈는데 서버가 TIMEOUT 등의 이유로 정상 응답을 못주었을 때 DELETE 메서드는 멱등이기 때문에 다시 DELETE를 시도할 수 있다.
Q. 재요청 중간에 다른 곳에서 리소스를 변경해버리면 멱등이 아니지 않은가? (만약 사용자1이 GET 요청을 보낸 후에 사용자2가 PUT으로 해당 리소스를 변경하게 되면 사용자1이 다시 GET을 했을 때 바뀐 데이터가 조회됨)
A. 멱등은 외부 요인으로 중간에 리소스가 변경되는 것까지는 고려하지 않는다.
캐시 가능
웹 브라우저에 큰 이미지를 요청한다고 했을 때 같은 요청을 매번 할 필요는 없다. 이럴 경우 내 로컬 pc에 웹 브라우저가 캐시로 저장을 한다. (물론 중간에 여러 캐시 서버가 존재함)
GET, HEAD, POST, PATCH는 캐시가 가능하다. 하지만 GET, HEAD 정도만 캐시로 사용한다.
그 이유는 POST, PATCH는 본문 내용까지 캐시 키로 고려해야 하는데 구현이 쉽지 않기 때문이다. 반면 GET은 URL만 키로 잡고 캐시를 하면 되서 간단하다.
새로 알게된 점
- POST는 무조건 리소스 생성으로만 생각했는데, 컨트롤 URI로도 쓰고 때때로 GET 요청을 대신할 수도 있다는 것이 신기했다.
- PUT과 PATCH는 많이 써보지 않았는데(특히 PATCH) 둘의 특징과 차이를 알게 되었다.
- 멱등에 대해서 오해를 하고 있었던 것 같다. GET만 멱등이라고 생각했다. 안전을 멱등으로 이해한 것 같다.
- GET이 멱등이라는 것은 알고 있었지만 중간에 외부 요인으로 변경되는 경우에는 어떻게 되는 것인지 궁금했는데, 그 부분은 고려하지 않는다는 것을 알게 되었다.
- GET만 캐시가 가능한 줄 알았는데 POST와 PATCH도 캐시가 가능하다는 것을 알게 되었다!
'TIL' 카테고리의 다른 글
[TIL] 22.12.17 HTTP 헤더 - 일반 헤더(1) (1) | 2022.12.18 |
---|---|
[TIL] 22.12.15 HTTP 메서드 활용, 상태코드 (0) | 2022.12.16 |
[TIL] 22.12.04 HTTP vs HTTPS (0) | 2022.12.04 |
[TIL] 22.11.30 HTTP 기본 (0) | 2022.12.01 |
[TIL] 22.11.26 인터넷 네트워크, URI와 웹 브라우저의 요청 흐름 (0) | 2022.11.26 |