이 화면을 보고, 진짜 문제를 짚어보자.
지금 이 응답은400 Bad Request를 던졌는데,
과연이메일 형식이 잘못된 걸까?
아니면비밀번호가 누락된 걸까?사용자 입장에서 보면, 무엇이 잘못됐는지 알 수 있는 방법이 전혀 없다.
이곳 말고도 여러곳의 Controller 에서 같은
@Vaild를 던지지만 예외처리는 전혀 처리 되지않았다.
콘솔에 뜨는 걸 사용자는 알 수 없다.
입력값 유효성 검사가 실패해도,
서버는 구체적인 필드 오류 메시지를 응답하지 않고,
단순히 400 에러만 던진다.
이로 인해 사용자는 문제를 수정하지 못하고,
서비스 이용 흐름이 끊기게 된다.
즉 UX 가 상당히 저하 된다.
Spring의 @Valid는 MVC 레벨에서 작동한다.
즉, 유효성 검사에 실패하면 컨트롤러 메서드가 호출되기 전에
Spring이 자동으로 MethodArgumentNotValidException을 발생시킨다.

이 예외는 우리가 정의한 전역 예외 처리기(@RestControllerAdvice)에서
가로채어 응답 형식을 커스터마이징할 수 있다.
결과적으로, 입력값 검증 실패에 대한 응답을 전역에서 통일감 있게 처리하는 것이
가장 효율적인 방식이라고 판단했다.
처음에는 유효성 검사 실패 시, Spring이 자동으로
400 Bad Request를 응답해주긴 했지만,
응답 메시지는 다음과 같이 내부 구현 정보와 긴 에러 문자열만 포함하고 있었다.
이렇게 된다면, 어떤 필드가 잘못됐는지 구분이 불가능하다
예외 메시지에 내부 클래스 경로까지 포함되어 가독성이 매우 떨어진다
사용자에게 전혀 도움이 되지 않는 에러 포맷이다
![]()
이제 사용자는 어떤 필드에서 어떤 문제가 발생했는지 명확하게 알 수 있고,
개발자도 예외 메시지를 구조적으로 관리할 수 있게 되었다.
처음에는 Spring이 기본 제공하는 예외 메시지에 의존했기 때문에,
유효성 검증 실패 시 사용자에게 전달되는 정보가 거의 없었다.
단순히 "400 Bad Request"만 반환되고 어떤 필드가 잘못되었는지 알 수 없었기 때문에,
사용자 입장에서 매우 불친절한 UX였다.
이를 개선하기 위해 @RestControllerAdvice를 활용한 전역 예외 처리기를 직접 구현했고,
MethodArgumentNotValidException에서 각 필드별 오류 메시지를 추출하여
구조화된 JSON 형태로 응답하도록 변경했다.
그 결과, 사용자에게 의미 있는 피드백을 제공할 수 있게 되었고,
개발자 입장에서도 유지보수성과 확장성이 높아졌다.
이전 응답
- 너무 길고, 어디서 잘못됐는지 알 수 없다.
- 내부 코드 정보까지 보여서 보기 불편하다.
이후 응답
![]()
- 어떤 필드에 어떤 문제가 있는지 명확하게 보여준다.
- 사용자도, 프론트엔드도 쉽게 이해 가능하다.