Dart Stream과 yield
이 문서 주변 탐색
주제 태그, 링크, 시리즈 흐름을 중심으로 옆으로 이동할 수 있습니다.
시리즈 흐름
이 문서는 아직 읽기 시리즈에 연결되지 않았습니다.
관련 문서
같이 읽을 만한 관련 문서가 아직 없습니다.
이 문서를 참조하는 문서
이 문서를 참조하는 다른 문서가 아직 없습니다.
1. 핵심 개념: 한 번에 vs 하나씩
프로그래밍에서 데이터를 받는 방식은 크게 두 가지임
방식 1: 한 번에 받기 (Future)
요청 → 기다림 → 결과 1개 도착 → 끝!방식 2: 하나씩 계속 받기 (Stream)
구독 시작 → 데이터1 도착 → 데이터2 도착 → ... → 스트림 종료2. 일상 비유로 이해하기
🍕 Future = 피자 배달
1. 피자 주문함
2. 배달 기다림
3. 피자 1판 도착
4. 끝!한 번에 하나의 결과만 받음
결과 받으면 거래 끝
// Future 예시
Future<String> orderPizza() async {
await Future.delayed(Duration(minutes: 30));
return '페퍼로니 피자'; // 한 번 반환하고 끝
}🏭 Stream = 공장 컨베이어 벨트
1. 공장 가동 시작
2. 제품 1번 나옴 → 받음
3. 제품 2번 나옴 → 받음
4. 제품 3번 나옴 → 받음
5. ... (계속)
6. 공장 멈춤 → 끝데이터가 연속으로 나옴
언제 끝날지 모름 (계속 나올 수도 있음)
구독하고 있어야 받을 수 있음
// Stream 예시
Stream<String> factoryBelt() async* {
yield '제품 1번'; // 내보내고 계속
yield '제품 2번'; // 내보내고 계속
yield '제품 3번'; // 내보내고 끝
}🎬 또 다른 비유들
Future | Stream |
|---|---|
영화 다운로드 (완료되면 한번에 받음) | 넷플릭스 스트리밍 (조금씩 계속 받음) |
택배 배송 (한 번에 도착) | 정기 구독 서비스 (매달 도착) |
사진 1장 찍기 | 동영상 촬영 (프레임이 계속 나옴) |
전화 통화 (한 번 연결) | 라디오 방송 (계속 송출) |
3. 코드 한 줄씩 뜯어보기
원본 코드
import 'dart:async';
void main() {
calculate(2).listen((val){
print('calculate(1) : $val');
});
}
Stream<int> calculate(int number) async* {
for(int i = 0; i < 5; i++){
yield i * number;
}
}3.1 Stream 만드는 함수 분석
Stream<int> calculate(int number) async* {
for(int i = 0; i < 5; i++){
yield i * number;
}
}코드 | 의미 |
|---|---|
| "정수(int)를 여러 개 내보내는 스트림을 반환할거야" |
| "number라는 숫자를 받아서 계산할거야" |
| "이 함수는 스트림 생성기야" ⭐ 별표(*) 중요! |
| "i를 0부터 4까지 5번 반복해" |
| "i × number 계산 결과를 내보내고, 멈추지 말고 다음으로" |
3.2 Stream 구독하기 분석
calculate(2).listen((val){
print('결과: $val');
});코드 | 의미 |
|---|---|
| "2를 넣고 스트림 만들어" |
| "스트림 구독 시작! 값 나올 때마다 알려줘" |
| "값이 나오면 val에 넣고 중괄호 안 코드 실행해" |
| "결과: (나온 값)" 출력 |
3.3 실행 결과
결과: 0 (i=0, 0 × 2 = 0)
결과: 2 (i=1, 1 × 2 = 2)
결과: 4 (i=2, 2 × 2 = 4)
결과: 6 (i=3, 3 × 2 = 6)
결과: 8 (i=4, 4 × 2 = 8)
4. return vs yield 차이
return (일반 함수)
int getNumber() {
return 1; // 1 반환하고 함수 완전히 끝!
return 2; // ❌ 절대 여기 도달 못함
return 3; // ❌ 절대 여기 도달 못함
}
void main() {
print(getNumber()); // 1만 출력됨
}return의 특징:
값을 반환하면 함수 즉시 종료
그 아래 코드는 실행 안 됨
한 번만 값을 줄 수 있음
yield (스트림 생성기)
Stream<int> getNumbers() async* {
yield 1; // 1 내보내고 잠깐 멈춤, 다음 줄로
yield 2; // 2 내보내고 잠깐 멈춤, 다음 줄로
yield 3; // 3 내보내고 함수 끝
}
void main() {
getNumbers().listen((n) => print(n));
// 1 출력
// 2 출력
// 3 출력
}yield의 특징:
값을 내보내도 함수 계속 진행
아래 코드도 계속 실행됨
여러 번 값을 줄 수 있음
핵심 차이 정리
구분 | return | yield |
|---|---|---|
함수 종료 | 즉시 종료 | 계속 진행 |
값 개수 | 1개만 | 여러 개 |
사용처 | 일반 함수 | async* 함수 |
비유 | "받아! 끝!" | "받아! 더 있어!" |
5. 실제 사용 예시
예시 1: 카운트다운
// 5, 4, 3, 2, 1, 발사!
Stream<String> countdown() async* {
for (int i = 5; i >= 1; i--) {
yield '$i...';
await Future.delayed(Duration(seconds: 1)); // 1초 대기
}
yield '발사! 🚀';
}
void main() {
countdown().listen((msg) => print(msg));
}
// 출력 (1초 간격으로):
// 5...
// 4...
// 3...
// 2...
// 1...
// 발사! 🚀예시 2: 파일 다운로드 진행률
Stream<int> downloadProgress() async* {
for (int percent = 0; percent <= 100; percent += 10) {
yield percent;
await Future.delayed(Duration(milliseconds: 500));
}
}
void main() {
downloadProgress().listen((percent) {
print('다운로드 중... $percent%');
});
}
// 출력:
// 다운로드 중... 0%
// 다운로드 중... 10%
// 다운로드 중... 20%
// ...
// 다운로드 중... 100%예시 3: 채팅 메시지 시뮬레이션
Stream<String> chatMessages() async* {
await Future.delayed(Duration(seconds: 1));
yield '👤 철수: 안녕!';
await Future.delayed(Duration(seconds: 2));
yield '👤 영희: 반가워~';
await Future.delayed(Duration(seconds: 1));
yield '👤 철수: 뭐해?';
}
void main() {
chatMessages().listen((message) {
print(message);
});
}예시 4: 실시간 주식 가격
import 'dart:math';
Stream<int> stockPrice() async* {
int price = 50000; // 시작 가격
while (true) { // 무한 스트림
// -500 ~ +500 사이 랜덤 변동
price += Random().nextInt(1001) - 500;
yield price;
await Future.delayed(Duration(seconds: 1));
}
}
void main() {
// 10번만 받고 종료
stockPrice().take(10).listen((price) {
print('현재 주가: ${price}원');
});
}6. 핵심 정리
키워드 정리표
키워드 | 의미 | 비유 |
|---|---|---|
| 미래에 받을 값 1개 | 택배 1개 |
| 계속 흘러나오는 값들 | 컨베이어 벨트 |
| "비동기 함수야" | "잠깐 기다릴 수도 있어" |
| "스트림 생성기야" | "값을 여러 개 줄 거야" |
| "기다려" | "택배 올 때까지 대기" |
| "이거 내보내" | "벨트에 제품 올림" |
| "구독할게" | "벨트 앞에서 대기" |
async vs async* 비교
구분 | async | async* |
|---|---|---|
반환 타입 |
|
|
값 내보내기 |
|
|
값 개수 | 1개 | 여러 개 |
완료 시점 | return 시 | 함수 끝날 때 |
Stream이 필요한 상황
상황 | 설명 |
|---|---|
채팅 앱 | 메시지가 언제 올지 모름 |
주식 앱 | 가격이 실시간으로 변함 |
다운로드 | 진행률이 계속 업데이트됨 |
GPS | 위치가 계속 바뀜 |
센서 | 데이터가 계속 들어옴 |
검색 자동완성 | 입력마다 결과 바뀜 |
본 글은 AI의 도움을 받아 작성되었습니다.
읽기 시리즈
현재 위치를 확인하고, 흐름을 따라 바로 다음 읽기로 이어갈 수 있습니다.