MongoDB 커서와 페이지네이션
2026년 8월 28일
MongoDB 커서와 페이지네이션
find()는 결과를 주지 않는다. 커서(cursor)를 준다. 커서는 "서버에 있는 결과 집합을 가리키는 손잡이"다.- 그래서
find()에는await가 없고, 소비할 때 네트워크가 오간다.
Python
Mermaid스크롤로 확대 · 드래그로 이동
세 가지 소비 방법
Python
to_list(length=None)은 전부 메모리에 올린다. 컬렉션이 커지면 그 순간 서버가 죽는다. 우리 코드가 항상 length=를 명시하는 이유다.
sort · skip · limit
Python
체인 순서는 상관없다. 서버가 항상 sort → skip → limit 순으로 처리한다.
Python
정렬에는 인덱스가 필요하다. 없으면 메모리에서 정렬하는데, MongoDB는 여기에 32MB 상한을 두고 넘으면 쿼리를 거부한다(Sort exceeded memory limit). 정렬 필드는 복합 인덱스에 포함시킨다.
skip 페이지네이션의 함정
Python
skip은 건너뛴 문서를 실제로 다 읽는다. 뒤로 갈수록 선형으로 느려진다. 100페이지째가 1페이지째보다 100배 느리다.
커서 페이지네이션 (keyset)
Python
| skip/limit | keyset | |
|---|---|---|
| 깊은 페이지 성능 | 선형으로 악화 | 일정 |
| 임의 페이지 점프 | 가능 | 불가 (다음/이전만) |
| 중간에 삽입되면 | 항목이 밀려 중복·누락 | 안정적 |
무한 스크롤·로그 조회는 keyset이 정답이다. _id는 생성순에 가깝게 정렬되므로 커서 키로 쓰기 좋다.
count_documents 주의
Python
전체 개수 표시 때문에 매 페이지마다 count_documents를 부르면 그게 병목이 된다. 우리 시딩 검증처럼 정확한 수가 판단 근거일 때만 쓴다 (Seed 배포와 멱등 동기화).
한 줄 정리
find()는 커서를 주고, 소비할 때 batch로 흐른다. to_list에는 항상 length를, 깊은 페이지에는 skip 대신 keyset을 쓴다.
관련
- MongoDB CRUD 메서드
- MongoDB 쿼리 연산자
- projection
- 복합 인덱스
- motor
- explain과 실행 계획
- MongoDB MOC