본문 바로가기

안드로이드/Flutter

How can I use Future in Flutter(Dart)

 

이번 포스팅에서는 Future을 사용해서,

Flutter 에서도 비동기 작업을 할 수 있는 방법을 소개하겠다.

 

Future가 뭘까?

비동기 작업의 결과를 나타난다.

두 가지 상태( 완료(value 생성), 미완료(value 생성하기 전) ) 를 가질 수 있다. 

 

- 비동기 작업이란?

동기, 비동기 작업으로 나뉜다.

- 동기 작업은 예를 들어, 3개의 동작을 수행해야 할 때, (이를 task1, task2, task3 라고 하자.)

순서대로 하나의 작업이 완전히 완료되면 다음 작업을 수행하는 방식이다.

 

task1 (block발생, 프로그램이 멈춤) -> 서버로 데이터 요청, 받음 -> task1(나머지 동작 수행) task2 task3

 

의 과정을 수행한다. 즉, 코드가 반드시 작성된 순서대로 실행된다.

 

- 이때 비동기 작업은

task1 (block발생, 프로그램이 멈춤) -> 서버로 데이터 요청, 받음 -> task1(나머지 동작 수행) task3

                                              task2 수행                           

 

의 과정을 수행한다.

이를 병렬 프로그래밍 이라고 하며, 자원을 효율적으로 쓸 수 있다.

즉, 여러 개의 프로세스(task)가 돌아가고 있고, 멀티태스킹이 되고 있다는 뜻이다.

프로세스마다 각각 동작을 수행하겠지?

 

이렇게 멀티테스킹이 가능하게 만들어주는 코드가 Future이다.

어떻게 쓰는지 살펴볼까?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
String createOrderMessage () {
  var order = getUserOrder();
  return 'Your order is: $order';
}
 
Future<String> getUserOrder() {
  // Imagine that this function is more complex and slow
  return Future.delayed(Duration(seconds: 4), () => 'Large Latte');
}
 
main () {
  print(createOrderMessage());
}
cs

이 코드를 돌려보자.

결과가 어떻게 나오는가?

Your order is: Instance of '_Future<String>'

이렇게 나오면 정상이다.

getUserOrder()에서 'Large Latte'를 리턴하는데 4초가 걸린다.

createOrderMessage()는 getUserOrder()가 'Large Latte'를 리턴할 때 까지 기다렸다가,

'Your order is: $order' 를 리턴해야 하는데, 기다리지 않고 리턴했기 때문에 var order(변수) 에 값을 리턴받지 못한 상태로 메인함수의 print에 'Your order is: $order' 를 리턴한다. 따라서

Your order is: Instance of '_Future<String>' 의 결과가 나오는 것이다.

 

1
2
3
4
5
6
7
8
Future<void> getUserOrder() {
  return Future.delayed(Duration(seconds: 3), () => print('Large Latte'));
}
 
main() {
  getUserOrder();
  print('Fetching user order...');
}
cs

이 코드를 사용하면 결과는

Fetching user order...

Large Latte

와 같이 출력된다.

getUserOrder(); 가 먼저 실행됐더라도, print('Large Latte');를 수행하기 전에 3초를 대기하기 때문에 나중에 출력된다.

번 확인해보자.

 

 
 

그럼 이 Future를 활용하는 방법은?

async , await

로 알아보자

async및 await키워드는 비동기 함수를 정의하고 그 결과를 사용하는 선언적 방법을 제공한다.

async : async함수 본문 앞에 키워드를 사용하여 비동기로 표시할 수 있다.

async function : async함수는 async 키워드로 표시된 함수

await : await키워드를 사용하여 비동기식의 완성된 결과를 얻을 수 있다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Future<String> createOrderMessage() async {
  var order = await getUserOrder();
  return 'Your order is: $order';
}
 
Future<String> getUserOrder() {
  return
    Future.delayed(Duration(seconds: 4), () => 'Large Latte');
}
 
// Asynchronous
main() async {
  print('Fetching user order');
  print(await createOrderMessage());
}
cs

이 코드를 실행해보자

결과: 

Fetching user order

Your order is: Large Latte

2번째 line에 await가 보이는가? 

await 키워드를 사용하면, 결과값을 받아올 때 까지 기다렸다가 동작을 수행한다.

이를 통해서, createOrderMessage() 는 getUserOrder() 가 값을 리턴하면, 받아온 후에

값을 리턴한다.

그래서 올바른 출력 결과를 확인할 수 있다.

일단 이렇게 사용할 수 있고

 

마지막 예제를 보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void createOrderMessage () async {
  print('Awaiting user order...');
  var order = await getUserOrder();
  print('Your order is: $order');
}
 
Future<String> getUserOrder() {
  return Future.delayed(Duration(seconds: 4), () => 'Large Latte');
}
 
main() async {
  countSeconds(4);
  await createOrderMessage();
}
 
void countSeconds(s) {
  for( var i = 1 ; i <= s; i++ ) {
    Future.delayed(Duration(seconds: i), () => print(i));
  }
}
 

결과:

Awaiting user order...

1

2

3

4

Your order is: Large Latte

와 같이 나온다면 잘 했다.

 

이와같이,

Future.delayed(Duration(seconds: 정수), () => function());

혹은

return Future.delayed(Duration(seconds: 정수), () => 리턴할값);

변수 = await 기다리는function();

와 같은 form으로 사용한다면 딜레이를 줄 수 있고, 비동기식 프로그래밍을 할 수 있다.

 

짜잔!

 

여기까지.

 

출처: https://beomseok95.tistory.com/309