Menu
Coddy logo textTech

Stream Controller

Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 78번째.

async* 제너레이터는 미리 정의된 데이터로 스트림을 생성하는 데 유용하지만, 때로는 코드의 서로 다른 부분에서 스트림에 데이터를 추가하는 것과 같이 더 많은 제어가 필요할 때가 있습니다. 그럴 때 StreamController가 사용됩니다.

StreamController는 스트림의 관리자 역할을 합니다. 데이터를 추가할 수 있는 "sink"와 리스너가 구독할 수 있는 "stream"을 제공합니다:

import 'dart:async';

void main() {
  var controller = StreamController<String>();
  
  // 스트림을 리슨합니다
  controller.stream.listen((data) {
    print('Received: $data');
  });
  
  // 싱크를 통해 데이터를 추가합니다
  controller.add('Hello');
  controller.add('World');
  
  controller.close();  // 작업이 끝나면 항상 닫아줍니다
}

add() 메서드는 스트림에 새로운 값을 밀어 넣으며, 모든 리스너는 이를 즉시 수신합니다. 자원을 해제하기 위해 작업이 끝나면 항상 close()를 호출해야 합니다.

기본적으로 스트림은 하나의 리스너만 가질 수 있습니다. 여러 리스너를 사용하려면 브로드캐스트 컨트롤러(broadcast controller)를 사용하세요:

import 'dart:async';

void main() {
  var controller = StreamController<int>.broadcast();
  
  controller.stream.listen((n) => print('Listener 1: $n'));
  controller.stream.listen((n) => print('Listener 2: $n'));
  
  controller.add(42);
  controller.close();
}

StreamControllers는 데이터 변경 시 앱의 여러 부분에 알림을 보내거나, 사용자 동작을 처리하거나, 객체 내에서 실시간 업데이트를 관리하는 것과 같이 이벤트 기반 클래스를 구축하는 데 있어 OOP에서 필수적입니다.

challenge icon

챌린지

쉬움

여러 구독자가 실시간으로 메시지를 받을 수 있는 메시지 허브 시스템을 구축해 봅시다! StreamController를 사용하여 메시지 흐름을 관리하고, 브로드캐스트 스트림이 어떻게 여러 리스너를 지원하는지 실습해 볼 것입니다.

코드는 두 개의 파일로 구성됩니다:

  • message_hub.dart: StreamController를 사용하여 메시지 배포를 관리하는 MessageHub 클래스를 생성합니다. 허브의 기능은 다음과 같아야 합니다:
    • 여러 리스너가 구독할 수 있도록 내부적으로 브로드캐스트 StreamController<String>를 사용합니다.
    • 리스너가 구독할 수 있는 스트림을 반환하는 messages라는 getter를 제공합니다.
    • 스트림에 메시지를 추가하는 broadcast(String message) 메서드를 작성합니다.
    • 컨트롤러를 닫는 shutdown() 메서드를 작성합니다.
  • main.dart: 메시지 허브를 임포트하고 동일한 스트림을 수신하는 여러 구독자가 있는 시나리오를 설정합니다:
    • MessageHub 인스턴스를 생성합니다.
    • Subscriber A: [message] 형식으로 메시지를 출력하는 첫 번째 리스너를 추가합니다.
    • Subscriber B: [message] 형식으로 메시지를 출력하는 두 번째 리스너를 추가합니다.
    • 세 개의 메시지를 브로드캐스트합니다: Hello everyone, Welcome to the hub, 그리고 Goodbye
    • 허브를 종료합니다.

StreamController를 사용하려면 메시지 허브 파일에서 dart:async를 임포트해야 함을 잊지 마세요. 두 구독자 모두 브로드캐스트되는 모든 메시지를 어떻게 수신하는지 확인해 보세요. 이것이 바로 브로드캐스트 스트림의 강력한 기능입니다!

예상 출력:

Subscriber A: Hello everyone
Subscriber B: Hello everyone
Subscriber A: Welcome to the hub
Subscriber B: Welcome to the hub
Subscriber A: Goodbye
Subscriber B: Goodbye

치트 시트

StreamController는 스트림을 관리하며, 데이터가 추가되는 시점과 방법을 제어할 수 있게 해줍니다. 데이터를 추가할 수 있는 "sink"와 리스너가 구독할 수 있는 "stream"을 제공합니다.

기본 사용법:

import 'dart:async';

var controller = StreamController<String>();

// Listen to the stream
controller.stream.listen((data) {
  print('Received: $data');
});

// Add data through the sink
controller.add('Hello');
controller.add('World');

controller.close();  // Always close when done

add() 메서드는 스트림에 새로운 값을 밀어넣습니다. 리스너는 이를 즉시 수신합니다. 리소스를 해제하기 위해 작업이 끝나면 항상 close()를 호출하세요.

기본적으로 스트림은 단 하나의 리스너만 가질 수 있습니다. 여러 리스너를 사용하려면 브로드캐스트 컨트롤러를 사용하세요:

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

controller.stream.listen((n) => print('Listener 1: $n'));
controller.stream.listen((n) => print('Listener 2: $n'));

controller.add(42);
controller.close();

StreamController는 이벤트 기반 클래스를 구축하거나, 데이터가 변경될 때 앱의 여러 부분에 알림을 보내거나, 사용자 동작을 처리하거나, 실시간 업데이트를 관리하는 데 필수적입니다.

직접 해보기

import 'message_hub.dart';

void main() {
  // TODO: MessageHub 인스턴스 생성
  
  // TODO: Subscriber A: [message]를 출력하는 첫 번째 리스너 추가
  
  // TODO: Subscriber B: [message]를 출력하는 두 번째 리스너 추가
  
  // TODO: 세 개의 메시지 브로드캐스트:
  // - "Hello everyone"
  // - "Welcome to the hub"
  // - "Goodbye"
  
  // TODO: 허브 종료
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨