사전 DELETE
인터페이스

DELETE

gabury1고친 사람 github-actions[bot]

DELETE 는 웹 서버에 주소 하나를 대며 그 주소에 있는 것을 지워 달라고 요청하는 방법입니다. 게시글 42번을 지우려면 /posts/42 에 DELETE 를 보냅니다. 같은 요청을 여러 번 보내도 서버에 남는 결과는 한 번 보낸 것과 같습니다. 데이터베이스에도 같은 이름의 명령이 있지만 이 문서는 웹 요청 쪽을 다룹니다.

쉽고 빠른 이해

DELETE 는 주소가 가리키는 것을 지워 달라는 요청입니다. 게시글 42번을 지우려면 /posts/42 주소에 DELETE 를 보냅니다.

지우기 전용 요청이 따로 있어야 서버와 중간 장비가 요청의 뜻을 알아봅니다. 중간 장비의 하나인 캐시는 응답을 저장해 두었다가 다시 내주는 장치입니다. 캐시는 DELETE 가 지나가면 그 주소에 저장해 둔 응답(저장본)을 버립니다.

어떻게 도나:

  1. 클라이언트가 지울 대상의 주소로 DELETE 를 보냅니다
  2. 서버가 권한을 확인하고 대상을 지웁니다
  3. 다 지웠으면 성공 코드로, 나중에 지울 예정이면 접수했다는 코드로 답합니다

대가도 있습니다. 한 번 지운 것은 요청으로 되돌릴 방법이 없습니다. 이미 지워진 것을 또 지우라고 하면 서버마다 답하는 코드가 달라 클라이언트가 두 경우를 모두 처리해야 합니다.

언제 쓰나: 사용자가 뜻을 갖고 누른 삭제 동작에 씁니다. 여러 개를 한꺼번에 지우려고 요청 본문에 목록을 싣는 데는 쓰지 않습니다.

상세

DELETE 는 HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜)의 요청 메서드 가운데 하나입니다. 요청 메서드는 요청이 서버에게 무엇을 해 달라는 것인지 알리는 낱말입니다. DELETE 는 요청 대상을 서버에서 없애 달라는 뜻입니다.

요청 대상은 URI(Uniform Resource Identifier, 통합 자원 식별자)로 가리킵니다. URI 는 서버 안의 무언가를 가리키는 주소입니다. 이 주소가 가리키는 대상을 자원이라고 부릅니다. 게시글 한 편, 사용자 한 명, 파일 하나가 각각 자원입니다.

DELETE 가 없다면 삭제를 다른 메서드에 섞어 보내야 합니다. 예를 들어 POST 요청 본문에 「지워라」라고 적는 식입니다. 그러면 서버 코드는 본문을 열어 봐야 요청의 뜻을 압니다.

클라이언트와 서버 사이에는 중간 장비가 끼기도 합니다. 프록시는 클라이언트의 요청을 대신 서버에 전달하는 서버입니다. 캐시는 응답을 저장해 두었다가 같은 요청에 다시 내주는 장치입니다. 이런 중간 장비는 본문을 해석하지 않으므로 그 요청이 무언가를 지웠다는 사실을 모릅니다.

요청과 응답의 모양

가장 짧은 DELETE 요청은 메서드와 주소만 있습니다. 지울 대상은 주소가 이미 말하므로 본문이 필요 없습니다.

http
DELETE /posts/42 HTTP/1.1
Host: example.com

서버가 게시글을 지우고 돌려줄 것이 없으면 이렇게 답합니다. 상태 줄 하나로 끝나는 응답입니다.

http
HTTP/1.1 204 No Content

첫 줄의 DELETE 가 메서드, /posts/42 가 요청 대상입니다. 응답의 204 는 상태 코드입니다. 상태 코드는 요청이 어떻게 끝났는지를 세 자리 숫자로 알리는 값입니다.

성공을 알리는 상태 코드

삭제가 성공했을 때 서버가 고르는 코드는 셋입니다. 셋은 「지금 끝났나」와 「돌려줄 본문이 있나」로 갈립니다.

코드 뜻 본문
204 No Content 지웠습니다 없음
200 OK 지웠습니다 결과를 설명하는 본문
202 Accepted 접수했고 나중에 지웁니다 없어도 됨

202 는 큰 파일이나 딸린 데이터가 많은 계정처럼 삭제에 시간이 걸릴 때 씁니다. 서버는 일단 요청만 받아 둡니다. 지우는 일은 뒤에서 천천히 합니다. 클라이언트는 이 응답만으로는 삭제가 끝났는지 알 수 없습니다.

실패하면 흔한 코드는 다음과 같습니다. 대상이 없으면 404 Not Found 입니다. 그 자원에 삭제를 허용하지 않으면 405 Method Not Allowed 입니다. 지울 권한이 없으면 403 Forbidden 입니다.

멱등성과 안전성

DELETE 는 멱등합니다. 멱등하다는 것은 같은 요청을 여러 번 보내도 서버에 남는 효과가 한 번 보낸 것과 같다는 뜻입니다. 게시글 42번을 한 번 지우든 세 번 지우든 결과는 「42번이 없다」입니다.

이 성질 덕분에 재시도가 안전해집니다. 요청을 보낸 뒤 응답이 오기 전에 연결이 끊기면 클라이언트는 삭제가 됐는지 모릅니다. DELETE 는 그냥 한 번 더 보내면 됩니다. 이미 지워졌어도 더 나빠질 것이 없습니다.

멱등성은 서버의 상태를 두고 하는 말이지 응답을 두고 하는 말이 아닙니다. 첫 요청은 204 를, 두 번째 요청은 404 를 받을 수 있습니다. 응답 코드는 달라도 서버에 남은 상태는 같으므로 멱등성은 지켜집니다.

반면 DELETE 는 안전한 메서드가 아닙니다. 안전한 메서드는 서버의 상태를 바꾸지 않는 메서드입니다. GET 이 대표입니다.

이 구분은 사람 대신 요청을 보내는 도구 때문에 중요합니다. 검색 엔진의 크롤러나 브라우저의 미리 읽기 기능은 사용자가 누르지 않아도 요청을 스스로 보냅니다. 이런 도구가 DELETE 를 보내면 사용자 모르게 데이터가 지워집니다. 그래서 DELETE 는 사용자가 뜻을 갖고 누른 동작에서만 나가야 합니다.

이미 없는 대상을 지울 때

두 번째 DELETE 에 무엇으로 답할지는 서버가 정합니다. 흔한 선택은 둘입니다.

선택 두 번째 요청의 응답 클라이언트가 얻는 것
없다고 알린다 404 대상이 이미 없다는 것을 알 수 있다
성공으로 친다 204 재시도할 때 오류 처리가 필요 없다

어느 쪽을 골라도 멱등성은 깨지지 않습니다. 다만 API(Application Programming Interface, 애플리케이션 프로그래밍 인터페이스) 문서에 어느 쪽인지 적어 두어야 클라이언트가 404 를 오류로 볼지 성공으로 볼지 정할 수 있습니다.

요청 본문

DELETE 요청에 본문을 실어도 그 본문의 뜻은 정해져 있지 않습니다. 어떤 서버는 본문을 무시합니다. 어떤 프록시나 라이브러리는 본문이 붙은 DELETE 를 거절합니다.

그래서 지울 대상은 주소에 담는 것이 원칙입니다. 여러 개를 한꺼번에 지우고 싶어도 본문에 목록을 싣기보다 다른 방법을 찾습니다. 흔한 방법 하나는 목록을 쿼리 문자열에 담는 것입니다.

http
DELETE /posts?ids=1,2,3 HTTP/1.1

위 요청은 지울 번호 셋을 쿼리 문자열의 ids 에 담았습니다. 이 모양을 받아들일지는 서버가 정합니다.

캐시와 무효화

캐시가 /posts/42 의 GET 응답을 들고 있다고 합시다. 그 게시글이 지워지면 문제가 생깁니다. 다음 GET 에 이미 없는 게시글을 내주게 됩니다.

그래서 성공한 DELETE 응답이 캐시를 지나가면 캐시는 그 주소에 저장해 둔 응답(저장본)을 버립니다. 이 동작을 무효화라고 부릅니다. 그리고 DELETE 응답 자체는 캐시에 저장하지 않습니다.

sequenceDiagram
    participant 클라이언트
    participant 캐시
    participant 서버
    클라이언트->>캐시: DELETE /posts/42
    캐시->>서버: DELETE /posts/42
    서버-->>캐시: 204
    Note over 캐시: /posts/42 로 저장한 응답을 버린다
    캐시-->>클라이언트: 204
    클라이언트->>캐시: GET /posts/42
    캐시->>서버: 저장본이 없어 서버에 묻는다
    서버-->>캐시: 404

그림은 DELETE 한 번이 지나간 뒤의 GET 을 보입니다. 삭제 응답이 캐시를 지나가면서 저장본이 사라집니다. 그래서 뒤이은 GET 은 캐시에서 끝나지 않고 서버까지 가서 404 를 받습니다.

무효화는 요청이 그 캐시를 지나갈 때만 일어납니다. 다른 경로로 삭제가 서버에 닿으면 이 캐시는 모릅니다. 저장본에는 캐시가 다시 내줘도 되는 기간이 붙어 있습니다. 이 유효 기간이 끝날 때까지 저장본이 남습니다.

주소에서 사라지는 것과 저장소에서 지우는 것

DELETE 가 약속하는 것은 「이 주소로는 더 이상 그 자원이 안 나온다」입니다. 저장소에서 데이터를 실제로 없애라는 약속은 아닙니다.

서버는 DELETE 를 받고 데이터에 「지워짐」 표시만 붙일 수 있습니다. 이런 방식을 소프트 삭제라고 부릅니다. 실수로 지운 것을 되살리거나 누가 무엇을 지웠는지 나중에 확인하려고 씁니다. 반대로 데이터를 저장소에서 실제로 없애는 것은 하드 삭제라고 부릅니다.

어느 쪽이든 클라이언트에게는 같게 보입니다. 지운 뒤 같은 주소로 GET 을 보내면 404 나 410 Gone 을 받습니다. 404 는 그 주소에 아무것도 없다는 뜻입니다. 410 은 예전에 있었지만 일부러 치웠다는 뜻입니다.

데이터베이스의 DELETE 와 가르기

SQL(Structured Query Language, 구조화 질의 언어)에도 DELETE 문이 있습니다. 이쪽은 데이터베이스 테이블에서 조건에 맞는 행을 지우는 문장입니다. 이름은 같지만 서로 다른 규칙을 따릅니다.

HTTP 의 DELETE 는 서버에게 보내는 요청입니다. 어떻게 지울지는 서버가 정합니다. 서버 코드가 이 요청을 받아 내부에서 SQL DELETE 를 실행하는 경우가 많습니다. 소프트 삭제를 쓰는 서버라면 SQL UPDATE 로 표시만 바꿉니다.

관련 항목

DELETE 와 나란히 서는 요청 메서드

요청 메서드 · GET · HEAD · POST · PUT · PATCH · OPTIONS · CONNECT · TRACE

DELETE 가 지키는 성질

멱등성 · 안전한 메서드 · 안전하지 않은 메서드 · 재시도 · 멱등 키

DELETE 응답에 오는 상태 코드

상태 코드 · 200 OK · 202 Accepted · 204 No Content · 403 Forbidden · 404 Not Found · 405 Method Not Allowed · 410 Gone

DELETE 가 지우는 대상과 그 주소

자원 · URI · 요청 대상 · 쿼리 문자열 · REST · API 설계

DELETE 뒤에 캐시가 거치는 처리 단계

캐시 · HTTP 캐싱 · 무효화 · 프록시 · RFC 9111

DELETE 를 정의하는 표준·문서

HTTP · RFC 9110 · HTTP/1.1 · OpenAPI

서버 안에서 삭제를 구현하는 방식

소프트 삭제 · 하드 삭제 · SQL · DELETE (SQL) · UPDATE · 감사 로그

다른 이름: DELETE 메서드 · HTTP DELETE