WEB

07. DELETE 작업에 상태 코드 200번? 아니면 204번?

멈재 2023. 1. 28. 00:53
728x90

최근 로버트 C. 마틴 저자의 클린 코드도 읽고 잘 읽히는 코드에 대해 고민을 하다 보니 여러 사람들의 코드를 보는 일이 많아졌다.

그러다 우연히 코드숨이라는 곳을 보게 되었고, 그 안에 어떤 분의 리뷰 내용으로 다음과 같은 내용이 있었다.

"왜 데이터가 없을 때 204 상태로 응답해야 하는지...(중략)"


나의 경우 DELETE 작업을 지금까지 두 가지로 처리해왔다.

  1. 플래그(Y/N) 필드를 두어 미사용 처리
  2. 영속 계층(persistence layer)에서 삭제(delete) 처리

그리고 위 두 경우 모두 정상적으로 실행하면 상태코드 200(OK)을 반환하도록 했었다.

HTTP 1.1 공식문서인 RFC 2616에서 DELETE는 다음과 같이 설명되어 있다.

...
A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not include an entity.
...
출처: https://www.rfc-editor.org/rfc/rfc2616#section-9.7

볼드 처리한 곳을 정리해서 해석해보면 HTTP DELETE 작업이 성공하면 성공 상태 코드(200, 202 또는 204)를 반환한다고 되어 있다.
(상태코드 202번은 비동기와 관련되어 있어서 내용이 길어질 듯하여 생략하겠다.)

HTTP Status Code 200 OK

Mozilla에서는 상태코드 200번을 다음과 같이 정의하고 있다.

The HTTP 200 OK success status response code indicates that the request has succeeded.
출처: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200

모질라뿐만 아니라 RFC 2616에서도 상태코드 200번은 요청이 성공했을 때 보내는 상태코드라고 되어있다.
이 말은 즉, 특정 요청에 대한 처리가 성공적으로 처리가 된 경우라면 200번으로 해도 된다는 것이다.

하지만, 2xx번이 여러 상태 코드로 세분화되었다는 것은 클라이언트에게 더 정확하고 자세한 정보를 제공하기 위함이기 때문에 적절한 상태 코드를 보내는 것이 낫다고 생각된다.

HTTP Status Code 204 No Content

The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. ...

The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.
출처: https://www.rfc-editor.org/rfc/rfc2616#section-10.2.5


마찬가지로 볼드 처리한 두 곳을 해석해보면,
- 서버가 요청을 처리했지만 반환을 해줄 필요가 없다.
- 204 응답은 메시지 본문(message body)을 포함해서는 안 된다. 그러므로 항상 헤더 필드 이후에 첫 번째 빈 줄로 종료된다.

결국 핵심은 다음과 같다.

상태코드 200(OK)은 메시지 본문에 null, { }, [ ], true 등과 같이 응답하는 것과 달리,
상태코드 204(No Content)는 메시지 본문(message body)이 존재하지도 않는다는 것이다.



처음에 설명한 지금까지의 내가 한 DELETE 작업을 토대로 어떤 경우에 상태 코드(200 or 204)가 적절한 지 예시를 들어보겠다.
(만약 틀린 부분이 있거나 잘못된 정보라면 댓글로 말씀해주시면 감사하겠습니다.)

전체 소스코드는 아래 링크를 참고해주세요.

 

GitHub - ahn-sj/spring-box: I want to handle the spring better. This repository is for me to apply what I've learned

I want to handle the spring better. This repository is for me to apply what I've learned - GitHub - ahn-sj/spring-box: I want to handle the spring better. This repository is for me to apply wha...

github.com

1. POST 학생 정보 저장
POST /api/student

2. DELETE 학생 정보 비활성화 (200 OK)
DELETE /api/student/v1/1

3. DELETE 학생 정보 삭제 (204 No Content)
DELETE /api/student/v2/1



멈재 학교에 학생 정보를 관리하는 통합정보시스템이 있다고 가정해보자.

멈재 학교 정책상 졸업을 한 경우 비활성화가 되고, 퇴학을 당한 경우 학생 정보를 지우도록 규정되어 있다.
또한, 비활성화를 한 경우라면 졸업한 학생 정보를 제공(반환)해주어야 하고, 삭제한 경우라면 자원을 제공하지 않도록 한다.

학생 정보를 비활성화하고 삭제한 경우에 다음과 같은 정보를 제공받게 된다.

1. 학생 정보 비활성화

HTTP/1.1 200
Content-Type: application/json
Content-Length: 55
Date: Fri, 27 Jan 2023 15:23:03 GMT
Keep-Alive: timeout=60
Connection: keep-alive

3학년 멈재 의 계정은 비활성화되었습니다.

 

2. 학생 정보 삭제

HTTP/1.1 204
Date: Fri, 27 Jan 2023 15:24:46 GMT
Keep-Alive: timeout=60
Connection: keep-alive

<Response body is empty>

 




아직 약간의 모호한 부분이 남아있다.

https://www.devdummy.com/2018/03/rest-response-code-for-delete-operation.html

 

REST Response Code for DELETE Operation, 200 or 204 ?

 

www.devdummy.com


위 포스팅에 의하면 상태 코드 200번과 204번의 사용 유무를 다음과 같이 정의한다.

200 OK 를 사용하는 경우
플래그 설정과 같이 데이터를 표시하여 일시 삭제하는 경우. 여기서 사용자는 플래그 또는 STATUS를 INACTIVE/DELETED로 설정하여 삭제된 것으로 표시해야 합니다. 관련 활동에서 INACTIVE 사용자를 건너뛰기 위해 애플리케이션에서 이를 처리하는 것이 매우 중요합니다.

204 No Content 를 사용하는 경우
되돌릴 수 없는 방식으로 데이터를 제거하면 시스템에서 데이터를 영구적으로 잃게 됩니다. 즉, 영구 삭제입니다. 예 : 특정 트랜잭션의 트랜잭션 항목을 삭제하여 중복 또는 기타 이유로 식별합니다. 이 경우 204 No Content를 사용할 수 있습니다.

이 내용들이 맞다면 어떤 상황에 200번과 204번을 써야 할지  명확히 나뉘게 된다고 생각된다.

그러나 내가 지금까지 이해한 바로 상태코드 200과 204의 차이는 메시지 본문(message body)의 존재 유무 차이였다.
만약 예시로는 통합정보시스템에서 학생 정보 비활성화도 자원을 제공해주지 않아야 한다로 변경된다면 위 포스팅에서 얘기하는 영구적인 삭제를 하지 않고도 상태코드 204로 반환할 수 있다는 생각이 들었다.

반대로 해당 포스팅에 말한 대로 자원의 존재 유무로 응답의 유무를 판단하는 것이라면, 자원을 삭제하는 경우 해당 자원이 존재하지 않기 때문에 HTTP body로 응답하는 것이 무의미해졌을 때 사용하는 것도 맞겠다는 생각도 든다.

이미지 출처:https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE