REST를 사용하여 여러 레코드 삭제


97

여러 항목을 삭제하는 REST-ful 방법은 무엇입니까?

내 사용 사례는 한 번에 여러 항목을 삭제할 수 있어야하는 백본 컬렉션이 있다는 것입니다. 옵션은 다음과 같습니다.

  1. 모든 단일 레코드에 대해 DELETE 요청을 보냅니다 (잠재적으로 수십 개의 항목이있는 경우 나쁜 생각처럼 보입니다).
  2. 삭제할 ID가 URL에서 함께 묶인 DELETE를 보냅니다 (예 : "/ records / 1; 2; 3").
  3. 비 REST 방식으로 삭제 표시된 ID가 포함 된 사용자 지정 JSON 개체를 보냅니다.

모든 옵션이 이상적이지 않습니다.

이것은 REST 규칙의 회색 영역처럼 보입니다.


답변:


92
  1. 실행 가능한 RESTful 선택이지만 분명히 설명한 제한 사항이 있습니다.
  2. 이러지마 중개인은 "(단일) 리소스를에서 삭제"를 의미하는 것으로 해석합니다. /records/1;2;3따라서 이에 대한 2xx 응답으로 인해 캐시를 제거 할 수 있습니다 /records/1;2;3. 하지 제거 /records/1, /records/2또는 /records/3; 에 대한 410 응답을 프록시 /records/1;2;3하거나 귀하의 관점에서 이해할 수없는 기타 사항을 프록시 하십시오.
  3. 이 선택은 최선이며 RESTfully으로 수행 할 수 있습니다. API를 만들고 리소스에 대한 대량 변경을 허용하려는 경우 REST를 사용하여 수행 할 수 있지만 정확히 어떻게 많은 사람들에게 즉시 명확하지 않습니다. 한 가지 방법은 '변경 요청'리소스생성 (예 : records=[1,2,3]to 와 같은 본문을 POSTing /delete-requests)하고 생성 된 리소스 ( Location응답 헤더로 지정)를 폴링 하여 요청이 수락되었는지, 거부되었는지, 진행 중인지 확인하는 것입니다. 또는 완료되었습니다. 이것은 장기 실행 작업에 유용합니다. 또 다른 방법은 목록 리소스에 요청보내는PATCH 것입니다 ./records, 본문에는 리소스 목록과 해당 리소스에 대해 수행 할 작업이 포함됩니다 (지원하려는 형식에 관계없이). 이는 요청에 대한 응답 코드가 작업 결과를 나타낼 수있는 빠른 작업에 유용합니다.

REST의 제약 내에서 모든 것을 달성 할 수 있으며 일반적으로 "문제"를 리소스로 만들고 URL을 제공하는 것이 답입니다.
따라서 여기에서 삭제하거나 목록에 여러 항목을 게시하거나 리소스를 동일하게 편집하는 등의 일괄 작업은 모두 "일괄 작업"목록을 만들고 여기에 새 작업을 게시하여 처리 할 수 ​​있습니다.

잊지 마세요. REST가 문제를 해결하는 유일한 방법은 아닙니다. "REST는"단지 건축 양식이고 당신은하지 않습니다 그것을 준수하는 (하지만 그렇게하지 않으면 당신은 인터넷의 특정 혜택을 상실). 이 HTTP API 아키텍처 목록을 살펴보고 자신에게 적합한 아키텍처 를 선택하는 것이 좋습니다. 다른 아키텍처를 선택하면 잃어버린 부분을 인식하고 사용 사례에 따라 정보에 입각 한 결정을 내리십시오.

REST 웹 서비스에서 일괄 작업을 처리하기위한 패턴에 대한 이 질문에 대한 잘못된 답변이 있습니까? 너무 많은 찬성표를 가지고 있지만 읽어야합니다.


2
걱정해야 할 것은 서버가 아니라 중개자, CDN, 캐싱 프록시 등입니다. 인터넷은 계층화 된 시스템입니다. 그것이 그렇게 잘 작동 하는 이유 입니다. Roy는 성공을 위해 시스템의 어떤 측면이 필요한지 결정하고이를 REST라고 명명했습니다. DELETE요청 을 발행 하면 요청자와 서버 사이에있는 모든 것이 지정된 URL에서 단일 리소스가 삭제되고 있다고 생각합니다. 쿼리 문자열은 이러한 장치에 대한 URL의 불투명 한 부분이므로 API를 지정하는 방법은 중요하지 않으며이 지식에 대한 권한이 없으므로 다르게 동작 할 수 없습니다.
Nicholas Shanks 2014

3
/ records / 1; 2; 3은 URI 길이 제한으로 인해 삭제할 리소스가 많은 경우 작동하지 않습니다
dukethrash

3
삭제할 리소스를 정의하는 DELETE 및 본문을 고려하는 경우 일부 중개자가 본문을 전달하지 않을 수 있습니다. 또한 일부 HTTP 클라이언트는 DELETE에 본문을 추가 할 수 없습니다. 참조 stackoverflow.com/questions/299628/...
누가 복음 Puplett

3
@LukePuplett 나는 단순히 요청과 함께 요청 본문을 전달하는 DELETE것은 금지되어 있다고 말할 것 입니다. 하지마. 당신이 그렇게한다면 나는 당신의 아이들을 먹을 것입니다. Nom nom nom.
Nicholas Shanks 2016

3
# 3에 대한 인수의 문제점은 # 2에 대한 반대 인수와 동일한 패널티를 갖는다는 것입니다. 삭제할 리소스를 만드는 것은 업스트림 프록시가 처리 방법을 알 수있는 것이 아닙니다. 접근 방식 # 2에 대해 제기되는 동일한 카운터 인수입니다.
LB2

16

GET /records?filteringCriteria기준과 일치하는 모든 레코드의 배열을 반환 하면 해당 레코드를 모두 DELETE /records?filteringCriteria삭제할 수 있습니다.

이 경우 귀하의 질문에 대한 답변은입니다 DELETE /records?id=1&id=2&id=3.


1
저는 또한이 결론에 도달했습니다. 동사를 원하는대로 바꾸면됩니다. GET이 어떻게 DELETE로 이동하지 않는지 이해하지 못합니다.
Luke Puplett 2015

9
GET /records?id=1&id=2&id=3"ID가 1, 2, 3 인 레코드 3 개 가져 오기" 가 아니라 "URL 경로가 / records? id = 1 & id = 2 & id = 3 인 단일 리소스 가져 오기"를 의미합니다. 이는 순무 그림, 일반 텍스트 일 ​​수 있습니다. 중국어로 숫자 "42"가 포함 된 문서 또는 존재하지 않을 수 있습니다.
Nicholas Shanks 2015

다음을 고려하십시오. /records?id=1/records?id=2에 대한 두 개의 순차적 요청 이 전송되고 해당 응답이 일부 중개자 (예 : 브라우저 또는 ISP)에 의해 캐시됩니다. 인터넷이 애플리케이션이 의미하는 바를 알고 있다면 /records?id=1&id=2원본 서버에 묻지 않고 이미 가지고있는 두 결과를 병합 (어떻게 든)하여 캐시 에서 요청을 반환 할 수 있다는 이유를 알 수 있습니다. 그러나 이것은 불가능합니다. /records?id=1&id=2유효하지 않거나 (요청 당 하나의 ID 만 허용됨) 완전히 다른 것을 반환 할 수 있습니다 (순무).
Nicholas Shanks 2015

이것은 기본적인 리소스 캐싱 문제입니다. 내 DBA가 상태를 직접 변경하면 캐시가 동기화되지 않습니다. 중개자가 반환 한 예제 410을 제공하지만 410은 영구 제거 용입니다. DELETE시 캐시는 해당 URL에 대한 슬롯을 지울 수 있지만 DBA가 있는지 알지 못하기 때문에 410 또는 404를 보내지 않습니다. 자원을 즉시 원래 위치로 되 돌리지 않았습니다.
Luke Puplett 2016

4
@NicholasShanks 정말 동의하지 않습니다. 결과가 캐시되면 서버의 결함입니다. API 디자인에 대해 이야기하고 있다면 서버용 코드를 작성하는 사람이되기를 바랍니다. 값 배열을 나타 내기 위해 쿼리 문자열을 사용 id[]=1&id[]=2하거나 id=1&id=2쿼리 문자열에서 해당 쿼리 문자열을 사용하는지 여부에 관계없이 해당 쿼리 문자열은이를 나타냅니다. 그리고 쿼리 문자열이 필터를 나타내는 것이 매우 일반적이고 좋은 습관이라고 생각합니다. 또한 삭제 및 업데이트를 허용하는 경우 GET요청을 캐시하지 마십시오 . 그렇게하면 클라이언트가 부실 상태를 유지합니다.
Joseph Nields

8

Mozilla Storage Service SyncStorage API v1.5는 REST를 사용하여 여러 레코드를 삭제하는 좋은 방법이라고 생각합니다.

전체 컬렉션을 삭제합니다.

DELETE https://<endpoint-url>/storage/<collection>

단일 요청으로 컬렉션에서 여러 BSO를 삭제합니다.

DELETE https://<endpoint-url>/storage/<collection>?ids=<ids>

ids : 제공된 쉼표로 구분 된 목록에있는 ID를 가진 컬렉션에서 BSO를 삭제합니다. 최대 100 개의 ID를 제공 할 수 있습니다.

지정된 위치에서 BSO를 삭제합니다.

DELETE https://<endpoint-url>/storage/<collection>/<id>

http://moz-services-docs.readthedocs.io/en/latest/storage/apis-1.5.html#api-instructions


이것은 좋은 해결책 인 것 같습니다 . 나는 모질라가 그것이 옳다고 생각한다면 그것은 틀림 없습니까? 유일한 질문은 오류 처리입니다. 그들이? ids = 1,2,3을 전달하고 id 3이 존재하지 않는다고 가정합니다. 1과 2를 삭제 한 다음 요청자가 3을 원하고 거기에 없기 때문에 200으로 응답합니까? 또는 1이 아닌 2 삭제할 수있는 권한이있는 경우 ... 오류가 당신에게 삭제 아무것도 응답을하거나 무엇을 당신은 당신과 다른 사람을 떠날 수있는 삭제 ...
tempcke

일반적으로 종료 상태가 동일하기 때문에 성공적인 응답을 반환합니다. 이렇게하면 더 이상 오류 상태를 처리 할 필요가 없기 때문에 클라이언트의 논리도 단순화됩니다. 승인 사례의 경우 전체 요청이 실패하지만 실제로는 사용 사례에 따라 다릅니다.
Nathan Phetteplace

3

이것은 REST 규칙의 회색 영역처럼 보입니다.

예, 지금까지 일괄 작업 (예 : 일괄 삭제)을 언급하는 REST API 디자인 가이드 인 google api 디자인 가이드를 건너 뛰었습니다 .

이 가이드 에서는 콜론 (예 :)을 사용하여 리소스를 통해 연결할 수있는 "사용자 지정"메서드 생성에 대해 언급 합니다. https://service.name/v1/some/resource/name:customVerb또한 배치 작업을 사용 사례로 명시 적으로 언급합니다.

사용자 지정 메서드는 리소스, 컬렉션 또는 서비스와 연결될 수 있습니다. 임의의 요청을 받아 임의의 응답을 반환 할 수 있으며 스트리밍 요청 및 응답도 지원합니다. [...] 사용자 지정 메서드는 가장 유연한 의미를 가지고 있기 때문에 HTTP POST 동사를 사용해야합니다. [...] 성능이 중요한 메서드의 경우 사용자 지정 배치 메서드를 제공하여 요청 당 오버 헤드를 줄이는 것이 유용 할 수 있습니다 .

따라서 Google의 API 가이드에 따라 다음을 수행 할 수 있습니다.

POST /api/path/to/your/collection:batchDelete

... 컬렉션 리소스의 여러 항목을 삭제합니다.


항목 목록이 JSON 형식 배열을 통해 전달되는 실행 가능한 솔루션입니까?
Daniele

물론이지. json 배열을 통해 ID가 전송되는 페이로드를 게시 할 수 있습니다.
B12Toaster

Google API 가이드 If the HTTP verb used for the custom method does not accept an HTTP request body (GET, DELETE), the HTTP configuration of such method must not use the body clause at all,가 Custom Method 장에서 언급 한 것이 흥미 롭습니다 . 그러나 GET accounts.locations.batchGetAPI는 본문이있는 GET 메소드입니다. 이상합니다. developers.google.com/my-business/reference/rest/v4/...
鄭元傑

@ 鄭元傑 동의, 첫눈에 약간 이상해 보이지만 자세히 살펴보면 실제로 사용되는 POSThttp 메소드이며 사용자 정의 메소드 만 명명 batchGet됩니다. 나는 Google이 (a) 모든 사용자 정의 방법이 있어야한다는 규칙을 고수하고 POST(내 대답 참조) (b) 사람들이 본문에 "필터"를 더 쉽게 넣을 수 있도록하기 위해 그렇게한다고 생각합니다. 쿼리 문자열과 마찬가지로 필터를 이스케이프하거나 인코딩합니다. 단점은 물론,이 ... 더 이상 정말 캐시되지 않는 것입니다
B12Toaster

https://service.name/v1/some/resource/name:customVerb정의상 RESTful이 아닙니다.
데몬

2

나는 컬렉션의 도매 교체를 허용했습니다. 예를 들어 PUT ~/people/123/shoes본문이 전체 컬렉션 표현 인 경우.

이는 클라이언트가 항목을 검토하고 일부를 정리하고 일부를 추가 한 다음 서버를 업데이트하려는 작은 하위 항목 컬렉션에 대해 작동합니다. 그들은 모두 삭제하기 위해 빈 컬렉션을 넣을 수 있습니다.

이것은 GET ~/people/123/shoes/9PUT가 그것을 삭제하더라도 여전히 캐시에 남아 있음을 의미 하지만 이는 단지 캐싱 문제이며 다른 사람이 신발을 삭제하면 문제가 될 것입니다.

내 데이터 / 시스템 API는 항상 만료 시간이 아닌 ETag를 사용하므로 서버는 각 요청에 맞고 데이터를 변경하려면 올바른 버전 / 동시성 헤더가 필요합니다. 읽기 전용이고보기 / 보고서가 정렬 된 API의 경우 만료 시간을 사용하여 오리진의 조회수를 줄입니다. 예를 들어 리더 보드는 10 분 동안 유용 할 수 있습니다.

같은 훨씬 더 큰 컬렉션의 ~/people경우 여러 삭제가 필요하지 않으며 유스 케이스가 자연스럽게 발생하지 않는 경향이 있으므로 단일 DELETE가 잘 작동합니다.

미래에는 REST API를 구축하고 감사와 같은 동일한 문제와 요구 사항을 충족 한 경험을 통해 GET 및 POST 동사와 이벤트에 대한 디자인 만 사용하는 경향이 있습니다 (예 : POST 주소 변경 이벤트). 자체 문제 세트가 함께 제공됩니다. :)

또한 엄격한 "Fielding zealot"REST API 설계를 싫어하는 실질적이고 유효한 클라이언트 측 이유가 있고 생산성 및 생산성을 위해 프런트 엔드 개발자가 더 엄격한 백엔드 API를 사용하는 자체 API를 구축 할 수 있도록 허용합니다. 캐시 계층화 이유.


나는 마지막 문장을 읽을 때 까지이 대답을 좋아했습니다. :) 엄격한 REST를 적용하는 것이 순 해로운 영향을 미치는 사용 사례를 본 적이 없습니다. 물론 양쪽 끝에서 더 많은 코드를 작성할 수 있지만 더 안전하고 깔끔하며 덜 결합 된 시스템으로 끝납니다.
니콜라스 정강이

ㅋ. 실제로 패턴이됩니다! 프런트 엔드 용 백엔드는 ThoughtWorks 기술 레이더에서 호출됩니다. 또한 JavaScript와 같이 번거로운 애플리케이션 로직을 작성할 수 있으며 iOS 앱의 경우 클라이언트없이 업데이트 할 수 있습니다.
누가 복음 Puplett

Google의 처음 4 개 히트 곡을 훑어 보면이 BFF 기술은 클라이언트가 귀하의 통제하에 있을 때만 작동하는 것 같습니다 . 클라이언트 개발자는 원하는 API를 개발하여 실제 백엔드 인 마이크로 서비스 API에 호출을 매핑합니다. 이 다이어그램에서 : samnewman.io/patterns/architectural/bff/#bff BFF 상자 아래에 "Perimeter"줄을 배치합니다. 각 상자는 단순히 클라이언트의 일부입니다. 마이크로 서비스가있는 데이터 센터 외부에있을 수도 있습니다. 또한 REST가 두 인터페이스 (클라이언트 / BFF 및 BFF / 마이크로 서비스)에 어떻게 적용되지 않는지도 알 수 없습니다.
Nicholas Shanks

1
네, 좋은 지적입니다. 예를 들어 마이크로 서비스를 구축하는 팀과 앵귤러 앱을 만드는 팀이 있고, 그 개발 팀이 작은 순수 서비스에 대해 작업하는 것을 좋아하지 않는 더 많은 프런트 엔드 유형일 때 사용됩니다. 마이크로 서비스를 추상화하고 고객을 위해 더 유용한 파사드로 집계하기 위해 동일한 패턴을 사용할 수없는 이유는 없지만 파사드에 영향을주지 않고 마이크로 서비스를 변경할 수 있습니다.
Luke Puplett 2017 년

API 엔드 포인트는 도메인과 비즈니스의 요구를 모델링해야합니다. 이러한 문제를 해결하고 과도한 엔지니어링을 피하여 엄격하고 많은 시간의 유연하지 않은 사양을 준수하는 코드입니다. REST는 어쨌든 지침에 불과합니다.
Victorio Berra 2018
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.