IT/development

[springBoot] ์œ ํšจ์„ฑ ๊ฒ€์ฆ(feat. @Valid, Validated)

์•Œ ์ˆ˜ ์—†๋Š” ์‚ฌ์šฉ์ž 2022. 11. 22.

๋ชฉ์ฐจ

     

    SpringBoot ์œ ํšจ์„ฑ ๊ฒ€์ฆ ๐Ÿ˜„

    ํด๋ผ์ด์–ธํŠธ์—์„œ ๋„˜์–ด์˜จ ๊ฐ’๋“ค์— ๋Œ€ํ•œ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์ด ํ•„์š”ํ•œ๋ฐ if(id != null || id != ""...) ์ด๋ ‡๊ฒŒ if๋ฌธ์œผ๋กœ ์œ ํšจ์„ฑ ์ฒดํฌ๋ฅผ ํ•˜๊ธฐ ์‹ซ์–ด์„œ ์ž๋ฐ”๋‚˜ ์Šคํ”„๋ง์—์„œ ์ง€์›ํ•˜๋Š” ์ข‹์€๊ฒŒ ์–ด๋”” ์—†๋‚˜ ๋ณด๋‹ค๊ฐ€ ๊ตฌ๊ธ€๋ง์„ ํ•˜๊ณ  @Valid์™€ @Validated๋ฅผ ์•Œ๊ฒŒ๋˜์–ด์„œ ์ ์šฉ์„ ํ•ด๋ดค๊ณ  ์ด๋ฅผ ๊ธฐ๋กํ•œ๋‹ค.

     

    ๋‚œ "", " ", null ์ด๋ ‡๊ฒŒ 3๊ฐœ๋งŒ ์ฒดํฌํ•˜๋ฉด ๋˜๋Š” ๋ถ€๋ถ„์ด์—ˆ๋‹ค. 

     

    ๊ฒฐ๋ก ์€ ์Šคํ”„๋ง๋ถ€ํŠธ์—์„  @Valid์™€ @Validated 2๊ฐœ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ„๋‹จํ•œ ์œ ํšจ์„ฑ ์ฒดํฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Œ

     

    @Valid ๐Ÿฅฐ

    @Valid๋Š” JSR-303 Bean Validator๋ฅผ ์ด์šฉํ•ด์„œ ์œ ํšจ์„ฑ์„ ์ฒดํฌํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ž„(์ž๋ฐ” ํ‘œ์ค€ ์ŠคํŽ™)

     

    ์‚ฌ์šฉ๋ฒ•

    ์Šคํ”„๋ง๋ถ€ํŠธ ๋ฒ„์ „์— ๋”ฐ๋ฅธ ์˜์กด์„ฑ ์ถ”๊ฐ€

    ์‚ฌ์šฉํ•˜๋Š” ์Šคํ”„๋ง ๋ถ€ํŠธ ๋ฒ„์ „์ด 2.3์ด์ „๋ฒ„์ „์ด๋ผ๋ฉด spring-boot-starter-web ์˜์กด์„ฑ์— ํฌํ•จ๋˜์–ด ์žˆ์–ด์„œ ๊ตณ์ด ํ•„์š”์—†์Œ, ๋‚˜๋Š” ํ˜„์žฌ ์—…๋ฌด ์‹œ 2.0๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด์„œ ์˜์กด์„ฑ์€ ๋”ฐ๋กœ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•˜๋‹ค.

    https://stackoverflow.com/questions/61959918/spring-boot-validations-stopped-working-after-upgrade-from-2-2-5-to-2-3-0

     

    Spring Boot - Validations stopped working after upgrade from 2.2.5 to 2.3.0

    I've migrated a Spring Boot project from 2.2.5 to 2.3.0 and after that, Validations stopped to work (they aren't invoked at all). I read in changelog documentation (https://github.com/spring-proje...

    stackoverflow.com

     

    ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์œ ํšจ์„ฑ ์ฒดํฌ๋ฅผ ํ•  ๊ฒƒ์ด๊ธฐ์— parameter๊ฐ’์œผ๋กœ ๋ฐ›๋Š” ๊ฐ์ฒด์— @Valid ์–ด๋…ธํ…Œ์ด์…˜ ์ถ”๊ฐ€

    @Valid๋Š” ์ปจํŠธ๋กค๋Ÿฌ์—์„œ๋งŒ ๊ฒ€์ฆ ๊ฐ€๋Šฅ(ArgumentResolver์—์„œ ์ฒ˜๋ฆฌ), ๋งŒ์ผ ๋‹ค๋ฅธ ์„œ๋น„์Šค๋‹จ ๊ฐ™์€ ๊ณณ์—์„œ ์‚ฌ์šฉํ•˜๋ ค๋ฉด @Validated ์‚ฌ์šฉ

     

    Controller(RestController)

    @PostMapping("")
    public ResponseEntity<?> insertUser(@RequestBody @Valid MemberVO memberVO) throws Exception {
        Map<String, Object> resultMap = new HashMap<String, Object>();
    
        try {   
            userService.insertUser(memberVO);
            resultMap.put("result", "success");
            return new ResponseEntity<>(resultMap, HttpStatus.OK);
        } catch (Exception e) {
            resultMap.put("result", "fail");
            return new ResponseEntity<>(resultMap, HttpStatus.BAD_REQUEST);
        }
    }

     

    MemberVO

    ์œ ํšจ์„ฑ ์ฒดํฌํ•  ํ•„๋“œ์— @NotNull, NotEmppty ๋“ฑ์˜ JSR ํ‘œ์ค€ ์ŠคํŽ™์—์„œ ์ œ๊ณตํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์„ ์ ์šฉํ•œ๋‹ค.

    package com.lsy.test;
    
    import lombok.Getter;
    import lombok.Setter;
    import lombok.ToString;
    
    import javax.validation.constraints.NotBlank;
    import javax.validation.constraints.NotNull;
    
    @Getter
    @ToString
    public class MemberVO {
        // ๋ฒˆํ˜ธ
        // default message ์„ค์ • ๊ฐ€๋Šฅ
        @NotNull(message = "์ผ๋ จ๋ฒˆํ˜ธ๋Š” ํ•„์ˆ˜๊ฐ’์ž…๋‹ˆ๋‹ค.") // null๋งŒ ๋ถˆ๊ฐ€("", " " ๊ฐ€๋Šฅ)
        private Long no;
        // ์•„์ด๋””
        @NotBlank(message = "์•„์ด๋””๋Š” ํ•„์ˆ˜๊ฐ’์ž…๋‹ˆ๋‹ค.")	// null, "", " " ๋ถˆ๊ฐ€
        private String id;
        // ์ด๋ฆ„
        @NotBlank(message = "์ด๋ฆ„์€ ํ•„์ˆ˜๊ฐ’์ž…๋‹ˆ๋‹ค.")
        private String name;
    }

     

     

    ํ…Œ์ŠคํŠธ

    ํ™”๋ฉด์—์„œ๋Š” JSON ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•œ๋‹ค. ์•„๋ž˜์ฒ˜๋Ÿผ ์ผ๋ถ€๋Ÿฌ ์•„์ด๋””๋ฅผ ๋นˆ๊ฐ’์œผ๋กœ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋ณด๊ฒ ๋‹ค.

    {
      "no": 10,
      "id": "",
      "name": "bbbb"
    }

     

    ์„œ๋ฒ„์—์„œ๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ Exception(MethodArgumentNotValidException)์ด ๋ฐœ์ƒํ–ˆ๋‹ค.

    default message์—๋Š” VO๊ฐ์ฒด์— ๋‚ด๊ฐ€ ์•„๊นŒ ์ž…๋ ฅํ•œ ๊ธฐ๋ณธ ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋˜์—ˆ๋‹ค.

     


     

    @Validated ๐Ÿฅฐ

    @Validated๋Š” ์Šคํ”„๋ง์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

    ๋งŒ์ผ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์‚ฌ์šฉ ์‹œ ์•„๋ž˜์ฒ˜๋Ÿผ ๊ฒ€์ฆํ•  ๊ฐ์ฒด์•ž์— @Validated๋ฅผ ๋ถ™์ด๋ฉด ๋œ๋‹ค.

    @PostMapping("")
    public ResponseEntity<?> insertUser(@RequestBody @Validated MemberVO memberVO) throws Exception {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        ๋‚˜๋จธ์ง€ ์ƒ๋žต...
    }

    @Valid๋Š” ๊ฐ์ฒด ์ „์ฒด์— ๋Œ€ํ•ด ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•˜๊ณ  @Validated๋Š” ๊ทธ๋ฃน์„ ๋งŒ๋“ค์–ด์„œ ์›ํ•˜๋Š” ์š”์†Œ๋งŒ ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๊ณ 

    ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์•„๋‹Œ ๊ณณ์—์„œ๋„ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์„ ํ•  ์ˆ˜ ์žˆ๊ณ  ์˜ˆ์™ธ๋„ ConstraintViolationException์ด ๋ฐœ์ƒํ•œ๋‹ค.

     

    ์ฐธ์กฐํ•œ ๋ธ”๋กœ๊ทธ์— ๊ฐ€๋ฉด ๋™์ž‘์›๋ฆฌ์™€ ๋” ์ž์„ธํ•œ ๋‚ด์šฉ์ด ๋‚˜์™€์žˆ๋‹ค.

     

     

    ์ฐธ์กฐ : ๋ง๋‚˜๋‹ˆ๊ฐœ๋ฐœ์ž๋‹˜ ๋ธ”๋กœ๊ทธ, 2021.7.19, https://mangkyu.tistory.com/174

     

    [Spring] @Valid์™€ @Validated๋ฅผ ์ด์šฉํ•œ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์˜ ๋™์ž‘ ์›๋ฆฌ ๋ฐ ์‚ฌ์šฉ๋ฒ• ์˜ˆ์‹œ - (1/2)

    Spring์œผ๋กœ ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด DTO ๋˜๋Š” ๊ฐ์ฒด๋ฅผ ๊ฒ€์ฆํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ณ„๋„์˜ ๊ฒ€์ฆ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ฐ„๋‹จํ•œ ๊ฒ€์ฆ์˜ ๊ฒฝ์šฐ์—๋Š” JSR ํ‘œ์ค€์„ ์ด์šฉํ•ด ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜

    mangkyu.tistory.com

    ๋Œ“๊ธ€