반응형
동기성 - 모든 코드가 순차적으로 진행되는 형태
비동기 - 코드가 동시다발적으로 실행, 순착적으로 보장을 할 수 없는 형태
다트 언어에서 제공하는 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 |