트렌딩 딥다이브 · 2026-07-18 · OSSInsight #21

withcoral/coral 딥다이브
— 흩어진 API·파일·서비스를 "전부 SQL 테이블"로 둔갑시켜 에이전트에게 쥐여 주는 로컬 쿼리 엔진

coralREST API·로컬 파일·다른 MCP 서버를 전부 하나의 SQL 인터페이스로 노출하고, 소스 사이의 JOIN까지 내 컴퓨터에서 실행하는 도구다. 저장소가 내건 한 줄은 이것 — "One SQL interface over APIs, files, and live sources — built for agents."(API·파일·라이브 소스 위의 단일 SQL 인터페이스, 에이전트를 위해 만든). 먼저 오해를 풀자 — 이건 새 데이터베이스가 아니다. 데이터를 어디론가 옮겨 담는 게 아니라, 이미 흩어져 있는 소스들을 "테이블처럼 보이게" 감싸서 질의하는 데이터 페더레이션 엔진이다. 심장부는 Apache DataFusion(러스트 SQL 쿼리 엔진)이다. 두 번째로 각인할 것 — "에이전트를 위해" 만들었다는 점. AI 에이전트가 API마다 툴을 갈아 끼우며 수십 번 호출하는 대신, coral에 붙은 MCP 서버로 SQL 한 방을 던지게 한다. 이 문서는 소스를 직접 클론해 "이 저장소에서 무엇을 배울 수 있는가"를 파고든다. (저장소: withcoral/coral · Rust(edition 2024) · Apache-2.0 · v0.6.0 · 최신 커밋 2026-07-17 · Apache DataFusion 기반 · 이번 회차는 TrendShift Daily·Weekly·Monthly가 모두 기분석 소진되어 OSSInsight 순위로 폴백)
목차
  1. 프로젝트 한 줄 요약
  2. 왜 지금 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트
  7. 시스템 · 실행 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한 줄 요약

에이전트를 위한 "모든 데이터 소스를 SQL 테이블로" — API·파일·MCP 서버를 감싸 질의하고 소스 간 JOIN까지

withcoral/coral내 컴퓨터에서 도는 로컬 우선(local-first) SQL 런타임이다. GitHub API, 로컬 CSV/Parquet 파일, 다른 MCP 서버 같은 서로 다른 데이터 소스를 전부 "테이블"처럼 보이게 감싼 뒤, 평범한 SQL로 질의하게 해 준다. 예컨대 SELECT * FROM github.issues WHERE repo='coral' 한 줄이 실제로는 GitHub REST API 호출로 바뀌어 실행된다.

가장 먼저 풀어야 할 오해 — coral은 데이터를 저장하는 새 데이터베이스가 아니다. Postgres나 MySQL처럼 데이터를 안에 쌓아 두는 게 아니라, 이미 다른 곳(웹 API·파일·서비스)에 사는 데이터를 그 자리에서 SQL로 질의한다. 이렇게 "여러 이질적 소스를 옮기지 않고 한 창구로 질의하는" 기술을 데이터 페더레이션(data federation)이라 부른다. coral은 그 엔진을 Apache DataFusion(러스트로 짠 SQL 쿼리 엔진) 위에 자체 커넥터를 얹어 구현했다.

핵심 용어 · 이게 뭐냐
데이터 페더레이션(Data Federation) — 데이터를 옮기지 않고 "제자리에서" 합쳐 질의
보통 여러 소스의 데이터를 합치려면 ETL(다 퍼와서 한 창고에 적재)을 한다. 페더레이션은 반대다 — 데이터를 옮기지 않고, 질의가 들어올 때마다 각 소스로 흩어 보내 그 자리에서 읽어 오고 합친다. coral은 GitHub API·CSV 파일·다른 MCP 서버를 각각 "테이블"로 등록해 두고, JOIN이 걸리면 필요한 만큼만 각 소스를 호출해 로컬(내 컴퓨터)에서 이어 붙인다. 창고를 새로 짓지 않아 항상 실시간 최신 데이터를 본다.
핵심 용어 · coral의 토대
Apache DataFusion — 러스트로 만든 "조립식 SQL 엔진"
DataFusion은 아파치 재단의 오픈소스 쿼리 엔진 라이브러리다. SQL 파싱 → 논리 계획 → 최적화 → 물리 실행까지 데이터베이스의 "머리"에 해당하는 부분을 러스트로 제공하되, 데이터를 어디서 읽어올지는 개발자가 TableProvider로 꽂아 넣게 열어 둔다. 내부 데이터는 Apache Arrow(컬럼형 인메모리 포맷)로 흐른다. coral은 이 확장점에 "HTTP API를 읽는 TableProvider", "파일을 읽는 TableProvider", "MCP 서버를 읽는 TableProvider"를 끼워 넣어 SQL-over-anything을 완성했다.
한 문장 비유

"제각각인 언어를 쓰는 상점들 사이에, 모든 걸 '표'로 번역해 주는 만능 사서를 세운 것"

에이전트 입장에서 GitHub·Linear·로컬 파일은 저마다 말이 다른 가게들이다 — 인증 방식도, 페이지 넘기는 법도, 응답 모양(JSON 구조)도 전부 다르다. 지금까지 에이전트는 가게마다 다른 점원(툴)을 일일이 상대하며 "이건 이렇게 물어봐야 하고 저건 저렇게…"를 외워야 했다. coral은 그 사이에 만능 사서를 세운다.

이 사서에게는 "모든 가게를 표(테이블)로 보여 달라"고만 하면 된다. 그러면 에이전트는 가게별 방언을 몰라도, 누구나 아는 공용어인 SQL로 "이 표에서 저 표를 이어 붙여 이런 조건으로 뽑아 줘"라고 한 번에 시킬 수 있다. 사서는 뒤에서 각 가게에 알맞은 방식으로 물어보고(API 호출·파일 읽기), 결과를 표로 정리해 돌려준다. 방언 통역은 사서가, 논리는 SQL이 담당한다.

2왜 지금 주목받는가

OSSInsight 트렌딩 — "에이전트의 툴 호출 폭증을, SQL 한 방으로 갈아 치우다"

coral이 트렌딩에 오른 이유는 "또 하나의 쿼리 엔진"이어서가 아니다. AI 에이전트가 데이터를 다루는 방식의 고질병을 정면으로 겨냥했기 때문이다. 지금 에이전트는 여러 API를 쓰려면 소스마다 툴을 갈아 끼우고, 인증·페이지네이션·재시도 로직을 매번 새로 짜고, 서로 다른 JSON을 힘겹게 이어 붙인다. 이 과정에서 툴 호출이 폭증하고, 토큰이 낭비되고, 크로스 소스(소스 간) 추론은 깨지기 쉽다. coral은 이 모든 걸 단일 SQL 인터페이스로 대체하겠다고 나선다.

포인트내용
정체에이전트를 위한 로컬 우선 SQL 런타임. API·파일·라이브 소스를 SQL 테이블로 노출하고 소스 간 JOIN을 로컬에서 실행. Apache DataFusion 위에 자체 커넥터·옵티마이저를 얹은 154K줄 규모의 러스트 프로젝트.
차별점 ①읽기 전용(read layer) 설계. 페이지네이션을 엔진이 알아서 처리하고 JSON 덩어리 대신 정돈된 테이블 행을 반환. 필요한 컬럼만 SELECT하니 API 트래픽·토큰이 준다.
차별점 ②소스를 선언적 YAML로 정의. 코드를 짜지 않고 manifest.yaml에 "이 API의 이 경로가 이 테이블"이라고 적으면 커넥터가 된다. OpenAPI 명세를 import해 자동 생성도 가능.
차별점 ③크로스 소스 JOIN을 진짜로 최적화. 한 소스의 결과값을 다른 소스 API의 필터로 밀어 넣는 dependent join을 DataFusion 커스텀 옵티마이저로 구현(뒤에서 상술).
제작자 · 라이선스withcoral 조직(withcoral.com·Discord 보유). Apache-2.0(관대한 라이선스). 러스트 크레이트 전부 coral-* 네이티브 네이밍 — 다른 프로젝트의 포크·리브랜드가 아니다.

주목 포인트 1 — "에이전트에게 데이터를 주는 법"을 SQL로 표준화

AI 에이전트 생태계의 뜨거운 병목은 "모델은 똑똑한데 내 데이터·서비스에 닿기가 번거롭다"는 것이다. MCP(Model Context Protocol)가 그 통로를 표준화했지만, 여전히 툴마다 응답 모양이 제각각이라 에이전트가 여러 소스를 엮으려면 글루 코드가 필요하다. coral은 "모든 소스를 SQL 테이블로" 통일해, 에이전트가 데이터 모델 하나(관계형 테이블)와 언어 하나(SQL)만 알면 되게 만든다. "에이전트 시대의 데이터 접근 계층"이라는 서사가 트렌딩의 동력이다.

주목 포인트 2 — "코드가 할 일은 코드에게" 넘기는 설계

coral의 흥미로운 지점은 필터링·조인·집계처럼 답이 정해진 데이터 작업을 LLM이 아니라 검증된 쿼리 엔진(DataFusion)에 맡긴다는 점이다. 에이전트는 "무엇을 원하는지"를 SQL로 표현만 하고, "어떻게 효율적으로 가져올지"(어떤 필터를 API로 밀어 넣고, 어떤 순서로 조인할지)는 옵티마이저가 결정한다. LLM에게 수백 줄 JSON을 읽혀 헤매게 하는 대신, 정확하고 값싼 부품에 계산을 위임하는 태도다.

주목 포인트 3 — "한 코어, 여러 얼굴"의 실전 패키징

coral은 사실 MCP 서버이자, CLI이자, 로컬 gRPC 서버이자, 데스크톱 앱(Electron)이자, 웹 UI(React)다. 같은 러스트 엔진을 여러 진입점으로 노출한다 — 에이전트는 coral mcp-stdio로, 사람은 터미널이나 reef 데스크톱 앱으로. 9개 크레이트로 나뉜 러스트 워크스페이스 안에, DataFusion 커스텀 확장·gRPC·MCP 서버·봉투 암호화·OpenTelemetry까지 요즘 백엔드 인프라 기술이 밀집해 있어 학습 표본으로도 훌륭하다.

균형 잡힌 시각
과대평가 금물 — 아직 초기 버전이고, "SQL은 사람/LLM이 쓴다"

냉정히 보면 coral은 아직 v0.6.0의 빠르게 움직이는 초기 프로젝트다. 그리고 중요한 경계 — coral은 자연어를 SQL로 바꿔 주지 않는다(NL2SQL 내장 아님). SQL을 짜는 건 여전히 사람 또는 LLM의 몫이고, coral은 그 SQL을 안전하게(읽기 전용) 실행할 뿐이다. 또 소스를 쓰려면 먼저 YAML 스펙으로 등록해야 하며(번들 26개 + 커뮤니티 181개가 있지만 내가 쓸 API가 없으면 직접 작성), README의 벤치마크 수치(직접 MCP 대비 정확도·비용·지연 개선)는 제작사 자체 측정이라 참고로만 봐야 한다. 즉 "만능 데이터 마법사"가 아니라 "에이전트용 데이터 접근을 SQL로 재설계한, 잘 짜인 진행 중 인프라"로 보는 게 정확하다.

3기술 스택 전체 지도

언어 = Rust(edition 2024) · 엔진 = Apache DataFusion · 전송 = gRPC(tonic) · 에이전트 표면 = MCP(rmcp)

coral은 Rust로 짠 대규모 워크스페이스다(러스트 edition 2024, 빌드에 rustc 1.95 필요). 코드의 압도적 다수가 .rs(344개 파일, 154,259줄)이고, 프론트엔드(TypeScript/React)는 apps/ 아래 별도로 산다. 특기할 점 하나 — 워크스페이스 전역 린트가 unsafe_code = "forbid"다. unsafe 러스트를 아예 금지하고 unwrap()·인덱싱·panic까지 경고로 잡는, 안전성을 최우선으로 둔 코드베이스다. 스택을 ① 쿼리 엔진, ② 데이터 소스 접근, ③ 전송·서버, ④ 보안·자격증명, ⑤ 관측·CLI로 나눠 지도를 그려 보자.

① 쿼리 엔진 — coral의 심장

영역기술 · 버전
SQL 엔진 코어datafusion 53 — SQL 파싱·논리계획·최적화·물리실행. coral의 모든 쿼리가 여기서 돈다
SQL 파서sqlparser 0.59 — SQL 텍스트를 구문 트리로
인메모리 포맷arrow 58.1 — 엔진 내부 데이터가 흐르는 컬럼형 포맷. 결과는 Arrow IPC로 클라이언트에 전송
파일 포맷parquet 58.1 + datafusion-datasource — Parquet/CSV/JSON 읽기
JSON 함수datafusion-functions-json — API 응답의 중첩 JSON을 SQL에서 다루기

② 데이터 소스 접근 — API·파일·MCP

구분기술 · 버전
파일·오브젝트 스토어object_store 0.13(feature aws → S3) — 로컬 파일과 S3를 같은 인터페이스로. DataFusion ListingTable로 등록
HTTP 클라이언트reqwest 0.13(rustls · http2 · blocking) — REST API 백엔드가 실제 API를 호출
MCP 클라이언트rmcp 1.6(공식 Rust MCP SDK) — 다른 MCP 서버를 테이블로 감싸기 위해 coral이 MCP 클라이언트도 된다
소스 스펙 파싱serde_yaml + schemars 1.2 + jsonschema — 선언적 YAML 커넥터 정의를 파싱·검증

③ 전송 · 서버 — 한 코어를 여러 창구로

영역기술 · 버전
내부 gRPCtonic 0.14 + tonic-web · prost — 앱↔클라이언트 전송 프로토콜(coral-api 크레이트가 protobuf 계약)
REST/웹axum 0.8 + tower · tower-http(cors) — 로컬 HTTP 서버
MCP 서버coral-mcp 크레이트 — coral mcp-stdiostdio(JSON-RPC) 표면을 에이전트에 노출
로컬 상태 DBrusqlite(bundled) · sqlx 0.9(postgres+sqlite, rustls) · sea-query — 세션·스레드·워크스페이스 영속

④ 보안 · 자격증명 — "키는 로컬을 떠나지 않는다"

데이터 소스 인증정보(API 키·토큰)를 다루는 만큼 보안이 두껍다. 저장 방식은 두 가지 — OS 키체인(keyring-core + macOS/Windows/libsecret 백엔드) 또는 AES-256-GCM 봉투 암호화 파일(ring 0.17로 암호화, zeroize로 메모리에서 즉시 소거). OAuth(device_code·PKCE)·헤더 인증·PAT를 지원하고, 자격증명은 환경변수나 대화형 프롬프트로만 주입되며 로컬을 떠나지 않는다.

⑤ 관측 · CLI · 프론트엔드

관측성opentelemetry 0.31 풀스택 + tracing(W3C trace-context)으로 쿼리 실행을 추적한다. CLIclap 4.5(derive + env), dialoguer, crossterm. 프론트엔드apps/reef(React 19 + React Router 7 + react-aria)와 apps/desktop(Electron 42 + electron-vite, reef를 감싸고 coral 바이너리를 사이드카로 구동), 문서는 apps/docs(Mintlify)로 나뉜다.

9개 러스트 크레이트 = 책임 분리의 교과서

크레이트역할
coral-engineDataFusion 페더레이션 엔진 — 백엔드별 컴파일·런타임 등록·쿼리 실행. 가장 큰 크레이트(≈45K줄)
coral-app로컬 서버 조립, 상태·워크스페이스·소스 라이프사이클·자격증명·카탈로그
coral-spec선언적 소스 스펙 파싱·검증·정규화(+ v4 DSL, OpenAPI import)
coral-apiprotobuf 계약 + 생성된 러스트 바인딩(앱↔클라이언트 전송)
coral-mcpMCP stdio 어댑터 — 에이전트가 마주하는 표면
coral-cli터미널 어댑터(clap)
coral-client얇은 로컬 전송 부트스트랩 + Arrow IPC 디코드·렌더
coral-telemetry크로스크레이트 트레이싱 헬퍼
coral-auth-awsAWS SigV4 등 인증

4아키텍처 심화 분석

소스 스펙(YAML) → 검증 → 백엔드별 컴파일 → DataFusion 카탈로그 등록 → SQL 실행 → Arrow로 반환

coral의 핵심 질문은 하나다 — "SQL over anything"을 대체 어떻게 구현하나?" 답은 이렇다. 각 데이터 소스를 선언적 YAML 스펙으로 기술하면, coral-spec이 검증하고, coral-engine이 백엔드(HTTP/파일/MCP)별로 DataFusion TableProvider로 컴파일해 카탈로그에 등록한다. 그 뒤 SessionContext에서 SQL을 실행하면, 엔진이 각 테이블의 provider를 호출해 실제 데이터를 끌어온다. 전체 지도를 먼저 그리자.

┌──────────────────────────────────────────────────────────────┐ │ coral 전체 데이터 흐름 │ └──────────────────────────────────────────────────────────────┘ [AI 에이전트 / 사람] Claude Code · Codex · Cursor · CLI · reef 앱 │ │ MCP over stdio 또는 gRPC / CLI ▼ ┌──────────────────────────────────────────────┐ │ coral (로컬 서버, coral-app) │ │ DataFusion SessionContext + 카탈로그 │ └──────────────────────────────────────────────┘ │ SQL 실행 (읽기 전용 강제) ▼ ┌──────────────────────────────────────────────┐ │ 등록된 테이블들 (소스 스펙 YAML → 컴파일) │ │ github.issues · linear.tickets · files.csv … │ └──────────────────────────────────────────────┘ │ 각 테이블 = 아래 3개 백엔드 중 하나 ▼ ┌───────────┐ ┌───────────┐ ┌───────────────┐ │ HTTP 백엔드 │ │ File 백엔드 │ │ MCP 백엔드 │ │TableProvider│ │ListingTable│ │ (다른 MCP서버) │ └─────┬─────┘ └─────┬─────┘ └───────┬───────┘ │ │ │ ▼ ▼ ▼ REST API CSV/JSON/Parquet MCP tools (WHERE→쿼리 (로컬 파일 · S3) (툴 호출을 파라미터로 pushdown) 테이블로) │ │ │ └───────┬───────┴─────────────────┘ ▼ 결과를 Apache Arrow(컬럼형)로 조립 │ Arrow IPC 로 전송 ▼ [에이전트 / 앱으로 테이블 반환]

핵심 설계 ① — 3개 백엔드로 "무엇이든 테이블로": 커넥터 추상화

coral의 확장점은 3개 백엔드다(crates/coral-engine/src/backends/). 소스 스펙이 어떤 종류냐에 따라 RuntimeSourceComponent enum으로 갈라져, 각자 DataFusion에 등록될 테이블로 컴파일된다.

// crates/coral-engine/src/backends/mod.rs — 백엔드 디스패치
match component {
    RuntimeSourceComponent::Http(manifest) => http::compile_manifest(manifest, request),
    RuntimeSourceComponent::File(manifest) => file::compile_manifest(manifest, request),
    RuntimeSourceComponent::Mcp(manifest)  => mcp::compile_manifest(manifest, request),
}
백엔드무엇을 테이블로 · 어떻게
HTTPREST API를 테이블로. HttpSourceTableProviderSQL의 WHERE/SELECT/LIMIT을 API 쿼리 파라미터로 밀어 넣는다(pushdown)
File로컬/S3 파일을 테이블로. DataFusion ListingTable + object_store. Parquet/JSONL/JSON/CSV 지원
MCP다른 MCP 서버의 tool을 테이블로 감싼다. coral이 그 서버의 MCP 클라이언트가 되어 tool 호출을 행으로

핵심 설계 ② — HTTP 백엔드: SQL을 "API 호출"로 번역하는 pushdown

가장 흥미로운 부분이다. SELECT title FROM github.issues WHERE owner='withcoral'이라는 SQL이, 실제로는 GET /repos/.../issues?owner=withcoral 같은 API 호출로 바뀐다. 이걸 predicate pushdown(술어 밀어넣기)이라 한다 — 필터 조건을 엔진이 로컬에서 거르는 대신 데이터 소스 쪽으로 밀어 보내 애초에 적게 가져오는 최적화다. DataFusion의 TableProvider 트레이트가 이 훅을 제공한다.

// backends/http/provider.rs — HttpSourceTableProvider: TableProvider
fn supports_filters_pushdown(&self, filters: &[&Expr])
    -> Result<Vec<TableProviderFilterPushDown>>
{
    // 이 API가 쿼리 파라미터로 받아 줄 수 있는 필터를 골라낸다
    let active_request = self.table.resolve_request(&filter_value_keys);
    let consumed = self.backend.request_filter_names(active_request);
    Ok(classify_filter_pushdown_for_consumed(filters, self.table.filters(), &consumed))
}

async fn scan(&self, _state, projection, filters, limit)
    -> Result<Arc<dyn ExecutionPlan>>
{
    // 필수 필터가 없으면 에러(예: 검색 API에 q 누락)
    // consumed 필터 → API 파라미터, 나머지(residual)는 DataFusion이 로컬 적용
    http_json_exec(HttpJsonExecRequest { /* projection, limit, … */ })
}

WHERE 절 중 API가 소화할 수 있는 조건은 파라미터로 pushdown되고, 나머지 조건은 결과를 받아 온 뒤 엔진이 로컬에서 마저 거른다(residual filter). SELECT한 컬럼만 projection으로 좁혀 응답을 줄인다. 이게 "API 트래픽·토큰 절감"의 실제 원리다.

핵심 설계 ③ — 소스 스펙: 코드 대신 "선언적 YAML"로 커넥터를 만든다

새 API를 붙이는 데 러스트 코드를 짤 필요가 없다. YAML 한 장에 "이 API의 이 경로가 이 테이블이고, 이 필터를 받고, 응답의 이 JSON 경로가 이 컬럼"이라고 선언하면 커넥터가 된다(coral-spec이 검증). 아래는 실제 sources/core/github/manifest.yaml의 축약이다.

# sources/core/github/manifest.yaml (dsl_version 3, backend: http)
name: github
base_url: "{{input.GITHUB_API_BASE}}"
auth:
  type: HeaderAuth
  headers:
    - { name: Authorization, template: "Bearer {{input.GITHUB_TOKEN}}" }
tables:
  - name: accepted_assignments
    filters: [{ name: assignment_id, required: true }]
    request: { method: GET, path: /assignments/{{filter.assignment_id}}/accepted }
    pagination: { mode: page, page_param: page, page_size: { query_param: per_page, max: 100 } }
    columns:
      - name: classroom_id
        type: Int64
        expr: { kind: path, path: [assignment, classroom, id] }   # 중첩 JSON → 컬럼
functions:
  - name: search_code                     # SQL 테이블 함수로 노출
    request: { method: GET, path: /search/code }

여기서 배울 설계는 페이지네이션·인증·중첩 JSON 매핑을 전부 "데이터"로 기술했다는 점이다. pagination 블록을 엔진이 읽고 알아서 여러 페이지를 넘겨 가며 모으고, expr: {kind: path, ...}로 깊은 JSON을 평평한 컬럼으로 편다. functions:SELECT * FROM search_code(q => 'rust')처럼 SQL 테이블 함수가 된다. 커뮤니티가 이미 181개 소스 스펙을 기여했고(번들 코어 26개), OpenAPI 명세를 import해 자동 생성하는 경로(coral-spec/src/v4/surfaces/openapi/)도 있다.

핵심 설계 ④ — 크로스 소스 JOIN: "dependent join" 커스텀 옵티마이저

coral에서 가장 고급인 부분이다. github.issueslinear.ticketsJOIN한다고 하자. 순진하게 하면 양쪽을 통째로 가져와 로컬에서 붙여야 한다. coral은 한쪽(resolver)에서 나온 값들을 다른 소스 API의 필터로 바인딩해 필요한 것만 호출하는 dependent join(의존 조인)을 구현했다. DataFusion의 확장 API 두 개를 직접 구현한다.

확장역할
DependentJoinNodeDataFusion의 UserDefinedLogicalNodeCore를 구현한 커스텀 논리 계획 노드 — "이 조인은 의존 조인이다"를 계획 트리에 표현
DependentJoinOptimizerRuleDataFusion의 OptimizerRule — 조인을 분석해 "한쪽 값을 다른 API 필터로 밀어넣을 수 있으면" 의존 조인으로 변환
BindingKey어떤 컬럼을 어떤 API 필터에 바인딩할지의 매핑. concurrency·max_bindings로 호출량 제어

주목할 만한 성숙함 — 이 규칙은 변환이 불리할 때의 폴백 사유를 taxonomy로 분류한다(NonEqui=등가조인 아님, NonHttpProvider, CostUnfavourable=비용상 불리, MissingRequired=필수 필터 없음 등). 즉 "무조건 pushdown"이 아니라 이득이 될 때만 하고, 아니면 일반 조인으로 되돌린다. 쿼리 옵티마이저를 직접 확장하는 실전 예제로서 학습 가치가 크다.

비유 · dependent join이 하는 일

친구 20명의 "생일"을 A수첩에서 찾고, 그 생일에 해당하는 "그날의 뉴스"를 B서비스에서 가져와 붙인다고 하자. 순진한 방법은 B서비스의 모든 날짜 뉴스를 통째로 받아 A와 맞춰 보는 것 — 엄청난 낭비다. dependent join은 영리하다. 먼저 A수첩에서 20개의 생일(값)을 뽑고, 그 20개 날짜만 B서비스에 물어본다. "resolver(A)의 결과값을 dependent(B)의 필터로 바인딩"한다는 게 이 뜻이다. coral의 옵티마이저는 이 변환이 정말 이득일 때만(등가 조건이고, B가 그 필터를 받는 HTTP 소스이며, 비용이 유리할 때) 자동으로 적용한다.

핵심 설계 ⑤ — 읽기 전용 강제: 안전이 기본값

coral은 read layer(읽기 계층)로 설계됐다. 쿼리 실행 경로(runtime/query.rs)에서 DataFusion의 SQLOptionsDML/DDL(INSERT·UPDATE·DELETE·CREATE 등)을 원천 차단한다. 에이전트가 실수로(혹은 프롬프트 인젝션으로) 데이터를 바꾸려 해도 SQL 레벨에서 막힌다. 결과는 Arrow RecordBatch로 만들어져 Arrow IPC로 클라이언트에 스트리밍된다. "에이전트에게 데이터를 열되, 망가뜨릴 권한은 주지 않는다"는 원칙이 코드로 박혀 있다.

5디렉토리 구조 해부

추적 파일 1,647개 · crates/가 두뇌(9 크레이트) · sources/가 커넥터 카탈로그 · apps/가 UI

저장소를 열면 압도되기 쉽다(파일 1,647개, 러스트만 15만 줄). 하지만 뼈대는 단순하다 — crates/가 러스트 엔진 두뇌, sources/가 "어떤 API를 테이블로 쓸지"의 카탈로그, apps/가 사람이 쓰는 UI다. 엔진을 이해하려면 coral-engine부터, 커넥터를 이해하려면 sources/부터 보면 된다.

coral/ ├── crates/ ← 러스트 두뇌 (154K줄, 9 크레이트) │ ├── coral-engine/ ← ★ DataFusion 페더레이션 엔진 (≈45K줄) │ │ └── src/ │ │ ├── backends/ ← http/ · file/ · mcp/ (3개 백엔드) │ │ │ http/provider.rs = SQL→API pushdown │ │ │ file/listing.rs = ListingTable(Parquet/CSV…) │ │ │ mcp/ = 다른 MCP서버를 테이블로 │ │ └── runtime/ │ │ query.rs = SessionContext, 읽기전용 강제 │ │ dependent_join/ = 크로스소스 JOIN 옵티마이저 │ ├── coral-app/ ← 서버 조립·상태·소스 라이프사이클·자격증명 │ │ credentials/ = 봉투암호화(AES-256-GCM)/키체인 │ ├── coral-spec/ ← 소스 스펙 파싱·검증 (+ v4 DSL, OpenAPI import) │ ├── coral-mcp/ ← MCP stdio 어댑터 (에이전트 표면, 툴 8개) │ ├── coral-api/ ← protobuf 계약 + gRPC 바인딩 │ ├── coral-cli/ ← 터미널 어댑터 (clap) │ ├── coral-client/ ← 얇은 전송 + Arrow IPC 디코드/렌더 │ ├── coral-telemetry/ ← 트레이싱 헬퍼 │ └── auth/aws/ ← coral-auth-aws (SigV4) ├── sources/ ← 커넥터 카탈로그 (선언적 YAML) │ ├── core/ ← 번들 소스 26개 (github · claude …) │ ├── community/ ← 커뮤니티 기여 소스 181개 │ └── v4/ ← 차세대 DSL 프리뷰 (아직 라이브 경로 아님) ├── apps/ ← 프론트엔드·UI │ ├── reef/ ← React 19 + React Router 7 데스크톱 프론트 │ ├── desktop/ ← Electron 42 (reef + coral 사이드카) │ ├── ui/ ← CLI에 임베드되는 UI │ └── docs/ ← Mintlify 문서 사이트 ├── plugins/coral/ ← 에이전트 스킬 패키징 (plugins/coral/skills) ├── xtask/ ← 빌드 자동화 (문서생성·perf·릴리스 서명) ├── scripts/ ← install.sh 등 ├── Cargo.toml ← 워크스페이스 (9 크레이트, 공용 deps) ├── AGENTS.md ← 크레이트 소유권·경계 규칙 (에이전트/사람용) └── README.md · CHANGELOG.md (83KB)

읽는 순서는 이렇다. ① README.md + AGENTS.md(크레이트 경계 규칙) → ② sources/core/github/manifest.yaml(소스가 어떻게 선언되는지) → ③ crates/coral-engine/src/backends/mod.rs(백엔드 디스패치) → ④ backends/http/provider.rs(SQL→API pushdown의 실제) → ⑤ runtime/dependent_join/(크로스 소스 JOIN) → ⑥ crates/coral-mcp/(에이전트가 마주하는 툴 8개). 엔진의 심장은 coral-engine, 커넥터의 문법은 sources/, 에이전트 접점은 coral-mcp — 이 세 곳만 훑어도 전체 그림이 잡힌다.

함정 · 자주 헷갈리는 것
"v4 소스 DSL"과 "coral이 SQL을 써 준다"는 오해 둘

sources/v4/는 프리뷰다. 차세대 소스 DSL이 들어와 있지만 현재 라이브 경로는 dsl_version 3(위 github 예제)다. 튜토리얼을 볼 때 v3/v4를 섞으면 헷갈린다 — 지금 쓰는 건 v3다. ② coral은 자연어→SQL 변환기가 아니다. "built for agents"라고 해서 coral이 SQL을 대신 짜 주는 게 아니라, SQL은 LLM(또는 사람)이 쓰고 coral은 실행·최적화만 한다. 에이전트가 좋은 SQL을 쓰도록 list_catalog·describe_table 같은 디스커버리 툴을 제공할 뿐이다. ③ 러스트 크레이트 이름(coral-*)과 프론트 앱 이름(reef)이 달라 "reef가 리브랜드?"로 오해하기 쉽지만, reef는 그냥 프론트엔드 서브앱이다(개명 아님).

6학습 포인트

이 저장소 하나에 밀집한 "요즘 데이터·에이전트 인프라" — 기술별로 무엇을 배울 수 있나

coral이 학습 표본으로 훌륭한 이유는 DataFusion 확장, 데이터 페더레이션, 쿼리 옵티마이저 커스터마이징, 선언적 커넥터 DSL, MCP 서버, 봉투 암호화, 멀티크레이트 워크스페이스 설계가 한 저장소에 모여 있기 때문이다. 관심사별로 배울 것을 짚어 보자.

① DataFusion을 "확장하는" 법 — 라이브러리로 DB를 짓기

backends/http/provider.rsDataFusion TableProvider를 직접 구현하는 실전 레퍼런스다. "데이터를 어디서 어떻게 읽어올지"를 엔진에 꽂는 법, supports_filters_pushdown/scan으로 술어·투영·리밋 pushdown을 설계하는 법을 볼 수 있다. "쿼리 엔진을 통째로 만들지 않고, 검증된 엔진에 내 데이터 소스만 얹는" 현대적 접근의 교재다.

② 쿼리 옵티마이저를 직접 확장하기

runtime/dependent_join/커스텀 OptimizerRule + UserDefinedLogicalNodeCore로 쿼리 계획을 재작성하는 드문 실전 예제다. "언제 이 최적화가 이득인가"를 비용 기반으로 판단하고, 불리하면 폴백하는 taxonomy 설계까지 담겨 있다. 데이터베이스 내부(옵티마이저)가 어떻게 동작하는지 코드로 배우고 싶은 사람에게 최고의 자료다.

③ "선언적 커넥터"라는 발상

sources/ + coral-specAPI 통합을 코드가 아니라 데이터(YAML)로 기술하는 법을 보여 준다. 페이지네이션·인증·중첩 JSON 매핑·테이블 함수를 선언으로 표현하고, OpenAPI 명세를 import해 커넥터를 자동 생성하는 파이프라인(coral-spec/src/v4/surfaces/openapi/)까지. "N개 API를 어떻게 확장 가능하게 통합하나"의 아키텍처 답안이다.

④ 에이전트 표면(MCP)을 SQL로 설계하기

coral-mcprmcp(공식 러스트 MCP SDK)로 서버를 짜는 레퍼런스다. 노출 툴이 흥미롭다 — sql(읽기 전용 쿼리 배치), search, list_catalog·describe_table·list_columns(디스커버리), start_task/end_task, feedback. "에이전트가 스스로 스키마를 탐색해 좋은 SQL을 쓰도록" 유도하는 discovery-first 워크플로를 배운다.

⑤ 러스트 멀티크레이트 워크스페이스 + 보안 설계

9개 크레이트로 책임을 가른 구조(엔진/앱/스펙/전송/MCP/CLI…)와 AGENTS.md에 명문화된 크레이트 소유권 규칙은 대규모 러스트 프로젝트의 경계 설계 교재다. 여기에 unsafe_code = "forbid" 정책, AES-256-GCM 봉투 암호화 자격증명(ring+zeroize), OS 키체인 연동까지 — 실무 보안 패턴이 함께 담겨 있다.

실습 아이디어 · 작게 시작하기
지금 당장 손에 익힐 3가지
① coral를 설치하고 sources/core의 소스 하나(예: github)를 붙인 뒤 SELECT 한 줄로 API를 SQL로 질의해 본다. ② list_catalog·describe_table로 등록된 테이블·컬럼을 탐색하며 "에이전트가 스키마를 어떻게 발견하는지" 체험한다. ③ sources/community의 YAML 스펙 하나를 열어 pagination·auth·columns 매핑이 어떻게 선언됐는지 읽는다. 이 세 가지만 해 봐도 "이 도구가 안에서 뭘 하는지" 손에 잡힌다.

7시스템 · 실행 요구사항

빌드엔 Rust 1.95(edition 2024) · 실행은 단일 바이너리 · GPU·고사양 불필요

coral은 클라우드 인프라가 필요 없다. 실행 파일 하나로 도는 로컬 도구이고, 무거운 모델을 돌리지 않으므로 특별한 GPU나 고사양이 필요 없다. 소스에서 빌드하려면 러스트 툴체인이, 그냥 쓰려면 프리빌트 바이너리만 있으면 된다.

항목요구/설명
빌드 툴체인Rust 1.95(edition 2024) — 소스 빌드 시. 프리빌트를 쓰면 불필요
실행단일 바이너리 — macOS brew install withcoral/tap/coral, Linux curl … install.sh, Windows 10/11 x86_64 zip
OSmacOS · Linux · Windows
런타임 의존없음(단일 바이너리). Postgres 소스를 테스트할 때만 Docker 사용
자격증명데이터 소스 키/토큰은 환경변수 또는 대화형 프롬프트로 주입 → OS 키체인 또는 봉투암호화 파일에 보관
네트워크API·라이브 소스 질의 시 실시간 접근 필요(파일 소스는 로컬만으로 가능)

설치 · 에이전트 연결 명령

# 설치 (macOS 예시)
brew install withcoral/tap/coral

# MCP 서버로 에이전트에 연결 (Claude Code 예시)
claude mcp add coral -- coral mcp-stdio
#   Codex · Cursor 등 MCP 지원 에이전트에 동일 방식으로 등록

# 에이전트용 스킬 설치 (범용)
npx skills add withcoral/skills

# 소스(커넥터) 추가 후 SQL로 질의 — SQL은 사람/LLM이 작성
#   예) SELECT number, title FROM github.issues WHERE state = 'open' LIMIT 20
함정 · "무엇을 준비해야 하나"의 정확한 경계
"SQL 인터페이스"는 진짜지만, 소스 등록과 SQL 작성은 내 몫

소스를 먼저 등록해야 한다 — coral은 아무 API나 즉시 읽지 않는다. sources/core(26개)·community(181개)에 있으면 붙이면 되지만, 내가 쓸 API가 없으면 YAML 스펙을 직접 작성해야 한다. ② SQL은 내가(또는 LLM이) 쓴다 — coral에 NL2SQL은 없다. 자연어로 질의하려면 앞단의 LLM이 SQL을 생성해 줘야 한다. ③ 읽기 전용이다 — 데이터를 바꾸는 용도가 아니다(설계상 DML/DDL 차단). ④ 초기 버전 — v0.6.0으로 빠르게 바뀌는 중이니, 버전·소스 스펙 문법은 클론한 소스 기준으로 확인하는 게 안전하다.

8직접 해볼 수 있는 실습 과제

난이도별 5개 — SQL로 API 질의부터 나만의 커넥터 YAML·미니 TableProvider까지
난이도 ★☆☆ · 초급

과제 1 — "API를 SQL로" 눈으로 확인

coral를 설치하고 sources/core의 소스 하나(예: github)를 붙인 뒤, SELECT number, title FROM github.issues WHERE state='open' LIMIT 10 같은 SQL을 실행한다. 이 SQL이 실제로는 API 호출로 바뀌어 정돈된 테이블로 돌아오는 걸 관찰한다. 목표: "데이터 페더레이션 = 소스를 옮기지 않고 제자리에서 질의"를 체감.

난이도 ★☆☆ · 초급

과제 2 — 에이전트의 "스키마 발견"을 따라가기

list_catalogdescribe_tablelist_columns 순서로 등록된 테이블·컬럼을 탐색한다. 그런 다음 같은 흐름을 Claude Code에 coral을 붙여(claude mcp add coral -- coral mcp-stdio) 에이전트가 스스로 스키마를 발견해 SQL을 쓰는 과정을 지켜본다. 목표: discovery-first 워크플로가 왜 필요한지 이해.

난이도 ★★☆ · 중급

과제 3 — 나만의 커넥터 YAML 스펙 작성

sources/core/github/manifest.yaml을 본떠, 키가 필요 없는 공개 REST API(예: 공공데이터·오픈 API) 하나를 테이블로 선언하는 manifest.yaml을 쓴다. request.path·pagination·columns[].expr(path)로 응답 JSON을 컬럼에 매핑하면 된다. 목표: "코드 없이 데이터로 커넥터를 만드는" 선언적 통합을 체득.

난이도 ★★★ · 고급

과제 4 — DataFusion으로 미니 TableProvider 구현

coral 없이, DataFusion을 직접 의존성에 넣고 고정 행을 반환하는 초소형 TableProvider를 러스트로 짠다. scan()Arc<dyn ExecutionPlan>을 돌려주는 인터페이스, supports_filters_pushdown()으로 필터를 소비하는 흐름을 손으로 만들어 본다. coral의 backends/http/provider.rs가 참고 예시. 목표: "쿼리 엔진에 내 데이터 소스를 꽂는" 확장점의 원리를 코드로 증명.

난이도 ★★★ · 고급

과제 5 — 크로스 소스 JOIN과 dependent join 관찰

두 소스(예: github + 로컬 CSV)를 등록하고 JOIN 쿼리를 던진 뒤, 한쪽 값이 다른 소스의 필터로 밀려 들어가는지(dependent join) 실행 계획을 살펴본다. 필터가 pushdown되지 않는 조건(비등가 조인 등)도 만들어 폴백을 관찰한다. coral의 runtime/dependent_join/가 참고. 목표: 쿼리 옵티마이저가 "언제 최적화하고 언제 포기하는지"를 체득.

9관련 기술 심화 학습 로드맵

4주 코스 — SQL·DataFusion 기초 → 데이터 페더레이션 → MCP·에이전트 → 쿼리 옵티마이저·보안
주차주제 · 학습 목표
1주차
SQL · DataFusion 기초
관계형 모델과 쿼리 엔진. SQL의 기본(SELECT·WHERE·JOIN), 관계형 사고, 그리고 Apache DataFusion의 구조TableProvider·LogicalPlan·ExecutionPlan·Arrow 컬럼 포맷. 작은 CSV를 DataFusion으로 질의해 보며 "엔진이 데이터를 어떻게 흐르게 하는지" 익힌다.
2주차
데이터 페더레이션 · 커넥터
소스를 옮기지 않고 합치기. predicate/projection pushdown의 원리, 선언적 커넥터 DSL, 페이지네이션·인증을 데이터로 기술하기, OpenAPI import. coral sources/·backends/http/를 교재로. Steampipe·Trino와 비교하며 "페더레이션 vs ETL"을 정리.
3주차
MCP · 에이전트 통합
에이전트에게 데이터를 주는 법. Model Context Protocol, rmcp로 MCP 서버 짜기, discovery-first 툴 설계(list_catalog/describe_table), 읽기 전용 강제. "왜 SQL 인터페이스가 툴 호출 폭증을 줄이는가"를 벤치마크 관점에서 분석.
4주차
쿼리 옵티마이저 · 보안
엔진 내부와 실무 보안. DataFusion OptimizerRule·UserDefinedLogicalNode로 계획 재작성(dependent join), 비용 기반 판단·폴백. 나아가 AES-256-GCM 봉투 암호화·OS 키체인·멀티크레이트 워크스페이스 경계 설계까지 — 대규모 러스트 인프라의 정석.

10핵심 키워드 사전

이 문서에서 반드시 챙길 용어 14개
용어 01
데이터 페더레이션(Data Federation)
데이터를 한 창고로 옮기지 않고, 질의할 때마다 각 소스로 흩어 보내 제자리에서 읽어 합치는 방식. coral의 정체성. 반대 개념은 ETL(다 퍼와서 적재).
용어 02
Apache DataFusion
러스트로 만든 조립식 SQL 쿼리 엔진 라이브러리. 파싱·최적화·실행을 제공하되 데이터 소스는 TableProvider로 꽂게 열어 둔다. coral의 심장.
용어 03
TableProvider
DataFusion에 "이 테이블의 데이터를 어디서 어떻게 읽어올지"를 알려 주는 확장 인터페이스. coral의 HTTP/File/MCP 백엔드가 각각 이걸 구현해 API·파일·MCP를 테이블로 만든다.
용어 04
Predicate/Projection Pushdown
필터(WHERE)와 선택 컬럼(SELECT)을 엔진이 로컬에서 거르는 대신 데이터 소스 쪽으로 밀어 보내 애초에 적게 가져오는 최적화. coral이 SQL을 API 쿼리 파라미터로 번역하는 원리.
용어 05
Dependent Join(의존 조인)
한 소스(resolver)의 결과값을 다른 소스 API의 필터로 바인딩해 필요한 것만 호출하는 크로스 소스 조인. coral이 DataFusion 커스텀 옵티마이저로 구현하며, 이득일 때만 적용하고 아니면 폴백.
용어 06
OptimizerRule · UserDefinedLogicalNode
DataFusion의 쿼리 계획을 확장하는 두 훅. 전자는 계획을 재작성하는 규칙, 후자는 커스텀 논리 노드. coral의 DependentJoinOptimizerRule·DependentJoinNode가 이걸로 만들어졌다.
용어 07
선언적 소스 스펙(YAML DSL)
API를 코드가 아니라 YAML로 기술하는 방식(manifest.yaml). base_url·auth·tables·pagination·columns 매핑을 선언하면 커넥터가 된다. 현재 라이브는 dsl_version 3(v4는 프리뷰).
용어 08
ListingTable · object_store
File 백엔드의 토대. object_store가 로컬 파일과 S3를 같은 인터페이스로 열고, DataFusion ListingTable이 Parquet/JSONL/JSON/CSV를 테이블로 등록한다.
용어 09
Apache Arrow · Arrow IPC
엔진 내부 데이터가 흐르는 컬럼형 인메모리 포맷(Arrow)과, 그 데이터를 프로세스 간 전송하는 직렬화(IPC). coral의 결과가 클라이언트로 이 형태로 스트리밍된다.
용어 10
MCP · coral mcp-stdio
에이전트가 coral를 쓰는 표면. rmcp SDK로 만든 MCP 서버가 stdio로 툴을 노출한다. 핵심 툴 = sql(읽기 전용 쿼리)·search·디스커버리 3종·start_task/end_task·feedback(총 8개).
용어 11
Discovery-first
에이전트가 list_catalog·describe_table·list_columns로 먼저 스키마를 발견한 뒤 SQL을 쓰게 하는 설계. "테이블·컬럼을 모른 채 SQL을 헛짜는" 것을 막는다.
용어 12
읽기 전용(Read Layer)
coral은 데이터를 읽기만 한다. SQLOptions로 DML/DDL(INSERT·UPDATE·CREATE 등)을 SQL 레벨에서 차단해, 에이전트가 실수나 인젝션으로 데이터를 바꾸지 못하게 한다.
용어 13
봉투 암호화(AES-256-GCM Envelope)
소스 자격증명을 파일에 보관할 때 쓰는 암호화. 데이터키(DEK)를 키암호화키(KEK)로 다시 감싸고(ring), 쓴 뒤 메모리에서 즉시 소거(zeroize). OS 키체인 저장도 선택 가능. 키는 로컬을 떠나지 않는다.
용어 14
Steampipe와의 관계 · Local-first
가장 가까운 선배는 Steampipe(SQL over API, Postgres FDW 기반)다. coral의 차별점은 DataFusion 기반 + 로컬 우선 + MCP 네이티브 + 에이전트용 읽기 전용 + 선언적 YAML 커넥터 + dependent-join pushdown. Trino/Presto(분산 대규모)와 달리 경량 로컬 도구다.

11참고 링크

원본을 직접 열어 확인하는 습관 — 특히 버전·소스 스펙 문법은 클론한 소스 기준

경쟁 · 유사 도구 대비 위치

도구coral과의 관계
Steampipe가장 유사(SQL over API). 단 Postgres FDW 기반 vs coral은 DataFusion + 로컬 + MCP + 에이전트 특화
Trino / Presto분산 대규모 페더레이션 쿼리 엔진. coral은 그 반대편의 경량 local-first
Apache DataFusioncoral이 올라탄 토대 라이브러리(경쟁 아님)
DuckDB임베디드 분석 DB. coral은 저장이 아니라 라이브 API 페더레이션에 초점

저장소 · 제품
· GitHub: github.com/withcoral/coral (Apache-2.0 · v0.6.0 · 최신 커밋 2026-07-17, PR #1799)
· 조직/제품: withcoral.com
· 토대: Apache DataFusion · 가장 가까운 대안: Steampipe

핵심 파일(클론 후)
· crates/coral-engine/src/backends/mod.rs — 3개 백엔드 디스패치
· crates/coral-engine/src/backends/http/provider.rs — SQL→API pushdown(TableProvider)
· crates/coral-engine/src/runtime/dependent_join/ — 크로스 소스 JOIN 옵티마이저
· crates/coral-engine/src/runtime/query.rs — SessionContext·읽기 전용 강제
· crates/coral-mcp/src/ — MCP 서버(에이전트 표면, 툴 8개)
· sources/core/github/manifest.yaml — 선언적 소스 스펙 예시

배경 지식
· Model Context Protocol — 에이전트 툴 표준
· Apache Arrow · DataFusion · sqlparser-rs
· Federated database system — 페더레이션의 개념
· object_store — 로컬/S3 파일 접근

확인된 함정 모음 · 재확인 필수
읽기 전에 알아 둘 6가지

새 DB 아님 — 데이터를 저장하는 게 아니라, 흩어진 소스를 제자리에서 SQL로 질의하는 페더레이션 엔진이다. ② NL2SQL 없음 — SQL은 사람/LLM이 쓰고 coral은 실행만 한다("built for agents"의 실제 의미는 MCP 표면 + 디스커버리 툴 제공). ③ 소스 등록 선행 — 쓰려는 API가 sources/에 없으면 YAML 스펙을 직접 작성해야 한다. ④ 읽기 전용 — DML/DDL은 SQL 레벨에서 차단(데이터 변경 도구 아님). ⑤ v4 DSL은 프리뷰 — 라이브 경로는 dsl_version 3. ⑥ reef는 개명 아님apps/reef는 프론트엔드 서브앱일 뿐, coral의 리브랜드가 아니다(크레이트는 전부 coral-*). README 벤치마크 수치는 제작사 자체 측정이니 참고로만.