본문 바로가기

Spring/Spring 입문

7. Validation

Validation, 검증이란 프로그래밍에 있어서 가장 필요한 부분이다.

특히 Java에서는 null 값에 대해서 접근 하려고 할 때 null pointer exception이 발생 함으로, 이러한 부분을 방지 하기 위해서 미리 검증을 하는 과정을 Validation 이라고 한다.

 

단순하게는 아래와 같은 코드들이 있다.

 

특정한 클래스 객체가 들어온다고 하던지 반복된다면 여러가지 문제점이 야기된다.

1. 검증해야 할 값이 많은 경우 코드의 길이가 길어진다.

2. 구현에 따라서 달라 질 수 있지만 Service Logic과의 분리가 필요 하다.

3. 흩어져 있는 경우 어디에서 검증을 하는지 알기 어려우며, 재사용의 한계가 있다.

4. 구현에 따라 달라 질 수 있찌만, 검증 Logic이 변경 되는 경우 테스트 코드 등 참조하는 클래스에서 Logic이 변경되어야 하는 부분이 발생 할 수 있다.

 

스프링에서는 Annotation 기반으로 제공한다.

 

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 어노테이션을 달아줘서 그 객체 안에 어노테이션을 검사하고 그 값을 검증하고 맞지 않는다면 에러가 나온다.

email 부분을 잘 못 입력하여서 실행하였더니 에러 메시지가 뜬다.

 

 

이메일 양식을 맞추었더니 정상 출력이 되었다.

 

 @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