지난 포스팅에서는 주요 HTTP Method
인 GET
POST
PUT
PATCH
DELETE
에 대해서 살펴보았다.
이어서 이번 포스팅에서는 Safe, Idempotent, Cacheable 과 같은 메서드들의 속성에 대해 알아볼 예정이다.
사실 이전 포스팅에서 예고했던 것처럼, 메서드들의 속성과 함께 실제 활용에 대해서도 작성하려고 했지만 생각보다 글이 길어져 실제 활용편은 다음 포스팅에서 작성해야 할 것 같다.
그럼 본격적으로 HTTP Method
들이 가지는 속성에 대해 알아보자.
HTTP Method
는 여러가지 속성들을 가진다.
그 중에서 안전, 멱등, 캐시 가능에 대해 차례대로 알아본다.
📌
HTTP Method
Properties
- 안전 Safe Method
- 멱등 Idempotent
- 캐시 가능 Cacheable
메서드 속성의 첫 번째는 안전이다.
여기서 안전이란, 호출해도 리소스가 변경되지 않는다는 의미이다.
예를 들어, GET
메서드는 단순히 데이터를 조회하는 기능을 수행하기 때문에 리소스를 변경 및 수정하지 않는다. 따라서, GET
은 안전 속성을 만족하는 메서드이다.
반면에, POST
PUT
PATCH
DELETE
와 같은 메서드들은 호출할 경우 데이터에 변경이 발생하거나, 삭제되기 때문에 안전하지 않은 메서드라고 볼 수 있다.
물론, 수많은 GET
요청에 의해 서버에 로그가 쌓이게 되고, 이 로그가 터져 장애가 발생할 우려가 있을 수도 있지만 '안전' 이라는 속성은 해당 리소스의 변경 및 수정 여부에 대해서만 고려하기 때문에 이러한 위험성은 배제된다.
즉, 안전 속성을 만족하는 메서드는 리소스를 변경 및 수정하지 않으므로 데이터의 일관성 유지에 있어 안전하며, 이 메서드가 전체적인 시스템 장애로부터 안전하다는 의미를 가지지는 않는다.
메서드 속성의 두 번째는 멱등이다.
이는 다음과 같은 수식으로도 나타낼 수 있을 것이다.
즉, 멱등이란 한 번을 호출하든 여러 번을 호출하든 그 결과가 같음을 의미한다.
멱등의 개념을 안전과 혼동하기 쉬운데, 안전이 한 번을 호출하든 여러 번을 호출하든 리소스에 변경 및 수정이 발생하지 않는 속성이라면, 멱등은 리소스에 변경 및 수정이 발생한다고 하더라도 메서드를 여러 번 실행한 결과가 한 번 실행한 결과와 같다면 속성을 만족할 수 있다.
앞서 배운 메서드들을 예시로 들어보자.
GET
은 데이터를 조회하는 메서드로 한 번을 조회하든 여러 번을 조회하든 같은 결과가 조회된다. 따라서, 안전과 멱등을 동시에 만족하는 메서드이다.
PUT
은 Body
에 담아 보낸 데이터로 리소스를 완전히 대체하는 메서드이다. 따라서, 여러 번 메서드를 실행한다고 하더라도 항상 새로운 리소스로 대체될 것이기 때문에 멱등 속성을 만족하는 메서드이다.
DELETE
또한 마찬가지다. 이는 리소스를 삭제하는 메서드이기 때문에 여러 번 실행한다고 하더라도 결과는 같다. 리소스가 삭제되어 존재하지 않는 결과는 항상 동일하기 때문이다. DELETE
또한 멱등 속성을 만족한다.
그렇다면, POST
와 PATCH
는 어떨까?
POST
는 멱등을 만족하지 않는다.
만약, POST
가 결제 요청 기능을 수행한다고 가정해본다면, POST
메서드가 여러 번 실행될 경우, 여러 번 결제가 요청될 것이다. 커뮤니티에 게시물을 포스팅하는 기능을 수행할 때는, 같은 게시물이 여러 번 포스팅될 것이다.
즉, 한 번 수행되었을 때와 여러 번 수행되었을 때의 결과가 다르기 때문에 멱등하지 않은 메서드이다.
PATCH
는 멱등하게 설계할 수도 있고, 멱등하지 않도록 설계할 수도 있다.
만약, {name:"Kim"}
이라는 데이터를 Body
에 담아 PATCH
로 요청할 경우, 기존 리소스의 name 컬럼을 단순히 "Kim" 으로 변경하는 기능을 수행하기 때문에 이러한 경우는 멱등하다고 볼 수 있다.
하지만, {"operation" : "add", "age" : 10}
과 같이 요청 시마다 age 컬럼에 10 을 더해주는 식으로 설계하게 될 경우에는 age 컬럼이 누적되어 증가하기 때문에 멱등 속성을 만족하지 않는다.
멱등은 실제로 HTTP Method
를 설계할 때, 굉장히 유용하게 활용될 수 있는 속성이다.
예를 들어, 클라이언트가 서버에게 HTTP Message
를 전송하였는데 TIMEOUT 과 같은 문제들로 인해 정상적인 응답을 전달받지 못했다고 가정해보자.
이러한 경우, 요청에 대한 응답을 정상적으로 받지 못했기 때문에 같은 요청을 다시 전송하도록 설계해도 괜찮을까?
세부적인 설계에 따라 다르겠지만, 일반적으로 GET
이나 PUT
, DELETE
와 같은 메서드들은 여러 번 수행해도 그 결과에 변함이 없기 때문에, 장애 시 같은 요청을 다시 전송하도록 설계해도 문제는 없을 것이다.
하지만 POST
나 멱등하지 않게 설계된 PATCH
와 같은 메서드들은 같은 요청을 다시 전송할 경우 더 큰 문제가 발생할 수 있기 때문에 다른 조치를 취할 수 있도록 설계하는 것이 적절할 것이다.
이렇게, 자동 복구 매커니즘의 사용 가능 여부에 있어서 판단의 근거가 되는 가장 중요한 속성은 각 메서드의 멱등성이 된다.
GET
과 PUT
, DELETE
가 멱등성을 만족하기 때문에 어떤 상황에서도 여러 번 요청할 경우 항상 같은 결과물을 내놓아야 한다는 생각은 금물이다.
다음과 같은 상황을 생각해보자.
GET
을 통해 /members/100 리소스를 조회하는 요청을 전송PUT
을 통해 /members/100 리소스를 변경GET
을 통해 /members/100 리소스를 조회하는 요청을 재전송A 가 /members/100 리소스 조회에 대해 재요청을 전송하기 직전, B 가 해당 리소스를 변경한 경우이다. 이 때는 A 가 GET
메서드를 사용하였는데도 불구하고, 중간에 다른 사용자의 개입으로 인해 응답받는 결과값이 달라지게 된다.
이렇게, 예외적으로 멱등성이 깨지는 케이스가 충분히 발생할 수 있다.
하지만, 멱등 속성의 여부는 외부 요인으로 인해 중간에 리소스가 변경되는 것은 고려하지 않기 때문에 결과적으로 GET
은 멱등성을 만족하는 메서드가 된다.
단지 모든 상황에서의 멱등성을 절대적으로 보장하는 것은 아니라는 점만 알아두자.
마지막으로 살펴볼 메서드 속성은 캐시 가능 이다.
캐시 가능은 응답 결과 리소스를 캐시해서 사용할 수 있는가 에 대한 여부이다.
캐시는 임시 저장소와 같은 개념으로 생각하면 되는데, 클라이언트가 서버에 한 번 요청했던 데이터에 대해 매 요청마다 다시 전송할 필요가 없도록 웹브라우저가 임시적으로 데이터를 보관하고 있는 장소이다. 따라서 웹브라우저가 리소스를 보관할 수 있는지 여부에 따라 캐시 가능 속성으로 메서드를 구분할 수 있다.
바로 본론으로 들어가보자면, GET
POST
PATCH
는 스펙 상으로 캐시가 가능하다. 또한, 이외에 살펴보지 않았던 메서드인 HEAD
도 웹브라우저에서 캐시가 가능한 메서드 중 하나이다.
하지만 실무에서는 구현의 복잡성 때문에 GET
과 HEAD
정도만 캐시로 사용하게 되고 POST
와 PATCH
는 지원되지 않는 경우가 일반적이라고 한다. 캐시를 사용하기 위해서는 원본 데이터가 변경되지 않고 유지되어야 하는데, POST
PUT
DELETE
PATCH
와 같은 메서드로 데이터가 변경되게 되면 원본 데이터 또한 변경되기 때문에 캐시를 유지하는 것이 어렵기 때문이다.
따라서, GET
HEAD
메서드는 캐시가 가능하기 때문에 웹브라우저에서 리소스를 임시로 보관할 수 있고, 나머지 메서드들은 아예 캐시가 지원되지 않거나 구현의 복잡성 혹은 유지의 어려움 때문에 사용하지 않는다고 생각해두면 될 것 같다.
지금까지, HTTP Method
들이 가지는 속성들에 대해 살펴보았다.
아래는 각 메서드 별 속성에 대해 정리해놓은 테이블이다.
[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol]
다음 포스팅에서는 지금까지 살펴본 다양한 HTTP Method
들이 실제로 어떻게 활용될 수 있는지 정리해볼 예정이다.