서버가 HTTP methods를 어떤식으로 처리할지는 전적으로 서버 프로그래머에 달려있다고 한다. 즉 POST를 받으면 데이터를 지우고, DELETE을 받으면 데이터를 생성하는 서버를 만들 수도 있는 것이다. 이는 사실상 HTTP methods들이 시스템상의 제약으로 각각의 기능이 나누어 지는 것이 아니라, 단지 사람의 이해를 돕기 위한 목적으로 구별되어지는 용도이기 때문이다. 실제로 많은 서버들이 GET(정보 읽기)과 POST(그 외의 모든 처리)로만 요청을 처리하기도 한다. 나 또한 그렇게 프로젝트를 진행하였다.
하지만 REST API 구조를 제대로 따라가보고 싶어졌다. 기존 로직을 보겠다.
기존 게시글 삭제 맵핑
html
URI는 자원을 표현하는데 중점을 두어야 한다는 REST API 중심 규칙에 따라 기존 delete와 같은 행위에 대한 표현이 들어간 부분은 수정이 필요하다는 결론을 내렸다.
@DeleteMapping, @PutMapping 등의 최신 매핑기능을 이용하기 위해선 아래와 같은 코드를 작성해야 한다고 한다
HiddenHttpMethodFilter
따라서 디스패처 서블릿(dispatcher Servlet)이 PUT, DELETE Method를 인식할 수 있도록 Spring Framework의 org.springframework.web.filter 패키지 안에 구현된 HiddenHttpMethodFilter를 사용해야 함.
- form 태그안의 input 태그를 히든으로 하고 name을 method로 하는 이유?
→ HiddenHttpMethodFilter.class 내부를 디버깅을 해보면 input 태그를 type="hidden" name = "_method" value = "delete"로 한 후 요청하면 doFilterInternal메서드 안에 있는 paramValue에 "delete"가 들어가게 됩니다. 그리고 HttpMethodRequestWrapper 객체를 생성하여 method를 delete로 변경하여 DELETE 요청이 온 것으로 바뀌게 됩니다. 따라서 히든으로 설정한 name이 "method"인 input 태그의 value 값에 따라 디스패처 서블릿(dispatcher Servlet)에 요청하는 HTTP Method가 결정됩니다.
컨트롤러 DELETE로 HTTP METHOD 수정
html
성공적으로 게시글이 삭제되었다.
여기서 한가지 궁금했던 점은, HTML Form에서 GET/POST만 지원하는 이유였다.
아니나 다를까 이에 대해 논쟁이 계속되고 있었다. 요약하자면 추가하자는 안건은 계속 올라오지만 리젝되고 있는 중이었음.
따라서
GET은 form에 있는 정보를 줄테니 나에게 리소스(representation)를 줘,
POST는 form에 있는 정보를 줄테니 이걸로 처리 좀 해줘
라는 의미가 되지만,
DELETE에서 URI는 리소스를 정확하게 식별하고 요청을 보내기 때문에 form을 통해 값을 전달할 게 없으며
권한을 획득하기 위해선 header를 이용해야할 것 같다.
PUT도 전송해야할 것은 대상 리소스를 대체할 representation 그 자체인데, 대상 리소스더러 조각난 form 데이터를 처리하라고 보낼 수는 없는 노릇.
--> 조각난 form 데이터 ?
((MDN 기준으로) HTML의 form은 "The form HTML element represents a document section containing interactive controls for submitting" 즉 대화형 컨트롤입니다. 뭔가(리소스 혹은 행위)를 요청하기 위해 필요한 데이터를 보내는 행위라서 그 자체가 PUT의 대상이 될 수 없다고 생각하시면 되겠습니다.)
게시글 삭제 뿐만 아니라 댓글 삭제도 DELETE로 처리해주었는데,
버튼을 클릭하면 서버에 POST 요청을 보내는 양식으로 진행하며 그런 다음 서버가 "_method" 필드를 탐지하고 DELETE 요청으로 처리할 수 있도록 하였다.
csrf 방어를 위한 _token에 관한 내용은 향후 다른 포스트에서 다뤄볼 예정.
참고 - How to send a DELETE request from Button with JavaScrpt?
게시글 좋아요 구현도 GET Mapping을 이용하여 xhr로 보내주었는데, PUT으로 변경해주었다.
외에도 다양한 방식이 있으니 추후에 참고해봐야겠다
참고 - JavaScript 및 XML HttpRequest 개체를 사용한 CRUD 페이지 작성