본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 05. 31. 05:01

Claude Code + Coral을 사용하여 관계 인텔리전스 CRM을 구축한 과정

요약

Claude Code와 Coral을 활용하여 흩어진 관계 데이터를 통합된 SQL 그래프로 관리하는 CRM 구축 과정을 소개합니다. Coral의 'SQL over APIs' 기능을 통해 다양한 서비스의 데이터를 연합 조인(Federated join)하여 AI 에이전트가 활용할 수 있는 통합 컨텍스트를 제공합니다.

핵심 포인트

  • Coral을 통해 API 데이터를 SQL로 쿼리 가능한 통합 그래프로 변환
  • Gmail, Slack, LinkedIn 등 분산된 데이터를 단일 SQL 인터페이스로 통합
  • 에이전트 워크로드를 위한 인증, 재시도, 페이지네이션 레이어 제공
  • 연합 조인을 활용한 실시간 데이터 결합 및 컨텍스트 확보

라이브 데모: coral-hackaton.onrender.com

저장소 (Repo): github.com/Geetansh-12/coral_hackaton

대부분의 사람들은 연락처와 연락이 끊기는 이유가 관심이 없어서가 아닙니다. 관계 데이터가 Gmail, Slack, LinkedIn, 캘린더 초대, 커뮤니티 서버 등에 흩어져 있기 때문입니다. 저는 Pirates of the Coral-bean 해커톤을 위해 Coral CRM을 구축했습니다. 이는 이러한 서비스들을 별개의 앱으로 취급하는 것을 멈추고, Coral을 기반으로 하는 **하나의 SQL 그래프 (SQL graph)**로 취급할 때 어떤 일이 일어나는지 보여주기 위함입니다.

이 포스트는 재현 가능한 경로를 제시합니다: 문제 정의 → 아키텍처 (Architecture) → Coral의 기능 → 라이브 데모 → 커스텀 Discord 소스 사양.

문제 (The problem)

모든 채널이 컨텍스트 (Context)의 일부를 점유하고 있을 때 관계 인텔리전스 (Relationship intelligence)는 깨집니다:

  • Gmail은 당신이 무엇을 말했는지 알고 있습니다.
  • 캘린더 (Calendar)는 당신이 언제 만나는지 알고 있습니다.
  • Slack은 DM에서 무슨 일이 일어났는지 알고 있습니다.
  • LinkedIn은 직업 변화를 알고 있습니다.
  • Discord는 커뮤니티 참여도를 알고 있습니다.

AI 에이전트 (AI agent)가 단 하나의 편지함만 볼 수 있다면, "목요일 회의 전에 Sarah에게 연락하세요"와 같은 추천을 할 수 없습니다. 에이전트가 안전하게 쿼리 (Query)할 수 있는 **통합 그래프 (Unified graph)**가 필요합니다.

왜 Coral인가 (단순한 MCP 커넥터가 아닌 이유)

MCP 커넥터 (MCP connectors)는 도구 호출 (Tool calls)에 매우 유용합니다. 하지만 Coral은 다른 것을 제공합니다: API 상에서의 SQL (SQL over APIs).

모든 소스에 대해 맞춤형 페치 (Fetch) 로직을 작성하는 대신, Coral은 JOIN할 수 있는 테이블을 노출합니다:

SELECT c.name, c.company, c.health_score,
       g.public_repos, g.followers
FROM contacts c
...

이 쿼리는 Coral CRM의 SQL 익스플로러 (SQL Explorer)에서 실행되며, 로컬 연락처와 결합된 실시간 GitHub 프로필 데이터를 반환합니다. 이는 연합 조인 (Federated joins)이 단순한 허상이 아님을 증명합니다.

또한 Coral은 다음을 제공합니다:

  • 카탈로그 검색 (Catalog discovery)coral.tables, coral.columns, coral.inputs
  • 캐시/최신성 관측 가능성 (Cache/freshness observability)coral.query_log
  • 에이전트 워크로드 (Agent workloads)를 위한 단일 인증/재시도/페이지네이션 (Auth/retry/pagination) 레이어

60초 만에 보는 아키텍처 (Architecture in 60 seconds)

Landing / Dashboard / Explorer / AI Chat
              ↓
        Next.js API routes (/api/query, /api/chat, /api/brief)
...

**데모 모드 (Demo Mode)**는 API 키 없이 작동하므로, 심사위원들이 즉시 클릭하여 체험해 볼 수 있습니다.

**라이브 모드 (Live Mode)**는 로컬에 SQLite를 시딩(seed)하고, 연합 쿼리 (federated queries)를 위해 실제 coral 바이너리를 실행합니다.

기술 스택: Next.js 14, TypeScript, Tailwind, AI를 위한 Gemini (무료 티어), better-sqlite3, Coral CLI.

단계별 가이드: 직접 실행해 보기

git clone https://github.com/Geetansh-12/coral_hackaton.git
cd coral_hackaton
npm install
...

**http://localhost:3000**을 엽니다. 앱은 34개의 사실적인 연락처와 함께 데모 모드로 시작됩니다.

라이브 모드로 전환하기

.env.local.example.env.local로 복사합니다:

DEMO_MODE=false
GEMINI_API_KEY=your_key
GITHUB_TOKEN=ghp_...
...

Discord 소스 스펙을 설치합니다:

coral source lint ./sources/discord/manifest.yaml
coral source add --file ./sources/discord/manifest.yaml --interactive
coral source test discord

우리가 시연하는 Coral의 기능 (7/7)

1. 다중 소스에 대한 SQL 인터페이스

sql/schema.sql에 시딩된 6개의 테이블: Gmail 스레드, Calendar 이벤트, Slack 메시지, LinkedIn 활동, Twitter 활동, Notion 연락처.

2. 소스 간 JOIN (Cross-source JOINs)

contact_relationship_graph 구체화된 뷰 (materialized view)는 이메일을 기준으로 6개 소스 모두를 LEFT JOIN 하여 health_score를 계산합니다.

3. 카탈로그 탐색 (Catalog discovery)

SELECT schema, table, sql_reference, source_type, freshness
FROM coral.tables ORDER BY schema;

4. 파라미터 힌트 (Parameter hints)

SELECT query, parameter, name, type, required FROM coral.inputs;

5. 캐시 및 신선도 (Cache & freshness)

SELECT query_name, sources_joined, cache_hit_rate, avg_ms
FROM coral.query_log;

6. 실제 CLI 실행

라이브 모드에서 /api/querycoral sql --format json을 비동기적으로 실행합니다. 이는 느린 API 호출 시 Next.js 이벤트 루프 (event loop)를 차단하지 않습니다.

7. 플러그형 소스 아키텍처 (Pluggable source architecture)

설정 페이지에서는 소스별 커넥터 진단(connector diagnostics) 정보를 보여줍니다. 저희는 **커스텀 Discord 소스 스펙 (custom Discord source spec)**을 추가했습니다 (아래 참조).

Judge 데모 흐름

  1. /dashboard 접속 → Judge Demo 클릭
  2. Agent PlanCoral Capability Cockpit 표시
  3. SQL Explorer 열기 → 소스 간 GitHub JOIN 레시피 실행
  4. 연락처(contact) 열기 → 회의 전 브리핑 (pre-meeting brief) 생성 → 내보내기
  5. 채팅 에이전트에게 질문: "이 데모는 어떤 Coral 기능을 사용하나요?"

스크린샷은 리포지토리의 docs/screenshots/에 있습니다.

커스텀 Discord 소스 스펙 구축 (bounty 트랙)

Coral은 Gmail, GitHub, Slack 등을 제공하지만, Discord는 카탈로그에 없었습니다. 해커톤 "Chart New Waters" 트랙을 위해, 저는 Discord REST API v10 엔드포인트를 SQL 테이블로 매핑하는 YAML 소스 스펙을 작성했습니다.

파일: sources/discord/manifest.yaml

노출된 테이블 (Tables exposed):

SQL 테이블Discord API
discord.current_userGET /users/@me
...

인증 패턴 (Auth pattern):

auth:
  type: HeaderAuth
  headers:
...

Coral의 __ 컨벤션을 사용한 중첩된 JSON → SQL 컬럼 (Nested JSON → SQL columns) 변환:

- name: author__username
  expr:
    kind: path
...

검증 워크플로우 (Validation workflow):

coral source lint ./sources/discord/manifest.yaml
coral source add --file ./sources/discord/manifest.yaml
coral source test discord

설치 후 CRM 쿼리 예시:

SELECT author__username, content, timestamp
FROM discord.messages
WHERE channel_id = 'YOUR_CHANNEL_ID'
...

전체 문서: sources/discord/README.md

업스트림 PR 대상: withcoral/coralsources/community/discord/

배운 점

  1. 하나의 테이블부터 시작하세요. 길드(Guilds)를 먼저 하고, 그다음 채널(channels), 그다음 메시지(messages) 순으로 진행합니다. 각 항목을 추가한 후에는 coral source test를 실행하세요.
  2. 중첩된 필드(Nested fields)에는 명시적인 expr이 필요합니다. author__username이 자동으로 평탄화(auto-flatten)될 것이라고 가정하지 말고, 경로를 직접 선언하세요.
  3. **URL 경로 내의 필터(Filters)**는 {{filter.guild_id}}를 사용합니다. 이는 다른 커뮤니티 사양(OSV, dbt Cloud)과 동일한 패턴입니다.
  4. 데모(Demo) + 라이브(Live) 이중 모드는 해커톤 심사위원들을 위한 올바른 결정이었습니다. 자격 증명(credentials)이 있을 때는 실제 CLI를 사용하고, 없을 때는 마찰 없이 탐색할 수 있습니다.
  5. Render에서의 Docker 사용은 150MB 크기의 Coral 바이너리(binary)의 경우 서버리스(serverless)보다 유리합니다. 하나의 컨테이너로 실제 라이브 URL을 제공할 수 있습니다.

다음 단계

  • Discord 소스 사양(source spec)에 대한 업스트림 PR(Open upstream PR) 제출
  • 사용자 이름/닉네임(username/nickname)을 기준으로 Discord 메시지를 contact_relationship_graph로 통합
  • 프로덕션 환경을 위한 Gmail/Calendar용 OAuth 디바이스 플로우(device flow) 구현

링크

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0