728x90
반응형

개발을 하다가 어드민을 사용하시는 부분에서 제보가 들어왔다.

request log를 보니 LocalDate 를 받도록 되어있는데 분명히 yyyy-MM-dd 형식으로 request log가 찍혔는데?

근데 좀 달랐다. access-language가 en-US로 되어있는것!

어드민 사용하시는 분에게 여쭤봤더니 자신은 크롬 브라우저를 영어모드로 사용한다고 했다.

시작점

아, 설명하기 앞서 이 상황은 앞단에 proxy 서버가 따로있다.

 

호출 방식이 아래처럼 되어있다.

앞단은 proxy server라고 지칭하겠다.

client ->  proxy server -> 우리의 server

proxy server에서는 우리 server로 bypass 시켜주며 그 때 call 해주는 방식을 Spring Cloud OpenFeign을 사용한 FeignClient호출을 해주는 것으로 설정이 되어있다.

 

근데 우리쪽 request log에서는 아래와 같은 로그가 찍혔었다.

참고로 지금 보여주는 이미지, 코드, 에러로그는 전부 개인 개발환경에서 똑같이 구현해서 만들었음을 먼저 이해하고 가야한다.

항상 얘기하지만 모든 코드는 내 깃허브에 있다. (해당 디렉토리 내부에만 예제 코드가 있다 ㅋㅋ)

코드는 회사가 아니라 혼자서 구현하기에 Kotlin으로 작성했다.

 

2025-02-21T00:07:36.586+09:00 WARN 70016 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Method parameter 'date': Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDate'; Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam java.time.LocalDate] for value [2/20/25]]

 

이렇게 예외가 났고, 문자열 정보를 보면 MM/dd/YY 형식으로 나와지는걸 볼 수 있다.

 

여기서부터 의아함을 갖고 디버깅을 깊게 해보기 시작했다.

 

디버깅

처음은 당연히 그냥 아래처럼 데이터를 주고 보냈다.

GET http://localhost:8080/api/v1/test?date=2025-02-20

 

당연히 예상하는 결과지만 너무 잘 파싱이 된다는것.

 

이제 문제의 access-language가 들어가게 되면 그냥 오류가 나는것인가?

다시한번 호출했다.

curl --location 'http://localhost:8080/api/v1/test?date=2025-02-20' \
--header 'Accept-Language: en-US,en;q=0.9'

이렇게 보냈을 때에도 정상으로 수신됐었다.

도대체 문제가 뭘까 하는 생각에 feign이 정말 문제라고?

라이브러리 자체에 치명적인 결함이 있는건가? 했었다. -> 왜 그랬냐면 이걸 의심하는 순간 라이브러리를 믿고 사용할 수 있을까? 라는 생각이 계속 들었었다.

 

문제의 FeignClient

로컬에서 api 2개를 만들었다.

  • /api/v1/test
  • /api/v1/accept

 

test는 처음에 테스트를 한 이후 feign을 붙여 accept라는 api를 feign으로 연결한 api였다.

이렇게 해서 테스트 준비가 끝났다.

 

테스트를 만들고 호출 했을 때 accept-language 를 en-US 로 가지게끔 설정해주고, 호출을 하게되면

feign 자체에서 Spring framework 가 가지는 

  • GenericConversionService
  • FormattingConversionService
  • TemporalAccessParser
  • ConversionUtils

같은 클래스들을 사용하게 된다.

컨버터와 포매터를 사용하여 spring 에서는 String으로 변환해서 주고받는 구조로 만들어 주는데,

feign에서 String을 -> LocalDate 파싱할 때 en-US 라고 accept-language에서 locale을 설정하게 되면 이제 us 양식인 localDate 값인 dd/MM/yy 형식으로 변환이 되어 request에 저 형식 String으로 전달되게 된다.

 

그래서 Request를 이제 파싱하게 되는 Controller에 들어가기 이전에 RequestParam 이 넘어온 값을 LocalDate로 핸들링 해주어야 되는데 이미 변경된 String 값과 Locale값으로 인해 정상적인 파싱을 하지 못하고 에러가 나는 것을 볼 수 있다.

 

해결법

  1. Spring 에서 제공하는 컨버터를 사용해서 구현한다.
  2. 전역적으로 Locale을 설정한다.

나는 회사에 LocaleResolver를 구현하니 정상 동작한다고 공유했었다!

@Bean
fun localeResolver(): LocaleResolver {
    return FixedLocaleResolver(Locale.KOREA)
}

 

이렇게 구현하게 되면 받아서 파싱까지 잘 되는걸 확인할 수 있었다.

728x90
반응형

'디버깅' 카테고리의 다른 글

Kafka가 내 로직을 9번이나 재시도를 했다  (0) 2023.11.02
Stream 오류 제거  (2) 2023.04.21
@Transactional 제대로 알고쓰기  (6) 2023.02.27
FeignClient Logging level 디버깅  (0) 2022.12.17

+ Recent posts