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

8. RxJava empty 연산자

목차

RxJava empty: 값 없이 정상 완료

Flowable.empty()는 onNext를 호출하지 않고 바로 onComplete를 보낸다. “데이터가 없다”와 “작업이 실패했다”를 구분하는 정상 결과다. RxJava 2는 null 값을 onNext로 보낼 수 없으므로 빈 결과를 표현할 때 null을 통지하려고 하면 안 된다.

empty 연산자의 시간선

그림에는 값 원이 없고 마지막의 완료선만 있다. never에는 이 완료선이 없고 error에는 완료선 대신 X가 있다. 출력 값만 보면 셋 모두 비어 보일 수 있지만, 다음 연산자로 흐름이 이어질 수 있는지는 다르다.

구독 시 일어나는 일

import io.reactivex.Flowable;

public class EmptyExample {
    public static void main(String[] args) {
        System.out.println("구독 전");
        Flowable.<String>empty().subscribe(
            value -> System.out.println("값: " + value),
            error -> System.out.println("오류: " + error),
            () -> System.out.println("완료")
        );
        System.out.println("구독 후");
    }
}

별도 스케줄러가 없으므로 예상 순서는 구독 전 → 완료 → 구독 후다. subscribe가 동기적으로 완료 신호를 전달하고 돌아온다. empty() 자체는 백그라운드 작업이나 대기를 만들지 않는다. 같은 코드에서 never()를 쓰면 가운데 완료가 사라진다.

concat과 대체값에서의 역할

Flowable.concat(
    Flowable.just("A"),
    Flowable.<String>empty(),
    Flowable.just("B")
).subscribe(System.out::println); // A, B

Flowable.<String>empty()
    .switchIfEmpty(Flowable.just("검색 결과 없음"))
    .subscribe(System.out::println); // 검색 결과 없음

첫 예제에서 concat은 A 소스가 완료된 뒤 빈 소스를 구독한다. 빈 소스는 즉시 완료하므로 다음 B 소스로 이동한다. 두 번째 예제의 switchIfEmpty는 원본이 값을 하나도 내지 않고 완료한 경우에만 대체 소스를 구독한다. 원본이 오류를 내면 빈 결과가 아니므로 이 대체 경로로 가지 않는다. 한 개의 기본값만 필요하면 defaultIfEmpty("검색 결과 없음")도 선택할 수 있다.

입력 값 중 조건에 맞지 않는 것만 빼고 싶으면 flatMap 안에서 빈 내부 스트림을 반환할 수 있다.

Flowable.just("A", "", "B")
    .flatMap(value -> value.isEmpty()
        ? Flowable.<String>empty()
        : Flowable.just(value))
    .subscribe(System.out::println); // A, B

다만 이 경우처럼 단순한 제외는 .filter(value -> !value.isEmpty())가 더 명확하다. empty()를 외부 시스템의 예외를 숨기기 위한 일반적인 대체로 쓰면 운영에서 장애를 정상적인 빈 결과로 착각할 수 있다. 오류가 정상적인 부재인지, 실패인지 먼저 정해야 한다.

즉시 완료하는 소스에는 오래 유지할 작업이 없지만, empty()를 포함한 상위의 비동기 조합은 구독 수명이 남을 수 있다. 전체 체인의 취소는 실제 작업을 하는 다른 소스까지 고려해 관리한다.

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

같은 카테고리의 글