프로그래밍 언어/Dart

Dart Stream 사용법 및 예제 통한 비동기 처리와 필터링 프로그래밍 - Dart 기초 #18

eco7T 2024. 6. 24. 09:05
반응형

이번에는 Dart 프로그래밍 중 Stream에 대해 정리합니다. Stream을 이용해 비동기 처리를 할 수 있는 방법을 이해하고, 이를 실제 프로젝트에 적용할 수 있도록 설명합니다.

Dart Stream 사용법 및 예제
Dart Stream 사용법 및 예제

 

Dart Stream 사용법

Stream은 데이터의 연속적인 흐름을 나타냅니다. 마치 강물이 끊임없이 흐르는 것처럼, Stream은 시간에 따라 여러 개의 데이터를 순차적으로 전달합니다. 이는 파일 읽기, 네트워크 요청, 센서 데이터 수집 등 지속적으로 데이터를 받아야 하는 상황에서 유용합니다.

    Stream 기본 사용법

1) Stream 생성하기

Stream을 생성하는 가장 간단한 방법은  Stream.fromIterable() 메서드를 사용하는 것입니다.

void main() { // 리스트로부터 Stream 생성 Stream<int> numberStream = Stream.fromIterable([1, 2, 3, 4, 5]); // Stream 사용하기 numberStream.listen((number) { print('받은 숫자: $number'); }); }

이 코드를 실행하면 다음과 같은 결과가 출력됩니다:

받은 숫자: 1 받은 숫자: 2 받은 숫자: 3 받은 숫자: 4 받은 숫자: 5

 listen 메서드는 Stream에서 데이터가 발생할 때마다 지정된 함수(여기서는 print 함수)를 실행합니다.

 

2) 비동기 생성자를 이용한 Stream 생성

 async* 키워드와  yield 키워드를 사용하여 Stream을 생성할 수 있습니다.

Stream<int> countStream(int max) async* { for (int i = 1; i <= max; i++){ await Future.delayed(Duration(seconds: 1)); yield i; } } void main() { countStream(5).listen((number){ print('카운트: $number'); }); }

이 코드는 1부터 5까지 1초 간격으로 숫자를 생성하는 Stream을 만듭니다. 실행 결과는 다음과 같습니다.

카운트: 1 (1초 후) 카운트: 2 (1초 후) 카운트: 3 (1초 후) 카운트: 4 (1초 후) 카운트: 5

 async* 는 이 함수가 비동기적으로 실행되며 Stream을 생성한다는 것을 나타냅니다. yield는 Stream에 값을 추가합니다.

반응형

    Stream 변환과 필터링

Stream의 데이터를 변환하거나 필터링하는 방법을 알아봅시다.

 

1) map() 메서드 사용하기

 map() 메서드를 사용하면 Stream의 각 데이터를 변환할 수 있습니다.

void main() { Stream<int> numberStream = Stream.fromIterable([1, 2, 3, 4, 5]); numberStream .map((number) => number * 2) .listen((doubledNumber) { print('2배로 만든 숫자: $doubledNumber'); }); }

실행 결과:

2배로 만든 숫자: 2 2배로 만든 숫자: 4 2배로 만든 숫자: 6 2배로 만든 숫자: 8 2배로 만든 숫자: 10

 

2) where() 메서드로 필터링하기

 where() 메서드를 사용하면 Stream의 데이터를 필터링할 수 있습니다.

void main() { Stream<int>> numberStream = Stream.fromIterable([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); numberStream .where((number) => number % 2 == 0) .listen((evenNumber) { print('짝수: $evenNumber'); }); }

실행 결과:

짝수: 2 짝수: 4 짝수: 6 짝수: 8 짝수: 10

    Stream 에러 처리

Stream 사용 시 발생할 수 있는 에러를 처리하는 방법을 알아봅시다.

Stream<int> countStream(int max) async* { for (int i = 1; i <= max; i++) { if (i == 4) { throw Exception('4는 좋지 않은 숫자입니다!'); } yield i; } } void main() { countStream(5).listen( (number) { print('받은 숫자: $number'); }, onError: (error) { print('에러 발생: $error'); }, onDone: () { print('Stream 완료'); } ); }

실행 결과:

받은 숫자: 1 받은 숫자: 2 받은 숫자: 3 에러 발생: Exception: 4는 좋지 않은 숫자입니다!

 listen 메서드의  onError  파라미터를 사용하여 에러를 처리할 수 있습니다.  onDone 파라미터는 Stream이 모든 데이터를 전송했을 때 실행됩니다.

    실제 응용 예제 - 파일 읽기

Stream을 사용하여 대용량 파일을 효율적으로 읽는 예제를 살펴보겠습니다.

import 'dart:io'; void main() { final file = File('example.txt'); file.openRead() .transform(utf8.decoder) .transform(LineSplitter()) .listen( (line) { print('읽은 줄: $line'); }, onError: () { print('파일 읽기 에러: $error'); }, onDone: () { print('파일 읽기 완료'); } ); }

이 예제는 'example.txt' 파일을 한 줄씩 읽어 출력합니다.  openRead() 메서드는 파일의 내용을 Stream으로 반환합니다.

 utf8.decoder 와  LineSplitter() 는 바이트 스트림을 문자열로, 그리고 개별 줄로 변환합니다.

이렇게 Stream을 사용하면 대용량 파일도 메모리를 효율적으로 사용하면서 처리할 수 있습니다.

 

Stream은 비동기 프로그래밍에서 매우 강력한 도구이며, 실시간 데이터 처리, 파일 입출력, 네트워크 통신 등 다양한 상황에서 유용하게 사용될 수 있습니다.

반응형