GKE 환경에서 A2A 프로토콜을 활용한 AI 에이전트 플랫폼 최소 구성 구현
요약
본 기사는 GKE(Google Kubernetes Engine) 환경에서 A2A(Agent-to-Agent) 프로토콜을 활용하여 다중 AI 에이전트 플랫폼의 최소 구성을 구현하는 방법을 다룹니다. Google의 ADK를 사용하여 3개의 에이전트가 서로 통신하며 작업을 수행하는 구조를 설명하며, Workload Identity를 통해 보안 키 없이 Vertex AI를 호출하는 키리스(Keyless) 인증 방식에 초점을 맞춥니다.
핵심 포인트
- A2A(Agent-to-Agent) 프로토콜의 핵심 개념(Agent Card, Message, Task, Part) 이해
- ADK의 to_a2a() 및 RemoteA2aAgent를 활용한 에이전트 간 RPC 통신 구현
- GKE 환경에서 Workload Identity를 이용한 보안 인증 및 Vertex AI 연동
- 단일 LLM 호출을 넘어 복수의 에이전트가 Pod 단위로 독립 동작하는 분산 실행 구조 설계
서론
최근 **AI 에이전트 플랫폼 (AI Agent Platform)**이라는 키워드를 자주 접할 수 있게 되었습니다. 구체적인 움직임을 살펴보면 다음과 같은 흐름이 있습니다.
- Google이 Gemini Enterprise Agent Platform을 발표. Vertex AI의 에이전트 관련 기능을 발전 및 통합하는 형태로, 에이전트의 구축·배포·데이터 연동·거버넌스·최적화까지 하나의 기반으로 집약하는 방향을 제시했습니다 (Google Cloud Blog).
- Gartner의 예측: 2027년까지 기업의 70%가 멀티 AI 에이전트 (Multi AI Agent)를 채택할 것이며, 시장 규모도 2028년에는 150억 달러 규모에 도달할 전망입니다. 일본 국내에서도 『멀티 AI 에이전트 / 멀티 에이전트 플랫폼 백서 2026년판』이 간행되는 등 흐름이 확산되고 있습니다.
「단일 LLM을 프롬프트로 호출하는」 단계에서, 「복수의 에이전트를 지속적으로 구동하는 운영 기반을 만드는」 단계로 업계의 관심이 급격히 이동하고 있음을 실감합니다.
저 또한 이 분야에 강한 관심을 가지고 있으며, 언젠가는 Kubernetes 상에서 AI 에이전트 플랫폼을 직접 만들고 싶다고 생각하고 있습니다. 복수의 에이전트가 Pod로서 독립적으로 움직이고, 서비스 간에 대화하며, 필요에 따라 스케일 아웃 (Scale-out)하는 구조. 더 나아가 공유 메모리 기반이나 오케스트레이션 (Orchestration) 레이어가 올라가는 그림을 그리고 있습니다.
다만, 갑자기 「플랫폼」을 조립하기 전에, 그 토대가 되는 두 가지 요소 ── **에이전트 간 통신 표준 프로토콜 (A2A, Agent-to-Agent)**과 **Kubernetes 상에서의 분산 실행 (GKE)**이 최소 구성에서 어떻게 맞물리는지 정리해 두고 싶습니다. 본 기사에서는 그 최소 구성을 해설합니다.
주제는 Google 공식 Agent Development Kit (ADK)로 3개의 에이전트를 만들어 A2A 프로토콜로 대화하게 하고, 최종적으로 GKE 상에 올리는 구성입니다.
주제의 구성
주제로 삼는 것은 다음과 같은 구성을 GKE 상에서 구동하는 최소 시스템입니다.
각 Pod에서 Vertex AI로 향하는 점선 화살표는 **Workload Identity (WI)**라는 GKE의 메커니 메커니즘으로 인증합니다. 서비스 계정(Service Account)의 키 파일을 전혀 사용하지 않고 Pod가 GCP의 API를 호출할 수 있게 하는 방식으로, 자세한 내용은 뒤의 장에서 설명합니다.
「20면체 주사위를 던져서 나온 숫자가 소수인지 판정해 주세요」라고 말을 걸면, root-agent가 dice-agent로 주사위를 던지고, 그 결과를 prime-agent에 전달하여 소수 판정을 수행한 뒤, 최종 답변을 통합하여 반환합니다.
배후에서는 root-agent Pod에서 dice-agent Pod로 HTTP 기반의 A2A RPC가 전달되고, 이어서 prime-agent Pod로 다시 한번 A2A RPC가 전달됩니다. 각각의 Pod는 Vertex AI에 Workload Identity를 통해 액세스하며, 서비스 계정 키는 전혀 사용하지 않습니다.
본 기사의 목표
읽고 난 시점에 다음 내용을 구현 수준에서 이해하는 것을 목표로 합니다.
- A2A 프로토콜의 최소 용어 (Agent Card / Message / Task / Part)가 구현과 어떻게 대응하는지
- ADK의
to_a2a()와RemoteA2aAgent가 무엇을 하고 있는지 - 로컬에서 GKE로 옮길 때 무엇이 변하는지
- Workload Identity를 통해 Vertex AI를 키리스 (Keyless)로 호출하는 최소한의 설정
본 기사에서 다루지 않는 것
학습을 최소 구성으로 한정하기 위해 다음 사항은 제외했습니다.
- root-agent의 외부 공개 (LoadBalancer / Ingress / Gateway API)
- 세션 (Session) / 장기 메모리 (Long-term Memory) / RAG
- HPA / KEDA 등의 오토스케일링 (Autoscaling)
- NetworkPolicy / Istio 등의 서비스 메쉬 (Service Mesh)
- 본격적인 로그·트레이싱 (Tracing) 기반
본 기사의 구성은 클러스터 내부 통신만으로 동작하는 것이며, 실제 운영에는 보안에 대한 추가 검토가 필요합니다.
사용 버전
google-adk: 1.20 계열 (to_a2a/RemoteA2aAgent포함)
(본 기사 작성 시점 기준 EXPERIMENTAL) - A2A 프로토콜: ADK 포함 버전(실제 값은 /.well-known/agent-card.json의 protocolVersion에서 확인 가능) - GKE: Standard 클러스터 (--release-channel=regular) - Python: 3.11 - LLM: Vertex AI 상의 gemini-2.5-flash
to_a2a()와 RemoteA2aAgent는 ADK의 experimental 기능이므로, 기동 시 경고가 발생합니다. 본 기사의 코드는 작성 시점에 동작을 확인했으나, API는 향후 변경될 가능성이 있습니다. 각 API의 최신 사양은 ADK / A2A의 공식 문서를 확인해 주세요.
전체 구성
본 기사에서 만든 에이전트는 3개입니다.
| 에이전트 | 역할 | 공개 포트(GKE) |
|---|---|---|
root_agent | 사용자 입력을 받아, dice / prime에 처리를 위임 | 8000 |
dice_agent | roll_die(sides)로 주사위를 굴림 | 8001 |
prime_agent | is_prime(n)으로 소수 판정 | 8002 |
사용된 스택.
| 계층 | 채택 |
|---|---|
| LLM | Vertex AI (Gemini 2.5 Flash) |
| ... |
여기서부터는 이 구성을 로컬 → GKE 순으로 구축해 나가겠습니다.
A2A 용어 정리
A2A는 HTTP + JSON-RPC 기반의, 에이전트끼리 서로를 발견하고, 능력을 이해하며, 표준 형식으로 태스크(Task)를 주고받기 위한 프로토콜입니다. 'LLM끼리 대충 채팅하게 만드는 메커니즘'이 아니라, 원격의 에이전트에게 구조화된 태스크를 보내기 위한 규약입니다.
구현에 들어가기 전, 최소한으로 파악해야 할 용어들을 표로 정리합니다.
| 용어 | 역할 | 본 기사에서의 구체적인 예 |
|---|---|---|
| Agent Card | 에이전트의 능력·URL·인증 요건을 기술하는 메타데이터. /.well-known/agent-card.json으로 공개 | dice_agent의 name / description / roll_die 스킬 |
| Message | 1회의 발화·입력·응답 | "20면체 주사위를 굴려줘" |
| Task | 상태를 가진 작업 단위 | dice 에이전트에 대한 "주사위 굴리기" 요청 |
| Part | Message / Artifact를 구성하는 최소 단위(text / file / data) | text part |
| Artifact | Task의 최종 결과물 | 주사위 눈을 포함한 응답 |
"클라이언트가 Agent Card를 취득 → 태스크를 보냄 → 에이전트가 Task를 처리 → Artifact를 반환"이 일련의 흐름입니다.
MCP와의 차이점을 한 줄로 말하자면, MCP는 에이전트와 도구(Tool) 사이, A2A는 에이전트와 에이전트 사이의 프로토콜입니다. 역할이 다르기 때문에 공존하는 경우도 많습니다.
to_a2a()로 A2A Server화
가장 먼저 만드는 것은, 우선 호출되는 쪽의 에이전트로, 주사위를 굴리기만 하는 것입니다. 이를 ADK로 만들고, to_a2a()를 한 줄 호출하는 것만으로 HTTP A2A Server로 변환합니다.
원래의 ADK Agent
agents/dice_agent/agent.py:
import random
from google.adk.agents import Agent
def roll_die(sides: int) -> int:
...
여기까지는 일반적인 ADK Agent이며, adk run agents/dice_agent로 로컬 대화가 가능합니다.
to_a2a()로 A2A Server화
A2A Server로 만드는 것은 to_a2a() 한 줄뿐입니다. agents/dice_agent/main.py:
import os
from google.adk.a2a.utils.agent_to_a2a import to_a2a
from .agent import root_agent
...
이를 uvicorn으로 실행합니다.
uv run uvicorn agents.dice_agent.main:app --host 127.0.0.1 --port 8001
실행 로그에 다음과 같은 줄이 나타나면 성공입니다.
INFO: Started server process [12345]
INFO: Uvicorn running on http://127.0.0.1:8001 (Press CTRL+C to quit)
to_a2a()가 내부적으로 수행하는 작업은 크게 세 가지입니다.
- ADK Agent를 A2A 프로토콜의 엔드포인트(Endpoint)로 감싸기 (
POST /로 JSON-RPC를 수신) - Agent Card를 자동 생성하여
/.well-known/agent-card.json으로 공개하기 - Starlette 앱(
app변수)으로 반환하기
A2A_HOST 환경 변수를 분리한 이유는 Agent Card에 기재되는 URL을 전환할 수 있도록 하기 위해서입니다.
여기까지가 A2A Server를 구동하는 절차입니다. 다음으로, 이를 호출하는 측의 에이전트를 살펴보겠습니다.
RemoteA2aAgent를 통한 호출
A2A는 Server를 구축하는 것만으로는 아무 일도 일어나지 않습니다. Client 측이 Agent Card를 가져오고, 태스크(Task)를 보내야 비로소 통신이 성립됩니다. ADK에는 클라이언트 역할을 하는 RemoteA2aAgent가 있습니다.
root_agent 구현
agents/root_agent/agent.py (발췌):
import os
from google.adk.agents import Agent
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
...
RemoteA2aAgent는 **URL만을 가진 프록시 (Proxy)**이며, 로컬의 ADK Agent와 동일한 인터페이스로sub_agents에 나열될 수 있습니다.- URL은
Agent Card의 URL(/.well-known/agent-card.json)을 가리킵니다.
DICE_AGENT_URL을 환경 변수화한 이유는 로컬과 GKE에서 참조 대상을 전환하기 위해서입니다. 로컬에서는 http://localhost:8001/...을 사용하고, GKE에서는 Service DNS 이름을 사용하게 됩니다.
동작 확인
다른 터미널에서 root_agent를 실행합니다.
uv run adk run agents/root_agent
여기서 "20면체 주사위를 굴려줘"라고 말하면, root_agent가 dice_agent에게 처리를 위임하고 결과를 반환합니다.
이때 A2A Server 측(dice_agent를 실행 중인 터미널)을 보면, POST / 액세스 로그가 출력되는 것을 확인할 수 있습니다.
INFO: 127.0.0.1:54321 - "POST / HTTP/1.1" 200 OK
이것이 A2A RPC의 실체입니다. /.well-known/agent-card.json에서 능력을 발견하고, POST /로 JSON-RPC를 던지는 단순한 프로토콜입니다.
참고로 RemoteA2aAgent 및 to_a2a를 처음 사용하면, 실행 시 EXPERIMENTAL 접두사가 붙은 경고가 나타납니다. ADK의 A2A 기능은 집필 시점 기준으로 experimental(실험적) 단계이므로, 향후 API가 변경될 가능성이 있습니다. 동작에는 영향을 미치지 않습니다.
curl을 이용한 Agent Card 확인
A2A의 핵심은 Agent Card입니다. 실제로 동작하는 모습을 한 번 확인해 두면 이후 장의 동작을 이해하기 쉬워집니다.
A2A Server (dice_agent)가 실행 중인 상태에서, 다른 터미널을 통해 요청을 보냅니다.
curl http://localhost:8001/.well-known/agent-card.json | jq .
반환되는 JSON (발췌 · 주요 필드만 표시):
{
"name": "dice_agent",
"description": "임의의 면을 가진 주사위를 던지는 에이전트.",
...
}
skills
필드 내용은 ADK의 버전이나 to_a2a()의 생성 로직에 따라 달라지므로, 직접 curl을 실행하여 확인하는 것이 가장 확실합니다. 본 기사에서 중요한 것은 url과 protocolVersion 두 가지입니다.
주목해야 할 부분은 "url": "http://localhost:8001/"입니다. 이는 클라이언트 (RemoteA2aAgent)가 JSON-RPC를 보내는 목적지이며, 서버 측의 A2A_HOST에 의해 결정됩니다. 로컬에서 자기 자신을 호출하는 경우에는 이것으로 충분하지만, 다른 호스트(다른 Pod)에서 호출할 때는 이곳이 해석 가능한 호스트명이어야 통신이 성립됩니다.
예를 들어 A2A_HOST를 지정하지 않고 0.0.0.0으로 리슨(Listen)시킨 상태에서 Agent Card를 가져오면, URL이 http://0.0.0.0:8001/이 되어 클라이언트가 "0.0.0.0에는 접속할 수 없다"라고 응답하게 됩니다.
여기까지가 로컬 A2A의 최소 구성입니다.
- ADK Agent를
to_a2a()로 A2A Server화할 수 있다 - Agent Card가 어떻게 공개되는지 실물로 확인할 수 있다
RemoteA2aAgent를 통해 다른 에이전트로부터 A2A를 거쳐 호출할 수 있다
다음은 이 구성을 그대로 GKE로 옮겨갑니다.
GKE로의 Pod 배포
로컬 구성을 거의 그대로 GKE로 가져갑니다. 여기서 수행할 작업은 크게 세 가지뿐입니다.
- GKE Standard 클러스터 생성 (Workload Identity를 활성화하여)
- Artifact Registry에 이미지 push (linux/amd64로)
- Deployment / Service apply
최종적인 GKE 구성은 위 그림과 같습니다. Namespace adk-a2a-lab 하위에 root / dice / prime의 Deployment와 ClusterIP Service가 나열되며, root-agent가 dice / prime의 Service DNS 명을 통해 내부 통신을 하는 구조입니다.
이 장에서는 우선 root-agent와 dice-agent 두 가지만 GKE에 전개합니다. prime-agent는 이후의 "1 턴 1 리모트" 장에서 추가합니다.
클러스터 생성
export PROJECT_ID=a2a-gke
export REGION=us-central1
export ZONE=us-central1-a
...
--workload-pool=$PROJECT_ID.svc.id.goog를 지정함으로써 Workload Identity가 활성화됩니다. 나중에 "KSA에서 GSA의 권한을 빌려오는" 설정을 할 것이므로, 여기서 지정해두지 않으면 애초에 권한을 빌려올 수 없습니다.
클러스터 생성에는 약 3~7분 정도 소요됩니다. 학습용 클러스터이므로 e2-small × 2를 사용합니다. Standard 클러스터를 선택한 이유는 Workload Identity 설정을 직접 작성해보고 싶었기 때문입니다 (Autopilot을 사용하면 많은 부분이 자동화됩니다).
Artifact Registry로의 push
docker buildx build --platform linux/amd64 \
-t us-central1-docker.pkg.dev/a2a-gke/a2a-gke-lab/dice-agent:dev \
-f docker/dice-agent.Dockerfile \
...
GKE의 노드는 linux/amd64이므로, 호스트의 아키텍처가 다를 경우를 대비하여 항상 --platform linux/amd64를 명시해두는 것이 안전합니다.
Deployment / Service의 apply
k8s/dice-agent-deployment.yaml (발췌):
apiVersion: apps/v1
kind: Deployment
metadata:
...
readinessProbe에서 Agent Card의 경로를 호출하는 이유는 A2A Server로서 실용적인 수준의 상태가 되었는지 확인하기 위해서입니다. 프로세스가 기동된 것뿐만 아니라, Agent Card가 응답할 수 있는 상태, 즉 A2A 클라이언트(Client)를 수용할 수 있는 상태까지를 「Ready」로 간주합니다.
Service는 ClusterIP만 사용:
apiVersion: v1
kind: Service
metadata
...
remote-agent는 클러스터 외부에 공개할 이유가 없으므로 ClusterIP만 사용합니다. root-agent 또한 마찬가지로 ClusterIP로 설정하고, 확인은 kubectl port-forward로 해결합니다.
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/serviceaccount.yaml
kubectl apply -f k8s/dice-agent-deployment.yaml
...
단, kubectl apply를 수행하더라도 Pod 자체는 기동되지만, 실제로 요청을 보내면 Vertex AI 인증에서 실패합니다. 이 인증을 성립시키는 것이 다음에 다룰 Workload Identity입니다.
Workload Identity를 통한 키리스 (Keyless) 인증
Pod가 Vertex AI를 호출하려면 어떤 형태로든 GCP 인증 정보가 필요합니다. Service Account 키를 Secret으로 배포하고 GOOGLE_APPLICATION_CREDENTIALS로 참조하게 하는 것이 전통적인 방식이지만, 키 파일의 관리, 로테이션 (Rotation), 유출 리스크 등 운영상의 부담이 급격히 증가합니다.
Workload Identity (WI)는 이를 **「Pod에 연결된 Kubernetes ServiceAccount (KSA)가 대응하는 GCP ServiceAccount (GSA)의 권한을 빌려온다」**는 메커니즘으로 해결합니다. 키를 전혀 배포하지 않고도 Vertex AI를 호출할 수 있게 됩니다.
Pod가 KSA를 참조하고, KSA의 annotation (주석)이 GSA를 가리키며, GSA 측의 IAM policy (정책)가 KSA로부터의 권한 대여를 허용하는 이 세 가지 연결을 통해 Vertex AI 호출 권한이 성립됩니다.
삼각관계의 내용
- GSA (GCP 측):
adk-a2a-runtime@a2a-gke.iam.gserviceaccount.com이며,roles/aiplatform.user권한을 가짐 - KSA (K8s 측): namespace
adk-a2a-lab의adk-a2a-runtime이며, Pod의serviceAccountName에 지정함 - WI binding: KSA에 대해
roles/iam.workloadIdentityUser권한을 GSA 측에 부여하여, "이 KSA가 GSA를 빌려 써도 된다"라고 선언함
요컨대, IAM 측에서 하나의 binding (결합)을, K8s 측에서 하나의 annotation (주석)을 추가하기만 하면 됩니다.
설정 3단계
1. GSA 생성 + Vertex AI 권한 부여
gcloud iam service-accounts create adk-a2a-runtime \
--display-name="ADK A2A runtime" \
--project=$PROJECT_ID
...
2. KSA에 annotation 추가
k8s/serviceaccount.yaml:
apiVersion: v1
kind: ServiceAccount
metadata
...
annotation의 이름은 iam.gke.io/gcp-service-account이며, 여기에 빌려 쓰고 싶은 GSA의 이메일 주소를 입력합니다.
3. WI binding
gcloud iam service-accounts add-iam-policy-binding \
adk-a2a-runtime@$PROJECT_ID.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
...
이것은 KSA adk-a2a-lab/adk-a2a-runtime에 대해 "GSA를 빌려 써도 좋다"라고 허가하는 명령입니다. <project>.svc.id.goog[<namespace>/<ksa>]라는 독특한 형식이 WI (Workload Identity)의 특징입니다.
WI가 통과되면, Pod 내부에서 gcloud auth application-default print-access-token을 실행했을 때 GSA에 연결된 액세스 토큰 (Access Token)을 획득할 수 있습니다. 서비스 계정 키 (Service Account Key)를 단 하나도 생성하지 않았음에도 Pod가 GCP API를 호출할 수 있는 것, 이것이 WI가 해결하는 과제입니다.
Service DNS와 Agent Card URL
GKE에 올리고 WI가 통과된 후, 다음에 맞닥뜨리는 것은 A2A 특유의 문제입니다. Agent Card 내의 URL이 클러스터(Cluster) 내에서 해결 가능한 호스트 이름(Hostname)이 아니라면, root-agent에서 dice-agent로 연결할 수 없습니다.
Pod에서 보이는 dice-agent의 이름
dice-agent를 ClusterIP로 공개하면, 클러스터 내부에서는 전체 DNS 이름 (FQDN)으로 이름 해결 (Name Resolution)이 가능합니다.
dice-agent-svc.adk-a2a-lab.svc.cluster.local
이 이름을 Agent Card 내의 URL에 기록하지 않으면, root-agent가 호출하는 목적지가 0.0.0.0인 상태로 남아 통신이 성립되지 않습니다. 설정은 Deployment의 env (환경 변수)를 통해 전달합니다 (GKE 배포 장에서 다룬 YAML 재게시).
env:
- name: A2A_HOST
value: dice-agent-svc.adk-a2a-lab.svc.cluster.local
...
그리고 root-agent 측의 DICE_AGENT_URL 또한 동일한 DNS를 가리킵니다.
env:
- name: DICE_AGENT_URL
value: "http://dice-agent-svc.adk-a2a-lab.svc.cluster.local:8001/.well-known/agent-card.json"
동작 확인
port-forward로 Agent Card를 확인하여, URL이 DNS 이름으로 되어 있는지 확인합니다.
kubectl port-forward -n adk-a2a-lab svc/dice-agent-svc 8001:8001 &
curl http://localhost:8001/.well-known/agent-card.json | jq .url
# → "http://dice-agent-svc.adk-a2a-lab.svc.cluster.local:8001/"
http://0.0.0.0:8001/이 반환된다면 A2A_HOST 설정이 누락된 것입니다. Deployment의 env를 다시 확인하십시오.
설계 판단으로는, "Agent Card URL은 고정값이 아니라 환경 변수로 교체한다"라는 방침을 따릅니다. 동일한 이미지에서 A2A_HOST를 바꾸는 것만으로 로컬과 GKE 환경 어디에서든 동작할 수 있습니다. 설정 분리의 전형적인 사례입니다.
"1 턴 1 리모트" 제약
여기까지 하면 root → dice의 단순한 A2A 통신이 성립됩니다. 다음으로 remote agent를 2개로 늘려 조금 더 복잡한 시나리오를 다룹니다. 이를 통해 본 기사의 최종 목표인 "주사위를 던져 소수를 판별하기"가 완성됩니다.
그리고 여기서 RemoteA2aAgent의 설계상의 제약에 부딪히게 됩니다.
prime_agent 추가
prime_agent는 dice_agent와 거의 동일한 구조이며, is_prime 도구 (Tool)를 가지고 있을 뿐입니다.
def is_prime(n: int) -> dict:
if n < 2:
return {"n": n, "is_prime": False}
...
to_a2a()를 통해 A2A Server로 만들고, port 8002로 공개한 뒤, prime-agent-deployment.yaml을 apply하는 흐름은 dice_agent와 완전히 동일합니다.
root_agent에는 두 번째 RemoteA2aAgent를 sub_agents에 추가합니다.
prime_remote = RemoteA2aAgent(
name="prime_agent",
agent_card=PRIME_AGENT_URL,
...
동작 확인
실제로 "20면체 주사위를 던져서, 그 눈이 소수인지 판정해 주세요"라고 말을 걸면, 그럴듯하게 통합된 응답이 돌아옵니다. 그런데 kubectl logs로 내부 흐름을 추적해 보면, 생각보다 단계(turn)가 많다는 것을 알 수 있습니다.
사용자의 단 한 번의 요청에 대해, root-agent가 "dice를 호출 → 결과를 바탕으로 prime을 호출 → 통합"이라는 3단계의 턴을 내부적으로 거칩니다.
제약의 정체
적어도 이번 ADK / RemoteA2aAgent 구성에서는, 한 번의 판단당 하나의 remote agent로 라우팅(routing)되는 동작을 보였습니다. 그 때문에 "주사위를 던져서 소수인지 판정해줘"라는 복합 요구는 내부적으로 다음의 3단계로 분해되어 처리됩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기