ONE QUESTION AT A TIME.

천천히 생각하고, 분명하게.

TODAY’S QUESTION371 / 1500
데이터베이스난이도 하5분 답변 목표 · 보강본

주문 목록에서 OFFSET으로 뒤 페이지를 열수록 느려집니다. 마지막 주문의 시각과 ID를 커서로 쓰면 어떻게 달라지나요?

잠깐, 답변을 보기 전에
먼저 내 말로 설명해 볼까요?

답변과 점검 포인트 펼치기답변 접기
01

구두 답변

정의를 외우기보다, 원리와 조건을 연결해 설명해 보세요.

OFFSET 방식은 앞의 행을 데이터베이스가 찾아 정렬한 뒤 버리고 다음 행을 반환하는 형태이므로, 뒤 페이지일수록 건너뛸 행이 많아질 수 있습니다. 반환 행이 20개라는 사실은 실제로 읽은 행이 20개라는 뜻이 아닙니다. 연속해서 더 보기 하는 대량 목록이라면 마지막 행의 정렬 키를 커서로 전달하는 키셋 페이지네이션(keyset pagination)을 선택하겠습니다. 정렬 인덱스의 다음 위치에서 바로 읽을 수 있어 페이지 번호가 커져도 접근 범위를 상대적으로 일정하게 만들 수 있습니다.

정렬은 유일하고 재현 가능해야 합니다

주문을 created_at DESC, id DESC로 정렬한다고 하겠습니다. 다음 요청은 마지막 행의 시각과 ID를 받아 PostgreSQL식으로 다음과 같이 표현할 수 있습니다.

SELECT id, created_at, customer_id, total_amount
FROM orders
WHERE (created_at, id) < (:last_created_at, :last_id)
ORDER BY created_at DESC, id DESC
LIMIT :page_size;

여기서 콜론은 설명용 바인딩 자리입니다. created_at이 NULL이 아니고 id가 유일하다고 가정해야 합니다. 행 비교식을 지원하지 않는 DBMS에서는 created_at < :t OR (created_at = :t AND id < :id)로 풀어 씁니다. 두 컬럼의 정렬 방향이 섞이면 단순 행 비교가 맞지 않을 수 있어 정규화한 키나 별도 표현을 사용합니다.

시각 하나만 커서로 쓰면 같은 시각의 주문을 건너뛰거나 중복으로 읽을 수 있습니다. ID를 보조 키로 둔 것은 단지 성능을 위한 것이 아니라 전체 순서를 결정하기 위한 것입니다. 필터 조건도 커서 계산과 같은 요청에 묶어야 합니다. 커서에는 마지막 키뿐 아니라 필터·정렬 버전·테넌트 범위가 포함될 수 있고, 사용자가 임의로 바꾸지 못하게 서명하거나 서버가 검증해야 합니다.

최신성 계약과 DB 엔진을 구분합니다

키셋이 자동으로 일관된 전체 스냅샷을 제공하는 것은 아닙니다. 다음 페이지를 읽기 전에 새 주문이 앞쪽에 삽입되면 이미 본 페이지와 겹치지는 않아도 사용자는 목록 시점에 따라 다른 결과를 볼 수 있습니다. 정렬 키가 수정되면 행이 앞으로 이동해 누락되거나, 이미 본 행이 다시 나타날 수 있습니다. 엄격한 스냅샷이 필요하면 DBMS의 스냅샷 트랜잭션, 별도의 목록 스냅샷 등을 설계해야 하며, 기준 시각이나 불변 정렬 키만으로는 행 삭제·내용 변경까지 모두 고정하지 못합니다. 또한, 긴 트랜잭션은 버전 유지 비용을 만듭니다.

PostgreSQL의 행 비교와 MVCC, SQL Server의 격리 수준, MySQL/InnoDB의 클러스터링과 인덱스 접근은 세부 동작이 다릅니다. 실제 엔진에서 EXPLAIN 또는 실행 계획으로 정렬 제거, 읽은 행 수, 인덱스 범위를 확인하겠습니다. 키셋은 임의의 300번째 페이지로 바로 이동하거나 정확한 전체 페이지 수를 매번 보여 주는 요구에는 자연스럽지 않습니다. 그런 관리 화면은 별도 카운트·점프 전략과 비용을 정하겠습니다. 검증은 같은 정렬 값, 삽입, 삭제, 정렬 키 변경, 중복 커서 재전송을 섞어 계약 범위 안의 누락·중복을 측정하는 방식으로 하겠습니다.

커서가 클라이언트에 노출되는 API라면 내부 키를 그대로 드러내는지, 만료·권한 범위를 어떻게 묶는지도 결정해야 합니다. 커서가 이전 필터와 다르면 같은 키라도 결과 의미가 바뀌므로 서버에서 서명 검증하거나 불일치를 거부하겠습니다. 삭제는 이미 본 행을 되돌리지 않지만, 수정 가능한 정렬 키는 이동을 만들 수 있습니다. 정렬 키를 불변으로 만들거나 목록 기준 시각을 고정하는 선택을 비용과 함께 비교하겠습니다.

02

득점 포인트

이해가 드러나는 지점을 확인해 보세요.

  • OFFSET의 반환량과 실제 건너뛴 읽기 비용을 구분한다.
  • 유일한 보조 정렬 키와 복합 커서 조건을 구성한다.
  • 페이지 이동 요구와 최신성·스냅샷 계약을 분리한다.
03

감점 포인트

놓치기 쉬운 조건과 오해를 짚어 보세요.

  • 인덱스가 있으면 OFFSET 비용이 항상 일정하다고 말한다.
  • 시각 하나를 커서로 써 동률 행의 누락을 허용한다.
  • 키셋이 모든 동시 변경에서 전체 스냅샷이라고 단정한다.
04

더 파고들 거리

하나 더 질문하며 이해의 범위를 넓혀 보세요.

득점·감점 포인트는 학습용 자기 점검 기준이며, 특정 회사의 실제 채점표가 아닙니다.

원리부터 공부하고 싶다면

답변을 보충하는 개념·예제·슈도코드를 읽어 보세요.

← 전체 질문 보기