프로젝트/개인 프로젝트(2023.11.13-2023.12.18)

[개인프로젝트] @FeignClient 파라미터 오류

dal_been 2023. 11. 22. 14:41
728x90

로그인 구현을 구글과 로그인으로 하는 중 각각 로그인 api에 요청을 보내고 응답을 받기 위해 @FeignClient를 이용중이었다.

 

구글의 경우 로그인 연동 결과로 code까지 잘 받고 접근 토큰 발급 요청하여 accessToken까지 잘 받아서 고객의 이메일과 이름을 잘받았다.

 

문제상황

 

네이버의 경우 문제가 생겼다

네이버의 로그인 연동 결과로 code값을 받았지만 접근 토큰 발급 요청에서 Response객체의 필드가 다 null인 상황이 발생한거다..

 

문제의 상황을 자세히 들여다보자

 

 
 public class NaverOauth implements Oauth {
     @Override
      public String getLoginView() {
        String reqUrl=NAVER_API_URL+"response_type=code&"
            +"client_id="+NAVER_CLIENT_ID+"&state=STATE_STRING&redirect_uri="
            +NAVER_REDIRECT_URL;
        return reqUrl;
      }

}

 

나의 코드를 일부 발췌해왔다. 일단 Naver로 회원가입 또는 로그인을 하겠다고 하면 해당 네이버 로그인 URL로 이동하게하였다.

그래서 로그인까지 확인하고 code값 까지 받아오는 걸 확인했다

 

2023-11-22T13:40:45.000+09:00  INFO 2158 --- [nio-8080-exec-3] 
c.p.d.m.controller.MemberController      : login result = #########

 

그런데 여기서 앞서 말한 문제 발생

 

2023-11-22T13:57:44.115+09:00 DEBUG 2233 --- [nio-8080-exec-3] 
	o.s.c.openfeign.support.SpringEncoder    : Writing [NaverRequest(grant_type=authorization_code, client_id=uKrQ_JhavpVwEijIzEIG, client_secret=7Y2QxDEkgP, code=H72NY8HjDAkfLxp32y, state=9kgsGTfH4j7IyAkg)] using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@6f18445b]

2023-11-22T13:57:44.440+09:00  INFO 2233 --- [nio-8080-exec-3] 
	c.p.d.member.client.naver.NaverOauth     : response =NaverResponse(access_token=null, refresh_token=null, token_type=null, expires_in=null)
2023-11-22T13:57:44.533+09:00 ERROR 2233 --- [nio-8080-exec-3] 
	o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: feign.FeignException$Unauthorized: [401 Unauthorized] during [GET] to [https://openapi.naver.com/v1/nid/me] [NaverClient2#getNaverDetailInfo(Map)]: [{"resultcode":"024","message":"Authentication failed (\uc778\uc99d \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.)"}]] with root cause

feign.FeignException$Unauthorized: [401 Unauthorized] during 
	[GET] to [https://openapi.naver.com/v1/nid/me] [NaverClient2#getNaverDetailInfo(Map)]: [{"resultcode":"024","message":"Authentication failed (\uc778\uc99d \uc2e4\ud328\ud558\uc600\uc2b5\ub2c8\ub2e4.)"}]

 

분명 맨 위줄을 보면 Request객체를 openFeign가 잘 인식했다. 근데 결과적으로 Response필드는 다 Null로 나왓다. 그러다보니 당연히 권한 불가라는 에러가 뜬 것이다.

 

그래서 직접 url에다가 쿼리 매개변수로 필요한건 붙이고 실행해봤더니 response객체가 원하는 대로 응답이 왔다..

 

 

왜일까?? 사실 내가 @FeignClients를 처음 써봐서 나온 에러라고 생각한다.

 

일단 나의 NaverClient코드를 간단하게 보자면

@FeignClient(name = "naver",url = "${naver.token.url}")
public interface NaverClient {

  @GetMapping("/oauth2.0/token")
  NaverResponse getNaverToken( NaverRequest naverRequest);

}

 

이런상태이다. 그래서 나는 "{url}?request 객체 필드들"이렇게 url이 매핑되는줄 알았다. 네이버에서 원하는 url 형태가 

https://nid.naver.com/oauth2.0/authorize?
response_type=code&client_id=CLIENT_ID&state=STATE_STRING&redirect_uri=CALLBACK_URL

이었기 때문이다.

 


 

그래서 문제점은 뭐냐

 

json 형식의 데이터 전달

 

찾아보니 get방식이든 post방식이든 openfeign는 json 형식으로 데이터를 전달한다고 하는 것같다. 

거기다가 아까 로그를 보면 "MappingJackson2HttpMessageConverter"를 통해 json형태로 형변환하는 것을 볼 수 있다.

Writing [NaverRequest(grant_type=authorization_code, client_id=uKrQ_JhavpVwEijIzEIG, client_secret=7Y2QxDEkgP, code=H72NY8HjDAkfLxp32y, state=9kgsGTfH4j7IyAkg)] using 
[org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@6f18445b]

 

근데 네이버에서는 get/post방식이 상관없다고 해서 나는 get방식을 택했고  쿼리 매개변수로 데이터를 보내야했다. 하지만 json형식으로 보내다 보니 당연히 권한이 없다고 뜬것이다.

 

spring cloud docs를 보면 쿼리 매개변수를 위한 어노테이션을 제공한다.

[Feign @QueryMap support]

Spring Cloud OpenFeign provides an equivalent @SpringQueryMap annotation
, which is used to annotate a POJO or Map parameter as a query parameter map.

For example, the Params class defines parameters param1 and param2:

// Params.java
public class Params {
    private String param1;
    private String param2;

    // [Getters and setters omitted for brevity]
}

The following feign client uses the Params class by using the @SpringQueryMap annotation:

@FeignClient("demo")
public interface DemoTemplate {

    @GetMapping(path = "/demo")
    String demoEndpoint(@SpringQueryMap Params params);
}

If you need more control over the generated query parameter map, 
you can implement a custom QueryMapEncoder bean.

 

그래서 requset 객체 앞에 @SpringQueryMap을 붙였더니...

 

@FeignClient(name = "naver",url = "${naver.token.url}")
public interface NaverClient {

  @GetMapping("/oauth2.0/token")
  NaverResponse getNaverToken(@SpringQueryMap NaverRequest naverRequest);

}

 

바로 성공..

 

 


 

결과적으로 openfeign를 자세히 공부하지 않고 사용했던 나의 잘못이다. 다음 블로그 내용은 openfeign을 자세히 공부하고 적어야겠다.

왜 openfeign를 사용하는지도 찾아봐야지 resttemplate나 다른 방법도 있는데 왜 사용하는지 궁금하기도 하다.