그 외 공부/네트워크

PATCH 메서드는 HTTP 표준 메서드가 아니었다? (feat. HTTP 메서드 히스토리 알아보기)

SeongOnion 2024. 4. 26. 15:55
728x90

HTTP PATCH 메서드는 표준 메서드가 아니었다?

HTTP의 표준 메서드

HTTP 표준 메서드를 하나씩 떠올려보자.

 

아마 대부분의 사람들이 GET, POST, PUT, PATCH, DELETE 이렇게 5가지 메서드를 생각할 것이다. (그 외에도 HEAD, OPTIONS 등..)

 

위 5가지 메서드들은 마치 일종의 불변상수와도 같아서 HTTP라는 녀석이 처음 세상에 나올때부터 함께 존재했던 것과 같은 착각을 불러일으킨다.

 

하지만 HTTP는 1990년대 초에 처음으로 명세되어 거진 30년이 가까운 시간동안 끊임없이 발전해왔고, 특히 PATCH 메서드는 비교적 최근인 2010년에야 RFC5789를 통해 HTTP의 표준 메서드로 채택되었다.

 

HTTP 스펙 살펴보기

 

https://www.w3.org/Protocols/HTTP/1.0/spec.html

 

https://www.w3.org/Protocols/rfc2616/rfc2616.html

위 두 이미지는 순서대로 HTTP/1.0과 HTTP/1.1의 스펙에 명시된 Method Definition이다.

 

GET, POST, PUT, DELETE 뿐 아니라, HEAD, OPTIONS 등의 메서드도 표준으로 제정된 것을 확인할 수 있으며, PATCH 메서드는 포함되어있지 않다.

 

두 가지는 각각 1996년 11월과 1997년 1월에 등장했다는 점을 감안하면 PATCH 메서드가 표준으로 제정된 시기와 무려 10년 이상의 텀이 존재하는 것을 확인할 수 있다.

 

하지만 재미있는 점은 PATCH 메서드가 표준 메서드로 제정된 시기가 2010년이라는 것이지, PATCH 메서드 자체의 등장은 RFC 2068로 이는 HTTP/1.1의 공식 명세인 RFC 2616보다 앞선다.

https://datatracker.ietf.org/doc/html/rfc2068#page-48

위는 실제 RFC 2068의 Additional Request Methods로 명시된 PATCH 메서드에 대한 명세이다.

 

Partial Update에 대한 설명으로, 우리가 아는 그 PATCH 메서드가 되겠다.

https://datatracker.ietf.org/doc/html/rfc2616

그리고 위는 앞서 언급한 HTTP/1.1의 표준 명세인 RFC 2616 중 일부인데, 비록 PATCH 메서드를 표준 메서드로 정의하진 않았으나 언급은 하고 있는 것을 확인할 수 있었다.

 

해당 내용으로 미루어보아, PATCH 메서드에 대한 논의가 이루어지긴 했으나 제대로 구현되지 않아 정작 표준 메서드에선 제외된 것으로 예상해볼 수 있을 것 같다.

 

그렇다면 사실상 HTTP/1.1의 공식 명세 이전에 등장한 PATCH 메서드는 어떤 계기로 10년이 넘은 후에야 표준 메서드로 제정되었을까?

이는 위키피디아에 명시된 PATCH 메서드 히스토리 부분에서 실마리를 잡을 수 있다.

 

루비 온 레일즈 팀에서 리소스의 부분 업데이트 지원을 위한 HTTP 메서드 도입의 필요성을 주장했고, 이후 2010년에 정식 메서드로 채택되게 되었다.

 

https://rubyonrails.org/2012/2/26/edge-rails-patch-is-the-new-primary-http-method-for-updates

이를 바탕으로 2012년에 루비 온 레일즈는 자신들의 공식 홈페이지에 업데이트 작업을 위한 PATCH 메서드 사용을 소개하기도 했다.

 

PATCH 메서드 표준화의 흔적 찾아보기

HttpServlet

이와 같은 PATCH 메서드 히스토리의 흔적은 루비뿐만 아니라 Web 및 HTTP 통신과 관련된 유명 라이브러리들에서도 확인할 수 있다.

 

가장 와닿을 수 있는 케이스 중 하나로, 자바의 서블릿 기술에서는 PATCH 요청을 지원하는 메서드가 존재하지 않는다.

package jakarta.servlet.http;

public abstract class HttpServlet extends GenericServlet {
	
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	...
    }
    
    protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	...
    }
    
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	...
    }
    
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	...
    }
    
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	...
    }
    
    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	...
    }
    
    protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	...
    }
}

HttpServlet 객체에서 지원하는 메서드는 GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE로, 모두 HTTP/1.1에서 표준 메서드로 정의된 것들 뿐이다.

 

이는 자바의 서블릿 기술이 처음 개발된 것이 1997년이고, 이는 PATCH 메서드가 표준이 된 2010년과 상당한 시간 차이가 나기 때문에 단순히 doPatch()와 같은 메서드를 추가하는 형태로 지원하기는 매우 어려웠을 것으로 판단된다.

 

이에 따라서, 스프링 웹 기술에서는 자신들이 정의한 FrameworkServlet을 통해 PATCH 메서드라면 자체적으로 처리를 해주고, 그 외의 자바 서블릿 기술이 지원하는 HTTP 메서드들에 대해선 서블릿이 처리하도록 구현해두었다.

org.springframework.web.servlet.FrameworkServlet

위처럼 서블릿에서 지원 가능한 HTTP 메서드들을 HTTP_SERVLET_METHODS로 정의해놓고, 요청 메서드가 그에 해당되면 HttpServlet에게 처리를 위임하고, 그 외엔 자신들이 정의한 processRequest() 메서드를 호출하도록 구현되었다.

 

해당 부분은 역시 독스에 잘 정리되어있다.

 

FeignClient

이전에 FeignClient를 사용 시 PATCH 메서드를 사용할 수 없다는 얘기를 들은 적이 있는데, 이 역시 FeignClient가 PATCH 메서드를 지원하지 않는 구현체를 사용하고 있기 때문이다.

 

FeignClient는 내부적으로 외부 API와의 통신을 위해 java.net.HttpURLConnection을 사용한다.

 

그리고 해당 클래스를 살펴보면, HttpServlet과 마찬가지로 PATCH 메서드를 지원하지 않는다.

java.net.HttpURLConnection

역시나 RFC 5789이전 HTTP/1.1에서 공표한 표준 메서드만을 유효한 HTTP 메서드로 정의하고 있다.

따라서 해당 구현체를 그대로 사용하는 경우, PATCH 요청 시 오류가 발생하게 되는 것이다!

 

물론 스프링 웹 기술에서처럼 OkHttpClient와 같은 PATCH 메서드를 지원하는 HTTP Connection 구현체들이 여럿 존재하고, FeignClient 사용 시 HttpURLConnection 대신 해당 구현체들을 사용해주도록 변경해주면 PATCH 메서드도 사용할 수 있게된다.

 

해당 부분은 검색해보면 많은 솔루션이 나오니 참고하면 된다.

 

레퍼런스

https://en.wikipedia.org/wiki/PATCH_(HTTP)#History_of_PATCH

 

PATCH (HTTP) - Wikipedia

From Wikipedia, the free encyclopedia Request method in the HTTP protocol In computing, the PATCH method is a request method in HTTP for making partial changes to an existing resource.[1] The PATCH method provides an entity containing a list of changes to

en.wikipedia.org

https://datatracker.ietf.org/doc/html/rfc5789

 

RFC 5789: PATCH Method for HTTP

Several applications extending the Hypertext Transfer Protocol (HTTP) require a feature to do partial resource modification. The existing HTTP PUT method only allows a complete replacement of a document. This proposal adds a new HTTP method, PATCH, to modi

datatracker.ietf.org

https://datatracker.ietf.org/doc/html/rfc2616

 

RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1

HTTP has been in use by the World-Wide Web global information initiative since 1990. This specification defines the protocol referred to as "HTTP/1.1", and is an update to RFC 2068. [STANDARDS-TRACK]

datatracker.ietf.org

https://datatracker.ietf.org/doc/html/rfc2068

 

RFC 2068: Hypertext Transfer Protocol -- HTTP/1.1

The Hypertext Transfer Protocol (HTTP) is an application-level protocol for distributed, collaborative, hypermedia information systems. [STANDARDS-TRACK]

datatracker.ietf.org

https://mangkyu.tistory.com/225

 

[Spring] 뒤늦게 등장한 HTTP PATCH 메소드와 스프링의 디스패처 서블릿에 미친 영향

PATCH 메소드는 2010년도에 뒤늦게 HTTP 표준 스펙으로 추가되었습니다. 그리고 이로 인해 스프링 코드도 영향을 받게 되었는데, 왜 영향을 받게 되었고 어떠한 영향을 받게 되었는지 살펴보도록 하

mangkyu.tistory.com