Flutter

Asynchronous Programming

chaenii 2021. 3. 9. 13:50

동기의 예시

void aFunction(){
	//step1
    print('Hello Moon!');
    //step2
    syncLoad('image from 'NASA');
    //step3
    print('Hello jupiter!');
    
  }

 

step 1 -> step 2 -> step 3

step 2 이미지 load에 특정 시간 소요된다. 하지만 step 3는 step2가 완료될 때까지 실행할 수 없다.

 


비동기의 예시

void aFunction(){
	//step1
    print('Hello Moon!');
    //step2
    asyncLoad('image from 'NASA');
    //step3
    print('Hello jupiter!');
    
  }

step2 이미지 load되는 동안 기다리지 않고, step3 먼저 출력한다.

 

고객이 100명이 있는데 여권 번호가 필요하다. 이때 모든 고객에게 순서대로 전화를 돌리며  고객이 여권을 찾는 시간동안 기다리는 것(동기)보다 모두에게 이메일을 보내고 이메일 답장을 기다리는 방법(비동기)을 사용하는 것이 훨씬 빠르다. 


Async & Await

아래의 코드를 실행했을 때, task1 -> task2 -> task3 순서대로 결과가 나오는 것을 확인할 수 있다.

import 'dart:io';

void main(){
  performTasks();
}

void performTasks(){
  task1();
  task2();
  task3();
}

void task1() {
  String result = 'task 1 data';
  print('Task 1 complete');
}

void task2() {
  String result = 'task 2 data';
  print('Task 2 complete');
}

void task3() {
  String result = 'task 3 data';
  print('Task 3 complete');
}

결과 화면 1

비동기 delay를 시뮬레이션 해보자. Future.delayed라는 method를 사용할 것이다.

시뮬레이션 결과를 확인해보면, task1이 실행되고, task2가 실행되는 동안 task3가 대기하지 않고 실행되었다는 것을 확인할 수 있다. 이것이 바로 비동기 프로그래밍이다.

import 'dart:io';

void main(){
  performTasks();
}

void performTasks(){
  task1();
  task2();
  task3();
}

void task1() {
  String result = 'task 1 data';
  print('Task 1 complete');
}

void task2() {

  Duration threeSeconds = Duration(seconds: 3);
  // 코드 추가한 부분
  // -----------------------------------------
  Future.delayed(threeSeconds, (){
    String result = 'task 2 data';
    print('Task 2 complete');
  });
  // -----------------------------------------
}

void task3() {
  String result = 'task 3 data';
  print('Task 3 complete');
}

결과 화면2

 

그렇다면, task2의 결과를 task3 함수에서 받아 사용하는 경우에는 어떨까?

아래의 코드에서는 task2에서 String을 반환받아 task3 출력문에 사용하는 코드이다. 

import 'dart:io';

void main(){
  performTasks();
}

void performTasks(){
  task1();
  String task2Result = task2();
  task3(task2Result);
}

void task1() {
  String result = 'task 1 data';
  print('Task 1 complete');
}

String task2() {
  Duration threeSeconds = Duration(seconds: 3);
  String result;
  Future.delayed(threeSeconds, (){
    result = 'task 2 data';
    print('Task 2 complete'); 
  });
  return result; 
}

void task3(String taskData) {
  String result = 'task 3 data';
  print('Task 3 complete with $taskData'); 
}

 

결과 화면 3

async와 await를 사용해 이러한 문제를 해결할 수 있다. async 키워드를 이용해 비동기적으로 동적할 수 있도록 만든다. 이전에는 task2보다 task3가 먼저 동작되어서 task2의 결과값을 받아 올 수 없는 문제가 생겼다.

이를 막기 위해서 task2함수에 await를 사용하여 작업 2를 호출하기 전에 완료 될 때까지 기다리도록 할 수 있다. task2 함수의 반환 값은 어떤 값이 나올지 예측할 수 없으므로 Future로 바꾸어 준다. (Future 설명은 아래에)

import 'dart:io';

void main(){
  performTasks();
}

void performTasks () async { 
  task1();
  String task2Result = await task2();
  task3(task2Result);
}

void task1() {
  String result = 'task 1 data';
  print('Task 1 complete');
}

Future task2() async{
  Duration threeSeconds = Duration(seconds: 3);
  String result;
  await Future.delayed(threeSeconds, (){
    result = 'task 2 data';
    print('Task 2 complete');
  });
  return result;
}

void task3(String taskData) {
  String result = 'task 3 data';
  print('Task 3 complete with $taskData');
}

async & await를 사용한 결과 드디어 우리가 원하는 결과를 얻을 수 있었다.

 

결과 화면3


Futures

coffee 주문하고, 주문 번호가 포함된 영수증을 받는다. 커피가 만들어질 때까지 서서 기다리지 않고, 자리로 가서 인스타그램이나 페이스북을 할 수 있다. Future는 이와 유사하다. 

바로 지금 완성 되는 것은 아니지만, 이미지를 다운로드하거나 텍스트를 다운로드하면 미래가 실제로 실제 객체로 구체화된다.

 

Future는 아래와 같이 더 구체적으로 표현할 수 있다. 

Future<String> 
Future<int>
반응형