[Flutter] 비동기 개념과 관련 키워드 알아보기(Future, async, await, then)

2024. 3. 1. 01:00·Flutter
728x90

서버에서 값을 가져오는 http 요청이나 파일에서 값을 가져올 때 비동기 개념을 많이 사용한다.

오늘은 비동기 개념과 관련된 예약어의 쓰임을 정리해보려고 한다.

 

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

 

Asynchronous programming: futures, async, await

Learn about and practice writing asynchronous code in DartPad!

dart.dev

 

예제 코드는 위 공식사이트에서 사용하는 코드를 사용했다.

 

비동기(Asynchronous)란?

 

한 작업이 완료될 때 까지 기다리지 않고 다른 작업을 동시에 수행하는 것을 말한다.

 

http 요청과 같은 작업에 비동기를 사용하는 이유는 네트워크를 이용하는 작업으로 네트워크 지연 시간이나, 서버에서 작업을 처리하는 시간들이 추가적으로 들 수 밖에 없다.

 

이러한 작업을 동기로 처리하게 된다면 값을 보내고 처리하고 다시 받는 시간 동안 어플은 할 수 있는게 없으므로 작동이 멈추게 될 것이다.

 

이것은 사용자들에게도 불편하게 느껴질 것이고 UX 측면에서 좋지 않을 것이다.

 

Future

 

Future 타입은 비동기 함수의 결과를 나타내거나 반환할 때 사용된다.

 

밑에 예시를 보자.

String createOrderMessage() {
  var order = fetchUserOrder(); // 내부에 값이 정해지지 않은 Future 객체 반환받음
  return 'Your order is: $order';
}

// Future 타입을 반환, 실제 값은 2초 뒤에 결정
Future<String> fetchUserOrder() =>
    Future.delayed(
      const Duration(seconds: 2),
      () => 'Large Latte',
    );

void main() {
  print('Fetching user order...');
  print(createOrderMessage());
}

위의 코드 실행 결과

 

Future 타입을 반환하면 작업이 완료된것(값이 결정된 것)과 상관없이 Future 타입을 반환한다.

실제 값은 비동기적으로 처리되어진다. (2초 뒤에 값이 결정)

Future 라는 껍데기만 가고 내부의 내용은 없다고 생각하면 편하다.

 

그래서 order 라는 변수의 값을 출력하면 Instance of '_Future<String>' 이라는 원하지 않는 결과를 반환한다.

 

그래서 Future 타입을 다루기 위해서 async, await 을 사용한다.

 

async

 

async 키워드는 함수를 비동기 함수로 만들 때 쓰인다.

async 키워드를 통해 선언되어진 함수들은 항상 Future 객체를 반환한다.

Future 타입의 객체를 통해 나중에 사용할 값을 사용한다.

 

//async로 함수 선언, 리턴 타입을 Future 로 변경
Future<String> createOrderMessage() async{
  var order = fetchUserOrder();
  return 'Your order is: $order';
}

// Future 타입을 반환, 실제 값은 2초 뒤에 결정
Future<String> fetchUserOrder() =>
    Future.delayed(
      const Duration(seconds: 2),
      () => 'Large Latte',
    );

//async로 함수 선언, 리턴 타입을 Future 로 변경
Future<void> main() async{
  print('Fetching user order...');
  print(createOrderMessage());
}

 

위의 코드 실행 결과

createOrderMessage() 함수와 main() 함수를 모두 비동기로 선언하여 반환 값을 모두 Future 타입으로 바꿨다.

하지만, 결과는 바뀌지 않는다. 

 

함수가 실행되고 값이 결정되기 전까지 기다리지 않았기 때문이다.

 

이 함수가 실행되고 기다리기 위해서 await 키워드를 사용한다.

 

await

 

함수에 async 가 쓰여진 함수에서만 await 키워드를 사용할 수 있다.

 

await 키워드는 Future 객체의 연산이 모두 끝나 결과가 나올때 까지 기다리는 역할을 한다.

함수 앞에 await 키워드를 추가해본다.

//함수 앞에 await 추가
Future<String> createOrderMessage() async{
  var order = await fetchUserOrder(); // 함수가 실행을 완료할때까지 기다린다.
  return 'Your order is: $order';
}

// Future 타입을 반환, 실제 값은 2초 뒤에 결정
Future<String> fetchUserOrder() =>
    Future.delayed(
      const Duration(seconds: 2),
      () => 'Large Latte',
    );

//함수 앞에 await 추가
Future<void> main() async{
  print('Fetching user order...');
  print(await createOrderMessage());
}

 

위 코드의 실행 결과

 

드디어 우리가 원하는 값을 얻을 수 있다.

 

then

 

then은 Future 객체의 작업이 완료되면 어떤 작업을 실행할지를 정하는 데 사용된다.

then은 반환타입이 Future 객체일때만 사용할 수 있다.

 

예를 들어 int 형을 반환하는 함수 뒤에 then을 사용하면 오류가 난다.

int printTwo(){
	return 2;
}

void main(){
  printTwo().then((value){ // Error :'then' isn't defined for the class 'int'.
  	print(value);
  }); 
}

 

전에 사용되던 예시 코드를 then을 사용하여 처리하면 이렇게 만들 수 있다.

// async, await 대신 then을 사용
Future<String> createOrderMessage() {
  return fetchUserOrder().then((order) {
    return 'Your order is: $order';
  });
}

// Future 타입을 반환, 실제 값은 2초 뒤에 결정
Future<String> fetchUserOrder() =>
    Future.delayed(
      const Duration(seconds: 2),
      () => 'Large Latte',
    );

// async, await 대신 then을 사용
void main(){
  print('Fetching user order...');
  createOrderMessage().then((value){
  	print(value);
  });
}

위 코드의 실행 결과

 

의문 해결

 

main 함수 밑에 String 타입의 orderMessage를 생성하여 then 함수 안에서 값을 대입하여 출력해보려 했다.

하지만, 밑에 코드는 오류가 났다.

Future<String> createOrderMessage() async{
  var order = await fetchUserOrder(); // 함수가 실행을 완료할때까지 기다린다.
  return 'Your order is: $order';
}

// Future 타입을 반환, 실제 값은 2초 뒤에 결정
Future<String> fetchUserOrder() =>
    Future.delayed(
      const Duration(seconds: 2),
      () => 'Large Latte',
    );

void main(){
  print('Fetching user order...');
  String orderMessage; // orderMessage 변수 생성
  createOrderMessage().then((value){
  	orderMessage = value; // orderMessage 변수에 대입
  });
  print(orderMessage); //Error: Non-nullable variable 'orderMessage' must be assigned before it can be used.
}

 

이유는 print(orderMessage); 가 비동기적으로 실행되었기 때문이다.

 

main 함수 내에서 동작이 이루어지는 순서는 아래처럼 이루어진다.

1. print('Fetching user order...');

2. String orderMessage; 

3. createOrderMessage().then((value){
   orderMessage=value;
  });

4. print(orderMessage);

 

하지만 완료되는 순서는 아래처럼 이루어진다.

1. print('Fetching user order...');

2. String orderMessage; 

3. print(orderMessage);

4. createOrderMessage().then((value){
   orderMessage=value; 
  });

 

이렇게 보면 null 을 출력하려 했으니 오류는 당연히 일어날 수 밖에 없어보인다.

 

느낀 점

 

  • Future 객체를 다루면서 데이터를 처리하는 일을 할때는 async / await 을 이용하여 처리하는 것이 좋은 것 같다.
  • then은 출력하는 것 처럼 단순한 일에는 편할 것 같다.
  • async / await 이 then 보다 가독성이 좋은 것 같다.

 

 

 

 

728x90

'Flutter' 카테고리의 다른 글

[Flutter] 상태 관리란? (GetX를 선택한 이유)  (0) 2024.03.08
[Flutter] Null safety 및 여러 문자의 의미(?, !, ??, ??=, < >, _, ..)  (1) 2024.03.06
[Flutter] 자주 사용하는 색상 및 글꼴 관리하기  (0) 2024.03.03
[Flutter] Figma Color Hex값 이용해서 색 설정하기  (0) 2024.02.27
[Flutter] React Native 말고 Flutter를 공부한 이유  (0) 2024.02.25
'Flutter' 카테고리의 다른 글
  • [Flutter] Null safety 및 여러 문자의 의미(?, !, ??, ??=, < >, _, ..)
  • [Flutter] 자주 사용하는 색상 및 글꼴 관리하기
  • [Flutter] Figma Color Hex값 이용해서 색 설정하기
  • [Flutter] React Native 말고 Flutter를 공부한 이유
Sanghyundal
Sanghyundal
  • Sanghyundal
    초보 개발자
    Sanghyundal
  • 전체
    오늘
    어제
    • Coding
      • Flutter
      • FE
      • CS 공부
      • Git
      • 활동 관련
      • SKALA
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    SK
    css normalize
    oscca
    Get.put()
    crew ai
    initialBinding
    클라우드
    멋쟁이 사자처럼 해커톤
    pr agent
    turbopack
    ossca
    skala 부트캠프
    skala1기
    skala 1기
    자바스크립트 이벤트 위임
    우테코 프론트엔드
    JS 이벤트 위임
    Get.lazyPut()
    ai agent
    skala
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Sanghyundal
[Flutter] 비동기 개념과 관련 키워드 알아보기(Future, async, await, then)
상단으로

티스토리툴바