Spring 예외 응답, 왜 Map으로 처리하는 경우가 생길까?

박화랑·2025년 4월 8일
1

Spring_6기

목록 보기
16/32

시작하며...

Spring 프로젝트에서 서버가 클라이언트에게 응답을 보낼 때,
Map이나 DTO 둘 다 사용할 수 있다.

특히 예외 처리에서 Map<String, Object> 형태로 응답을 구성하는 경우가 많은데,
처음엔 "왜 DTO를 안 만들고 Map으로 하지?" 의문이 들어서 확인해봤다

그래서 이 글에서는 Map을 사용하는 이유와 함께,
언제 DTO를 써야 하고 언제 Map이 좋은지에 대해 정리해보았다.


Map<String, Object>로 응답을 구성하는 이유

1. 빠르게 응답 구조 생성 가능 (개발 속도 ↑)

Map.of("status", 400, "message", "잘못된 요청입니다");
  • 별도 클래스를 만들지 않고 바로 JSON 응답 생성 가능
  • 빠르게 테스트하거나 간단한 응답 구조일 때 유리

2. 유연함 – 상황에 따라 키-값 조정 용이

  • 어떤 예외는 fieldErrors가 있고, 어떤 예외는 없을 수도 있음
  • 이럴 때 Map을 쓰면 조건에 따라 응답 필드를 넣고 뺄 수 있음
if (ex.hasFieldErrors()) {
  body.put("fieldErrors", errors);
}

3. 일회성 응답, 재사용 필요 없는 경우 적합

  • 간단한 에러 메시지나 일시적인 응답에는 DTO 만들 필요 없음
  • 특히 테스트 코드, 샘플 API 등에 자주 사용됨

Map vs DTO 비교

항목Map<String, Object>DTO (Data Transfer Object)
✅ 장점빠른 개발, 유연함, 가벼움타입 안정성, IDE 지원, 명확한 구조
❌ 단점타입 안정성 부족, IDE 자동완성 X클래스 파일이 많아짐, 수정 시 코드량 증가
사용 용도일회성 응답, 테스트, 빠른 구현재사용, 문서화, 유지보수 중심의 응답
Swagger 연동어려움 (명세 없음)문서 자동화 가능 (Model 명세화)

🔍 실무에서 어떻게 쓸까?

상황추천 응답 방식
✅ 간단한 에러 응답 (400, 500 등)Map<String, Object>
✅ 예외 핸들링에서 유동적인 필드 필요할 때Map<String, Object>
✅ API 응답을 Swagger에 문서화해야 할 때DTO 클래스 사용
✅ 응답 형식이 고정되어 있거나 재사용할 경우DTO 클래스 사용

💡 결론

  • Map빠르게 응답을 만들고 유연하게 필드를 구성할 수 있어 예외 처리에 최적화 되어 있다.
  • 하지만 구조가 고정되거나 명확한 스펙 문서화를 요구한다면 DTO가 더 적절하다. 또한 가독성이 떨어져 협업시에 좋지 않고 팀프로젝트를 진행할 때 코드의 통일성 또한 떨어져 보인다.
  • 상황에 따라 Map과 DTO를 적절히 혼용하는 것이 실용적인 방법이다.
  • 목적에 따라 명확한 이유를 가지고 사용하도록 하자

예시: GlobalExceptionHandler (실습에서 사용된 코드)

@ExceptionHandler(CustomException.class)
public ResponseEntity<Map<String, Object>> handleCustomException(CustomException ex, HttpServletRequest request) {
    return ResponseEntity
        .status(ex.getErrorCode().getStatus())
        .body(Map.of(
            "timestamp", LocalDateTime.now(),
            "status", ex.getErrorCode().getStatus().value(),
            "error", ex.getErrorCode().getStatus().name(),
            "message", ex.getErrorCode().getMessage(),
            "path", request.getRequestURI()
        ));
}
@ExceptionHandler(CustomException.class)
public ResponseEntity<ErrorResponseDto> handleCustomException(CustomException ex, HttpServletRequest request) {
    return ResponseEntity
        .status(ex.getErrorCode().getStatus())
        .body(ErrorResponseDto.from(ex.getErrorCode(), request.getRequestURI()));
    }
  • 이렇게 두가지 방법으로 응답을 나눌 수 있다! 어떤 대답으로 할 지는 팀원끼리 소통을 통해 정하자!

📚 참고자료


profile
개발자 희망생

0개의 댓글