본문 바로가기
JAVA

[Java] Exception Error message Front-end error message로 뿌리기.

by 승븐지 2025. 12. 22.
반응형
개발을 하다가 문득 exception에 에러 메시지 성공 메시지 등을 뿌려주지를 않는,, 기이한 현상을 발견했다. 화면 개발자 입장에서는 생각해보면 당연한거였는데 혼자 다 하려다보니까 이러한 에러 메시지는 JAVA에서만  처리를 해놓고 그 메시지를 화면에 뿌려줘야하는 것을 까먹고 있었다. 그래서 Exception에 대한 처리를 추가했다.

 

우선 패키지 구조는 @SpringBootApplication이 선언된 하위 패키지이다.

구조는 exception이라는 폴더를 만들어서 진행를 하려고한다. 

우선 가장 먼저 BusinessException , GlobalExceptionHandler라는 파일을 만들겠다.

BusinessException 파일 소스
package com.test.gw.exception;

/**
 * 비즈니스 규칙 위반 시 사용하는 커스텀 예외
 *
 * - 서버 장애(Exception)와 구분하기 위함
 * - 예: 고객 중복, 필수값 누락, 상태상 저장 불가 등
 * - GlobalExceptionHandler에서 잡아서 400(Bad Request)로 내려줌
 */
public class BusinessException extends RuntimeException {

    /**
     * @param message 프론트엔드에 그대로 전달할 사용자용 메시지
     */
    public BusinessException(String message) {
        super(message);
    }
}

 

GlobalExceptionHandler.java 파일 소스 
package com.test.gw.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Map;

/**
 * 전역 예외 처리 클래스
 *
 * - Controller / Service 어디에서 발생한 예외든 여기서 공통 처리
 * - 프론트엔드에 내려줄 HTTP 상태 코드와 메시지를 표준화
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 비즈니스 예외 처리
     *
     * - BusinessException은 "사용자 입력/상태 문제"
     * - HTTP 400 (Bad Request)로 응답
     * - message는 프론트에서 alert / toast로 그대로 사용
     */
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<?> handleBusinessException(BusinessException e) {
        return ResponseEntity
                .status(HttpStatus.BAD_REQUEST)
                .body(Map.of(
                        "code", "BUSINESS_ERROR",  // 프론트 분기용 코드
                        "message", e.getMessage()  // 실제 사용자 메시지
                ));
    }
    /**
     * 그 외 모든 예외 처리 (예상하지 못한 서버 오류)
     *
     * - NullPointerException, SQLException 등
     * - HTTP 500 (Internal Server Error)
     * - 실제 오류 메시지는 로그로만 남기고,
     *   사용자에게는 공통 메시지 제공
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> handleException(Exception e) {
        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR) // 500
                .body(Map.of(
                        "code", "SERVER_ERROR",
                        "message", "서버 오류가 발생했습니다."
                ));
    }
}

 

service단에서 실제 사용예시이다.
// BusinessException에 대한 처리이다.
if (dup != null) {
    throw new BusinessException(
            "이미 다른 품목에서 사용 중인 LOT 번호입니다. (LOT: " + noLot + ")"
    );
}

 

 

실제로 프론트엔드에서 뿌려지는 문구를 확인해보자. 저장 버튼 클릭시 번호가 중복되면은 문구를 띄워줬다.
네트워크 상태를 보면은 정상적으로 넘어온게 확인이된다.

 

try {
    const listAction = await dispatch(
      getTestList({...searchParams, test: selectedRow?.test ?? testList?.[0]?.test ?? ""})
    );
    const payload = listAction.payload as Payload;
    if (payload.status === 200 && payload.data) {
        console.log(payload);
    }
    showAlert("저장되었습니다.");
        
  } catch (err) {
    let message = "저장에 실패했습니다.";

    // 에러문구는 여기서 표출을 시켜준다.
    if (typeof err === "object" && err !== null) {
      const anyErr = err as any;

      message =
        anyErr?.message ??
        anyErr?.response?.data?.message ??
        message;
    }
    showAlert(message);
  }
};

 

반응형