Flutter 위젯 렌더링 최적화 - const 생성자 활용
문제 상황
사내 모바일 앱을 Flutter로 전환하는 프로젝트를 진행 중이다. 리스트 스크롤 시 프레임 드롭이 발생해 DevTools로 프로파일링을 해보니 불필요한 위젯 리빌드가 빈번하게 일어나고 있었다.
원인 분석
StatefulWidget의 setState()가 호출될 때마다 하위 위젯들이 매번 새로 생성되고 있었다. 특히 변하지 않는 정적인 위젯들까지 재생성되는 것이 주요 원인이었다.
class UserList extends StatefulWidget {
@override
_UserListState createState() => _UserListState();
}
class _UserListState extends State<UserList> {
List<User> users = [];
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(users[index].name),
// 매번 새로운 Icon 인스턴스 생성
trailing: Icon(Icons.chevron_right),
);
},
);
}
}
해결 방법
변하지 않는 위젯은 const 생성자를 사용해 컴파일 타임에 인스턴스를 생성하도록 수정했다.
class _UserListState extends State<UserList> {
List<User> users = [];
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(users[index].name),
// const로 선언해 재사용
trailing: const Icon(Icons.chevron_right),
);
},
);
}
}
복잡한 정적 위젯은 별도로 분리했다.
class _EmptyState extends StatelessWidget {
const _EmptyState();
@override
Widget build(BuildContext context) {
return Center(
child: Column(
children: const [
Icon(Icons.inbox, size: 64),
SizedBox(height: 16),
Text('데이터가 없습니다'),
],
),
);
}
}
결과
Flutter DevTools의 Performance 탭에서 확인 결과 위젯 리빌드 횟수가 약 60% 감소했고, 스크롤 시 프레임 드롭도 해결되었다. const 키워드 하나로 꽤 큰 성능 개선을 얻을 수 있었다.
Flutter는 선언형 UI라 위젯 트리를 매번 재구성하는 방식이지만, const를 적절히 활용하면 불필요한 연산을 줄일 수 있다. 앞으로는 정적 위젯에 const를 습관적으로 붙이는 게 좋겠다.