[Dart] 다트 비동기 프로그래밍

찌니월드·2024년 2월 13일
0

📚 책 스터디

목록 보기
3/11
post-thumbnail

Future

Future 클래스는 미래에 받아올 값을 뜻한다. 제네릭으로 어떤 미래의 값을 받아올지를 정할 수 있다.

Future<String> name;
Future<int> number;
Futuer<bool> isOpened;

비동기 프로그래밍은 서버 요청과 같이 오래 걸리는 작업을 기다린 후 값을 받아와야 하기 때문에 Future 클래스가 필요하다.

void main() {
  addNumbers(1, 1);
}

void addNumbers(int number1, int number2) {
  print('$number1 + $number2 계산 시작!');
  
  // Future.delayed()를 사용하면 일정 시간 후에 콜백 함수를 실행할 수 있음
  Future.delayed(Duration(seconds: 3), () {
    print('$number1 + $number2 = ${number1 + number2}');
  });
  
  print('$number1 + $number2 코드 실행 끝');
}

async와 await

async와 await 키워드를 사용하면 비동기 프로그래밍 특징을 그대로 유지하며 코드가 작성된 순서대로 프로그램을 실행한다.

void main() {
  addNumbers(1, 1);
}

// async 키워드는 함수 매개변수 정의와 바디 사이에 입력한다.
Future<void> addNumbers(int number1, int number2) async {
  print('$number1 + $number2 계산 시작!');
  
  // await는 대기하고 싶은 비동기 함수 앞에 입력한다.
  await Future.delayed(Duration(seconds: 3), () {
    print('$number1 + $number2 = ${number1 + number2}');
  });
  
  print('$number1 + $number2 코드 실행 끝');
}

Stream

Future는 반환값을 딱 한 번 받아내는 비동기 프로그래밍에 사용한다. 지속적으로 값을 반환 받을 때는 Stream을 사용한다.

Future.wait() 함수는 하나의 Future로 구성된 리스트를 매개변수로 입력받는다. Future.wait()에 입력된 비동기 함수들은 모두 동시에 실행되며 응답값 요청을 보낸 순서대로 저장해둔다.

스트림 사용법

import 'dart:async';

void main() {
  final controller = StreamController();
  final stream = controller.stream;
  
  // Stream에 listen() 함수를 실행하면 값이 주입될 때마다 콜백 함수를 실행할 수 있다.
  final streamListener1 = stream.listen((val) {
    print(val);
  });
  
  // Stream에 값을 주입하기
  controller.sink.add(1);
  controller.sink.add(2);
  controller.sink.add(3);
  controller.sink.add(4);
}

브로드캐스트 스트림

스트림은 단 한 번만 listen()을 실행할 수 있다. 하지만 브로드캐스트 스트림을 사용하면 스트림을 여러 번 listen()하도록 변환할 수 있다.

import 'dart:async';

void main() {
  final controller = StreamController();
  
  // 여러 번 리슨할 수 있는 Broadcast Stream 객체 생성
  final stream = controller.stream.asBroadcastStream();
  
  // 첫 번째 listen() 함수
  final streamListener1 = stream.listen((val) {
    print('listening 1');
    print(val);
  });
  
  // 두 번째 listen() 함수
  final streamListener2 = stream.listen((val) {
    print('listening 2');
    print(val);
  });
  
  // add()를 실행할 때마다 listen()하는
  // 모든 콜백 함수에 값이 주입된다.
  controller.sink.add(1);
  controller.sink.add(2);
  controller.sink.add(3);
}

함수로 스트림 반환하기

StreamController를 직접 사용하지 않고도 직접 스트림을 반환하는 함수를 작성할 수도 있다.

import 'dart:async';

// Stream을 반환하는 함수는 async*로 선언한다.
Stream<String> calculate(int number) async* {
  for (int i = 0; i < 5; i++) {
    // StreamController의 add()처럼 yield 키워드를 이용해서 값 반환
    yield 'i = $i';
    await Future.delayed(Duration(seconds: 1));
  }
}

void playStream() {
  // StreamController와 마찬가지로 listen() 함수로 콜백 함수 입력
  calculate(1).listen((val) {
    print(val);
  });
}

void main() {
  playStream();
}

참고

이 글은 골든래빗 《코드팩토리의 플러터 프로그래밍》의 스터디 내용 입니다.

profile
Front-End Developer

0개의 댓글