5.9 KiB
5.9 KiB
NHN 모듈 가이드
NHN은 uGUI 기반 무한 스크롤(InfiniteScroll) 컴포넌트 라이브러리입니다. 대량 데이터 목록을 효율적으로 렌더링하기 위해 아이템을 재활용(recycling)합니다.
참고: 새 UI는 UI Toolkit의
ListView/TreeView가상화 기능을 권장합니다. 이 모듈은 uGUI 기반 레거시 프로젝트용입니다.
파일 구조
NHN/
├── InfiniteScroll.cs # 메인 클래스 (partial)
├── InfiniteScroll.ItemContainer.cs # 아이템 컨테이너 관리
├── InfiniteScroll.ItemData.cs # 데이터 컨텍스트
├── InfiniteScroll.Layout.cs # 레이아웃 계산
├── InfiniteScroll.Scroll.cs # 스크롤 처리
├── InfiniteScrollItem.cs # 아이템 베이스 클래스
├── InfiniteScrollData.cs # 데이터 베이스 클래스
├── ScrollLayout.cs # 레이아웃 설정
├── ScrollMoveTo.cs # 스크롤 이동 유틸리티
├── LayoutUpdater.cs # 레이아웃 업데이트
├── DraggableRect.cs # 드래그 가능한 영역
├── DragEventHandler.cs # 드래그 이벤트 처리
└── ContentSizeSetter.cs # 콘텐츠 크기 설정
핵심 클래스
InfiniteScroll
uGUI ScrollRect 기반의 무한 스크롤 컴포넌트입니다.
namespace Gpm.Ui
{
public partial class InfiniteScroll : MonoBehaviour
{
// 이벤트
public ChangeValueEvent onChangeValue; // 스크롤 값 변경
public ItemActiveEvent onChangeActiveItem; // 아이템 활성화 변경
public StateChangeEvent onStartLine; // 시작점 도달
public StateChangeEvent onEndLine; // 끝점 도달
}
}
기본 사용법
1. 데이터 삽입
// 단일 데이터 삽입
InfiniteScrollData myData = new MyScrollData();
infiniteScroll.InsertData(myData, immediately: true);
// 다중 데이터 삽입
InfiniteScrollData[] dataArray = new InfiniteScrollData[100];
infiniteScroll.InsertData(dataArray, immediately: true);
// 특정 인덱스에 삽입
infiniteScroll.InsertData(myData, insertIndex: 0, immediately: true);
2. 데이터 제거
// 데이터 객체로 제거
infiniteScroll.RemoveData(dataToRemove, immediately: true);
// 인덱스로 제거
infiniteScroll.RemoveData(dataIndex: 0, immediately: true);
3. 데이터 초기화
// 데이터만 초기화 (아이템 객체 유지)
infiniteScroll.ClearData(immediately: true);
// 완전 초기화 (아이템 객체도 제거)
infiniteScroll.Clear();
4. 데이터 업데이트
// 단일 데이터 업데이트
InfiniteScrollData existingData = infiniteScroll.GetData(0);
// ... 데이터 수정 ...
infiniteScroll.UpdateData(existingData);
// 전체 새로고침
infiniteScroll.UpdateAllData(immediately: true);
이벤트 처리
// 스크롤 값 변경 (첫 번째/마지막 보이는 인덱스)
infiniteScroll.onChangeValue.AddListener((first, last, isStart, isEnd) => {
Debug.Log($"Visible: {first}~{last}, Start: {isStart}, End: {isEnd}");
});
// 아이템 활성화 상태 변경
infiniteScroll.onChangeActiveItem.AddListener((dataIndex, isActive) => {
Debug.Log($"Item {dataIndex} is {(isActive ? "active" : "inactive")}");
});
// 시작/끝 도달
infiniteScroll.onStartLine.AddListener((isAtStart) => {
if (isAtStart) LoadPreviousPage();
});
infiniteScroll.onEndLine.AddListener((isAtEnd) => {
if (isAtEnd) LoadNextPage();
});
필터링
// 필터 설정
infiniteScroll.SetFilter(data => {
MyCustomData myData = data as MyCustomData;
return myData.score > 50; // 점수 50 이상만 표시
});
// 필터 적용 후 업데이트
infiniteScroll.UpdateAllData(immediately: true);
스크롤 제어
// 특정 아이템 위치로 이동
float position = infiniteScroll.GetItemPosition(itemIndex: 10);
// 뷰포트/콘텐츠 크기
float viewportSize = infiniteScroll.GetViewportSize();
float contentSize = infiniteScroll.GetContentSize();
float contentPos = infiniteScroll.GetContentPosition();
// 수동 새로고침
infiniteScroll.RefreshScroll();
infiniteScroll.ResizeScrollView();
커스텀 데이터/아이템 구현
데이터 클래스
public class MyScrollData : InfiniteScrollData
{
public string title;
public int score;
public Sprite icon;
}
아이템 클래스
public class MyScrollItem : InfiniteScrollItem
{
[SerializeField] private Text titleText;
[SerializeField] private Image iconImage;
public override void UpdateData(InfiniteScrollData scrollData)
{
base.UpdateData(scrollData);
if (scrollData is MyScrollData myData)
{
titleText.text = myData.title;
iconImage.sprite = myData.icon;
}
}
}
성능 최적화
| 항목 | 설명 |
|---|---|
| 아이템 재활용 | 화면에 보이는 아이템만 생성, 나머지는 풀에서 재활용 |
| 즉시 업데이트 | immediately: true로 즉시 레이아웃 갱신 |
| 필터링 | 서버 필터링 권장, 클라이언트 필터는 대량 데이터 시 주의 |
| 아이템 프리팹 | 가볍게 유지, 복잡한 UI는 지연 로딩 고려 |
UI Toolkit 마이그레이션
새 프로젝트에서는 UI Toolkit의 ListView 사용을 권장합니다:
// UI Toolkit ListView (권장)
var listView = new ListView();
listView.makeItem = () => new Label();
listView.bindItem = (element, index) => {
(element as Label).text = items[index].title;
};
listView.itemsSource = items;
InfiniteScroll → ListView 마이그레이션 시:
InfiniteScrollData→ 일반 데이터 클래스InfiniteScrollItem→makeItem/bindItem콜백- 이벤트 → ListView 이벤트 (
selectionChanged등)