[Project] ConstraintViolationError NPE ๋ฐœ์ƒ

Updated:

Categories:

Tags: ,

๐Ÿ“Œ ๊ฐœ์ธ์ ์ธ ๊ณต๊ฐ„์œผ๋กœ ๊ณต๋ถ€๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ๋ณต์Šตํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๋ธ”๋กœ๊ทธ์ž…๋‹ˆ๋‹ค.
์ •ํ™•ํ•˜์ง€ ์•Š์€ ์ •๋ณด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ ๋ฐ”๋ž๋‹ˆ๋‹ค :๐Ÿ˜ธ
[ํ‹€๋ฆฐ ๋‚ด์šฉ์€ ๋Œ“๊ธ€๋กœ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด ๋ณต๋ฐ›์œผ์‹ค๊ฑฐ์—์š”]


null ๊ฐ’์ด ๋“ค์–ด์˜ค๋Š” ์ƒํ™ฉ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ConstraintViolationError ํด๋ž˜์Šค์—์„œ null์„ "null" ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•ด ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€์— ํฌํ•จ์‹œํ‚ค๋„๋ก ์ฝ”๋“œ ์ˆ˜์ •. ์ด๋ฅผ ํ†ตํ•ด NullPointerException ๋ฐœ์ƒ์„ ๋ฐฉ์ง€ํ•˜๊ณ , ์˜๋ฏธ ์žˆ๋Š” ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

์˜ˆ์™ธ ์ฒ˜๋ฆฌ ์‹œ ConstraintViolationError ์ˆ˜์ •ํ•˜๊ธฐ: NullPointerException ํ•ด๊ฒฐ ๊ณผ์ •

ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ ์ค‘, checkbox๋กœ ํ•œ๋ฒˆ์— ์ˆ˜์ • ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ Dto๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์žˆ์—ˆ๋‹ค. PATCH ์š”์ฒญ์œผ๋กœ List๋กœ ๋ณด๋‚ผ ๋•Œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ์ˆ˜์ •๋˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ PATCH ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค๋Š” ๊ฒƒ์ด POST ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ์‹ค์ˆ˜๋ฅผ ํ–ˆ๊ณ , ๊ทธ๋กœ ์ธํ•ด ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

์•ˆ๊ทธ๋ž˜๋„ ๋ฐœ์ƒํ•˜๋Š” ์ƒํƒœ์ฝ”๋“œ 500๋ฒˆ ์—๋Ÿฌ๋Š” ๋‹ค ์žก๊ณ  ์‹ถ์–ด์„œ ์ž˜๋˜์—ˆ๋‹ค ์ƒ๊ฐํ•˜๊ณ  ๋””๋ฒ„๊น…์„ ์ง„ํ–‰ํ•œ ๊ฒฐ๊ณผ, ๋‹น์—ฐํžˆ postDto ์— ํ•„์š”ํ•œ ํ•„๋“œ๊ฐ€ ์—†์–ด์„œ ๋ฐœ์ƒํ•œ ๋ฌธ์ œ ์˜€๋‹ค.

๊ทผ๋ฐ ๋‹น์—ฐํžˆ dto๋Š” @Valid ์• ๋„ˆํ…Œ์ด์…˜์œผ๋กœ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์„ ํ•ด์„œ ์—ฌ๊ธฐ์„œ ์˜ˆ์™ธ๋ฅผ ์žก์•„์ค„ ๊ฒƒ ๊ฐ™์€๋ฐ ์™œ ์•ˆ์žก์•„์ฃผ์ง€? ๋ผ๊ณ  ์ƒ๊ฐ์ด ๋“ค์–ด์„œ ์„ค๋งˆ @Valid ๋‚˜ @Validated๊ฐ€ ์—†๋Š” ๊ฑธ๊นŒ ํ•˜๊ณ  ์ƒ๊ฐํ•˜๊ณ  ํ™•์ธํ•ด๋ดค๋Š”๋ฐ ๊ทธ ๋ฌธ์ œ๋Š” ์•„๋‹ˆ์˜€๋‹ค.

์˜ˆ์™ธ ๋ฐœ์ƒ ์‹œ ์ƒ๊ธฐ๋Š” ๋ฉ”์„ธ์ง€๋ฅผ ๋‹ค์‹œ ์ฝ์–ด๋ณด๋‹ˆ ConstraintViolation.getInvalidValue() ์ด null๋กœ ๋“ค์–ด์™€์„œ ์ƒ๊ธด ๋ฌธ์ œ์ž„์„ ํ™•์ธํ–ˆ๋‹ค.

๋ฐœ์ƒํ•œ ๋ฌธ์ œ์ : NullPointerException๊ณผ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

  • ์ฆ‰ Exception ํด๋ž˜์Šค์—์„œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋˜ ์ค‘ Value๊ฐ€ null๋กœ ๋“ค์–ด์˜ค๋ฉด์„œ ๋ฐœ์ƒํ•œ ๊ฒƒ
  • ๋ฌธ์ œ๋Š” ConstraintViolation.getInvalidValue()๊ฐ€ null ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒฝ์šฐ, ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•ด NullPointerException์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค. ์ด๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด, null์ด ๋“ค์–ด์˜ค๋Š” ์ƒํ™ฉ์—์„œ๋„ ์ ์ ˆํ•œ ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•œ๋‹ค.
  • ๋‹ค์‹œ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ postDto๋„ List๋กœ ๋“ค์–ด์˜ค๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์กด์—๋Š” List๊ฐ€ ์•„๋‹ˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์žก์•„์คฌ๋˜ ์˜ˆ์™ธ๋ฅผ ๋ณ€๊ฒฝ๋˜๊ณ  ๋‚˜์„œ๋Š” ๋ชป์žก๋Š” ๊ฒƒ ๊ฐ™์•˜๋‹ค.

๋ฌธ์ œ ํ•ด๊ฒฐ : ConstraintViolationError ํด๋ž˜์Šค ์ˆ˜์ •

์šฐ์„  ErrorResponse ๋‚ด์˜ ConstraintViolationError ํด๋ž˜์Šค๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ, null์ด ๋ฐœ์ƒํ•  ๊ฒฝ์šฐ์—๋„ ์•ˆ์ „ํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด getInvalidValue()๊ฐ€ null์ผ ๋•Œ๋Š” ์ด๋ฅผ ๋ฌธ์ž์—ด "null"๋กœ ๋ณ€ํ™˜ํ•ด ๋ฐ˜ํ™˜ํ•˜๋„๋ก ์ˆ˜์ •ํ–ˆ๋‹ค.

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
@Getter
public static class ConstraintViolationError {
    private String propertyPath;
    private String rejectedValue;  // Use String to handle null gracefully
    private String reason;

    private ConstraintViolationError(String propertyPath, String rejectedValue, String reason) {
        this.propertyPath = propertyPath;
        this.rejectedValue = rejectedValue;
        this.reason = reason;
    }

    public static List<ConstraintViolationError> of(
            Set<ConstraintViolation<?>> constraintViolations) {
        return constraintViolations.stream()
                .map(constraintViolation -> {
                // ์ˆ˜์ •ํ•œ ๋ถ€๋ถ„
                    String invalidValue = (constraintViolation.getInvalidValue() == null)
                            ? "null" // Handle null safely
                            : constraintViolation.getInvalidValue().toString(); // Convert null values to "null"
                            
                           //์—ฌ๊ธฐ๊นŒ์ง€
                    return new ConstraintViolationError(
                            constraintViolation.getPropertyPath().toString(),
                            invalidValue,
                            constraintViolation.getMessage()
                    );
                }).collect(Collectors.toList());
    }
}
  • getInvalidValue()์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ’์ด null์ผ ๊ฒฝ์šฐ, ์ด๋ฅผ "null" ๋ฌธ์ž์—ด๋กœ ์ฒ˜๋ฆฌํ–ˆ๊ณ  ์ด๋กœ ์ธํ•ด NullPointerException์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ  ์˜๋ฏธ ์žˆ๋Š” ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.
  • ์ด์ „์—๋Š” null ๊ฐ’์œผ๋กœ ์ธํ•ด ์˜ˆ์™ธ ๋ฉ”์‹œ์ง€๊ฐ€ ์ œ๋Œ€๋กœ ์ „๋‹ฌ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ์ด์ œ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ "null"์ด๋ผ๋Š” ๋ฌธ์ž์—ด์ด ๋ฉ”์‹œ์ง€๋กœ ์ „๋‹ฌ๋˜์–ด ์˜ˆ์™ธ ์ƒํ™ฉ์„ ๋ช…ํ™•ํžˆ ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.
  • null ๊ฐ’์ด ๋ฐ˜ํ™˜๋˜๋”๋ผ๋„ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ๋ฐ˜ํ™˜๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ฝ”๋“œ์˜ ์œ ์—ฐ์„ฑ๊ณผ ์•ˆ์ •์„ฑ์ด ํ–ฅ์ƒ๋˜์—ˆ๋‹ค. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ๋” ์œ ์—ฐํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๊ณ , ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ์˜ˆ์™ธ ์ƒํ™ฉ์—์„œ๋„ ์‰ฝ๊ฒŒ ๋ฌธ์ œ๋ฅผ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ตฟ๊ตฟ

ํ•ด๊ฒฐ

์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ์„ ํ†ตํ•ด ConstraintViolation.getInvalidValue()์—์„œ null ๊ฐ’์ด ๋ฐ˜ํ™˜๋  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” NullPointerException์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋กœ์ง์„ ์ˆ˜์ •ํ•จ์œผ๋กœ์จ, ๋” ์•ˆ์ •์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์œผ๋ฉฐ, null ๊ฐ’ ์ฒ˜๋ฆฌ ์‹œ์—๋„ ์˜๋ฏธ ์žˆ๋Š” ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐœ์„ ํ–ˆ๋‹ค.

์ด๋ฒˆ ๋ฌธ์ œ ํ•ด๊ฒฐ ๊ณผ์ •์€ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ ์ƒํ™ฉ์„ ๋” ์œ ์—ฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๊ณ ๋ฏผํ•  ๊ธฐํšŒ๊ฐ€ ๋˜์—ˆ๊ณ , ์ด๋ฅผ ํ†ตํ•ด ์‹ค์ˆ˜๋ฅผ ์ค„์ด๊ณ  ์˜ˆ์™ธ ์ƒํ™ฉ์—์„œ ๋” ๋‚˜์€ ๋ฉ”์‹œ์ง€๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

Project ์นดํ…Œ๊ณ ๋ฆฌ ๋‚ด ๋‹ค๋ฅธ ๊ธ€ ๋ณด๋Ÿฌ๊ฐ€๊ธฐ

Leave a comment