[플러터] 플러터 웹 앱 빌드 및 배포

빌드 및 배포

  1. 빌드 (Build)
    • 릴리즈 버전 빌드: flutter build web
      • 빌드를 수행하면 애플리케이션에 포함된 모든 리소스 파일들을 프로젝트의 /build/web 폴더에 생성한다. aassets 폴더의 파일들이 포함된다.
      • 릴리스 빌드는 개발 컴파일러 대신 dart2js를 사용하여 단일 자바스크립트 파일인 main.dart.js를 생성한다.
      • flutter run --release와 동일하다.
    • 디버그 버전 빌드: flutter run -d chrome
  2. 배포 (Release)
    • 파이어베이스 (Firebase)
      • 계정 로그인/로그아웃
        • 로그인: firebase login
        • 로그아웃: firebase logout
      • 로컬에서 테스트: firebase emulators:start
      • 라이브 배포: firebase deploy --only hosting
        • build/web 폴더에 있는 파일들을 호스팅 서버에 배포한다.


웹 렌더러 선택

웹 앱은 다음 두 렌더러를 사용하여 실행 및 빌드된다.

  • HTML 렌더러: HTML 요소, CSS, 캔버스 요소 및 SVG 요소의 조합을 사용한다. <img> 요소를 사용하여 이미지를 렌더링한다. 캔버스킷 렌더러보다 다운로드 크기가 더 작다.
  • 캔버스킷(CanvasKit) 렌더러: 플러터 모바일 및 데스크톱과 완전히 호환된다. 위젯 밀도가 높아 성능이 더 빠르지만 다운로드 크기가 약 1.5MB 추가된다. 캔버스킷은 WebGL을 사용하여 스키아(Skia) 페인트 명령을 렌더링하므로 이미지의 픽셀에 대한 액세스가 필요하다.


기본적으로 flutter buildflutter run 명령어는 웹 렌더러에 대한 자동 선택을 사용한다. 웹 앱은 모바일 브라우저에서는 HTML 렌더러로, 데스크톱 브라우저에서는 캔버스킷 렌더러로로 실행된다. 이는 각 플랫폼의 특성에 맞게 최적화하기 위해 권장되는 렌더러 조합이다.

런더러를 직접 선택하기 위해 --web-renderer 명령어를 사용한다. 명령어는 auto, html, canvaskit 세 가지 값 중 하나를 인자로 받는다.

  • auto (기본값): 사용할 렌더러를 자동으로 선택한다. 웹앱이 모바일 브라우저에서 실행되는 경우 HTML 렌더러를, 데스크톱 브라우저에서 실행되는 경우 캔버스킷 렌더러를 선택한다. 모바일 브라우저에서는 다운로드 크기에 맞게 최적화하고 데스크톱 브라우저에서는 성능에 맞게 최적화하는 경우 기본값을 사용한다.
  • html: 항상 HTML 렌더러를 사용한다. 데스크톱 및 모바일 브라우저 모두에서 성능보다 다운로드 크기를 최적화하려는 경우 HTML 렌더러를 선택하는 것이 좋다.
  • canvaskit: 항상 캔버스킷 렌더러를 사용한다. 데스크톱과 모바일 브라우저 모두에서 성능과 픽셀의 완벽한 일관성을 우선시하는 경우 캔버스킷 렌더러를 사용하는 것이 좋다.


다음과 같이 flutter build 또는 flutter run 명령어 사용 시 렌더러를 선택할 수 있다.

flutter run -d chrome --web-renderer canvaskit
flutter build web --web-renderer html


렌더러와 이미지 표시

HTML 렌더러는 <img> 요소를 사용하기 때문에 리소스 출처에 관계 없이 임의의 소스의 이미지를 표시할 수 있지만 수행할 수 있는 작업에 다음과 같은 제한이 있다.

  • Image.toByteData에 대한 지원이 제한적이다.
  • OffsetLayer.toImageScene.toImage에 대한 지원이 없다.
  • 애니메이션 이미지의 프레임 데이터에 액세스할 수 없다. Codec.getNextFrame, frameCount는 항상 1이며, repetitionCount는 항상 0이다.
  • ImageShader를 지원하지 않는다.
  • 이미지에 적용할 수 있는 셰이더 효과가 제한적으로 지원된다.
  • 이미지 메모리를 제어할 수 없다(Image.dispose는 효과가 없다). 메모리는 브라우저에서 백그라운드 상 관리된다.


반면 캔버스킷 렌더러는 플러터의 이미지 API를 완벽하게 구현한다. 그러나 이를 위해서는 이미지 픽셀에 대한 액세스가 필요하므로 CORS 정책의 적용을 받는다.


CORS

웹 앱은 단일 출처 정책(single origin policy, SOP)에 의해 교차 출처 리소스 공유(cross-origin resource sharing, CORS)(이하 CORS)가 불가능하다. CORS란 웹 애플리케이션 클라이언트가 리소스를 제공 받은 출처 외 다른 출처에서 리소스를 제한적으로 요청할 수 있도록 하는 HTTP 헤더 기반 메커니즘이다.

<image>, <picture>, <canvas> 요소를 사용할 때 브라우저가 다른 사이트에서 이미지를 가져오는 경우, CORS 정책에서 해당 사이트에 대한 데이터에 대한 접근을 허용하지 않으면 픽셀에 대한 접근이 자동으로 차단된다.

WebGL은 이미지를 렌더링하기 위해 이미지 데이터에 대한 접근 권한이 필요하다. 따라서 웹 애플리케이션이 WebGL을 사용하여 렌더링할 이미지를 제공하는 경우, 해당 이미지는 애플리케이션을 서비스하는 도메인과 작동하도록 구성된 CORS 정책이 있는 서버에서 제공되어야 한다. 즉, 웹 애플리케이션을 서비스하는 서버가 이미지 출처(교차 출처)를 허용해야 한다.


구글 맵

플러터에서 구글 맵 기능을 위해 google_maps_flutter 패키지를 사용할 수 있다. 웹 앱의 경우 web/index.html 파일을 수정하여 구글 맵 자바스크립트 SDK를 포함시켜야 한다. 웹 앱을 위한 패키지인 google_maps_flutter_webgoogle_maps_flutter 패키지 설치 시 자동으로 앱에 포함되므로 pubspec.yaml에 추가할 필요는 없다.


참고

Comments