김태오

FeignClient 사용시 PATCH method 가 안되는 오류 본문

Spring Boot

FeignClient 사용시 PATCH method 가 안되는 오류

ystc1247 2024. 3. 11. 03:36

FeignClient 는 Spring Cloud 의 HTTP client 이다. microservice 등의 멀티모듈 환경 구성시 HTTP request 와 response 를 쉽게 주고받을 수 있도록 한다.

 

RestTemplate 과 WebClient 등의 선택지도 있지만 이들보다 코드가 훨씬 보기 편하고 간결하다는 장점이 있다.

implementation("org.springframework.cloud:spring-cloud-starter-feign:1.4.7.RELEASE")

 

일단 이런걸 버젼 맞춰서 넣어준다.

 

@FeignClient(name = "feignclient")
sealed interface FeignController {
    @PatchMapping("/test")
    fun test(
        @RequestBody
        body: String,
    ): String
}

 

하나의 모듈에서 이런걸 가지고 있고,

@RestController
class Controller {
    @PatchMapping("/test")
    fun test(
        @RequestBody
        body: String,
    ): String {
        return "test"
    }
}

 

다른 모듈에서 일반적인 controller 를 가지고 있으면, uri 와 넘겨주는 인자들, response type 등을 모두 맞춰서 소통이 되는 것이다. 근데 이걸 쓰다가 희안한 문제가 발생하는데, PATCH method 를 사용할 때 오류가 터지는 것이다. 일단 로그부터 까보자.

java.net.ProtocolException: Invalid HTTP method: PATCH
	at java.base/java.net.HttpURLConnection.setRequestMethod(HttpURLConnection.java:489) ~[na:na]
	at java.base/sun.net.www.protocol.http.HttpURLConnection.setRequestMethod(HttpURLConnection.java:598) ~[na:na]
	at feign.Client$Default.convertAndSend(Client.java:171) ~[feign-core-13.1.jar:na]
	at feign.Client$Default.execute(Client.java:106) ~[feign-core-13.1.jar:na]
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:100) ~[feign-core-13.1.jar:na]
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:70) ~[feign-core-13.1.jar:na]
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:99) ~[feign-core-13.1.jar:na]
	at jdk.proxy3/jdk.proxy3.$Proxy73.test(Unknown Source) ~[na:na]
 
가장 흔하게 쓰는 HTTP method 중 하나인 PATCH 가 Invalid 하다니 뭔가 하니, 두번째 줄에 힌트가 있다. FeignClient 는 별도의 설정을 해주지 않으면 기본적으로 HTTP 통신 시 HttpURLConnection 이라는 자바 객체를 사용한다. Intellij 에서도 바로 라이브러리 파일들을 까볼 수 있으니, 가서 관찰해보자.
    /* valid HTTP methods */
    private static final String[] methods = {
        "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE"
    };

 

이러한 String array 가 있고, 이는 지원되는 method 들인 것 같다. 좀 역사를 살펴보면, HTTP/1.1 RFC 2068 이 발표된 것이 1997년 1월이다. https://www.rfc-editor.org/info/rfc2068 Java 1.1 이 release 되었을 때 포함된 HttpURLConnection 은 이 전에 만들어졌는데, PATCH 라는 메소드는 2010년 3월에 발표된 RFC 5789 에 포함된다. 부분적 수정이 목적인 PATCH 는 이전의 resource 와 수정되는 resource 간의 diff file 의 생성되기 때문에 전체적 수정이 목적인 PUT 에 비해 오버헤드가 발생하는데, 이때문인지 늦게 발표되었나 모르겠다. 루비 언어의 요구사항과 관련이 있다고도 하는데, 궁금하면 찾아보자.

 

아무튼간에 이렇게 되면 FeignClient 가 통신할 때 사용하는 도구를 비틀어줄 필요가 생긴다. 여기서 쓰이는게 okhttp 라는 친구다. 

implementation("io.github.openfeign","feign-okhttp")

 

이놈을 넣어주고, feignclient 가 HTTP 통신 시 okhttp Client 를 사용할 수 있도록 온몸비틀기를 해보자. client bean 을 생성하여 @FeignClient 어노테이션의 configuration value 에 넣어주면 되겠다.

@Configuration
class FeignOkHttpConfiguration {
    @Bean
    fun client(): OkHttpClient {
        return OkHttpClient()
    }
}
@FeignClient(name = "feign", configuration = [FeignOkHttpConfiguration::class])