Flutter에서 동적 위젯 로딩(Dynamically Loading Widgets in Flutter)
Flutter에서는 기본적으로 정적으로 컴파일된 언어(Dart)를 사용하기 때문에, JavaScript처럼 동적으로 코드를 로딩하여 실행하는 기능이 제한적입니다. 하지만 몇 가지 방법을 활용하면 동적으로 위젯을 생성하고 실행할 수 있습니다.
1. Map<String, WidgetBuilder>
을 활용한 동적 위젯 생성
Flutter에서는 Map<String, WidgetBuilder>
를 사용하여 특정 문자열 키로 위젯을 찾고 실행할 수 있습니다.
예제 코드
import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // 동적으로 위젯을 매핑하는 Map final Map<String, WidgetBuilder> widgetRegistry = { 'home': (context) => HomeScreen(), 'profile': (context) => ProfileScreen(), }; @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text("Dynamic Widget Loader")), body: DynamicWidgetLoader(widgetRegistry: widgetRegistry), ), ); } } class DynamicWidgetLoader extends StatefulWidget { final Map<String, WidgetBuilder> widgetRegistry; const DynamicWidgetLoader({required this.widgetRegistry, Key? key}) : super(key: key); @override _DynamicWidgetLoaderState createState() => _DynamicWidgetLoaderState(); } class _DynamicWidgetLoaderState extends State<DynamicWidgetLoader> { String selectedWidget = 'home'; @override Widget build(BuildContext context) { return Column( children: [ DropdownButton<String>( value: selectedWidget, items: widget.widgetRegistry.keys .map((key) => DropdownMenuItem(value: key, child: Text(key))) .toList(), onChanged: (value) { setState(() { selectedWidget = value!; }); }, ), Expanded( child: widget.widgetRegistry[selectedWidget]!(context), ), ], ); } } class HomeScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Center(child: Text("Home Screen")); } } class ProfileScreen extends StatelessWidget { @override Widget build(BuildContext context) { return Center(child: Text("Profile Screen")); } }
설명
Map<String, WidgetBuilder>
를 사용하여 키(String)로 위젯을 등록합니다.DropdownButton
으로 사용자가 선택한 위젯을 불러와 동적으로 변경합니다.
2. Reflection(반사)을 이용한 동적 위젯 로딩
Dart는 기본적으로 Reflection(반사)을 지원하지 않지만, dart:mirrors
패키지를 이용하면 클래스 이름을 문자열로 받아 인스턴스를 생성할 수 있습니다.
⚠️ 하지만 dart:mirrors
는 Flutter에서 정식 지원되지 않으므로, json_serializable
이나 code generation
같은 대체 방식을 사용하는 것이 좋습니다.
import 'dart:mirrors'; class HomeScreen { void show() => print("HomeScreen Loaded"); } void main() { String className = "HomeScreen"; // 동적으로 로딩할 클래스 이름 var mirrorSystem = currentMirrorSystem(); var library = mirrorSystem.libraries.values.firstWhere((lib) => lib.declarations.containsKey(Symbol(className))); var classMirror = library.declarations[Symbol(className)] as ClassMirror; var instance = classMirror.newInstance(Symbol(''), []).reflectee; instance.show(); // "HomeScreen Loaded" 출력 }
주의사항
- Flutter에서는
dart:mirrors
를 지원하지 않음. - 웹 및 모바일 앱에서는 사용하기 어려움.
3. JSON을 이용한 동적 위젯 로딩
서버에서 JSON 데이터를 받아 동적으로 위젯을 생성하는 방법이 있습니다.
예제
JSON 데이터 (widget_config.json
)
{ "type": "container", "color": "0xFF42A5F5", "width": 200, "height": 100 }
Flutter 코드
import 'dart:convert'; import 'package:flutter/material.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text("JSON Dynamic Widget")), body: FutureBuilder( future: loadWidgetFromJson(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return CircularProgressIndicator(); } if (snapshot.hasError) { return Text("Error loading widget"); } return snapshot.data as Widget; }, ), ), ); } Future<Widget> loadWidgetFromJson() async { // 가정: JSON이 서버에서 로드됨 String jsonString = ''' { "type": "container", "color": "0xFF42A5F5", "width": 200, "height": 100 } '''; Map<String, dynamic> jsonData = jsonDecode(jsonString); return parseWidget(jsonData); } Widget parseWidget(Map<String, dynamic> jsonData) { switch (jsonData["type"]) { case "container": return Container( width: jsonData["width"].toDouble(), height: jsonData["height"].toDouble(), color: Color(int.parse(jsonData["color"])), ); default: return Text("Unknown Widget"); } } }
설명
- JSON 데이터를 받아 위젯을 생성하는 방식
- API에서 JSON을 받아 화면을 동적으로 구성할 수 있음
4. Code Generation(코드 생성)을 활용한 동적 로딩
build_runner
와 같은 도구를 이용하여 코드 생성을 통해 동적으로 위젯을 로드하는 방식도 가능합니다.
json_serializable
을 활용하여 JSON 데이터를 Dart 객체로 변환 후 위젯을 생성flutter_dynamic_widget
패키지를 사용하여 JSON으로 UI 구성
결론(Conclusion)
방법 | 설명 | 장점 | 단점 |
---|---|---|---|
Map<String, WidgetBuilder> | 사전에 정의된 위젯을 동적으로 로드 | 간단하고 효율적 | 사전에 등록된 위젯만 가능 |
Reflection (dart:mirrors ) | 문자열로 클래스를 로드하여 실행 | 유연한 동적 로딩 | Flutter에서 지원되지 않음 |
JSON 기반 동적 위젯 | JSON 데이터를 기반으로 위젯을 생성 | 서버 기반 UI 변경 가능 | 미리 정의된 위젯 타입만 지원 |
Code Generation | 코드 생성을 통해 동적 UI 제공 | 성능 최적화 가능 | 초기 설정이 필요 |
Flutter는 기본적으로 정적으로 컴파일되므로 JavaScript처럼 자유롭게 코드를 불러와 실행할 수는 없지만, 위의 방법들을 활용하면 동적인 UI 구성이 가능합니다.