본문 바로가기

Spring

[SpringFramework] 스프링 예외 처리 방법 (프로젝트로 실전 적용!)

개인적으로 제작 중인 프로젝트에 적용시키면서 실전경험 쌓기 1 (2024.03.25)

 

https://github.com/GyuminGomin/people-driver

 

GitHub - GyuminGomin/people-driver: busan IT Academy Final Project

busan IT Academy Final Project. Contribute to GyuminGomin/people-driver development by creating an account on GitHub.

github.com

 

동기 : 개인적으로 컨트롤러를 작성하며 try catch문을 직접 사용해 모든 예외를 감싸주며 진행했는데, 너무 불편하다는 생각이 들었다. 우연히 개발자 사이트를 돌아다니는 도중, 스프링에 Exception을 전역적으로 처리해주는 방법이 있다는 것을 알게 되었고 하나씩 공부기록을 남기려고 한다.

 

1. 에러와 예외

일반적으로 에러OutOfMemoryError, StackOverflowError와 같이 발생하면 복구가 불가능한 심각한 오류를 의미하고,(JVM 실행에 생기는 문제) 예외NullPointerException, FileNotFoundException와 같이 발생하더라도 복구가 가능한 덜 심각한 오류를 의미한다.

따라서 예외 처리를 해주기 위해 try catch, throws로 예외를 다루어 서버가 중지되지 않도록 처리를 한다. 

다음과 같이 Error와 Exception들을 살펴보면 다음과 같이 엄청나게 많다는 것을 알 수 있다.

 

에러 클래스의 종류와 예외 클래스 종류

 

즉 계층을 그려보면,

예외와 에러의 hierarchy

 

가볍게 그린 것이고 모든 클래스는 java.lang 패키지에 속해있다.

'위 그림은 가볍게 저렇게 많구나' 라는 것을 느끼면 되고

 

중요한 것은 Exception 클래스는 다시 실행 예외(runtime exception)와 일반 예외(compile exception)으로 나뉜다.

 

실행 예외는 Unchecked Exception으로 예외 처리가 필수는 아니고 (즉 컴파일시에 JVM이 체크하지 않음)

일반 예외는 Checked Exception으로 반드시 예외 처리가 필수 이다. (즉 컴파일시에 JVM이 반드시 체크함!)

 

저는 여기서 Checked Exception을 try-catch로 모두 감싸줬는데 이걸 Spring에서 지원해주는 @ControllerAdvice, @ExceptionHandler로 처리해 코드의 관리가 용이하게 하고자 한다.

 

2. @ExceptionHandler, @ControllerAdvice

@ExceptionHandler는 말 그대로 스프링에서 지원해주는 예외 처리기입니다.

@Controller 어노테이션이 등록된 곳에서만 쓸 수 있으며,

@ControllerAdvice 어노테이션이 등록된 곳의 @ExceptionHandler보다 더욱 높은 우선순위를 갖습니다.

 

예를 들면,

@Controller
public class SimpleController {
	@ExceptionHandler(IOException.class)
    	public String exampleHandler() {
    		return '/error/error1';
    	}
}


@ControllerAdvice
public class ExControllerAdvice {
	@ExceptionHandler(IOException.class)
    	public String exampleHandler() {
    		return '/error/error2';
    	}
}

위와 같이 @Controller의 @ExceptionHandler가 더 우선권을 지니게 되어 IOException이 발생하였을 때, error1 페이지가 오픈됩니다.

 

적용 예시

package com.gls.ppldv.common.controller;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice("com.gls.ppldv.user.controller")
public class CommonExceptionHandler {
	
	@ExceptionHandler(Exception.class)
	public void handleException(Exception e) {
		e.printStackTrace();
	}
}

// 먼저 common.controller 패키지 아래 ExceptionHandler 클래스를 생성하고

// 6번째 라인에 적용할 패키지를 지정한 후

// 9번째 라인부터 ExceptionHandler 를 통해 어떤 예외를 어떻게 다룰 것인지 설정함

 

현재 적용 대상의 변화 모습

// 회원정보 삭제
@PostMapping("/removeUser")
public String removeUser(String email, RedirectAttributes rttrs) {
    String message = null;
    try {
        message = ms.removeUser(email);
    } catch (Exception e) {
        message = "Remove Failed Try Again!";
        e.printStackTrace();
    }

    return "redirect:/user/logout";
}

// 기존 쓸데 없이 많은 길이를 차지했던 블럭을

// 회원정보 삭제
@PostMapping("/removeUser")
public String removeUser(String email, RedirectAttributes rttrs) throws Exception{
    ms.removeUser(email); // 메시지를 반환하던 서비스 코드의 반환 값을 void로 수정해서 이렇게 되었습니다.
    
    return "redirect:/user/logout";
}

// 다음과 같이 축소해 기능을 보기 쉽게 만들 수 있었음

 

이제 제 개인 프로젝트의 예외 관련된 설정을 다 끝내고 나면,

 

기존 Interceptor로 한 권한 설정을 Spring Security로 처리하는 내용을 갖고 돌아오도록 하겠습니다.

지금까지 읽어주셔서 감사합니다! (부족한 점이 많습니다. 많은 피드백 부탁드립니다!)

 

Reference

https://docs.spring.io/spring-framework/reference/web/webflux/controller/ann-exceptions.html

 

Exceptions :: Spring Framework

@Controller and @ControllerAdvice classes can have @ExceptionHandler methods to handle exceptions from controller methods. The following example includes such a handler method: @Controller public class SimpleController { // ... @ExceptionHandler (1) public

docs.spring.io

https://docs.spring.io/spring-framework/reference/web/webflux/controller/ann-advice.html

 

Controller Advice :: Spring Framework

Typically, the @ExceptionHandler, @InitBinder, and @ModelAttribute methods apply within the @Controller class (or class hierarchy) in which they are declared. If you want such methods to apply more globally (across controllers), you can declare them in a c

docs.spring.io

 

https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%97%90%EB%9F%ACError-%EC%99%80-%EC%98%88%EC%99%B8-%ED%81%B4%EB%9E%98%EC%8A%A4Exception-%F0%9F%92%AF-%EC%B4%9D%EC%A0%95%EB%A6%AC

 

☕ 자바 에러(Error) 와 예외 클래스(Exception) 💯 이해하기

프로그래밍의 오류 종류 프로그램에서 오류가 발생하면 시스템 레벨에서 프로그램에 문제를 야기하여 원치 않는 버그를 일으키거나, 심각하면 실행 중인 프로그램을 강제로 종료시키도 한다.

inpa.tistory.com

 

혼자 공부하는 자바 (저자 : 신용권, 출판사 : 한빛미디어)

https://hongong.hanbit.co.kr/%EC%9E%90%EB%B0%94/

 

혼자 공부하는 자바(개정판)

혼자 공부하는 자바가 더욱 풍성한 내용을 담아 돌아왔습니다! 개정판에서는 자바 21 최신 버전을 반영했고, 강화된 언어 기능을 담은 실전 예제를 추가했습니다. 이 책을 통해 자바의 핵심 문법

hongong.hanbit.co.kr

 

초보 웹 개발자를 위한 스프링 프로그래밍 입문 (저자 : 최범균, 출판사 : 가메출판사)

https://product.kyobobook.co.kr/detail/S000001248954

 

스프링5 프로그래밍 입문 | 최범균 - 교보문고

스프링5 프로그래밍 입문 | 스프링 프레임워크의 버전업으로 개선된 내용을 담았습니다.필자의 한마디 : 처음 스프링을 배우고자 하는 독자들이 입문할 때 필요한 것은 스프링의 방대한 내용이

product.kyobobook.co.kr