티스토리 뷰

(변경에 유연한 코드 설계 | 프리온보딩 BE 챌린지 9월)을 참여하면서 겪었던 에러를 정리한 포스팅입니다.

 

변경에 유연한 코드 설계 | 프리온보딩 BE 챌린지 9월 | 원티드

무료로 양질의 교육을 들어보세요! 챌린저만을 위한 다양한 혜택을 제공해드리고 있습니다.

www.wanted.co.kr

개발 환경은 다음과 같습니다.

  • 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 사이에 데이터를 주고받을 때 스프링 내부에서는 어떻게 동작하는지 깊게 공부해볼 필요가 있겠습니다.

다음 포스팅에서는 프리온보딩에서 들은 강의에 대한 주제로 찾아뵙겠습니다.

읽어주셔서 감사합니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
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
글 보관함