Study/Dart,Flutter

4. Dart Flutter, 플러터의 비동기식 Future, await 그리고 async

코딩 잘 할거얌:) 2021. 7. 28. 03:09
반응형

포스팅이 점점 더 기초적으로 가지만, 짚고 넘어가야 할 것 같아서 작성하게 되었다.

앞서 Dart의 비동기의 작동방식을 살펴보았다. 그러면 어떻게 사용하는지 살펴보자.


바쁜 사람을 위한 빠른 결론!

  1. Dart Flutter에서 비동기식을 사용할 때 Future, async, await를 사용한다.
  2. 함수 이름 앞 Future은 반환을 나타낸다. 가독성을 위해 적는것을 추천하지만, 생략해도 무방하다. 
  3. await를 사용하기 위해서는 반드시 async가 적혀있어야한다.
  4. await를 사용하면 비동기 함수가 끝날때까지 기다리며, await를 사용하지않으면 기다리지않는다.
  5. 비동기함수가 끝났음을 알리고싶다면 Callback함수를 이용하여 알릴 수 있다.

직전 포스팅을 안 읽은 사람들을 위해 Dart 공식홈페이지 링크를 다시 올리겠다.

https://dart.dev/codelabs/async-await

 

 

Asynchronous programming: futures, async, await

Learn about and practice writing asynchronous code in DartPad!

dart.dev

 

Flutter에서 비동기식을 왜 사용할까?

여러이유가 있겠지만 가장 큰 이유는 외부DB에 생성,읽기,수정,삭제(CRUD)하는데 있다 . 외부에서 데이터를 조작하는동안 메인에서는 다른 작업을 할 수 있다. 그래서 데이터를 가져오는동안 메인에서 다른작업 수행하고, 비동기식으로 불러온 데이터가 준비완료 된다면 사용하는 방식이 되어야 한다.

비동기식으로 외부데이터를 불러올 때 메인에서는 로딩을 띄울 수 있다.(CupertinoActivityIndicator)

 

그러면 비동기를 사용한 코드를 보자.

위의 Dart 공식홈페이지를 보거나 구글링을 조금만 해 보면 비동기식을 알 수 있겠지만, 처음부터 천천히 다져보자.

  void main() {
    getCoffee();
  }

  getCoffee() async {
    String menu = await todayCoffee();
    print("Today Coffee is $menu"); 
  }

  //쌍따옴표 사이에 $는 변수를 String으로 출력하기 위한 것이다.
  //함수 속 변수를 출력하려면 ${Starbucks.coffee} 처럼 사용해야한다.


  Future<String> todayCoffee() {
    return Future.delayed(Duration(seconds: 1), () => "Latte");
  }

  //=>의 표현은 람다(Lambda)식 이라고 읽는다.
  //간단하게 return처럼 사용하면 되며, 자세한내용은 아래링크 참고
  //https://khj93.tistory.com/entry/JAVA-%EB%9E%8C%EB%8B%A4%EC%8B%9DRambda%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EA%B3%A0-%EC%82%AC%EC%9A%A9%EB%B2%95


  //출력
  //(1초 후)
  //Today Coffee is Latte

최대한 쉽게 작성했지만, 보자마자 머리아플 수 있으니 차근차근 설명하겠다.

 

getCoffee에서 매개변수(parameter)를 받는 ()와 {}사이에 async가 적혀져있다. 이 async는 반드시 await를 사용하기위해서 필요하다. async를 붙이지 않으면 await를 사용 할 수 없다.

 

그렇다면 await는 무엇일까? 말그대로 기다리는거다. 비동기 함수가 끝날 때까지 기다린다. 기다린 후 그 이후의 작업을 진행하게 된다. 그래서 출력값은 딜레이 1초 후 Today Coffee is Latte가 되는 것이다. await는 반환값이 Future인 함수 앞에 사용한다.(물론 아닌거에도 붙일 수 있긴하고, async가 있는데 await를 안 써도 된다.)

 

Future<String>은 String으로 반환을 하는데, 비동기로 반환을 한다. 라고 이해하면 좋다. 물론 Future<String>의 부분은 생략이 가능하며, Future 만 사용해도 자동으로 Future<dynamic>으로 인식한다.

 

몇몇 분들은 'await해서 기다릴거면 비동기식으로 사용한 의미가 없지않나?' 라고 생각 할 수 있다.

  void main() {
    getLunch();
  }

  todayLunch() {
    return Future.delayed(Duration(seconds: 1), () {
      print("Pasta");
    });
    // () {print("Pasta");}는 ()=>print("Pasta")로 가능하다.
  }

  getLunch() {
    print("Today Lunch");
    todayLunch();
    print("Still Wait");
  }
  //출력
  //Today Lunch
  //Still Wait
  //Pasta

 

비동기식 처리를 기다리지 않길 원하면 await를 붙이지 않으면 된다. 

 

'그러면 비동기식으로 처리하고 끝났으면 main에 알리고싶으면 어떻게하지?' 라고도 생각할 수 있다. 전역변수를 사용해도 되지만, 개인적으로 Callback함수를 사용하는게 더 낫다고 생각한다.

  void main() {
    todayDinner();
  }

  todayDinner() {
    print("Today Dinner");
    getDinner(menuCallback);
    print("Still Wait...");
  }

  getDinner(Function callback) {
    return Future.delayed(Duration(seconds: 1), () {
      String menu = "Steak";
      callback(menu);
    });
  }

  menuCallback(String menu) => print("Today Dinner is $menu");

  //Callback함수는 
  //1. 다른 함수의 인자로써 이용되는 함수.
  //2. 어떤 이벤트에 의해 호출되어지는 함수.
  //라고 할 수 있다. 더 자세한건 아래 링크 참고
  //https://stackoverflow.com/questions/824234/what-is-a-callback-function


  //출력
  //Today Dinner
  //Still Wait...
  //Today Dinner is Steak

 

그렇다면 어디에서 await를 쓰고 어디에서 await를 쓰지않으면 될까?

앱을 키는순간 중요한 데이터들은 await해서 데이터를 불러와야 할 것이다. 하지만 상대적으로 중요도가 떨어지는 데이터들은 await를 사용하지 않고 백그라운드에서 작업을 진행해도 무방할 것이다.

 

예를들어 중고장터같은 앱을 제작한다고 했을 때, 사용자의 정보와 바로 보여야하는 메인화면에 관련된 데이터는 await를 써야 할 것이다.

하지만 메인화면에 바로 보여지지 않는 공지사항같은 것은 await를 사용하지 않고, 사용자가 불러오기 전 공지사항을 실행한다면 로딩창을 띄워주면 될 것이다.


결론

  1. Dart에서 비동기식을 사용할 때 Future, async, await를 사용한다.
  2. 함수 이름 앞 Future은 반환을 나타낸다. 가독성을 위해 적는것을 추천하지만, 생략해도 무방하다. 
  3. await를 사용하기 위해서는 반드시 async가 적혀있어야한다.
  4. await를 사용하면 비동기 함수가 끝날때까지 기다리며, await를 사용하지않으면 기다리지않는다.
  5. 비동기함수가 끝났음을 알리고싶다면 Callback함수를 이용하여 알릴 수 있다.

오류, 지적사항 그리고 궁금한 것은 댓글 이용 부탁드립니다.

728x90