워드프레스는 별도 설정 없이 wp-json으로 글 목록을 내줍니다. 그래서 사이트의 글을 통째로
모아야 할 때 가장 먼저 손이 갑니다. 그런데 일부만 들어오고 조용히 끝나는 경우가 있습니다.
에러도 안 나고 결과도 그럴듯해서, 몇백 건이 빠진 걸 한참 뒤에야 알게 됩니다.
/wp-json/wp/v2/posts?per_page=50&page=2&_fields=link,title,excerpt
_fields로 필요한 항목만 받으면 응답이 훨씬 가벼워집니다. 본문(content)까지
받으면 글 하나가 수십 KB가 되므로, 목록을 만드는 게 목적이라면 빼는 편이 낫습니다.
per_page는 최대 100입니다. 더 큰 수를 넣어도 100으로 잘립니다.
그래서 per_page만 키우고 page를 넘기지 않으면
101번째 글부터는 없는 셈이 됩니다. 요청은 성공하고 결과도 오기 때문에 실패로 보이지 않습니다.
실무에서는 100보다 낮게 잡는 편이 안전합니다. 항목을 많이 담을수록 응답이 커지고,
요약(excerpt)이 긴 사이트에서는 타임아웃이 먼저 납니다.
마지막 페이지를 넘어서 요청하면 빈 배열이 아니라 HTTP 400이 돌아옵니다.
응답 코드는 rest_post_invalid_page_number입니다.
HTTP 오류에서 예외를 던지는 방식으로 요청 함수를 짰다면, 마지막 페이지에서 그 예외가 터집니다. 루프 전체를 감싸지 않았다면 지금까지 모은 수백 건이 통째로 날아갑니다. 400은 실패가 아니라 정상 종료 신호로 다뤄야 합니다.
while (page <= MAX) {
try {
const items = await fetchPage(page);
if (!items.length) break; // 빈 응답도 종료
all.push(...items);
page++;
} catch (e) {
if (isPageExhausted(e)) break; // 400 = 여기까지가 끝
throw e; // 그 외는 진짜 실패
}
}
2번을 처리하고 나면 새로운 문제가 생깁니다. 모든 예외를 종료로 처리해 버리는 것입니다. 네트워크가 느려 3페이지에서 타임아웃이 났는데 그걸 "페이지 소진"으로 읽으면, 루프는 얌전히 끝나고 결과는 성공으로 보입니다. 실제로는 4페이지 이후가 전부 빠진 채로요.
그래서 종료 판정은 400인지 확인해서 해야 합니다. 그리고 400이 아닌 이유로 중단했다면 그 사실을 결과에 남겨야 합니다 — "몇 건 수집" 옆에 "중간에 끊겼음, 사유"가 같이 보여야 나중에 숫자를 믿을 수 있습니다.
수집 도구에서 제일 위험한 실패는 에러가 나는 실패가 아니라, 성공한 척하는 실패입니다.
보안 플러그인이 REST API를 막아둔 사이트도 흔합니다. 그럴 때 다음 후보는 사이트맵인데,
거기에도 함정이 있습니다 — /sitemap.xml을 먼저 찔러보면 안 됩니다.
사이트맵을 못 찾는 이유에서 따로 정리했습니다.
이 글은 EonsFlow가 블로그 자동화 도구를 만들며 겪은 내용을 정리한 것입니다. 워드프레스 버전과 설치된 플러그인에 따라 동작이 다를 수 있습니다.