๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
์›น๊ณต๋ทฐ/flutter

flutter webview ์„ค์ • ๋ฐ ๊ฐ„๋‹จํ•œ ๊ตฌํ˜„

by ์ด๋…ธํ‚ค_ 2023. 7. 26.

์›น๋ทฐ๋ž€?

์•ฑ์—์„œ ์›น๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด์ฃผ๋Š” ๊ธฐ์ˆ 

๋ณด์—ฌ์ฃผ๋Š” ํ™”๋ฉด์€ ์›น์œผ๋กœ ๊ฐœ๋ฐœํ•ด๋†“๊ณ  ๊ฒ‰์„ ์•ฑ์œผ๋กœ ๊ฐ์‹ธ์„œ ๋ฐฐํฌํ•จ

๋„ค์ดํ‹ฐ๋ธŒ์— ๋น„ํ•ด ์†๋„๊ฐ€ ๋Š๋ฆฌ๊ณ , ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋ถ€์ž์—ฐ์Šค๋Ÿฝ๊ธด ํ•˜์ง€๋งŒ ๊ธฐ์กด์˜ ์›น์‚ฌ์ดํŠธ๋ฅผ ์žฌํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Œ.

 

0. ์‚ฌ์ „ ์„ค์ •

(1) pubspec.yaml ์„ค์ •

webview_flutter ์˜์กด์„ฑ ์ถ”๊ฐ€

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  webview_flutter: 3.0.4

(2) ์•ˆ๋“œ๋กœ์ด๋“œ ์„ค์ •

android/app/src/main/AndroidManifest.xml

uses-permission, android:usesCleartextTraffic ์ถ”๊ฐ€

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.blog_web_app">
    <uses-permission android:name="android.permission.INTERNET"/>
   <application
        android:label="blog_web_app"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        android:usesCleartextTraffic="true">
        
        .. ์ƒ๋žต

build.gradle ์„ค์ •

android/app/build.gradle 

compiledSdkVersion, minSdkVersion ์ˆ˜์ •

android {
    compileSdkVersion 32 //32๋กœ ์ˆ˜์ •
    
    ... ์ƒ๋žต ... 
    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.example.blog_web_app"
        // You can update the following values to match your application needs.
        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
        minSdkVersion 20 //20์œผ๋กœ ๋ณ€๊ฒฝ
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

(3) ios ์„ค์ •

ios/Runner/Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	... ์ƒ๋žต ... 
    <!-- ์•„๋ž˜ ๋‚ด์šฉ ์ถ”๊ฐ€ >
	<key>NSAppTransportSecurity</key>
	<dict>
	    <key>NSAllowsLocaleNetworking</key>
	    <true/>
	    <key>NSAllowsArbitraryLoadsInWebContent</key>
	</dict>

</dict>
</plist>

 

1. ์ฒซ ํ™”๋ฉด ๋„์šฐ๊ธฐ

class HomeScreen extends StatelessWidget {
  
  final url = 'https://yonglimlee.tistory.com';

  HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.orange,
        title: Text('yllee'),
        centerTitle: true, //๊ฐ€์šด๋ฐ ์ •๋ ฌ
      ),
      body: WebView(
        initialUrl: url,
        javascriptMode: JavascriptMode.unrestricted,
        
      ),
    );
  }
}

์Šคํฌ๋กค์„ ํ•ด๋ณด๋ฉด ์ œ๋Œ€๋กœ ๋™์ž‘ํ•จ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. 

 

2. ์›น๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ ์ถ”๊ฐ€

ํ”Œ๋Ÿฌํ„ฐ๋Š” ์œ„์ ฏ์„ ํ”„๋กœ๊ทธ๋žจ์ ์œผ๋กœ(์ฝ”๋“œ๋กœ) ์ œ์–ดํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณต. ์ด ๊ธฐ๋Šฅ์€ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋‹ด๋‹นํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์›น๋ทฐ์˜ ๊ฒฝ์šฐ์—๋Š” ์›น๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์ด์šฉํ•ด ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค. 

class HomeScreen extends StatelessWidget {
  /*์ถ”๊ฐ€๋จ*/
  WebViewController? controller;
  final url = 'https://yonglimlee.tistory.com';

  HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.orange,
        title: Text('yllee'),
        centerTitle: true, //๊ฐ€์šด๋ฐ ์ •๋ ฌ
        /*์ถ”๊ฐ€๋จ*/
        actions: [
          IconButton(
              onPressed: (){ 
                if(controller != null){
                  controller!.loadUrl(url); //ํ™ˆ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ดˆ๊ธฐ url๋กœ ์ด๋™
                }
              },
              icon: const Icon(Icons.home)
          ),
          IconButton(
              onPressed: (){
                if(controller != null){
                  controller!.goBack();
                }
              },
              icon: const Icon(Icons.arrow_back) //๋’ค๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์ด์ „ ํŽ˜์ด์ง€๋กœ ์ด๋™
          ),
          IconButton(
              onPressed: (){
                if(controller != null){
                  controller!.goForward();
                }
              },
              icon: const Icon(Icons.arrow_forward)//์•ž์œผ๋กœ๊ฐ€๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์•ž ํŽ˜์ด์ง€๋กœ ์ด๋™
          )
        ],
      ),
      body: WebView(
        initialUrl: url,
        javascriptMode: JavascriptMode.unrestricted,
        
        /*์ถ”๊ฐ€๋จ. ์›น๋ทฐ ์ƒ์„ฑํ•จ์ˆ˜*/
        onWebViewCreated: (WebViewController controller){
          this.controller = controller; //๋ณ€์ˆ˜์— ์ €์žฅํ•˜๋ฉด ์œ„์ ฏ ์–ด๋””์„œ๋“  ์‚ฌ์šฉ๊ฐ€๋Šฅํ•จ
        },
      ),
    );
  }
}

 

๋Œ“๊ธ€