티스토리 뷰
(변경에 유연한 코드 설계 | 프리온보딩 BE 챌린지 9월)을 참여하면서 겪었던 에러를 정리한 포스팅입니다.
개발 환경은 다음과 같습니다.
- Spring Boot Version : 3.1.2
- Java Version : 17
다음은 관련 코드 소스입니다.
https://github.com/kkoon9/wanted-preonboarding-challenge-backend-13/tree/feature/kkoon9
배경
RequestBody에 들어가는 정보는 다음과 같습니다.
- amount : 관람객이 가진 돈
- when : 초대권을 받았다면 초대권을 받은 날짜
controller 코드입니다.
package com.wanted.preonboarding.theater.controller;
import com.wanted.preonboarding.theater.controller.dto.AudienceRequest;
import com.wanted.preonboarding.theater.service.TheaterService;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
@RequestMapping("/theater")
@RequiredArgsConstructor
@Log4j2
public class TheaterController {
private final TheaterService theaterService;
@PostMapping("/enter")
public String enter(
@RequestBody AudienceRequest request
){
log.info(request.toString());
return theaterService.enter(request);
}
}
AudienceRequest 코드입니다.
package com.wanted.preonboarding.theater.controller.dto;
import com.wanted.preonboarding.theater.service.handler.Audience;
import com.wanted.preonboarding.theater.service.handler.Bag;
import com.wanted.preonboarding.theater.service.handler.Invitation;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.time.LocalDateTime;
@NoArgsConstructor
@ToString
@Getter
public class AudienceRequest {
private Long amount;
private LocalDateTime when;
public Audience toAudience() {
return new Audience(
new Bag(
this.when == null ? null : new Invitation(this.when),
this.amount
)
);
}
}
에러 상황
enter API를 호출하면 다음과 같은 에러가 발생합니다.
에러 메시지를 잘 살펴보면 다음과 같은 내용이 있습니다.
Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2023-05-23 10:00:00' could not be parsed at index 10]
when 값의 10번째 index에서 파싱이 실패했다는 내용입니다.
timestamp 값을 잘 보면 YYYY-MM-DDTHH:mm:ss 형태인걸 알 수 있습니다.
즉, when의 데이터 형태가 잘못됐다는 이야기입니다.
실제로, timestamp와 동일한 형태의 값을 전달하면 에러가 발생하지 않는다는걸 알 수 있습니다.
YYYY-MM-DD HH:mm:ss 형태로 보내고 싶다.
처음 시도했던 형태로 개발을 하고 싶을 수 있습니다.
이럴 때에는 JsonFormat 어노테이션을 사용해서 내가 주고 싶은 형태를 명시해주면 됩니다.
package com.wanted.preonboarding.theater.controller.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.wanted.preonboarding.theater.service.handler.Audience;
import com.wanted.preonboarding.theater.service.handler.Bag;
import com.wanted.preonboarding.theater.service.handler.Invitation;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.time.LocalDateTime;
@NoArgsConstructor
@ToString
@Getter
public class AudienceRequest {
private Long amount;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime when;
public Audience toAudience() {
return new Audience(
new Bag(
this.when == null ? null : new Invitation(this.when),
this.amount
)
);
}
}
Custom Deserializer을 만드셨다는 분 블로그도 있어서 링크 첨부합니다.
https://perfectacle.github.io/2018/01/15/jackson-local-date-time-deserialize/
결론
이러한 에러는 원인을 모르면 많은 시간이 뺏길수도 있다고 느꼈습니다.
현업에서도 만난 적 있었지만, 코드를 직접 타이핑해보면서 개발해서 마주칠 수 있었습니다.
덕분에 블로그에 정리할 수 있었네요.
client와 server 사이에 데이터를 주고받을 때 스프링 내부에서는 어떻게 동작하는지 깊게 공부해볼 필요가 있겠습니다.
다음 포스팅에서는 프리온보딩에서 들은 강의에 대한 주제로 찾아뵙겠습니다.
읽어주셔서 감사합니다.
'개발 노트' 카테고리의 다른 글
git push한 commit 취소하기 (0) | 2023.09.01 |
---|---|
[스프링] yaml 파일 하나로 스프링 환경변수 관리하기 (0) | 2023.09.01 |
[스프링+코틀린] kotest로 리팩터링 내성 파악하기 (0) | 2023.08.20 |
git merge 옵션 squash (0) | 2023.08.10 |
intellij에서 git 커밋 순서 바꾸기 (0) | 2023.08.02 |
- Total
- Today
- Yesterday
- 디자인패턴
- Effective Java
- C++
- programmers
- 이펙티브 자바
- 디자인 패턴
- 코테
- Kotlin
- Olympiad
- node.js
- 이팩티브 자바
- 클린 아키텍처
- MSA
- kkoon9
- BAEKJOON
- Spring Boot
- 프로그래머스
- 클린 코드
- kotest
- Java
- AWS
- BOJ
- Algorithm
- 알고리즘
- Spring
- 정규표현식
- JPA
- 백준
- 객체지향
- 테라폼
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |