본문 바로가기

MAUI CollectionView Item Recycling이 깨지는 7가지 패턴과 해결 전략

@veedeeo 2025. 12. 14. 09:52

CollectionView는 성능을 위해 셀 재사용 Item Recycling을 핵심 원리로 사용한다. 하지만 실제 프로젝트에서는 재사용이 의도대로 동작하지 않아 성능이 급격히 떨어지는 경우가 많다. 특히 MAUI의 경우 특정 UI 구조나 바인딩 패턴에 따라 Recycling이 완전히 비활성화되며, 그 결과 메모리 증가와 프레임 저하가 발생한다. 이 글에서는 개발 현장에서 자주 발생하는 Recycling 깨짐 패턴 7가지를 정리하고, 해결 방법을 단계적으로 제시한다.

 

MAUI CollectionView 셀 재사용 실패 원인과 최적화 핵심 정리

1. Recycling이 깨지는 구조적 원인 7가지
TemplateSelector 사용, HeightRequest 동적 변경, GestureRecognizer 남발, BindableLayout 중첩, ControlTemplate 변경, 복잡한 Grid 구조, 항목별 UI 불일치 등이 주요 원인이다.

2. 재사용을 지키기 위한 필수 전략
Template 캐싱, MeasureFirstItem, RowHeight 고정, 이미지 Downsampling, 이벤트 Command 바인딩을 통해 재사용률을 극대화할 수 있다.

3. 디버깅 팁
셀 생성 로그를 출력하면 실제 재사용 여부를 쉽게 파악할 수 있다.

4. 최종 결론
MAUI CollectionView는 기본적으로 재사용 기반 구조지만, 개발자가 UI 구조를 잘못 설계하면 즉시 비활성화된다. 템플릿 단순화와 이미지 최적화만 적용해도 스크롤 성능은 20, 40퍼센트까지 개선된다.

 

CollectionView Item Recycling


1. CollectionView Recycling이 깨지는 주요 원인 7가지

MAUI에서 재사용이 깨지는 원인은 크게 레이아웃, 템플릿, 바인딩, 이벤트, 구조적 문제로 나뉜다. 각 상황을 세밀하게 분석해 보자.


1,1 DataTemplateSelector 사용 시 재사용 중단

DataTemplateSelector는 항목마다 다른 Template을 반환하기 때문에 MAUI는 해당 Template을 캐싱하지 않는다. 그 결과 스크롤 시 매번 새로운 셀이 생성되어 병목이 발생한다.

해결책

  • 가능하면 Template을 통합하고 내부에서 조건 분기
  • 또는 TemplateSelector를 사용하되 가벼운 UI 구조로 최소화

1,2 Template 내부의 동적 HeightRequest 변경

셀의 높이가 스크롤 중 변경되면 레이아웃 엔진은 기존 셀을 재사용할 수 없다. 따라서 새로운 셀을 생성하게 된다.

해결책

  • HeightRequest는 고정값 또는 Auto로 통일
  • Expandable UI는 접힘 영역만 변경하고 전체 높이는 유지

1,3 GestureRecognizer가 여러 개 중첩된 경우

TapGestureRecognizer, SwipeGestureRecognizer가 너무 많이 붙어 있으면 셀의 이벤트 핸들러가 재사용 불가 상태가 된다.

해결책

  • GestureRecognizer는 한두 개만 사용
  • 버튼을 통한 이벤트 처리로 구조 단순화

1,4 BindableLayout 사용 시 재사용 중단

템플릿 내부에 BindableLayout이 있으면 내부 리스트의 크기에 따라 매번 렌더링이 발생한다. 이 구조는 Recycling의 이점을 거의 없앤다.

해결책

  • BindableLayout 제거
  • 필요한 경우 중첩 CollectionView로 분리
  • UI를 더 단순한 StackLayout 기반으로 변경

1,5 ControlTemplate 내부에서 Control이 동적으로 바뀌는 경우

Template 내에서 Content, Control 타입이 변하면 캐싱 불가 상태가 된다.

해결책

  • ControlTemplate 대신 VisualStateManager를 사용해 UI를 전환
  • 상태별 UI를 완전 별도로 만들지 말고 Visibility만 조정

1,6 ItemTemplate 내부에서 대형 Grid 구조 복잡도 문제

다음 요소가 누적될수록 재사용률이 떨어진다.

  • 다단 Grid
  • 중첩 StackLayout
  • 불필요한 Margin
  • RowDefinition과 ColumnDefinition 남용

레이아웃이 복잡할수록 MAUI는 셀을 재사용하기보다 새로운 셀을 만들려 한다.

해결책

  • Grid 한 개, VerticalStackLayout 한 개 정도로 단순화
  • Margin 최소화
  • Label이나 Image도 Row, Column을 간결하게 구성

1,7 항목별 UI가 너무 다르게 구성된 경우

예를 들어 특정 아이템만 이미지가 있고 다른 아이템은 버튼이 있는 구조는 Template을 깨트리는 대표적인 패턴이다.

해결책

  • 항목의 UI 구조를 동일하게 유지
  • 표시 여부는 IsVisible만 변경
  • 가능한 한 같은 구성의 템플릿 유지

CollectionView Item Recycling


2. 재사용을 보장하기 위한 최적화 패턴

이제 위 문제들에 대한 실무 최적화 패턴을 제시한다.


2,1 Template 캐싱 강제 적용

가장 강력한 방식은 DataTemplate을 미리 인스턴스화하는 것이다.

 
static readonly DataTemplate CachedTemplate = new(() => new MyItemView());

collectionView.ItemTemplate = CachedTemplate;
 
 

이 방식은 재사용률을 최대화한다.


2,2 ItemSizingStrategy 조정

가상화 성능은 셀 크기를 어떻게 계산하느냐에 따라 달라진다.

  • MeasureFirstItem
    첫 셀 크기만 재고 나머지는 동일하게 계산
  • MeasureAllItems
    모든 셀을 계산하기 때문에 대용량에서는 비추천
ItemSizingStrategy="MeasureFirstItem"

2,3 RowHeight 고정 전략

자동 높이보다 성능이 강력하게 올라간다.

HeightRequest="72"
 
 

UI 디자인을 고려해 적당한 값으로 고정하면 스크롤 성능이 크게 향상된다.


2,4 이미지 로딩 최적화

대부분의 셀 재사용 깨짐은 이미지 때문이므로 다음 조치를 적용해야 한다.

  • DownsampleToViewSize
  • CacheDuration
  • FadeAnimationDuration 최소화

2,5 이벤트 핸들러를 ViewModel로 이동

클릭 이벤트를 코드비하인드에서 잡으면 재사용률이 흔들릴 수 있다.
가능하면 Command 바인딩으로 통일한다.

예시.

<Button Text="삭제" Command="{Binding Source={RelativeSource AncestorType={x:Type local:MainViewModel}}, Path=DeleteCommand}" />
 
 

 


3. 재사용 깨짐 여부를 확인하는 디버깅 팁

간단한 Debug 코드만 추가해도 문제가 재사용인지 단순 렌더링인지 확인할 수 있다.

 
public MyItemView()
{
    InitializeComponent();
    Debug.WriteLine("Cell Created");
}
 
 

스크롤할 때 로그가 계속 찍힌다면 재사용이 깨졌다는 의미이다.


4. 실제 프로젝트 적용 시 체크리스트

1, TemplateSelector 사용 줄이기
2, Template 단순화
3, GestureRecognizer 최소화
4, HeightRequest 고정
5, BindableLayout 제거
6, 이미지 최적화 필수
7, 스크롤 중 상태 변경 UI 지양
8, Template 캐싱 적극 활용

이 체크리스트만 정확히 적용해도 스크롤 FPS가 30퍼센트 이상 개선된다

veedeeo
@veedeeo :: .net MAUI·Netlify·SEO·웹 최적화 기술 블로그

.net MAUI·Netlify·SEO·웹 최적화 기술 블로그

공감하셨다면 ❤️ 구독도 환영합니다! 🤗

목차