본문으로 바로가기
학습 목표
1. @ControllerAdvice, @RestControllerAdvice 는 뭘까?
2. @ControllerAdivce 와 @RestControllerAdivce 에 차이점을 이해 하자
3. 사용자 정의 예외 클래스를 만들기
4. @ControllerAdvice 구현해 보기
5. 에러 페이지 코드 수정 (errorPage.jsp)
6. 직업 예외 발생해보기

1. @ControllerAdvice, @RestControllerAdvice 는 뭘까?

HTTP 통신을 통해 예외 상황을 클라이언트에게 알려주는 방법은 여러 가지가 있으며, 이들을 적절히 사용하는 것이 중요합니다.

 

@ControllerAdvice 와 @RestControllerAdvice 는 Spring Framework에서 제공하는 어노테이션들로, 애플리케이션 전역에 걸쳐 발생하는 예외를 효과적으로 관리하고 처리하는 데 사용됩니다. 이들은 일종의 "예외 처리의 중앙 집중화"를 가능하게 해주며, 애플리케이션 내 여러 컨트롤러나 서비스에서 공통적으로 발생할 수 있는 예외를 한 곳에서 관리할 수 있게 해줍니다.

 

2. @ControllerAdivce 와 @RestControllerAdivce 에 차이점을 이해 하자.

@ControllerAdvice와 @RestControllerAdvice 차이점

  • @ControllerAdvice: 이 어노테이션은 주로 @Controller 또는 @RequestMapping 어노테이션이 적용된 클래스(즉, MVC 컨트롤러)에서 발생하는 예외를 처리하기 위해 사용됩니다. HTML 뷰를 반환하는 전통적인 웹 애플리케이션에서 주로 사용됩니다.
  • @RestControllerAdvice: **@ControllerAdvice**와 유사한 기능을 제공하지만, **@RestController**에서 발생하는 예외를 처리하는 데 특화되어 있습니다. 즉, RESTful 웹 서비스에서 JSON이나 XML 같은 응답을 반환할 때 사용됩니다. 사실상, **@RestControllerAdvice**는 **@ControllerAdvice**에 **@ResponseBody**를 추가한 것과 동일한 효과를 제공하여, 응답 본문에 직접 데이터를 매핑할 수 있습니다.

예시 코드 확인 - 1

ControllerAdvice 에서 데이터를 반환하는 예시 코드

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = ResourceNotFoundException.class)
    @ResponseBody
    public ResponseEntity<Object> handleResourceNotFoundException(ResourceNotFoundException ex) {
        // 에러 메시지와 함께 404 상태 코드를 반환
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }
}

 

예시 코드 확인 - 2

RestControllerAdvice 에서 반환

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = ResourceNotFoundException.class)
		// @ResponseBody 사용 안해도 됨(데이터를 반환 처리 함) 
    public ResponseEntity<Object> handleResourceNotFoundException(ResourceNotFoundException ex) {
        // 에러 메시지와 함께 404 상태 코드를 반환
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }
}

 

 

 

3. 사용자 정의 예외 클래스를 만들기

RuntimeException은 프로그램의 실행 도중 발생하는 예외를 나타냅니다. 컴파일 시 예외가 아닌 실행 시 예외로 분류되며, 따로 try-catch 블록으로 처리하지 않아도 컴파일러가 오류로 인식하지 않습니다.

예시로는 NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException 등이 있습니다. 여기서는 RuntimeException 확장해서 사용자 정의 예외 클래스를 만들어 봅니다.

 

 

 

 

위 그림처럼 패키지와 자바 파일을 만들어 주세요 (handler/GlobalControllerAdivce.java 파일 생성)

  • handler/GlobalControllerAdivce.java 파일 생성
  • handler/exception 패키지 생성
  • handler/exception/UnAuthorizedException 자바 파일 생성

: UnAuthorizedException 클래스는 인증이 안된 사용자가 인증이 필요하 서비스에 접근 요청을 할 때 예외를 발생 시킬 사용자 정의 예외 클래스를 설계 합니다.

 

package com.tenco.bank.handler.exception;

import org.springframework.http.HttpStatus;

import lombok.Getter;

@Getter
public class UnAuthorizedException extends RuntimeException  {
	
	private HttpStatus status; 
	
	// throw new UnAuthorizedException(   ,  ) 
	public UnAuthorizedException(String message, HttpStatus status) {
		super(message);
		this.status = status;
	}
	
}

 

package com.tenco.bank.handler.exception;

import org.springframework.http.HttpStatus;

import lombok.Getter;

// 에러 발생시에 여러 페이지로 이동 시킬 때 사용 예정 

@Getter
public class RedirectException extends RuntimeException {
	
	private HttpStatus status;
	
	// throw new RedirectException(???, ???);
	public RedirectException(String message, HttpStatus status) {
		super(message);
		this.status = status;
	}
	
}
package com.tenco.bank.handler.exception;

import org.springframework.http.HttpStatus;

import lombok.Getter;

@Getter
public class DataDeliveryException extends RuntimeException {
	
	private HttpStatus status;
	
	public DataDeliveryException(String message, HttpStatus status) {
		super(message);
		this.status = status;
	}

}

 

 

4.@ControllerAdvice 구현해 보기

 

package com.tenco.bank.handler;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.tenco.bank.handler.exception.DataDeliveryException;
import com.tenco.bank.handler.exception.RedirectException;
import com.tenco.bank.handler.exception.UnAuthorizedException;

@ControllerAdvice  // IoC 대상 (싱글톤 패턴) --> HTML 렌더링 예외에 많이 사용
public class GlobalControllerAdvice {
	
	/**
	 * (개발시에 많이 활용) 
	 * 모든 예외 클래스를 알 수 없기 때문에 로깅으로 확인할 수 있도록 설정  
	 * 로깅처리 - 동기적 방식(System.out.println), @slf4j (비동기 처리 됨) 
	 */
	@ExceptionHandler(Exception.class)
	public void exception(Exception e) {
		System.out.println("----------------------");
		System.out.println(e.getClass().getName());
		System.out.println(e.getMessage());
		System.out.println("----------------------");
	}
	
	/**
	 * Data로 예외를 내려주는 방법 
	 * @ResponseBody 활용 
	 * 브라우저에서 자바스크립트 코드로 동작 하게 됨
	 */
	
	// 예외를 내릴 때 데이터를 내리고 싶다면 1. @RestControllerAdvice 를 사용하면 된다.
	// 단. @ControllerAdvice 사용하고 있다면 @ResponseBody 를 붙여서 사용하면 된다. 
	@ResponseBody
	@ExceptionHandler(DataDeliveryException.class)
	public String dataDeleveryExcption(DataDeliveryException e) {
		StringBuffer sb = new StringBuffer();
		sb.append("<script>");
		sb.append("alert('"+ e.getMessage()  +"')");
		sb.append("window.history.back();");
		sb.append("</script>");
		return sb.toString(); 
	}
	
	@ResponseBody
	@ExceptionHandler(UnAuthorizedException.class)
	public String unAuthorizedException(UnAuthorizedException e) {
		StringBuffer sb = new StringBuffer();
		sb.append("<script>");
		sb.append("alert('"+ e.getMessage()  +"')");
		sb.append("window.history.back();");
		sb.append("</script>");
		return sb.toString(); 
	}
	
	/*
	 *  에러 페이지로 이동 처리 
	 *  JSP로 이동시 데이터를 담아서 보내는 방법 
	 *  ModelAndView, Model 사용 가능 
	 *  throw new RedirectException('페이지 없는데???', 404);
	 */
	@ExceptionHandler(RedirectException.class)
	public ModelAndView redirectException(RedirectException e) {
		ModelAndView modelAndView = new ModelAndView("errorPage");
		modelAndView.addObject("statusCode", e.getStatus().value());
		modelAndView.addObject("message", e.getMessage());
		return  modelAndView; // 페이지 반환 + 데이터 내려줌 
	}
	
}

 

 

5. 에러 페이지 생성 (errorPage.jsp)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>${statusCode} Error - Page Not Found</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
<style type="text/css">
	body {
		display: flex;
		justify-content: center;
		align-items: center;
		height: 100vh;
	}
	
	.error--message {
		text-align: center;
		margin-bottom: 20px;
	}
	
</style>
</head>
<body>
	<div class="container">
		<div class="text-center">
			<h1>${statusCode}</h1>
			<p class="error--message"> Page Not Found </p>
			<p>${message}</p>
			<a href="/index" class="btn btn-primary">Go to Home Page</a>
		</div>
	</div>
</body>
</html>

 

'Spring boot' 카테고리의 다른 글

# 12. MyBatis 설정 (DB 접근 기술이란?)  (1) 2024.08.07
# 11. 어노테이션 정리  (0) 2024.08.07
# 9. MainController, mainPage.jsp 구현  (2) 2024.08.06
# 7. 화면 구현 - 1(템플릿 가져오기)  (0) 2024.08.06
# 6. 모델링  (0) 2024.08.06