[Spring] 유효성 검증

검증이 필요한 이유

  • 특정 규칙을 준수하는 데이터를 얻기 위해
  • 사용자 오류를 줄이기 위해
  • 오류 방지

DTO 유효성 검사 코드의 예

// build.gradle 추가
implementation 'org.springframework.boot:spring-boot-starter-validation'

package com.codestates.board.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.validation.constraints.NotBlank;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Setter
public class BoardPostDto {

    @NotBlank(message = "제목은 공백이 될 수 없습니다.") // 공백으로 데이터를 보내면 message가 나옴
    private String title;

    @NotBlank(message = "내용은 공백이 될 수 없습니다.") // 공백으로 데이터를 보내면 message가 나옴
    private String content;


}
package com.codestates.board.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import javax.validation.constraints.NotBlank;

@Getter
@AllArgsConstructor
@NoArgsConstructor
@Setter
public class BoardPatchDto {

    private long boardId;

    @NotBlank(message = "제목은 공백이 될 수 없습니다.") // 공백으로 데이터를 보내면 message가 나옴
    private String title;

    @NotBlank(message = "내용은 공백이 될 수 없습니다.") // 공백으로 데이터를 보내면 message가 나옴
    private String content;
}

샘플 컨트롤러 유효성 검사 코드

package com.codestates.board.controller;

import com.codestates.board.dto.BoardPatchDto;
import com.codestates.board.dto.BoardPostDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.Positive;

@RestController // Rest API 리소스를 처리하기 위한 API 엔드포인트로 동작, Spring Bean 자동 등록
@RequestMapping("/v1/board") // 공통 URL 설정 + 핸들러 메서드 매핑
@Validated // @PathVariable 추가된 변수에 유효성 검증이 정상적으로 수행에 필요 (@Positive)
public class BoardController {

    // @RequestBody -> Dto 클래스를 객체로 변환 시켜주는 역할 (클라이언트가 JSON 형식의 데이터를 전송할때만 가능)
    // @PathVariable -> Rest API 변환 파라미터 처리

    // 게시판 생성 API (@PostMapping)
    @PostMapping
    public ResponseEntity postBoard(@Valid @RequestBody BoardPostDto boardPostDto) {
        // @Valid --> 유효성 검증 로직이 실행
        System.out.println(boardPostDto); // -> 클라이언트에서 보내는 데이터를 출력

        return new ResponseEntity<>(HttpStatus.CREATED);
    }

    // 게시판 수정 API (@PatchMapping)
    @PatchMapping("/{board-id}")
    public ResponseEntity patchBoard(@PathVariable("board-id") @Positive long boardId,
                                     @Valid @RequestBody BoardPatchDto boardPatchDto) {
        // @Positive --> 양수만 가능 (유효성 검증)
        System.out.println(boardId); // -> board id 출력
        System.out.println(boardPatchDto); // -> 클라이언트에서 보내는 데이터를 출력

        return new ResponseEntity<>(HttpStatus.OK);
    }

    // 특정 게시판 1개 조회 API (@GetMapping)
    @GetMapping("/{board-id}")
    public ResponseEntity getBoard(@PathVariable("board-id") @Positive long boardId) {

        System.out.println(boardId); // -> board id 출력

        return new ResponseEntity<>(HttpStatus.OK);
    }

    // 저장된 게시판 모두 조회 API (@GetMapping)
    @GetMapping("/list")
    public ResponseEntity getBoards() {
        System.out.println("Board 리스트 출력");

        return new ResponseEntity<>(HttpStatus.OK);
    }

    // 게시판 삭제 API (@DeleteMapping)
    @DeleteMapping("/{board-id}")
    public ResponseEntity deleteBoard(@PathVariable("board-id") @Positive long boardId) {
        System.out.println(boardId); // -> board id 출력

        return new ResponseEntity<>(HttpStatus.OK);
    }


}

몇 가지 확인 참고 사항

  • @NotBlank -> null, 공백, ” ” 모든 X 허용
  • @Email -> 이메일 형식이 아닌 경우 허용 X
  • @Pattern -> 정규 표현식으로 유효성 검사
  • @Positive -> 양수만 허용