Programing/Java & Spring

세무민의 코딩일기 : Spring WebClient doOnError와 onErrorResume 차이

세기루민 2025. 3. 26. 12:00
728x90
doOnErroronErrorResume은 Spring WebFlux의 WebClient와 같은 반응형 프로그래밍에서 오류를 다루는 데 사용되는 메서드인데, 목적과 동작 방식에서 차이가 있어서 간단히 소개해보려고 함

doOnError

  • 로깅, 메트릭 기록, 알림 전송 등과 같이 오류가 발생했을 때 오류를 처리하지 않지만 발생했다는 사실만 감지하여 추가 작업을 수행할 수 있는 매서드
  • 즉, 오류를 처리하거나 복구하지 않고, 오류가 발생했다는 사실을 감지해 추가 작업을 수행하고 이후 오류는 스트림 아래로 그대로 전달
  • 반환 값은 없으며 보통 에러 로그를 남기기 위해 사용됨

 

doOnError 예시 코드

WebClient webClient = WebClient.create("https://sg-moomin.tistory.com");
String exceptionDefaultMessage = "exception occurred to";

webClient.get()
    .uri("/contents")
    .retrieve()
    .bodyToMono(String.class)
    .doOnError(throwable -> System.err.println(exceptionDefaultMessage + throwable.getMessage()))
    .subscribe(
    	...
    );

 

doOnError 사용 목적 

  • 오류를 기록하거나 모니터링하고 싶을 경우나 단순 감지만 해도 문제가 없는 경우 

onErrorResume

  • 오류가 발생했을 때 오류에 대해 해결하고 새로운 스트림(Mono, Flux)을 제공하여 정상적으로 Flow를 흘림 
  • 즉, 오류 전파가 되지 않는다는 의미이며 더 이상 아래 Flow로 오류를 전달하지 않음
    • 예외 처리를 하지 않아도 되는 상황이지만 로그를 남겨야할 경우 적합하다고 볼 수 있음 

 

onErrorResume 예시 코드

WebClient webClient = WebClient.create("https://sg-moomin.tistory.com");
String exceptionDefaultMessage = "exception occurred to";
String newStream = "onErrorResume By new Mono";

webClient.get()
    .uri("/data")
    .retrieve()
    .bodyToMono(String.class)
    .onErrorResume(throwable -> {
        System.err.println(exceptionDefaultMessage + throwable.getMessage());
        // 새로운 스트림을 생성
        return Mono.just(newStream);
    })
    .subscribe(
    	...
    );
  • API 호출 실패 시 exceptionDefaultMessage를 출력하고 새로운 스트림(newStream)을 반환한다.
  • 이에 따라 error 전파가 되지 않으며, 만약 subscribe에서 error 람다를 호출하더라도 error가 실행되지 않는다. 
  • 현재는 Mono에 기본값을 넣어뒀는데 이는 예외가 발생하더라도 후속 로직을 추가해줬다고 볼 수 있으며 후속 로직 없이 예외 자체를 무시하고 싶을 경우에는 Mono.Empty를 반환하면 됨

 

onErrorResume 사용 목적

  • 오류가 발생했을 때 대체 로직으로 Flow를 수행하고 싶을 때나 사용자에게 오류 상황을 노출시키지 않고 싶을 때 사용

doOnError vs onErrorResume 차이점 정리

  doOnError onErrorResume
목적 부수 효과 실행 (로깅 등) 오류 복구 및 대체 값 제공
오류 전파 오류를 그대로 전달 오류를 잡고 전파 중단
스트림 변경 변경 없음 새로운 Mono/Flux로 대체
반환값 없음 새로운 Mono/Flux
사용 시나리오 오류 관찰 및 기록 오류 해결 및 스트림 지속

 


기타

1) doOnError와 onErrorResume을 같이 쓸수도 있음?

doOnError와 onErrorResume을 둘다 함께 사용할 수 있는데, 굳이 두개를 같이 쓰는건 비효율적이라고 생각함 

그 이유는 onErrorResume에서도 로깅과 같은 부분은 처리가 가능하기 때문에 불필요한 중복 로직이 들어갈 수도 있고

단순 로깅 혹은 오류 전파 중단을 위해 사용하는거라면 함께 사용하는건 비추임

 

오히려 onErrorResume 단일으로 사용하는게 조금 더 효율적이지 않을까 하는게 주관적인 의견임

  • 오류 전파를 하고 싶다면 같이 써야하겠지만. 새로운 Stream을 통해 결과를 반환하고 서비스 로직에서 후처리해도 무관하지 않을까 싶음
728x90