티스토리 뷰
앱 개발을 하면서 반복적으로 사용되거나 내부 로직이 약간 차이가 있지만 큰 틀에서는 비슷한 형태의 위젯을 만들 때 하위 위젯으로 구분하여 사용한다.
위젯을 선언하는 방법으로는 Widget을 return 하는 Function Widget과 클래스로 선언하는 Class Widget을 사용할 수 있다. 지금까지는 무분별하게 사용하고 있었던 것 같아 그동안 내가 왜 / 어떻게 사용했는지, 그리고 그 쓰임새를 정확하게 하기 위해 정리하는 시간을 가졌다.
지금 나는 어떻게 사용하고 있는가.
Flutter로 앱개발으 하면서 양쪽 모두 사용해서 위젯을 개발해봤다.
현재 나는 Row나 Column을 사용할 때 하위 컴포넌트로 인해 전체 컴포넌트가 복잡해지는 경우나, 같은 위젯이 반복되는 경우에 클래스 위젯 내부에서 함수 위젯으로 분리하여 사용하고 있다.
그리고 페이지 단위, 형태가 다양한 위젯(ex. Button, Input)의 경우에 클래스 위젯으로 선언하여 사용하고 있다.
간단하게 두가지로 똑같은 화면을 만들어보았다.
두 위젯의 차이점
rebuild의 범위
두 위젯으로 다음과 같이 동일한 화면을 만들어보았고, Dart DevTools를 통해 내부 위젯 투리 구조를 확인해보았다.
Function Widget
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: _myHomePage(),
);
}
}
Widget _myHomePage() {
return Container(
child: Center(
child: Text('Hello, Flutter!'),
));
}
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text('Hello, Flutter!'),
));
}
}
Class의 경우 ( 클래스 이름 > build 하는 위젯 ) 구조로 상위 위젯에 포함되어 있는 것을 볼 수 있고, 반면에 Function의 경우 return 하는 위젯 자체가 상위 위젯에 그대로 포함되는 것을 볼 수 있다.
구조적으로는 약간의 차이가 있지만 문제가 없어 보인다. 하지만 리프레시되는 경우에 그 차이가 발생한다. Class로 선언된 위젯은 리프레시될 때 Flutter의 랜더링 방식에 의해 Class 내부의 변경 점들만 리프레시된다.
반면 Function으로 만든 위젯의 경우, 리프레시될 때 함수가 다시 호출되기 때문에 구조를 처음부터 다시 그린다.
클래스로 선언된 경우 위젯 트리가 인식하지만, Function으로 return 된 위젯은 Function으로 구분한 위젯이 상위 위젯 내부에 포함된 채로 인식된다.
Performance
1번과 연결된 내용으로, 리프레시했을 때 rebuild가 발생하는 범위가 클수록 성능이 떨어질 가능성이 높다. 그래서 Function으로 만든 위젯이 성능이 좋지 않을 가능성이 높다. 그리고 작은 구조의 경우 문제가 되지 않지만 구조가 복잡해지는 경우, 그 차이는 더욱 심할 것이다.
Bugs
Function을 통해 위젯 트리에 위젯을 넣게 되면 버그에 노출될 수 있고 일부 성능 최적화를 놓칠 수 있다. Function을 사용하면 버그가 발생할 수 있지만, Class의 경우보다 그런 문제에 노출되지 않는다는 것을 보장한다고 한다.
결론
Class를 이용하는 것이 Function 위젯보다 더 나은 점이 많다.
Class로 위젯을 선언했을 때는, 위에서 다룬 내용처럼 최적화되어 있는 성능이나 DevTools에서 보다 명확하게 구분된 위젯을 확인할 수 있다는 점 외에도, 서로 다른 레이아웃 간 전환이 일어날 때 리소스를 정확하게 처리하는지 확인 가능하고, 핫 리로드가 제대로 작동하는지 확인할 수 있다. 그리고 우리가 Error 메시지를 확인할 때도 위젯 이름을 통해 위치를 확인할 수 있다.
Function 위젯은 이전에 내가 사용하던 방식으로는 사용할 수는 없지만 단일 위젯 내에서 코드가 복잡해질 때, 코드를 간략하게 정리하는 경우에는 선택적으로 사용할 수 있을 것 같다는 생각을 해보았다.
그래서 Function 보다 Class 기반으로 위젯을 생성하는 것을 습관화하자.
Reference
'Flutter' 카테고리의 다른 글
[Flutter] Future<void> 와 void (0) | 2022.11.30 |
---|
- Total
- Today
- Yesterday
- redux
- SPA
- Transpiler
- error
- redux-thunk
- Vue.js
- js
- 백준
- React
- 문제풀이
- 파이썬
- python
- GraphQL
- Repository Pattern
- AxiosInterceptor
- bundler
- TypeScript
- SOAP API
- 알고리즘
- Vue
- Preloading
- 프로그래머스
- programmers
- Vuex
- webpack
- clean code
- 상호평가
- v-for
- React.memo
- reactrouter
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |