AI

CrewAI 및 Bright Data를 활용한 GEO 콘텐츠 최적화

CrewAI, Gemini, Bright Data를 활용한 고급 다중 에이전트 시스템을 통해 AI 및 기존 검색 엔진에 최적화된 페이지 콘텐츠 제작 방법을 알아보세요.
7 분 읽기
GEO with Query Fan-Out and SERP Comparison blog image

이 튜토리얼에서는 다음을 배웁니다:

  • 쿼리 팬아웃(query fan-out)과 Google AI 개요 비교를 기반으로 한 접근 방식이 GEO 및 SEO 개선에 어떻게 활용될 수 있는지.
  • – 6개의 AI 에이전트를 활용하여 이 워크플로를 고수준으로 구축하는 방법
  • CrewAI를 활용하여 Gemini 및 Bright Data와 통합된 AI 콘텐츠 최적화 워크플로우 구현 방법.
  • 워크플로우를 더욱 향상시키기 위한 아이디어와 조언.

시작해 보겠습니다!

TL;DR

바로 사용 가능한 프로젝트 파일로 넘어가고 싶으신가요? GitHub에서 프로젝트를 확인하세요.

더 나은 GEO 및 SEO를 위한 쿼리 팬아웃 및 AI 개요 비교 설명

우리 모두는 SEO(검색 엔진 최적화)가 유기적 검색 결과에서 웹사이트의 가시성을 개선하는 기술이라는 것을 알고 있습니다. 그러나 세상은 이제 GEO(생성형 엔진 최적화)로 전환되고 있습니다.

GEO에 익숙하지 않다면, 이는 Google AI 개요, ChatGPT 등과 같은 AI 기반 검색 엔진 내에서 콘텐츠의 가시성을 높이는 데 초점을 맞춘 디지털 마케팅 전략입니다.

An example of a Google AI Overview

LLM(대규모 언어 모델)은 본질적으로 블랙박스이기 때문에, 키워드 검색량 분석 도구가 등장하기 전의 SEO와 마찬가지로 웹 페이지를 GEO에 맞게 ‘최적화’하는 직접적인 방법은 존재하지 않습니다.

실증적 접근법을 따를 있습니다: 실제 AI 생성 요약문과 대상 키워드의 쿼리 팬아웃(query fan-out)을 분석하세요. 특정 검색어에 대해 AI 결과에 특정 주제가 반복적으로 등장한다면, 해당 주제를 중심으로 페이지 콘텐츠를 최적화해야 합니다.

구글의 AI 기반 검색에서 ‘쿼리 팬아웃 ( query fan-out )’은 단일 사용자 쿼리를 관련 하위 쿼리 네트워크로 전환하는 기술입니다. 구글 AI 모드는 단순히 원본 쿼리와 최상의 답변을 매칭하는 대신, 여러 관련 질문을 동시에 생성하고 검색하는 방식으로 한 단계 더 나아갑니다.

아래 예시에서 볼 수 있듯이, 구글 AI 모드는 일반적으로 주제를 더 깊이 탐색할 수 있도록 짧은 요약과 함께 약 10개의 관련 링크를 반환합니다:

The query fan-out from a Google AI Mode result page

이것이 바로 구글 쿼리 팬아웃의 개념으로, 간단히 말해 단일 AI 검색에서 생성된 관련 하위 쿼리들의 집합이라고 정의할 수 있습니다.

쿼리 팬아웃과 AI 개요에서 특정 주제가 반복적으로 등장한다면, 이를 중심으로 콘텐츠 페이지를 구성하는 것이 합리적입니다. 긍정적인 부수 효과로, 구글 같은 검색엔진은 AI 기반 검색 결과에서 이미 우수한 성과를 보이는 페이지를 SERP(검색 결과 페이지) 상위에 노출시킬 가능성이 높아, 이 접근법은 기존 SEO 개선에도 기여할 수 있습니다.

기본 개념을 이해하셨다면, 이제 GEO를 위한 이 접근법의 기술적 세부 사항을 살펴보시기 바랍니다!

다중 에이전트 기반 GEO 최적화 시스템 구축 방법

GEO 콘텐츠 최적화 워크플로우를 지원하는 AI 에이전트를 구현하는 것이 쉽지 않다는 점은 예상하셨을 것입니다. 효과적인 접근법 중 하나는 여섯 가지 전문 에이전트로 구성된 다중 에이전트 시스템에 의존하는 것입니다:

  • 제목 추출 에이전트: URL을 입력하면 웹 페이지의 주요 제목이나 헤딩을 추출합니다.
  • Google 쿼리 팬아웃 연구자: 추출된 제목을 활용하여 Gemini에서 제공하는 Google 검색 도구를 호출하고 쿼리 팬아웃을 생성합니다.
  • Google 메인 쿼리 추출기: 쿼리 팬아웃을 파싱하여 Google과 유사한 주요 검색 쿼리를 식별하고 추출합니다.
  • Google AI 개요 검색기: 주요 쿼리를 사용하여 Google SERP 검색을 수행하고, 그 결과에서 AI 개요 섹션을 추출합니다.
  • 쿼리 팬아웃 요약기: 일반적으로 매우 긴 쿼리 팬아웃 내용을 최적화된 마크다운 요약으로 압축하여 주요 주제를 강조합니다.
  • AI 콘텐츠 최적화기: 쿼리 팬아웃 요약본과 Google AI 개요를 비교하여 패턴과 반복되는 주제를 식별합니다. GEO 콘텐츠 최적화를 위한 실행 가능한 인사이트가 포함된 출력 마크다운 문서를 생성합니다.

이제, 위에서 설명한 에이전트 중 일부는 상당히 일반적이며 대부분의 LLM(예: Google 메인 쿼리 추출기, 쿼리 팬아웃 요약기, AI 콘텐츠 최적화기)으로 구현할 수 있습니다. 그러나 다른 에이전트는 더 전문화된 기능과 특정 모델이나 도구에 대한 접근이 필요합니다.

예를 들어, Google 메인 쿼리 추출기는 Gemini 모델에서만 사용할 수 있는 google_search 도구에 접근해야 합니다. 마찬가지로, Title Scraper 에이전트는 제목을 추출하기 위해 웹 페이지 콘텐츠에 접근해야 합니다. 많은 웹사이트가 AI 방지 조치를 시행하고 있어 이 작업은 어려울 수 있습니다. 문제를 피하려면 Title Scraper를 Web Unlocker와 통합할 수 있습니다. 이 Bright Data 스크래핑 API는 모든 차단을 우회하여 원시 HTML 또는 AI 최적화 Markdown 형식의 콘텐츠를 가져옵니다.

마찬가지로 Google AI 개요 추출기는 검색 쿼리를 수행하고 실시간으로 AI 개요를 스크래핑하기 위해 Bright Data SERP API와 같은 도구가 필요합니다.

다시 말해, Gemini와 Bright Data의 AI 인프라 덕분에 이 GEO/SEO 사용 사례를 구현할 수 있습니다. 이제 필요한 것은 이 요약 그래프에 설명된 대로 이러한 에이전트를 조정할 AI 에이전트 구축 시스템입니다:

The GEO content optimization multi-agent workflow

CrewAI는 다중 에이전트 시스템의 조율을 위해 특별히 설계되었으므로, 이 워크플로우를 구축하고 관리하기에 이상적인 프레임워크입니다.

CrewAI에서 Gemini 및 Bright Data를 활용한 다중 에이전트 GEO 콘텐츠 최적화 시스템 구현

아래 단계를 따라 AI 기반 검색 엔진에 최적화된 웹 페이지를 반복 가능한 워크플로로 제공하는 다중 에이전트 시스템을 구축하는 방법을 알아보세요. 쿼리 팬아웃과 AI 개요를 체계적으로 분석함으로써, 이 접근법은 우선순위가 높은 주제를 발견하고 AI 주도 순위를 높이기 위한 콘텐츠 구조화를 돕습니다.

아래 코드는 Python으로 작성되었으며, 에이전트에게 필요한 도구와 기능을 제공하기 위해 Bright Data 및 Gemini와 통합된 CrewAI를 사용합니다.

필수 조건

이 튜토리얼을 따라하려면 다음이 설치되어 있어야 합니다:

Bright Data 계정이 없더라도 걱정하지 마세요. 계정 생성 과정을 안내해 드립니다.

또한 CrewAI의 작동 방식을 어느 정도 이해하는 것이 매우 중요합니다. 시작하기 전에 공식 문서를 검토하는 것을 권장합니다.

1단계: CrewAI 애플리케이션 설정

CrewAI 설치에는 uv가 필요합니다. 다음 명령어로 전역 설치할 수 있습니다:

pip install uv

또는 운영 체제에 맞는 공식 설치 가이드를 따르세요.

다음으로 시스템에 CrewAI를 전역으로 설치하세요:

uv tool install crewai 

이제 ai_content_optimization_agent라는 새 CrewAI 프로젝트를 생성하세요:

crewai create crew ai_content_optimization_agent

AI 공급자를 선택하라는 메시지가 표시됩니다. 현재 워크플로가 Gemini에서 실행되므로 옵션 3을 선택하세요:

The CrewAI model selection view

다음으로 Gemini 모델을 선택하세요:

Selecting a Gemini model

사용 가능한 모델 중 아무거나 선택해도 됩니다. 이 글 후반부에 모델을 교체할 예정이므로 중요하지 않습니다.

계속해서 Gemini API 키를 붙여넣으세요:

Setting your Gemini API key

이 단계 이후, ai_content_optimization_agent/ 폴더 구조 내 프로젝트는 다음과 같이 구성됩니다:

ai_content_optimization_agent/
├── .gitignore
├── knowledge/
├── pyproject.toml
├── README.md
├── .env
└── src/
    └── ai_content_optimization_agent/
        ├── __init__.py
        ├── main.py
        ├── crew.py
        ├── tools/
        │   ├── custom_tool.py
        │   └── __init__.py
        └── config/
            ├── agents.yaml
            └── tasks.yaml

선호하는 Python IDE에서 프로젝트를 로드하고 익숙해지세요. 현재 파일을 살펴보고 .env 파일에 이미 선택한 Gemini 모델과 귀하의 Gemini API 키가 포함되어 있음을 확인하세요:

MODEL=<SELECTED_GEMINI_MODEL>
GEMINI_API_KEY=<YOUR_GEMINI_API_KEY>

CrewAI의 파일에 익숙하지 않거나 문제가 발생하면 공식 설치 가이드를 참조하세요.

터미널에서 프로젝트 폴더로 이동하세요:

cd ai_content_optimization_agent

그런 다음 해당 폴더 내에서 Python 가상 환경을 초기화하세요:

python -m venv .venv 

참고: 가상 환경 이름은 반드시 .venv이어야 합니다. 그렇지 않으면 CrewAI 워크플로우를 시작하는 crewai run 명령어가 실패합니다.

Linux 및 macOS에서는 다음 명령어로 가상 환경을 활성화하세요:

source .venv/bin/activate

대안으로 Windows에서는 다음을 실행하세요:

.venvScriptsactivate

완료! 이제 빈 CrewAI 프로젝트가 준비되었습니다.

2단계: Gemini 통합

앞서 언급한 바와 같이, 기본적으로 CrewAI는 선택한 Gemini 모델을 .env 파일에 추가합니다. 최신 모델을 구성하려면 .env 파일의 MODEL 환경 변수를 다음과 같이 덮어쓰세요:

MODEL=gemini/gemini-2.5-flash

이렇게 하면 CrewAI로 오케스트레이션된 AI 에이전트가 gemini-2.5-flash에 연결할 수 있습니다. 현재 작성 시점 기준으로 이는 최신 Gemini Flash 모델입니다. 또한 API를 통해 질의할 때(이 CrewAI 통합과 같이) 매우 관대한 속도 제한을 제공합니다.

crew.py 파일에서 환경 변수를 통해 MODEL 이름을 로드하려면 다음을 사용하세요:

MODEL = os.getenv("MODEL")

이 변수는 나중에 에이전트의 LLM을 설정하는 데 사용됩니다.

Python 표준 라이브러리에서 os를 반드시 임포트하세요:

import os

좋아요! Gemini 설정이 완료되었습니다.

3단계: CrewAI Bright Data 도구 설치 및 구성

웹 페이지에서 AI를 통해 제목을 추출하는 것은 간단하지 않습니다. 대부분의 LLM은 웹 페이지 콘텐츠에 직접 접근할 수 없습니다. 심지어 이를 위한 내장 도구가 있더라도 브라우저 지문 인식이나 CAPTCHA 같은 고급 스크래핑 방지 조치로 인해 종종 실패합니다. 실시간 SERP 스크래핑에도 동일한 문제가 적용됩니다. Google은 자동화된 스크래핑을 적극적으로 차단하기 때문입니다.

이때 Bright Data가 핵심 역할을 합니다. 다행히 CrewAI의 Bright Data 도구를 통해 공식 지원됩니다.

시작하려면 Bright Data 계정에 가입하거나 (이미 계정이 있다면 로그인 ) 프로필 대시보드로 이동하여 공식 지침에 따라 Web Unlocker 영역을 설정하세요:

A configured Web Unlocker zone

존이 “활성화됨(Active)”으로 설정되어 있는지 확인하세요:

The Web Unlocker zone is activated

이 예시에서 웹 언락커 존 이름은 "web_unlocker"이지만 원하는 대로 지정 가능합니다. 곧 필요할 수 있으니 이 이름을 기억해 두세요.

설정이 완료되면 공식 가이드에 따라 Bright Data API 키를 생성하세요. 곧 필요할 것이므로 안전하게 보관하십시오.

이제 활성화된 가상 환경에서 CrewAI Bright Data 도구 요구 사항을 설치하세요:

pip install crewai[tools] aiohttp requests

통합이 작동하려면 다음 두 환경 변수를 통해 Bright Data 자격 증명을 .env 파일에 추가하세요:

BRIGHT_DATA_API_KEY="<BRIGHT_DATA_API_KEY>"
BRIGHT_DATA_ZONE="<YOUR_BRIGHT_DATA_ZONE>"

<YOUR_BRIGHT_DATA_API_KEY><YOUR_BRIGHT_DATA_ZONE> 자리 표시자를 각각 실제 Bright Data API 키와 Web Unlocker 영역 이름으로 대체하세요.

다음으로 crew.py에서 Bright Data 도구를 임포트하세요:

from crewai_tools import BrightDataWebUnlockerTool, BrightDataSearchTool

아래와 같이 초기화합니다:

web_unlocker_tool = BrightDataWebUnlockerTool()
serp_search_tool = BrightDataSearchTool()

이제 에이전트에게 이 도구들을 전달하기만 하면 웹 언락 및 SERP 검색 기능을 제공할 수 있습니다. 훌륭합니다!

4단계: 제목 스크레이퍼 에이전트 구축

이제 첫 번째 에이전트를 구축할 모든 준비가 완료되었습니다. 웹 페이지에서 제목을 추출하는 역할을 하는 제목 스크레이퍼 에이전트부터 시작하세요.

페이지 제목을 얻는 주요 방법은 두 가지입니다:

  1. <h1> HTML 요소에서 텍스트 콘텐츠를 가져옵니다.
  2. <h1> 이 누락된 경우, AI에게 페이지 나머지 콘텐츠로부터 페이지 제목을 추론하도록 요청합니다.

이를 위해서는 Web Unlocker 도구 통합이 필요하다는 점을 잊지 마십시오. crew.py에서 CrewAI 에이전트와 작업을 다음과 같이 정의하세요:

@agent
def title_scraper_agent(self) -> Agent:
    return Agent(
        config=self.agents_config["title_scraper_agent"],
        tools=[web_unlocker_tool], # <--- Web Unlocker 도구 통합
        verbose=True,
        llm=MODEL,
    )

@task
def scrape_title_task(self) -> Task:
    return Task(
        config=self.tasks_config["scrape_title_task"],
        agent=self.title_scraper_agent(),
        max_retries=3,
    )

이 작업은 타사 도구 호출을 포함하므로 max_retries 옵션을 통해 재시도 로직(최대 3회)을 활성화하는 것이 합리적입니다. 이는 일시적인 네트워크 문제나 도구 오류로 인해 전체 워크플로가 실패하는 것을 방지합니다. 타사 서비스(도구 활용)에 의존하거나 LLM 처리 오류로 실패할 수 있는 복잡한 AI 작업을 포함하는 다른 모든 작업에도 동일한 로직을 적용해야 합니다.

다음으로 agents.yaml 구성 파일에서 Title Scraper 에이전트를 다음과 같이 정의하세요:

title_scraper_agent:
  role: "Title Scraper"
  goal: "주어진 웹 페이지 URL에서 주요 H1 헤딩 또는 제목을 추출합니다."
  backstory: "당신은 웹페이지의 주요 헤딩(H1) 또는 제목을 식별하고 추출하는 데 특화된 전문 스크레이퍼입니다."

그런 다음 tasks.yaml에서 주요 작업을 다음과 같이 설명하세요:

scrape_title_task:
  description: |
    1. URL '{url}'을 방문합니다.
    2. Bright Data Web Unlocker 도구(Markdown 데이터 형식 사용)를 사용하여 페이지 전체 콘텐츠를 스크래핑합니다.
    3. `<h1>` 태그 내 텍스트만 찾아 추출합니다. `<h1>` 태그가 없을 경우 페이지 콘텐츠에서 제목을 추론합니다.
    4. 추출된 텍스트를 일반 문자열로 출력합니다.
  expected_output: "지정된 URL에서 추출된 텍스트를 포함한 일반 문자열."

이 작업이 {url} 구문을 통해 CrewAI 입력에서 URL을 읽어오는 방식을 확인하세요. 다음 단계 중 하나에서 해당 입력 인수를 채우는 방법을 보게 될 것입니다.

훌륭합니다! 제목 스크레이퍼 에이전트가 완성되었습니다. 이제 남은 모든 에이전트를 정의하기 위해 유사한 논리를 적용할 것입니다.

단계 #5: Google 쿼리 팬아웃 리서처 에이전트 구현

CrewAI는 Gemini 모델에서 제공하는 Google 검색 도구에 접근할 수 있는 내장된 방법을 제공하지 않습니다. 대신 공식 Gemini CrewAI 통합 저장소에 표시된 대로 사용자 정의 Gemini LLM 통합을 정의해야 합니다.

기본적으로 CrewAI LLM 클래스를 확장하는 클래스를 생성해야 합니다. 이 클래스는 Gemini에 연결하고 google_search 도구를 활성화합니다. 이 클래스는 사용자 정의 llms/ 하위 폴더 내 gemini_google_search_llm.py 파일로 저장하거나(또는 crew.py 상단에 직접 배치할 수 있습니다).

사용자 정의 Gemini LLM 통합 클래스는 다음과 같이 정의하세요:

# src/ai_content_optimization_agent/llms/gemini_google_search_llm.py

from crewai import LLM
import os
from typing import Any, Optional

# Google 검색 그라운딩을 지원하는 커스텀 Gemini LLM 통합 정의
class GeminiWithGoogleSearch(LLM):
    """
    "google_search" 도구가 활성화된 Gemini 전용 LLM입니다.
    """

    def __init__(self, model: str | None = None, **kwargs):
        if not model:
            # 기본 Gemini 모델 사용
            model = os.getenv("MODEL")

        super().__init__(model, **kwargs)


    def call(
        self,
        messages: str | list[dict[str, str]],
        tools: list[dict] | None = None,
        callbacks: list[Any] | None = None,
        available_functions: dict[str, Any] | None = None,
        from_task: Optional[Any] = None,
        from_agent: Optional[Any] = None,
    ) -> str | Any:
        if not tools:
            tools = []

        # LiteLLM은 `google_search`를 감지하면 경고를 발생시키므로,
        # 여기서는 반드시 camel case를 사용해야 합니다
        tools.insert(0, {"googleSearch": {}})

        return super().call(
            messages=messages,
            tools=tools,
            callbacks=callbacks,
            available_functions=available_functions,
            from_task=from_task,
            from_agent=from_agent,
        )

이렇게 하면 설정된 Gemini 모델에서 Google 검색 도구에 접근할 수 있습니다.

참고: Google 검색 도구는 API 무료 계층에 할당량이 포함되어 있으므로 프리미엄 플랜 없이도 앱에서 사용할 수 있습니다.

그런 다음 crew.py에서 GeminiWithGoogleSearch 클래스를 임포트하세요:

from llms.gemini_google_search_llm import GeminiWithGoogleSearch

다음과 같이 Query Fan-Out Researcher 에이전트를 지정하는 데 사용하세요:

@agent
def query_fanout_researcher_agent(self) -> Agent:
    return Agent(
        config=self.agents_config["query_fanout_researcher_agent"],
        verbose=True,
        llm=GeminiWithGoogleSearch(MODEL), # <--- Google 검색 도구와 통합된 Gemini
    )

@task
def google_search_task(self) -> Task:
    return Task(
        config=self.tasks_config["google_search_task"],
        context=[self.scrape_title_task()],
        agent=self.query_fanout_researcher_agent(),
        max_retries=3,
        markdown=True,
        output_file="output/query_fanout.md",
    )

Agent 클래스에서 사용되는 LLM은 사용자 정의 GeminiWithGoogleSearch 클래스의 인스턴스임을 유의하십시오. 쿼리 팬아웃 생성 작업은 디버깅 및 추가 분석에 유용한 출력을 생성하므로, 이를 사용자 정의 출력 파일로 내보내야 합니다. 이 경우 생성된 출력은 output/query_fanout.md 파일에 저장됩니다.

또한 에이전트의 메인 태스크 컨텍스트가 워크플로우 내 이전 에이전트의 메인 태스크 출력과 정확히 일치하는 점에 유의하십시오. 이를 통해 현재 에이전트는 Title Scraper 에이전트가 생성한 출력에 접근할 수 있습니다. 특히 Google Search 도구를 통한 팬아웃 검색 수행 시 해당 출력을 입력으로 활용합니다.

다음으로 agents.yaml에 다음을 추가합니다:

query_fanout_researcher_agent:
  role: "Google Query Fan-Out Researcher"
  goal: "주어진 제목을 바탕으로 포괄적인 웹 검색을 수행하여 쿼리 팬아웃을 확보하라."
  backstory: "당신은 Gemini의 Google Search 도구를 기반으로 한 AI 연구 조교입니다."

그리고 tasks.yaml에 다음을 추가하세요:

google_search_task:
  description: |
    1. 이전 작업의 제목을 검색어로 사용합니다.
    2. Google 검색 도구를 사용하여 웹 검색을 수행합니다.
    3. Google 검색 도구의 결과를 반환합니다.
  expected_output: "Markdown 형식의 Google 검색 도구 출력 결과."

쿼리 팬아웃(query fan-out)이 어떻게 생겼는지 궁금하다면, 실제 google_search 도구 출력의 짧은 스니펫을 아래에서 확인하세요:

A sample query fan-out

완벽합니다! Google 쿼리 팬아웃 리서처 에이전트가 준비되었습니다.

6단계: 나머지 에이전트 정의

이전과 마찬가지로 crew.py에서 나머지 에이전트를 정의하세요:

@agent
def main_query_extractor_agent(self) -> Agent:
    return Agent(
        config=self.agents_config["main_query_extractor_agent"],
        verbose=True,
        llm=MODEL,
    )

@task
def main_query_extraction_task(self) -> Task:
    return Task(
        config=self.tasks_config["main_query_extraction_task"],
        context=[self.google_search_task()],
        agent=self.main_query_extractor_agent(),
    )

@agent
def ai_overview_retriever_agent(self) -> Agent:
    return Agent(
        config=self.agents_config["ai_overview_retriever_agent"],
        tools=[serp_search_tool], # <--- SERP API 도구 통합
        verbose=True,
        llm=MODEL,
    )

@task
def ai_overview_extraction_task(self) -> Task:
    return Task(
        config=self.tasks_config["ai_overview_extraction_task"],
        context=[self.main_query_extraction_task()],
        agent=self.ai_overview_retriever_agent(),
        max_retries=3,
        markdown=True,
        output_file="output/ai_overview.md",
    )

@agent
def query_fanout_summarizer_agent(self) -> Agent:
    return Agent(
        config=self.agents_config["query_fanout_summarizer_agent"],
        verbose=True,
        llm=MODEL,
    )

@task
def query_fanout_summarization_task(self) -> Task:
    return Task(
        config=self.tasks_config["query_fanout_summarization_task"],
        context=[self.google_search_task()],
        agent=self.query_fanout_summarizer_agent(),
        markdown=True,
        output_file="output/query_fanout_summary.md",
    )

@agent
def ai_content_optimizer_agent(self) -> Agent:
    return Agent(
        config=self.agents_config["ai_content_optimizer_agent"],
        verbose=True,
        llm=MODEL,
    )

@task
def compare_ai_overview_task(self) -> Task:
    return Task(
        config=self.tasks_config["compare_ai_overview_task"],
        context=[self.query_fanout_summarization_task(), self.ai_overview_extraction_task()],
        agent=self.ai_content_optimizer_agent(),
        max_retries=3,
        markdown=True,
        output_file="output/report.md",
    )

위 코드는 각각 다음을 지정합니다:

  • Google 메인 쿼리 추출기 에이전트와 그 주요 작업.
  • Google AI 개요 검색 에이전트와 그 주요 작업.
  • 쿼리 팬아웃 요약기 에이전트와 그 주요 작업.
  • AI 콘텐츠 최적화 에이전트와 그 주요 작업.

agents.yaml에 다음 줄을 추가하여 에이전트 정의를 완성하세요:

main_query_extractor_agent:
  role: "Google 메인 쿼리 추출기"
  goal: "제공된 쿼리 팬아웃에서 Google과 유사한 메인 검색 쿼리를 추출합니다."
  backstory: "당신은 쿼리 팬아웃을 분석하고 Google 검색에 적합한 간결한 메인 검색 쿼리를 식별하는 데 특화된 AI 어시스턴트입니다."

ai_overview_retriever_agent:
  role: "Google AI 개요 검색 에이전트"
  goal: "주어진 쿼리 팬아웃에서 주요 검색 쿼리를 추출하고, 이를 사용하여 Google에서 SERP 검색을 수행해 AI 개요 섹션을 검색합니다."
  backstory: "당신은 Google에서 SERP를 검색할 수 있는 AI SERP 검색 어시스턴트입니다."

query_fanout_summarizer_agent:
  role: "쿼리 팬아웃 요약기"
  goal: "제공된 쿼리 팬아웃으로부터 간결하고 구조화된 요약을 생성합니다."
  backstory: "당신은 쿼리 팬아웃을 명확하고 실행 가능한 마크다운 형식의 요약으로 압축하는 데 특화된 AI 요약 전문가입니다."

ai_content_optimizer_agent:
  역할: "AI 콘텐츠 최적화 전문가"
  목표: "쿼리 팬아웃에서 생성된 요약과 Google AI 개요를 비교하고, 패턴과 유사점을 식별하며, 공통 주제에 기반한 실행 항목 목록을 생성합니다."
  배경: "콘텐츠 요약과 AI 개요를 분석하여 반복되는 주제, 패턴 및 실행 가능한 인사이트를 찾아 콘텐츠 전략을 최적화하는 AI 어시스턴트입니다."

그리고 다음 내용을 tasks.yaml에 추가하세요:

main_query_extraction_task:
  description: |
    1. 제공된 쿼리 팬아웃에서 주요 검색 쿼리를 추출합니다.
    2. 검색 쿼리를 사용자가 Google에 입력할 만한 간결한 Google 스타일의 핵심 문구로 변환합니다.
  expected_output: "짧고 명확한 Google 스타일 검색 쿼리."

ai_overview_extraction_task:
  description: |
    1. 이전 작업의 검색 쿼리를 사용하여 Bright Data SERP 검색 도구를 통해 Google에서 SERP 검색을 수행합니다. 이때 `brd_ai_overview` 인수를 2로 설정합니다.
    2. 검색 결과에서 AI 개요 섹션의 통합된 마크다운 버전을 추출하여 반환합니다.
    3. 모든 시도 후, 응답 중 구글 AI 개요가 포함된 것이 없으면 SERP API 결과를 기반으로 생성하고 생성된 것임을 나타내는 주석을 포함하세요.
  expected_output: "AI 개요 섹션의 마크다운 형식(SERP API에서 가져온 것 또는 사용할 수 없는 경우 생성된 것)."

query_fanout_summarization_task:
  description: |
    1. 입력으로 받은 쿼리 팬아웃(fan-out)으로부터 요약문을 생성합니다.
  expected_output: "쿼리 팬아웃의 주요 정보를 포함한 마크다운 요약문."

compare_ai_overview_task:
  description: |
    1. 이전에 생성된 요약문과 입력으로 제공된 Google AI 개요를 비교합니다.
    2. 두 출처 간의 패턴과 유사점(하위 주제나 반복되는 주제 등) 및 차이점을 식별합니다.
    3. 비교 결과를 바탕으로 Google AI 개요와 초기 요약에 모두 등장하는 주제에 초점을 맞춘 실행 항목 목록을 생성합니다.
    4. 패턴, 유사점, 차이점을 비교하는 요약 테이블을 생성하세요. 테이블에는 다음 열을 포함합니다: 측면(Aspect), 쿼리 팬아웃 요약(Query Fan-Out Summary), Google AI 개요(Google AI Overview), 유사점/패턴(Similarities/Patterns), 차이점(Differences).
  expected_output: |
    쿼리 팬아웃에서 도출된 패턴, 유사점 및 실행 항목 목록을 강조하는 마크다운 형식의 비교 보고서.
    문서는 주요 유사점과 차이점을 제시하는 요약 테이블로 시작해야 하며, 그 다음에 나머지 모든 콘텐츠가 이어져야 합니다.

ai_overview_extraction_task 작업이 SERP API 응답에서 AI 개요를 추출하기 위한 기술적 사양을 포함하는 방식을 확인하세요. 자세한 내용은 공식 문서를 참조하십시오.

훌륭합니다! GEO 콘텐츠 최적화 워크플로우의 모든 AI 에이전트가 생성되었습니다. 이제 이들을 조정할 크루를 추가할 차례입니다.

7단계: 모든 에이전트를 크루로 통합하기

crew.py 내부에서 에이전트를 순차적으로 실행할 새로운 Crew 함수를 정의하세요:

@crew
def crew(self) -> Crew:
    return Crew(
        agents=self.agents,
        tasks=self.tasks,
        process=Process.sequential,
        verbose=True,
    )

완성! crew.py 파일의 AiContentOptimizationAgent 클래스가 완성되었습니다. main.py 파일에서 crew() 메서드를 실행하기만 하면 워크플로우가 시작됩니다.

단계 #8: 실행 흐름 정의

main.py 파일을 다음과 같이 재정의하세요:

  1. 터미널에서 Python의 input() 함수를 사용하여 입력 URL을 읽습니다.
  2. 제공된 URL을 사용하여 필요한 에이전트 입력을 구성합니다.
  3. AiContentOptimizationAgent 인스턴스를 초기화하고 crew() 메서드를 호출합니다. 이때 필수 {url} 필드가 채워진 입력 객체를 전달합니다.
  4. AI 워크플로를 실행합니다.

위의 모든 로직을 main.py 에 다음과 같이 구현합니다:

#!/usr/bin/env python

import warnings
from ai_content_optimization_agent.crew import AiContentOptimizationAgent
warnings.filterwarnings("ignore", category=SyntaxWarning, module="pysbd")

def run():
    # 터미널에서 URL 읽기
    url = input("처리할 URL을 입력하세요: ").strip()

    if not url:
        raise ValueError("URL이 제공되지 않았습니다. 종료합니다.")


    # 필요한 에이전트 입력값 생성
    inputs = {
        "url": url,
    }

    try:
        print(f"AI 콘텐츠 최적화를 위해 '${url}'을(를) 분석 중...")

        # 다중 에이전트 워크플로 실행
        AiContentOptimizationAgent().crew().kickoff(inputs=inputs)
    except Exception as e:
        raise Exception(f"크루 실행 중 오류 발생: {e}")

단계 #9: 에이전트 테스트

활성화된 가상 환경에서 에이전트를 시작하기 전에 다음 명령어로 필요한 종속성을 설치하세요:

crewai install

그런 다음 다중 에이전트 GEO 최적화 시스템을 실행하세요:

crewai run

입력 URL을 입력하라는 메시지가 표시됩니다:

The URL prompt from the AI application

이 예시에서는 입력으로 CrewAI 사이트 자체의 페이지를 사용하겠습니다:

https://www.crewai.com/ecosystem
The input page from the CrewAI site

이 페이지는 AI 에이전트 생태계의 주요 주체들을 소개합니다.

이 페이지에서 에이전트를 실행하면 다음과 같은 출력이 표시됩니다:

위 GIF는 속도를 높인 것이지만, 단계별로 진행되는 과정은 다음과 같습니다:

  1. Title Scraper 에이전트는 Bright Data Web Unlocker 도구를 통해 페이지 제목을 수집합니다. 결과는 "가장 빠르게 성장하는 AI 에이전트 생태계" (페이지 스크린샷에 표시된 것과 정확히 동일)입니다.
  2. Google Query Fan-Out Researcher는 google_search 도구로부터 쿼리 팬아웃(query fan-out) 출력을 생성합니다. 이로 인해 output/ 폴더에 query_fanout.md 파일이 생성됩니다.
  3. Google Main Query Extractor는 쿼리 팬아웃에서 주요 Google 유사 검색 쿼리를 식별합니다. 결과는 "AI 에이전트 생태계 성장"입니다.
  4. Google AI 개요 검색기는 Bright Data SERP API를 통해 검색어에 대한 AI 개요를 가져옵니다. 결과는 ai_overview.md에 저장됩니다.
  5. 쿼리 팬아웃 요약기 에이전트는 쿼리 팬아웃 내용을 요약하여 query_fanout_summary.md에 상세한 마크다운 요약본으로 압축합니다.
  6. AI 콘텐츠 최적화기는 쿼리 팬아웃 요약과 Google AI 개요를 비교하여 최종 report.md 파일을 생성합니다.

실행 완료 시 output/ 폴더에는 다음 네 개의 파일이 포함되어야 합니다:

Visual Studio Code에서 report.md를 미리보기 모드로 열고 내용을 스크롤해 보세요:

The final Markdown report with insights for content optimization produced by the agent

보시다시피, 주어진 입력 페이지의 콘텐츠를 GEO(및 SEO)에 최적화하는 데 도움이 되는 상세한 마크다운 보고서가 포함되어 있습니다!

이제 AI 순위를 높이고자 하는 웹 페이지 URL에 이 에이전트를 적용하면 GEO 및 SEO 포지셔닝을 향상시킬 수 있습니다.

자, 이제 완료되었습니다!

다음 단계

위에서 구축한 AI 콘텐츠 최적화 에이전트는 이미 상당히 강력하지만, 항상 개선의 여지가 있습니다. 한 가지 아이디어는 워크플로 시작 부분에 사이트맵을 입력으로 받는 또 다른 에이전트를 추가하는 것입니다(예를 들어 블로그 게시물만 선택하기 위해 정규 표현식으로 URL을 필터링하는 등). 이 에이전트는 기존 워크플로에 URL을 전달할 수 있으며, 병렬 처리로 여러 페이지를 동시에 AI 콘텐츠 최적화를 위해 분석할 수 있게 해줍니다.

일반적으로, agents. yaml과 tasks.yaml의 지시문을 실험하여 여섯 에이전트 각각의 동작을 특정 사용 사례에 맞게 조정할 수 있다는 점을 기억하세요. 이러한 조정을 위해 고급 기술적 지식은 필요하지 않습니다!

결론

이 글에서는 Bright Data의 AI 통합 기능을 활용하여 CrewAI에서 GEO/SEO 최적화를 위한 복잡한 다중 에이전트 워크플로를 구축하는 방법을 알아보았습니다.

여기에 소개된 AI 워크플로는 기존 검색 엔진과 AI 기반 검색 모두를 위해 웹 페이지 콘텐츠를 개선할 수 있는 프로그래밍 방식을 찾는 모든 분에게 이상적입니다.

비슷한 고급 워크플로를 생성하려면 Bright Data AI 인프라에서 실시간 웹 데이터를 검색, 검증 및 변환하기 위한 모든 솔루션을 살펴보세요.

지금 바로 무료 Bright Data 계정을 생성하고 AI 지원 웹 도구로 실험을 시작하세요!