๐ 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
'Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring AOP - (2) AOP ๊ฐ๋ ๋ฐ ์ค์ต (0) | 2021.09.24 |
---|---|
[Spring] - ๋ก๊น : Log4j, Log4j2, Slf4j, Logback (0) | 2021.09.15 |
Spring Boot + MockMvc ํ ์คํธ(feat. Kotlin) (0) | 2021.09.07 |
[Spring] - @JsonProperty, @JsonNaming (2) | 2021.09.02 |
Spring AOP - (1) ํ๋ก์ ํจํด, ๋ฐ์ฝ๋ ์ดํฐ ํจํด (0) | 2021.08.27 |
๋๊ธ