본문 바로가기

춘기IT/춘기개발

동기 / 비동기 / await / async

동기(Synchronous) / 비동기(Asynchronous) / async / await에 대해 알아보겠습니다.

 

✅ 동기(Synchronous)

- 동기 방식은 작업이 순차적으로 실행되는 것을 의미합니다.

- 하나의 작업이 끝나야 다음 작업이 실행됩니다.

 

📌 동기 방식의 소스코드 예시

void main() {
  print('1. 시작');
  print('2. 처리 중');
  print('3. 완료');
}

//
1. 시작
2. 처리 중
3. 완료

 

ㄴ 예상대로 위에서 아래로 코드가 실행된 결과입니다.

    웬만한 프로그래밍의 경우 동기 방식으로 처리됩니다.

 

📌 동기 방식은 블로킹 / 비효율성이라는 단점이 있습니다.

1. 블로킹

- 하나의 작업이 완료될 때까지 다른 작업이 블로킹됨

- 특히 시간이 오래 걸리는 작업인 경우 전체 프로그램의 응답성이 저하됨

2. 비효율성

- 자원이 비효율적으로 사용될 수 있음 (ex. 네트워크 요청 동안 CPU는 유휴 상태)

 

✅ 비동기(Asynchronous)

- 비동기는 작업이 병렬적으로 처리될 수 있습니다.

- 즉, 동시에 여러 작업이 이루어질 수 있는 방식입니다.

- 작업이 완료될 때까지 기다리지 않고 다음 작업을 바로 시작하여

   주로, 네트워크 요청, 파일 읽기/쓰기 등 시간이 걸리는 작업에 사용됩니다.

 

📌 비동기 방식의 소스코드 예시

void main() {
  print('1. 시작');

  Future.delayed(Duration(seconds: 2), () {
    print('2. 2초 뒤 실행');
  });

  print('3. 완료');
}

// 출력
1. 시작
3. 완료
2. 2초 뒤 실행

 

ㄴ 2번 줄은 2초 뒤 실행되기 때문에, 먼저 3번이 출력됩니다.

 

📌 비동기 방식은 복잡성 / 디버깅이 어렵다는 단점이 있습니다.

1. 복잡성

- 코드가 복잡해질 수 있음

- 비동기 함수의 오류 처리 등이 복잡

2. 디버깅 어려움

- 비동기 코드의 흐름을 추적하고 디버깅하는 것이 더 어려움

- 이벤트 루프와 비동기 호출 스택을 이해해야 함

 

✅ async / await

동기와 비동기에 대해 설명하면 비동기 방식이 더 좋다고 느낄 수 있지만,

프로그래밍을 하다 보면 비동기 상황을 동기처럼 처리해야 할 때가 있습니다.

ex. 서버로부터 데이터 요청 시 요청한 것을 받아야만 화면에 결과를 보여줄 수 있기 때문에

요청하고 나서 결과를 받을 때까지 기다려야 하는 상황을 만들도록 처리할 수 있게 해주는 문법이 async와 await입니다.

 

🚀 async (함수가 비동기 함수임을 선언)

- 함수에 async를 붙이면 비동기 함수가 됨 

- 비동기 함수는 항상 Future 객체를 반환되도록 설계되어 있음

- 예시) Future<void> main() async {}

 

🚀 await (해당 작업이 끝날때까지 기다리겠다는 의미)

- await은 비동기 함수 내에서만 사용 가능

- Future가 완료될 때까지 기다리며 완료되면 결과 값을 반환함

- await은 비동기 코드를 동기 코드처럼 작성할 수 있게 해줌

- 예시) await Future.delayed(...)

 

📌 비동기 방식을 동기 방식으로 처리하는 소스 코드

void main() async{
  print('작업 1 시작');
  await performTask();
  print('작업 1 완료');
}

Future<void> performTask() async {
  await Future.delayed(Duration(seconds: 2));
  print('작업 2 실행');
}

// 출력
작업 1 시작
(2초뒤에)
작업 2 실행
작업 1 완료

 

📌 실전 예시: API(Application Programming Interface)호출

Future<void> fetchData() async {
  print('데이터 가져오는 중...');
  final response = await Future.delayed(Duration(seconds: 3), () => '데이터 완료');
  print('서버 응답: $response');
}

void main() async {
  print('앱 시작');
  await fetchData();
  print('다음 화면으로 이동');
}

//출력
앱 시작
데이터 가져오는 중...
서버 응답: 데이터 완료
다음 화면으로 이동

 

앱 개발에서 사용자 경험(UX)은 반응성과 속도가 핵심입니다.

예를 들어, 사용자가 버튼을 눌렀을 때 데이터를 서버에서 불러오느라 앱이 멈춘다면?!

사용자는 바로 앱을 삭제하고 싶어질 수 있으니까요... 그래서,

 

Flutter에서는 시간이 오래 걸리는 작업은 항상 비동기 방식으로 처리하고,
그 과정을 async/await로 깔끔하게 다루는 것이 중요합니다.