반응형
Flutter WebView 앱 제작 완벽 가이드
1. 사전 준비
1.1 Flutter SDK 설치
- https://flutter.dev/docs/get-started/install 접속
- 운영체제에 맞는 Flutter SDK 다운로드
- 압축 해제 후 환경변수 PATH에
flutter/bin
경로 추가
1.2 개발 환경 설정
- Android Studio 설치 (Android 개발용)
- Xcode 설치 (iOS 개발용, macOS만)
- VS Code 설치 (권장 에디터)
1.3 설치 확인
터미널에서 다음 명령어 실행:
flutter doctor
2. 프로젝트 생성
2.1 새 프로젝트 만들기
flutter create webview_app
cd webview_app
2.2 WebView 플러그인 추가
pubspec.yaml
파일을 열고 dependencies 섹션에 추가:
dependencies:
flutter:
sdk: flutter
webview_flutter: ^4.4.2
connectivity_plus: ^5.0.2
url_launcher: ^6.2.2
터미널에서 의존성 설치:
flutter pub get
3. 코드 작성
3.1 main.dart 파일 수정
lib/main.dart
파일을 다음 코드로 완전히 교체:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(WebViewApp());
}
class WebViewApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My WebView App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: WebViewScreen(),
debugShowCheckedModeBanner: false,
);
}
}
class WebViewScreen extends StatefulWidget {
@override
_WebViewScreenState createState() => _WebViewScreenState();
}
class _WebViewScreenState extends State<WebViewScreen> {
// ⭐ 여기에 원하는 웹사이트 URL 입력 ⭐
static const String WEBSITE_URL = 'https://example.com';
late WebViewController _controller;
bool _isLoading = true;
bool _hasError = false;
String _currentUrl = WEBSITE_URL;
@override
void initState() {
super.initState();
_initWebView();
}
void _initWebView() {
_controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setBackgroundColor(const Color(0x00000000))
..setNavigationDelegate(
NavigationDelegate(
onProgress: (int progress) {
if (progress == 100) {
setState(() {
_isLoading = false;
});
}
},
onPageStarted: (String url) {
setState(() {
_isLoading = true;
_hasError = false;
_currentUrl = url;
});
},
onPageFinished: (String url) {
setState(() {
_isLoading = false;
});
},
onWebResourceError: (WebResourceError error) {
setState(() {
_hasError = true;
_isLoading = false;
});
},
onNavigationRequest: (NavigationRequest request) {
// 외부 링크 처리
if (_shouldOpenExternally(request.url)) {
_launchURL(request.url);
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
),
)
..loadRequest(Uri.parse(WEBSITE_URL));
}
bool _shouldOpenExternally(String url) {
// 외부 브라우저에서 열어야 할 URL 패턴
return url.contains('tel:') ||
url.contains('mailto:') ||
url.contains('sms:') ||
url.contains('market://') ||
url.contains('intent://');
}
Future<void> _launchURL(String url) async {
if (await canLaunchUrl(Uri.parse(url))) {
await launchUrl(Uri.parse(url));
}
}
Future<void> _refresh() async {
await _controller.reload();
}
Future<bool> _onWillPop() async {
if (await _controller.canGoBack()) {
_controller.goBack();
return false;
}
return true;
}
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
appBar: AppBar(
title: Text('My App'),
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
elevation: 0,
actions: [
IconButton(
icon: Icon(Icons.refresh),
onPressed: _refresh,
),
],
),
body: Stack(
children: [
if (_hasError)
_buildErrorWidget()
else
WebViewWidget(controller: _controller),
if (_isLoading)
Center(
child: CircularProgressIndicator(
color: Colors.blue,
),
),
],
),
),
);
}
Widget _buildErrorWidget() {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.error_outline,
size: 64,
color: Colors.red,
),
SizedBox(height: 16),
Text(
'페이지를 불러올 수 없습니다',
style: TextStyle(fontSize: 18),
),
SizedBox(height: 16),
ElevatedButton(
onPressed: _refresh,
child: Text('다시 시도'),
),
],
),
);
}
}
4. 앱 설정 커스터마이징
4.1 앱 이름 변경
pubspec.yaml
파일에서:
name: your_app_name
description: Your app description
4.2 Android 설정
android/app/src/main/AndroidManifest.xml
:
<application
android:label="Your App Name"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
인터넷 권한 추가:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
4.3 iOS 설정
ios/Runner/Info.plist
에 추가:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
5. 앱 아이콘 변경
5.1 flutter_launcher_icons 플러그인 설치
pubspec.yaml
에 추가:
dev_dependencies:
flutter_launcher_icons: ^0.13.1
flutter_icons:
android: "launcher_icon"
ios: true
image_path: "assets/icon/icon.png"
min_sdk_android: 21
5.2 아이콘 생성
- 1024x1024 PNG 이미지 준비
assets/icon/
폴더 생성- 이미지를
icon.png
로 저장 - 터미널에서 실행:
flutter pub run flutter_launcher_icons:main
6. 빌드 및 배포
6.1 Android APK 빌드
# 디버그 버전
flutter build apk
# 릴리즈 버전
flutter build apk --release
6.2 iOS 빌드 (macOS 전용)
flutter build ios --release
6.3 앱스토어 업로드용 빌드
# Android
flutter build appbundle --release
# iOS
flutter build ipa --release
7. URL 변경 방법
단일 URL 변경
main.dart
파일에서 다음 줄만 수정:
static const String WEBSITE_URL = 'https://your-new-website.com';
여러 웹사이트용 템플릿 만들기
- 프로젝트 복사
- URL 변경
- 앱 이름, 패키지명, 아이콘 변경
- 빌드
8. 고급 기능 추가
8.1 푸시 알림
pubspec.yaml
에 추가:
firebase_messaging: ^14.7.9
8.2 오프라인 캐싱
pubspec.yaml
에 추가:
flutter_cache_manager: ^3.3.1
8.3 진동 피드백
pubspec.yaml
에 추가:
vibration: ^1.8.4
9. 트러블슈팅
자주 발생하는 오류
- Build 실패:
flutter clean
후flutter pub get
실행 - WebView 빈 화면: AndroidManifest.xml의 인터넷 권한 확인
- iOS 빌드 실패: Info.plist의 ATS 설정 확인
성능 최적화
- 이미지 최적화
- 캐시 설정 조정
- 메모리 사용량 모니터링
10. 체크리스트
배포 전 확인사항:
- URL 정상 작동 확인
- 앱 이름 변경 완료
- 아이콘 교체 완료
- 권한 설정 완료
- 테스트 기기에서 정상 작동 확인
- 앱스토어 정책 준수 확인
완료! 이제 Flutter WebView 앱이 준비되었습니다.
반응형
'Tech : 데이터 분석 > by ChatGPT' 카테고리의 다른 글
구글 애드센스 무효 클릭 방지 완벽 가이드(2025) (0) | 2025.08.30 |
---|---|
[R] 파일명이 숫자로만 이뤄진 임시파일 일괄 삭제 (2) | 2025.08.17 |
[Bash셸] Docker 컨테이너 임시 파일 정리 스크립트 🛠️ (0) | 2025.04.03 |
(~3/2) 2025 서울리빙디자인페어: 리빙 디자인의 미래를 만나다 (0) | 2025.02.28 |
[2025-02-25] 한국은행 기준금리 0.25%p 인하 연 2.75%로 조정 (0) | 2025.02.26 |
댓글