Dart 문법을 사용하여 비동기 프로그래밍 하는 방법을 알아본다.
트러블슈팅이 들어간 TIL은 따로 모으고 싶어서 게시글을 두 개로 나눴다.
과제와 관련된 내용은
https://velog.io/@utiranoj/TIL-RPG-게임2-필수-기능-보충
참조
프로그래밍을 할 때, 대부분의 코드는 작업을 순차적으로 처리한다.
작업 하나가 끝나서 결과가 나오면 값을 반환하고 다음 줄로 넘어가는 식이다.
이러한 코드를 동기적인 코드라고 부른다.
용량이 크지 않은 동작을 할 때는 동기적으로 프로그래밍해도 명시적인 차이가 보이지 않는다.
그러나 파일을 읽거나 데이터베이스에 접근하는 등 오랜 시간이 걸리는 작업을 할 때는 긴 처리시간동안 아무런 동작도 하지 않고 기다려야 한다는 점이 비효율적으로 느껴질 수 있다.
그래서 존재하는 것이 비동기 프로그래밍
이다.
비동기적인 코드는 작업이 완료되는 순간이 아닌, 미래의 특정 시점에 값을 반환한다. 그리고 그 동안 수행할 수 있는 다른 작업이 있다면 찾아서 계속 수행한다.
예를 들어서 아래와 같은 코드가 있다고 하자.
// *****
// 비동기 방식으로 file reading 하는 코드
// *****
print('1');
동기 방식에서는 긴 파일을 모두 읽고 난 후에야 '1'이 출력될 것이다.
하지만 비동기 방식에서는 파일 읽기를 시작한 다음 곧바로 1을 출력한다. 그리고 어느 시점에 파일 읽기가 끝나면 해당 값을 반환한다.
Dart에서도 비동기 프로그래밍을 할 수 있다. 비동기 프로그래밍을 지원하는 클래스는 Future
, Stream
으로 dart:async
를 import하여 사용한다.
하나의 작업 당 값 반환이나 이벤트가 한 번 발생하는 단일 비동기 작업에 사용한다.
사용자가 여러 번 써야 하거나 실시간으로 변경을 반영하는 동작에 어울리지 않는다.
비동기 프로그래밍에서 쓰이는 대표적인 클래스이다.
dart:async
의 클래스 중 하나이지만 dart:core
에도 포함되어있기 때문에 따로 SDK를 불러오지 않아도 사용할 수 있다.
Future
클래스에서는 delayed()
메서드를 통해 동작을 지연시킬 수 있다.
매개 변수로 지연할 시간을 전달하고 코드 블록 안에 지연 시간만큼 기다린 후에 처리할 동작을 적으면 된다.
만약 비동기 코드를 동기적인 코드처럼 실행되게 하려면 다음 과정을 거친다.
await
추가await
가 붙은 코드를 포함하는 전체 함수에 async
추가await
는 Future
류 함수에만 사용할 수 있다. 예를 들어서 void
타입의 함수에 await
를 적용하고 싶으면 반환타입을 Future<void>
로 바꿔야 한다.
하지만 await
를 쓴다고 해서 완전히 동기적인 결과가 나오는 것은 아니다.
await
키워드는 들어간 객체에만 효과를 발휘하기 때문에, 다음에 올 예정인 다른 객체가 있으면 프로그램은 해당 객체를 비동기적으로 먼저 실행한다.
하나의 작업 당 값 반환이나 이벤트가 여러 번 발생하는 경우에 사용한다.
비동기 연산의 결과값이 여러 번 반환될 때 그 값들을 순차적으로 받기 위해 쓰인다.
Future
와 마찬가지로 비동기 프로그래밍에 쓰이는 클래스이다.
Stream
은 시간에 따라서 연속적인 데이터 흐름을 제공한다. 결과값을 한 번 반환하면 자동으로 실행을 종료하는 Future
와 달리 계속 값을 받고 처리하기 위한 대기 상태에 있다는 의미이다.
따라서 실행 종료 시점을 따로 명시해야 한다.
값을 여러 번 내보내는 것이 주 쓰임새인 만큼 return
대신 yield
키워드로 값을 방출
할 수 있다. 반환과 달리 값을 방출해도 함수가 종료되지 않는다.
이 때 Stream
을 반환 타입으로 갖는 함수에는 async
가 아닌 async*
를 붙여야 한다.