๐Ÿ“š[Spring] ExtendedScheduler ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…_1

ํ…ํ…ยท2025๋…„ 5์›” 25์ผ

๋กœ๊ทธ์ธ ํ•„ํ„ฐ ์ง๋ ฌํ™” ๋ฌธ์ œ

๋ฌธ์ œ์ƒํ™ฉ - 1

๋กœ๊ทธ์ธ์ด ์•ˆ๋œ ์ƒํƒœ์—์„œ API ํ˜ธ์ถœ ์‹œ ๋กœ๊ทธ์ธ ํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด ErrorResponse ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
ํ•˜์ง€๋งŒ ํ•ด๋‹น ์‘๋‹ต ๊ฐ์ฒด์—์„œ LocalDateTime ์ง๋ ฌํ™” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค.

  • ์—๋Ÿฌ๋ฉ”์„ธ์ง€
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type `java.time.LocalDateTime` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: com.example.extendedscheduler.common.dto.ErrorResponse["timestamp"])

๋ฌธ์ œ ๋ฐœ์ƒ ์ฝ”๋“œ

  • LoginFilter ๋‚ด๋ถ€
...
ObjectMapper ob = new ObjectMapper();
...
httpResponse.getWriter().write(ob.writeValueAsString(new ErrorResponse("๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
, HttpStatus.UNAUTHORIZED.value())));
...

์‘๋‹ต์— ErrorResponse ๊ฐ์ฒด๋ฅผ ๋‹ด๊ณ  ์‹ถ์–ด ObjectMapper ๋ฅผ ์ƒ์„ฑํ–ˆ๋‹ค.

  • ErrorResponse
//์—๋Ÿฌ ์‘๋‹ต๊ฐ์ฒด
@Getter
public class ErrorResponse {
    private String message;
    private int status;
    private LocalDateTime timestamp;
    
    public ErrorResponse(String message, int status) {
        this.message = message;
        this.status = status;
        this.timestamp = LocalDateTime.now();
    }
}

ErroResponse ์˜ timestamp ํ•„๋“œ๋Š” LocalDateTime.now() ๋ฅผ ํ†ตํ•ด ์ดˆ๊ธฐํ™”๋œ๋‹ค.


๋ฌธ์ œ ์›์ธ

LocalDateTime ํƒ€์ž…์€ Jackson ๊ธฐ๋ณธ ์„ค์ •์—์„  ์ง๋ ฌํ™”๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜์—ฌ jackson-datatype-jsr310 ๋ชจ๋“ˆ์„ ๋ฐ˜๋“œ์‹œ ๋“ฑ๋กํ•ด์ค˜์•ผ ํ•œ๋‹ค.
๊ธฐ๋ณธ์ ์œผ๋กœ Spring Boot๋Š” ObjectMapper์— ํ•ด๋‹น ๋ชจ๋“ˆ์„ ํฌํ•จํ•˜์—ฌ ๊ด€๋ฆฌํ•˜๊ธฐ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์ง€๋งŒ new ObjectMapper()๋กœ ์ง์ ‘ ์ƒ์„ฑํ•œ ์ธ์Šคํ„ด์Šค์—๋Š” ์Šคํ”„๋ง ์„ค์ •์ด ๋ฐ˜์˜๋˜์ง€ ์•Š์•„ ํ•ด๋‹น ๋ชจ๋“ˆ์ด ์ž๋™์œผ๋กœ ๋“ฑ๋ก๋˜์ง€ ์•Š๋Š”๋‹ค.


ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

...
ObjectMapper ob = new ObjectMapper();
ob.registerModule(new JavaTimeModule());

JavaTimeModule ์„ ์ง์ ‘ ๋“ฑ๋กํ•ด์ฃผ๋ฉด LocalDateTime ์ง๋ ฌํ™” ์—๋Ÿฌ๋Š” ํ•ด๊ฒฐ๋œ๋‹ค.


๋ฌธ์ œ์ƒํ™ฉ - 2: ๋‚ ์งœ ํฌ๋งท์ด ๋ฐฐ์—ด๋กœ ์ถœ๋ ฅ

  • ์‘๋‹ต์˜ˆ์‹œ
{
  "message": "๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.",
  "status": 401,
  "timestamp": [
    2025,
    5,
    25,
    23,
    42,
    35,
    495226700
  ]
}

๋ฌธ์ œ๋Š” ํ•ด๊ฒฐ๋์ง€๋งŒ timestamp๊ฐ€ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ISO-8601 ํฌ๋งท์ด ์•„๋‹Œ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์ถœ๋ ฅ๋œ๋‹ค.


ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

...
ObjectMapper ob = new ObjectMapper();
ob.registerModule(new JavaTimeModule());
ob.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

WRITE_DATES_AS_TIMESTAMPS๊ฐ€ ํ™œ์„ฑํ™”๋ผ ์žˆ์œผ๋ฉด ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ JSON์— ํ‘œํ˜„๋œ๋‹ค.
๋”ฐ๋ผ์„œ ํ•ด๋‹น ์„ค์ •์„ ๋„๋ฉด ์ผ๋ฐ˜์ ์ธ ๋‚ ์งœ ํฌ๋งท์œผ๋กœ ๋‚˜์˜ค๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์„ค์ •์„ ๋„๊ณ  ๋ฐ›์€ ์‘๋‹ต
{
    "message": "๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.",
    "status": 401,
    "timestamp": "2025-05-26T00:55:06.7293507"
}

๋งˆ์น˜๋ฉฐ

์ฒ˜์Œ ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ErrorResponse๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋‹จ์ˆœํžˆ ์˜ˆ์™ธ๋งŒ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•๋„ ๊ณ ๋ คํ–ˆ์ง€๋งŒ
๊ณตํ†ต์ ์ธ ์‘๋‹ต ํฌ๋งท์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ ๋ฐฉํ–ฅ์ด๋ผ๊ณ  ํŒ๋‹จํ–ˆ๋‹ค.
๊ฒฐ๊ตญ ๊ตฌ์กฐ๋ฅผ ํฌ๊ฒŒ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  Jackson ์„ค์ •๋งŒ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์–ด ๋‹คํ–‰์ด์—ˆ๋‹ค.

profile
์ฐจ๊ทผ์ฐจ๊ทผ

0๊ฐœ์˜ ๋Œ“๊ธ€