HTTP Method 간략 정리
주요 메소드 : GET, POST, PUT, DELETE, PATCH
OPTIONS : 주로 CORS에서 사용, 요청 URI에서 사용할 수 있는 옵션 설명
HEAD : GET과 동일하지만 메시지 부분을 제외하고, 상태 줄과 헤더만 반환
TRACE : 목적 리소스의 경로를 따라 메시지 loop-back 테스트
CONNECT : 메서드는 목적 리소스로 식별되는 서버로의 터널을 맺음
Patch Method의 등장
PUT, PATCH의 차이
Update 방식에서의 차이
Id | name | class |
1 | Ella | A반 |
2 | Luke | B반 |
3 | Khan | C반 |
위와 같은 테이블 예시에서 PUT 메소드의 동작 >> 리소스를 대체, 없는 컬럼은 null로 대체
PATCH 메소드의 동작 >> 리소스 부분 수정
자원이 존재하지 않을 때
PUT은 생성, PATCH의 경우는 4xx 에러를 반환
멱등성 관점에서의 차이
멱등성 : 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질
- PUT은 멱등성을 가지지만, PATCH는 멱등성을 가지지 않는다
-
•이전의 예시들만 보면 두 메소드 모두 멱등성이 있는 것 처럼 보인다.
-
-
PATCH는 왜 멱등성을 가지지 않을까?
-
멱등으로 설계할 수도 있지만 멱등이 아니게도 설계할 수 있다. PATCH는 멱등이 아니기 때문에 다음과 같이 특정 부분을 추가로 더하거나 하는 식으로 설계해도 된다.
- Ex) { "operation": "add", "age": 10"} >> 호출할 때마다 나이를 연산하는 API
- 위 예시로 보면 호출할 때마다 결과 값이 달라지므로 멱등성을 가지지 않는다.
-
정리하면 PATCH는 리소스의 특정 부분을 변경하는데, 이 변경 방식이 멱등이어도 되고, 멱등이 아니어도 된다. 구현에 따라 멱등성을 가질 수도, 가지지 않을 수도 있다.
스프링 Dispatcher Servlet의 변화
- Dispatcher Servlet의 dispatch는 "보내다"라는 뜻을 가지고 있다.
- 이러한 단어를 포함하는 디스패처 서블릿은 HTTP 프로토콜로 들어오는 모든 요청을 가장 먼저 받아 적합한 컨트롤러에 위임해주는 프론트 컨트롤러라고 정의
Dispatcher Servlet의 구조
- HttpServlet
- HttpServlet을 구현하기 위한 J2EE 스펙의 추상 클래스
- HttpServletBean
- HttpServlet을 Spring이 구현한 추상 클래스
- FrameworkServlet
- doX 메소드를 오버라이딩하고 있으며, doX 요청들을 공통된 요청 처리 메소드인 processRequest로 전달함
- DispatcherServlet
- 컨트롤러로 요청을 전달하는 중앙 집중형 프론트 컨트롤러(서블릿 구현체)
Dispatcher Servlet의 변화
1. Dispatcher Servlet이 요청을 받으면 가장 먼저 하는 것은 서블릿 요청/응답을 HTTP 서블릿 요청/응답으로 변경
public abstract class HttpServlet extends GenericServlet {
...
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException(lStrings.getString("http.non_http"));
}
service(request, response);
}
...
}
2. Service 메소드 호출
- HTTP 메소드에 맞게 자식 클래스(FrameworkServlet)에 오버라이딩된 do{Method} 메소드 호출
- 예를들어 POST 요청이라면 doPost메소드 호출
public abstract class HttpServlet extends GenericServlet {
...
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
...
}
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals(METHOD_GET)) {
... // lastModifed에 따른 doGet 처리(요약함)
doGet(req, resp);
} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals(METHOD_POST)) {
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);
} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);
} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);
} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);
} else {
... // 에러 처리
}
}
...
}
여기서 PATCH의 경우 doPatch 메소드를 호출해야 하지만 HttpServlet은 PATCH 메소드가 등장하기 이전에 탄생하여, PATCH 메소드에 대해 doPatch를 호출해주는 부분이 없다.
J2EE 표준 기술인 HttpServlet를 스프링 개발자들이 함부로 수정할수는 없었고, 그렇다고 표준 기술로 채택된 PATCH 메소드를 지원하지 않을수도 없었다.
그래서 스프링은 PATCH를 지원하고자 자식 클래스인 FrameworkServlet에 HttpServlet의 service 메소드를 오버라이딩하였다. 요청 메소드가 PATCH라면 바로 요청을 처리하는 processRequest를 호출하고, PATCH가 아니라면 부모 클래스인 HttpServlet의 service를 호출하도록 구현한 것이다. 이러한 구조로 PATCH 메소드를 지원하도록 처리하였다.
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
...
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
if (httpMethod == HttpMethod.PATCH || httpMethod == null) {
processRequest(request, response);
}
else {
super.service(request, response);
}
...
}
}
Ref :
https://mangkyu.tistory.com/225?category=761302
https://tecoble.techcourse.co.kr/post/2020-08-17-put-vs-patch/
'Back-end' 카테고리의 다른 글
[SpringBoot] 프로젝트 리소스 파일 가져오기 (0) | 2022.11.29 |
---|---|
자바 직렬화(Serializable) (0) | 2022.10.04 |
[Kotlin] Kotlin + Springboot 에서의 validation (0) | 2022.04.27 |
[Kotlin] 코틀린 타입 시스템(Type System) - ( ?/!!/.?/as?/let함수/lateinit) (0) | 2022.03.24 |
카카오 소셜 로그인 With Front (React) (2) | 2022.01.26 |