반응형
동기성 - 모든 코드가 순차적으로 진행되는 형태
비동기 - 코드가 동시다발적으로 실행, 순착적으로 보장을 할 수 없는 형태

 

다트 언어에서 제공하는 Future, Stream, await, async는 모두 비동기 프로그래밍을 지원하는 기능입니다.
비동기 프로그래밍이란 시간이 오래걸리는 작업을 실행한 후 끝날 때까지 기다리지 않고 다음 작업을 실행하는 것입니다. 비동기 프로그래밍과 반대되는 개념은 동기 프로그래밍으로 어떤 작업을 실행하고 끝날 때까지 기다렸다가 그 다음 작업을 수행하는 것입니다.
dart 비동기 프로그래밍은 프로그램의 흐름을 중단시키지 않고, 무언가의 완료를 기다리는 동안 다른 작업을 수행할 수 있게 해줍니다. Dart에서는 이를 위해 Future와 Stream이라는 두 가지 주요 개념을 제공합니다.

 

동기로 실행되는 예를 들어 비동기 프로그래밍이 왜 필요한지 알아보겠습니다.

다음 코드는 버튼을 클릭하면 onPress() 함수가 호출되고, onPress() 함수에서 sum() 함수를 호출합니다.

여기서 sum() 함수에서 간단한 더하기를 처리했지만, 시간이 오래 걸리는 작업이라 가정하겠습니다.

void main() {

  onPress();

}

void sum() {
  var sum = 0;
  Stopwatch stopwatch = new Stopwatch();
  stopwatch.start();
  for(int i = 0; i < 500000000; i++) {
    sum += i;
  }
  stopwatch.stop();
  print("${stopwatch.elapsed}, result : $sum");
}

void onPress() {
  print('onPress top...');
  sum();
  print('onPress bottom...');
}

 

[실행결과]

onPress top...
0:00:00.161466, result : 124999999750000000
onPress bottom...

 

실행결과를 보면 onPress top이 출력되고 sum() 함수의 결과가 출력된 후에 onPress bottom 이 출력되었습니다.

즉, sum() 함수가 끝나야 onPress() 함수에서 sum() 함수를 호출한 다음 그 다음 줄이 실행됩니다. 결국, onPress() 함수는 sum() 함수의 실행이 끝날 때 까지 대기합니다.

만약 sum() 함수의 작업이 오래 걸린다면 문제가 됩니다. 왜냐하면 sum() 함수의 작업을 마칠때까지 onPress()의 나머지를 수행할 수 없기 때문입니다.

이처럼 시간이 오래걸리는 작업은 다양한데 네트워킹 또는 파일을 읽거나 쓰는 겨웅가 대표적입니다. 이런 작업을 동기로 프로그래밍하면 그 작업이 끝날 때 까지 사용자 이벤트나 화면을 처리할 수 없습니다. 따라서 앱의 성능이 떨어지는 문제가 있습니다.

// 키워드 묶음 // async / await / Future : 1회만 응답을 돌려 받는 경우
// async* / yield / Stream : 지속적으로 응답을 돌려 받아야 하는 경우

 

시나리오 코드 1 - Future 타입 사용해보기

import 'package:flutter/material.dart';

void main() {


// 비동기 프로그래밍
// 키워드 묶음 - async, await : Future (1회성 응답을 돌려 받는 경우)

print("task ...... 1");
// 비동기 함수 만들기
  var data1 = fetchData();
print("task ...... $data1");
print("task ...... 3");


}

// 비동기 함수 - Future
Future<String> fetchData() {
  // 2초 뒤에 데이터를 가져 옴
  return Future.delayed(Duration(seconds: 2), () {
    return "2초 data";
  });
}

 

Performing hot restart...
Syncing files to device sdk gphone x86...
Restarted application in 761ms.
I/flutter (28571): task ...... 1
I/flutter (28571): task ...... Instance of 'Future<String>'
I/flutter (28571): task ...... 3

 

시나리오 코드 2 - await 사용 (마치 동기 프로그래밍 처럼 활용할 수 있다)

규칙

await 키워드를 사용하는 포함하고 있는 함수는 반드시 함수 선언부에 async 키워드를 선언해주어야 한다.
import 'package:flutter/material.dart';

void main() async {


// 비동기 프로그래밍
// 키워드 묶음 - async, await : Future (1회성 응답을 돌려 받는 경우)

print("task ...... 1");
// 비동기 함수 만들기
  var data1 = await fetchData();
print("task ...... $data1");
print("task ...... 3");


}

// 비동기 함수 - Future
Future<String> fetchData() {
  // 2초 뒤에 데이터를 가져 옴
  return Future.delayed(Duration(seconds: 2), () {
    return "연산완료 처리";
  });
}

 

Performing hot restart...
Syncing files to device sdk gphone x86...
Restarted application in 783ms.
I/flutter (28571): task ...... 1
I/flutter (28571): task ...... 연산완료 처리
I/flutter (28571): task ...... 3

 

이해도를 높이기 위한 코드 작성

import 'package:flutter/material.dart';

void main()  {
  // Future 타입과 값을 꺼내는 방법
  // 비동기 함수를 - 동기성으로 변경하면 값이 자동으로 꺼내졌다.
  // Future 타입 선언
  Future<String> name = Future.value("주녘");
  Future<int> number = Future.value(29);
  Future<bool> isTrue = Future.value(true);

  print(name);
  print(number);
  print(isTrue);
  print("-------------------");
}

 

Performing hot restart...
Syncing files to device sdk gphone x86...
Restarted application in 1,177ms.
I/flutter (29095): Instance of 'Future<String>'
I/flutter (29095): Instance of 'Future<int>'
I/flutter (29095): Instance of 'Future<bool>'
I/flutter (29095): -------------------

 

 

async, await 사용하면?

import 'package:flutter/material.dart';

void main() async {
  // Future 타입과 값을 꺼내는 방법
  // 비동기 함수를 - 동기성으로 변경하면 값이 자동으로 꺼내졌다.
  // Future 타입 선언
  Future<String> name = Future.value("주녘");
  Future<int> number = Future.value(29);
  Future<bool> isTrue = Future.value(true);

  print(name);
  print(number);
  print(isTrue);
  print("-------------------");

  print(await name);
  print(await number);
  print(await isTrue);
  print("-------------------");
}

 

Performing hot restart...
Syncing files to device sdk gphone x86...
Restarted application in 807ms.
I/flutter (29095): Instance of 'Future<String>'
I/flutter (29095): Instance of 'Future<int>'
I/flutter (29095): Instance of 'Future<bool>'
I/flutter (29095): -------------------
I/flutter (29095): 주녘
I/flutter (29095): 29
I/flutter (29095): true
I/flutter (29095): -------------------

 

시나리오 코드 4 - Future 타입과 값 꺼내는 방법 - 2 (Future.then() 사용)

import 'package:flutter/material.dart';

void main()  {
  // Future 타입과 값을 꺼내는 방법
  // 비동기 함수를 - 동기성으로 변경하면 값이 자동으로 꺼내졌다.
  // Future 타입 선언
  Future<String> name = Future.value("주녘");
  Future<int> number = Future.value(29);
  Future<bool> isTrue = Future.value(true);

  print(name);
  print(number);
  print(isTrue);
  print("-------------------");

  // 1번 방법은 동기성으로 만들기
  // 2번 미래 타입을 소화시키는 2번째 방법 : 콜백 메서드의 활용
  // print(await name);
  name.then((value) => print("미래 타입 값 꺼내기 콜백 :  $value"));
  number.then((e) => print("xxxxx :  $e"));
  isTrue.then((value) { print("ooooo : $value"); });
}

 

Performing hot restart...
Syncing files to device sdk gphone x86...
Restarted application in 904ms.
I/flutter (29303): Instance of 'Future<String>'
I/flutter (29303): Instance of 'Future<int>'
I/flutter (29303): Instance of 'Future<bool>'
I/flutter (29303): -------------------
I/flutter (29303): 미래 타입 값 꺼내기 콜백 :  주녘
I/flutter (29303): xxxxx :  29
I/flutter (29303): ooooo : true

 

🎈 Key Point Future 타입을 소화 시키는 방법
1. 동기적 프로그래밍으로 만들어 준다.
2. 비동기 처리를 한다 - 콜백 메서드로 활용 한다.
3. 하나의 비동기 작업을 처리하기 위해 두 가지 방법을 혼합하여 사용할 수도 있다.

 

응용

import 'package:flutter/material.dart';

void main()  {


  // var result1 = addNumber1(100, 200);
  // print(result1);
  // print(result1.runtimeType);
  // result1.then((value) => print("result1 소화 : $value"));
  print('---------------------');
  var result2 = addNumber2(100, 200);
  result2.then((value) => print("result2 소화 : $value"));
  print('---------------------2222222222');
}

Future<int> addNumber2(int n1, int n2){

  return Future.delayed(Duration(seconds: 3), () => n1 + n2);

}

// 응용
// 함수 설계, 인수 2개 int 값을 받아서 2초 뒤에 연산되는 함수를 설계해보자.
// 동기적 방식으로 처리
Future<int> addNumber1(int n1, int n2) async {
  print("함수 시작 1");
  var result = 0;
  await Future.delayed(Duration(seconds: 2), () {
    result = n1 + n2;
  });
  print("함수 완료 2");
  return result;
}

 

import 'package:flutter/material.dart';

void main() async {


  // var result1 = addNumber1(100, 200);
  // print(result1);
  // print(result1.runtimeType);
  // result1.then((value) => print("result1 소화 : $value"));
  print('---------------------');
  var result2 = await addNumber2(100, 200);
  // result2.then((value) => print("result2 소화 : $value")); 동기방식으로 변경하기
  // 동기방식으로 변경하기
  print(result2);
  print('---------------------2222222222');
}

Future<int> addNumber2(int n1, int n2) {

  return Future.delayed(Duration(seconds: 3), () => n1 + n2);

}

// 응용
// 함수 설계, 인수 2개 int 값을 받아서 2초 뒤에 연산되는 함수를 설계해보자.
// 동기적 방식으로 처리
Future<int> addNumber1(int n1, int n2) async {
  print("함수 시작 1");
  var result = 0;
  await Future.delayed(Duration(seconds: 2), () {
    result = n1 + n2;
  });
  print("함수 완료 2");
  return result;
}
반응형

'Flutter' 카테고리의 다른 글

TodoList App 만들기  (0) 2024.03.21
Flutter MVVM 패턴 - 1  (0) 2024.03.19
dart 비동기 프로그래밍 - 3  (0) 2024.03.15
dart 비동기 프로그래밍 - 2  (0) 2024.03.15
블로그 웹 앱 만들어보기  (0) 2023.12.15

+ Recent posts