도구로서의 데이터베이스: ADK, MCP 도구 상자, Cloud SQL을 사용한 에이전트형 RAG

1. 소개

AI 에이전트의 유용성은 액세스할 수 있는 데이터에 따라 달라집니다. 대부분의 실제 데이터는 데이터베이스에 저장되어 있으며, 에이전트를 데이터베이스에 연결하려면 일반적으로 연결 관리, 쿼리 로직을 작성하고 에이전트 코드 내에 파이프라인을 삽입해야 합니다. 데이터베이스 액세스가 필요한 모든 에이전트가 이 작업을 반복하며, 쿼리 변경이 있을 때마다 에이전트를 다시 배포해야 합니다.

이 Codelab에서는 다른 접근 방식을 보여줍니다. 표준 SQL 쿼리, 벡터 유사성 검색, 자동 임베딩 생성 등 데이터베이스 도구를 YAML 파일로 선언하면 데이터베이스용 MCP 도구 상자가 모든 데이터베이스 작업을 MCP 서버로 처리합니다. 에이전트 코드는 최소한으로 유지됩니다. 도구를 로드하고 Gemini가 호출할 도구를 결정하도록 합니다.

빌드할 항목

'TechJobs'를 위한 스마트 채용 게시판 어시스턴트: 개발자가 표준 필터 (역할, 기술 스택)를 사용하여 기술 직무 목록을 탐색하고 'AI 챗봇을 개발하는 원격 직무를 원해'와 같은 자연어 설명을 통해 직무를 찾을 수 있도록 지원하는 Gemini 기반 ADK 에이전트입니다. 에이전트는 데이터베이스 액세스를 모두 처리하는 MCP Toolbox for Databases를 통해 PostgreSQL용 Cloud SQL 데이터베이스에서 읽고 씁니다. 여기에는 벡터 검색을 위한 자동 임베딩 생성이 포함됩니다. 결국 도구 상자와 에이전트가 모두 Cloud Run에서 실행됩니다.

eb6de681c40990c1.jpeg

학습할 내용

  • MCP (모델 컨텍스트 프로토콜)가 AI 에이전트의 도구 액세스를 표준화하는 방법과 데이터베이스용 MCP 도구 상자가 이를 데이터베이스 작업에 적용하는 방법
  • ADK 에이전트와 Cloud SQL PostgreSQL 간의 미들웨어로 데이터베이스용 MCP 도구 상자 설정
  • tools.yaml에서 선언적으로 데이터베이스 도구 정의 - 에이전트에 데이터베이스 코드가 없음
  • ToolboxToolset를 사용하여 실행 중인 도구 상자 서버에서 도구를 로드하는 ADK 에이전트 빌드
  • Cloud SQL의 기본 제공 embedding() 함수를 사용하여 벡터 임베딩을 생성하고 pgvector로 시맨틱 검색 사용 설정
  • 쓰기 작업 시 자동 벡터 수집을 위해 valueFromParam 기능 사용
  • 도구 상자 서버와 ADK 에이전트를 모두 Cloud Run에 배포

기본 요건

  • 평가판 결제 계정이 있는 Google Cloud 계정
  • Python 및 SQL에 대한 기본 지식
  • ADK, MCP 도구 상자 또는 pgvector에 대한 사전 경험이 필요하지 않음

2. 환경 설정

이 단계에서는 Cloud Shell 환경을 준비하고, Google Cloud 프로젝트를 구성하고, 참조 저장소를 클론합니다.

Cloud Shell 열기

브라우저에서 Cloud Shell을 엽니다. Cloud Shell은 이 Codelab에 필요한 모든 도구가 사전 구성된 환경을 제공합니다. 메시지가 표시되면 승인을 클릭합니다.

그런 다음 '보기' -> '터미널'을 클릭하여 터미널을 엽니다. 인터페이스는 다음과 유사해야 합니다.

86307fac5da2f077.png

이것이 기본 인터페이스가 됩니다. 상단에는 IDE가 있고 하단에는 터미널이 있습니다.

작업 디렉터리 설정하기

작업 디렉터리를 만듭니다. 이 Codelab에서 작성하는 모든 코드는 여기에 있습니다.

mkdir -p ~/build-agent-adk-toolbox-cloudsql
cloudshell workspace ~/build-agent-adk-toolbox-cloudsql && cd ~/build-agent-adk-toolbox-cloudsql

Google Cloud 프로젝트 설정

위치 변수를 사용하여 .env 파일을 만듭니다.

# For Vertex AI / Gemini API calls
echo "GOOGLE_CLOUD_LOCATION=global" > .env
# For Cloud SQL, Cloud Run, Artifact Registry
echo "REGION=us-central1" >> .env

프로젝트 설정 스크립트를 작업 디렉터리에 다운로드합니다.

curl -sL https://raw.githubusercontent.com/alphinside/cloud-trial-project-setup/main/setup_verify_trial_project.sh -o setup_verify_trial_project.sh

스크립트를 실행합니다. 무료 체험 결제 계정을 확인하고, 새 프로젝트를 만들거나 기존 프로젝트를 검증하고, 현재 디렉터리의 .env 파일에 프로젝트 ID를 저장하고, gcloud에서 활성 프로젝트를 설정합니다.

bash setup_verify_trial_project.sh && source .env

스크립트는 다음을 수행합니다.

  1. 활성 상태의 무료 체험 결제 계정이 있는지 확인
  2. .env에 기존 프로젝트가 있는지 확인합니다 (있는 경우).
  3. 새 프로젝트를 만들거나 기존 프로젝트를 재사용합니다.
  4. 무료 체험 결제 계정을 프로젝트에 연결
  5. 프로젝트 ID를 .env에 저장합니다.
  6. 프로젝트를 활성 gcloud 프로젝트로 설정

Cloud Shell 터미널 프롬프트의 작업 디렉터리 옆에 있는 노란색 텍스트를 확인하여 프로젝트가 올바르게 설정되었는지 확인합니다. 프로젝트 ID가 표시되어야 합니다.

dcba35ce1389f313.png

이 Codelab을 진행하는 동안 언제든지 Cloud Shell 세션이 재설정되면 작업 디렉터리로 다시 이동하고 bash setup_verify_trial_project.sh && source .env를 다시 실행하여 프로젝트 구성을 복원하세요. 터미널 프롬프트에 노란색 프로젝트 ID 텍스트가 다시 표시되는지 확인합니다.

gcloud services enable \
  aiplatform.googleapis.com \
  sqladmin.googleapis.com \
  compute.googleapis.com \
  run.googleapis.com \
  cloudbuild.googleapis.com \
  artifactregistry.googleapis.com
  • Vertex AI API (aiplatform.googleapis.com) - 에이전트가 Gemini 모델을 사용하고, 도구 상자가 벡터 검색을 위해 임베딩 API를 사용합니다.
  • Cloud SQL Admin API (sqladmin.googleapis.com) - PostgreSQL 인스턴스를 프로비저닝하고 관리합니다.
  • Compute Engine API (compute.googleapis.com) - Cloud SQL 인스턴스를 만드는 데 필요합니다.
  • Cloud Run, Cloud Build, Artifact Registry - 이 Codelab의 후반부 배포 단계에서 사용됩니다.

3. 데이터베이스 인스턴스 만들기

이 단계에서는 백그라운드에서 Cloud SQL 인스턴스 생성을 설정합니다. 가이드를 계속 진행하는 동안 프로비저닝됩니다.

인스턴스 생성 시작

.env 파일에 데이터베이스 비밀번호를 추가하고 다시 로드합니다.

echo "DB_PASSWORD=techjobs-pwd-2025" >> .env
source .env

Cloud SQL 인스턴스 생성을 시작합니다. 이 기능은 백그라운드에서 실행되므로 계속해서 작업할 수 있습니다.

gcloud sql instances create jobs-instance \
  --database-version=POSTGRES_17 \
  --tier=db-custom-1-3840 \
  --edition=ENTERPRISE \
  --region=$REGION \
  --root-password=$DB_PASSWORD \
  --enable-google-ml-integration \
  --database-flags cloudsql.enable_google_ml_integration=on \
  --quiet &
  • db-custom-1-3840ENTERPRISE 버전에서 가장 작은 전용 코어 Cloud SQL 등급 (vCPU 1개, RAM 3.75GB)입니다. 자세한 내용은 여기를 참고하세요. Vertex AI ML 통합에는 전용 코어가 필요합니다. 공유 코어 등급 (db-f1-micro, db-g1-small)은 지원하지 않습니다.
  • --root-password는 기본 postgres 사용자의 비밀번호를 설정합니다.
  • --enable-google-ml-integration를 사용하면 Cloud SQL과 Vertex AI 간의 기본 제공 통합이 사용 설정되어 embedding() 함수를 사용하여 SQL에서 직접 임베딩 모델을 호출할 수 있습니다.
  • &는 백그라운드에서 명령어를 실행합니다.

이 명령은 백그라운드에서 실행됩니다. 다음으로 MCP 도구 상자 바이너리를 다운로드합니다. 동일한 터미널에서 이 작업을 수행할 수 있습니다.

도구 상자 바이너리 다운로드

이 튜토리얼에서는 MCP Toolbox를 사용합니다. 다행히도 Linux 환경에서 사용할 수 있는 사전 빌드된 바이너리가 함께 제공됩니다. 시간이 오래 걸리므로 백그라운드에서 다운로드하겠습니다.

cd ~/build-agent-adk-toolbox-cloudsql
curl -O https://storage.googleapis.com/genai-toolbox/v0.27.0/linux/amd64/toolbox &

이 프로세스가 현재 탭에서 실행되도록 합니다 (이미 백그라운드에서 실행되고 있지만 출력은 계속 표시됨). 더 집중할 수 있도록 Cloud Shell에서 새 터미널 탭을 엽니다 (+ 아이콘 클릭).

b01e3fbd89f17332.png

작업 디렉터리로 다시 이동하여 이전 설정 스크립트를 사용하여 프로젝트를 활성화합니다.

cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env

이 단계에서는 Python 프로젝트를 설정하고, 종속 항목을 설치하고, ADK 에이전트 디렉터리를 스캐폴딩합니다.

4. 에이전트 프로젝트 초기화

Python 프로젝트 설정

uv은 Rust로 작성된 빠른 Python 패키지 및 프로젝트 관리자입니다 ( uv 문서). 이 Codelab에서는 속도와 단순성을 위해 이를 사용합니다.

Python 프로젝트를 초기화하고 필요한 종속 항목을 추가합니다.

uv init
uv add google-adk==1.25.0 toolbox-adk==0.6.0
  • google-adk: Gemini SDK를 포함한 Google의 에이전트 개발 키트
  • toolbox-adk - 데이터베이스용 MCP 도구 상자의 ADK 통합

에이전트 디렉터리 구조 만들기

ADK는 __init__.py, agent.py, .env가 포함된 에이전트 이름의 디렉터리와 같은 특정 폴더 레이아웃을 예상합니다. 이를 위해 구조를 빠르게 설정하는 명령어가 내장되어 있습니다.

uv run adk create jobs_agent \
    --model gemini-2.5-flash \
    --project ${GOOGLE_CLOUD_PROJECT} \
    --region ${GOOGLE_CLOUD_LOCATION}

이제 디렉터리가 다음과 같이 표시됩니다.

build-agent-adk-toolbox-cloudsql/
├── jobs_agent/
│   ├── __init__.py
│   ├── agent.py
│   └── .env
├── pyproject.toml
├── .env              (project setup — already exists)
└── .venv/

5. 채용 등록정보 데이터베이스 시드

이 단계에서는 시드 데이터를 쓰고, Cloud SQL 인스턴스의 프로비저닝이 완료될 때까지 기다리고, jobs 테이블에 15개의 채용 정보와 설명 삽입을 로드합니다.

시드 SQL 작성

Cloud Shell 편집기에서 채용 정보 목록 콘텐츠가 포함된 seed.sql 파일을 만듭니다. 이렇게 하면 pgvector 지원으로 jobs 테이블이 생성되고 기술 회사에 15개의 채용 정보가 삽입됩니다.

먼저 다음 명령어를 사용하여 seed.sql 파일을 만듭니다.

cloudshell edit seed.sql

그런 다음 이 스크립트를 파일에 복사합니다.

-- seed.sql
-- DISCLAIMER: These job listings are entirely fictional and created for tutorial
-- purposes only. Company names are used for illustrative context — the positions,
-- salaries, and descriptions do not reflect real openings.

CREATE EXTENSION IF NOT EXISTS google_ml_integration;
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE IF NOT EXISTS jobs (
    id SERIAL PRIMARY KEY,
    title VARCHAR NOT NULL,
    company VARCHAR NOT NULL,
    role VARCHAR NOT NULL,
    tech_stack VARCHAR NOT NULL,
    salary_range VARCHAR NOT NULL,
    location VARCHAR NOT NULL,
    openings INTEGER NOT NULL,
    description TEXT NOT NULL,
    description_embedding vector(3072)
);

INSERT INTO jobs (title, company, role, tech_stack, salary_range, location, openings, description) VALUES
('Senior Backend Engineer', 'Stripe', 'Backend', 'Go, PostgreSQL, gRPC, Kubernetes', '$180-250K/year', 'San Francisco, Hybrid', 3,
 'Design and build high-throughput microservices powering payment infrastructure for millions of businesses. Optimize Go services for sub-100ms latency at scale, work with PostgreSQL and Redis for data persistence, and deploy on Kubernetes clusters handling billions of API calls.'),

('Machine Learning Engineer', 'Spotify', 'Data/AI', 'Python, TensorFlow, BigQuery, Vertex AI', '$170-230K/year', 'Stockholm, Remote', 2,
 'Build and deploy ML models for music recommendation and personalization systems serving hundreds of millions of listeners. Design feature pipelines in BigQuery, train models using distributed computing, and serve predictions through real-time APIs processing thousands of requests per second.'),

('Frontend Engineer', 'Vercel', 'Frontend', 'React, TypeScript, Next.js', '$140-190K/year', 'Remote', 4,
 'Build developer-facing dashboard interfaces and deployment tools used by millions of developers worldwide. Create responsive, accessible React components for project management, analytics, and real-time deployment monitoring with a focus on developer experience.'),

('DevOps Engineer', 'Datadog', 'DevOps', 'Terraform, GCP, Docker, Kubernetes, ArgoCD', '$160-220K/year', 'New York, Hybrid', 2,
 'Manage cloud infrastructure powering an observability platform used by thousands of engineering teams. Automate deployment pipelines with ArgoCD, manage multi-cloud Kubernetes clusters, and implement infrastructure-as-code with Terraform across production environments.'),

('Mobile Engineer (Android)', 'Grab', 'Mobile', 'Kotlin, Jetpack Compose, GraphQL', '$120-170K/year', 'Singapore, Hybrid', 3,
 'Develop features for a super-app serving millions of users across Southeast Asia. Build modern Android UIs with Jetpack Compose, integrate GraphQL APIs, and optimize app performance for diverse device capabilities and network conditions.'),

('Data Engineer', 'Airbnb', 'Data', 'Python, Apache Spark, Airflow, BigQuery', '$160-210K/year', 'San Francisco, Hybrid', 2,
 'Build data pipelines that process booking, search, and pricing data for a global travel marketplace. Design ETL workflows with Apache Spark and Airflow, maintain data warehouses in BigQuery, and ensure data quality for analytics and machine learning teams.'),

('Full Stack Engineer', 'Revolut', 'Full Stack', 'TypeScript, Node.js, React, PostgreSQL', '$130-180K/year', 'London, Remote', 5,
 'Build the next generation of financial products making banking accessible to millions of users across 35 countries. Develop real-time trading interfaces with React and WebSockets, build Node.js APIs handling market data streams, and design PostgreSQL schemas for financial transactions.'),

('Site Reliability Engineer', 'Cloudflare', 'SRE', 'Go, Prometheus, Grafana, GCP, Terraform', '$170-230K/year', 'Austin, Hybrid', 2,
 'Ensure 99.99% uptime for a global network handling millions of requests per second. Define SLOs, build monitoring dashboards with Prometheus and Grafana, manage incident response, and automate infrastructure scaling across 300+ data centers worldwide.'),

('Cloud Architect', 'Google Cloud', 'Cloud', 'GCP, Terraform, Kubernetes, Python', '$200-280K/year', 'Seattle, Hybrid', 1,
 'Help enterprises modernize their infrastructure on Google Cloud. Design multi-region architectures, lead migration projects from on-premises to GKE, and build reference implementations using Terraform and Cloud Foundation Toolkit.'),

('Backend Engineer (Payments)', 'Square', 'Backend', 'Java, Spring Boot, PostgreSQL, Kafka', '$160-220K/year', 'San Francisco, Hybrid', 3,
 'Build payment processing systems handling millions of transactions for businesses of all sizes. Design event-driven architectures using Kafka, implement idempotent payment flows with Spring Boot, and ensure PCI-DSS compliance across all services.'),

('AI Engineer', 'Hugging Face', 'Data/AI', 'Python, LangChain, Vertex AI, FastAPI, PostgreSQL', '$150-210K/year', 'Paris, Remote', 2,
 'Build AI-powered tools for the largest open-source ML community. Develop RAG pipelines that index and search model documentation, create conversational agents using LangChain, and deploy AI services with FastAPI on cloud infrastructure.'),

('Platform Engineer', 'Coinbase', 'Platform', 'Rust, Kubernetes, AWS, Terraform', '$180-250K/year', 'Remote', 0,
 'Build the infrastructure platform for a leading cryptocurrency exchange. Develop high-performance matching engines in Rust, manage Kubernetes clusters for microservices, and design CI/CD pipelines that enable rapid feature deployment with zero downtime.'),

('QA Automation Engineer', 'Shopify', 'QA', 'Python, Selenium, Cypress, Jenkins', '$110-160K/year', 'Toronto, Hybrid', 3,
 'Design and maintain automated test suites for a commerce platform powering millions of merchants. Build end-to-end test frameworks with Cypress and Selenium, integrate tests into Jenkins CI pipelines, and establish quality gates that prevent regressions in checkout and payment flows.'),

('Security Engineer', 'CrowdStrike', 'Security', 'Python, SIEM, Kubernetes, Penetration Testing', '$170-240K/year', 'Austin, On-site', 1,
 'Protect enterprise customers from cyber threats on a leading endpoint security platform. Conduct penetration testing, design security monitoring with SIEM tools, implement zero-trust networking in Kubernetes environments, and lead incident response for security events.'),

('Product Engineer', 'GitLab', 'Full Stack', 'Go, React, PostgreSQL, Redis, GCP', '$140-200K/year', 'Remote', 4,
 'Own features end-to-end for an all-in-one DevSecOps platform used by millions of developers. Build Go microservices for CI/CD pipelines, create React frontends for code review and project management, and collaborate with product managers to iterate on user-facing features using data-driven development.');

시드 스크립트는 다음 두 PostgreSQL 확장 프로그램을 설치합니다.

  • google_ml_integration - SQL에서 직접 Vertex AI 임베딩 모델을 호출하는 embedding() SQL 함수를 제공합니다. 이는 jobs_db 내에서 ML 함수를 사용할 수 있도록 하는 데이터베이스 수준 확장 프로그램입니다. 인스턴스 생성 중에 설정한 인스턴스 수준 플래그 (--enable-google-ml-integration)를 사용하면 Cloud SQL VM이 Vertex AI에 도달할 수 있습니다. 확장 프로그램을 사용하면 이 특정 데이터베이스 내에서 SQL 함수를 사용할 수 있습니다.
  • vector (pgvector) - 삽입을 저장하고 쿼리하기 위한 vector 데이터 유형과 거리 연산자를 추가합니다.

description_embedding 열은 vector(3072)입니다. vector(3072)은 3072차원 벡터를 저장하는 pgvector 열입니다. 지금은 NULL입니다. 다음 단계에서 embedding() 함수를 사용하여 임베딩을 생성하고 채웁니다.

데이터베이스 설정 완료하기

이전 단계에서 시작한 Cloud SQL 인스턴스 생성이 아직 실행 중이며 완료되지 않았을 수 있습니다. 인스턴스가 준비되었는지 확인합니다.

gcloud sql instances describe jobs-instance --format="value(state)"

다음 출력이 표시될 것입니다.

RUNNABLE

34f5b48006b4cb3a.png

다음으로 Cloud SQL 인스턴스의 서비스 계정에 Vertex AI를 호출할 수 있는 권한을 부여합니다. 이는 다음 단계에서 사용할 내장 embedding() 함수에 필요합니다.

SERVICE_ACCOUNT=$(gcloud sql instances describe jobs-instance --format="value(serviceAccountEmailAddress)")

gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT \
  --member="serviceAccount:$SERVICE_ACCOUNT" \
  --role="roles/aiplatform.user" \
  --quiet

그런 다음 채용 정보 전용 데이터베이스를 만듭니다.

gcloud sql databases create jobs_db --instance=jobs-instance

데이터베이스가 생성되었음을 확인하는 출력이 표시됩니다.

Creating Cloud SQL database...done.                                                                         
Created database [jobs_db].
instance: jobs-instance
name: jobs_db
project: workshop-xxxxxxx

데이터베이스 연결 및 시드

Cloud SQL 인증 프록시를 시작합니다 (cloud-sql-proxy는 Cloud Shell에 사전 설치되어 있음). 이렇게 하면 Cloud Shell에서 Cloud SQL 인스턴스로의 보안 인증된 연결이 제공됩니다.

d72e56478b517b5c.jpeg

cloud-sql-proxy ${GOOGLE_CLOUD_PROJECT}:${REGION}:jobs-instance --port 5432 &

프록시가 시작되면 터미널에 다음과 같은 출력이 표시됩니다.

... Authorizing with Application Default Credentials
... [workshop-xxxxxx:your-location:jobs-instance] Listening on 127.0.0.1:5432
... The proxy has started successfully and is ready for new connections!

이제 현재 터미널에서 Cloud SQL 프록시의 로그가 지속적으로 출력됩니다. 더 집중할 수 있도록 Cloud Shell에서 새 터미널 탭을 엽니다 (+ 아이콘 클릭).

b01e3fbd89f17332.png

작업 디렉터리로 다시 이동하여 이전 설정 스크립트를 사용하여 프로젝트를 활성화합니다.

cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env

그런 다음 시드 스크립트를 실행합니다.

psql "host=127.0.0.1 port=5432 dbname=jobs_db user=postgres password=$DB_PASSWORD" -f seed.sql

다음과 같은 터미널 출력이 표시됩니다.

CREATE EXTENSION
CREATE EXTENSION
CREATE TABLE
INSERT 0 15

데이터를 확인해 보겠습니다.

psql "host=127.0.0.1 port=5432 dbname=jobs_db user=postgres password=$DB_PASSWORD" \
  -c "SELECT title, company, role, openings FROM jobs ORDER BY role, title;"

다양한 역할에 걸쳐 15개의 채용 정보가 표시됩니다.

             title              |    company     |   role    | openings
---------------------------------+----------------+-----------+----------
 Senior Backend Engineer         | Stripe         | Backend   |        3
 Backend Engineer (Payments)     | Square         | Backend   |        3
 Cloud Architect                 | Google Cloud   | Cloud     |        1
 ...
(15 rows)

직무 설명의 임베딩 생성

jobs 테이블의 description_embedding 열이 현재 NULL입니다. Cloud SQL의 기본 제공 google_ml_integration 확장 프로그램은 Python 스크립트나 외부 SDK 없이 SQL에서 Vertex AI를 직접 호출하는 embedding() 함수를 제공합니다.

백그라운드에서 삽입 생성 시작 이렇게 하면 Vertex AI가 gemini-embedding-001 모델을 사용하여 15개 직무 설명 각각에 대해 3072차원 벡터를 생성합니다.

psql "host=127.0.0.1 port=5432 dbname=jobs_db user=postgres password=$DB_PASSWORD" \
  -c "UPDATE jobs SET description_embedding = embedding('gemini-embedding-001', description)::vector;" &

스크립트가 수행하는 작업은 다음과 같습니다.

  • embedding('gemini-embedding-001', description) - 각 작업의 description 텍스트를 전달하여 SQL에서 Vertex AI의 Gemini 임베딩 모델을 직접 호출합니다. 이는 시드 스크립트에 설치한 google_ml_integration 확장 프로그램입니다.
  • ::vector - 반환된 float 배열을 pgvector의 vector 유형으로 변환하여 거리 연산자로 저장하고 쿼리할 수 있습니다.
  • UPDATE은 15개 행 전체에서 실행되어 직무 설명당 3072차원 임베딩을 하나 생성합니다.
  • &는 백그라운드에서 명령어를 실행하므로 Vertex AI가 삽입을 처리하는 동안 계속 작업할 수 있습니다.

이전 백그라운드 프로세스 실행과 마찬가지로 현재 터미널에 프로세스 로그가 출력됩니다. 더 집중할 수 있도록 Cloud Shell에서 새 터미널 탭을 엽니다 (+ 아이콘 클릭).

b01e3fbd89f17332.png

작업 디렉터리로 다시 이동하여 이전 설정 스크립트를 사용하여 프로젝트를 활성화합니다.

cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env

그런 다음 다음 프로세스를 진행할 수 있습니다.

6. 데이터베이스용 MCP 도구 상자 구성

이 단계에서는 데이터베이스용 MCP 도구 상자를 소개하고, Cloud SQL 인스턴스에 연결하도록 구성하며, 두 개의 표준 SQL 쿼리 도구를 정의합니다.

MCP란 무엇이며 도구 상자를 사용해야 하는 이유는 무엇인가요?

e7b9be2e1c98b4db.png

MCP (모델 컨텍스트 프로토콜)는 AI 에이전트가 외부 도구를 검색하고 상호작용하는 방식을 표준화하는 개방형 프로토콜입니다. 클라이언트-서버 모델을 정의합니다. 에이전트는 MCP 클라이언트를 호스팅하고 도구는 MCP 서버에 의해 노출됩니다. MCP 호환 클라이언트는 MCP 호환 서버를 사용할 수 있습니다. 에이전트에는 각 도구에 대한 맞춤 통합 코드가 필요하지 않습니다.

d5baa77423f0f465.png

MCP Toolbox for Databases는 데이터베이스 액세스를 위해 특별히 빌드된 오픈소스 MCP 서버입니다. 이 기능을 사용하지 않으면 데이터베이스 연결을 열고, 연결 풀을 관리하고, SQL 삽입을 방지하기 위해 매개변수화된 쿼리를 구성하고, 오류를 처리하고, 이 모든 코드를 에이전트 내에 삽입하는 Python 함수를 작성해야 합니다. 데이터베이스 액세스가 필요한 모든 에이전트가 이 작업을 반복합니다. 쿼리를 변경하면 에이전트를 다시 배포해야 합니다.

Toolbox를 사용하면 YAML 파일을 작성합니다. 각 도구는 파라미터화된 SQL 문에 매핑됩니다. 툴박스는 연결 풀링, 매개변수화된 쿼리, 인증, 관측 가능성을 처리합니다. 도구가 에이전트에서 분리됨: 에이전트 코드를 건드리지 않고 tools.yaml를 수정하고 Toolbox를 다시 시작하여 쿼리를 업데이트합니다. ADK, LangGraph, LlamaIndex 또는 MCP 호환 프레임워크에서 동일한 도구가 작동합니다.

도구 구성 작성

이제 Cloud Shell 편집기에서 tools.yaml이라는 파일을 만들어 도구 구성을 설정해야 합니다.

cloudshell edit tools.yaml

이 파일은 다중 문서 YAML을 사용합니다. ---로 구분된 각 블록은 독립형 리소스입니다. 모든 리소스에는 리소스가 무엇인지 선언하는 kind (데이터베이스 연결의 경우 sources, 에이전트 호출 가능 작업의 경우 tools)와 백엔드를 지정하는 type (소스의 경우 cloud-sql-postgres, SQL 기반 도구의 경우 postgres-sql)가 있습니다. 도구는 name로 소스를 참조합니다. 이를 통해 도구 상자는 실행할 연결 풀을 알 수 있습니다. 환경 변수는 ${VAR_NAME} 구문을 사용하며 시작 시 확인됩니다.

이제 다음 스크립트를 먼저 tools.yaml 파일에 복사합니다.

# tools.yaml

# --- Data Source ---
kind: sources
name: jobs-db
type: cloud-sql-postgres
project: ${GOOGLE_CLOUD_PROJECT}
region: ${REGION}
instance: jobs-instance
database: jobs_db
user: postgres
password: ${DB_PASSWORD}

---

이 스크립트는 다음 리소스를 정의합니다.

  • 소스 (jobs-db) - 툴박스가 Cloud SQL PostgreSQL 인스턴스에 연결하는 방법을 알려줍니다. cloud-sql-postgres 유형은 내부적으로 Cloud SQL 커넥터를 사용하여 인증과 보안 연결을 자동으로 처리합니다. ${GOOGLE_CLOUD_PROJECT}, ${REGION}, ${DB_PASSWORD} 자리표시자는 시작 시 환경 변수에서 확인됩니다.

그런 다음 tools.yaml--- 기호 아래에 다음 스크립트를 추가합니다.

# --- Tool 1: Search jobs by role and/or tech stack ---
kind: tools
name: search-jobs
type: postgres-sql
source: jobs-db
description: >-
  Search for job listings by role category and/or tech stack.
  Use this tool when the developer wants to browse listings
  by role (e.g., Backend, Frontend, Data) or find jobs
  using a specific technology. Both parameters accept an
  empty string to match all values.
statement: |
  SELECT title, company, role, tech_stack, salary_range, location, openings
  FROM jobs
  WHERE ($1 = '' OR LOWER(role) = LOWER($1))
  AND ($2 = '' OR LOWER(tech_stack) LIKE '%' || LOWER($2) || '%')
  ORDER BY title
  LIMIT 10
parameters:
  - name: role
    type: string
    description: "The role category to filter by (e.g., 'Backend', 'Frontend', 'Data/AI', 'DevOps'). Use empty string for all roles."
  - name: tech_stack
    type: string
    description: "A technology to search for in the tech stack (partial match, e.g., 'Python', 'Kubernetes'). Use empty string for all tech stacks."

---

# --- Tool 2: Get full details for a specific job ---
kind: tools
name: get-job-details
type: postgres-sql
source: jobs-db
description: >-
  Get full details for a specific job listing including its description,
  salary range, location, and number of openings. Use this tool when the
  developer asks about a particular job by title or company.
statement: |
  SELECT title, company, role, tech_stack, salary_range, location, openings, description
  FROM jobs
  WHERE LOWER(title) LIKE '%' || LOWER($1) || '%'
  OR LOWER(company) LIKE '%' || LOWER($1) || '%'
parameters:
  - name: search_term
    type: string
    description: "The job title or company name to look up (partial match supported)."

---

이 스크립트는 다음 리소스를 정의합니다.

  • 도구 1과 2 (search-jobs, get-job-details) - 표준 SQL 쿼리 도구입니다. 각각은 도구 이름 (에이전트가 보는 것)을 파라미터화된 SQL 문 (데이터베이스가 실행하는 것)에 매핑합니다. 매개변수는 $1, $2 위치 자리표시자를 사용합니다. 툴박스는 이를 준비된 문으로 실행하여 SQL 삽입을 방지합니다.

계속해서 tools.yaml--- 기호 아래에 다음 스크립트를 추가합니다.

# --- Embedding Model ---
kind: embeddingModels
name: gemini-embedding
type: gemini
model: gemini-embedding-001
dimension: 3072

---

이 스크립트는 다음 리소스를 정의합니다.

  • 임베딩 모델 (gemini-embedding): 3072차원 텍스트 임베딩을 생성하기 위해 Gemini의 gemini-embedding-001 모델을 호출하도록 Toolbox를 구성합니다. 툴박스는 애플리케이션 기본 사용자 인증 정보 (ADC)를 사용하여 인증하므로 Cloud Shell 또는 Cloud Run에 API 키가 필요하지 않습니다. 여기에서 구성된 dimension는 데이터베이스를 시드하기 위해 이전에 구성한 것과 동일해야 합니다.

계속해서 tools.yaml--- 기호 아래에 다음 스크립트를 추가합니다.

# --- Tool 3: Semantic search by description ---
kind: tools
name: search-jobs-by-description
type: postgres-sql
source: jobs-db
description: >-
  Find jobs that match a natural language description of what the developer
  is looking for. Use this tool when the developer describes their ideal job
  using interests, work style, career goals, or project type rather than a
  specific role or tech stack. Examples: "I want to work on AI chatbots,"
  "a remote job at a fintech startup," "something involving infrastructure
  and reliability."
statement: |
  SELECT title, company, role, tech_stack, salary_range, location, description
  FROM jobs
  WHERE description_embedding IS NOT NULL
  ORDER BY description_embedding <=> $1
  LIMIT 5
parameters:
  - name: search_query
    type: string
    description: "A natural language description of the kind of job the developer is looking for."
    embeddedBy: gemini-embedding

---

이 스크립트는 다음 리소스를 정의합니다.

  • 도구 3 (search-jobs-by-description) - 벡터 검색 도구 search_query 매개변수에는 embeddedBy: gemini-embedding이 있습니다. 이는 Toolbox가 원시 텍스트를 가로채 임베딩 모델로 전송하고 결과 벡터를 SQL 문에서 사용하도록 지시합니다. <=> 연산자는 pgvector의 코사인 거리입니다. 값이 작을수록 설명이 더 유사합니다.

마지막으로 tools.yaml--- 기호 아래에 마지막 도구를 추가합니다.

# --- Tool 4: Add a new job listing with automatic embedding ---
kind: tools
name: add-job
type: postgres-sql
source: jobs-db
description: >-
  Add a new job listing to the platform. Use this tool when a user asks
  to post a job that is not currently listed.
statement: |
  INSERT INTO jobs (title, company, role, tech_stack, salary_range, location, openings, description, description_embedding)
  VALUES ($1, $2, $3, $4, $5, $6, CAST($7 AS INTEGER), $8, $9)
  RETURNING title, company
parameters:
  - name: title
    type: string
    description: "The job title (e.g., 'Senior Backend Engineer')."
  - name: company
    type: string
    description: "The company name (e.g., 'Stripe', 'Spotify')."
  - name: role
    type: string
    description: "The role category (e.g., 'Backend', 'Frontend', 'Data/AI', 'DevOps')."
  - name: tech_stack
    type: string
    description: "Comma-separated list of technologies (e.g., 'Python, FastAPI, GCP')."
  - name: salary_range
    type: string
    description: "The salary range (e.g., '$150-200K/year')."
  - name: location
    type: string
    description: "Work location and arrangement (e.g., 'Remote')."
  - name: openings
    type: string
    description: "The number of open positions."
  - name: description
    type: string
    description: "A short description of the job (2-3 sentences)."
  - name: description_vector
    type: string
    description: "Auto-generated embedding vector for the job description."
    valueFromParam: description
    embeddedBy: gemini-embedding

이 스크립트는 다음 리소스를 정의합니다.

  • 도구 4 (add-job) - 벡터 수집을 보여줍니다. description_vector 매개변수에는 다음과 같은 두 개의 특수 필드가 있습니다.
  • valueFromParam: description - 도구 상자에서 description 매개변수의 값을 여기에 복사합니다. LLM은 이 매개변수를 볼 수 없습니다.
  • embeddedBy: gemini-embedding: Toolbox는 복사된 텍스트를 SQL에 전달하기 전에 벡터에 삽입합니다.

결과: 에이전트가 임베딩에 대해 아무것도 알지 못해도 하나의 도구 호출이 원시 설명 텍스트와 벡터 임베딩을 모두 저장합니다.

다중 문서 YAML 형식은 각 리소스를 ---로 구분합니다. 각 문서에는 무엇인지 정의하는 kind, name, type 필드가 있습니다. 요약하자면 다음 사항을 모두 구성했습니다.

  • 소스 데이터베이스 정의
  • 표준 필터로 데이터베이스를 쿼리하는 도구 ( 도구 1 및 2) 정의
  • 임베딩 모델 정의
  • 데이터베이스에 벡터 검색을 실행하는 도구 ( 도구 3) 정의
  • 벡터 데이터 수집 ( 도구 4)을 데이터베이스에 실행하는 도구 정의

임베딩 확인

Toolbox를 시작하기 전에 백그라운드 삽입 생성 작업이 완료되었는지 확인합니다. 이제 모든 작업에 삽입이 있는지 확인합니다.

psql "host=127.0.0.1 port=5432 dbname=jobs_db user=postgres password=$DB_PASSWORD" \
  -c "SELECT title, (description_embedding IS NOT NULL) AS has_embedding FROM jobs ORDER BY title;"

모든 행의 has_embedding 열에 t (true)이 표시되어야 합니다. 그렇지 않은 경우 모든 행 삽입 생성 프로세스가 완료될 때까지 기다릴 수 있습니다.

           title            | has_embedding 
-----------------------------+---------------
 AI Engineer                 | t
 Backend Engineer (Payments) | t
 Cloud Architect             | t
 Data Engineer               | t
 DevOps Engineer             | t
 Frontend Engineer           | t
 Full Stack Engineer         | t

도구 상자 서버 시작

설정 단계에서 이미 toolbox 실행 파일을 다운로드했습니다. 이 바이너리 파일이 존재하고 다운로드되었는지 확인합니다. 그렇지 않은 경우 다운로드하고 완료될 때까지 기다립니다.

cd ~/build-agent-adk-toolbox-cloudsql
if [ ! -f toolbox ]; then
  curl -O https://storage.googleapis.com/genai-toolbox/v0.27.0/linux/amd64/toolbox
fi
chmod +x toolbox

필수 환경 변수를 내보내고 도구 상자를 시작합니다. GOOGLE_CLOUD_LOCATIONGOOGLE_GENAI_USE_VERTEXAI 변수는 구성에 임베딩 모델이 포함되어 있으므로 필요합니다. GOOGLE_GENAI_USE_VERTEXAI는 Gemini SDK에 소비자 Gemini API 대신 Vertex AI를 통해 라우팅하도록 지시하고 GOOGLE_CLOUD_LOCATION는 사용할 리전 엔드포인트를 지정합니다.

export GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT
export GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION
export GOOGLE_GENAI_USE_VERTEXAI=true
export DB_PASSWORD=$DB_PASSWORD
export REGION=$REGION
./toolbox --tools-file tools.yaml &

아래와 같이 서버가 준비되었음을 확인하는 출력이 표시됩니다.

... INFO "Initialized 0 authServices: " 
... INFO "Initialized 1 embeddingModels: gemini-embedding" 
... INFO "Initialized 4 tools: add-job, search-jobs, get-job-details, search-jobs-by-description" 
...
... INFO "Server ready to serve!"

이전 단계와 마찬가지로 다른 프로세스가 생성되고 출력이 표시됩니다. 더 집중할 수 있도록 Cloud Shell에서 새 터미널 탭을 엽니다 (+ 아이콘 클릭).

b01e3fbd89f17332.png

작업 디렉터리로 다시 이동하여 이전 설정 스크립트를 사용하여 프로젝트를 활성화합니다.

cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env

도구 확인

도구 상자 API를 쿼리하여 등록된 모든 도구를 나열합니다.

curl -s http://localhost:5000/api/toolset | python3 -m json.tool

설명과 매개변수가 포함된 도구가 표시됩니다. 아래와 같이

...
       
"search-jobs-by-description": {
            "description": "Find jobs that match a natural language description of what the developer is looking for. Use this tool when the developer describes their ideal job using interests, work style, career goals, or project type rather than a specific role or tech stack. Examples: \"I want to work on AI chatbots,\" \"a remote job at a fintech startup,\" \"something involving infrastructure and reliability.\"",
            "parameters": [
                {
                    "name": "search_query",
                    "type": "string",
                    "required": true,
                    "description": "A natural language description of the kind of job the developer is looking for.",
                    "authSources": []
                }
            ],
            "authRequired": []
        }
...

search-jobs 도구를 직접 테스트합니다.

curl -s -X POST http://localhost:5000/api/tool/search-jobs/invoke \
  -H "Content-Type: application/json" \
  -d '{"role": "Backend", "tech_stack": ""}' | jq '.result | fromjson'

응답에는 시드 데이터의 두 백엔드 엔지니어링 작업이 포함되어야 합니다.

[
  {
    "title": "Backend Engineer (Payments)",
    "company": "Square",
    "role": "Backend",
    "tech_stack": "Java, Spring Boot, PostgreSQL, Kafka",
    "salary_range": "$160-220K/year",
    "location": "San Francisco, Hybrid",
    "openings": 3
  },
  {
    "title": "Senior Backend Engineer",
    "company": "Stripe",
    "role": "Backend",
    "tech_stack": "Go, PostgreSQL, gRPC, Kubernetes",
    "salary_range": "$180-250K/year",
    "location": "San Francisco, Hybrid",
    "openings": 3
  }
]

7. ADK 에이전트 빌드

이 단계에서는 ADK 에이전트를 실행 중인 Toolbox 서버에 연결하고 표준 쿼리, 시맨틱 검색, 벡터 수집 등 네 가지 도구를 모두 테스트합니다. 에이전트 코드는 최소한입니다. 모든 데이터베이스 로직은 tools.yaml에 있습니다.

에이전트 환경 구성

ADK는 이전 단계에서 이미 설정한 셸 환경에서 GOOGLE_GENAI_USE_VERTEXAI, GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION를 읽습니다. 에이전트별 변수는 TOOLBOX_URL뿐입니다. 이를 에이전트의 .env 파일에 추가합니다.

echo -e "\nTOOLBOX_URL=http://127.0.0.1:5000" >> jobs_agent/.env

에이전트 모듈 업데이트

Cloud Shell 편집기에서 jobs_agent/agent.py 열기

cloudshell edit jobs_agent/agent.py

다음 코드로 콘텐츠를 덮어씁니다.

# jobs_agent/agent.py
import os

from google.adk.agents import LlmAgent
from toolbox_adk import ToolboxToolset

TOOLBOX_URL = os.environ.get("TOOLBOX_URL", "http://127.0.0.1:5000")

toolbox = ToolboxToolset(TOOLBOX_URL)

root_agent = LlmAgent(
    name="jobs_agent",
    model="gemini-2.5-flash",
    instruction="""You are a helpful assistant at "TechJobs," a tech job listing platform.

Your job:
- Help developers browse job listings by role or tech stack.
- Provide full details about specific positions, including salary range and number of openings.
- Recommend jobs based on natural language descriptions of what the developer is looking for.
- Add new job listings to the platform when asked.

When a developer asks about a specific job by title or company, use the get-job-details tool.
When a developer asks for a specific role category or tech stack, use the search-jobs tool.
When a developer describes what kind of job they want — by interest area, work style,
career goals, or project type — use the search-jobs-by-description tool for semantic search.
When in doubt between search-jobs and search-jobs-by-description, prefer
search-jobs-by-description — it searches job descriptions and finds more relevant matches.

If a position has no openings (openings is 0), let the developer know
and suggest similar alternatives from the search results.

Be conversational, knowledgeable, and concise.""",
    tools=[toolbox],
)

여기에는 데이터베이스 코드가 없습니다. ToolboxToolset는 시작 시 Toolbox 서버에 연결하고 사용 가능한 모든 도구를 로드합니다. 에이전트는 이름으로 도구를 호출합니다. 도구 상자는 이러한 호출을 Cloud SQL에 대한 SQL 쿼리로 변환합니다.

TOOLBOX_URL 환경 변수는 로컬 개발의 경우 기본적으로 http://127.0.0.1:5000로 설정됩니다. 나중에 Cloud Run에 배포할 때 Toolbox 서비스의 Cloud Run URL로 이를 재정의하면 됩니다. 코드 변경은 필요하지 않습니다.

현재 안내에서는 두 가지 표준 도구 (search-jobsget-job-details)만 참조합니다. 다음 단계에서 시맨틱 검색 및 수집 도구를 추가할 때 이를 확장합니다.

에이전트 테스트

ADK 개발 UI를 시작합니다.

cd ~/build-agent-adk-toolbox-cloudsql
uv run adk web

Cloud Shell의 웹 미리보기 기능을 사용하거나 터미널에 표시된 URL을 ctrl + 클릭하여 터미널에 표시된 URL (일반적으로 http://localhost:8000)을 엽니다. 왼쪽 상단의 에이전트 드롭다운에서 jobs_agent를 선택합니다.

표준 쿼리 테스트

다음 프롬프트를 사용하여 표준 SQL 도구를 확인해 보세요.

What backend engineering jobs do you have?
Any jobs using Kubernetes?
Tell me about the Cloud Architect position

93ac33e7f73aa0b9.png 240c53376042a916.png

특정 역할이나 기술 스택에 매핑되지 않는 자연어 설명을 사용해 보세요.

I want a remote job where I can work on AI and machine learning
Find me something in fintech with good work-life balance
I'm interested in infrastructure and reliability engineering

에이전트는 쿼리 유형에 따라 적절한 도구를 선택하려고 시도합니다. 구조화된 필터는 search-jobs를 거치고 자연어 설명은 search-jobs-by-description를 거칩니다.

b0ea629f5c9b4c26.png

벡터 수집 테스트

에이전트에게 새 작업을 추가해 달라고 요청합니다.

Add a new job: 'Robotics Software Engineer' at Boston Dynamics, role Robotics, tech stack: Python, C++, ROS, Computer Vision, salary $160-230K/year, location Waltham MA, Hybrid, 2 openings. Description: Design and implement autonomous navigation and manipulation algorithms for next-generation robots. Work on perception pipelines using computer vision and lidar, develop motion planning software in C++ and Python, and test systems on real hardware in warehouse and logistics environments.

c601a7a9bc0a705b.png

이제 검색해 보세요.

Find me jobs involving autonomous systems and working with physical hardware

삽입 중에 삽입이 자동으로 생성되었으므로 별도의 단계가 필요하지 않습니다.

5a3d8e6f523dc18b.png

이제 ADK, MCP 도구 상자, CloudSQL을 활용하는 완전한 에이전트형 RAG 애플리케이션이 있습니다. 수고하셨습니다. 한 단계 더 나아가 이러한 앱을 Cloud Run에 배포해 보겠습니다.

이제 계속하기 전에 Ctrl+C를 두 번 눌러 프로세스를 종료하여 개발 UI를 중지합니다.

8. Cloud Run에 배포

에이전트와 Toolbox는 로컬로 작동합니다. 이 단계에서는 인터넷을 통해 액세스할 수 있도록 두 항목을 모두 Cloud Run 서비스로 배포합니다. 도구 상자 서비스는 Cloud Run에서 MCP 서버로 실행되고 에이전트 서비스는 여기에 연결됩니다.

배포를 위해 Toolbox 준비하기

도구 상자 서비스의 배포 디렉터리를 만듭니다.

cd ~/build-agent-adk-toolbox-cloudsql
mkdir -p deploy-toolbox
cp toolbox tools.yaml deploy-toolbox/

Toolbox의 Dockerfile을 만듭니다. Cloud Shell 편집기에서 deploy-toolbox/Dockerfile를 엽니다.

cloudshell edit deploy-toolbox/Dockerfile

다음 스크립트를 복사합니다.

# deploy-toolbox/Dockerfile
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY toolbox tools.yaml ./
RUN chmod +x toolbox
EXPOSE 8080
CMD ["./toolbox", "--tools-file", "tools.yaml", "--address", "0.0.0.0", "--port", "8080"]

툴박스 바이너리와 tools.yaml는 최소 Debian 이미지로 패키징됩니다. Cloud Run은 트래픽을 포트 8080으로 라우팅합니다.

도구 상자 서비스 배포

cd ~/build-agent-adk-toolbox-cloudsql
gcloud run deploy toolbox-service \
  --source deploy-toolbox/ \
  --region $REGION \
  --set-env-vars "DB_PASSWORD=$DB_PASSWORD,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT,REGION=$REGION,GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION,GOOGLE_GENAI_USE_VERTEXAI=true" \
  --allow-unauthenticated \
  --quiet

이 명령어는 소스를 Cloud Build에 제출하고, 컨테이너 이미지를 빌드하고, Artifact Registry에 푸시하고, Cloud Run에 배포합니다. 몇 분 정도 걸리므로 Cloud Shell에서 새 터미널 탭을 열어 (더하기 아이콘 클릭) 집중도를 높여 보겠습니다.

b01e3fbd89f17332.png

작업 디렉터리로 다시 이동하여 이전 설정 스크립트를 사용하여 프로젝트를 활성화합니다.

cd ~/build-agent-adk-toolbox-cloudsql
bash setup_verify_trial_project.sh && source .env

배포를 위해 에이전트 준비

도구 상자가 빌드되는 동안 에이전트의 배포 파일을 설정합니다.

프로젝트 루트에 Dockerfile를 만듭니다. Cloud Shell 편집기에서 Dockerfile를 엽니다.

cloudshell edit Dockerfile

그런 다음 다음 콘텐츠를 복사합니다.

# Dockerfile
FROM ghcr.io/astral-sh/uv:python3.12-trixie-slim
WORKDIR /app
COPY pyproject.toml ./
COPY uv.lock ./
RUN uv sync --no-dev
COPY jobs_agent/ jobs_agent/
EXPOSE 8080
CMD ["uv", "run", "adk", "web", "--host", "0.0.0.0", "--port", "8080"]

이 Dockerfile은 Python과 uv이 모두 사전 설치된 ghcr.io/astral-sh/uv를 기본 이미지로 사용하므로 pip를 통해 uv을 별도로 설치할 필요가 없습니다.

.dockerignore 파일을 만들어 컨테이너 이미지에서 불필요한 파일을 제외합니다.

cloudshell edit .dockerignore

그런 다음 다음 스크립트를 복사하여 붙여넣습니다.

# .dockerignore
.venv/
__pycache__/
*.pyc
.env
jobs_agent/.env
toolbox
tools.yaml
seed.sql
deploy-toolbox/

에이전트 서비스 배포

툴박스 배포가 완료될 때까지 기다립니다. 다음 명령어를 사용하여 Cloud Run URL을 가져옵니다.

TOOLBOX_URL=$(gcloud run services describe toolbox-service \
  --region=$REGION \
  --format='value(status.url)')
echo "Toolbox URL: $TOOLBOX_URL"

다음과 비슷한 출력이 표시됩니다.

Toolbox URL: https://toolbox-service-xxxxxx-xx.a.run.app

그런 다음 배포된 Toolbox가 작동하는지 확인합니다.

curl -s "$TOOLBOX_URL/api/toolset" | python3 -m json.tool | head -5

출력이 이 예와 같이 표시되면 배포가 이미 성공한 것입니다.

{
    "serverVersion": "0.27.0+binary.linux.amd64.c5524d3",
    "tools": {
        "add-job": {
            "description": "Add a new job listing to the platform. Use this tool when a user asks to post a job that is not currently listed.",

이제 도구 상자 URL을 환경 변수로 전달하여 에이전트를 배포합니다.

cd ~/build-agent-adk-toolbox-cloudsql
gcloud run deploy jobs-agent \
  --source . \
  --region $REGION \
  --set-env-vars "TOOLBOX_URL=$TOOLBOX_URL,GOOGLE_CLOUD_PROJECT=$GOOGLE_CLOUD_PROJECT,GOOGLE_CLOUD_LOCATION=$GOOGLE_CLOUD_LOCATION,GOOGLE_GENAI_USE_VERTEXAI=TRUE" \
  --allow-unauthenticated \
  --quiet

에이전트 코드는 환경에서 TOOLBOX_URL을 읽습니다 (이전에 설정함). 로컬에서는 http://127.0.0.1:5000를 가리키고 Cloud Run에서는 Toolbox 서비스 URL을 가리킵니다. 코드를 변경할 필요가 없습니다.

배포된 에이전트 테스트

에이전트의 Cloud Run URL을 가져옵니다.

AGENT_URL=$(gcloud run services describe jobs-agent \
  --region=$REGION \
  --format='value(status.url)')
echo "Agent URL: $AGENT_URL"

브라우저에서 URL을 엽니다. ADK 개발 UI가 로드됩니다. 로컬에서 사용하던 것과 동일한 인터페이스가 이제 Cloud Run에서 실행됩니다.

드롭다운에서 jobs_agent를 선택하고 테스트합니다.

What backend engineering jobs do you have?
I want a remote job working on AI and machine learning

두 쿼리 모두 배포된 서비스를 통해 작동합니다. Cloud Run의 에이전트가 Cloud Run의 Toolbox를 호출하고, Toolbox가 Cloud SQL을 쿼리합니다.

9. 축하합니다 / 정리

데이터베이스용 MCP 도구 상자를 사용하여 ADK 에이전트와 Cloud SQL PostgreSQL을 연결하는 스마트 채용 게시판 어시스턴트를 빌드하고 배포했습니다. 이 어시스턴트는 표준 SQL 쿼리와 시맨틱 벡터 검색을 모두 사용합니다.

학습한 내용

  • MCP가 AI 에이전트의 도구 액세스를 표준화하는 방법과 데이터베이스용 MCP 도구 상자가 이를 데이터베이스 작업에 적용하여 선언적 YAML 구성으로 맞춤 데이터베이스 코드를 대체하는 방법
  • cloud-sql-postgres 소스 유형을 사용하여 Cloud SQL PostgreSQL을 도구 상자 데이터 소스로 구성하는 방법
  • SQL 삽입을 방지하는 매개변수화된 문을 사용하여 표준 SQL 쿼리 도구를 정의하는 방법
  • pgvector 및 gemini-embedding-001를 사용하여 벡터 검색을 사용 설정하는 방법(자동 쿼리 임베딩을 위한 embeddedBy 매개변수 사용)
  • valueFromParam를 통해 자동 벡터 수집이 가능합니다. LLM이 텍스트 설명을 제공하면 Toolbox가 텍스트와 함께 벡터를 자동으로 복사, 삽입, 저장합니다.
  • ADK의 ToolboxToolset가 실행 중인 도구 상자 서버에서 도구를 로드하여 에이전트 코드를 최소화하고 데이터베이스 로직을 완전히 분리하는 방법
  • 도구 상자 MCP 서버와 ADK 에이전트를 별도의 서비스로 Cloud Run에 배포하는 방법

정리

이 Codelab에서 생성된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 개별 리소스를 삭제하거나 전체 프로젝트를 삭제하면 됩니다.

삭제하는 가장 쉬운 방법은 프로젝트를 삭제하는 것입니다. 이렇게 하면 프로젝트와 연결된 모든 리소스가 삭제됩니다.

gcloud projects delete $GOOGLE_CLOUD_PROJECT

옵션 2: 개별 리소스 삭제

프로젝트는 유지하고 이 Codelab에서 만든 리소스만 삭제하려면 다음 단계를 따르세요.

gcloud run services delete jobs-agent --region=$REGION --quiet
gcloud run services delete toolbox-service --region=$REGION --quiet
gcloud sql instances delete jobs-instance --quiet
gcloud artifacts repositories delete cloud-run-source-deploy --location=$REGION --quiet 2>/dev/null