Flutter

Flutter Day 8-1: 비동기 프로그래밍(Java vs Dart) 알아보기

@leem 2025. 1. 14. 15:01
비동기 프로그래밍은 현대 애플리케이션 개발에서 매우 중요한 개념입니다.
서버 요청, 파일 처리 등 시간이 오래 걸리는 작업을 비동기로 처리하면 앱의 응답성을 유지할 수 있습니다.
이번 포스팅에서는 Java와 Dart에서 비동기 프로그래밍의 차이점과 중요한 개념을 정리해 보겠습니다.

1. 비동기 프로그래밍이란?

동기(Synchronous): 코드가 순차적으로 실행되며, 한 작업이 끝날 때까지 다음 작업이 대기
 - 단점: 오래 걸리는 작업이 있으면 전체 흐름이 멈춤(Blocking)

 

비동기(Asynchronous): 작업 완료 여부와 상관없이 다음 코드가 실행되고, 작업이 완료되면 결과를 처리.
작업이 완료되면 콜백, Future, 또는 이벤트 루프를 통해 결과를 처리.
 - 장점: 효율적인 리소스 사용 및 빠른 응답.

2. Dart에서 비동기 프로그래밍

특징

  • Dart는 단일 스레드 기반의 이벤트 루프를 사용하여 비동기 작업을 처리합니다.
  • 비동기 작업은 주로 Future 객체로 처리되며, 필요에 따라 async/await 또는 then을 사용합니다.

Future 타입

  • Future 객체: 미래에 값을 반환하거나 오류를 발생시킬 약속(Promise).
  • async 함수 내부에서 await를 사용하면 Future가 완료될 때까지 실행을 멈췄다가 완료되면 다시 실행합니다.

1) async/await를 사용한 비동기 코드

  • async/await를 사용한 비동기 코드
void main() async {
  print('작업 1 시작...');
  var data = await fetchData();
  print('작업 2 진행...');
  print('결과 데이터: $data');
}

Future<String> fetchData() {
  return Future.delayed(
    Duration(seconds: 3),
    () => '3초 기다린 결과 데이터',
  );
}

 

  1. await로 fetchData 함수 호출.
  2. 3초 후 Future가 완료되면 결과 반환.

2) 연산 처리에서 Future 활용

void main() async {
  await addNumbers(10, 20);
  print('메인 함수 완료');
}

Future<void> addNumbers(int num1, int num2) async {
  print('addNumbers 함수 시작...');
  var result = 0;
  await Future.delayed(Duration(seconds: 3), () {
    result = num1 + num2;
  });
  print('결과 값: $result');
}
  1. 비동기 연산 처리 후 await로 결과 확인.
  2. Future.delayed를 활용하여 연산 지연.

3) then을 사용한 비동기 처리

void main() {
  addNumbersWithThen(10, 5).then((result) => print("결과: $result"));
  print('main() 함수 종료');
}

Future<int> addNumbersWithThen(int num1, int num2) {
  return Future.delayed(Duration(seconds: 3), () => num1 + num2);
}
  1. then을 사용하여 콜백 방식으로 결과 처리.
  2. main 함수는 결과가 준비되기 전에도 다른 작업 가능.
Future: 비동기 작업의 결과나 오류를 나타내는 객체.
async/await: 비동기 코드를 동기 방식처럼 작성 가능.
then: 콜백 방식으로 비동기 작업 완료 후 처리.
Future.delayed: 특정 시간 후 결과 반환.

3. Java에서 비동기 프로그래밍

특징

  • Java는 멀티스레드 기반으로 비동기 작업을 처리하며, 비동기 작업은 주로 CompletableFuture 또는 ExecutorService를 사용합니다.

코드 예제

CompletableFuture를 사용한 비동기 코드

import java.util.concurrent.CompletableFuture;

public class Main {
    public static void main(String[] args) {
        System.out.println("작업 시작");
        CompletableFuture<String> future = fetchData();
        future.thenAccept(result -> System.out.println("결과: " + result));
        System.out.println("다른 작업 실행 중...");
    }

    static CompletableFuture<String> fetchData() {
        return CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000); // 2초 대기
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Java 결과";
        });
    }
}

 

4. Dart vs Java: 주요 차이점

특징 Dart Java
비동기 객체 Future, Stream CompletableFuture, ExecutorService
병렬 처리 단일 스레드 기반, 병렬 처리는 Isolate로 처리 멀티스레드 기반, 병렬 처리가 기본적으로 가능
코드 흐름 async/await로 동기 코드처럼 작성 가능 thenApply와 같은 체인 방식 사용
스레드 관리 개발자가 직접 스레드를 제어하지 않음 개발자가 스레드를 생성하거나 관리 가능
에러 처리 try-catch 또는 catchError try-catch 또는 exceptionally

요약

Java의 주요 키워드

  1. Thread: 스레드를 생성하고 실행.
  2. Runnable: 실행 가능한 작업 정의.
  3. CompletableFuture: 비동기 작업 결과 처리.
  4. ExecutorService: 스레드 풀 관리.

Dart의 주요 키워드

  1. Future: 비동기 작업 결과를 나타냄.
  2. async/await: 비동기 작업을 동기 코드처럼 처리.
  3. Isolate: 병렬 작업을 위한 Dart의 독립 실행 환경.
  • Java는 멀티스레드와 병렬 처리에 강점이 있으며, 서버 및 대규모 백엔드 시스템 개발에 적합합니다.
  • Dart는 단일 스레드 기반으로 동작하며, UI 중심의 Flutter 앱 개발에 적합합니다.