[SQL] 쿼리테스트5 - LIMIT + OFFSET 기반 페이징 방식 알고 가기

Hyunjun Kim·2026년 2월 9일

SQL

목록 보기
95/98

1. 문제

다음과 같은 사용자 테이블이 존재한다.

CREATE TABLE users (
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(50) NOT NULL
);

아래 쿼리는 사용자 목록을 페이지 단위로 조회하기 위해 사용된다.

SELECT *
FROM users
ORDER BY username
LIMIT 5 OFFSET 15;

이와 같은 LIMIT + OFFSET 기반 페이징 방식에 대해 올바른 설명을 모두 고르시오.

(복수 선택 가능)

A. 이 쿼리는 5번부터 15번까지의 행을 반환한다.
B. 결과의 일관성을 보장하려면 반드시 ORDER BY 절이 필요하다.
C. OFFSET 값이 커질수록 성능 저하가 발생할 수 있다.
D. LIMIT 절 자체는 성능에 부정적인 영향을 준다.


2. 정답

정답은 B, C 이다.

선택지정답 여부
A
B
C
D

이제 왜 그런지 하나씩 해부하자.


2.0 쿼리 자체부터 정확히 해석하기

SELECT *
FROM users
ORDER BY username
LIMIT 5 OFFSET 15;

이 쿼리의 의미는 다음과 같다.

username 기준으로 정렬된 결과에서
앞에서 15개를 건너뛰고(skip)
그 다음 5개 행을 반환하라

즉,

  • OFFSET = “몇 개를 버릴 것인가”
  • LIMIT = “몇 개를 가져올 것인가”

이다.


2.1 선택지 A

❌ “이 쿼리는 5–15번 행을 반환한다”

이 문장은 아주 흔한 오해다.

실제 반환 범위

OFFSET 15 → 앞의 15개 행을 버림
LIMIT 5   → 그 다음 5개를 가져옴

👉 반환되는 것은 16번째부터 20번째 행

번호처리
1 ~ 15건너뜀
16 ~ 20반환

따라서
❌ “5–15번 행”이라는 설명은 완전히 틀리다.


2.2 선택지 B

✅ “결과의 일관성을 보장하려면 ORDER BY가 필요하다”

이건 핵심 정답이다.

ORDER BY가 없으면 무슨 일이 생길까?

SELECT * FROM users LIMIT 5 OFFSET 15;
  • SQL 표준에서 정렬 순서는 보장되지 않는다
  • MySQL은 내부 실행 계획, 인덱스 상태에 따라 매번 다른 순서로 결과를 반환할 수 있다

즉,

  • 1페이지에서 봤던 행이
  • 2페이지에서 다시 나오거나
  • 어떤 행은 아예 건너뛰어질 수 있다

결론

페이지네이션에서 ORDER BY는 선택이 아니라 필수이다.

그래서 이 선택지는 이다.


2.3 선택지 C

✅ “OFFSET 값이 커질수록 성능 저하가 발생한다”

이건 실무에서 아주 중요한 포인트다.

MySQL 엔진 관점에서 보면

LIMIT 5 OFFSET 100000;

MySQL은 내부적으로 이렇게 한다.

  1. 정렬 수행 (ORDER BY username)
  2. 앞의 100,000개 행을 읽고 버림
  3. 그 다음 5개만 반환

👉 버리는 행도 전부 읽는다

즉,

  • OFFSET이 커질수록
  • 디스크 I/O 증가
  • CPU 사용 증가
  • 응답 시간 증가

그래서 실무에서는

  • OFFSET 기반 페이지네이션은 뒤 페이지로 갈수록 느려진다
  • 대용량 테이블에서는 keyset pagination (seek method) 를 사용한다

따라서 이 선택지는 이다.


2.4 선택지 D

❌ “LIMIT 절 자체는 성능에 부정적인 영향을 준다”

이 문장은 그럴듯해 보이지만 틀렸다.

왜 틀렸나?

  • LIMIT은 “얼마나 가져올지”를 제한하는 역할
  • 오히려 결과 집합을 줄여서 네트워크·메모리 사용량을 감소시킨다

성능 문제의 원인은:

  • LIMIT
  • OFFSET + 큰 값 ⭕️
  • 정렬 대상 컬럼에 인덱스 없음 ⭕️

따라서

LIMIT 자체가 느린 게 아니라
OFFSET이 문제다

이 선택지는 거짓이다.


3. 한 문장으로 정리하면

LIMIT + OFFSET 기반 페이지네이션은 구현은 간단하지만,
OFFSET 값이 커질수록 성능 저하가 발생하며,
결과의 일관성을 보장하기 위해 ORDER BY 절이 반드시 필요하다.


4. 실무 연결 포인트

이 문제의 숨은 의도는 이거다.

  • OFFSET 페이징의 한계 이해 여부
  • ORDER BY 없는 페이징의 위험성 인지 여부
  • 대안(keyset pagination)을 알고 있는지

5. OFFSET 대신 WHERE + 마지막 키(Keyset Pagination)가 빠른 이유

5.1 문제의 출발점: OFFSET 기반 페이징의 한계

다음과 같은 쿼리는 흔히 사용되는 페이지네이션 방식이다.

SELECT *
FROM users
ORDER BY username
LIMIT 5 OFFSET 100000;

이 방식은 OFFSET 기반 페이지네이션이라 불린다.
구현은 간단하지만, 데이터가 많아질수록 심각한 성능 문제가 발생한다.


5.1 OFFSET 방식이 느려지는 이유

MySQL 엔진은 위 쿼리를 다음 순서로 처리한다.

  1. username 기준으로 전체 결과를 정렬한다.
  2. 정렬된 결과 중 앞의 100,000개 행을 읽고 버린다.
  3. 그 다음 5개 행만 반환한다.

이때 중요한 점은 다음과 같다.

  • 버려지는 100,000개 행도 실제로는 전부 읽는다
  • OFFSET 값이 커질수록 읽고 버리는 작업이 선형적으로 증가한다
  • 뒤 페이지로 갈수록 쿼리는 점점 느려진다

즉, OFFSET 방식은 페이지 번호가 커질수록 비효율이 누적되는 구조이다.


5.3 WHERE + 마지막 키 방식이란 무엇인가

이를 해결하기 위한 방식이 Keyset Pagination (Seek Method) 이다.

핵심 아이디어는 단순하다.

“앞의 N개를 버리지 말고,
이전 페이지의 마지막 값 이후부터 바로 조회하자

예를 들어 이전 페이지의 마지막 username 값이 'mike'라면 다음 페이지는 다음과 같이 조회한다.

SELECT *
FROM users
WHERE username > 'mike'
ORDER BY username
LIMIT 5;

5.4 왜 이 방식이 빠른가

1) OFFSET이 사라진다

Keyset 방식에서는

OFFSET n → 없음

이 된다.

즉,

  • “앞의 N개를 읽고 버리는 작업” 자체가 존재하지 않는다
  • 필요한 범위만 바로 읽는다

2) 인덱스를 그대로 활용할 수 있다

다음 조건이 만족되면 성능은 극적으로 개선된다.

CREATE INDEX idx_users_username ON users(username);

이 경우 MySQL은

  • 인덱스를 이용해 'mike' 이후 위치로 즉시 이동
  • 그 지점부터 5개만 순차적으로 읽는다

이는 내부적으로 B-Tree의 특정 노드로 바로 seek하는 동작이다.


3) 처리 비용이 일정하다

OFFSET 방식:

페이지가 뒤로 갈수록 점점 느려짐 (O(n))

Keyset 방식:

항상 일정한 속도 유지 (O(page_size))

즉, 1페이지든 10만 페이지든 읽는 행 수는 거의 동일하다.


5.5 두 방식의 성능 차이 요약

구분OFFSET 방식Keyset 방식
읽는 행 수OFFSET + LIMITLIMIT
뒤 페이지 성능급격히 저하일정
인덱스 활용제한적매우 효율적
대용량 데이터부적합적합

5.6 실무에서 Keyset Pagination이 특히 중요한 이유

OFFSET 방식은 다음 상황에서 문제가 된다.

  • 사용자 목록
  • 로그 데이터
  • 거래 내역
  • 메시지 타임라인
  • 이벤트 스트림

이런 데이터들은 공통적으로

  • 행 수가 많고
  • 뒤로 갈수록 조회될 가능성이 있으며
  • 최신 데이터가 계속 추가된다

Keyset 방식은 이런 상황에서 사실상 표준이다.


5.7 주의할 점 (Keyset의 제약)

Keyset Pagination에도 조건이 있다.

1) 정렬 기준이 반드시 고정되어야 한다

ORDER BY username (고정)

정렬 기준이 바뀌면 페이지 연속성이 깨진다.


2) 유니크하지 않은 컬럼은 보조 키가 필요하다

username이 중복 가능하다면 다음과 같이 보완한다.

WHERE (username, id) > ('mike', 123)
ORDER BY username, id
LIMIT 5;

이는 정렬의 결정성을 보장하기 위함이다.


5.8 한 문장으로 정리

OFFSET 기반 페이지네이션은 앞의 행을 모두 스캔해야 하므로 페이지가 뒤로 갈수록 느려지지만,
Keyset Pagination은 인덱스를 이용해 마지막 키 이후로 바로 탐색하기 때문에 대용량 데이터에서도 일정한 성능을 유지한다.

profile
Data Analytics Engineer 가 되

0개의 댓글