[FlutterWeb] #2 플러터에서 자바스크립트 라이브러리 사용하기steemCreated with Sketch.

in hive-138689 •  2 years ago 

플러터 웹 개발 시리즈 2번째.
[FlutterWeb] #1 플러터 웹앱 기록 시작

플러터 웹 프로젝트 생성 및 firebase 연결하는 부분은 영어로 별도로 작성하였다. 이것을 참고.
[FlutterWeb] #1 How to create a new flutter project with Firebase

이번에 설명할 내용은 매우 중요하다. 플러터에서 자바스크립트 라이브러리를 사용하는 방법을 소개한다.

플러터 웹앱

플러터 프로젝트는 Dart라는 언어로 개발하고 이것을 웹앱으로 서비스하기 위해서는 자바스크립트로 빌드해야 한다. 결국 플러터로 웹앱을 만들면 Dart 코드가 바로 실행되는 것이 아니라, 자바스크립트 코드가 실행되는 것이다. 따라서, 아무리 잘해서 자바스크립트보다 빠르게 할 수가 없다. 나중에 WebAssembly(WASM)을 적용하는 방법을 소개할 기회가 있겟지만, wasm을 일부 적용해서 보다 빠른 코드 실행이 가능하기도 하다.

그렇지만, 근본적으로 플러터 웹앱은 Dart로 개발하고 자바스크립트로 빌드하기 때문에, 자바스크립트 이상의 속도 향상은 불가능하다. 이점을 알고 프로젝트를 개발해야 한다.

또하나 중요한 것은, 플러터 웹은 Dart로 개발하기 때문에, 자바스크립트 코드를 바로 사용할 수가 없는 것이다. 수 많은 자바스크립트 라이브러리 및 코드가 있는데, 이것들을 직접 사용할 수 없는 것은 단점이다. 그러나 Flutter팀, Dart팀에서 자바스크립트를 연결해서 사용할 수 있도록 했다. 일명 JS Interoperability다.

이번 글에서는 바로 이 방법에 대해서 알아본다. remarkable이라는 마크다운을 html로 바꿔주는 자바스크립트로 개발된 라이브러리를 사용하는 방법을 소개한다.

플러터에서 자바스크립트 연결하는 방법을 찾으면 다음과 같은 방법이 검색되는데, 이 방법은 제대로 동작하지 않는다.
https://codeburst.io/how-to-use-javascript-libraries-in-your-dart-applications-e44668b8595d

그럼, 실제 동작하는 방법을 차례대로 알아보자.
이 방법은 다음을 참고로 하여 구현하였다.
Using JavaScript in Flutter Web

1. 자바스크립트 파일 준비

사용하고자 하는 자바스크립트 파일을 준비한다.
대부분의 자바스크립트 라이브러리는 npm에 등록되어 있고, minified 자바스크립트 파일을 다운로드 받을 수 있다.
remarkable의 경우는 다음 링크에서 다운로드 가능하다.
https://www.jsdelivr.com/package/npm/remarkable?path=dist
https://cdn.jsdelivr.net/npm/[email protected]/dist/remarkable.min.js

이 파일을 다운로드 또는 'remarkable.js'라는 이름으로 저장한다.

다운로드 받지 않고, 소스코드에서 직접 생성하는 것도 가능하다. 아래 소스를 다운로드 받는다.
https://github.com/jonschlinkert/remarkable
이 소스 코드를 npm build하면 dist 폴더 밑에 minified 자바스크립트 파일이 만들어진다. 이것을 사용해도 된다.

2. Require.js 파일 준비

위의 remarkable.js 파일을 플러터 웹에 로드하기 위해서는 'require.js'이 필요하다. 따라서 이 파일을 다음 링크에서 다운로드 받는다.
https://requirejs.org/docs/release/2.3.6/minified/require.js

3. 폴더 구조 및 main.js 파일 생성

이제 필요한 파일들은 모두 준비가 되었다. 다운로드 받은 자바스크립트 파일을 로드하기 위해 다음과 같이 폴더 구조를 만든다.


플러터 웹 프로젝트의 루트 폴더를 보면 web이라는 폴더가 있다. 여기에 js/scripts 라는 폴더를 만든다.
scripts 폴더에 remarkable.js 파일을 복사해서 넣는다. 그 다음 js 폴더에 main.js 파일을 아래처럼 생성한다.

define(function (require) {
  window.remarkable = require("./scripts/remarkable");
});

4. web폴더의 index.html 수정

프로젝트 루트의 web 폴더에 있는 index.html을 다음과 같이 수정하여 remarkable.js를 로드하도록 한다.

<script src="main.dart.js" type="application/javascript"></script>
  <script src="js/require.js"></script>
  <script>
    require(["js/main"]);
  </script>

5. 플러터 코드와 연결

이제 자바스크립트 라이브러리 파일이 로드되었기 때문에, 플러터 코드와 연결시키는 작업이 필요하다.
이를 위해 'js'라는 Dart 패키지가 필요하다.
https://pub.dev/packages/js
현재 아래와 같이 firebase의 버전 충돌 문제로 최신 버전을 사용할 수 없다. 0.6.4 버전까지 사용 가능하다.

이 패키지는 fiirebase버전과 충돌이슈가 있기 때문에 다음과 같이 버전을 맞춘다. (향후 버전이 업데이트 될 수 있다.)
아래와 같이 pubspec.yaml에 의존 패키지를 추가한다.

## pubspect.yaml

dependencies:
  # firebase 
  firebase_core: ^2.4.1
  firebase_auth: ^4.2.5
  cloud_firestore: ^4.3.1
  firebase_messaging: "^14.2.1"
  cloud_functions: "^4.0.7"

  # js
  js: ^0.6.4

FlutterFire패키지 버전은 다음 사이트에서 확인할 수 있다.
https://firebase.flutter.dev/

이제 다음과 같은 폴더 구조를 만들고, remarkable.dart 파일을 생성하여 내용을 입력한다.

프로젝트 루프 폴더 밑에 lib 폴더가 있는데, 여기에 js라는 폴더를 만들고, 자바스크립트 라이브러리와 인터페이스하기 위한 remarkable.dart 파일을 만든다. 참고로, lib 폴더 밑에 소스 코드를 관리하기 위한 src 폴더를 만들었다.

@JS('remarkable')
library remarkable;

import 'package:js/js.dart';

@JS('Remarkable')
class Remarkable {
  external Remarkable(RenderOptions options);
  external String highlight(String str, String lang);
  external String render(String string);
}

@anonymous
@JS()
abstract class RenderOptions {
  external bool get html;
  external bool get xthmOut;
  external bool get breaks;
  external String get langPrefix;
  external bool get typographer;
  external String get quotes;
  external bool get linkify;
  external factory RenderOptions({
    bool html,
    bool xthmOut,
    bool breaks,
    String langPrefix,
    bool typographer,
    String quotes,
    bool linkify,
  });
}

여기서 @JS('remarkable')에 입력하는 이름이 중요하다. 이것이 네임스페이스 이름을 뜻하기 때문이다.
이 코드 이후에 오는 것들은 이 네임스페이스에 속하게 된다.

이 파일을 생성하는 방법은 각 자바스크립트 라이브러리의 구성을 따르면 된다.
remarkable의 github 페이지에 보면 다음과 같이 Remarkable 클래스가 정의되어 있다.

// Actual default values
var md = new Remarkable({
  html:         false,        // Enable HTML tags in source
  xhtmlOut:     false,        // Use '/' to close single tags (<br />)
  breaks:       false,        // Convert '\n' in paragraphs into <br>
  langPrefix:   'language-',  // CSS language prefix for fenced blocks

  // Enable some language-neutral replacement + quotes beautification
  typographer:  false,

  // Double + single quotes replacement pairs, when typographer enabled,
  // and smartquotes on. Set doubles to '«»' for Russian, '„“' for German.
  quotes: '“”‘’',

  // Highlighter function. Should return escaped HTML,
  // or '' if the source string is not changed
  highlight: function (/*str, lang*/) { return ''; }
});

위 경우를 참고하면 다른 자바스크립트 라이브러리를 연결하는 것도 어렵지 않게 할 수 있다.

6. 자바스크립트 라이브러리 사용

이제 모든 준비가 완료되었다. 이제 사용해보자.

자바스크립트 라이브러리가 필요한 곳에 다음과 같이 코딩한다.

import '../../js/remarkable.dart';

var remarkable = Remarkable(RenderOptions(
  breaks: true,
  html: true,
  typographer: false,
));

...

// markdownBody를 html로 변환

output = remarkable.render(markdownBody);

Remarkable 클래스에는 render라는 함수가 정의되어 있다. 마크다운을 html로 변환하는 함수다.
위 예처럼 마크다운 텍스트를 Remarkable 라이브러리를 사용해서 html로 변환할 수 있다.

정리

플러터 웹 프로젝트에서 자바스크립트 라이브러리를 로드하고 플러터 웹앱에서 사용하는 실전 예시를 보였다. 다양한 자바스크립트 라이브러리를 위 방법처럼 자유롭게 사용하는 것이 가능하다. 플러터 패키지에 없는 것들을 새로 만들려고 하지 않고, 위 방법처럼 사용하자. You don't have to reinvent the wheel!

Please vote for me as a witness and Resteem this post

Thank you everyone for voting.
https://steemitwallet.com/~witnesses
image.png

@steemcurator01, Thank you for Your Support



Posted through the AVLE Dapp (https://avle.io)

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Thank you, friend!
I'm @steem.history, who is steem witness.
Thank you for witnessvoting for me.
image.png
please click it!
image.png
(Go to https://steemit.com/~witnesses and type fbslo at the bottom of the page)

The weight is reduced because of the lack of Voting Power. If you vote for me as a witness, you can get my little vote.

화이팅입니다