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 구성이 가능합니다.
