메인 콘텐츠로 건너뛰기

최근 검색 페이지네이션

소개

검색 쿼리는 보통 단일 API 응답에 포함될 수 있는 것보다 더 많은 포스트와 일치합니다. 이런 경우 데이터는 여러 개의 ‘페이지’로 나뉘어 반환됩니다. 페이지네이션은 전체 데이터 세트를 가져오기 위해 이 모든 페이지를 순차적으로 요청하는 방법을 의미합니다. 다음은 최근 검색 페이지네이션의 기본 사항입니다.
  • 최근 검색 엔드포인트는 쿼리에 대해 최소 한 페이지로 응답하며, 추가 페이지가 있을 경우 JSON 응답에 next_token을 제공합니다. 일치하는 포스트를 모두 받기 위해, 응답에 더 이상 토큰이 포함되지 않을 때까지 이 과정을 반복할 수 있습니다.
  • next_token은 만료되지 않습니다. 동일한 next_token 값을 사용한 여러 요청은, 요청 시점과 관계없이 동일한 결과를 받게 됩니다.
  • 포스트는 UTC 타임존 기준으로 최신순(역순)으로 전달됩니다. 이는 개별 페이지 내에서도, 여러 페이지 전체에 걸쳐서도 동일합니다:
    • 첫 번째 응답에서 첫 번째 포스트는 쿼리와 일치하는 가장 최신 포스트입니다.
    • 마지막 응답에서 마지막 포스트는 쿼리와 일치하는 가장 오래된 포스트입니다.
  • max_results 요청 파라미터를 사용하면, 응답마다 반환되는 포스트 수를 설정할 수 있습니다. 기본값은 포스트 10개이며, 최대값은 100입니다.
  • 모든 페이지네이션 구현에는 응답 페이로드에서 next_token 값을 파싱하고, 이를 ‘다음 페이지’ 검색 요청에 포함하는 과정이 포함됩니다. 이러한 ‘다음 페이지’ 요청을 구성하는 방법에 대한 자세한 내용은 아래를 참고하세요.  
최근 검색 엔드포인트는 두 가지 기본 사용 패턴을 지원하도록 설계되었습니다.
  • Get historical - 관심 있는 기간 동안의 일치하는 포스트를 요청하는 패턴입니다. 보통 역사적/과거 데이터 분석을 지원하기 위한 일회성 요청에 해당합니다. 검색 요청은 start_time 및 end_time 요청 파라미터를 기반으로 할 수 있습니다. 최근 검색 엔드포인트는 쿼리와 일치하는 가장 최신 포스트부터 시작하여, 포스트를 최신순(역순)으로 반환합니다.
  • Polling - 마지막으로 받은 포스트 이후에 게시된 일치하는 포스트를 요청하는 패턴입니다. 이러한 사용 사례는 대개 준실시간 성격을 가지며, 관심 있는 새로운 포스트를 ‘청취(listening)’하기 위한 빈번한 요청이 특징입니다. 최근 검색 엔드포인트는 이 ‘polling’ 패턴을 지원하기 위해 since_id 요청 파라미터를 제공합니다. 포스트 id를 기준으로 범위를 탐색할 수 있도록 until_id 요청 파라미터도 함께 사용할 수 있습니다.  
다음으로, historical 모드에 대해 설명하겠습니다. 이는 최근 검색 엔드포인트의 기본 모드이며, 페이지네이션의 기본 개념을 보여 줍니다. 그다음으로 polling 사용 사례의 예시를 다룹니다. polling으로 인해 페이지네이션이 발생하는 경우, 검색 요청을 관리하기 위한 추가 단계가 필요합니다.  

과거 데이터 검색

이 섹션에서는 start_time 및 end_time 요청 매개변수를 사용해 관심 있는 기간(현재는 최근 7일로 제한) 동안의 포스트를 조회하는 방법을 설명합니다. 과거 데이터 요청은 일반적으로 연구 및 분석을 지원하기 위한 일회성 요청입니다.  기간을 지정해 데이터를 요청하는 방식은 recent search 엔드포인트의 기본 동작입니다. search 요청에서 start_time, end_time 또는 since_id 요청 매개변수를 지정하지 않으면 end_time은 기본적으로 “지금”(실제로는 쿼리 시점 30초 전)으로 설정되고, start_time은 기본적으로 7일 전으로 설정됩니다. 엔드포인트는 가장 최근 포스트부터 시작해 역시간순으로 정렬된 첫 번째 ‘페이지’의 포스트를 반환합니다. 응답 JSON 페이로드에는 추가 데이터 페이지가 있는 경우 next_token도 포함됩니다. 일치하는 포스트의 전체 집합을 페이지 수와 관계없이 모두 수집하려면 next_token이 더 이상 제공되지 않을 때까지 요청을 반복해서 보내면 됩니다.  예를 들어, 지난 일주일 동안 키워드 snow가 포함된 포스트에 대한 초기 요청은 다음과 같습니다: https://api.x.com/2/tweets/search/recent?query=snow 응답에는 가장 최근 10개의 포스트와 함께 JSON 응답의 “meta” 속성이 포함됩니다:
"meta": {
        "newest_id": "1204860593741553664",
        "oldest_id": "1204860580630278147",
        "next_token": "b26v89c19zqg8o3fobd8v73egzbdt3qao235oql",
        "result_count": 10
    }
다음 10개의 포스트를 가져오려면 이 next_token 값을 원래 요청에 추가합니다. 요청은 다음과 같습니다: https://api.x.com/2/tweets/search/recent?query=snow&next_token=b26v89c19zqg8o3fobd8v73egzbdt3qao235oql next_token을 확인해 이후 요청에 포함하는 과정을, 모든(또는 특정 개수의) 포스트를 수집할 때까지, 또는 정해진 횟수만큼 요청을 보낼 때까지 반복할 수 있습니다. 데이터 완전성(쿼리와 일치하는 모든 결과를 수집하는 것)이 해당 사용 사례에서 중요하다면, 단순한 “request.next_token이 null이 될 때까지 반복” 설계면 충분합니다.

폴링 및 리스닝 사용 사례

이 섹션에서는 since_id 요청 매개변수를 사용하여 최근 검색 엔드포인트를 폴링해 최근 포스트를 가져오는 방법을 설명합니다.  폴링 사용 사례에서는 “새로운 관심 포스트가 있나요?”와 같은 쿼리를 지속적이고 빈번하게 수행합니다. 시간에 기반해 요청을 보내는 과거 데이터 사용 사례와 달리, 폴링 사용 사례는 일반적으로 포스트 ID를 기준으로 요청을 보냅니다. 폴링 사용 패턴의 핵심은 X 플랫폼에서 생성되는 모든 새로운 포스트에는 일반적으로 오름차순으로 ‘부여’되는 고유 ID가 있다는 점입니다. 한 포스트의 ID가 다른 포스트의 ID보다 작다면, 더 먼저 게시되었다는 의미입니다. 최근 검색 엔드포인트는 포스트 ID를 기준으로 포스트 아카이브를 탐색할 수 있도록 지원합니다. 이 엔드포인트의 응답에는 oldest_idnewest_id 포스트 ID가 포함됩니다. 폴링 모드에서는 지금까지 수신한 ID 중 가장 큰(가장 최신) ID를 since_id로 설정해 요청을 보냅니다.  예를 들어, 눈(snow)에 대한 새 포스트를 5분마다 조회하고 있고, 마지막으로 수신한 포스트의 포스트 ID가 10000이라고 가정해 보겠습니다. 폴링 시점에 요청은 다음과 같습니다: https://api.x.com/2/tweets/search/recent?query=snow&since_id=10000 다음으로, 마지막 요청 이후에 7개의 포스트가 새로 게시되었다고 가정해 보겠습니다. 이 모든 포스트가 하나의 데이터 ‘페이지’에 담기므로 next_token은 없습니다. 응답에는 가장 최근(최신) 포스트의 포스트 ID가 제공됩니다:
"meta": {
        "newest_id": "12000",
        "oldest_id": "10005",
        "result_count": 7
    }
다음 폴링 쿼리를 수행할 때는 이 newest_id 값을 사용해 다음 since_id 파라미터를 설정합니다: https://api.x.com/2/tweets/search/recent?query=snow&since_id=12000 추가로 사용할 수 있는 데이터가 있고, next 토큰이 제공되는 경우에는 결과의 첫 페이지에 있는 newest_id 값만 있으면 됩니다. 각 데이터 페이지에는 newest_id와 oldest_id 값이 모두 포함되지만, 다음 정기 폴링 요청에 필요한 값은 첫 페이지에서 제공된 값뿐입니다. 따라서 폴링 방식을 설계하거나 ID 범위로 포스트를 검색하는 경우, 페이지네이션 로직은 조금 더 복잡해집니다.  이제 일치하는 포스트가 18개 더 있다고 가정해 보겠습니다. 이 엔드포인트는 이 5분 구간에서 다음 데이터 페이지를 요청할 수 있도록 전체 데이터 페이지와 next_token이 포함된 초기 응답을 반환합니다. 또한 5분 뒤 다음 폴링 주기에 필요한 최신 포스트 ID도 함께 포함합니다.
"meta": {
        "newest_id": "13800",
        "oldest_id": "12500",
        "next_token": "fnsih9chihsnkjbvkjbsc",
        "result_count": 10
    }
이 5분 구간의 모든 일치하는 데이터를 수집하려면, 다음 요청에서 이전 요청과 동일한 since_id 값과 함께 next_token을 전달하세요. https://api.x.com/2/tweets/search/recent?query=snow&since_id=12000&next_token=fnsih9chihsnkjbvkjbsc
"meta": {
        "newest_id": "12300",
        "oldest_id": "12010",
        "result_count": 8
    }
두 번째 응답은 나머지 8개의 포스트를 반환하며, next_token은 포함되지 않습니다. newest_id 값(12300)은 업데이트하지 않고, 대신 첫 번째 응답의 newest_id 값을 기준으로 다음 since_id 요청을 보냅니다: https://api.x.com/2/tweets/search/recent?query=snow&since_id=13800