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

4. RxJava range와 rangeLong 연산자

목차

RxJava range와 rangeLong: 연속 번호 만들기

Flowable.range(start, count)의 두 번째 인자는 끝값이 아니라 통지할 개수다. range(3, 5)는 3, 4, 5, 6, 7을 차례로 보낸 뒤 완료한다. rangeLong은 같은 규칙으로 Long 값을 만든다. 원래 글에는 같은 예시가 두 번 반복돼 있어 결과 해석을 하나로 정리했다.

range 연산자의 시간선

그림의 연속된 원은 숫자 하나씩의 통지, 마지막 선은 정상 완료다. 원 사이의 간격이 1초라는 뜻은 아니다. range는 시간을 재지 않고, 별도 스케줄러가 없다면 구독 호출 스레드에서 가능한 만큼 값을 보낸다.

시작값과 개수 계산

import io.reactivex.Flowable;

public class RangeExample {
    public static void main(String[] args) {
        Flowable.range(3, 5).subscribe(
            value -> System.out.println("값 " + value),
            Throwable::printStackTrace,
            () -> System.out.println("완료")
        );
    }
}
// 예상 출력: 값 3, 값 4, 값 5, 값 6, 값 7, 완료

count=5이므로 마지막 값은 start + count - 1 = 7이다. 구독 전에 모든 숫자를 담은 목록을 만들지 않고 필요할 때 순서대로 생성할 수 있다. Flowable은 하류의 request(n)에 맞춰 통지를 진행할 수 있으므로 요청하지 않은 값을 무조건 밀어 넣는 시간 기반 interval과 다르다. 일반적인 subscribe 콜백은 배압 요청을 직접 보여주지 않으니 직접 관찰하려면 Subscriber의 Subscription.request를 구현한다.

완료와 조기 종료

Flowable.range(3, 5)
    .take(2)
    .concatWith(Flowable.just(99))
    .subscribe(System.out::println);
// 3, 4, 99

take(2)는 두 값 뒤에 상류 range 구독을 취소하고 결과 스트림은 완료한다. 그래서 concatWith가 다음 소스 99를 구독할 수 있다. 이와 달리 중간에 never()를 연결하면 정상 완료가 오지 않아 다음 소스로 가지 못한다. range(3, 0)은 값 없이 바로 완료하므로 empty()처럼 다음 소스로 넘어갈 수 있다.

음수 count는 잘못된 설정이다. 시작값과 개수 때문에 int 범위를 넘어가는 경우에는 range로 무리하게 번호를 만들지 말고 rangeLong을 검토한다. 그러나 rangeLong도 long의 범위를 넘을 수는 없다. 대용량 번호는 생성 비용뿐 아니라 하류가 처리하는 총 건수가 지연과 저장소 부하를 결정하므로 개수를 제한한다. 주기적 번호가 필요하면 interval을 사용하되 종료와 초과 데이터 정책을 함께 정한다.

참고: ReactiveX Range, RxJava 2 Flowable API

같은 카테고리의 글