🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

Dart Async 비동기 프로그래밍 완벽 가이드 - 슬라이드 1/11
A

AI Generated

2025. 10. 31. · 22 Views

Dart Async 비동기 프로그래밍 완벽 가이드

Dart의 비동기 프로그래밍을 처음부터 끝까지 다룹니다. Future, async/await, Stream 등 실무에서 필수적인 비동기 처리 패턴을 실전 예제와 함께 학습합니다.


카테고리:Dart
언어:Dart
메인 태그:#Dart
서브 태그:
#Async#Future#Stream#await

들어가며

이 글에서는 Dart Async 비동기 프로그래밍 완벽 가이드에 대해 상세히 알아보겠습니다. 총 10가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.

목차

  1. Future_기본_사용법
  2. async_await_패턴
  3. 에러_처리_try_catch
  4. Future_wait_병렬_처리
  5. Stream_기본_개념
  6. Stream_listen_구독
  7. StreamController_커스텀_스트림
  8. Stream_변환_map_where
  9. FutureOr_타입
  10. Completer_수동_Future_제어

1. Future 기본 사용법

개요

Future는 미래에 완료될 작업을 나타내는 객체입니다. 네트워크 요청이나 파일 읽기 같은 시간이 걸리는 작업에 사용됩니다.

코드 예제

Future<String> fetchUserData() {
  return Future.delayed(
    Duration(seconds: 2),
    () => 'User: John Doe'
  );
}

void main() {
  print('데이터 요청 시작');
  fetchUserData().then((data) => print(data));
  print('다른 작업 계속 진행');
}

설명

Future.delayed로 2초 후 데이터를 반환하며, then()으로 완료 후 실행할 콜백을 등록합니다. 비동기이므로 다른 작업이 블로킹되지 않습니다.


2. async await 패턴

개요

async/await는 비동기 코드를 동기 코드처럼 읽기 쉽게 작성할 수 있게 해줍니다. 콜백 지옥을 피하고 코드 가독성을 높입니다.

코드 예제

Future<void> loadUserProfile() async {
  print('프로필 로딩 시작');

  final user = await fetchUserData();
  final orders = await fetchOrders(user);

  print('완료: $user, 주문: $orders개');
}

Future<int> fetchOrders(String user) async {
  await Future.delayed(Duration(seconds: 1));
  return 5;
}

설명

async 함수 내에서 await 키워드로 Future가 완료될 때까지 기다립니다. 순차적으로 읽히지만 실제로는 비동기로 동작합니다.


3. 에러 처리 try catch

개요

비동기 작업에서 발생하는 에러는 try-catch로 처리할 수 있습니다. Future의 catchError 메서드도 사용 가능합니다.

코드 예제

Future<String> fetchData() async {
  try {
    await Future.delayed(Duration(seconds: 1));
    throw Exception('네트워크 오류');
  } catch (e) {
    print('에러 발생: $e');
    return '기본 데이터';
  }
}

void main() async {
  final result = await fetchData();
  print('결과: $result');
}

설명

try-catch 블록으로 비동기 함수의 예외를 처리합니다. 에러 발생 시 기본값을 반환하거나 대체 로직을 실행할 수 있습니다.


4. Future wait 병렬 처리

개요

여러 비동기 작업을 동시에 실행하고 모두 완료될 때까지 기다립니다. 순차 실행보다 훨씬 빠릅니다.

코드 예제

Future<void> loadDashboard() async {
  final results = await Future.wait([
    fetchUserData(),
    fetchNotifications(),
    fetchStatistics(),
  ]);

  print('모든 데이터 로드 완료');
  print('User: ${results[0]}');
}

Future<String> fetchNotifications() async {
  await Future.delayed(Duration(seconds: 1));
  return '알림 3개';
}

Future<String> fetchStatistics() async {
  await Future.delayed(Duration(seconds: 1));
  return '통계 데이터';
}

설명

Future.wait()는 여러 Future를 병렬로 실행하고 모든 결과를 리스트로 반환합니다. 대시보드처럼 독립적인 데이터를 한 번에 로드할 때 유용합니다.


5. Stream 기본 개념

개요

Stream은 연속적인 데이터의 흐름을 나타냅니다. 이벤트, 실시간 데이터, 파일 읽기 등에 사용되며 여러 값을 순차적으로 받을 수 있습니다.

코드 예제

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

void main() async {
  await for (final count in countStream()) {
    print('카운트: $count');
  }
  print('스트림 완료');
}

설명

async* 함수는 Stream을 생성하며, yield로 값을 하나씩 방출합니다. await for로 스트림의 각 값을 순차적으로 받아 처리합니다.


6. Stream listen 구독

개요

Stream을 listen()으로 구독하면 데이터가 발생할 때마다 콜백이 실행됩니다. 구독 취소도 가능합니다.

코드 예제

void main() {
  final stream = Stream.periodic(
    Duration(seconds: 1),
    (count) => count + 1
  ).take(5);

  final subscription = stream.listen(
    (data) => print('받은 데이터: $data'),
    onDone: () => print('완료'),
    onError: (e) => print('에러: $e'),
  );
}

설명

Stream.periodic은 주기적으로 데이터를 생성하고, listen()으로 구독합니다. onDone과 onError 콜백으로 완료와 에러를 처리합니다.


7. StreamController 커스텀 스트림

개요

StreamController로 직접 Stream을 제어할 수 있습니다. 원하는 시점에 데이터를 추가하거나 스트림을 닫을 수 있습니다.

코드 예제

import 'dart:async';

class ChatRoom {
  final _controller = StreamController<String>();

  Stream<String> get messages => _controller.stream;

  void sendMessage(String msg) => _controller.add(msg);

  void close() => _controller.close();
}

void main() {
  final chat = ChatRoom();
  chat.messages.listen((msg) => print('메시지: $msg'));

  chat.sendMessage('안녕하세요');
  chat.sendMessage('반갑습니다');
}

설명

StreamController로 커스텀 스트림을 만들고, add()로 데이터를 추가합니다. 채팅, 알림 등 실시간 이벤트 처리에 적합합니다.


8. Stream 변환 map where

개요

Stream도 리스트처럼 map, where 등으로 변환할 수 있습니다. 데이터를 필터링하거나 가공하여 새로운 Stream을 생성합니다.

코드 예제

Stream<int> numberStream() async* {
  for (int i = 1; i <= 10; i++) {
    yield i;
  }
}

void main() async {
  final evenSquares = numberStream()
    .where((n) => n % 2 == 0)
    .map((n) => n * n);

  await for (final value in evenSquares) {
    print('짝수의 제곱: $value');
  }
}

설명

where()로 짝수만 필터링하고 map()으로 제곱을 계산합니다. 원본 Stream을 변경하지 않고 새로운 Stream을 생성하는 함수형 프로그래밍 패턴입니다.


9. FutureOr 타입

개요

FutureOr<T>는 동기 값(T) 또는 비동기 값(Future<T>)을 모두 반환할 수 있는 타입입니다. 조건에 따라 즉시 또는 나중에 값을 반환할 때 유용합니다.

코드 예제

import 'dart:async';

FutureOr<String> getData(bool useCache) {
  if (useCache) {
    return 'cached data';
  } else {
    return Future.delayed(
      Duration(seconds: 1),
      () => 'fresh data'
    );
  }
}

void main() async {
  print(await getData(true));
  print(await getData(false));
}

설명

캐시가 있으면 즉시 반환하고, 없으면 Future를 반환합니다. await는 두 경우 모두 처리하므로 호출하는 쪽에서 타입을 신경 쓰지 않아도 됩니다.


10. Completer 수동 Future 제어

개요

Completer는 Future를 직접 완료시킬 수 있는 객체입니다. 콜백 기반 API를 Future로 변환할 때 유용합니다.

코드 예제

import 'dart:async';

Future<String> waitForUser() {
  final completer = Completer<String>();

  Timer(Duration(seconds: 2), () {
    completer.complete('사용자 입력 완료');
  });

  return completer.future;
}

void main() async {
  print('입력 대기 중...');
  final result = await waitForUser();
  print(result);
}

설명

Completer로 Future를 생성하고, complete()로 직접 완료시킵니다. 타이머나 이벤트 리스너 같은 콜백을 Future로 감쌀 때 사용합니다.


마치며

이번 글에서는 Dart Async 비동기 프로그래밍 완벽 가이드에 대해 알아보았습니다. 총 10가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.

관련 태그

#Dart #Async #Future #Stream #await

#Dart#Async#Future#Stream#await

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.

함께 보면 좋은 카드 뉴스

Riverpod 3.0 쇼핑 앱 종합 프로젝트 완벽 가이드

Flutter와 Riverpod 3.0을 활용한 실무 수준의 쇼핑 앱 개발 과정을 단계별로 학습합니다. 상품 목록, 장바구니, 주문, 인증, 검색 기능까지 모든 핵심 기능을 구현하며 상태 관리의 실전 노하우를 익힙니다.

Riverpod 3.0 Retry 자동 재시도 완벽 가이드

Riverpod 3.0에 새로 추가된 Retry 기능을 활용하여 네트워크 오류나 일시적인 실패 상황에서 자동으로 재시도하는 방법을 배웁니다. 초급 개발자도 쉽게 따라할 수 있도록 실무 예제와 함께 설명합니다.

Riverpod 3.0 requireValue로 Provider 결합하기

Riverpod 3.0에 새로 추가된 requireValue를 활용하여 여러 Provider의 데이터를 효율적으로 결합하는 방법을 배웁니다. 비동기 데이터를 마치 동기 데이터처럼 다루는 실전 패턴을 소개합니다.

Flutter 3.0 Offline 데이터 영속화 완벽 가이드

Flutter 3.0에서 새롭게 추가된 Offline 데이터 영속화 기능을 배웁니다. Storage 인터페이스부터 SharedPreferences 활용, 실전 예제까지 실무에서 바로 사용할 수 있는 패턴을 배워봅시다.

Riverpod 3.0 Mutation으로 폼 제출 완벽 가이드

Riverpod 3.0의 새로운 Mutation 기능으로 로그인과 회원가입 폼을 우아하게 처리하는 방법을 배웁니다. 로딩 상태, 에러 처리, 성공 처리까지 실무에서 바로 쓸 수 있는 패턴을 익혀보세요.

이전
1/4다음