Flutter를 배우기 시작했을 때, 웹 플랫폼에서 HttpClient를 사용하려고 하면 "Platform not supported" 오류가 발생한다. 이는 Flutter의 기본 HTTP 클라이언트가 브라우저 환경에서 지원되지 않기 때문이다. 이 문제를 해결하기 위해 JavaScript 라이브러iri와 dart:js의 상호 운용성을 활용하는 방법을 알아본다.
먼저 Dart 측面的 코드를 살펴보자. main.dart 파일에서 JavaScript 함수를 호출하고, JavaScript에서 결과를 다시 Dart로 전달받는 구조다.
import 'package:flutter/material.dart';
import 'dart:js';
void executeNetworkRequest(){
context['console'].callMethod('log', ['API 요청 시작']);
JsObject(context['fetchDataFromServer'], ['https://api.example.com/data', '{userId: 5678, nickname: "Developer"}']);
}
void handleServerResponse(responseData){
print('서버 응답: $responseData');
}
void main() {
context['receiveData'] = handleServerResponse;
runApp(new SampleApplication());
}
class SampleApplication extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new DashboardPage(),
);
}
}
class DashboardPage extends StatefulWidget {
DashboardPage({Key key}) : super(key: key);
@override
_DashboardPageState createState() => new _DashboardPageState();
}
class _DashboardPageState extends State<DashboardPage> {
@override
Widget build(BuildContext context) {
var spacing = new SizedBox(height: 48.0);
return new Scaffold(
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text('Dart-JavaScript 연동 데모'),
new Text('네트워크 요청 실행'),
spacing,
new RaisedButton(
onPressed: (){
executeNetworkRequest();
},
child: new Text('요청 보내기'),
),
],
),
),
);
}
}
이제 웹 환경의 index.html 파일을 수정해야 한다. Flutter가 생성한 HTML 파일에 필요한 스크립트를 추가하고, JavaScript 함수를 정의한다.
<html>
<head>
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="sample_app">
<link rel="apple-touch-icon" href="icons/Icon-192.png">
<link rel="shortcut icon" type="image/png" href="favicon.png"/>
<title>sample_app</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<script src="https://cdn.bootcss.com/axios/0.18.0/axios.min.js" type="application/javascript"></script>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('load', function () {
navigator.serviceWorker.register('flutter_service_worker.js');
});
}
function fetchDataFromServer(requestUrl, parameters){
let result = '';
axios({
method: 'get',
url: requestUrl,
params: parameters
})
.then(function(response) {
result = response.data;
receiveData(result);
}).catch(function(error){
receiveData(error);
});
}
</script>
<script src="main.dart.js" type="application/javascript"></script>
</body>
</html>
이 구현의 핵심 원리는 다음과 같다. Dart 측면에서 JavaScript의 전역 객체를 통해 JS 함수에 접근하고, JavaScript側에서는 axios를 사용하여 HTTP 요청을 수행한 후 Dart에서 등록한 콜백 함수를 통해 결과를 반환한다.
다른 대안으로는 http 패키지의 BrowserClient를 사용하는 방법도 있지만, 특정 요구사항에 따라 dart:js를 활용하는 것이 더 적합한 경우도 있다.