handleBindException 의 기대의도가 방향이 맞는지 궁금합니다.
36
投稿した質問数 2
안녕하세요. 바인딩 에러와 관련해 어떤 의도로 if 절이 나뉜 것인지 정확히 이해를 못한것 같아서 질문드립니다.
메시지 작성에서 nullable 한 값이 존재하여 null-safe 하게 메시지 여부를 검사하고, 존재한다면 메시지를 반환해주는 것으로 이해를 하였습니다.
그리고 여러 필드에서 에러가 발생한 경우 람다식을 통해 에러 메시지를 "," 로 조합해주고 리턴을 하는 것으로 이해하였습니다.
이후 직접 테스트해보는 과정에서 localhost:8080/v1/books 으로 파라미터들을 모두 제외하고 요청을 보낸 경우의 기대가 "쿼리비어있을수 없습니다., 페이지..., 사이즈... 값들이 정확하지 않습니다." 이런 결과가 나오는 것으로 기대를 하였지만, 실제론 랜덤하게 누락된 값 하나만 결과로 나오는 것을 확인하였습니다.
혹시 e.getFieldErrors().stream() 가 default 메시지가 null 인 케이스만 방어하기 위해서 작성된 것일까요?
回答 2
0
안녕하세요 swye199님 😀
질문남겨주셔서 감사합니다! 혹시 질문과 연관된 코드를 첨부해주실 수 있으실까요?
0
넵 코드는 약간 수정을하였습니다.
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ApiException.class)
public ProblemDetail handleApiException(ApiException e) {
log.error("API Exception message={}, className={}", e.getErrorMessage(), e.getClass().getName());
return getProblemDetail(e.getHttpStatus(), e.getMessage(), e.getErrorType());
}
@ExceptionHandler(Exception.class)
public ProblemDetail handleException(Exception e) {
log.error("Exception message={}, className={}", e.getMessage(), e.getClass().getName());
return getProblemDetail(
HttpStatus.INTERNAL_SERVER_ERROR,
ErrorType.UNKNOWN.getDescription(),
ErrorType.UNKNOWN);
}
@ExceptionHandler(NoResourceFoundException.class)
public ProblemDetail handleNoResourceFoundException(NoResourceFoundException e) {
log.error("NoResourceFoundException message={}, className={}", e.getMessage(), e.getClass().getName());
return getProblemDetail(
HttpStatus.NOT_FOUND,
ErrorType.NO_RESOURCE.getDescription(),
ErrorType.NO_RESOURCE);
}
@ExceptionHandler(BindException.class)
public ProblemDetail handleBindException(BindException e) {
log.error("Bind message={}, className={}", e.getMessage(), e.getClass().getName());
return getProblemDetail(HttpStatus.BAD_REQUEST, createMessage(e), ErrorType.INVALID_PARAMETER);
}
private String createMessage(BindException e) {
if (e.getFieldError() != null && e.getFieldError().getDefaultMessage() != null) {
return e.getFieldError().getDefaultMessage();
}
return e.getFieldErrors().stream()
.map(FieldError::getField)
.collect(Collectors.joining(", ")) + " 값들이 정확하지 않습니다.";
}
private ProblemDetail getProblemDetail(HttpStatus httpStatus, String message, ErrorType errorType) {
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(httpStatus, message);
problemDetail.setProperty("exception", errorType);
problemDetail.setProperty("timestamp", LocalDateTime.now());
return problemDetail;
}
}
만약 요청예시가
curl --location 'localhost:8080/v1/books?query=HTTP&page=-1&size=-1
이런 식으로 나가서, page 및 size 의 유효성 검증이 위반되었을때
현재는
{
"detail": "페이지 번호는 1이상이어야합니다.",
"instance": "/v1/books",
"status": 400,
"title": "Bad Request",
"exception": "INVALID_PARAMETER",
"timestamp": "2026-05-27T19:15:01.156153"
}이런식으로 내려주고 있습니다.
메시지를 생성해주는
if (e.getFieldError() != null && e.getFieldError().getDefaultMessage() != null) {
return e.getFieldError().getDefaultMessage();
}해당 부분에서의 조건이 항상 참이기 떄문에 그런것이라고 생각하는데,
return e.getFieldErrors().stream()
.map(FieldError::getField)
.collect(Collectors.joining(", ")) + " 값들이 정확하지 않습니다.";해당 코드는 default 메시지가 null 인 케이스만을 대비하기 위한 의도로 작성된 것인지
아니면 유효성검증을 여러개 통과하지 못하였을때,
{
"detail": "size, page 값들이 정확하지 않습니다.",
"instance": "/v1/books",
"status": 400,
"title": "Bad Request",
"exception": "INVALID_PARAMETER",
"timestamp": "2026-05-27T19:18:27.164512"
}다음과 같이 내려오는 것을 의도하고 작성하신 코드인지 궁금합니다.
0
질문 잘 짚어주신거같습니다! 분석하신 내용이 맞습니다. 정리하면
default message가 null인케이스만을 방어하기위한 fallback이라고 봐주시면 될것같고, 여러필드를 각각 에러처리를 한다고하면 항상 stream을 돌리는게 맞을거같네요.
필드각각을 처리한다면 아래처럼 수정을 해야될거같습니다.
private String createMessage(BindException e) {
return e.getFieldErrors().stream()
.map(fe -> {
// 로직 필요에 맞게 수정
String msg = fe.getDefaultMessage();
return msg != null ? msg : fe.getField() + " 값이 정확하지 않습니다.";
})
.collect(Collectors.joining(", "));
}혹은 둘중 하나라도 틀리면 그냥 공통된 메세지로 처리해도 될거같구요.
코드의 의도가 제대로 드러나지 않은 부분을 잘 짚어주신거같습니다!
-1
안녕하세요, 인프런 AI 인턴입니다. swye199님,
현재 질문해주신 사항에 대해 답변 드리겠습니다.
handleBindException에 대해 궁금해 하신 부분은 Spring에서 요청 바인딩 시 발생할 수 있는 여러 오류들, 특히 잘못된 값이나 누락된 파라미터들을 처리하기 위한 것임을 알 수 있습니다. 이 과정에서 모든 필드 에러를 수집하여 이를 사용자에게 명확히 전달하는 것이 목표입니다.
핵심 개념 요약:
e.getFieldErrors().stream()의 역할:- 이 라인을 통해 각 필드에 대해 발생한 에러를 리스트 형태로 가져옵니다. 이는 각 필드에 설정된 바인딩 규칙을 위반했을 때 발생한 에러 정보를 제공합니다.
- 이 라인을 통해 각 필드에 대해 발생한 에러를 리스트 형태로 가져옵니다. 이는 각 필드에 설정된 바인딩 규칙을 위반했을 때 발생한 에러 정보를 제공합니다.
에러 메시지 조합:
- 에러 메시지들을 stream을 사용하여 “,“로 조합하는 이유는, 여러 필드에서 에러가 발생했을 때 사용자에게 명확하게 어떤 필드에 문제가 있는지를 알려주기 위함입니다.
- 에러 메시지들을 stream을 사용하여 “,“로 조합하는 이유는, 여러 필드에서 에러가 발생했을 때 사용자에게 명확하게 어떤 필드에 문제가 있는지를 알려주기 위함입니다.
기대되는 결과와의 차이:
- 실제로 모든 누락된 값이 에러로 리턴되기를 기대했지만, 랜덤한 하나의 에러만 반환되는 것은 테스트 환경이나 설정에 따라 에러 리스트가 다르게 구성될 수 있음을 의미합니다. 이는
BindingResult나Errors인터페이스의 구현에 영향을 받을 수 있습니다. 기본적으로 Spring은 모든 바인딩 에러를 수집하지만, 이후 처리 과정에서의 설정에 따라 화면 또는 로그에 나타나는 내용이 달라질 수 있습니다.
- 실제로 모든 누락된 값이 에러로 리턴되기를 기대했지만, 랜덤한 하나의 에러만 반환되는 것은 테스트 환경이나 설정에 따라 에러 리스트가 다르게 구성될 수 있음을 의미합니다. 이는
참고 자료:
Spring에서의 BindException 처리에 관한 더 자세한 내용을 읽고 싶으시다면 아래 링크를 추천드립니다. 비슷한 질문과 답변을 통해 추가 정보를 얻으실 수 있습니다.
- Spring에서의 BindException 문제 해결 및 에러 메시지 처리 방법 - 바인딩 에러와 관련된 깊이 있는 논의입니다.
확인하시고 활용하시기에 불편함이 없도록, 추가적으로 궁금하신 점이 있다면 언제든지 문의해 주세요. 지식공유자께서 더 세부적인 답변을 제공하시길 기다려주시기 바랍니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
NaverBookRepository.class 의 위치에 따른 모듈간의 의존성에 대해 질문드립니다.
1
48
2
패키지 vs 모듈 선택 기준
0
65
2
Kotlin 테스트 프레임워크
0
92
2
import 오류?
0
80
2
JSON 역직렬화
0
76
2
Spring Cloud 버전 관리 문제
0
282
2
AsyncExcutor 설정값 질문
0
94
2
17강 api서버구현2 질문있습니다.(ai답변이 이상합니다.)
0
123
2
16강 api서버구현 질문있습니다.
0
85
2
14번쨰 부분 중 질문드립니다..<ai답변으로 해도 안되요>
0
152
2
.
0
162
1
서비스에 @Transactional 애노테이션을 사용하시지 않는 이유가 궁금합니다
0
168
2
NaverClientTest 질문있습니다.
0
188
2
멀티모듈 구성 질문입니다.
0
218
3
멀티모듈 구성 강의에 대해 질문이 있습니다.
0
226
3
SPOCK 의존성 추가 후 Generate Test 옵션 미노출
0
215
3
멀티모듈 지식 습득에 관하여 질문 드립니다.
0
261
2
Async Config 테스트컨트롤러의 코드의 동작이 안되는거 같습니다.
0
232
3
author 배열이 비어서 오는 경우가 있으니 참고하세요.
0
202
3
커밋 끊으면서 해주시는거 너무 좋네요.
1
166
2
비즈니스 로직 담당 서비스
0
209
2
모의과제 소개
0
182
2
cqrs에 관하여
1
264
2
멀티모듈 문의드립니다.
0
268
2

