공식 문서 : https://pub.dev/packages/webview_flutter
flutter에서 webview_flutter 라이브러리는 애플리케이션 내에서 웹 콘텐츠를 표시할 수 있도록 도와주는 공식 패키지입니다. 이를 통해 웹 페이지, 로컬 HTML 파일, 또는 웹 기반 애플리케이션을 Flutter 앱 내에 통합할 수 있습니다. **webview_flutter**는 다양한 플랫폼(안드로이드, iOS)에서 일관된 웹뷰 경험을 제공하며, 웹 페이지와의 상호작용을 가능하게 합니다.
주요 특징:
먼저, 프로젝트의 pubspec.yaml 파일에 webview_flutter 패키지를 추가해야 합니다. 최신 버전을 사용하도록 권장합니다.
ependencies:
flutter:
sdk: flutter
webview_flutter: ^4.0.7 # 최신 버전 확인 후 적용
패키지를 추가한 후, 터미널에서 다음 명령어를 실행하여 패키지를 설치합니다.
flutter pub get
안드로이드에서 웹뷰를 사용하려면 몇 가지 추가 설정이 필요합니다.
android {
defaultConfig {
applicationId "com.example.your_app"
minSdkVersion 19
targetSdkVersion 33
// 기타 설정
}
}
iOS에서도 웹뷰를 사용하려면 몇 가지 설정이 필요합니다.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
주의: NSAllowsArbitraryLoads를 true로 설정하면 모든 HTTP 요청이 허용되므로, 보안에 민감한 앱에서는 특정 도메인만 허용하도록 설정하는 것이 좋습니다.아래는 Flutter 애플리케이션 내에 웹뷰를 삽입하여 웹 페이지를 로드하는 기본 예제입니다.
main.dart:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'WebView Flutter Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const WebViewExample(),
);
}
}
class WebViewExample extends StatefulWidget {
const WebViewExample({super.key});
@override
State createState() => _WebViewExampleState();
}
class _WebViewExampleState extends State {
late final WebViewController _controller;
@override
void initState() {
super.initState();
// 초기화 시점에 WebViewController 설정
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted) // JavaScript 허용
..setBackgroundColor(const Color(0x00000000)) // 배경색 설정
..setNavigationDelegate(
NavigationDelegate(
onPageStarted: (String url) {
print('페이지 로딩 시작: $url');
},
onPageFinished: (String url) {
print('페이지 로딩 완료: $url');
},
onWebResourceError: (WebResourceError error) {
print('웹 리소스 오류: ${error.description}');
},
),
)
..loadRequest(Uri.parse('<https://flutter.dev>'));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('WebView Example'),
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: () {
_controller.reload(); // 페이지 새로고침
},
),
],
),
body: WebViewWidget(controller: _controller),
);
}
}
설명:
웹뷰 내에서 JavaScript를 실행할 수 있습니다. 예를 들어, 특정 함수를 호출하거나 웹 페이지와 상호작용할 수 있습니다.
예제: JavaScript 코드 실행
// 버튼을 눌러 JavaScript 실행
ElevatedButton(
onPressed: () {
_controller.runJavaScript('alert("Hello from Flutter!");');
},
child: const Text('JavaScript 실행'),
),
결과: 웹 페이지 내에서 "Hello from Flutter!"라는 경고창이 표시됩니다.
웹뷰의 로딩 상태를 관리하여 사용자에게 로딩 스피너 등을 표시할 수 있습니다.
예제: 로딩 인디케이터 추가
class _WebViewExampleState extends State {
late final WebViewController _controller;
bool _isLoading = true; // 로딩 상태 변수
@override
void initState() {
super.initState();
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onPageStarted: (String url) {
setState(() {
_isLoading = true;
});
},
onPageFinished: (String url) {
setState(() {
_isLoading = false;
});
},
onWebResourceError: (WebResourceError error) {
setState(() {
_isLoading = false;
});
print('웹 리소스 오류: ${error.description}');
},
),
)
..loadRequest(Uri.parse('<https://flutter.dev>'));
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('WebView Example'),
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: () {
_controller.reload();
},
),
],
),
body: Stack(
children: [
WebViewWidget(controller: _controller),
if (_isLoading)
const Center(
child: CircularProgressIndicator(),
),
],
),
);
}
}
설명:
웹뷰 내의 JavaScript와 Flutter 코드 간에 상호작용할 수 있습니다. 이를 통해 양방향 통신이 가능합니다.
예제: JavaScript에서 Flutter로 메시지 보내기
<!DOCTYPE html>
<html>
<head>
<title>Flutter WebView Communication</title>
<script type="text/javascript">
function sendMessageToFlutter() {
FlutterChannel.postMessage('Hello from JavaScript!');
}
</script>
</head>
<body>
<h1>Flutter WebView Communication</h1>
<button onclick="sendMessageToFlutter()">Send Message to Flutter</button>
</body>
</html>
설명:
웹뷰를 사용할 때 보안은 매우 중요한 요소입니다. 다음은 웹뷰 사용 시 고려해야 할 주요 보안 사항입니다:
JavaScript 실행을 완전히 허용할 경우, 악의적인 스크립트가 실행될 수 있으므로 신뢰할 수 없는 콘텐츠를 로드할 때는 주의가 필요합니다.
예시: JavaScript 실행 제한
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.disabled) // JavaScript 비활성화
..loadRequest(Uri.parse('<https://secure-website.com>'));
민감한 데이터를 다루는 경우, 항상 HTTPS를 통해 안전하게 데이터를 전송하도록 합니다.
앱 내에서 로드할 수 있는 콘텐츠의 출처를 제한하여, 신뢰할 수 없는 도메인에서의 콘텐츠 로드를 방지합니다.
예시: URL 필터링
_controller.setNavigationDelegate(
NavigationDelegate(
onNavigationRequest: (NavigationRequest request) {
if (request.url.startsWith('<https://trusted-domain.com>')) {
return NavigationDecision.navigate;
} else {
return NavigationDecision.prevent;
}
},
),
);
웹뷰 내에서 로그인 정보나 인증 토큰을 다루는 경우, 해당 정보가 안전하게 처리되도록 주의합니다.
웹뷰를 사용할 때 필요한 최소한의 권한만 부여하여 보안 위험을 줄입니다. 예를 들어, 인터넷 권한 외에 추가적인 권한이 필요하지 않다면 요청하지 않습니다.
웹뷰에서 로드하는 콘텐츠는 신뢰할 수 있는 출처에서만 로드하도록 제한합니다. 이를 통해 악의적인 스크립트 실행을 방지할 수 있습니다.
웹뷰 내에서 사용자로부터 입력받은 데이터를 처리할 때는 항상 입력을 검증하고, 필요한 경우 이스케이프 처리를 합니다.
webview_flutter 패키지와 Flutter SDK를 최신 버전으로 유지하여 보안 패치를 적용받도록 합니다.
웹뷰의 상태(로딩 상태, 오류 상태 등)를 적절히 관리하여 사용자에게 명확한 피드백을 제공합니다.
웹뷰 내에서 불필요한 리소스를 로드하지 않도록 최적화하고, 필요한 경우 캐싱을 활용하여 성능을 향상시킵니다.
[Flutter] 카메라 및 이미지 라이브러리 - ImagePicker (1) | 2024.12.19 |
---|---|
[Flutter] HTTP 통신 라이브러리 - DIO (0) | 2024.12.18 |
[Flutter] API Key나 다른 민감 정보 분리 - DOTENV (0) | 2024.12.16 |