티스토리 뷰
FeignClient 란?
Feign Client란 Netflix에서 개발한 Http Client다.
카카오 소셜로그인
카카오 토큰을 받는 API는 x-www-form-urlencoded 타입이 필수값이다.
x-www-form-urlencoded 타입은 Spring에서 @RequestParam, @ModelAttribute 어노테이션으로 주입받을 수 있다.
둘중에 하나를 선택해야하는데 @RequestParam은 사용하고싶지않았다.
@RequestParam 단일 파라메터
@FeignClient(url = "https://kauth.kakao.com", value = "kakaoAuthApi")
public interface KakaoAccessTokenClient {
@PostMapping(
value = "/oauth/token",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
KakaoAccessTokenResponse getKakaoToken(
@RequestParam("grant_type") String grantType,
@RequestParam("client_id") String clientId,
@RequestParam("redirect_uri") String redirectUri,
@RequestParam("code") String code
);
}
첫번째 방식은 파라메터가 많고 모두 타입이 동일해서 실수할 가능성이 높아서 사용하고싶지않았다. (Builder를 사용하고싶었다)
@RequestParam Map
@FeignClient(url = "https://kauth.kakao.com", value = "kakaoAuthApi")
public interface KakaoAccessTokenClient {
@PostMapping(
value = "/oauth/token",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
KakaoAccessTokenResponse getKakaoToken(
@RequestParam HashMap<String,String> paramMap
);
}
HashMap<Object, Object> request = new HashMap<>();
request.put("grant_type", grantType);
request.put("client_id", clientId);
request.put("redirect_uri", redirectUri);
request.put("code", code);
두번째 방식은 HashMap으로 HttpClient 이외의 Service 등의 layer에서 구체적인 Api 명세를 알아야해서 사용하고싶지않았다.
@ModelAttribute
@FeignClient(url = "https://kauth.kakao.com", value = "kakaoAuthApi")
public interface KakaoAccessTokenClient {
@PostMapping(
value = "/oauth/token",
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE
)
KakaoAccessTokenResponse getKakaoToken(
KakaoAccessTokenRequest request
);
}
@Builder
public record KakaoAccessTokenRequest(
@JsonProperty("grant_type")
String grantType,
@JsonProperty("client_id")
String clientId,
@JsonProperty("redirect_uri")
String redirectUri,
String code
) {
}
위와 같이 작성했지만 정삭적으로 값이 들어오지 않았다.
이유는 x-www-form-urlencoded 타입은 Json 타입이 아니기때문에 @JsonProperty를 사용할 수 없었다.
그렇다고 변수명을 스네이크 케이스로 사용하고싶지도 않았다.
@BindParam
spring-framwork 이슈를 찾아보니 나와 같은 고민을 하는 사람들이 있었고 @BindParam이 추가되었다.
https://github.com/spring-projects/spring-framework/issues/18012#issuecomment-1651169636
@Getter
public class KakaoAccessTokenRequest {
private String grantType;
private String clientId;
private String redirectUri;
private String code;
@Builder
public KakaoAccessTokenRequest(
@BindParam("grant_Type")
final String grantType,
@BindParam("client_id")
final String clientId,
@BindParam("redirect_uri")
final String redirectUri,
final String code
) {
this.grantType = grantType;
this.clientId = clientId;
this.redirectUri = redirectUri;
this.code = code;
}
}
public record KakaoAccessTokenRequest(
String grantType,
String clientId,
String redirectUri,
String code
) {
@Builder
public KakaoAccessTokenRequest(
@BindParam("grant_Type")
final String grantType,
@BindParam("client_id")
final String clientId,
@BindParam("redirect_uri")
final String redirectUri,
final String code
) {
this.grantType = grantType;
this.clientId = clientId;
this.redirectUri = redirectUri;
this.code = code;
}
}
하지만 @BindParam 방식 또한 정삭적을 동작하지 않았습니다.
아마 FeignClient에 BindParamNameResolver를 아직 지원하지 않는것같다.
@FormProperty
조금더 찾아보니 FeignClient에서는 @FormProperty 어노테이션을 제공하고 x-www-form-urlencoded 타입에서 사용이 가능할것같았다.
https://github.com/OpenFeign/feign-form
public record KakaoAccessTokenRequest(
@FormProperty("grantType")
String grantType,
@FormProperty("clientId")
String clientId,
@FormProperty("redirectUri")
String redirectUri,
String code
) {
}
하지만 @FormProperty 또한 정상적으로 동작하지않았다.
디버깅을 해보니 FeignClient @FormProperty를 바인딩 하기위해서 내부적으로 PojoUtil 클래스를 사용한다.
문제는 isFinal 메서드에 있었다.
프로젝트에서 Dto에서 record를 사용하고있었고 record를 사용하면 각 필드는 private final 필드로 정의되기 때문에 정상적으로 작동하지않는다.
접근 제어자를 강제하는것은 Pojo가 아니라 Java-Bean이다.
https://www.geeksforgeeks.org/pojo-vs-java-beans/
마무리
아직 FeignClient @FormProperty에서 record를 사용할 수 없다.
https://github.com/OpenFeign/feign-form/pull/120
위 코드를 제거해서 PR을 올렸는데 마지막 업데이트가 4년전인 하위 모듈이기때문에 언제 업데이트 될지는 모르겠다.
'spring' 카테고리의 다른 글
ShedLock 도입기 (0) | 2024.04.11 |
---|---|
Spring Boot 로그에 바인딩 매개변수가 표시되지 문제 해결 (0) | 2023.10.24 |
스프링의 트랜잭션 전파 속성(Transaction propagation) 실제 쿼리 (0) | 2023.10.07 |
DispatcherServlet을 어떻게 Eembeded Tomcat에 등록할까? (0) | 2023.09.28 |
Jackson의 ObjectMapper는 Thread-safe 한가? (0) | 2023.09.27 |
- Total
- Today
- Yesterday
- dto 검증
- CreationTimestamp
- Attribute Converter
- setDateFormat
- feignClient
- entity 검증
- dto 위치
- HandlesTypes
- User Scenario
- 구글 소셜로그인
- ServletContainerInitializer
- HTTPInterface
- BasicBinder
- DispatcherServletInitializer
- 구글 OpenID
- Spring Boot 3
- 레이어드 아키텍처
- 유저 스토리
- FormProperty
- CreatedDate
- ValidateException
- @ElementCollection
- defer-datasource-initialization
- org.springframework:spring-webflux
- 유저 시나리오
- @Converter
- WebFlux 의존성
- @FormProperty
- java 17
- JPA SQL Injection
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |