[Flutter 교육]
Flutter 웹 앱을 React에 임베드하기: 단계별 가이드
이 가이드에서는 Flutter로 만든 웹 애플리케이션을 React 애플리케이션에 iframe
없이 직접 임베드하는 방법을 개념 단계부터 상세히 설명합니다. 모든 코드를 제공하며, 초보자도 이해할 수 있도록 각 단계마다 자세한 설명을 포함합니다.
목차
- 소개
- 필요한 도구 및 사전 준비
- 3단계: React 애플리케이션 만들기
- React란 무엇인가?
- 새 React 프로젝트 생성
- 4단계: Flutter 웹 앱을 React에 통합
- Flutter 빌드 결과물 복사
- React에서 Flutter 앱 로드
- Flutter 앱을 React 컴포넌트로 래핑
- 5단계: React와 Flutter 간의 상호 작용
- Flutter에서 JavaScript 함수 호출
- React에서 Flutter로 데이터 전달
- 결론
- 추가 자료
소개
이 가이드는 Flutter로 만든 웹 애플리케이션을 React 애플리케이션에 iframe
없이 직접 임베드하는 방법을 다룹니다. 이 방법은 성능 향상과 더 나은 사용자 경험을 제공하며, React와 Flutter 간의 상호 작용도 용이합니다.
필요한 도구 및 사전 준비
이 가이드를 따라하기 위해서는 다음이 필요합니다:
- Flutter SDK: Flutter 애플리케이션을 만들고 빌드하기 위해 필요합니다.
- Node.js 및 npm: React 애플리케이션을 생성하고 실행하기 위해 필요합니다.
- 텍스트 에디터 또는 IDE: Visual Studio Code, Android Studio 등
- 터미널 또는 명령 프롬프트: 명령어를 실행하기 위해 필요합니다.
Flutter 설치 확인
Flutter SDK가 이미 설치되어 있는지 확인하려면 터미널에서 다음 명령어를 실행합니다:
flutter --version
Flutter 버전 정보가 출력되면 설치가 완료된 것입니다. 설치되지 않았다면 Flutter 공식 설치 가이드를 참고하여 설치하세요.
Node.js 및 npm 설치 확인
Node.js와 npm이 설치되어 있는지 확인하려면 터미널에서 다음 명령어를 실행합니다:
node -v
npm -v
버전 정보가 출력되면 설치가 완료된 것입니다. 설치되지 않았다면 Node.js 공식 사이트에서 다운로드하여 설치하세요.
1단계: Flutter 웹 애플리케이션 만들기
Flutter란 무엇인가?
Flutter는 모바일, 웹, 데스크톱 및 임베디드 플랫폼용으로 아름답고 빠른 앱을 만들 수 있는 오픈 소스 UI 소프트웨어 개발 키트입니다. 하나의 코드베이스로 여러 플랫폼에서 동작하는 애플리케이션을 만들 수 있습니다.
Flutter 웹 지원 활성화
Flutter SDK는 기본적으로 웹 지원을 포함합니다. 활성화되어 있는지 확인하려면 다음 명령어를 실행합니다:
flutter devices
출력 결과에 Chrome (web)
또는 Web Server (web)
가 포함되어 있다면 웹 지원이 활성화된 것입니다.
웹 지원을 활성화하려면 다음 명령어를 실행합니다:
flutter config --enable-web
새 Flutter 프로젝트 생성
Flutter 프로젝트를 생성하려면 다음 명령어를 실행합니다:
flutter create my_flutter_app
my_flutter_app
은 프로젝트 이름이며, 원하는 이름으로 변경 가능합니다.
프로젝트 디렉토리로 이동
cd my_flutter_app
간단한 Flutter 앱 작성
lib/main.dart
파일을 열어 기본 코드를 확인합니다. 기본적으로 Flutter는 Counter
앱을 생성합니다. 이 앱은 버튼을 눌러 숫자를 증가시키는 간단한 애플리케이션입니다.
원한다면 앱을 간단하게 수정해봅시다. 예를 들어, "Hello, Flutter Web!"을 표시하도록 수정합니다.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Web Demo',
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Web in React'),
),
body: Center(
child: Text(
'Hello, Flutter Web!',
style: TextStyle(fontSize: 24),
),
),
));
}
}
이렇게 하면 앱은 중앙에 "Hello, Flutter Web!"이라는 텍스트를 표시하게 됩니다.
2단계: Flutter 웹 애플리케이션 빌드
Flutter 애플리케이션을 웹용으로 빌드해야 합니다.
웹용으로 앱 빌드
터미널에서 다음 명령어를 실행합니다:
flutter build web
이 명령어는 build/web
디렉토리에 웹 애플리케이션을 빌드합니다.
빌드 결과물 확인
build/web
디렉토리에는 다음과 같은 파일들이 포함되어 있습니다:
index.html
main.dart.js
flutter.js
assets/
디렉토리
이제 이 빌드된 웹 애플리케이션을 React 애플리케이션에 통합할 준비가 되었습니다.
3단계: React 애플리케이션 만들기
React란 무엇인가?
React는 사용자 인터페이스를 구축하기 위한 JavaScript 라이브러리입니다. 컴포넌트 기반의 접근 방식을 사용하여 복잡한 UI를 쉽게 만들 수 있습니다.
새 React 프로젝트 생성
React 애플리케이션을 생성하기 위해 create-react-app
을 사용할 수 있습니다.
터미널에서 원하는 작업 디렉토리로 이동한 후 다음 명령어를 실행합니다:
npx create-react-app my_react_app
my_react_app
은 프로젝트 이름이며, 원하는 이름으로 변경 가능합니다.
프로젝트 디렉토리로 이동
cd my_react_app
4단계: Flutter 웹 앱을 React에 통합
Flutter 웹 애플리케이션의 빌드 결과물을 React 애플리케이션에 통합합니다.
Flutter 빌드 결과물 복사
Flutter 애플리케이션의 빌드 결과물(build/web
디렉토리)을 React 애플리케이션의 public
디렉토리 내에 복사합니다.
flutter_app
폴더 생성
React 애플리케이션의 public
디렉토리 내에 flutter_app
폴더를 생성합니다.
mkdir public/flutter_app
빌드 결과물 복사
Flutter 프로젝트의 build/web
디렉토리의 모든 파일을 public/flutter_app
디렉토리에 복사합니다.
cp -r ../my_flutter_app/build/web/* public/flutter_app/
경로는 Flutter 프로젝트와 React 프로젝트의 상대적인 위치에 따라 조정해야 합니다.
React에서 Flutter 앱 로드
이제 React 애플리케이션에서 Flutter 앱을 로드할 수 있습니다.
Flutter 앱을 React 컴포넌트로 래핑
Flutter 애플리케이션을 로드하고 렌더링하기 위한 React 컴포넌트를 생성합니다.
FlutterApp.js
파일 생성
src
디렉토리 내에 FlutterApp.js
파일을 생성합니다.
touch src/FlutterApp.js
FlutterApp.js
내용 작성
// src/FlutterApp.js
import React, { useEffect } from 'react';
function FlutterApp() {
useEffect(() => {
// flutter.js 로드
const script = document.createElement('script');
script.src = `${process.env.PUBLIC_URL}/flutter_app/flutter.js`;
script.onload = () => {
// Flutter 앱 실행
if (window.flutterWebRenderer) {
// 이미 로드된 경우 무시
return;
}
window.flutterWebRenderer = 'html'; // 또는 'canvaskit' 사용 가능
window.addEventListener('flutter-first-frame', () => {
console.log('Flutter 앱이 로드되었습니다.');
});
window.flutterConfiguration = {
assetBase: `${process.env.PUBLIC_URL}/flutter_app/`,
};
const script2 = document.createElement('script');
script2.src = `${process.env.PUBLIC_URL}/flutter_app/main.dart.js`;
document.body.appendChild(script2);
};
document.body.appendChild(script);
}, []);
return (
<div>
<h2>Flutter 앱이 로드됩니다...</h2>
<div id="flutter-app"></div>
</div>
);
}
export default FlutterApp;
코드 설명
useEffect
훅을 사용하여 컴포넌트가 마운트될 때 Flutter 애플리케이션을 로드합니다.
flutter.js
스크립트를 동적으로 로드합니다.
flutter.js
로드가 완료되면 main.dart.js
를 로드하여 Flutter 애플리케이션을 실행합니다.
window.flutterConfiguration
객체를 설정하여 Flutter 애플리케이션의 자산 경로를 지정합니다.
#flutter-app
이라는 div에 Flutter 애플리케이션이 렌더링됩니다.
App.js
에서 FlutterApp
컴포넌트 사용
src/App.js
파일을 열어 FlutterApp
컴포넌트를 임포트하고 사용합니다.
// src/App.js
import React from 'react';
import FlutterApp from './FlutterApp';
function App() {
return (
<div className="App">
<h1>React와 Flutter 통합 예제</h1>
<FlutterApp />
</div>
);
}
export default App;
React 애플리케이션 실행
터미널에서 React 애플리케이션을 실행합니다.
npm start
브라우저에서 http://localhost:3000
을 열면 "Hello, Flutter Web!" 메시지가 표시된 Flutter 애플리케이션이 React 애플리케이션 내에서 렌더링된 것을 볼 수 있습니다.
5단계: React와 Flutter 간의 상호 작용
React와 Flutter 간에 데이터를 주고받으려면 JavaScript와 Dart 간의 통신을 설정해야 합니다.
Flutter에서 JavaScript 함수 호출
Flutter 애플리케이션에서 JavaScript 함수를 호출하려면 dart:js
라이브러리를 사용합니다.
Flutter 코드 수정
lib/main.dart
파일을 수정하여 JavaScript 함수를 호출하는 버튼을 추가합니다.
import 'package:flutter/material.dart';
import 'dart:js' as js;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
void _callJavaScriptFunction() {
js.context.callMethod('onFlutterMessage', ['Hello from Flutter!']);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Web Demo',
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Web in React'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Hello, Flutter Web!',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _callJavaScriptFunction,
child: Text('Call JavaScript Function'),
),
],
),
),
));
}
}
코드 설명
dart:js
라이브러리를 임포트합니다.
_callJavaScriptFunction
메소드를 정의하여 JavaScript 함수 onFlutterMessage
를 호출합니다.
- 버튼을 추가하여 사용자가 클릭하면 JavaScript 함수를 호출합니다.
Flutter 애플리케이션 다시 빌드
Flutter 애플리케이션을 다시 빌드합니다.
flutter build web
빌드된 파일들을 다시 React 애플리케이션의 public/flutter_app
디렉토리에 복사합니다.
cp -r build/web/* ../my_react_app/public/flutter_app/
React에서 JavaScript 함수 정의
React 애플리케이션에서 Flutter에서 호출할 JavaScript 함수를 정의합니다.
FlutterApp.js
수정
FlutterApp.js
파일을 수정하여 JavaScript 함수를 정의합니다.
// src/FlutterApp.js
import React, { useEffect } from 'react';
function FlutterApp() {
useEffect(() => {
// JavaScript 함수 정의
window.onFlutterMessage = function (message) {
alert('Flutter로부터 메시지: ' + message);
};
// flutter.js 로드
const script = document.createElement('script');
script.src = `${process.env.PUBLIC_URL}/flutter_app/flutter.js`;
script.onload = () => {
// Flutter 앱 실행
if (window.flutterWebRenderer) {
// 이미 로드된 경우 무시
return;
}
window.flutterWebRenderer = 'html'; // 또는 'canvaskit' 사용 가능
window.addEventListener('flutter-first-frame', () => {
console.log('Flutter 앱이 로드되었습니다.');
});
window.flutterConfiguration = {
assetBase: `${process.env.PUBLIC_URL}/flutter_app/`,
};
const script2 = document.createElement('script');
script2.src = `${process.env.PUBLIC_URL}/flutter_app/main.dart.js`;
document.body.appendChild(script2);
};
document.body.appendChild(script);
}, []);
return (
<div>
<h2>Flutter 앱이 로드됩니다...</h2>
<div id="flutter-app"></div>
</div>
);
}
export default FlutterApp;
코드 설명
window.onFlutterMessage
함수를 정의하여 Flutter에서 메시지를 받으면 알림을 표시합니다.
- 나머지 코드는 동일합니다.
React에서 Flutter로 데이터 전달
React에서 Flutter로 데이터를 전달하려면 Flutter 애플리케이션에서 JavaScript 함수를 호출하도록 설정해야 합니다.
Flutter에서 JavaScript로부터 메시지 수신
Flutter에서 JavaScript에서 전달한 데이터를 수신하려면 js
패키지를 사용합니다.
lib/main.dart
수정
import 'package:flutter/material.dart';
import 'dart:js' as js;
void main() {
// JavaScript에서 Flutter로 메시지 전달
js.context['sendMessageToFlutter'] = (String message) {
print('React로부터 메시지: $message');
};
runApp(MyApp());
}
class MyApp extends StatelessWidget {
void _callJavaScriptFunction() {
js.context.callMethod('onFlutterMessage', ['Hello from Flutter!']);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Web Demo',
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Web in React'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Hello, Flutter Web!',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _callJavaScriptFunction,
child: Text('Call JavaScript Function'),
),
],
),
),
));
}
}
React에서 Flutter로 메시지 보내기
FlutterApp.js
에서 Flutter로 메시지를 보냅니다.
// src/FlutterApp.js
import React, { useEffect } from 'react';
function FlutterApp() {
useEffect(() => {
// JavaScript 함수 정의
window.onFlutterMessage = function (message) {
alert('Flutter로부터 메시지: ' + message);
};
// flutter.js 로드
const script = document.createElement('script');
script.src = `${process.env.PUBLIC_URL}/flutter_app/flutter.js`;
script.onload = () => {
// Flutter 앱 실행
if (window.flutterWebRenderer) {
// 이미 로드된 경우 무시
return;
}
window.flutterWebRenderer = 'html'; // 또는 'canvaskit' 사용 가능
window.addEventListener('flutter-first-frame', () => {
console.log('Flutter 앱이 로드되었습니다.');
// Flutter로 메시지 보내기
if (window.sendMessageToFlutter) {
window.sendMessageToFlutter('Hello from React!');
}
});
window.flutterConfiguration = {
assetBase: `${process.env.PUBLIC_URL}/flutter_app/`,
};
const script2 = document.createElement('script');
script2.src = `${process.env.PUBLIC_URL}/flutter_app/main.dart.js`;
document.body.appendChild(script2);
};
document.body.appendChild(script);
}, []);
return (
<div>
<h2>Flutter 앱이 로드됩니다...</h2>
<div id="flutter-app"></div>
</div>
);
}
export default FlutterApp;
이렇게 하면 Flutter 애플리케이션이 로드된 후 window.sendMessageToFlutter
함수가 정의되었을 때 메시지를 보낼 수 있습니다.
결론
이 가이드에서는 Flutter 웹 애플리케이션을 React 애플리케이션에 iframe
없이 임베드하는 방법을 자세히 알아보았습니다. 또한 React와 Flutter 간에 데이터를 주고받는 방법도 살펴보았습니다.
이 방법을 통해 Flutter의 강력한 UI 기능을 React 애플리케이션에 통합할 수 있으며, 성능 향상과 더 나은 사용자 경험을 제공할 수 있습니다.
추가 자료
주의사항:
- Flutter와 React는 서로 다른 프레임워크이므로, 통합 시 버전 호환성 및 환경 설정에 주의해야 합니다.
- Flutter 웹 애플리케이션의 자산 경로와 React 애플리케이션의 빌드 설정을 조정해야 할 수 있습니다.
- 보안상의 이유로 Cross-Origin Resource Sharing (CORS) 문제가 발생할 수 있으므로 동일한 도메인에서 호스팅하는 것이 좋습니다.
출처 : https://cheddar-sparrow-aba.notion.site/Flutter-React-13997e0a8ff3807b814dc717d3ec9fbc