Flutter 앱 성능 개선 - Skia 렌더링 병목 해결
문제 상황
300개 이상의 아이템을 가진 리스트 화면에서 스크롤 시 프레임이 심하게 떨어지는 현상이 발생했다. 사용자 피드백에서도 버벅임이 계속 지적되었다.
분석
Flutter DevTools의 Performance 탭으로 확인한 결과:
- UI 스레드에서 16ms를 초과하는 프레임 다수 발견
- Raster 스레드의 Skia 렌더링 시간이 과도하게 높음
- 부모 위젯 상태 변경 시 전체 리스트가 rebuild되고 있었음
해결 과정
1. RepaintBoundary 적용
각 리스트 아이템을 RepaintBoundary로 감싸서 렌더링 범위를 격리했다.
ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return RepaintBoundary(
child: ItemCard(item: items[index]),
);
},
)
2. const 생성자 활용
변경되지 않는 위젯은 const로 선언하여 불필요한 rebuild를 방지했다.
class ItemCard extends StatelessWidget {
const ItemCard({super.key, required this.item});
final Item item;
@override
Widget build(BuildContext context) {
return Card(
child: const Padding( // const 추가
padding: EdgeInsets.all(16),
child: ...,
),
);
}
}
3. ListView.builder 최적화
cacheExtent를 조정하고 addAutomaticKeepAlives를 false로 설정했다.
ListView.builder(
cacheExtent: 100,
addAutomaticKeepAlives: false,
itemBuilder: ...,
)
결과
- 평균 프레임 시간: 23ms → 11ms
- Jank 발생률: 35% → 5% 이하
- 사용자 체감 성능 크게 개선
DevTools의 프로파일링 도구를 활용하면 Flutter 성능 병목을 정확히 찾아낼 수 있다. 특히 RepaintBoundary는 복잡한 UI에서 렌더링 비용을 크게 줄여준다.