Flutter 웹뷰에서 window.close() 함수가 제대로 작동하지 않는 것은 흔한 문제입니다. 이는 웹뷰가 일반적인 브라우저와 달리 자체적인 창 관리 메커니즘을 가지고 있지 않기 때문입니다. 이 문제를 해결하려면 **웹뷰와 Flutter 네이티브 코드 간의 통신**을 활용해야 합니다. 다음은 window.close() 기능을 구현하기 위한 다양한 방법과 구체적인 코드 예시입니다.
1. JavaScript 인터페이스 사용 (가장 일반적인 방법)
이 방법은 웹페이지의 JavaScript에서 Flutter 코드로 직접 함수를 호출하는 방식입니다. 웹뷰에 JavaScript 핸들러를 등록하고, 웹에서 해당 핸들러를 호출하여 웹뷰를 닫습니다.
Flutter 코드:
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:flutter/material.dart';
// ...
InAppWebView(
initialUrlRequest: URLRequest(url: WebUri("https://example.com")),
onWebViewCreated: (controller) {
controller.addJavaScriptHandler(
handlerName: 'closeWebView', // JavaScript에서 호출할 핸들러 이름
callback: (args) {
print("JavaScript에서 'closeWebView'가 호출되었습니다.");
Navigator.of(context).pop(); // 웹뷰가 포함된 화면을 닫음
},
);
},
)
JavaScript 코드:
웹페이지에서는 아래 코드를 사용하여 Flutter 네이티브 핸들러를 호출합니다.
function closeWindow() {
if (window.flutter_inappwebview) {
// Flutter 웹뷰 환경일 경우 핸들러 호출
window.flutter_inappwebview.callHandler('closeWebView');
} else {
// 일반 웹 브라우저 환경일 경우 window.close() 호출
window.close();
}
}
2. URL 변경 감지 (간단하고 효과적인 방법)
이 방법은 웹페이지에서 특정 URL로 리다이렉션하는 것을 감지하여 웹뷰를 닫는 방식입니다. 웹페이지에서 미리 정해둔 스키마(예: myapp://)를 가진 URL로 이동하도록 코드를 작성하고, Flutter에서 이 URL을 감지하면 됩니다.
Flutter 코드:
InAppWebView(
initialUrlRequest: URLRequest(url: WebUri("https://example.com")),
onLoadStart: (controller, url) {
if (url.toString() == 'myapp://close') {
print("'myapp://close' URL이 감지되었습니다. 웹뷰를 닫습니다.");
Navigator.of(context).pop();
return NavigationActionPolicy.CANCEL; // URL 변경을 취소하여 페이지 이동 방지
}
return NavigationActionPolicy.ALLOW; // 다른 URL은 정상적으로 로드
},
)
JavaScript 코드:
웹페이지의 특정 버튼 클릭 시 아래 함수가 실행되도록 설정합니다.
function closeWindow() {
window.location.href = 'myapp://close';
}
3. 웹뷰 상태 관리 (보다 유연한 제어)
웹뷰를 위젯으로 감싸고, Flutter의 상태 관리(setState)를 통해 웹뷰 위젯 자체를 화면에서 제거하는 방법입니다. 웹페이지에서 네이티브 코드로 메시지를 보내면, Flutter는 상태를 변경하여 웹뷰를 숨기거나 닫을 수 있습니다.
Flutter 코드:
bool _showWebView = true;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("웹뷰 예제")),
body: _showWebView
? InAppWebView(
initialUrlRequest: URLRequest(url: WebUri("https://example.com")),
onWebViewCreated: (controller) {
controller.addJavaScriptHandler(
handlerName: 'closeWebView',
callback: (args) {
print("웹뷰 상태를 변경합니다.");
setState(() {
_showWebView = false;
});
},
);
},
)
: Center(child: Text("웹뷰가 닫혔습니다.")),
);
}
이 방법은 웹뷰를 닫는 대신 다른 위젯을 보여주는 등 더 복잡한 화면 전환 로직을 구현할 때 유용합니다.
결론
Flutter 웹뷰에서 window.close() 문제는 웹(JavaScript)과 네이티브(Flutter) 간의 통신을 통해 해결해야 합니다. JavaScript 핸들러를 이용하는 방법, URL 변경을 감지하는 방법, 그리고 상태 관리를 통해 웹뷰 위젯 자체를 제어하는 방법 등 여러 가지가 있습니다. 프로젝트의 특성과 요구사항에 가장 적합한 방법을 선택하여 구현하고, 디버깅을 통해 안정성을 확보하세요.