본문 바로가기

Project

[Project] Lv_6 스케줄 프로젝트

 


 

요구사항

설명

  • ✅ 유효성 검사
    1. 잘못된 입력이나 요청을 미리 방지할 수 있습니다.
    2. 데이터의 무결성을 보장하고 애플리케이션의 예측 가능성을 높여줍니다.
    3. Spring에서 제공하는 @Valid 어노테이션을 이용할 수 있습니다.

조건

  • ✅ 할일은 최대 200자 이내로 제한, 필수값 처리
  • ✅ 비밀번호는 필수값 처리
  • ✅ 담당자의 이메일 정보가 형식에 맞는지 확인

 


 

요구 구현

ScheduleController

더보기
@RestController
@RequestMapping("/schedules")
public class ScheduleController {

    private final ScheduleService scheduleService;

    public ScheduleController(ScheduleService scheduleService) {
        this.scheduleService = scheduleService;
    }

    @PostMapping
    public ResponseEntity<ScheduleResponseDto> createSchedule(@RequestBody @Valid ScheduleRequestDto requestDto) {
        return new ResponseEntity<>(scheduleService.saveSchedule(requestDto), HttpStatus.CREATED);
    }
    
    // 다른 메서드들 제외
}
  • @RequestBody @Valid ScheduleRequestDto requestDto : `ScheduleRequestDto`에서 유효성 검증 어노테이션들(`@NotNull`, `@Size` 등)을 작동시키기 위해서 `@Valid`를 붙였습니다.

 

 

ScheduleRequestDto

더보기
@Getter
public class ScheduleRequestDto {


    @NotNull(message = "사용자 Id는 필수 입니다.")
    private Long userId;

    @Size(max=200, message = "할 일은 200자 내여야 합니다.")
    @NotNull(message = "할 일은 필수 입니다.")
    private String toDoContent;
}
  • `@NotNull`, `@Size` 어노테이션을 붙이면, 해당 필드에 유효성 위반시 `MethodArgumentNotValidException` 오류를 던집니다.
  • `@NotNull` : 해당 값에 `null` 값이 들어오면 예외처리를 해줍니다.
  • `@Size` : 해당 값에 max보다 큰 값이 들어오거나 min보다 작은 값이 들어오면 예외처리를 해줍니다.
  • message 설정을 통해 예외처리 시, 보내고 싶은 message를 지정할 수 있습니다.

 

 

UserController

더보기
@RestController
@RequestMapping("/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping
    public ResponseEntity<UserResponseDto> createUser(@RequestBody @Valid UserRequestDto requestDto) {
        return new ResponseEntity<>(userService.saveUser(requestDto), HttpStatus.CREATED);
    }
    
    ...
}
  • @RequestBody @Valid UserRequestDto requestDto : `UserRequestDto`에서 유효성 검증 어노테이션들(`Email` 등)을 작동시키기 위해서 `@Valid`를 붙였습니다.

 

 

UserRequestDto

더보기
@Getter
public class UserRequestDto {

    @Email(message = "올바른 형식의 이메일 주소가 아닙니다.")
    private String email;
    private String userName;
}
  • `@Email` 어노테이션을 붙이면, 해당 필드에 유효성 위반시 `MethodArgumentNotValidException` 오류를 던집니다.
  • `@NotNull` : 해당 값에 `null` 값이 들어오면 예외처리를 해줍니다.
  • message 설정을 통해 예외처리 시, 보내고 싶은 message를 지정할 수 있습니다.

 

 

GlobalExceptionHandler

더보기
@RestControllerAdvice
public class GlobalExceptionHandler {

    ....

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> handleMethodArgumentNotValidException (
            MethodArgumentNotValidException ex,
            HttpServletRequest request) {
        Map<String, Object> response = new HashMap<>();
        response.put("timestamp", LocalDateTime.now());
        response.put("status", ex.getStatusCode().value());
        String errorMessage = ex.getBindingResult().getFieldErrors().stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.joining(", "));
        response.put("message", errorMessage);
        response.put("path", request.getRequestURI());
        return new ResponseEntity<>(response, ex.getStatusCode());
    }
}
  • 유효성 검증 어노테이션에서 발생하는 예외를 공통으로 처리하는 메서드입니다.
    (예외처리는 했지만, 보여지는건 예외 발생했을 때랑 비슷해보이게 커스텀하였습니다.)

 

❗유효성 검증 어노테이션은 기본적으로 제공하는 예외처리가 있습니다.
(커스텀으로 만들어보고싶어서 진행하였습니다. 필수 ❌)

 


 

회고

1. @Valid에 대해 처음 겪어보다보니 사용하는게 익숙하지 않았습니다.

❗트러블 슈팅으로 작성하려다, 처음 사용하는 것이기 때문에 회고를 통해 내용 정리를 진행하였습니다.

 

 

@Valid란?

  • `javax.validaton.valid`(Java EE) 또는 `jakarta.validation.valid`(Jakarta EE) 패키지의 어노테이션입니다.
  • `@Valid`는 자바 빈 검증(Bean Validation)을 트리거(trigger)하는 어노테이션으로, 객체의 필드들이 적절하게 설정되어 있는지 검사합니다.
  • 객체 내부의 필드에 붙은 유효성 검증 어노테이션들(@NotNull, @Size, @Email, 등)을 자동으로 검사합니다.
  • `@Valid` 어노테이션이 없으면, 아무리 유효성 검증 어노테이션을 붙여도 검증이 수행되지 않습니다.

 

내부적으로 동작

  • Spring은 `@Valid`를 감지하고, JSR-300 Bean Validation API (Hibernate Validator가 대표 구현체)를 사용하며 DTO 필드들을 검사합니다.
  • 유효성 위반 시 `MethodArgumentNotValidException`을 통해 예외를 던집니다.

 

유효성 검증 어노테이션 종류

어노테이션 설명
@NotNull null이 아니어야 함
@NotEmpty null 또는 ""(빈 문자열)이 아니어야 함 (문자열, 컬렉션, 배열 등)
@NotBlank 공백 문자만 있어도 안 됨 (" "도 유효하지 않음)
@Size(min=, max=) 문자열, 배열, 컬렉션의 길이 또는 크기 제한
@Min(value) 숫자의 최소값 제한
@Max(value) 숫자의 최대값 제한
@Positive 양수만 허용 (> 0)
@PositiveOrZero 양수 또는 0 허용 (>= 0)
@Negative 음수만 허용 (< 0)
@NegativeOrZero 음수 또는 0 허용 (<= 0)
@Email 이메일 형식이 맞는지 검증
@Pattern(regexp = "") 정규식으로 형식 지정 (예: 전화번호, 비밀번호 조건 등)
@AssertTrue boolean이 true여야 함
@AssertFalse boolean이 false여야 함
@Past 현재보다 과거여야 함
@PastOrPresent 과거 또는 현재여야 함
@Future 현재보다 미래여야 함
@FutureOrPresent 미래 또는 현재여야 함

 

 


 

트러블 슈팅

1. 유효성 검증 어노테이션에 대한 오류 출력 시, 사용자 message 출력 안되는 오류

유효성 검증 어노테이션은 공통 예외처리로 따로 커스텀하여 처리하지 않아도 기본적으로 예외처리를 진행합니다.

따라서 커스텀 예외처리 없이, 그냥 사용하면 아래에서와 같이 예외처리가 되어 응답받습니다.

 

설명 & 문제

userId가 null이거나 toDoContent가 null, size가 200이 넘어가면 예외처리가 발생합니다.

 

userId를 추가하지 않자, `@Notnull` 어노테이션으로 인해 예외처리가 발생하였습니다.

하지만 여기서 문제 ❗, 내가 설정한 message가 보이지 않는 것을 알 수 있습니다.

 

 

해결 방법

Spring Boot의 기본 동작은 예외를 `BasicErrorController`가 처리합니다. 하지만 `message`, `errors` 필드를 포함시키려면 `application properties`에서 옵션을 켜야합니다.

 

server.error.include-message=always를 넣어주시면 됩니다.

 

사용자 설정 message가 정상적으로 출력됩니다.