1. common 패키지에 advice 패키지 추가 후 GlobalExceptionHandler 클래스 생성
2. GlobalExceptionHandler 클래스 작성
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(InvalidCredentialException.class)
public ResponseEntity<Map<String, Object>> handleInvalidCredentialException(InvalidCredentialException ex) {
return getErrorResponse(HttpStatus.UNAUTHORIZED, ex.getMessage());
}
private ResponseEntity<Map<String, Object>> getErrorResponse(HttpStatus status, String message) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("status", status.name());
errorResponse.put("code", status.value());
errorResponse.put("message", message);
return new ResponseEntity<>(errorResponse, status);
}
}
3. common 패키지에 exception 패키지 추가 후 ApplicationException 클래스 생성/작성
@Getter
public class ApplicationException extends RuntimeException {
private final HttpStatus status;
public ApplicationException(String message, HttpStatus status) {
super(message);
this.status = status;
}
}
4. common 패키지에 exception 패키지 추가 후 InvalidCredentialException 클래스 생성/작성
public class InvalidCredentialException extends ApplicationException {
public InvalidCredentialException(String message) {
super(message, HttpStatus.UNAUTHORIZED);
}
}
5. 서비스 로직에서 exception 적용
@Service
@RequiredArgsConstructor
public class AuthService {
private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;
// 로그인
@Transactional(readOnly = true)
public AuthLoginResponseDto login(AuthLoginRequestDto dto) {
Member member = memberRepository.findByEmail(dto.getEmail()).orElseThrow(
() -> new InvalidCredentialException("해당 이메일이 없습니다."));
if (!passwordEncoder.matches(dto.getPassword(), member.getPassword())) {
throw new InvalidCredentialException("비밀번호가 일치하지 않습니다.");
}
return new AuthLoginResponseDto(member.getId());
}
끝!
[ GlobalExceptionHandler의 동작 원리 및 예외 처리 순서 ]
Spring Boot의 전역 예외 처리(Global Exception Handling) 기능을 사용하여 예외가 발생했을 때 일괄적으로 처리하는 방법을 구현하고 있습니다.
<1> @ControllerAdvice를 통한 글로벌 예외 처리
✅ 동작 원리
- @ControllerAdvice
- Spring MVC의 전역 예외 처리 클래스를 정의하는 어노테이션
- 컨트롤러에서 발생하는 예외를 이 클래스에서 한 곳에서 처리할 수 있도록 해줌
- @ExceptionHandler(InvalidCredentialException.class)
- InvalidCredentialException이 발생하면 이 메서드가 자동으로 실행됨
- HTTP 상태 코드 401 Unauthorized와 함께 JSON 형태의 응답을 반환
- getErrorResponse(HttpStatus status, String message)
- 에러 메시지를 Map<String, Object> 형식으로 변환
- status, code, message를 포함하여 일관된 오류 응답을 생성
✅ 예외 발생 시 응답 예시 (InvalidCredentialException 발생)
{
"status": "UNAUTHORIZED",
"code": 401,
"message": "해당 이메일이 없습니다."
}
"status": "UNAUTHORIZED",
"code": 401,
"message": "해당 이메일이 없습니다."
}
<2> ApplicationException (커스텀 예외의 부모 클래스)
✅ 동작 원리
- 모든 커스텀 예외의 부모 클래스 역할을 하는 ApplicationException
- RuntimeException을 상속받아 Unchecked Exception(체크 예외가 아님)으로 만듦
- 예외 발생 시 HTTP 상태 코드를 함께 저장할 수 있도록 필드(status) 추가
<3> InvalidCredentialException
✅ 동작 원리
- ApplicationException을 상속받아 예외 처리
- 예외가 발생하면 **HTTP 상태 코드 401 Unauthorized**가 자동 설정됨
=> InvalidCredentialException 예외가 발생하면, GlobalExceptionHandler가 이를 감지하고 적절한 JSON 응답을 반환
- 401 Unauthorized 상태 코드와 함께 에러 메시지를 포함한 JSON 응답을 전송
🚀 이 방식의 장점
- 예외 처리 코드의 중복 제거 → 서비스 코드에서 직접 ResponseEntity를 반환하지 않아도 됨
- 일관된 오류 응답 제공 → 모든 예외 응답이 같은 형식(status, code, message)을 가짐
- 유지보수 용이 → 새로운 예외 타입이 추가될 경우 @ExceptionHandler만 추가하면 됨
'개발 > 부트캠프' 카테고리의 다른 글
본캠프 : 향상된 for문, stream 사용법 (0) | 2025.03.08 |
---|---|
본캠프 : 비밀번호 암호화 (0) | 2025.03.07 |
본캠프 : Git rebase (0) | 2025.03.04 |
본캠프 : 페이징 조회 Pageable (0) | 2025.03.03 |
본캠프 : BaseEntity 사용 (0) | 2025.03.02 |