Languague/C# / / 2025. 5. 2. 08:00

[C# LINQ] 페이징 처리 – Skip, Take vs ToPagedList 성능 비교

300x250

대용량 데이터에서 페이지 단위로 조회해야 할 때 Skip()Take()를 직접 쓰는 방법과 패키지 라이브러리인 ToPagedList()를 쓰는 방법이 있다. 이번 글에서는 두 방법을 비교하고 성능 팁까지 정리한다.

 

📚 목차

  1. 1. Skip & Take 기본 사용법
  2. 2. ToPagedList() 사용법
  3. 3. 성능 비교 예제
  4. 4. 자주 보는 문제 & 해결 팁
  5. 5. 마무리 정리

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
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유