REST API DELETE에 Body를 넣어도 될까?
고민의 시작
카카오테크캠퍼스에서 위시리스트 API를 구현하다가 삭제 API URL 설계에서 막혔다.
원래 이렇게 설계했다:
1
DELETE /api/wishlist/{id}
이 {id}가 wishlist의 id인지, product의 id인지 모호하다는 피드백을 받았다. URL만 봐서는 구분하기 어렵다.
멘토님 피드백
“/api/wishlist/1 라는 경로가 있다면, 1은 바로 앞에 위치한 wishlist에 종속된, 관계가 있는 정보라고 이해할 수 있습니다. 그런데 설계해주신 건 wishlist와 관계가 없어보이는(product와 관련이 있는) 정보가 오도록 설계해주셨는데요. URL만 보면 wishlist의 식별자인지, product의 식별자인지 알아채기 어렵지 않을까요?”
URL만 봐도 뭘 삭제하는 건지 알 수 있어야 한다는 거였다.
시도 1: Body에 넣기
그러면 DELETE 요청의 Body에 product id를 넣으면 어떨까?
1
2
DELETE /api/wishlist
Body: { "productId": 1 }
찾아보니 이 방식은 권장하기 어렵다는 의견이 많았다.
문제점
- HTTP 스펙상 DELETE 요청에 Body가 있어도 되긴 하는데, 서버가 무시해도 된다고 명시되어 있다.
- 일부 프록시나 캐시 서버가 DELETE Body를 제거하는 경우가 있다.
- 클라이언트 라이브러리 중에 DELETE에 Body를 못 넣는 것도 있다.
결국 되긴 되지만, 운영 환경에선 변수가 많다는 결론이었다. 표준에서 애매한 영역은 가능하면 피하는 게 안전했다.
시도 2: Query Parameter
1
DELETE /api/wishlist?productId=1
이것도 고려했는데, 의미 전달은 되더라도 리소스 식별이 쿼리로 가는 게 어색하다는 의견이 있었다. 나도 팀에서 코드 리뷰 받는다고 생각하면, 한 번 더 설명이 필요해 보였다.
최종 선택: 명확한 Path Variable
결국 다시 Path Variable로 돌아왔다. 대신 URL 구조를 더 명확하게 바꿨다.
1
DELETE /api/wishlist/products/{productId}
길긴 한데, 위시리스트에서 특정 상품을 삭제한다는 의미가 URL만 봐도 드러난다.
처음에는 URL이 길어진다고 느꼈는데, 멘토님 말씀을 듣고 나니까 짧은 것보다 명확한 게 낫다는 생각이 들었다.
정리: DELETE 요청에 데이터를 넘기는 방법들
| 방법 | 장점 | 단점 |
|---|---|---|
| Body | URL이 짧다 | 프록시에서 제거될 수 있음, 비표준 |
| Query Parameter | 구현이 쉽다 | DELETE에 어울리지 않음 |
| Path Variable | 명확하다 | URL이 길어질 수 있음 |
정리
- DELETE + Body는 가능 여부보다 안전 관점에서 보면 피하는 쪽이 낫다.
- URL은 리소스와 관계를 드러내야 한다. 모호한
{id}하나로 처리하면, 결국 API 문서 의존도가 올라간다. - 길이는 단점이지만, 이 케이스에선 명확성이 더 큰 이득이었다.
프로젝트: 카카오테크캠퍼스 3기 선물하기 API 클론 코딩 관련 링크
- GitHub: Neibce/spring-gift-wishlist