๐Ÿ“ฑFlutter/Flutter Framework

[Flutter] ํ”Œ๋Ÿฌํ„ฐ ์›น๋ทฐ ์•ฑ ๋งŒ๋“ค๊ธฐ (package:webview_flutter)

๋ฃจ๋ฆฌ์•ผใ…‘ 2025. 5. 12. 17:09
๋ฐ˜์‘ํ˜•

ํ”Œ๋Ÿฌํ„ฐ๋กœ ์›น๋ทฐ ์•ฑ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•! ๋…ธ์น˜์™€ ์ƒํƒœ๋ฐ” ๋ถ€๋ถ„ SafeArea๋กœ ์ฒ˜๋ฆฌํ•ด์„œ ํŽธ์•ˆํ•˜๊ฒŒ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

0. ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ์€ ์ƒ๋žต

.. 

1. ์›น๋ทฐ ํ”Œ๋Ÿฌ๊ทธ์ธ(webview_flutter) ์ถ”๊ฐ€ - pubspec.yaml

์•„๋ž˜์™€ ๊ฐ™์ด dependencies ์ถ”๊ฐ€ํ•˜๊ณ  ํ„ฐ๋ฏธ๋„์—์„œ pub get์œผ๋กœ ํŒจํ‚ค์ง€ ์ถ”๊ฐ€

dependencies:
  flutter:
    sdk: flutter
  webview_flutter: ^4.11.0 # (์ตœ์‹  ๋ฒ„์ „ ํ™•์ธ)

 

2.  ๋„ค์ดํ‹ฐ๋ธŒ๋ณ„ ์„ค์ •

2.1. Android

android/app/src/main/AndroidManifest.xml ์— ์ธํ„ฐ๋„ท ๊ถŒํ•œ ์ถ”๊ฐ€

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-permission android:name="android.permission.INTERNET"/>
    
    ...

 

2.2. iOS

ios/Runner/Info.plist ์— ์•„๋ž˜ ๋‚ด์šฉ ์ถ”๊ฐ€

iOS ์•ฑ์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ณด์•ˆ์ƒ์˜ ์ด์œ ๋กœ, ์•ฑ์—์„œ ์ ‘์†ํ•˜๋Š” ๋ชจ๋“  ์›น์‚ฌ์ดํŠธ๊ฐ€ HTTPS(์•”ํ˜ธํ™”๋œ ํ†ต์‹ )๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๊ฐ•์ œํ•œ๋‹ค.
์ด ์ •์ฑ…์„ App Transport Security(ATS)๋ผ๊ณ  ํ•˜์ง€๋งŒ,
์›น๋ทฐ(WebView)๋กœ ์ ‘์†ํ•˜๋ ค๋Š” ์›น์‚ฌ์ดํŠธ๊ฐ€ HTTP(์•”ํ˜ธํ™”๋˜์ง€ ์•Š์€ ํ†ต์‹ )๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜,
ํŠน์ •ํ•œ ์ด์œ ๋กœ ๋ชจ๋“  ๋„๋ฉ”์ธ์— ๋Œ€ํ•ด ์˜ˆ์™ธ๋ฅผ ํ—ˆ์šฉํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.

์œ„์™€ ๊ฐ™์€ ์ƒํ™ฉ์ด ์žˆ์„ ์ˆ˜ ์žˆ์–ด ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•ด์ค˜์•ผ ํ•œ๋‹ค.

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

 

3. ์›น๋ทฐ ์ฝ”๋“œ

ํŽธ์˜์ƒ main์—์„œ ์›น๋ทฐ๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์›น๋ทฐ ์Šคํฌ๋ฆฐ๊ณผ ์Šคํ”Œ๋ž˜์‰ฌ ํ™”๋ฉด์„ ๋”ฐ๋กœ ๋งŒ๋“ค์–ด์„œ ํ–ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์•„๋ž˜ ์ฝ”๋“œ์—์„œ๋Š” debug ๋ฆฌ๋ณธ๋„ ์—†์• ๊ณ 
SafeArea๋กœ ์ƒํƒœ๋ฐ”์™€ ๋…ธ์น˜์— ํ™”๋ฉด์ด ๊ฒน์ณ ๋ถˆํŽธํ•œ ํ˜„์ƒ๋„ ์—†์•ด๋‹ค.

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: 'Flutter WebView App',
      // debug ๋ฆฌ๋ณธ ์—†์• ๊ธฐ
      debugShowCheckedModeBanner: false,
      theme: ThemeData( 
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const WebViewExample(),
    );
  }
}

class WebViewExample extends StatefulWidget {
  const WebViewExample({super.key});

  @override
  State<WebViewExample> createState() => _WebViewExampleState();
}

class _WebViewExampleState extends State<WebViewExample> {
  late final WebViewController _controller;

  @override
  void initState() {
    super.initState();
    _controller = WebViewController()
      ..loadRequest(Uri.parse('https://flutter.dev'));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        backgroundColor: Colors.white,
        resizeToAvoidBottomInset: true,
        
      // SafeArea๋กœ ์ƒํƒœ๋ฐ” ๋…ธ์น˜ ๊ฐ€๋ฆฌ์ง€ ์•Š๋„๋ก
      body: SafeArea(
        child: WebViewWidget(controller: _controller),
      ), 
      
    );
  }
}
๋ฐ˜์‘ํ˜•