Dart Programmer 되기 [26]

< Dart 기초문법 – Library and File/Stream/Process >

Library는 단어 그대로 도서관이라는 의미입니다. 대신 프로그래밍 언어에서의 도서관이란, 책이 아닌 소프트웨어 코드들이 있는 것이지요. 실제로 물리적으로 어딘가를 간다는 의미가 아니고, 1) 내가 만든 멋진 소프트웨어 코드를 두고 두고 재활용(!)하기 위함 2) 남이 만든 검증된 코드를 재활용(!)하여 개발 기간의 단축과 조기 안정성 확보를 도모함 이라 생각하면 됩니다. Library는 프로그래밍 언어에서 기본적으로 제공하는 built-in library와 제3자(개발자 본인 포함)가 만들었기에, 별도로 설치해야 하는 3rd-party library로 나뉩니다. 본 글에서는 전자인 Dart 언어의 built-in library를 중심으로 하며, 이 튜토리얼의 흐름에서 알아야 하는 부분을 중심으로 설명합니다.

Built-in Library in Dart

dart:core는 가장 기본적인 기능을 제공하며, 개발자가 아무런 작업을 별도로 하지 않아도, 개발하는 프로그램에 자동으로 포함됩니다. 지금까지의 글에서 제공되는 built-in 데이터 타입 들에 대한 사항을 포함하여 가장 기초가 되는 기능들로 이루어 집니다.

dart:async는 앞서 async 파트에서 확인한 비동기적 기능을 제공하는 library 입니다. Dart 2.1 버전 부터 개발자가 별도로 작업을 하지 않아도, dart:core를 통해서 개발하는 프로그램 내부에 포함이 됩니다.

dart:math는 최대값, 최소값과 같이 가장 기본이 되는 수학적인 기능들을 포함하여, 난수발생(random number generation)과 같은 복잡한 기능까지를 제공하는 library 입니다. 이 기능을 사용하고자 한다면, 개발하는 프로그램의 시작부분에 import “dart:math”;를 입력하면 됩니다.

dart:convert는 글자와 숫자에 대한 코딩을 담당하는 library 입니다. 앞 부분의 글에서 언급된 적이 있는 Unicode와 UTF, 그리고 JSON 등의 데이타 표현 방식에 대한 기능을 제공합니다. 이 기능을 사용하고자 한다면, 개발하는 프로그램의 시작부분에 import “dart:convert”;를 입력하면 됩니다.

다음으로 설명할 dart:html 및 dart:io를 설명하기 전에 알아야 할 부분이 있습니다. 이를 아래의 그림을 보면서 이해해 봅니다.

[그림 1] Dart 언어 지원 플랫폼 및 개발 방법 (출처: https://dart.dev/platforms)

dart:io는 개발한 프로그램이 스마트폰과 같은 모바일앱, 데스크탑 컴퓨터, 그리고 서버 프로그램을 개발하고자 할 때 사용하는 library이며, 이는 Native 영역 이라고 합니다. 즉, Dart Native 라고 하며, ARM/x86 CPU 위에서 동작하는 프로그램을 개발하는 것 입니다. 이런 경우에 사용하는 library가 dart:io 입니다. Dart I/O는 Dart VM(Virtual Machine), Flutter Apps, Server, Command-line Script 등을 위해서 사용합니다. 여기서 첨언하면, Flutter에서는 dart:io 대신 Flutter-specific한 API 들을 사용하도록 권장하고 있는점 참조하기 바랍니다. 참조로 그림에서 Develop는 개발하는 시점을 의미하며, Deploy는 실제 운영하는 시점을 의미 합니다. 그림안에 등장 하는 단어들에 대해서는 향후 설명할 시간이 있을 예정 이므로, 지금은 설명하지 않습니다.

dart:html은 웹브라우저 기반의 서비스를 만들때 사용하여 웹의 DOM(Document Object Model)을 제어하기 위한 용도입니다. Dart는 기본적으로 웹 상에서 동작할때 JavaScript로 변환하여 동작하게 됩니다. Dart가 제공하는 dart:html 외에도, Flutter framework는 이런 웹 서비스/어플리케이션을 제공하며, AngularDart의 경우도 웹 기반의 서비스/어플리케이션을 Dart 언어로 개발할때 활성화 되고 있는 도구이니 참조하십시오.

Useful Sites for Dart Libraries

Dart 언어의 library 들에 대한 설명이 필요하다면, 다음의 사이트 들이 어느 정도 이해를 도울 수 있을 것으로 생각되니, 참조합니다. 특히 dart:core, dart:math, dart:async, dart:html의 경우는 아래의 첫번째 사이트인 ‘A tour of the core libraries‘를 한번 정독하기 바랍니다. 지금까지의 글을 통해서 살펴온 내용을 library라는 입장에서 다시 한번 정리하는 계기가 될 것 입니다.

Understanding Standalone Dart VM Operation

Dart 언어를 기본적으로 single-threaded 방식이라고 합니다. 쉽게 이야기 하면, Dart 언어로 만든 프로그램은 일꾼이 하나라고 보면 됩니다. 따라서 처리할 일이 여럿 이면, 한명의 일꾼이 일을 하나씩 하나씩 마쳐야 한다는 의미입니다. 이렇게 되면, 지연이 상당히 발생할 우려가 있는 입출력 기능을 필연적으로 멈춰있는 시간이 많아지고, 이를 블럭킹(blocking)이라고 합니다. 이러한 이유로 동시에 여러 작업을 해야 한다면, 앞서 글에서 살펴본 async 동작과 관련한 기술을 필연적으로 사용하게 됩니다. 이를 이해하기 위하여, 다음의 그림과 이에 대한 설명을 숙지해 봅시다.

[그림 2] Dart 프로그램의 내부 Queue (큐) 구조
(출처: https://buildflutter.com/flutter-threading-isolates-future-async-and-await/)

Dart 언어로 만든 프로그램은 실행과 함께 그림2와 같은 두 개의 큐를 만듭니다. Queue(큐)는 프로그램이 수행해야할 다양할 일들을 쌓아놓은 후, 중요도(우선순위)와 발생순서 등을 담안하여 처리됩니다. Queue가 두개인데, 키보드, 마우스, 타이머, 제스추어(gesture), 드로잉(drawing) 등의 주로 사용자의 입출력에 대한 사항은 Event Queue에 저장됩니다. Microtask Queue는 상대적으로 우선순위가 Event Queue보다 높으며, 프로그램에서 동작시키는 짧은 비동기 동작들을 저장하는데 사용합니다.

Native 방식의 (서버 측) 애플리케이션을 실행할 때, Dart VM은 보류(저장) 중인 비동기 작업의 관련 이벤트 큐와 함께 이벤트 루프에서 실행 합니다. Dart VM은 현재 코드를 실행하여 완료하고 더 이상 보류 중인 작업이 Queue에 없으면 종료 합니다. 이를 간단한 코드로 이해하기 위하여 An introduction to the dart:io library 홈페이지의 샘플 코드들을 살펴 보겠습니다 (출처: https://dart.dev/articles/libraries/dart-io).

Dart의 Queue 구조를 이해하고, 앞서 배운 async의 개념을 아주 간단하게 연결한 다음의 darttutorial-26-01.dart과 실행결과를 살펴보는 것으로 시작하겠습니다. darttutorial-26-01.dart 프로그램은 다음과 같습니다.

// darttutorial-26-01.dart
// Reference: https://dart.dev/articles/libraries/dart-io

import 'dart:async';

void main() {
  Timer(Duration(seconds: 1), () => print('timer'));
  print('end of main');
}

darttutorial-26-01.dart 프로그램의 수행결과가 아래와 같이 나와 있습니다. Timer()는 Dart 언어의 built-in library로써 필연적으로 aync 함수입니다. 이의 사용을 위해서 dart:async library를 사용하도록 import 명령을 사용 했습니다. 동작해야할 시점과 동작을 정하며, 예제의 경우는 1초후 timer 문자열을 출력하라는 의미입니다. 따라서, main()의 마지막 부분인 print(‘end of main’);이 수행되고 나면, 이후 타이머가 지정한 시점에서 print(‘timer’)가 실행되는 모습을 확인할 수 있습니다. 따라서, 앞서 async에서 배운 것처럼, main()에서 할일은 다하고 기다리다가, 비동기 동작들까지 모두 마친후에 프로그램을 동료하는 것을 확인할 수 있습니다.

end of main
timer

Files, Directory and Platform in dart:io Library

지금까지 다루지 않았던 내용이지만, 많이 사용하는 기능 중 하나가 file을 다루는 부분입니다. 여기에서는 file을 다루는 File class (참조), file을 찾아가기 위한 Directory class (참조), 그리고 program이 동작하는 환경을 다루는 Platform class(참조)에 대해서 간단하게 알아봅니다. darttutorial-26-02.dart 프로그램을 통해서 가장 기초적인 부분들을 이해합니다.

// darttutorial-26-02.dart
// Reference: https://dart.dev/articles/libraries/dart-io

import 'dart:io';
import 'dart:convert';

Future<void> main() async {
  // #1 Get the operating system as a string.
  String os = Platform.operatingSystem;
  print("> OS: $os");
  
  // #2 Get the URI & Path of the script being run.
  var uri = Platform.script;
  var path = uri.toFilePath();
  print("> Source File Name: $path");

  // #3 Read and print the source code of THIS program
  var file = File(Platform.script.toFilePath());
  print("> Source File Contents: [start] \n");
  print("${await (file.readAsString(encoding: ascii))}\n");
  print("> Source File Contents: [end] \n");
}

프로그램을 살펴보면, 먼저 dart:io를 import 합니다. 이는 Platform, File, Directory class를 활용하기 위함입니다. dart:convet를 import한 이유는 ascii 코드로의 인코딩을 위함 입니다. 프로그램은 총3가지 부분으로 나눌수 있습니다.

#1은 Platform 클래스 객체를 통해서 프로그램이 동작하는 컴퓨터에 대한 정보를 획득합니다. 그리고 이중 운영체제의 이름을 알려주는 operatingSystem property를 통해서 운영체제 정보를 획득하고, 화면에 출력합니다.

#2는 Platform 클래스 객체의 script property는 현재 수행중인 프로그램의 위치를 URI 형태로 표시합니다. 이는 인터넷을 통해서 접근하기 위해서 추가정보가 포함된 것으로, 컴퓨터에서 다루기 위한 정보만 추출하는 작업을 위하여, URI를 화일 경로(File Path)로 변환하는 작업을 uri.toFilePath()로 수행합니다.

#3에서는 실행화일의 소스프로그램인 darttutorial-26-02.dart와 이의 위치 정보가 추가된 Platform.script.toFilePath()를 File() 클래스의 constructor에 입력 파라메타로 주어서 File 클래스의 객체를 만들었습니다. 이 객체는 이제 해당 소스코드와 1:1로 매핑되게 되었습니다. 이후 이 화일의 내용을 문자열로 읽어들이는 멤버 메소드인 readAsString() 수행하게 됩니다. 이때 읽어드리는 방식을 ASCII 코드 방식을 지정하여, 화면에 출력할 때에도 문제가 없도록 하였습니다. readAsString() 메소드는 비동기 방식으로 동작하여, 읽어드리는 동안에도 다른 일을 수행할 수 있도록 합니다. 따라서, await 구문을 통해서 비동기적인 작업이 가능하도록 하고, 이의 결과가 리턴되면, 결과를 화면에 출력합니다.

darttutorial-26-02.dart 프로그램의 수행 결과가 아래와 같이 나타나 있습니다. 이해한 부분과 같게 동작하는지 천천히 살펴보기 바랍니다.

> OS: macos
> Source File Name: /Users/drsungwon/OneDrive/Programming/hellodart/darttutorial-26/darttutorial-26-02.dart
> Source File Contents: [start] 

// darttutorial-26-02.dart
// Reference: https://dart.dev/articles/libraries/dart-io

import 'dart:io';
import 'dart:convert';

Future<void> main() async {
  // #1 Get the operating system as a string.
  String os = Platform.operatingSystem;
  print("> OS: $os");
  
  // #2 Get the URI & Path of the script being run.
  var uri = Platform.script;
  var path = uri.toFilePath();
  print("> Source File Name: $path");

  // #3 Read and print the source code of THIS program
  var file = File(Platform.script.toFilePath());
  print("> Source File Contents: [start] \n");
  print("${await (file.readAsString(encoding: ascii))}\n");
  print("> Source File Contents: [end] \n");
}

> Source File Contents: [end] 

File Random Access in dart:io Library

Random access란 프로그래밍 언어에서, 화일의 특정 위치 들을 찾아 다니면서 원하는 지점에 원하는 정보를 저장, 삭제 혹은 읽어 내는 작업을 의미합니다. darttutorial-26-03.dart는 darttutorial-26-02.dart를 random access 모드로 바꾸어서, 앞으로 화일을 다룰때 어떻게 다뤄야 하는지의 간단한 형태를 보여줍니다.

[그림 3] darttutorial-26-03.dart 소스 프로그램

darttutorial-26-02.dart 보다 복잡하다고 생각할 수 있지만, 천천히 읽어 보면 많이 다르지 않습니다. 일단 7/8번 줄은 소스 프로그램의 줄바꿈을 인식하기 위한 용도입니다. ‘;’.codeUnitAt(0);과 같이 하여서, 문자열의 0번째 위치 문자의 UTF-16 코드로 변환했으니, 쉽게 말하면, 세미콜론(;)의 UTF-16 코드를 얻은 것 입니다. 마찬가지로 ‘}’를 UTF-16 코드로 변환했습니다. Dart 언어가 UTF-16을 기본 코드로 사용하기 때문입니다. 9번 줄은 화일에서 한글자씩 읽어 들여서 한줄을 만들기 위한 정보를 저장하는 용도의 리스트 입니다. 12번 줄은 앞서와 동일하며, 13번에서 random access를 위한 방식으로 open 메소드를 실행하였고, 읽기 전용인 FileMode.read로 연 것을 볼 수 있습니다. 그런데, 이 경우 화일을 여는 작업은 I/O작업으로 시간이 걸릴수 있으니, await로 비동기 모드 작업을 할 것을 볼 수 있습니다. 이후 while 반복문을 통해서 file.readByte()를 통해서 화일에서 한글자씩 읽어 들입니다. 이후 조건문에서 -1인지 비교하는 구문은 화일의 끝까지 읽었다는 의미입니다. file.readByte()는 화일의 끝까지 가면 -1을 리턴 합니다. 이 경우는 file.close()를 통해서 화일을 닫습니다. open과 마찬가지로 I/O 작업을 위한 비동기 모드로 동작하는 await 구문을 사용 하였습니다. 화일의끝 부분이 아닌 경우는 추후 출력을 위하여 리스트에 읽은 글자를 저장합니다. 그리곤 줄의 끝까지 온 것인지를 확인하여, 줄의 끝이면 만든 줄을 출력하고 다시 다음 줄을 처리하기 위하여, 리스트를 초기화 합니다.

프로그램의 수행 결과는 앞서 darttutorial-26-02.dart 와 별반 다르지 않기에 추가로 본 글에 포함하지는 않았습니다.

File Stream in dart:io Library

Stream(참조)은 비동기적이면서 순차적인 데이타들을 다루는 프로그래밍 기법입니다. 말이 어려울 수 있는데, 키보드를 계속 타이핑하는 경우를 생각해 봅니다. 키보드를 꾸준하게 타이핑하면 글자들이 끊임 없이 컴퓨터 안으로 향해서 들어갑니다. 마치 물줄기 처럼 정보가 주르륵 흘러서 들어가는 이런 데이타의 흐름을 Stream 이라고 합니다. 키보드와 같이 사용자와의 상호작용에서 발생하는 이벤트 들이 여기에 해당하며, 컴퓨터 화일도 Stream을 통해서 처리하는 경우가 일반 적입니다. 이경우 우리는 await for 라는 새로운 반복문도 만나게 됩니다. 미리 설명하면, 비동기적인 작업이 아니라면 for 구문만으로 충분하기만, 반복문 안에서 Stream과 같이 비동기적으로 발생하는 정보를 (기다리면서) 가져와야 한다면, “비공기적 작업을 위한 for” 구문이라는 의미에서 await for 구문을 사용하게 됩니다.

darttutorial-26-03.dart 프로그램을 Stream 모드로 다시 작성한 프로그램이 darttutorial-26-04.dart에 나타나 있습니다.

[그림 4] darttutorial-26-04.dart 소스 프로그램

darttutorial-26-03.dart 보다 조금 단출해진 코드를 볼 수 있습니다. 달라진 부분 중심으로 설명하면, 일단 화일을 여는 부분인 12번 줄 입니다. 화일을 열어서, List<int> 들로 (한 줄씩) 이루어진 Stream 클래스의 객체인 stream으로 리턴해 줍니다. 화일을 정수 코드들로 이루어진 줄들로 정의한 것이지요. 다음으로 stream으로 명명한 화일에서 한줄씩 읽어 들이는 코드는 15번 중입니다. var data in stream을 통해서 한줄씩 읽은 정보가 data에 저장됩니다. 만약 stream에서 더이상 읽을 부분이 없으면 for 반복문은 동작하지 않습니다. 그런데, Stream은 앞서 설명한 것처럼 비동기 모드로 동작하므로, 기존 for 반복문 처럼, 이미 준비된 데이타를 처리하는 방법 대신 await 구문을 for 구문앞에 추가한 await for 구문을 써여 합니다. 따라서 반복문 안에서는 별도의 await 구문은 없습니다. 한줄씩 읽어 들이기에, 앞서 프로그램에서의 한 글자 단위 코드를 재사용하기 위하여 다시 한번 한줄을 글자들로 바꾸는 for (int i = 0; i < data.length; i++) { .. } 구문이 나타납니다. 한줄의 길이가 data.length property에 저장되었으니, 한줄에서 한글자씩 꺼내서 처리하는 셈입니다.

프로그램의 수행 결과는 앞서 darttutorial-26-02.dart 와 별반 다르지 않기에 추가로 본 글에 포함하지는 않았습니다.

Processes in dart:io Library

지금까지 함수를 비동기 모드로 동작시키는 내용에 대해서 살펴 보았습니다. Dart의 Process(프로세스) 클래스는 “프로그램”을 수행하는 용도로 사용합니다. 핵심 메소드는 run과 start 입니다. run 메소드는 프로그램의 수행중에 사용자(혹은 프로세스)와의 인터액션이 없는 경우를 의미하며, start의 경우는 “시작”이라는 의미처럼, 프로그램의 수행을 시작하되, 사용자(혹은 프로세스)와의 인터액션을 포함하겠다는 의미입니다 (참조).

start 메소드는 주어진 입력 파라메타의 프로그램을 수행하며, 리턴 값이 Future<Process> 타입입니다. 이는 성공적으로 프로그램이 수행되었다는 의미로 리턴됩니다. 따라서, 리턴된 프로세스 객체를 통해서 프로세스와의 인터액션을 수행합니다. 만약 입력 파라메타로 주어진 프로그램의 수행에 에러가 발생하면 exception이 발생합니다 (참조).

run 메소드는 앞서 설명처럼 프로그램이 수행되어, 인터액션 없이 결과만 취하면 됩니다. 따라서 리컨 타입이 Future<ProcessResult>로 되며, 이는 프로그램의 종료에 따른 exit code, 혹은 stdin/stdout의 형태로 주어 집니다.

run 메소드를 사용한 간단한 예제 프로그램이 darttutorial-26-05.dart에 나타나 있습니다. 프로그램은 간단합니다. 본문이 2줄 밖에는 안됩니다. Process.run(‘ls’, [‘-l’]); 구문은 Unix/Linux 명령(프로그램)인 ls를 -l 옵션을 주어서 실행하는 것으로서, 인터액션 없이 결과만 취하면 되므로, Process 클래스의 run 메소드를 사용합니다. 비동기식 모드로 동작을 해야 하므로, await 구문을 사용하여 제대로된 결과가 리컨되기를 기다린후, 결과를 results에 저장합니다.

// darttutorial-26-05.dart
// Reference: https://dart.dev/articles/libraries/dart-io

import 'dart:io';

Future<void> main() async {
  // List all files in the current directory,
  // in UNIX-like operating systems.
  ProcessResult results = await Process.run('ls', ['-l']);
  print(results.stdout);
}

print 구문을 통해서 결과를 화면에 출력했습니다. ls는 현재 디렉토리에 있는 화일의 리스트를 확인하는 명령이므로, 본 글에서 사용한 예제 프로그램들의 이름이 순차적으로 나타남을 볼 수 있습니다.

total 40
-rw-r--r--  1 drsungwon  staff  200 Feb 12 13:11 darttutorial-26-01.dart
-rw-r--r--  1 drsungwon  staff  675 Feb 12 13:58 darttutorial-26-02.dart
-rw-r--r--  1 drsungwon  staff  841 Feb 12 15:01 darttutorial-26-03.dart
-rw-r--r--  1 drsungwon  staff  682 Feb 12 15:14 darttutorial-26-04.dart
-rw-r--r--  1 drsungwon  staff  301 Feb 12 15:50 darttutorial-26-05.dart

darttutorial-26-05.dart 프로그램을 Process.start()로 수행한 프로그램 예제가 Dart 공식 홈페이지에 다음과 같이 나타나 있습니다. 공부 삼아 한줄 한줄 이해를 해보기 바랍니다.

import 'dart:convert';
import 'dart:io';

Future<void> main() async {
  final process = await Process.start('ls', ['-l']);
  var lineStream = 
    process.stdout.transform(Utf8Decoder()).transform(LineSplitter());
  await for (var line in lineStream) {
    print(line);
  }

  await process.stderr.drain();
  print('exit code: ${await process.exitCode}');
}

An introduction to the dart:io library에는 Process.start()를 사용하는 다음의 예제가 있습니다. ls 명령의 결과를 저장할 File 객체인 output이 있고, Process.start()로 ls 프로그램을 수행하는 것을 볼 수 있습니다. 새롭게 등장한 메소드는 Future 클래스의 wait 메소드 입니다. 이 메소드는 비동기로 동작할 기능들이 모두 마쳐지기를 기다린 후, 이들의 결과를 모아서 다시 리턴 합니다. 리컨 되는 결과를 리스트의 형태로 되며, 이러한 이유로, 아래의 예제를 보면 마지막 줄에 process.exitCode의 결과를 출력하기 위해서, [2]의 인덱스를 취하는 모습을 볼 수 있습니다. 따라서, 아래의 프로그램에서 가장 중요한 부분은 리스트로 이루어진 작업인, 1) process의 stdout 쪽으로 나갈 결과를 pipe 메소드를 통해서 (방향을 바꾸어) output.txt 화일로 저장하기 (참조), 2) process의 stderr(standard error)를 통해서 에러가 도출 된다면, 이를 비우는 작업하기 (참조), 3) 마지막으로 process 종료후 exitCode를 가져오기 (참조), 이렇게 세가지 작업을 비동기적으로 독립적인 수행을 합니다. 이의 작업을 마치면, 리턴 받은 결과들의 리스트에서 exitCode에 해당 하는 값을 [2] 인덱스로 접근하여 화면에 출력하고 종료하게 됩니다.

import 'dart:io';

Future<void> main() async {
  final output = File('output.txt').openWrite();
  Process process = await Process.start('ls', ['-l']);

  // Wait for the process to finish; get the exit code.
  final exitCode = (await Future.wait([
    process.stdout.pipe(output), // Send stdout to file.
    process.stderr.drain(), // Discard stderr.
    process.exitCode
  ]))[2];

  print('exit code: $exitCode');
}

Future 클래스의 wait 메소드를 좀 더 쉽고 이해하기 편하게 만든 예제를 darttutorial-26-06.dart로 나타내었습니다. 이는 https://alvinalexander.com/dart/how-run-multiple-dart-futures-in-parallel 사이트에 있는 프로그램을 그대로 참조하였습니다.

// darttutorial-26-06.dart
// Reference: https://alvinalexander.com/dart/how-run-multiple-dart-futures-in-parallel

import 'dart:async';

Future<int> async1() async {
    await Future<String>.delayed(const Duration(seconds: 1));
    return 10;
}

Future<int> async2() async {
    await Future<String>.delayed(const Duration(seconds: 2));
    return 20;
}

Future<int> async3() async {
    await Future<String>.delayed(const Duration(seconds: 3));
    return 30;
}

void main() {  //<- 'async' is not necessary here
    var t1 = DateTime.now();
    Future.wait([async1(), async2(), async3()])
          .then((List<int> nums) {
              var t2 = DateTime.now();
              var sum = nums.reduce((curr, next) => curr + next);
              print('sum = $sum');
              print('delta = ${t2.difference(t1)}');  
              // should be 3, not 6
          });  
}

프로그램은 3개의 비동기 함수를 wait 메소드로 수행합니다. 각각은 1/2/3초의 지연을 준 후 각각 정의한 10/20/30을 리턴하는 매우 단순한 함수들 입니다. wait 함수로 이들을 독립적이고 동시에 수행한 후, 최대값인 3초 지연이 지나면, 리턴 값을 모두 더한 60을 출력하도록 만들어진 프로그램입니다. 특별히 Future.wait()의 결과인 리스트에 “.” 연산자를 통해서 then 구문을 써서, 리턴된 리스트에 anonymous 함수를 써서 시간 계간과 결과의 총합을 구하는 것을 볼 수 있습니다.

마무리

Dart 언어의 Built-in library에 대해서 설명을 하였습니다. 특별히 자주 사용하게될 File과 Directory를 설명하였고, 컴퓨터의 환경 정보를 접근하는 Platform에 대해서도 다뤘습니다. 그리고 비동기 모드가 Dart의 Built-in library에서 어떻게 쓰이는지를 살펴보았고, 앞으로 매우 자주 만나게될 Stream에 대해서도 알아보았습니다.

Creative Commons License (CC BY-NC-ND)

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다