Dart 언어의 비동기 프로그래밍에서 Future와 함께 중요하게 사용되는 개념 중 하나인 Stream에 대하여 알아보고자 한다.
Future와 Stream의 차이점은 아주 간단 명료 하다. "단일 값" vs "다중 값".
Future는 단일 비동기 작업에 대해 단일 값 혹은 단일 오류를 처리하는데에 사용되는 개념이고,
Stream은 다중 비동기 작업에 대해 다중 값 혹은 다중 오류를 처리하는데에 사용되는 개념이다.
또한 Stream은 Future로 불가능한 작업 중 하나인 실시간 데이터 리스닝이 가능하다.
이를 이해하기 위해, 전통적인 Data Pulling 방식을 생각해보자
전통적인 Data Pulling 방식 Flow
1. 초기에 필요한 데이터를 Database로 부터 받아온다.
2. 새로고침 혹은 데이터를 다시 불러와야 할 필요가 있는 시점에 DataBase로 부터 데이터를 받아온다.
위의 방식으로 데이터를 불러오는 경우, 지속적으로 Future 값을 받아와 비동기적으로 데이터를 한번씩 업데이트 해야한다.
물론 위의 방식이 필요한 경우도 있다.
예를 들어, 한번만 데이터를 불러오면 되는 경우 혹은 데이터를 주기적으로 pulling 받아도 횟수가 너무 적어 실시간 리스닝이 필요 없는 경우가 있다.
하지만 비동기 데이터를 받아오는 대부분의 경우 실시간 리스닝이 필요하고, 나 뿐만 아니라 다른 유저의 정보도 표시되는 프로젝트에서는 실시간 리스닝은 반드시 구현되어야 하는 Data pulling 방식이다.
때문에 Stream을 공부할 때는 "다중 작업 Listen하기", "다중 값을 실시간으로 Listen하기", "다중 작업을 특정 횟수만 Listen 하기", "Stream 닫기" 에 대한 연습을 해보려고 한다.
다중 작업 처리하기
[코드]
[코드 설명(라인별)]
Line 4
: streamController에서 받는 값을 int라고 지정하고 controller 변수를 선언 및 초기화
Line 7
: int(1)~int(5)까지를 차례대로 streamController에 add
Line 10~19
: controller의 stream의 수신을 설정
[실행 결과]
[설명]
현재 코드에서 stream을 listen할 때, take 함수를 사용해서 특정 횟수를 지정하지 않았기 때문에 stream에 들어오는 모든 정보를 읽어들이고 있는 것이다.
즉, listen이 선언된 이후 새로운 값들이 stream에 들어오면 listen 안의 함수 body가 호출된다는 의미이다.
또한 stream을 close 하지 않았기 때문에 onDone() method가 실행되지 않고 있다.
Listen 이후 Stream에 데이터 추가해보기
[코드]
[코드 설명(라인별)]
Line 22
: int(6)~int(10) 까지의 값을 controller에 add
[실행 결과]
[설명]
Listen 횟수를 지정하지 않았고, controller의 stream이 close 되지 않았기 때문에 값이 stream에 들어가면 실시간으로 리스닝을 진행함
Listen 횟수 지정
[코드]
[코드 설명(라인별)]
Line 10
: stream 뒤에 .take(7) 메서드를 호출하여 7번의 작업에 대한 결과 값만 가져오도록 하였다.
[실행 결과]
[설명]
Listen 횟수를 7번으로 지정하니깐 7번만 데이터를 받고 stream이 close 된 것을 확인할 수 있다.
원래 값이 들어오기 전에 stream이 close되면 runtime 중 error가 발생하지만, take함수를 통해 listen 횟수를 정해놓으면 error가 발생하지 않는다.
Controller에 값이 추가되기 전 Close 된 경우
[코드]
[코드 설명(라인별)]
Line 22
: controller.close() 메서드를 호출하여 명시적으로 stream을 close 해주었다.
[실행 결과]
[설명]
stream이 closed 되면서 onDone 메서드가 호출되었고, 그 후 Code Line에서 int(6)~int(10)까지의 값들이 stream에 add 되면서 에러가 출력되는 것을 볼 수 있다.
오늘은 아주 간단하게 int 자료형 값을 stream값으로 받는 예시를 통해 Stream의 개념과 구조에 대해 알아보았다.
실제 DB 값을 Listen할 때는 다양한 자료형을 활용한다.
내가 자주 쓰는 firebase에서는 QuerySnapshot 자료형을 Stream 구조로 활용하여, DB 값이 바뀌게 되면 StreamBuilder가 바뀐 DB의 정보를 Listen하여 UI를 변경해주는 구조로 동작한다.
여러 정보를 한번에 받아오거나, 비동기적으로 특정 횟수의 Datas Pulling이 필요할 때 Stream 개념을 적절하게 사용하면 좋은 코드를 작성할 수 있을 것 같다.
'Flutter > Basic Knowledge' 카테고리의 다른 글
[Dart] Asynchronous & Future (0) | 2024.01.12 |
---|---|
[Dart] 단일 상속과 Mixin (0) | 2024.01.10 |
[Dart] AOT(Ahead-Of-Time) 과 JIT(Just-In-Time) 컴파일러 (0) | 2024.01.10 |
[Dart] Garbage Collection 이란? (1) | 2024.01.10 |
[Dart] Dart 란? (0) | 2024.01.10 |