Skip to main content
페이지 넘기기는 스크래퍼의 탐색 계층입니다. 스크래퍼가 한 페이지를 가져오고 렌더링하고 추출할 수 있게 된 뒤에도 실용적인 질문에 답해야 합니다. 다음 레코드 묶음은 어디에 있으며, 더 이상 데이터가 없다는 것을 어떻게 알 수 있을까요? 대부분의 페이지 넘기기 실패는 모든 사이트를 번호가 매겨진 페이지 목록처럼 취급할 때 발생합니다. 실제로 카탈로그는 URL 매개변수, 다음 버튼, 무한 스크롤, 더 보기 버튼, API 오프셋 또는 불투명한 커서 토큰을 사용할 수 있으며, 여러 패턴을 조합하는 사이트도 있습니다.

UI가 아닌 요청부터 확인하기

페이지 넘기기 로직을 작성하기 전에 DevTools를 열고 다음 데이터 묶음으로 이동할 때 무엇이 바뀌는지 확인하세요.
  1. Network 탭을 열고 Fetch/XHR로 필터링합니다.
  2. 다음 페이지를 클릭하거나 아래로 스크롤하거나 더 보기 버튼을 누릅니다.
  3. 요청 URL, 쿼리 매개변수, 요청 본문, 응답을 검사합니다.
  4. 스크래퍼가 링크를 따라갈지, 페이지와 상호작용할지, API 엔드포인트를 직접 호출할지 결정합니다.
UI는 단서로 활용하되 네트워크 요청을 신뢰하세요. “더 보기” 버튼이 단순한 offset=40 API를 호출할 수 있습니다. 페이지 링크도 URL 변경 후 JavaScript를 통해 결과를 실제로 하이드레이션할 수 있습니다.

번호 페이지

번호 페이지는 다음 위치가 URL에 표시되므로 가장 단순한 경우입니다.
스크래퍼는 페이지 번호를 늘리면서 응답에 항목이 없거나, 예상보다 항목이 적거나, 알려진 404/빈 상태 페이지가 나타날 때 중지할 수 있습니다.
페이지 인덱스가 0에서 시작하는 경우, p 또는 start 같은 매개변수 이름, 페이지 번호가 범위를 벗어났을 때 첫 페이지를 다시 반환하는 사이트에 주의하세요. 첫 페이지 반복은 명확한 오류 없이 중복 데이터를 만들 수 있으므로 빈 페이지보다 더 위험합니다.

다음 링크

일부 사이트는 페이지 번호 없이 “다음” 링크나 화살표만 제공합니다. 요소가 일반 앵커라면 링크를 따라가는 방식으로 처리하세요.
seen_urls 보호 장치는 중요합니다. 잘못 설정된 사이트는 마지막 “다음” 링크가 현재 페이지나 첫 페이지를 가리키기도 합니다. 링크를 신뢰하기 전에 aria-disabled="true", disabled 또는 disabled 클래스 같은 비활성화 상태도 확인하세요.

무한 스크롤

무한 스크롤은 브라우저만의 문제처럼 보이지만 일반적으로 그 아래에 API가 있습니다. DevTools를 연 상태에서 한 번 스크롤하여 다음 레코드 묶음을 가져오는 요청을 찾으세요. 유용한 매개변수 이름은 대개 offset, page, after, cursor 또는 limit입니다. 엔드포인트를 사용할 수 있다면 직접 호출하세요.
인증, 서명된 매개변수 또는 복잡한 클라이언트 측 상태 때문에 페이지 밖에서 API를 호출하기 어려울 때만 브라우저를 사용하세요.
무한 스크롤에서는 페이지 높이에만 의존하지 마세요. 광고, 이미지, 가상화된 목록으로 인해 높이가 계속 바뀔 수 있습니다. 항목 수, 네트워크 유휴 상태, 최대 스크롤 횟수를 조합하는 편이 더 안전합니다.

더 보기 버튼

더 보기 버튼은 제어 가능한 무한 스크롤입니다. 다음 데이터 묶음을 요청하기 전에 페이지가 클릭을 기다립니다. 스크래퍼가 대기하고 새 항목 수를 검증하며 요청 실패 시 재시도할 수 있어 속도 조절이 더 쉽습니다. 버튼이 깔끔한 API를 호출한다면 해당 API를 사용하세요. 그렇지 않다면 브라우저 루프에서 버튼을 클릭합니다.
중요한 검사는 단순히 “버튼을 클릭했는지”가 아니라 “새 레코드가 나타났는지”입니다. 버튼은 조용히 실패하거나 비활성화되거나 마지막 묶음 이후에도 계속 표시될 수 있습니다.

오프셋 및 커서 API

최신 사이트는 API 계층에서 데이터를 페이지로 나누는 경우가 많습니다. 오프셋 페이지 넘기기는 숫자 위치를 요청합니다.
커서 페이지 넘기기는 이전 응답이 반환한 다음 불투명 토큰을 요청합니다.
스크래핑 중 레코드가 추가되거나 제거될 때는 커서 페이지 넘기기가 더 안정적입니다. 커서는 “처음 40행을 건너뛰기” 대신 “알려진 이 위치 다음부터 계속하기”를 뜻합니다.
API 페이지 넘기기에서는 속도 제한을 명시적으로 처리하세요. Retry-After를 준수하고, 일시적인 실패에는 백오프를 적용해 재시도하며, 첫 페이지부터 다시 시작하는 비용이 큰 대규모 작업이라면 진행 상황을 저장하세요.

혼합 페이지 넘기기

실제 사이트는 여러 패턴을 조합하는 경우가 많습니다.
  • 카테고리는 번호 페이지를 사용하지만 각 페이지에서 스크롤 후 제품을 추가로 지연 로드합니다.
  • 검색 페이지가 더 보기 버튼으로 시작한 뒤 번호 링크로 전환됩니다.
  • 탭 인터페이스의 “신규”, “인기”, “할인”에 각각 별도의 페이지 넘기기가 있습니다.
  • 목록 페이지는 결과 URL을 페이지로 나누고, 각 상세 페이지의 리뷰 또는 댓글도 별도로 페이지가 나뉩니다.
이를 중첩 루프로 처리하세요. 외부 루프는 더 큰 탐색 단위를 담당하고, 각 내부 루프는 하나의 반복 작업을 담당하게 합니다. 전체 실행에서 고유 ID를 추적하여 중복 레코드가 결과에 섞이지 않도록 하세요.

실용적인 보호 장치

  • 중지 신호를 정의하세요. 빈 결과 집합, 누락된 다음 링크, 비활성화된 버튼, hasNextPage: false, 반복되는 커서, 최대 반복 횟수는 모두 유효한 중지 신호입니다.
  • 중복을 감지하세요. 무한 스크롤과 커서 API는 실행 중 데이터가 변경되면 레코드를 반복할 수 있습니다. 안정적인 ID 또는 표준 URL을 저장하세요.
  • 탐색 속도를 조절하세요. 각 데이터 묶음 사이에 짧고 무작위인 대기 시간을 추가하세요. 브라우저 자동화는 고정 타임아웃만 기다리지 말고 콘텐츠 변경을 기다려야 합니다.
  • 실패를 기록하세요. 재시도 후에도 페이지가 실패하면 URL 또는 커서를 기록하고 가능하면 계속 진행하세요.
  • 합법적이고 안정적인 API를 우선 사용하세요. 직접 API로 페이지를 넘기면 일반적으로 브라우저를 구동하는 것보다 빠르고 검증하기 쉽습니다.
  • 맞춤 코드보다 속도가 중요하면 시각적 도구를 사용하세요. Octoparse에서는 일반적인 다음 페이지, 더 보기, 무한 스크롤 흐름을 시각적으로 설정한 뒤 로컬이나 클라우드에서 실행할 수 있습니다.
페이지 넘기기는 단지 “다음 페이지로 이동”하는 것이 아니라 스크래퍼의 제어 루프입니다. 이 루프에 명확한 다음 단계 로직, 신뢰할 수 있는 중지 조건, 중복 방지 기능이 있으면 스크래퍼가 첫 페이지에서 조용히 멈추거나 끝없이 반복하지 않고 사이트 전체를 이동할 수 있습니다.