Validation, 검증이란 프로그래밍에 있어서 가장 필요한 부분이다.
특히 Java에서는 null 값에 대해서 접근 하려고 할 때 null pointer exception이 발생 함으로, 이러한 부분을 방지 하기 위해서 미리 검증을 하는 과정을 Validation 이라고 한다.
단순하게는 아래와 같은 코드들이 있다.
특정한 클래스 객체가 들어온다고 하던지 반복된다면 여러가지 문제점이 야기된다.
1. 검증해야 할 값이 많은 경우 코드의 길이가 길어진다.
2. 구현에 따라서 달라 질 수 있지만 Service Logic과의 분리가 필요 하다.
3. 흩어져 있는 경우 어디에서 검증을 하는지 알기 어려우며, 재사용의 한계가 있다.
4. 구현에 따라 달라 질 수 있찌만, 검증 Logic이 변경 되는 경우 테스트 코드 등 참조하는 클래스에서 Logic이 변경되어야 하는 부분이 발생 할 수 있다.
bean validation spec https://beanvalidation.org/2.0-jsr380/
Jakarta Bean Validation - Bean Validation 2.0 (JSR 380)
Bean Validation 2.0 focused on the following topics: support for validating container elements by annotating type arguments of parameterized types e.g. List<@Positive Integer> positiveNumbers. This also includes: more flexible cascaded validation of contai
beanvalidation.org
bean validation의 스펙에 대한 정의를 정리해 둔 사이트이다.
해당 사이트에 어떠한 어노테이션이 제공되고 활용할 수 있는지 알 수 있다.
이외에 구글에 검색하여도 다양하게 나온다.
코드 실습.
import javax.validation.constraints.Email;
public class User {
private String name;
private int age;
@Email
private String email;
private String phoneNumber;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
", phoneNumber='" + phoneNumber + '\'' +
'}';
}
}
package com.example.validation.controller;
import com.example.validation.dto.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
@RequestMapping("/api")
public class ApiController {
@PostMapping("/user")
public ResponseEntity<User> user(@Valid @RequestBody User user){
System.out.println(user);
if(user.getAge()>= 90){
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(user);
}
return ResponseEntity.ok(user);
}
}
간단하게 @Email 어노테이션을 사용해서 Validation을 실습해보았다.
어노테이션을 사용하면 @Vaild 어노테이션을 달아줘서 그 객체 안에 어노테이션을 검사하고 그 값을 검증하고 맞지 않는다면 에러가 나온다.
@Pattern() 어노테이션을 사용해서 정규식을 이용해서 실습을 더 진행했다.
@Pattern(regexp = "^\\d{2,3}-\\d{3,4}-\\d{4}$")
private String phoneNumber;
정규식은 인터넷 검색하면 쉽게 구할 수 있기도 하고
필요하다면 공부하는 것도 좋다.
@PostMapping("/user")
public ResponseEntity<User> user(@Valid @RequestBody User user, BindingResult bindingResult){
System.out.println(user);
또한 파라미터에 BindingResult를 이용하여 예외가 바로 터지는 것이 아니라 bindingResult에 값을 가지게 하여 처리 할 수 있다.
public class ApiController {
@PostMapping("/user")
public ResponseEntity<User> user(@Valid @RequestBody User user, BindingResult bindingResult){
if(bindingResult.hasErrors()){
StringBuilder sb = new StringBuilder();
bindingResult.getAllErrors().forEach(objectError -> {
FieldError field = (FieldError) objectError;
String message = objectError.getDefaultMessage();
System.out.println("field : "+field.getField());
System.out.println(message);
});
}
System.out.println(user);
return ResponseEntity.ok(user);
}
}
bindingResult를 이용해서 어떤한 오류가 나있는지 출력하는 메서드이다.
오류 메시지를 바꾸고 싶다면
@Pattern(regexp = "^\\d{2,3}-\\d{3,4}-\\d{4}$", message = "핸드폰 번호 양식을 맞춰 주세요. 01x-xxx(x)-xxxx")
private String phoneNumber;
이런식으로 변경을 하면 된다.
sb.append("field : "+field.getField());
sb.append("message : "+ message);
});
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(sb.toString());
}
응답 메시지에 바로 오류 출력을 하도록 설정했다.
package com.example.validation.controller;
import com.example.validation.dto.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController
@RequestMapping("/api")
public class ApiController {
@PostMapping("/user")
public ResponseEntity user(@Valid @RequestBody User user, BindingResult bindingResult){
if(bindingResult.hasErrors()){
StringBuilder sb = new StringBuilder();
bindingResult.getAllErrors().forEach(objectError -> {
FieldError field = (FieldError) objectError;
String message = objectError.getDefaultMessage();
System.out.println("field : "+field.getField());
System.out.println(message);
sb.append("field : "+field.getField());
sb.append("message : "+ message);
});
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(sb.toString());
}
System.out.println(user);
return ResponseEntity.ok(user);
}
}
package com.example.validation.dto;
import javax.validation.constraints.*;
public class User {
@NotBlank
private String name;
@Max(value = 90)
private int age;
@Email
private String email;
@Pattern(regexp = "^\\d{2,3}-\\d{3,4}-\\d{4}$", message = "핸드폰 번호 양식을 맞춰 주세요. 01x-xxx(x)-xxxx")
private String phoneNumber;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
", phoneNumber='" + phoneNumber + '\'' +
'}';
}
}
최종코드
정리하면 어노테이션을 변수에 붙여주고
컨트롤러나 검사하고 싶은 객체에 @Valid를 붙여서 사용하면 된다.
'Spring > Spring 입문' 카테고리의 다른 글
빈(Bean) 스코프 (0) | 2025.03.20 |
---|---|
8. Object Mapper (0) | 2022.06.30 |
7. Response (0) | 2022.06.30 |
6. 리소스 삭제 DELETE (0) | 2022.06.30 |
5. PUT API (0) | 2022.06.30 |