본문으로 건너뛰기
홈
기술
기술 전체
프로그래밍68
컴퓨터 과학63
AI48
웹 개발36
인프라33
데이터31
소프트웨어 공학18
소개
← 목록으로프로그래밍 › 비동기 › 리액티브 프로그래밍

9. RxJava error 연산자

목차

RxJava error: 값 대신 실패 신호 보내기

Flowable.error(cause)는 구독되면 onNext 없이 onError(cause)를 보낸다. 실패는 종료 신호이므로 같은 구독에서 그 뒤의 onComplete나 새 값은 오지 않는다. empty()는 정상적으로 값이 없는 상태, never()는 끝나지 않은 상태다. 세 연산자가 화면에 같은 “값 없음”처럼 보이더라도 후속 처리에는 큰 차이가 난다.

error 연산자의 시간선

그림의 X가 오류다. X 이후 원이나 완료선이 없다는 것은 이 소스가 더 이상 값을 전달하지 않는다는 뜻이다.

오류 신호의 시점

import io.reactivex.Flowable;

public class ErrorExample {
    public static void main(String[] args) {
        Flowable<String> source = Flowable.error(
            new IllegalArgumentException("잘못된 요청")
        );
        System.out.println("구독 전");
        source.subscribe(
            System.out::println,
            error -> System.out.println("오류: " + error.getMessage()),
            () -> System.out.println("완료")
        );
        System.out.println("구독 후");
    }
}

별도 스케줄러가 없는 이 예제의 예상 순서는 구독 전 → 오류: 잘못된 요청 → 구독 후다. 예외 객체는 Flowable.error(...)를 호출할 때 만들어졌지만 오류 신호는 구독 시 전달된다. 구독마다 새 예외 객체가 필요하면 해당 버전의 error(() -> new IllegalArgumentException(...)) 오버로드를 쓴다. 콜백에서 오류를 받지 않으면 전역 오류 처리 경로에 맡기게 되어 장애를 놓치기 쉽다.

앞의 값을 살리고 뒤는 멈춘다

Flowable.concat(
    Flowable.just("A"),
    Flowable.<String>error(new IllegalStateException("중단")),
    Flowable.just("B")
).subscribe(
    System.out::println,
    error -> System.out.println(error.getMessage())
);
// A, 중단. B 소스는 구독되지 않음

concat은 이전 소스가 정상 완료해야 다음으로 이동한다. A 뒤의 오류 소스가 실패로 종료하므로 B에 도달하지 못한다. 반면 Flowable.empty()는 정상 완료하므로 다음 소스로 넘어간다. 어떤 입력이 비어 있어 무시해도 되는지와 전체 작업을 중단해야 하는지는 업무 규칙으로 결정한다.

Flowable.<String>error(new IllegalStateException("원본 실패"))
    .onErrorResumeNext(Flowable.just("대체 결과"))
    .subscribe(System.out::println); // 대체 결과

복구 연산자를 오류 뒤에 붙이면 실패를 대체 스트림으로 바꾸고 전체가 정상 완료할 수 있다. 단, 대체값이 실제 결과와 구별되지 않으면 실패를 숨기는 문제가 생긴다. 일시적 외부 서비스 장애에 캐시를 돌려줄지, 입력 검증 오류를 호출자에게 그대로 알릴지 분리한다. 구독을 취소한 뒤에는 더 이상 오류와 대체값을 기다리지 않으며, 비동기 소스라면 해당 작업의 취소 가능 여부도 확인한다.

참고: ReactiveX Empty/Never/Error, RxJava 2 Flowable API

같은 카테고리의 글