무엇이 문제였나: 후보 14건 중 13건이 무관했다
네이버 검색 API 정렬 옵션 하나가 수집 파이프라인 전체를 굶기고 있었습니다. 겉으로 드러난 증상은 단순했습니다. 스카우트가 매 회차 질문 후보를 가져오는데, 그중 답변을 달 만한 질문이 거의 없었습니다. 2026년 8월 16일 기록에는 “오늘 후보 14건 중 13건 무관”이라고 적혀 있습니다. 관련 있는 질문이 하루 1건이면 뒤에 붙은 초안 작성기와 품질 검사가 아무리 잘 돌아도 쓸 재료가 없습니다. 실제로 선정 단계를 통과하는 후보가 0건까지 내려갔습니다.
다음 날 대표가 물었습니다. “스카우트 후보를 더 많이 뽑아 놔야 하는 거 아니야?” 표면만 보면 맞는 말입니다. 후보가 적으면 더 많이 모으면 됩니다. 문제는 그 질문이 이미 답을 하나 정해 두고 있었다는 점입니다. 후보가 적은 이유가 공급량인지, 공급은 충분한데 엉뚱한 후보만 위로 올라오는지에 따라 해법이 정반대가 됩니다.
비용 문제도 함께 있었습니다. 스카우트는 검색 결과 목록만 보고 끝나지 않습니다. 쓸 만해 보이는 질문은 페이지를 직접 열어 답변 수와 작성일을 확인하고, 그다음 단계에서는 LLM이 후보를 채점합니다. 무관한 후보가 많을수록 쓸모없는 페이지 열기와 LLM 호출이 함께 늘어납니다. 시간과 돈을 쓰고도 결과는 0건인 구조였습니다.
처음 잰 숫자: 정렬만 바꾸면 결과가 어떻게 달라지나?
원인을 추측하기 전에 한 가지를 먼저 쟀습니다. 키워드는 그대로 두고 정렬만 바꿨습니다. 당시 스카우트는 네이버 검색 API의 지식iN 검색을 sort=date로만 호출하고 있었습니다. 같은 키워드를 sort=sim(관련도순)으로 한 번 더 호출해, 두 결과의 상위 10건 가운데 저희 서비스와 관련 있는 질문이 몇 건인지 셌습니다. 키워드 2개에 정렬 2종이라 호출은 4번이면 됐습니다. 측정 규모가 작다는 점은 알고 있었지만, 이 단계의 목적은 원인을 확정하는 일이 아니라 “정렬이 결과를 바꾸는가”라는 질문에 예·아니오를 얻는 일이었습니다. 정렬이 결과를 바꾸지 않았다면 매칭 문제를 의심하는 쪽으로 돌아가면 됩니다.
결과는 한쪽으로 크게 기울었습니다. “영업 관리 프로그램”은 sort=date에서 10건 중 3건, sort=sim에서 10건 중 10건이 관련 질문이었습니다. “홈페이지 제작 비용”도 똑같이 3건과 10건으로 갈렸습니다. 키워드도, API도, 호출 시각도 같았고 정렬 파라미터 하나만 달랐습니다.

두 번째로 잰 숫자는 공급량입니다. sort=sim으로 넓게 훑어 보니, 저희 키워드와 관련 있는데 스카우트가 한 번도 가져온 적 없는 질문이 1,414건 있었습니다. 그때까지 스카우트가 누적으로 수집한 질문은 631건이었습니다. 손대지 않은 풀이 이미 모은 양의 2.2배였다는 뜻입니다.

세운 가설: 검색 매칭이 느슨하니 키워드를 늘리자
숫자를 재기 전, 저희가 세운 가설은 두 개였습니다. 첫째, 네이버 검색 API가 키워드와 느슨하게 매칭하는 구조라서 무관한 질문이 섞인다. 8월 16일 기록은 실제로 이 결론에서 멈춰 있었습니다. “구조적 문제”라고 이름을 붙이면 더 파고들 이유가 사라집니다. 바깥 서비스의 동작이니 저희가 고칠 수 없다는 뜻이 되기 때문입니다.
둘째, 매칭이 느슨해서 관련 질문 비율이 낮다면 키워드를 늘려 모수를 키우자. 대표의 질문도 이 방향이었고, 저희에게는 이 방법이 통한 전례도 있었습니다. 2026년 7월 26일, 지식iN 신규 질문 유입이 하루 15건에서 2건으로 떨어졌을 때 키워드를 13개에서 21개로 늘렸습니다. 당시 키워드 일부가 이미 판매를 접은 서비스를 겨냥하고 있었고, 매출 기여가 큰 서비스(홈페이지 제작·AI 챗봇·블로그 운영 대행)에는 키워드가 하나도 없었습니다. 그 빈칸을 채우자 신규 후보가 2건에서 92건으로, 46배 늘었습니다.
전례가 있으니 같은 처방을 다시 쓰고 싶어지는 것이 자연스럽습니다. 하지만 7월의 문제는 커버리지 공백이었습니다. 겨냥할 키워드 자체가 없던 서비스에 키워드를 만들어 준 일입니다. 8월의 증상이 같은 종류인지는 확인하지 않은 상태였습니다.
가설은 어디서 틀렸나?
첫 번째 가설은 앞의 측정 하나로 무너졌습니다. API의 매칭 자체가 느슨하다면 sort=sim도 무관한 질문을 섞어 내야 합니다. 그런데 같은 키워드, 같은 API에서 sort=sim은 상위 10건을 전부 관련 질문으로 채웠습니다. 매칭은 문제가 아니었습니다. 결과를 어떤 순서로 줄을 세우느냐가 문제였습니다.
두 번째 가설도 같은 자리에서 틀렸습니다. 관련 질문 1,414건이 이미 손 닿는 곳에 있었으니 공급량은 병목이 아니었습니다. 이 상태에서 키워드를 늘리면 새 키워드도 똑같이 sort=date로 조회합니다. 새 키워드마다 무관한 질문이 위로 올라오는 현상이 그대로 복제되고, 페이지 열기와 LLM 채점 비용만 키워드 수에 비례해 커집니다.
비슷한 일은 다른 곳에서도 한 번 있었습니다. 2026년 8월 9일, 콘텐츠 주제를 공급하는 쪽에서 씨앗 키워드를 13개에서 34개로 늘렸습니다. 수확한 키워드는 5,978개에서 7,935개로 늘었지만, 실제로 쓸 수 있는 주제 목록의 순증은 1건이었습니다. 키워드 수는 입력일 뿐이고, 병목이 다른 곳에 있으면 입력을 늘려도 출력이 움직이지 않습니다.
병목이 공급량이 아니라 정렬축이라는 걸 모르고 키워드만 늘리면 같은 정렬 오염이 반복된다.
진짜 원인: sort=date는 질문이 아니라 답변 최신순이다
sort=date라는 이름만 보면 질문을 작성일 순으로 줄 세운다고 읽힙니다. 지식iN 검색에서 이 정렬은 질문 작성일이 아니라 답변이 달린 최신순으로 움직입니다. 그래서 키워드와 무관한 오래된 질문이라도, 누군가 최근에 단 답변 본문에 키워드 조각이 들어 있으면 결과 위쪽에 올라옵니다. “홈페이지 제작 비용”을 검색했는데 결과가 답변 속 한 문장 때문에 걸린 엉뚱한 질문으로 차는 식입니다.
더 부끄러운 대목이 있습니다. 이 동작은 저희가 몰랐던 사실이 아니었습니다. 2026년 8월 3일, 지식iN 검색의 sort=date가 답변 최신순이라는 함정을 이미 내부 지식 문서에 적어 두었습니다. 그런데 스카우트 코드는 그 뒤로도 sort=date만 썼고, 8월 16일의 진단은 그 기록과 증상을 잇지 못한 채 “API 구조 문제”로 끝났습니다. 적어 둔 지식이 코드와 진단 습관에 닿지 않으면 방어 수단이 되지 못합니다.
그렇다고 sort=sim으로 갈아타면 끝나는 문제도 아니었습니다. sort=sim은 순위가 안정적입니다. 오늘 상위 10건과 내일 상위 10건이 거의 같아서, 이것만 쓰면 새로 올라온 질문이 들어올 자리가 없습니다. sort=date는 관련도가 낮은 대신 새 질문을 데려오고, sort=sim은 관련도가 높은 대신 같은 질문만 반복해서 줍니다. 두 정렬이 서로의 약점을 메우는 관계였습니다.
조치 1: 두 정렬을 각자 돌려서 합친다
스카우트가 키워드마다 두 번 조회하도록 바꿨습니다. sort=date는 신선도 축으로 키워드당 20건을, sort=sim은 관련도 축으로 3페이지×30건을 가져옵니다. 두 결과는 지식iN 문서 번호(docId)로 중복을 지워 하나로 합칩니다.
두 조회를 한 목록으로 순회하지 않고 키워드마다 별도 루프로 나눈 이유가 있습니다. 한 목록으로 돌리면, sort=date 결과가 20건을 채우지 못하고 일찍 끝나 루프를 빠져나갈 때 그 키워드의 sort=sim 조회까지 함께 건너뜁니다. 질문이 적은 키워드일수록 sort=sim이 더 필요한데, 바로 그 키워드에서 sort=sim이 돌지 않는 구조가 됩니다. 루프를 나누면 한쪽이 일찍 끝나도 다른 쪽은 자기 몫을 끝까지 돕니다.

조치 2: 페이지를 열기 전에 answerNo로 거른다
sort=sim을 붙이자 새 문제가 보였습니다. 관련도가 높은 질문은 이미 답변이 많이 쌓인 질문인 경우가 많습니다. 지식iN은 한 질문에 답변이 8개 이상 달리면 답변 입력창을 내주지 않으므로, 그런 질문은 아무리 관련이 깊어도 쓸모가 없습니다. 실제로 sort=sim으로 새로 들어온 후보 1,313건 가운데 12%가 이 조건에 걸렸습니다.
답변 수를 알려면 보통 페이지를 열어야 합니다. 그런데 검색 결과에 이미 단서가 있었습니다. 검색 결과 링크에는 answerNo=N이라는 값이 붙는데, 이 값은 결과에 걸린 답변의 순번입니다. 그래서 페이지를 열지 않고도 “이 질문에는 답변이 최소 N개 있다”를 알 수 있습니다. 한 docId가 answerNo=3, 4, 5, 6, 7, 9, 10으로 결과에 7번 등장한 사례도 있었습니다. 링크 하나에서 정규식 한 줄로 뽑는 값이라 추가 비용이 들지 않습니다.
- answerNo가 8 이상인 후보는 페이지를 열지 않고 제외한다
- sort=sim 축은 관련도가 높은 대신 답변이 쌓인 질문에 쏠리므로, 이 필터가 특히 sort=sim 후보를 많이 걸러 낸다
- 이 필터는 LLM 채점보다 앞에 둔다. 공짜로 거를 수 있는 후보를 비싼 단계까지 보내지 않는다
LLM 채점 단계에서 답변 수까지 판단하게 하는 방법도 검토했지만 버렸습니다. 채점은 호출마다 비용이 들고, answerNo는 이미 손에 든 검색 결과에서 얻습니다. 비용이 0인 필터를 비용이 드는 단계 뒤에 두면 그 차이만큼 낭비입니다.
조치 3: 작성일 상한을 90일에서 365일로 넓힌다
스카우트에는 작성된 지 90일이 넘은 질문을 버리는 상한이 있었습니다. 이 값은 채택을 지키려고 정한 숫자였습니다. 채택은 질문자가 여러 답변 중 하나를 골라 주는 기능으로, 채택을 받으면 답변자 등급이 오릅니다. 오래된 질문일수록 질문자가 돌아와 채택할 가능성이 낮다고 보고 90일로 막아 둔 것입니다.
그런데 실측해 보니 그때까지 채택은 누적 0건이었고 등급도 그대로였습니다. 지키려던 가치가 실제로는 한 번도 생기지 않았습니다. 이 파이프라인이 실제로 버는 것은 검색 노출이었고, 검색 노출에는 질문의 나이가 상관없다고 판단했습니다. 상한을 바꾸면 얼마나 달라지는지도 쟀습니다. sort=sim으로 쌓인 후보 1,160건을 기준으로 표본 60건을 열어 확인한 결과, 90일을 유지하면 193건, 365일로 넓히면 502건이 남았습니다.

작은 부수 변경도 두 가지 넣었습니다. 회차당 페이지 열기 예산을 정하고, 예산을 넘긴 후보는 이미 본 목록에 적지 않고 다음 회차로 넘깁니다. 그리고 탈락이 확정된 후보(답변 과다·자주 묻는 질문·작성일 초과)도 이미 본 목록에 기록하게 했습니다. 이전에는 통과한 후보만 적어서, 회차마다 같은 탈락 후보의 페이지를 다시 열고 있었습니다. sort=date로 키워드당 10건 남짓 가져오던 시절에는 드러나지 않던 낭비지만, sort=sim이 붙어 신규 후보가 천 단위로 늘면 회차 시간을 통째로 잡아먹습니다.
| 대안 | 버린 이유 |
|---|---|
| 키워드를 더 늘린다 | 관련 질문 1,414건이 이미 방치돼 있었다. 정렬을 그대로 두면 새 키워드에도 같은 오염이 반복된다 |
| sort=sim으로 완전히 갈아탄다 | 순위가 안정적이라 매일 같은 상위를 준다. 새 질문 공급이 끊긴다 |
| 답변 수 판단을 LLM 채점에 맡긴다 | 채점은 호출 비용이 든다. answerNo는 검색 결과에서 정규식 한 줄로 공짜로 얻는다 |
고치다 생긴 실수: 예산 150건 중 111건이 버려졌다
첫 구현은 바로 통과하지 못했습니다. 초판에서는 페이지 열기 예산을 회차당 150건으로 잡고, 답변이 적은 질문부터 열도록 answerNo 오름차순으로 순서를 정했습니다. 답변이 적을수록 저희 답이 눈에 띌 테니 그쪽을 먼저 보자는 생각이었습니다.
돌려 보니 예산 150건 가운데 111건이 작성일 초과로 버려졌습니다. answerNo가 작은 질문은 sort=sim 쪽에 많았고, sort=sim은 작성일과 무관하게 관련도 높은 질문을 모으므로 오래된 질문 비율이 높았습니다. 페이지를 열어야 작성일을 알 수 있으니, 예산 대부분을 상한에 걸릴 질문을 여는 데 쓴 셈입니다. 신선한 축을 먼저 봐야 나이 초과로 버려질 확률이 낮다는 점을 놓쳤습니다.
순서를 sort=date 축 우선으로 다시 정렬하고, 예산을 회차당 250건으로 늘렸습니다. 이 실수는 “무엇을 거를지”만큼 “무엇부터 열지”가 비용을 좌우한다는 점을 보여 줍니다. 필터를 맞게 짜도 여는 순서가 틀리면 예산이 엉뚱한 곳에서 바닥납니다. 이 정정은 첫 회차를 돌려 단계별 탈락 사유를 세어 보고 나서야 드러났습니다.
재측정 결과: 수집 1,390건에서 초안 10건까지
고친 스카우트를 한 회차 돌려 단계별 숫자를 다시 쟀습니다. 두 정렬을 합쳐 수집한 질문이 1,390건, 그중 이미 본 목록에 없던 신규 후보가 59건이었습니다. 59건이 필터와 채점을 거쳐 10건이 선정됐고, 이 10건은 회차당 선정 상한에 닿은 값입니다. 선정된 10건은 초안 작성 단계에서 10건 모두 초안이 나왔습니다.

발행을 기다리는 대기 큐는 3건에서 10건으로 늘었습니다. 남은 백로그 967건은 회차마다 페이지 열기 예산 250건씩 소화합니다. 이전에는 선정 0건, 하루 후보 14건 중 관련 1건이었으니 같은 키워드 목록으로 출력이 상한까지 올라온 셈입니다.
치른 비용도 숫자로 남깁니다. 페이지 열기 예산 250건 때문에 한 회차 실행 시간이 1분 42초로 늘었습니다. sort=date만 쓰던 시절에는 몇 초였습니다. sort=sim을 3페이지씩 조회하느라 API 호출도 회차당 최대 96회가량 늘었습니다. 네이버 검색 API의 하루 쿼터는 25,000회라 여유는 충분합니다.
| 항목 | 전 | 후 |
|---|---|---|
| 정렬 | sort=date만 | sort=date 20건 + sort=sim 3페이지×30건 |
| 상위 10건 중 관련 질문 | 3건 | 10건 (sort=sim, 키워드 2개 실측) |
| 작성일 상한 | 90일 | 365일 |
| 답변 8개 이상 질문 | 페이지를 열어서 확인 | answerNo로 열기 전에 제외 |
| 회차당 선정 | 0건 | 10건 (상한 도달) |
| 대기 큐 | 3건 | 10건 |
| 회차 실행 시간 | 몇 초 | 1분 42초 |
남는 한계: 이 개선이 아직 증명하지 못한 것은 무엇인가?
재측정은 한 회차뿐입니다. 선정 10건이 상한에 닿았다는 사실은 공급이 충분하다는 뜻이지만, 그 10건이 품질 검사를 지나 실제 발행까지 가는지는 이 측정에 들어 있지 않습니다. 또 지금의 출력은 그동안 쌓인 백로그 967건을 꺼내 쓰는 덕을 보고 있습니다. 백로그를 다 소화한 뒤에도 매 회차 새로 들어오는 질문만으로 선정이 유지되는지, 아니면 다시 0건으로 돌아가는지는 8월 19일에 다시 확인하기로 했습니다.
작성일 상한 365일도 가정 위에 서 있습니다. “채택이 0건이니 질문 나이는 상관없다”는 판단은 채택을 포기한 상태에서만 성립합니다. 채택을 다시 목표로 삼으면 같은 숫자가 반대 방향을 가리킬 수 있습니다. 실제로 질문 나이와 채택의 관계는 이후 따로 다시 쟀고, 그 과정은 지식인 채택률 2.8%의 원인에 정리했습니다. 365일과 90일 비교도 표본 60건에서 나온 값이라 전체 1,160건에 그대로 맞는다고 장담할 수 없습니다.
가장 오래 남을 교훈은 기술보다 습관 쪽에 있습니다. sort=date의 동작은 2주 전에 이미 기록돼 있었는데, 증상을 “바깥 API의 구조 문제”로 정리하는 순간 그 기록을 다시 열 이유가 사라졌습니다. 바꿀 수 없는 원인으로 결론을 내리기 전에, 바꿀 수 있는 변수(이번에는 정렬 파라미터 하나)를 한 번 돌려 보는 편이 훨씬 쌉니다. 이번에는 키워드 2개에 호출 4번이면 충분했습니다.
네이버 검색 API나 비슷한 검색 API로 수집 파이프라인을 운영하는데 후보만 쌓이고 쓸 만한 질문이 없다면, 키워드 목록보다 정렬 옵션과 필터 순서를 먼저 열어 보길 권합니다. 비슷한 자동화를 설계하는 중이거나 운영하다 막힌 상황이라면 상담으로 알려 주세요.