🚀 Spring Boot 예외 처리 및 Global Exception Handling
✅ 1️⃣ 서론 - 예외 처리가 필요한 이유
✅ 2️⃣ Spring Boot에서 예외 처리하는 방법
✅ 3️⃣ @ControllerAdvice를 활용한 Global Exception Handling
✅ 4️⃣ 커스텀 예외(Custom Exception) 및 응답 형식 설정
✅ 5️⃣ REST API의 예외 처리 베스트 프랙티스
1️⃣ 서론 - 예외 처리가 필요한 이유
🔹 예외(Exception)란?
- 프로그램 실행 중 예상치 못한 상황이 발생하면 **예외(Exception)**가 발생
- 예를 들어 DB 조회 시 데이터가 없거나, 잘못된 입력값이 들어온 경우
🔹 예외 처리가 중요한 이유
✅ API 응답을 표준화 → 프론트엔드에서 예외 응답을 일관되게 처리 가능
✅ 보안 강화 → 내부 서버 오류를 사용자에게 노출하지 않음
✅ 디버깅 및 유지보수 용이 → 오류를 로그로 남겨 빠르게 문제 해결 가능
🔥 Spring Boot에서는 다양한 방법으로 예외를 처리할 수 있음!
이제 예외 처리 방법을 단계별로 살펴보자.
2️⃣ Spring Boot에서 예외 처리하는 방법
🔹 1. 기본적인 예외 처리 (Try-Catch 활용)
가장 기본적인 예외 처리 방법은 try-catch 블록을 사용하는 것
📌 예제 코드 (PostService.java)
public Post getPostById(Long id) {
try {
return postRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Post not found"));
} catch (RuntimeException e) {
System.out.println("예외 발생: " + e.getMessage());
return null;
}
}
✅ 하지만 이 방식은 API 응답을 표준화할 수 없고, 코드 중복이 발생함
🔥 따라서 Spring Boot의 Global Exception Handling을 활용하자!
3️⃣ @ControllerAdvice를 활용한 Global Exception Handling
🔹 1. @ControllerAdvice란?
- 모든 컨트롤러에서 발생하는 예외를 한 곳에서 처리할 수 있도록 도와주는 어노테이션
- **전역 예외 처리 (Global Exception Handling)**을 구현할 때 사용
🔹 2. Global Exception Handler 구현
📌 예제 코드 (GlobalExceptionHandler.java)
package com.example.demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice // REST API 예외 처리를 위한 전역 핸들러
public class GlobalExceptionHandler {
@ExceptionHandler(RuntimeException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public String handleRuntimeException(RuntimeException e) {
return "예외 발생: " + e.getMessage();
}
}
✅ 이제 모든 RuntimeException이 발생하면 GlobalExceptionHandler가 자동으로 예외를 처리!
📌 예외 발생 시 응답 예제 (API 호출)
GET /api/posts/100
{
"예외 발생": "Post not found"
}
4️⃣ 커스텀 예외(Custom Exception) 및 응답 형식 설정
🔹 1. 커스텀 예외 클래스 만들기
📌 예제 코드 (PostNotFoundException.java)
package com.example.demo.exception;
public class PostNotFoundException extends RuntimeException {
public PostNotFoundException(String message) {
super(message);
}
}
🔹 2. Service에서 커스텀 예외 적용
📌 예제 코드 (PostService.java)
public Post getPostById(Long id) {
return postRepository.findById(id)
.orElseThrow(() -> new PostNotFoundException("해당 게시글을 찾을 수 없습니다. ID: " + id));
}
🔹 3. Global Exception Handler에서 커스텀 예외 처리
📌 예제 코드 (GlobalExceptionHandler.java)
@ExceptionHandler(PostNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ErrorResponse handlePostNotFoundException(PostNotFoundException e) {
return new ErrorResponse("404", e.getMessage());
}
📌 예외 응답 모델 (ErrorResponse.java)
package com.example.demo.exception;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public class ErrorResponse {
private String status;
private String message;
}
✅ 이제 예외 발생 시 표준화된 JSON 응답을 받을 수 있음!
📌 예외 발생 시 응답 예제 (API 호출)
GET /api/posts/100
{
"status": "404",
"message": "해당 게시글을 찾을 수 없습니다. ID: 100"
}
5️⃣ REST API의 예외 처리 베스트 프랙티스
✅ 1. HTTP 상태 코드 적절히 사용
- 400 BAD REQUEST → 잘못된 요청 (유효성 검사 실패)
- 401 UNAUTHORIZED → 인증 실패
- 403 FORBIDDEN → 접근 권한 없음
- 404 NOT FOUND → 존재하지 않는 리소스
- 500 INTERNAL SERVER ERROR → 서버 내부 오류
✅ 2. 예외 응답을 JSON 형태로 표준화
{
"status": "404",
"message": "해당 게시글을 찾을 수 없습니다."
}
✅ 3. 전역 예외 처리 (@ControllerAdvice)를 적극 활용
- 모든 컨트롤러에서 발생하는 예외를 한 곳에서 관리 가능
- 서비스 로직에서 예외 처리를 단순화하여 코드 품질 향상
✅ 4. 커스텀 예외 클래스를 만들어 명확한 예외 처리
- UserNotFoundException, InvalidRequestException 등 의미 있는 예외를 정의하여 코드 가독성 향상
✅ 5. API 문서(Swagger)와 연동하여 예외 상황을 문서화
- 예외 응답도 API 문서에 포함하여 클라이언트 개발자가 쉽게 이해할 수 있도록 제공
🎯 마무리: Global Exception Handling을 적용한 예외 처리 최적화
🔥 Spring Boot에서 예외 처리는 단순한 Try-Catch를 넘어서 전역 예외 처리(@ControllerAdvice)를 활용해야 함!
✅ Global Exception Handling을 적용하면 API 응답을 표준화하고 유지보수를 쉽게 할 수 있음
✅ 커스텀 예외를 활용하면 의미 있는 오류 메시지를 제공할 수 있음
✅ Swagger와 연동하여 API 문서를 통해 예외 응답을 정의하는 것이 베스트 프랙티스
🚀 이제 실전 프로젝트에 적용하여 안정적인 RESTful API를 구축해보자!