Dart Programmer 되기 [42]

< Web 개발 – Dart for Web >

이 글에서 설명하는 기술은 Flutter를 사용하지 않고, Dart언어의 Core 라이브러리인 dart:html을 사용하는 방법 입니다. 이는 HTML/CSS/JavaScript의 조합에서 JavaScript에 상응하는 역할을 Dart 언어 그리고 dart:html의 코어 라이브러리 기능이 수행 한다고 보면 됩니다. 따라서, 이 글을 이해하기 위해서는 HTML/CSS/JavaScript를 기반으로 Web 어플리케이션을 만드는 기술에 대한 기본적인 이해가 필요합니다.

“Hello, World!” Dart web-only app 이해

앞서 < Web 개발 – “Hello, World!” Dart web-only app >에서 Stagehand가 자동으로 생성한 소스 코드를 살펴보도록 합니다. 먼저 index.html 입니다.

<!DOCTYPE html>

<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="scaffolded-by" content="https://github.com/dart-lang/stagehand">
    <title>dart4web</title>
    <link rel="stylesheet" href="styles.css">
    <link rel="icon" href="favicon.ico">
    <script defer src="main.dart.js"></script>
</head>

<body>

  <div id="output"></div>

</body>
</html>

head 부분은 일반적인 내용으로 채워지고 있습니다. script가 main.dart.js로 설정되어 dart 소스 프로그램이 JavaScript로 변환되어 실행된다는 것을 볼 수 있습니다. 그리고 JavaScript에서 HTML 컨텐츠를 동적으로 다룰때 사용하는 전형적인 형태로서, id를 가진 영역을 선언하였으나, 처음에는 비어 있는 것을 볼 수 있습니다. 여기서 우리가 동적으로 컨텐츠를 업데이트할 id는 “output” 입니다.

그러면, 이 “output”라는 id를 갖는 영역을 업데이트 하는 Dart 코드를 볼 차례입니다. 해당 코드는 main.dart에 정의되어 있습니다.

import 'dart:html';

void main() {
  querySelector('#output').text = 'Your Dart app is running.';
}

가장 먼저 Dart 언어의 HTML 제어 코어 라리브러리인 dart:html을 import하는 것을 볼 수 있습니다. 그리고 main()가 선언되어 있습니다. main()안에는 한줄의 코드가 있습니다. 기능은 html 화인에서 “output”을 id로 갖는 구문을 찾은후(querySelector()), 그 속에 있는 문자열을 “Your Dart app is running.”로 바꾼다는 의미입니다.

따라서 이 프로그램이 수행이 되면, 비어있는 영역에 상기 문자열을 동적으로 삽입하는 것을 볼 수 있습니다. 여기서 알수 있듯이, HTML과 JavaScript가 연결되는 프로그래밍 방식과 거의 동일한 방식으로 HTML과 Dart 소스 프로그램이 연결되어 있는 것을 볼 수 있습니다. 따라서, JavaScript에서 HTML을 제어하는 방식에 상응하는 함수들이 dart:html에서 제공이 되고 있다는 것을 예측할 있습니다.

마지막 확인인 css 화일은 styles.css 로서, 다음의 내용을 갖습니다.

@import url(https://fonts.googleapis.com/css?family=Roboto);

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  font-family: 'Roboto', sans-serif;
}

#output {
  padding: 20px;
  text-align: center;
}

CSS에 대한 기본 지식이 있다면, 특별히 어렵거나 인상적인 코드는 아니며, 일반적인 형태와 폰트에 대한 부분인 것을 알 수 있습니다.

dart:html을 통한 HTML 제어

dart:html을 사용하여 html로 표시되는 Web 컨텐츠를 동적으로 변경하는 내용에 대해서 조금 더 이해를 해 보겠습니다. 이를 위해서, main.dart의 내용을 다음과 같이 변경 합니다. 이는 Dart의 공식 사이트( https://dart.dev/tutorials/web/get-started )에 게재된 내용을 그대로 사용합니다.

import 'dart:html';

Iterable<String> thingsTodo() sync* {
  var actions = ['Walk', 'Wash', 'Feed'];
  var pets = ['cats', 'dogs'];

  for (var action in actions) {
    for (var pet in pets) {
      if (pet == 'cats' && action != 'Feed') continue;
      yield '$action the $pet';
    }
  }
}

void addTodoItem(String item) {
  print(item);

  var listElement = LIElement();
  listElement.text = item;
  todoList.children.add(listElement);
}

UListElement todoList;

void main() {
  todoList = querySelector('#todolist');
  thingsTodo().forEach(addTodoItem);
}

다음으로 index.html 화일도 body 부분을 변경한 다음의 내용으로 변경 합니다.

<!DOCTYPE html>

<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="scaffolded-by" content="https://github.com/dart-lang/stagehand">
    <title>dart4web</title>
    <link rel="stylesheet" href="styles.css">
    <link rel="icon" href="favicon.ico">
    <script defer src="main.dart.js"></script>
</head>

<body>
    <h2>A Simple To-Do List</h2>
    <p>Things to do:</p>
    <ul id="todolist">
    </ul>
</body>
</html>

먼저 index.html 화일의 body 내용을 살펴보면, 헤더(h2)로 제목을 나타냅니다. 그리고 문장(p)으로 “Things to do:”를 문자열을 화면에 출력합니다. 그리고 id를 “todolist”로 정의한 비어 있는 Unnumbered-List를 생성하는 것을 볼 수 있습니다. 앞서 Hello World 예제처럼 이 부분의 내용을 Dart 언어를 사용하여 동적으로 변경할 것 입니다. 이 프로그램을 webdev serve 명령으로 수행하고, http://localhost:8080으로 접속하면 다음과 같이 Web 컨텐츠가 채워지는 것을 볼 수 있습니다.

이렇게 화면이 채워지게된 이유를 main.dart를 통해서 설명 하겠습니다. main.dart 안에는 main()을 제외하고 두개의 함수가 있습니다.

addTodoItem() 함수는 입력 파라메타도 문자열을 하나 받습니다. 그리고 디버그 용도를 위해서 print() 함수로 화면 출력을 수행합니다. 이 출력은 Web 브라우저를 개발자 모드로 수행해서, JavaScript 프로그램의 출력이 표시되는 console 탭을 선택하면 확인 가능 합니다. 다음의 3줄이 수행해야 하는 동작인데, 먼저 비어있는 List Element를 하나 생성합니다. 그리고, 이 List Element의 text 내용을 입력 파라메타로 받은 내용으로 채우게 됩니다. 이렇게 채워진 문자열은 HTML 화일인 index.html의 body 부분인 todolist id 부분을 채우기 위한 용도로 사용되어, 함수 실행시 마다 List Element를 하나씩 추가 합니다. 이를 통해서 위의 화면 출력과 같이 4개의 Unnumbered List 4개가 나타나도록 합니다.

thingsTodo() 함수가 실질적으로 HTML에 추가되는 4개의 Unnumbered List Element를 만들어 내는 기능을 합니다. 이 함수 안에는 동작을 의미하는 문자열 3개로 이루어진 actions 리스트와 동물을 나타내는 pets 리스트가 있습니다. Nested for 구문을 통해서, 이들을 매칭하게 되며, pets가 dogs인 경우는 3가지 actions에 모두 매핑하여, “$action the $pet”의 문자열을 생성합니다. pets가 cats 인 경우는 오직 actions이 “Feed”인 경우메나 문자열을 생성합니다. 여기서 yield 구문은 return 구문과 유사하게 값을 리턴하는 문법 입니다. 차이점은 return이 한번에 하나의 값을 전달하고 마친다면, yield 구문은 generator 구문으로서, thingsTodo()의 결과 값이 필요한 구문이 실행될때 마다 그때 그때 필요한 결과 값을 만들어서 리턴하는 점에서 다릅니다. 이를 thingsTodo() 함수가 async* 구문의 비동기적인 동작을 하는 부분에서 기인 합니다.

이 두가지 함수를 이해한 상태에서 main() 함수를 보면, 이해가 용이합니다. 즉 main()의 첫번째 줄에서는 index.html에서 정의한 비어있는 영역을 선택하게 되고, 여기에 thingsTodo()가 실행되면서 만들어지는 하나 하나의 문자열을 추가하게 되는 것 입니다.

따라서, HTML/CSS/JavaScript를 혼용하여 Web 콘텐츠를 다룰수 있는 개발자라면, JavaScript 대신 Dart 언어와 dart:html 코어 라이브러리를 사용하여 Web 콘텐츠를 제어하는 것이 가능 합니다.

결론적으로 Dart 언어로 DOM을 사용하려면, JavaScript를 통한 Web 컨텐츠를 다루는 경우와 동일하게, Window, Document, Element 및 Node 에 대해 알아야합니다.

Window 객체는 웹 브라우저의 실제 윈도우를 나타냅니다. 각 Window에는 현재 로드 된 문서를 가리키는 Document 객체가 있습니다. Window 객체에는 IndexedDB (데이터 저장 용), requestAnimationFrame (애니메이션 용) 등과 같은 다양한 API에 대한 접근자가 있습니다. 탭 브라우저에서 각 탭에는 고유한 Window 객체가 있습니다.

Document 객체를 사용하면 문서 내에서 Element 객체를 만들고 조작 할 수 있습니다. Document 자체는 요소이며 조작 할 수 있습니다.

DOM은 Node 트리를 모델링 합니다. 이러한 Node는 종종 Element 이지만 attributes, test, comment 및 기타 DOM 유형일 수도 있습니다. 부모가 없는 루트 노드를 제외하고 DOM의 각 노드에는 하나의 부모가 있으며 많은 자식이 있을 수 있습니다.

마무리

이 글에서는 전통적인 Web 어플리케이션을 만드는 기술인 HTML/CSS/JavaScript의 조합을 사용하는 기술에서 JavaScript 대신 Dart를 활용하는 접근 방법인 Dart for Web 기술에 대해서 알아 보았습니다.

dart:html을 사용한 Dart for Web 기술에 대해서 좀 더 이해하고 싶다면, Dart 공식 사이트에서 “A tour of the core libraries”의 dart:html에 대한 설명인 “dart:html – browser-based apps” 부분( https://dart.dev/guides/libraries/library-tour#darthtml )을 읽고 실행해 보기를 권장합니다.

Creative Commons License (CC BY-NC-ND)

댓글 남기기

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