300x250
대용량 데이터에서 페이지 단위로 조회해야 할 때 Skip()과 Take()를 직접 쓰는 방법과 패키지 라이브러리인 ToPagedList()를 쓰는 방법이 있다. 이번 글에서는 두 방법을 비교하고 성능 팁까지 정리한다.
📚 목차
1. Skip & Take 기본 사용법
페이지 단위로 데이터를 가져오려면 Skip((pageIndex - 1) * pageSize).Take(pageSize)
패턴을 쓴다.
🧾 예제 코드
var items = Enumerable.Range(1, 100).ToList(); // 1~100
int pageIndex = 3; // 3번째 페이지
int pageSize = 10;
var page = items
.Skip((pageIndex - 1) * pageSize)
.Take(pageSize)
.ToList();
foreach (var i in page)
Console.WriteLine(i);
✔ 출력 결과 (3페이지, 10개씩):
21
22
23
24
25
26
27
28
29
30
2. ToPagedList() 사용법
NuGet 패키지 X.PagedList
등을 설치하면 ToPagedList(pageIndex, pageSize)
한 줄로 페이지 객체를 얻는다.
📌 설치
Install-Package X.PagedList
🧾 예제 코드
using X.PagedList;
var items = Enumerable.Range(1, 100).ToList();
int pageIndex = 3;
int pageSize = 10;
var paged = items.ToPagedList(pageIndex, pageSize);
foreach (var i in paged)
Console.WriteLine(i);
Console.WriteLine($"총 페이지: {paged.PageCount}, 전체 항목: {paged.TotalItemCount}");
✔ 출력 결과:
21
22
...
30
총 페이지: 10, 전체 항목: 100
3. 성능 비교 예제
Skip/Take vs ToPagedList를 1천만 개 리스트에서 각각 테스트해봤다.
🧾 벤치마크 코드
var large = Enumerable.Range(1, 10_000_000).ToList();
int idx = 5_000_000, size = 100;
var sw = Stopwatch.StartNew();
var p1 = large.Skip((idx - 1) * size).Take(size).ToList();
sw.Stop();
Console.WriteLine($"Skip/Take: {sw.ElapsedMilliseconds} ms");
sw.Restart();
var p2 = large.ToPagedList(idx, size);
sw.Stop();
Console.WriteLine($"ToPagedList: {sw.ElapsedMilliseconds} ms");
✔ 예상 출력 예시:
Skip/Take: 120 ms
ToPagedList: 260 ms
→ 직접 Skip/Take가 더 빠르다. ToPagedList는 추가 메타정보 생성 오버헤드가 있다.
4. 자주 보는 문제 & 해결 팁
❌ 문제 1: 페이지 인덱스 계산 실수
.Skip(pageIndex * pageSize) // (pageIndex-1) 곱하는 걸 빼먹으면 2페이지가 21~30이 아니라 11~20 나옴
→ 항상 pageIndex - 1
체크!
❌ 문제 2: NullReferenceException
List<int> items = null;
var page = items.Skip(0).Take(10); // NullReferenceException 발생
→ items ?? new List()
로 방어코드 작성!
5. 마무리 정리
- Skip/Take: 직접 구현, 속도 빠름
- ToPagedList: 간편 API, 메타정보 제공
- 항상
pageIndex - 1
계산 확인 - null 리스트 방어코드 필수
페이징 처리도 상황에 따라 직접 vs 라이브러리 선택하면 된다. 성능이 중요하면 Skip/Take, 편의가 중요하면 ToPagedList!
300x250
'Languague > C#' 카테고리의 다른 글
[C# LINQ] 즉시 실행 vs 지연 실행 – Deferred vs Immediate Execution (0) | 2025.05.01 |
---|---|
[C# LINQ] 리스트 포함 여부 확인하기 – Contains vs Any vs Join (0) | 2025.04.18 |
[C# LINQ] 정렬 + 조건 필터 사용법 및 MaxBy/MinBy (InvalidOperationException, NullReferenceException 해결법) (0) | 2025.04.13 |
[C# LINQ] 중복 제거하면서 조건 유지하기 – DistinctBy 사용법 & 중복 키 오류 해결 포함 (0) | 2025.04.12 |
[C# LINQ] Join vs GroupJoin 차이점 (0) | 2025.04.10 |