예외처리 Best Practice에 대해서 알아보자

Alex·2025년 1월 26일
0

CS를 공부하자

목록 보기
20/74

1. @ControllerAdvice를 사용해라

이를 사용하면, 전역적으로 예외를 가로채서 처리할 수 있다.

2. 애플리케이션에 맞춰서 커스텀 예외를 만들어라

@Getter
public class CustomException extends RuntimeException {

    private final CodeInterFace codeInterFace;

    public CustomException(CodeInterFace v) {
        super(v.getMessage());
        this.codeInterFace = v;
    }

    public CustomException(CodeInterFace v, String message) {
        super(v.getMessage() + message);
        this.codeInterFace = v;
    }

    public HttpStatus getHttpStatus() {
        return codeInterFace.getHttpStatus();
    }
}

3. 메시지를 보낼 땐 원인을 명시해라

명확한 메시지를 보내서, 예외의 원인을 정확하게 알려주는 게 좋다. 그래야 디버깅이 용이하다.

4. 예외를 잡는 건 가장 높은 추상화단계에서하고, 핸들링은 가장 낮은 수준에서 해라

public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User getUserById(Long id) {
        try {
            return userRepository.findById(id)
                    .orElseThrow(() -> new ResourceNotFoundException("User not found with id " + id));
        } catch (DataAccessException e) {
            throw new DatabaseAccessException("Error accessing the database", e);
        }
    }
}

이걸 보면, 예외를 가장 추상화가 높은 단계인 서비스단에서 한다. 그리고, 가장 낮은 단계인 글로벌 예외 핸들러에서 한다. 이를 통해 비즈니스 로직과 예외 처리 로직의 관심사르 분리할 수 있다.

5.폴백 메커니즘을 활용해라

특정한 상황에서는 예외를 처리하기 위해서, 폴백을 활용하는 것이 좋다.
db 예외 발생시, 메모리를 사용하도록 하는 방식이다.

@GetMapping("/users/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
    User user = userRepository.findById(id)
            .orElseGet(() -> {
                log.warn("User not found in the database, falling back to cache");
                return cacheService.getUser(id);
            });

    return ResponseEntity.ok(user);
}

DB에서 유저가 없다고 나오면, 메모리나 캐시에 유저가 있는지 확인하는 구조다. DB 장애가 발생해도, 서비스가 안정적으로 작동하도록 돕는 구조다.

6. 에러 응답은 일관된 형식으로 보내라

public class ErrorResponse {
    private final int errorCode;
    private final String errorMessage;

    public ErrorResponse(int errorCode, String errorMessage) {
        this.errorCode = errorCode;
        this.errorMessage = errorMessage;
    }

    public int getErrorCode() {
        return errorCode;
    }

    public String getErrorMessage() {
        return errorMessage;
    }
}

@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleResourceNotFoundException(ResourceNotFoundException ex) {
        ErrorResponse errorResponse = new ErrorResponse(1001, ex.getMessage());
        return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
    }
}

참고자료

  • Best Exception Handling Practices Java Spring Boot
  • Spring Boot: Exception Handling Best Practices
  • Effective Exception Handling
profile
답을 찾기 위해서 노력하는 사람

0개의 댓글