관리 메뉴

나만을 위한 블로그

[Dart] Future, async / await를 사용한 비동기 프로그래밍 본문

개인 공부/Flutter

[Dart] Future, async / await를 사용한 비동기 프로그래밍

참깨빵위에참깨빵 2023. 8. 5. 21:42
728x90
반응형

비동기 프로그래밍이 무엇이고 왜 필요한지 모른다면, 잠시 생각해 보자. 비동기라는 건 뭘까?

아주 간단한 예시를 들어 본다. 어떤 식당에 들어갔는데 키오스크 앞에 이미 줄 서 있는 사람들이 5명 정도 있다고 가정한다. 내가 주문하려면 내 앞의 5명이 모두 키오스크를 통해 주문을 완료하고 자기 자리로 돌아가야 한다.

그리고 내 앞의 사람들은 키오스크에서 메뉴를 고른 다음 결제를 해서, 주문완료라는 화면이 표시된 뒤에야 키오스크 앞을 뜰 수 있다. 이 일련의 과정들은 나를 비롯해 내 뒤에 줄을 선 사람들도 공평하게 모두 똑같이 겪어야 하는 일이다.

이것이 동기(synchronous)다. 즉 어떤 요청이 발생하면 시간이 얼마나 걸리든 그 자리에서 결과를 받아야 한다. 만약 내 앞의 누군가가 결정을 빨리 못 하는 타입이라 한참을 고민한다면, 그 사람 뒤에서 기다리는 다른 사람들과 나는 그저 기다릴 수밖에 없다. 왜냐면 이 결정이 느린 사람이 메뉴를 고르고 결제를 완료해야 하기 때문이다.

 

이 경우를 위해 비동기 프로그래밍이 존재한다. 식당에 키오스크가 5대 있고 직접 주문할 수 있는 주문대도 있다면, 동시에 여러 명의 사람들이 주문을 끝내고 자리로 이동할 수 있다. 이렇게 되면 결정을 빨리 내리지 못하는 사람이 있더라도 그리 오래 기다리지 않고 내 주문을 완료할 수 있다. 이것이 비동기(asynchronous)다.

 

프로그래밍으로 넘어와서 동기와 비동기의 차이를 보면, 동기는 요청한 작업이 완료될 때까지 기다렸다가 결과를 받는 것이고, 비동기는 요청 후 다른 작업을 계속하다가 작업이 완료됐을 때 결과를 받는 방식이라는 차이가 있다.

 

플러터에선 Future 클래스와 async, await를 적절히 사용하면 비동기 프로그래밍을 구현할 수 있다. 아래는 Future 클래스를 사용한 간단한 비동기 프로그래밍 예시다.

 

void addNumbers(int number1, int number2) {
  print("계산 시작");

  Future.delayed(const Duration(seconds: 3), () {
    print("$number1 + $number2 = ${number1 + number2}");
  });

  print("addNumbers() end");
}

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

// 계산 시작
// addNumbers() end
// 1 + 1 = 2

 

Future.delayed()는 이름에서 유추할 수 있겠지만 몇 초 뒤에 () {} 안의 내용을 실행하도록 지연을 거는 함수다. 그래서 실행 로그를 보면 addNumbers()의 마지막 줄까지 실행돼도 3초가 아직 지나지 않았기 때문에 잠시 후에 두 매개변수를 더한 값이 출력된다. 그리고 나서야 프로그램이 종료된다.

Future.delayed()에 API를 호출하는 코드나 DB에 접근하는 로직 등이 들어가면 될 것이다. 그런데 Duration을 설정하는 부분이 걸린다. 만약 어떤 기기에선 2초만에 API 호출이 완료됐지만 어떤 기기에선 5초가 지나도 API 호출이 완료되지 않을 수 있다. 이렇게 되면 Duration을 설정하는 의미가 없어진다.

 

이 경우에 async, await를 사용하면 좋다.

 

Future<int> addNumbers(int number1, int number2) async {
  print("계산 시작");

  await Future.delayed(const Duration(seconds: 3), () {
    print("$number1 + $number2 = ${number1 + number2}");
  });

  print("addNumbers() end");

  return number1 + number2;
}

void main() async {
  final result = await addNumbers(1, 1);
  print("결과 : $result");
}

// 계산 시작
// 1 + 1 = 2
// addNumbers() end
// 결과 : 2

 

addNumbers()의 함수 매개변수 선언부와 바디 사이에 async를 넣고, Future.delayed() 앞에 await를 걸었다. await는 비동기로 작업을 수행하는 함수 앞에 입력하면 된다.

그리고 main 함수도 async를 붙이고 안에서 결과값을 받을 때에도 await를 붙였기 때문에 계산이 완료되는 3초가 지난 후에 계산 결과가 나오면서 addNumbers()가 종료되고, main 함수에서 결과값을 받아 출력하게 된다.

반응형
Comments