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에서 렌더링 비용을 크게 줄여준다.