Flutter/Dart

Dart 기본 문법 3 - Future와 async/await

빈코더 2025. 1. 10. 15:03
728x90

안녕하세요! 오늘은 Flutter 개발에 필수적인 문법 중 

 

1. Dart 언어의 기본 문법 1편 - 변수, 함수, 클래스, 리스트, 조건문, 반복문

 

Dart 기본 문법 1 - 변수, 함수, 클래스, 리스트, 조건문, 반복문

안녕하세요! 오늘은 Flutter 개발에 필수적인 Dart 언어의 기본 문법을 정리해 보겠습니다. Dart는 Google에서 만든 프로그래밍 언어로, 특히 Flutter 앱 개발에서 사용됩니다. 이번 포스팅에서는 Dart의

binogood.tistory.com

 

2. Dart 언어의 기본 문법 2편 - Map, Null Safety, Enum, Set, 연산자

 

Dart 기본 문법 2 - 맵(Map), Null Safety, Enum, Set, 연산자

안녕하세요! 오늘은 Flutter 개발에 필수적인 Dart 언어의 기본 문법 1편에 이어 2편을 정리해 보겠습니다. 이번 포스팅에서는 Dart의 핵심 문법인 맵(Map),  Enum, Null Safety, Set, 연산자을 다룰 예정

binogood.tistory.com

 

이어 3편을 정리해 보겠습니다. ( 위 문법을 필수로 확인하셔야 합니다 !! )

 

이번 포스팅에서는 Dart의 핵심 문법인 Future와 async/await 를 다룰 예정입니다. 

1. Future와 async/await

Dart는 비동기 프로그래밍을 위해 Future, async, await 키워드를 지원합니다.

이는 주로 시간이 걸리는 작업(예: 네트워크 요청, 파일 읽기/쓰기)을 처리할 때 사용됩니다.

비동기 작업은 메인 스레드가 작업을 기다리며 멈추지 않고, 다른 작업을 계속 진행할 수 있도록 해줍니다.

 

1-1 Future

Future는 미래의 특정 시점에 값이나 에러를 제공하는 객체입니다.

  • 작업이 완료되면 값을 반환하거나 에러를 발생시킵니다.
  • then(), catchError(), whenComplete() 메서드를 사용하여 작업 완료 후 처리할 수 있습니다.

Future는 다음 세 가지 상태를 가질 수 있습니다.

  1. Uncompleted (미완료): 작업이 아직 끝나지 않음.
  2. Completed with a value (값 완료): 작업이 성공적으로 끝나고 값이 반환됨.
  3. Completed with an error (에러 완료): 작업이 실패하고 에러가 반환됨.
1번 예제 
Future<String> fetchData() async {
  return 'Hello from Future!';
}

void main() {
  fetchData().then((value) => print(value));
}

2번 예제 
Future<String> fetchData() {
  return Future.delayed(Duration(seconds: 2), () {
    return 'Data loaded';
  });
}

void main() {
  print('Fetching data...');
  fetchData().then((data) {
    print(data); // 2초 후 'Data loaded' 출력
  }).catchError((error) {
    print('Error: $error');
  }).whenComplete(() {
    print('Fetching complete');
  });
}

 

1-2 async/await

async와 await는 비동기 작업을 더 읽기 쉽게 작성할 수 있도록 도와줍니다.

  • async: 함수가 비동기 함수임을 나타냅니다.
  • await: 비동기 작업이 완료될 때까지 기다립니다.
# Future의 2번 예제를 async/await으로 작성

Future<String> fetchData() async {
  await Future.delayed(Duration(seconds: 2)); // 2초 대기
  return 'Data loaded';
}

void main() async {
  print('Fetching data...');
  try {
    var data = await fetchData(); // 데이터가 로드될 때까지 대기
    print(data);
  } catch (e) {
    print('Error: $e');
  } finally {
    print('Fetching complete');
  }
}

 

차이점

  • then() 방식은 콜백 체인이 많아지면 코드가 복잡해질 수 있습니다.
  • async/await 방식은 동기 코드처럼 읽히기 때문에 가독성이 좋습니다.

1-3 동기/비동기 코드의 혼합

async 함수 내부에서는 동기 코드와 비동기 코드를 혼합하여 사용할 수 있습니다.

await는 비동기 코드가 끝날 때까지 기다리게 하며, 그 동안 다른 작업을 계속 처리할 수 있습니다.

 

Future<void> performTasks() async {
  print('Task 1 started');
  await Future.delayed(Duration(seconds: 2)); // 비동기 작업
  print('Task 1 completed');
  
  print('Task 2 started');
  await Future.delayed(Duration(seconds: 1));
  print('Task 2 completed');
}

void main() {
  performTasks();
  print('Main function continues...');
}


## 출력 결과
Task 1 started
Main function continues...
Task 1 completed
Task 2 started
Task 2 completed

 

1-4 Future를 병렬로 처리하기 (Future.wait)

여러 Future를 동시에 실행하고, 모든 작업이 완료될 때까지 기다릴 수 있습니다.

Future<void> fetchUsers() async {
  await Future.delayed(Duration(seconds: 2));
  print('Users fetched');
}

Future<void> fetchOrders() async {
  await Future.delayed(Duration(seconds: 1));
  print('Orders fetched');
}

void main() async {
  print('Fetching data...');
  await Future.wait([fetchUsers(), fetchOrders()]);
  print('All data fetched');
}

## 출력 결과

Fetching data...
Orders fetched
Users fetched
All data fetched

 

1-5 에러 처리

비동기 작업 중 에러가 발생했을 때 적절히 처리할 수 있습니다.

## try-catch로 처리

Future<String> fetchDataWithError() async {
  await Future.delayed(Duration(seconds: 2));
  throw Exception('Failed to load data');
}

void main() async {
  try {
    var data = await fetchDataWithError();
    print(data);
  } catch (e) {
    print('Error: $e');
  }
}

## catchError로 처리

Future<String> fetchDataWithError() {
  return Future.delayed(Duration(seconds: 2), () {
    throw Exception('Failed to load data');
  });
}

void main() {
  fetchDataWithError().then((data) {
    print(data);
  }).catchError((error) {
    print('Error: $error');
  });
}

 

1-6 비동기 반복 (Stream)

Future가 단일 값에 대한 비동기 처리를 담당한다면, **Stream**은 여러 값의 비동기 처리를 지원합니다.

Stream<int> countStream(int max) async* {
  for (int i = 1; i <= max; i++) {
    await Future.delayed(Duration(seconds: 1)); // 1초 대기
    yield i;
  }
}

void main() async {
  await for (var value in countStream(5)) {
    print(value); // 1부터 5까지 1초 간격으로 출력
  }
}

 

Dart의 Future와 async/await는 비동기 작업을 처리하는 강력한 도구입니다.

Future를 통해 작업 상태를 추적하고, async/await를 사용해 동기 코드처럼 작성할 수 있어

가독성과 유지보수성이 높아집니다.

 

이제 Dart의 비동기 프로그래밍을 활용해 네트워크 요청이나 파일 작업 등 복잡한 비동기 로직을 효율적으로 처리해 보세요! 😊

더 궁금한 점이 있다면 댓글로 남겨주세요!

728x90