ListView.builder의 shrinkWrap, 메모리는 안녕하십니까?

Carl's Space·2025년 3월 18일

Flutter

목록 보기
3/4
post-thumbnail

ListView.builder의 shrinkWrap, 언제나 정답일까? – Sliver로 해결하는 렌더링 최적화

Flutter에서 리스트를 구성할 때 가장 많이 쓰는 구조 중 하나는 ListView.builder다.
그런데 shrinkWrap: trueNeverScrollableScrollPhysics() 조합은 단순히 UI 구성에는 편리하지만, 대량 데이터를 다룰 때 심각한 성능 문제를 일으킬 수 있다.


🤔 왜 shrinkWrap을 쓰게 되는가?

대부분은 이런 구조에서다:

SingleChildScrollView(
  child: Column(
    children: [
      Text("제목"),
      ListView.builder(
        shrinkWrap: true,
        physics: NeverScrollableScrollPhysics(),
        itemCount: items.length,
        itemBuilder: ...
      ),
    ],
  ),
)

위처럼 여러 위젯과 리스트를 함께 배치하려다 보니 shrinkWrap: true를 사용하게 되는데,
이 구조는 비효율적이다.


🧠 문제의 본질 – lazy rendering이 아니다

ListView.builder는 원래 lazy rendering, 즉 스크롤되기 전에는 위젯을 만들지 않는 방식으로 작동한다.
하지만 shrinkWrap: true를 사용하면 이 lazy 특성이 사라진다. 전체 데이터를 한 번에 렌더링하게 된다.

❗ 어떤 문제가 생기나?

  • 리스트 아이템이 수천 개면, build 시점에 모든 위젯을 생성함
  • Flutter의 렌더링 트리가 커지고 메모리 사용량 폭발
  • 결국 UI 지연, 프레임 드랍, 심하면 앱 크래시

💥 잘못된 대안 – for문, map().toList()

map().toList()

Column(
  children: items.map((item) => Text(item)).toList(),
)

for문

Column(
  children: [
    for (var item in items) Text(item),
  ],
)

이 코드도 결국 모든 아이템을 한 번에 렌더링한다.
즉, lazy rendering이 아닌 건 똑같다.


✅ 해결책 – CustomScrollView + SliverList

CustomScrollView는 여러 scrollable 위젯을 lazy하게 조합할 수 있게 도와준다.
가장 적절한 구조는 아래와 같다:

CustomScrollView(
  slivers: [
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (context, index) => Text(items[index]),
        childCount: items.length,
      ),
    ),
  ],
)

이 방식은 ListView.builder의 lazy 성능은 유지하면서도, 여러 위젯을 함께 구성할 수 있는 유연함을 제공한다.


🔄 Sliver로 대체 가능한 구조

CustomScrollView(
  slivers: [
    SliverToBoxAdapter(
      child: Text("제목"),
    ),
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (context, index) => Text(items[index]),
        childCount: items.length,
      ),
    ),
  ],
)
  • SliverToBoxAdapter → 일반 위젯을 포함시킬 때 사용
  • SliverList → 리스트 아이템을 lazy하게 렌더링

📌 정리

  • shrinkWrap: true는 필요할 때만 쓰고, 대량 데이터에는 반드시 피해야 한다.
  • for문, map().toList() 방식은 그저 더 빠르게 메모리를 고갈시킬 뿐이다.
  • 여러 UI 구성과 lazy 성능을 모두 잡고 싶다면 CustomScrollView + Sliver가 정답이다.

profile
성장중...

0개의 댓글