에러 발생
외부 API를 이용해서 데이터를 받아오는 로직을 추가하고 있었다.
API Response Body DTO를 작성해서 RestTemplate을 이용하여 API 요청을 하고 응답을 받았는데 DTO로 Parsing 하던 중 에러가 발생했다.
Caused by: org.springframework.web.client.RestClientException: Error while extracting response for type [-] and content type [application/json;charset=UTF-8]
해결 과정
해당 에러를 검색해보니 자료가 좀 있었는데, 나랑은 상황이 좀 다른 글들이 많았다. (e.g. PutMapping
을 PostMapping
으로 바꾸니까 해결)
아마 이 에러가 포함하고 있는 에러 상황이 포괄적인듯하다.
하지만 나는 JSON을 Class로 deserialize 하던 과정에서 에러가 발생했다고 거의 확신했기 때문에 디버깅을 하였다.
어느 property를 parsing할 때 에러가 발생하는지 알아야 했기 때문이다. (DTO의 property가 많아서 거의 150줄이었다.)
RestTemplate.exchange
→ RestTemplate.execute
→ RestTemplate.doExecute
→ RestTemplate.extractData
→ HttpMessageConverterExtractor.extractData
→ AbstractJackson2HttpMessageConverter.read
→ AbstractJackson2HttpMessageConverter.readJavaType
→ ObjectReader.readValue
→ ObjectReader._bindAndClose
→ DefaultDeserializationContext.readRootValue
→ BeanDeserializer.deserialize
→ BeanDeserializer.deserializeFromObject
→ FieldProperty.deserializeAndSet
→ CollectionDeserializer._deserializeFromArray
→ DateDeserializers._parseDate
→ StdDeserializer._parseDate
→ DeserializationContext.parseDate
→ StdDateFormat.parse
대략 이런 식으로 parsing 과정을 타고 타고 들어가서 어느 property에서 에러가 발생하는지 확인할 수 있었다.
실제로는 저렇게 깊게 들어가진 않았고 날짜를 parsing할 때 에러가 발생한다는 것 까지만 파악 후 관련 내용을 검색했다.
API 응답으로 들어온 날짜 형식의 문자열 값인 2024-01-04 16:52:22
을 Java의 Date 형식으로 만들어줄 때 에러가 발생했다.
Java의 기본적인 date formatter랑 형식이 일치하지 않는 것 같다.
그리고 생각해보니 어느정도 당연한 에러라고 생각했다. 막연히 Framework에서 알아서 Date로 변환해줄 거라고 생각을 했는데 각 API 응답마다 보내주는 date string 형식이 충분히 다를 수 있고 그걸 다 알아서 변환해 줄 수는 없는게 당연하다고 느꼈다.
그래서 Spring Boot RestTemplate Date Format
으로 검색해보니 뭔가 document 사이트 같은 곳이 있어서 그곳을 참고했다.
@JsonFormat
Annotation을 활용해서 Date String이 어떤 형식으로 들어올 것인지 미리 지정해 줄 수 있다.
@JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss")
Date registerDate;
그리고 나는 저렇게 적용했을 때 parsing은 에러 없이 잘 진행되었지만 Date의 시간이 다르게 나왔다.
9시간 차이나는 것으로 보아 타임존 문제로 추측하고 timezone
설정도 찾아서 적용했다.
@JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss", timezone = "Asia/Seoul")
Date registerDate;
이렇게 재밌고 눈이 아픈 디버깅 시간을 통해 DTO의 수많은 property를 일일이 확인해보지 않고 빠르게 해결할 수 있었다.