공통 응답 DTO 및 예외 처리 구조 만들기

💡 학습 목표
    1. 공통 응답 DTO를 사용하여 일관성 있는 API 응답을 구성하는 방법을 습득한다.
    2. 예외 처리(Exception Handling)를 통해 API 호출 시 발생할 수 있는
        다양한 예외를 통합된 방식으로 처리하는 방법을 알아 본다.

1. ApiUtil 클래스 작성

  • ApiUtil 클래스는 모든 API 응답을 동일한 형태로 구성하기 위한 공통 응답 DTO이다.
  • 이를 통해 성공 응답에러 응답을 일관된 구조로 제공할 수 있다.
package com.tenco.blog_v3.common.utils;


public class ApiUtil<T> {

    private Integer status;  // 협의 -  1, 성공 -1 실패
    private String msg;
    private T body;

    public ApiUtil(T body) {
        this.status = 200;
        this.msg = "성공";
        this.body = body;
    }

    public ApiUtil(Integer status, String msg) {
        this.status = status;
        this.msg = msg;
        this.body = null;
    }

}

 

  • T: 제네릭 타입으로, 응답 본문(body)에 담을 데이터의 타입을 유연하게 처리한다.
  • 성공 응답: status는 200, msg는 "성공"으로 설정되고, 본문에는 실제 데이터가 담긴다.
  • 에러 응답: status와 msg는 에러에 맞는 코드와 메시지로 설정되며, 본문은 비워둔다.

2. 에러 코드

사용할 에러 코드 확인

  • 400: 잘못된 요청
  • 401: 인증되지 않은 사용자
  • 403: 권한 없음
  • 404: 자원 없음
  • 500: 서버 내부 오류
package com.tenco.blog_v3.common;

import com.tenco.blog_v3.common.errors.*;
import com.tenco.blog_v3.common.utils.ApiUtil;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

// 데이터 반환
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 400 Bad Request 예외 처리
     * @return json
     */
    @ExceptionHandler(Exception400.class)
    public ResponseEntity<?> handleException400(Exception400 e) {
        ApiUtil<?> apiUtil = new ApiUtil<>(400, e.getMessage());
        // return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(apiUtil);
        return new ResponseEntity<>(apiUtil, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(Exception401.class)
    public ResponseEntity<?> handleException401(Exception401 e) {
        ApiUtil<?> apiUtil = new ApiUtil<>(401, e.getMessage());
        // return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(apiUtil);
        return new ResponseEntity<>(apiUtil, HttpStatus.UNAUTHORIZED);
    }

    @ExceptionHandler(Exception403.class)
    public ResponseEntity<?> handleException403(Exception403 e) {
        ApiUtil<?> apiUtil = new ApiUtil<>(403, e.getMessage());
        // return ResponseEntity.status(HttpStatus.FORBIDDEN).body(apiUtil);
        return new ResponseEntity<>(apiUtil, HttpStatus.FORBIDDEN);
    }

    @ExceptionHandler(Exception404.class)
    public ResponseEntity<?> handleException404(Exception404 e) {
        ApiUtil<?> apiUtil = new ApiUtil<>(404, e.getMessage());
        // return ResponseEntity.status(HttpStatus.NOT_FOUND).body(apiUtil);
        return new ResponseEntity<>(apiUtil, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(Exception500.class)
    public ResponseEntity<?> handleException500(Exception500 e) {
        ApiUtil<?> apiUtil = new ApiUtil<>(500, e.getMessage());
        // return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(apiUtil);
        return new ResponseEntity<>(apiUtil, HttpStatus.INTERNAL_SERVER_ERROR);
    }

}

 

  • @RestControllerAdvice: 모든 컨트롤러에서 발생한 예외를 감지하고, 해당 예외에 대한 응답을 처리하는 역할을 한다.
  • @ExceptionHandler: 특정 예외 클래스가 발생할 때 실행되는 메서드를 지정한다.
  • 예외가 발생하면, ApiUtil을 사용해 클라이언트에게 에러 메시지HTTP 상태 코드를 전달한다.

목차로 돌아가기