본문 바로가기
Flutter & Dart

Flutter & Dart - Stream,StreamBuilder

by 방정맞은사람 2025. 1. 7.

 

 

Stream과 StreamBuilder의 이해

Stream이란?

Stream은 Dart에서 비동기적으로 연속적인 데이터 이벤트를 전달하는 방식입니다. 마치 데이터의 흐름을 관리하는 파이프라인과 같으며, 비동기 처리에서 강력한 도구로 사용됩니다. 방송 플랫폼에 비유하자면, 스트리머가 데이터를 송출하고 시청자가 이를 구독하는 구조와 같습니다.

Stream의 특징:

  • 데이터를 순차적으로 전달합니다.
  • 데이터 이벤트에는 data, error, done의 세 가지 유형이 있습니다.
  • 필요에 따라 데이터를 지연 생성(lazy production)할 수 있습니다.

Stream의 주요 상태:

  • Idle 상태: Stream이 아직 데이터 이벤트를 생성하지 않은 초기 상태입니다.
  • Active 상태: 데이터를 방출하고 리스너가 이를 구독하는 상태입니다.
  • Paused 상태: 구독자가 일시 중지된 상태로, 데이터 방출이 일시적으로 멈춥니다.
  • Done 상태: Stream이 데이터를 모두 방출하고 종료된 상태입니다.

Stream의 생성

Stream은 데이터를 순차적으로 방출하며, async*yield를 사용하여 쉽게 생성할 수 있습니다.


Stream<int> countStream(int max) async* {
  for (int i = 1; i <= max; i++) {
    await Future.delayed(Duration(seconds: 1));
    yield i;
  }
}
    

생성 로직:

  • async*: 비동기 스트림 생성 함수로, 데이터를 비동기적으로 방출합니다.
  • yield: 데이터를 하나씩 스트림으로 방출합니다.
  • 지연 생성: 각 데이터 방출은 Future.delayed로 1초 간격을 두고 이루어집니다.

Stream 사용하기

Stream을 사용하여 데이터를 처리하려면 listen 메서드를 사용합니다.


countStream(5).listen((event) {
  print('$event 초가 지났습니다.');
});
    

실행 결과:

1 초가 지났습니다.
2 초가 지났습니다.
3 초가 지났습니다.
4 초가 지났습니다.
5 초가 지났습니다.
    

내부 동작:

  • listen: Stream에 리스너를 추가하여 데이터를 구독합니다.
  • Stream이 데이터를 방출할 때마다 리스너의 콜백 함수가 호출됩니다.

StreamBuilder로 UI에 연결

StreamBuilder를 사용하면 Stream 데이터를 실시간으로 Flutter 위젯에 반영할 수 있습니다.


StreamBuilder<int>(
  stream: countStream(5),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) {
      return CircularProgressIndicator();
    } else if (snapshot.hasError) {
      return Text('Error: ${snapshot.error}');
    } else if (snapshot.hasData) {
      return Text('${snapshot.data} 초가 지났습니다.');
    } else if (snapshot.connectionState == ConnectionState.done) {
      return Text('완료');
    }
    return Container();
  },
);
    

설명:

  • snapshot.connectionState: Stream의 현재 상태를 나타냅니다.
    • waiting: 초기 로딩 중.
    • active: 데이터 방출 중.
    • done: 스트림이 종료된 상태.
  • snapshot.hasData: 스트림에서 데이터를 받았는지 여부를 확인.
  • snapshot.hasError: 스트림에서 에러가 발생했는지 여부를 확인.

Stream의 종류

Dart에서는 두 가지 주요 Stream 유형이 있습니다:

  • Single Subscription Stream: 한 번만 구독 가능. 기본 스트림 방식.
  • Broadcast Stream: 여러 리스너가 동시에 구독 가능.

Broadcast Stream 예제:


final controller = StreamController<int>.broadcast();

controller.stream.listen((event) {
  print('Listener 1: $event');
});

controller.stream.listen((event) {
  print('Listener 2: $event');
});

for (int i = 1; i <= 3; i++) {
  controller.sink.add(i);
}
    

실행 결과:

Listener 1: 1
Listener 2: 1
Listener 1: 2
Listener 2: 2
Listener 1: 3
Listener 2: 3
    

내부 로직:

  • StreamController.broadcast(): Broadcast Stream을 생성하는 컨트롤러.
  • controller.sink.add(): 데이터를 스트림에 추가하여 모든 리스너가 이를 받도록 합니다.
  • 각 리스너는 독립적으로 데이터를 수신하고 처리합니다.

오늘의 학습 요약

오늘은 Stream과 StreamBuilder를 학습하면서 Flutter에서 비동기 데이터를 처리하고 UI에 반영하는 방법을 배웠습니다.
특히, Broadcast Stream을 활용하면 여러 리스너가 동시에 데이터를 처리할 수 있다는 점이 인상 깊었습니다.
또한, Stream의 다양한 이벤트 타입과 yield를 활용한 데이터 방출 방식이 매우 유용하다는 것을 배웠습니다.
다음에는 StreamController를 활용한 커스텀 Stream 생성과 상태 관리 방법을 깊이 탐구해볼 예정입니다.