๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Spring

Spring Validation - @NotNull, @NotEmpty, @NotBlank

by ์ฃผ๋ฐœ2 2021. 9. 9.
๋ฐ˜์‘ํ˜•

๐Ÿ“Ž Spring Validation - @NotNull, @NotEmpty, @NotBlank

์•ˆ๋…•ํ•˜์„ธ์š”, ์ด๋ฒˆ ์‹œ๊ฐ„์— ์ •๋ฆฌํ•  ๋‚ด์šฉ์€ spring-boot-starter-validation์˜ @NotNull, @NotEmpty, @NotBlank ์–ด๋…ธํ…Œ์ด์…˜ ์ž…๋‹ˆ๋‹ค. ํ‰์†Œ ๋„๋ฉ”์ธ ํด๋ž˜์Šค์— ์ œ์•ฝ ์กฐ๊ฑด์œผ๋กœ Validation์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ์œ„ ์–ด๋…ธํ…Œ์ด์…˜๋“ค์€ ์ด๋ฆ„๋งŒ ๋ด์„œ๋Š” ๋น„์Šทํ•œ ์—ญํ• ์„ ํ•  ๊ฒƒ ๊ฐ™์€๋ฐ ์ •ํ™•ํžˆ ๋ฌด์—‡์ด ๋‹ค๋ฅธ์ง€ ๊ถ๊ธˆํ•ด์„œ ํฌ์ŠคํŒ…์„ ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿค”

์•„๋ž˜ ์˜ˆ์ œ์˜ ์ฝ”๋“œ๋Š” ๊นƒํ—ˆ๋ธŒ์—์„œ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค :)

 

 

 

์˜์กด์„ฑ ์ถ”๊ฐ€ - Maven

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-validation -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>2.5.4</version>
</dependency>

 

์˜์กด์„ฑ ์ถ”๊ฐ€ - Gradle

implementation 'org.springframework.boot:spring-boot-starter-validation'

 

 

 

@NotNull


@NotNull ์–ด๋…ธํ…Œ์ด์…˜์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์‚ฌ์šฉํ•  ๋„๋ฉ”์ธ ํด๋ž˜์Šค๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

package com.example.validation.model;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

import javax.validation.constraints.NotNull;

@Getter
@ToString
@AllArgsConstructor
public class UserNotNull {

    @NotNull(message = "name must not be null")
    private final String name;
}

 

 

 

@NotNull ์–ด๋…ธํ…Œ์ด์…˜์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€๋ฅผ ์•Œ์•„๋ณด๊ธฐ ์œ„ํ•ด ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package com.example.validation.model;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;

public class NotNullValidationTest {

    private Validator validator = null;

    @BeforeEach
    public void setupValidator() {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    @Test
    void name์ด_notNull์ผ๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•˜์ง€_์•Š๋Š”๋‹ค() {
        // given
        UserNotNull user = new UserNotNull("JuHyun");

        // when
        Set<ConstraintViolation<UserNotNull>> violations = validator.validate(user);

        // then
        assertThat(violations.size()).isEqualTo(0);
    }

    @Test
    public void name์ด_null์ผ๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•œ๋‹ค() {
        // given
        UserNotNull user = new UserNotNull(null);

        // when
        Set<ConstraintViolation<UserNotNull>> violations = validator.validate(user);

        // then
        violations.forEach(i -> System.out.println(i.getMessage()));
        assertThat(violations.size()).isEqualTo(1);
    }

    @Test
    public void name์ด_๋น„์–ด์žˆ๋Š”๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•˜์ง€_์•Š๋Š”๋‹ค() {
        // given
        UserNotNull user = new UserNotNull("");

        // when
        Set<ConstraintViolation<UserNotNull>> violations = validator.validate(user);

        // then
        assertThat(violations.size()).isEqualTo(0);
    }

}

์œ„ ์„ธ ์ฝ”๋“œ๋Š” ๋ชจ๋‘ ์„ฑ๊ณตํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. 

์œ„ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด @NotNull ์–ด๋…ธํ…Œ์ด์…˜์€ ํ•„๋“œ๊ฐ€ null์ผ ๊ฒฝ์šฐ๋Š” ํ—ˆ์šฉํ•˜์ง€ ์•Š์œผ๋‚˜, ๋น„์–ด์žˆ๋Š” ๊ฒฝ์šฐ๋Š” ์ƒ๊ด€์—†์Šต๋‹ˆ๋‹ค.

๋‘ ๋ฒˆ์งธ ๋ฉ”์†Œ๋“œ  name์ด_notNull์ผ๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•˜์ง€_์•Š๋Š”๋‹ค()  ์˜ ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

ConstraintViolationํด๋ž˜์Šค์˜ getMessage() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด name ํ•„๋“œ์— ์„ค์ •ํ•œ 'name must not be null' ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ์ด ๋˜๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์œ„ @NotNull ์–ด๋…ธํ…Œ์ด์…˜์ด ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” NotNullValidator ํด๋ž˜์Šค์˜ isValid() ๋ฉ”์†Œ๋“œ๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

@NotEmpty


์ด๋ฒˆ์—๋Š” @NotEmpty ์–ด๋…ธํ…Œ์ด์…˜์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์‚ฌ์šฉํ•  ๋„๋ฉ”์ธ ํด๋ž˜์Šค๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

package com.example.validation.model;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

import javax.validation.constraints.NotEmpty;

@Getter
@ToString
@AllArgsConstructor
public class UserNotEmpty {

    @NotEmpty(message = "name must not be empty")
    private final String name;
}

 

 

์ด๋ฒˆ์—๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package com.example.validation.model;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;

public class NotEmptyValidationTest {

    private Validator validator = null;

    @BeforeEach
    public void setupValidator() {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    @Test
    void name์ด_๋น„์–ด์žˆ์ง€_์•Š๋Š”๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์€_์กด์žฌํ•˜์ง€_์•Š๋Š”๋‹ค() {
        // given
        UserNotEmpty user = new UserNotEmpty("JuHyun");

        // when
        Set<ConstraintViolation<UserNotEmpty>> violations = validator.validate(user);

        // then
        assertThat(violations.size()).isEqualTo(0);
    }

    @Test
    public void name์ด_๋น„์–ด์žˆ๋Š”๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•œ๋‹ค() {
        // given
        UserNotEmpty user = new UserNotEmpty("");

        // when
        Set<ConstraintViolation<UserNotEmpty>> violations = validator.validate(user);

        // then
        violations.forEach(i -> System.out.println(i.getMessage()));
        assertThat(violations.size()).isEqualTo(1);
    }

    @Test
    public void name์ด_null์ธ๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•œ๋‹ค() {
        // given
        UserNotEmpty user = new UserNotEmpty(null);

        // when
        Set<ConstraintViolation<UserNotEmpty>> violations = validator.validate(user);

        // then
        violations.forEach(i -> System.out.println(i.getMessage()));
        assertThat(violations.size()).isEqualTo(1);
    }

}

์œ„ ์„ธ ์ฝ”๋“œ๋Š” ๋ชจ๋‘ ์„ฑ๊ณตํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

@NotEmpty ์–ด๋…ธํ…Œ์ด์…˜์€ @NotNull ํด๋ž˜์Šค์˜ isValid() ๋ฉ”์†Œ๋“œ์™€ ํ•„๋“œ์˜ size/length๊ฐ€ 0๋ณด๋‹ค ํฐ ์ง€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•˜๋Š” ํ•„๋“œ๊ฐ€ NotNull์ด์—ฌ์•ผ ํ•˜๊ณ , size/length๊ฐ€ 0๋ณด๋‹ค ์ปค์•ผํ•ฉ๋‹ˆ๋‹ค.

 

๋‘๋ฒˆ์งธ ๋ฉ”์†Œ๋“œ name์ด_๋น„์–ด์žˆ๋Š”๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•œ๋‹ค() ์˜ ์ถœ๋ ฅ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

@NotEmpty ์–ด๋…ธํ…Œ์ด์…˜์€ @Size ์–ด๋…ธํ…Œ์ด์…˜๊ณผ ํ•จ๊ป˜ ์„ค์ •ํ•˜๋ฉด ๋” ์ œํ•œ์ ์œผ๋กœ ํ•„๋“œ์— ๋Œ€ํ•ด ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    @NotEmpty(message = "name must not be empty")
    @Size(min = 2, max = 10, message = "name must be between 2 and 10 length")
    private final String name;

 

 

 

@NotBlank


๋งˆ์ง€๋ง‰์œผ๋กœ @NotBlank ์–ด๋…ธํ…Œ์ด์…˜์— ๋Œ€ํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์‚ฌ์šฉํ•  ๋„๋ฉ”์ธ ํด๋ž˜์Šค๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

package com.example.validation.model;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

import javax.validation.constraints.NotBlank;

@Getter
@ToString
@AllArgsConstructor
public class UserNotBlank {

    @NotBlank(message = "name must not be blank")
    private final String name;
}

 

 

๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

package com.example.validation.model;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;

import static org.assertj.core.api.Assertions.assertThat;

public class NotBlankValidationTest {

    private Validator validator = null;

    @BeforeEach
    public void setupValidator() {
        validator = Validation.buildDefaultValidatorFactory().getValidator();
    }

    @Test
    public void name์ด_notBlank์ผ๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์€_์กด์žฌํ•˜์ง€_์•Š๋Š”๋‹ค() {
        // given
        UserNotBlank user = new UserNotBlank("John");

        // when
        Set<ConstraintViolation<UserNotBlank>> violations = validator.validate(user);

        // then
        assertThat(violations.size()).isEqualTo(0);
    }

    @Test
    public void name์ด_blank์ผ๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•œ๋‹ค() {
        // given
        UserNotBlank user = new UserNotBlank(" ");

        // when
        Set<ConstraintViolation<UserNotBlank>> violations = validator.validate(user);

        // then
        violations.forEach(i -> System.out.println(i.getMessage()));
        assertThat(violations.size()).isEqualTo(1);
    }

    @Test
    public void name์ด_๋น„์–ด์žˆ๋Š”๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•œ๋‹ค() {
        // given
        UserNotBlank user = new UserNotBlank("");

        // when
        Set<ConstraintViolation<UserNotBlank>> violations = validator.validate(user);

        // then
        assertThat(violations.size()).isEqualTo(1);
    }

    @Test
    public void name์ด_null์ผ๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•œ๋‹ค() {
        // given
        UserNotBlank user = new UserNotBlank(null);

        // when
        Set<ConstraintViolation<UserNotBlank>> violations = validator.validate(user);

        // then
        assertThat(violations.size()).isEqualTo(1);
    }

}

์œ„ ์ฝ”๋“œ๋„ ๋ชจ๋‘ ์„ฑ๊ณตํ•˜๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

@NotBlank ์–ด๋…ธํ…Œ์ด์…˜์€ NotBlankValidator ํด๋ž˜์Šค์˜ isValid() ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•„๋“œ์— ๊ณต๋ฐฑ์ด ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ์œ„ ํด๋ž˜์Šค์— ์กด์žฌํ•˜๋Š” trim() ๋ฉ”์†Œ๋“œ๋ฅผ ํ†ตํ•ด ์ œ๊ฑฐ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์•„๋ž˜ ๋ฉ”์†Œ๋“œ๋Š” ๊ณต๋ฐฑ์ด ์ œ๊ฑฐ๋˜๋ฏ€๋กœ, ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ํ†ต๊ณผํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๋‹ค.

    @Test
    public void name์ด_blank์ผ๊ฒฝ์šฐ_์ œ์•ฝ์กฐ๊ฑด์ด_์กด์žฌํ•œ๋‹ค() {
        // given
        UserNotBlank user = new UserNotBlank(" ");

        // when
        Set<ConstraintViolation<UserNotBlank>> violations = validator.validate(user);

        // then
        violations.forEach(i -> System.out.println(i.getMessage()));
        assertThat(violations.size()).isEqualTo(1);
    }

 

 

 

 

์ •๋ฆฌ


์ด์ƒ์œผ๋กœ Valid์˜ @NotNull, @NotEmpty, @NotBlank ์–ด๋…ธํ…Œ์ด์…˜์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค.

๊ฐ๊ฐ ์ฃผ์–ด์ง„ ์ƒํ™ฉ์— ๋งž๊ฒŒ ์ ์ ˆํ•œ ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค :)

 

 

 

 

Reference

 

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€