콘텐츠 갭 자동화: 15개의 쿼리로 GSC에서 Dev.to까지
요약
Google Search Console(GSC) 데이터를 활용하여 콘텐츠 갭을 자동으로 식별하고, Claude 3.5 Sonnet과 OCI Functions를 통해 기사를 생성 및 발행하는 자동화 파이프라인 구축 사례를 소개합니다.
핵심 포인트
- GSC 데이터를 기반으로 노출은 높으나 클릭이 낮은 '콘텐츠 갭'을 정밀하게 정의
- OCI Functions와 Python 에이전트 프레임워크를 활용한 워크플로우 오케스트레이션
- 비용 효율적인 LLM 라우팅을 통해 기사당 발행 비용을 0.05달러 미만으로 절감
- 단순 텍스트 생성이 아닌 데이터 기반의 타겟 키워드 발굴 프로세스 구축
원문은 AIdeazz에 처음 게시되었으며, 정식 링크(canonical link)와 함께 이곳에 교차 게시되었습니다.
나의 첫 번째 AI 콘텐츠 파이프라인 시도는 유의미한 변화를 만들어내는 데 실패했습니다. 두 달 동안 30개의 기사를 작성하고 120달러의 API 비용을 지출했지만, Google Search Console (GSC)는 타겟 키워드에 대해 새로운 노출(impressions)을 전혀 보여주지 않았습니다. 핵심 문제는 LLM(대규모 언어 모델)의 출력이 아니라 입력값이었습니다. "콘텐츠 갭 (Content gap)"은 마케팅 용어이지 엔지니어링 사양이 아닙니다. 개발자에게 콘텐츠 갭이란 노출은 높지만 클릭은 낮고, 해당 쿼리에 대해 순위가 매겨진 기존 페이지가 없는 특정 GSC 쿼리를 의미합니다. 나의 시스템은 단순히 더 많은 텍스트를 생성하는 것이 아니라, 바로 그러한 갭을 찾아내야 했습니다.
이 글은 Oracle Cloud Infrastructure (OCI)에서 실행되는 나의 자동화된 발행 파이프라인의 현재 버전을 자세히 설명합니다. 이 프로세스는 GSC 데이터로 시작하여, 초안 작성을 위해 Claude 3.5 Sonnet을 사용하며, Dev.to와 나의 사이트인 aideazz.xyz에 게시합니다. 갭 식별부터 발행에 이르는 전체 과정은 인간의 개입 없이 실행되며, 기사당 비용은 0.05달러 미만입니다.
갭 식별: GSC 쿼리 필터
초기 GSC 데이터 추출은 간단합니다. GSC API를 통해 지난 90일간의 성능 데이터를 쿼리하는 것입니다. 과제는 필터링입니다. 나의 첫 번째 실수는 주관적인 지표인 "경쟁이 낮은" 키워드를 찾는 것이었습니다. 이제 나는 콘텐츠 갭에 대한 정밀한 정의에 집중합니다:
- 노출 (Impressions) > 500: 해당 쿼리가 상당한 검색량을 가지고 있습니다.
- 클릭 (Clicks) < 50: 사용자들이 쿼리를 보고 있지만, 내 사이트로 클릭하여 들어오지 않습니다.
- CTR (클릭률) < 1%: 낮은 클릭률을 확인합니다.
- 평균 순위 (Average Position) > 20: 나의 기존 콘텐츠가 이 쿼리에 대해 순위가 높지 않습니다.
- 해당 쿼리에 대해 순위가 매겨진 기존 페이지 없음: 이 부분이 결정적입니다. 나는 쿼리를 나의 사이트맵 및 기존 GSC 페이지 데이터와 교차 참조합니다. 만약 어떤 페이지가 이 쿼리에 대해 순위가 낮더라도 이미 매겨져 있다면, 그것은 갭이 아니라 최적화 대상입니다.
이 필터는 aideazz.xyz와 같은 사이트의 경우 일반적으로 한 달에 10~20개의 실행 가능한 쿼리를 생성합니다. 각 쿼리는 잠재적인 기사 주제가 됩니다. 예를 들어, 최근에 식별된 갭은 "OCI free tier always free limits"였습니다. 제 사이트에는 OCI에 관한 콘텐츠가 있었지만, 해당 문구에 대한 노출수(impressions)가 높았음에도 불구하고 무료 티어의 *제한 사항(limits)*에 특화된 내용은 없었습니다.
OCI Functions 및 Groq/Claude 라우팅을 통한 오케스트레이션 (Orchestration)
전체 파이프라인은 일일 크론 잡(cron job)에 의해 트리거되는 일련의 OCI Functions로 구성됩니다. 저는 비용과 작업 복잡도에 따라 요청을 서로 다른 LLM으로 라우팅하는 커스텀 Python 에이전트 프레임워크를 사용합니다.
핵심 에이전트는 다음과 같습니다:
GSC_Analyzer: GSC 데이터를 가져오고, 갭 필터를 적용하며,(query, impressions, clicks, position)튜플 리스트를 출력합니다.Topic_Generator: 각 갭 쿼리에 대해, 이 에이전트는 속도를 위해 Groq에서 실행되는 작고 미세 조정된(fine-tuned) Llama 3 8B 모델을 사용하여 쿼리를 3~5개의 잠재적인 기사 제목과 짧은 2문장 요약으로 확장합니다. 이 단계는 초안 작성 LLM에 충분한 문맥(context)을 제공하는 데 매우 중요합니다.Article_Drafter: 이 단계는 Claude 3.5 Sonnet이 빛을 발하는 부분입니다. 이 에이전트는Topic_Generator로부터 선택된 제목과 요약을 전달받습니다. 프롬프트는 특정 마크다운(markdown) 형식을 강제하고, 관련 있는 경우 코드 예시를 포함하며, 기술적이고 회의적인(skeptical) 톤을 유지하도록 구조화되어 있습니다. 저는 Claude 3.5 Sonnet이 해당 가격대의 다른 모델들과 비교했을 때 장문의 구조화된 기술 콘텐츠 작성에 있어 더 우수하다는 것을 발견했습니다. 이 모델의 컨텍스트 윈도우(context window)는 상세한 지침과 참조 자료를 잘 처리합니다.SEO_Optimizer: 초안이 작성된 기사를 가져와 의미적 유사성(semantic similarity)을 기반으로 기존aideazz.xyz콘텐츠에 대한 3~5개의 내부 링크를 제안하는 더 작은 에이전트입니다 (마찬가지로 Groq 기반의 Llama 3를 사용합니다). 또한 메타 설명(meta description)과 5개의 관련 태그를 생성합니다.Publisher: 이 에이전트는 실제 게시 작업을 처리합니다.
이 시스템은 게시를 위해 Dev.to API를 사용하며, aideazz.xyz에 정적 HTML 페이지를 생성하기 위해 커스텀 스크립트를 사용하고, 이는 Cloudflare에 의해 캐싱됩니다.
라우팅 로직은 간단합니다. 작업이 짧고 복잡도가 낮으며 지연 시간(latency)에 민감한 경우(제목 생성이나 내부 링크 연결 등)에는 Groq으로 전달됩니다. 만약 긴 형식의 콘텐츠 생성(long-form content generation)이거나 복잡한 추론(complex reasoning)이 필요한 경우에는 Claude로 전달됩니다. 이러한 하이브리드 접근 방식은 비용을 낮게 유지하면서 처리량(throughput)을 높게 유지합니다. 기사당 평균 LLM 비용은 Claude의 경우 $0.03, Groq의 경우 $0.01이며, 여기에 OCI Function 실행 비용이 추가됩니다.
Claude 3.5 Sonnet 초안 작성 프롬프트 (Drafting Prompt)
Article_Drafter를 위한 프롬프트는 매우 구조화되어 있습니다. 이는 단순히 "기사를 작성하라"는 식이라기보다 "이러한 제약 사항을 준수하면서, 특정 콘텐츠로 이 마크다운(markdown) 섹션들을 채워라"에 가깝습니다.
당신은 개발자를 위한 전문 기술 작가(technical writer)입니다. 당신의 작업은 [TOPIC]에 대해 상세하고, 회의적이며, 실용적인 기사를 작성하는 것입니다.
기사는 최소 1200단어 이상이어야 합니다.
다음 구조를 사용하십시오:
...
이 프롬프트는 편집이 거의 필요 없는 기사를 일관되게 생성합니다. "실패/제약 사항을 먼저 제시하라(lead with failure/constraint)"는 지침은 적절한 톤을 설정하고 주의를 끄는 데 특히 효과적입니다.
Dev.to 및 aideazz.xyz로의 자동 게시
기사가 초안 작성되고 최적화되면, Publisher 에이전트가 업무를 인계받습니다.
Dev.to의 경우, 저는 API를 사용하여 새 포스트를 생성합니다. 기사 콘텐츠는 마크다운(Markdown) 형식으로 전송됩니다. SEO_Optimizer 에이전트가 제목, 태그, 그리고 (aideazz.xyz를 가리키는) 표준 URL(canonical URL)을 제공합니다. 이를 통해 Dev.to가 기본 소스가 아닌 배포 채널로서 작동하도록 보장합니다.
aideazz.xyz의 경우, 프로세스가 약간 더 복잡합니다. 제 사이트는 커스텀 Python 스크립트에 의해 생성되는 정적 사이트(static site)입니다. Publisher 에이전트는:
_posts디렉토리에 새로운 Markdown 파일을 생성합니다.- 제목(title), 날짜(date), 태그(tags), 메타 설명(meta description)이 포함된 YAML 프론트매터(YAML front matter)를 추가합니다.
- 정적 사이트 생성기(static site generator)를 실행합니다.
- 업데이트된 사이트를 OCI Object Storage 버킷에 푸시(push)하며, 이후 OCI CDN을 통해 서비스됩니다.
이러한 설정 덕분에 aideazz.xyz는 항상 최신 콘텐츠를 유지하며, CDN은 빠른 글로벌 전송을 보장합니다. 전체 게시 프로세스는 30초 미만이 소요됩니다.
결과 및 향후 반복 (Results and Future Iterations)
이 정교해진 파이프라인을 3개월 동안 운영한 결과, 유망한 성과를 거두었습니다. 매달 생성되는 15~20개의 기사는 이제 일관되게 특정 GSC 갭(gaps)을 타겟팅합니다. 이러한 타겟 쿼리에 대해 유기적 노출(organic impressions)이 15% 증가했으며, 전체 사이트 클릭(clicks)은 3% 증가했습니다. 기사당 비용은 0.05달러 미만으로 유지되어 확장성이 매우 높습니다.
다음 단계의 반복은 피드백 루프(feedback loop)에 집중할 것입니다. 현재 시스템은 갭을 식별하고 게시할 뿐입니다. 저는 게시된 기사의 GSC 성과를 모니터링하다가, 60일 후에도 성과가 저조할 경우 Article_Reviser 에이전트를 트리거하는 에이전트를 구축하고 싶습니다. 이 에이전트는 성과가 낮은 기사의 GSC 데이터를 분석하여 새로운 하위 갭(sub-gaps)이나 관련 쿼리를 식별한 다음, Claude를 사용하여 기사의 섹션을 다시 쓰거나 확장할 것입니다. 이는 단순히 게시하는 것을 넘어 지속적인 최적화로 나아가는 루프를 완성합니다. 여기서의 과제는 불필요한 재작성을 피할 수 있도록 "성과 저조"를 충분히 정밀하게 정의하는 것입니다.
자주 묻는 질문 (Frequently Asked Questions)
Q: Dev.to와 본인 사이트 간의 중복 콘텐츠 문제를 어떻게 처리하나요?
A: Dev.to의 canonical URL 기능을 사용하여 모든 포스트가 aideazz.xyz의 원본 기사를 가리키도록 합니다. 이를 통해 검색 엔진에 aideazz.xyz가 기본 소스임을 알려 중복 콘텐츠 페널티를 방지합니다.
Q: LLM이 잘못된 기술 정보나 코드를 생성하면 어떻게 하나요?
A: 이는 실제적인 위험 요소입니다. 중요한 주제의 경우, 새로운 도메인의 초기 5~10개 기사에 대해서는 사람의 검토(human review) 단계를 거칩니다. 해당 도메인에 대한 LLM의 정확성에 대한 신뢰가 구축되면, 사람의 감독을 줄입니다. 코드의 경우, 저는 주로 보일러플레이트(boilerplate)나 잘 알려진 패턴을 위해 LLM을 사용하며, 새로운 알고리즘을 만드는 데 사용하지는 않습니다.
Q: 왜 AWS/GCP/Azure 대신 Oracle Cloud Infrastructure (OCI)를 사용하나요?
A: OCI의 상시 무료 계층(always-free tier)은 비용을 발생시키지 않고도 OCI Functions 및 정적 사이트 호스팅을 실행하기에 충분한 관대한 컴퓨팅 및 스토리지 리소스(4 OCPU, 24GB RAM, 200GB 블록 스토리지)를 제공합니다. 이는 벤처 캐피털(VC) 투자 없이 초기 구축(bootstrapping)을 하는 데 있어 결정적인 요소였습니다.
Q: LLM이 주제에서 벗어나거나 환각(hallucination)을 일으키는 것을 어떻게 방지하나요?
A:
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기