Codelab: Spanner MCP 서버

1. 개요

이 Codelab에서는 gemini-cli와 Google의 모델 컨텍스트 프로토콜 (MCP) 서버를 사용하여 Spanner에서 그래프 쿼리를 실행하는 방법을 보여줍니다. 관리형 MCP 서비스와 Spanner Graph를 비롯한 Spanner의 멀티 모델 데이터베이스를 통합하면 복잡한 GQL (Graph Query Language) 또는 SQL 쿼리를 수동으로 작성하지 않고도 단일 데이터베이스에서 자연어를 사용하여 사기 서클이나 공급망 종속성과 같은 데이터의 숨겨진 관계를 파악할 수 있습니다.

43e1993ca796652e.png

학습할 내용

  • MCP용 Spanner Graph를 포함한 Spanner 멀티 모델 데이터베이스를 설정하는 방법
  • Gemini CLI를 관리형 원격 Spanner 서비스 엔드포인트에 연결하는 방법
  • 자연어를 사용하여 GQL과 통합된 SQL을 자동으로 생성하여 관계형 작업과 함께 그래프 순회 및 패턴 일치를 실행하는 방법
  • AI 워크플로에서 그래프 데이터를 보호하기 위한 권장사항

기본 요건

  • 결제가 사용 설정된 Google Cloud 프로젝트
  • 터미널 (예: Cloud Shell)에 액세스할 수 있어야 합니다. Codelab을 참고하세요.
  • gcloud CLI가 설치되고 인증되었습니다.
  • Gemini CLI에 대한 액세스 권한

참고: 모든 명령어는 Unix 터미널에서 실행됩니다. 위의 사전 요구사항을 참고하여 적절한 인증으로 gcloud에 액세스할 수 있는 터미널에 액세스하세요.

2. Spanner 멀티 모델 환경 설정

관리 MCP는 데이터베이스 스키마가 사전 정의된 경우에 가장 효과적입니다. Spanner Graph 샘플을 기반으로 금융 '사기 감지' 그래프를 만듭니다.

API 사용 설정

export PROJECT_ID="YOUR_PROJECT_ID"
gcloud config set project ${PROJECT_ID}

# Enable Spanner's MCP endpoint
gcloud beta services mcp enable spanner.googleapis.com --project=${PROJECT_ID}

데이터베이스 스키마 만들기

데이터베이스 테이블과 속성 그래프를 사용하여 인스턴스와 데이터베이스를 만듭니다. 이 스키마는 계정, 개인, 계정 간 이체를 추적합니다.

참고: Spanner Studio에서 이러한 DDL 문을 실행할 수 있습니다. GCP 콘솔에서 Spanner 데이터베이스를 만들고 쿼리하는 방법에 대한 자세한 내용은 이 링크를 참고하세요.

CREATE TABLE Account (
  id INT64 NOT NULL,
  create_time TIMESTAMP,
  is_blocked BOOL,
  nick_name STRING(MAX),
) PRIMARY KEY(id);

CREATE TABLE Person (
  id INT64 NOT NULL,
  name STRING(MAX),
  birthday TIMESTAMP,
  country STRING(MAX),
  city STRING(MAX),
) PRIMARY KEY(id);

CREATE TABLE AccountTransferAccount (
  id INT64 NOT NULL,
  to_id INT64 NOT NULL,
  amount FLOAT64,
  create_time TIMESTAMP NOT NULL,
  order_number STRING(MAX),
  FOREIGN KEY(to_id) REFERENCES Account(id),
) PRIMARY KEY(id, to_id, create_time),
  INTERLEAVE IN PARENT Account ON DELETE CASCADE;

CREATE TABLE PersonOwnAccount (
  id INT64 NOT NULL,
  account_id INT64 NOT NULL,
  create_time TIMESTAMP,
  FOREIGN KEY(account_id) REFERENCES Account(id),
) PRIMARY KEY(id, account_id),
  INTERLEAVE IN PARENT Person ON DELETE CASCADE;

CREATE PROPERTY GRAPH FinGraph
  NODE TABLES(
    Account
      KEY(id)
      LABEL Account PROPERTIES(
        create_time,
        id,
        is_blocked,
        nick_name),

    Person
      KEY(id)
      LABEL Person PROPERTIES(
        birthday,
        city,
        country,
        id,
        name)
  )
  EDGE TABLES(
    AccountTransferAccount
      KEY(id, to_id, create_time)
      SOURCE KEY(id) REFERENCES Account(id)
      DESTINATION KEY(to_id) REFERENCES Account(id)
      LABEL Transfers PROPERTIES(
        amount,
        create_time,
        id,
        order_number,
        to_id),

    PersonOwnAccount
      KEY(id, account_id)
      SOURCE KEY(id) REFERENCES Person(id)
      DESTINATION KEY(account_id) REFERENCES Account(id)
      LABEL Owns PROPERTIES(
        account_id,
        create_time,
        id)
  );

데이터 채우기

사용자 삽입

INSERT INTO Person (id, name, birthday, country, city) VALUES
(1, 'Alex', '1990-01-01T00:00:00Z', 'USA', 'New York'),
(2, 'Lee', '1985-05-15T00:00:00Z', 'USA', 'San Francisco'),
(3, 'Dana', '1995-08-20T00:00:00Z', 'Canada', 'Vancouver'),
(4, 'Maria', '1992-04-15T00:00:00Z', 'USA', 'Chicago'),
(5, 'David', '1988-11-20T00:00:00Z', 'Canada', 'Toronto');

계정 삽입

INSERT INTO Account (id, create_time, is_blocked, nick_name) VALUES
(7, '2020-01-10T14:22:20.222Z', false, 'Vacation Fund'),
(16, '2020-01-28T01:55:09.206Z', true, 'Vacation Fund'),
(20, '2020-02-18T13:44:20.655Z', false, 'Rainy Day Fund'),
(25, '2023-01-15T10:00:00Z', false, 'Savings'),
(30, '2023-02-20T11:00:00Z', false, 'Checking');
INSERT INTO PersonOwnAccount (id, account_id, create_time) VALUES
(1, 7, '2020-01-10T14:22:20.222Z'),
(2, 16, '2020-01-28T01:55:09.206Z'),
(3, 20, '2020-02-18T13:44:20.655Z'),
(4, 25, '2023-01-15T10:00:00Z'),
(5, 30, '2023-02-20T11:00:00Z');

전송 추가

INSERT INTO AccountTransferAccount (id, to_id, amount, create_time, order_number) VALUES
(7, 16, 300, '2024-02-28T10:00:00Z', 'ORD123'),
(7, 16, 100, '2024-02-29T11:00:00Z', 'ORD124'),
(16, 20, 300, '2024-02-29T12:00:00Z', 'ORD125'),
(20, 7, 500, '2024-02-29T13:00:00Z', 'ORD126'),
(20, 16, 200, '2024-02-29T14:00:00Z', 'ORD127'),
(7, 25, 150.75, '2024-03-01T12:00:00Z', 'ORD456'),
(25, 30, 200.00, '2024-03-02T14:30:00Z', 'ORD457'),
(30, 16, 50.25, '2024-03-03T16:00:00Z', 'ORD458');

3. Gemini CLI 및 Spanner MCP 구성

이 실습은 Gemini CLI를 기본 에이전트로 사용하여 대부분의 작업을 수행하도록 설계되었으며 첫 번째 단계는 원격 Spanner MCP 서버와 함께 작동하도록 구성하는 것입니다. 또한 최신 버전의 Gemini CLI와 최신 버전의 Gemini(예: Gemini-3-pro 또는 Gemini-3-flash(현재 프리뷰))를 사용하는 것이 좋습니다.

최신 버전의 Gemini CLI가 이미 설치되어 있고 최신 Gemini 모델을 사용하도록 구성되어 있다면 다음 두 단계를 건너뛰고 3단계로 바로 이동하면 됩니다.

Gemini API 키 가져오기

Gemini CLI에서 최신 Gemini 모델을 사용하려면 API 키 인증으로 구성해야 합니다. Google AI Studio에서 API 키를 가져올 수 있습니다.

  1. 브라우저에서 Google AI Studio -> API 키 받기로 이동합니다.
  2. 화면 오른쪽에서 Create API key 버튼을 클릭합니다.
  3. 팝업 창에서 프로젝트를 선택하거나 표시되지 않는 경우 가져옵니다.

4072657f24158cbe.png

  1. API 키를 만듭니다.
  2. 오른쪽의 복사 버튼을 사용하여 키를 복사할 수 있습니다.

a9a9a1bddb81ae21.png

키가 준비되었으므로 이제 Gemini CLI에 사용할 수 있습니다.

Gemini CLI 구성

Gemini CLI는 설정 구성 파일을 통해 구성하거나 /settings 명령어를 사용하여 대화형으로 구성할 수 있습니다. 설정 파일에 설정이 유지되기를 원합니다.

먼저 프로젝트의 디렉터리를 만듭니다. 디렉터리를 projectspannermcp라고 하고 다음 명령어를 사용하여 해당 디렉터리로 전환합니다.

mkdir ~/projectspannermcp
cd ~/projectspannermcp

이 디렉터리에서 Gemini 구성 파일용 디렉터리를 만들고 모든 명령어를 실행합니다. Gemini CLI는 기본적으로 사용자 범위 구성 파일과 ~/.gemini 디렉터리에 설치된 확장 프로그램을 사용합니다. 하지만 ~/projectspannermcp 디렉터리에 자체 프로젝트 범위 구성을 만들 것입니다. 먼저 구성 디렉터리와 파일을 만들어 보겠습니다.

mkdir ~/projectspannermcp/.gemini
touch ~/projectspannermcp/.gemini/settings.json

그런 다음 Cloud Shell 편집기를 사용하여 ~/projectspannermcp/.gemini/settings.json 파일을 엽니다.

edit ~/projectspannermcp/.gemini/settings.json

열린 편집기 창에 다음 구성을 추가합니다.

{
  "general": {
    "preferredEditor": "vscode",
    "previewFeatures": true,
    "sessionRetention": {
      "enabled": true
    }
  },
  "ide": {
    "enabled": true,
    "hasSeenNudge": true
  },
  "security": {
    "auth": {
      "selectedType": "gemini-api-key"
    }
  },
  "ui": {
    "theme": "Default"
  },
  "tools": {
    "shell": {
      "enableInteractiveShell": false
    }
  }
}

파일을 수정한 후 ctrl+s를 사용하여 변경사항을 저장하고 Open Terminal 버튼을 클릭하여 터미널로 다시 전환할 수 있습니다.

b4d9fc5b7a8bc7b7.png

위의 settings.json 파일은 Gemini CLI 인증 유형을 gemini-api-key로 설정하며 모델에 키를 제공해야 합니다. Gemini CLI로 작업하려는 디렉터리에 .env 파일을 만들고 Gemini CLI 인증을 위한 API 키를 환경 변수로 저장하면 됩니다. 이렇게 하면 IDE를 시작할 때 환경 변수가 선택됩니다.

Cloud Shell 편집기를 사용하여 파일을 수정해 보겠습니다.

edit ~/projectspannermcp/.env

위의 'Gemini API 키 가져오기' 단계에서 만든 API 키를 저장합니다.

GEMINI_API_KEY= <YOUR_API_KEY>

이제 터미널로 돌아가서 계속 진행할 수 있습니다. 다음 단계는 Gemini CLI를 최신 버전으로 업데이트하는 것입니다. Google Cloud Shell 또는 환경의 버전이 오래되어 최신 구성 및 MCP 서비스와 올바르게 작동하지 않을 수 있습니다. 따라서 Gemini CLI를 최신 버전으로 업데이트하고 시작해야 합니다. 터미널에서 다음을 실행합니다.

cd ~/projectspannermcp/
npm install -g @google/gemini-cli@latest

이제 버전을 확인할 수 있습니다. Google Cloud Shell에서 작업하는 경우 셸을 다시 시작할 때마다 이전 버전으로 돌아갈 수 있습니다. Gemini CLI 자체에 적용한 변경사항은 Cloud Shell에서 영구적이지 않습니다.

gemini --version

최신 Gemini CLI 버전 (실습을 작성하는 시점의 버전은 0.27)이 표시되어야 합니다. 최신 Gemini CLI 버전은 여기에서 확인할 수 있습니다. 이제 시작하여 최신 Gemini 모델을 사용하고 있는지 확인할 수 있습니다. 프로젝트 폴더에서 다음 명령어를 실행하여 Gemini CLI를 시작합니다.

gemini

Gemini CLI가 시작되면 인터페이스에서 /about 명령어를 실행하여 버전과 모델을 확인할 수 있습니다. 아래 그림과 같은 결과가 표시됩니다.

af2be742dd0a5bc1.png

최신 Gemini-3 모델을 사용하고 있음을 확인할 수 있습니다. 자연어 쿼리를 보여주는 아래 단계에서는 Gemini-3 모델을 사용해야 합니다.

Spanner MCP를 사용하도록 Gemini CLI 구성

settings.json 파일에 추가할 사항이 하나 더 있습니다. 먼저 Gemini CLI를 종료합니다 (Ctrl+C를 두 번 누르면 됨).

위와 동일한 settings.json에서 Spanner MCP 서버를 구성하는 비트를 추가합니다. 아래에 전체 settings.json이 포함되어 있습니다. "mcpServers"로 시작하는 부분을 확인합니다.

{
 "general": {
   "preferredEditor": "vscode",
   "previewFeatures": true,
   "sessionRetention": {
     "enabled": true
   }
 },
 "ide": {
   "enabled": true,
   "hasSeenNudge": true
 },
 "security": {
   "auth": {
     "selectedType": "gemini-api-key"
   }
 },
 "ui": {
   "theme": "Default"
 },
 "tools": {
   "shell": {
     "enableInteractiveShell": false
   }
 },
 "mcpServers": {
   "spanner": {
     "httpUrl": "https://spanner.googleapis.com/mcp",
     "authProviderType": "google_credentials",
     "oauth": {
       "scopes": ["https://www.googleapis.com/auth/spanner.admin",
                  "https://www.googleapis.com/auth/spanner.data"]
     },
     "timeout": 5000
   }
 },
 "mcp": {
   "allowed": [
     "spanner"
   ]
 }
}

다음 단계로 계속하기 전에 인증하세요.

gcloud auth application-default login

인증 후 gemini-cli를 다시 시작합니다.

gemini

4. 그래프 중심 쿼리를 포함한 멀티 모델 생성

먼저 구성된 프로젝트의 Spanner 인스턴스를 나열해 보겠습니다.

'내 프로젝트 <project1> (프로젝트 ID로 대체)의 모든 Spanner 인스턴스를 나열해 줘.'

응답:

The Spanner instances in your project are:
 [instance1]

'<instance1>의 모든 데이터베이스를 나열해 줘.'(<instance1>을 인스턴스로 대체)

응답:

The Spanner databases in [instance1] are:
  [database1]

다음으로, Spanner 설정 섹션에서 DDL 문과 삽입 문을 실행한 인스턴스/데이터베이스를 기억하도록 Gemini에 알려줍니다.

'달리 명시되지 않는 한 모든 쿼리는 <your-instance> 인스턴스의 <your-db> db에 대해 제출된다고 가정해'

NOTE: 위의 DDL 문과 삽입 문을 실행한 인스턴스/데이터베이스를 사용하세요.

연결되면 Gemini 모델이 그래프 스키마를 이해합니다. 이제 자연어를 사용하여 정교한 순회를 실행할 수 있습니다.

모델은 다음을 GQL (Graph Query Language)로 자동 변환합니다.

네트워크 구조 식별

'FinGraph' 속성 그래프의 구조를 설명해 줘. 노드와 에지 라벨은 무엇인가요?'

응답:

  Node Labels
   * `Account`: Represents financial accounts.
       * Properties: id, create_time, is_blocked, nick_name
   * `Person`: Represents individuals.
       * Properties: id, name, birthday, country, city

  Edge Labels
   * `Transfers`: Represents a transfer between two Account nodes.
       * Source: Account
       * Destination: Account
       * Properties: id, to_id, amount, create_time, order_number
   * `Owns`: Represents a Person owning an Account.
       * Source: Person
       * Destination: Account
       * Properties: id, account_id, create_time

사기 및 주기 감지

'계정 A에서 송금된 후 3홉 이내에 계정 A로 다시 반환된 순환 이체를 찾아줘.'

응답:

The analysis confirms the following circular transfers where money returns to the originating account within 3 hops:

  3-Hop Cycles
  Money travels through two intermediate accounts before returning to the origin.
   * Account 16 (Involved in multiple 3-hop paths)
   * Account 20 (Involved in multiple 3-hop paths)
   * Account 7 (Involved in multiple 3-hop paths)

These accounts are participating in circular flow patterns of varying lengths.

심층 관계 분석

'지난 24개월 동안 다른 사람이 소유한 계정으로 499달러 이상을 보낸 계정을 소유한 모든 사람을 식별해 줘.'

응답:

Dana is the only person who owns an account that has sent more than $499 to an account owned by a different person in the last 24 months.

(Specifically, her account sent exactly $500, which is the maximum transfer amount in the database).

경로 탐색

'계정 ID 16과 계정 ID 20 간의 가장 짧은 전송 경로를 찾아 줘.'

응답:

The shortest path between Account 16 and Account 20 is 1 hop.

This means there is a direct transfer from Account 16 to Account 20.

5. 축하합니다.

축하합니다. Codelab을 완료했습니다.

학습한 내용

이 Codelab에서는 Spanner MCP 서버로 gemini-cli를 구성하고 Spanner 그래프 데이터에 대해 자연어 쿼리를 실행하여 유용한 정보를 표시하는 방법을 알아봤습니다. 주요 마일스톤은 다음과 같습니다.

  • 관리형 인프라: 원격 Spanner MCP 서버를 사용 설정하여 로컬 프록시나 MCP 도구 상자가 필요하지 않습니다.
  • 그래프 통합: 복잡한 관계를 나타내기 위해 노드와 에지가 있는 Spanner 속성 그래프 (FinGraph)를 구성했습니다.
  • 기본 도구: 표준 URI 스키마를 사용하여 Gemini CLI를 관리형 Spanner 엔드포인트에 직접 연결했습니다.
  • 자연어 SQL 및 GQL: 그래프 관련 프롬프트로 서버를 실행하여 LLM이 수동 SQL/GQL 코딩 없이 멀티홉 순회 및 사이클 감지를 실행할 수 있도록 했습니다.
  • 엔터프라이즈 준비: 관리형 MCP가 AI 에이전트가 운영 데이터와 상호작용할 수 있는 확장 가능하고 인증된 경로를 제공하는 방법을 살펴봤습니다.