프로그래밍 실전 가이드

프로그래밍의 핵심 개념과 실무 활용

Rust중급
10시간
5개 항목
학습 진행률0 / 5 (0%)

학습 항목

1. Dart
Dart|Async|비동기|프로그래밍|완벽|가이드
퀴즈튜토리얼
2. Go
Go|채널|고루틴|동시성|프로그래밍
퀴즈튜토리얼
3. Java
Spring|WebFlux|리액티브|프로그래밍|완벽|가이드
퀴즈튜토리얼
4. JavaScript
Node.js|비동기|프로그래밍|완벽|가이드
퀴즈튜토리얼
5. Rust
Tokio|비동기|프로그래밍|Rust|고급
퀴즈튜토리얼
1 / 5

이미지 로딩 중...

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

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