https://product.kyobobook.co.kr/detail/S000220221456
LUVIT EPL과 유튜브 데이터로 배우는 DuckDB | 이기준 - 교보문고
LUVIT EPL과 유튜브 데이터로 배우는 DuckDB | 복잡한 데이터 분석 흐름을 더 단순하게 만드는 DuckDB 최근 주목받고 있는 DuckDB를 활용해 SQL 기반 데이터 분석과 실전 프로젝트를 학습할 수 있도록 구
product.kyobobook.co.kr
Claude in Excel에서 바로 SQL 쿼리를 실행할 수 있는 공개 MCP 서버를 구축했습니다. 설정도 없고, 인증 정보도 없고, 별도 설치도 필요 없습니다. 연결한 뒤 질문만 하면 됩니다.
이 서버는 두 개의 크리켓 데이터베이스 위에서 동작합니다. 약 200만 건의 공(ball) 단위 데이터가 저장되어 있습니다.
하나는 ODI 데이터를 담고 있는 Postgres(Supabase) 데이터베이스이고, 다른 하나는 T20 데이터를 담고 있는 DuckDB 데이터베이스입니다. 두 데이터베이스 모두 2013년부터 2025년까지의 데이터를 포함하고 있습니다.
각 행은 경기 중 하나의 투구(delivery)를 나타냅니다. 따라서 타자, 투수, 타격 득점, 추가 득점(wide, no-ball, bye, leg bye), 아웃 유형, 아웃된 선수, 경기장, 타격 팀, 수비 팀, 이닝, 시즌, 경기 날짜 등의 정보를 모두 포함합니다. 12년 동안의 모든 ODI 및 T20 경기에 대한 공 단위 상세 데이터입니다.
예를 들어 다음과 같은 질문을 할 수 있습니다.
"총 득점, 경기 수, 상대 오버 수, 경기당 득점률, 오버당 득점률 기준 상위 20명의 타자를 보여줘."
Claude는 SQL을 자동으로 작성하고, 데이터베이스를 조회한 뒤 결과를 Excel로 가져옵니다.
사용 방법도 간단합니다.
Claude in Excel을 열고:
Settings → Connectors → Custom Connectors
로 이동한 뒤 MCP URL을 붙여넣고 이름을 지정하여 저장합니다.
그 다음 채팅 창으로 돌아와 질문을 시작하면 됩니다.
또한 이 서버에서 가져온 데이터를 기반으로 차트를 만든 예제 스프레드시트도 제공하고 있습니다. 링크는 아래 리소스 섹션에서 확인할 수 있습니다.
에이전트는 데이터 구조를 어떻게 이해할까?
실무적으로 매우 중요한 부분입니다.
Claude가 MCP 서버에 연결되면 어떻게 테이블 구조와 컬럼 의미를 이해할까요?
이번 사례에서는 MCP 도구 설명(tool description)에 상세한 docstring을 추가했습니다.
Claude가 연결되면 다음 정보를 함께 받습니다.
- 테이블 이름
- 모든 컬럼 이름
- 각 컬럼의 의미
- 데이터 집계 규칙
- 오버 계산 방식
- 득점 계산 방식
- 위켓 확인 방법
- 선수 이름 검색 팁
- 시즌 포맷 관련 주의사항
- 예제 SQL 쿼리
예를 들어 ball 컬럼은 단순 순번이 아니라 over.ball 형식의 식별자이며, wide나 no-ball 때문에 한 오버에 6개 이상의 투구가 존재할 수 있다는 설명이 포함됩니다.
또한 득점 계산 시 runs_off_bat와 extras의 차이점도 설명됩니다.
위켓은 wicket_type뿐 아니라 other_wicket_type도 함께 확인해야 하며, 선수 검색 시에는 성(surname)을 기준으로 LIKE 검색을 사용하는 것이 좋다는 팁도 포함됩니다.
단일 테이블 기반의 크리켓 데이터셋에서는 이러한 정보만으로도 충분합니다. 추가 안내 없이도 대부분의 SQL을 올바르게 생성합니다.
하지만 실제 운영 환경에서는 이야기가 다릅니다.
수십 개 또는 수백 개의 테이블이 존재하고, 비즈니스 로직이 복잡하며, 여러 조인과 계산 필드가 존재하는 환경에서는 docstring만으로는 부족합니다.
이때는 적절한 Semantic Layer가 필요합니다.
여기에는 다음과 같은 요소가 포함됩니다.
- 테이블 및 컬럼별 비즈니스 정의
- 테이블 간 관계 정보
- 검증된 Golden Query
- KPI 정의 규칙
- 비즈니스 용어 사전
예를 들어:
- Revenue는 Gross Revenue가 아닌 Net Revenue를 의미한다.
- Active Customer는 최근 90일 내 거래가 1건 이상 발생한 고객을 의미한다.
와 같은 규칙들입니다.
이 Semantic Layer를 구축하고 유지하는 것 자체가 하나의 프로젝트입니다.
얼마나 상세하게 작성할지, 쿼리마다 어떤 컨텍스트를 제공할지, 스키마 변경 시 어떻게 유지보수할지 모두 고민해야 합니다.
저는 고객 프로젝트에서 이러한 작업을 여러 번 수행해 보았는데 실제로 상당한 노력이 필요한 작업입니다.
다만 이번 공개 데모 서버에서는 단순한 스키마와 명확한 데이터 의미 덕분에 docstring만으로도 충분히 잘 동작합니다.
내부 동작 방식
서버는 FastAPI 기반으로 구현되어 있습니다.
Postgres는 asyncpg와 커넥션 풀을 사용합니다.
DuckDB는 읽기 전용 임베디드 연결을 사용합니다.
두 데이터베이스는 각각 다음 API 엔드포인트로 노출됩니다.
- /api/query/postgres
- /api/query/duckdb
그리고 Tadata의 FastAPI-MCP 패키지를 이용하여 MCP 서버로 마운트됩니다.
따라서 다음과 같은 모든 MCP 클라이언트에서 사용할 수 있습니다.
- Claude in Excel
- Claude Code
- Claude Desktop
- 기타 MCP 지원 클라이언트
서버는 두 가지 응답 형식을 지원합니다.
기본 형식은 JSON입니다.
TSV 형식도 지원하며, 이 경우 축약된 컬럼명을 사용하여 응답 크기를 약 70% 줄일 수 있습니다.
AI 컨텍스트 윈도우 사용량을 줄이는 데 상당히 도움이 됩니다.
한계점과 해결 방법
이전에 Claude in Excel과 MCP에 관한 글을 읽어보셨다면 익숙한 문제일 것입니다.
Claude in Excel은 데이터를 한 번에 모두 가져오려는 경향이 있습니다.
Claude Code처럼 동작하면서 전체 결과를 컨텍스트에 로드하고, 수천 개의 셀에 한 번에 기록하려고 시도합니다.
결과적으로 중간에 멈추거나 실패하는 경우가 있습니다.
이번 서버에서는 백엔드에서 이를 처리했습니다.
응답은 최대 1,000행으로 제한됩니다.
1,000행을 초과하는 결과가 나오면:
- 처음 1,000행만 반환
- truncation 플래그 추가
방식으로 처리합니다.
오류를 발생시키지는 않습니다.
즉, 일부 데이터라도 항상 받을 수 있습니다.
전제는 간단합니다.
Claude in Excel을 사용하는 경우 대부분:
- 요약 결과
- 집계 결과
- 필터링된 데이터
를 조회하지, 수백만 행을 Excel로 가져오지는 않는다는 것입니다.
예를 들어:
"시즌별 상위 20명 득점자"
는 20행 정도만 반환됩니다.
"2024년 모든 T20 경기 요약"
도 수백 행 수준입니다.
이 정도가 현재 구조에 가장 적합한 사용 사례입니다.
만약 전체 테이블 덤프나 수백만 행 추출이 필요하다면 Claude in Excel보다는 Claude Code 또는 직접 데이터베이스 연결을 사용하는 것이 적합합니다.
또한 1,000행 이하라 하더라도 500행 이상 데이터를 가져오는 경우에는 다음과 같이 요청하는 것이 좋습니다.
"데이터를 가져와서 100행씩 나누어 작성해줘."
문제는 데이터 조회가 아니라 Excel 셀에 기록하는 과정에서 발생하기 때문입니다.
하지만 대부분의 분석 작업에서는:
- 상위 득점자
- 팀별 평균
- 경기 요약
- 볼링 기록
- 스트라이크 레이트
정도의 결과만 필요하므로 일반적으로 문제없이 동작합니다.
추천 테스트 쿼리
제가 주로 사용하는 테스트 쿼리는 다음과 같습니다.
총 타격 득점, 경기 수, 상대 오버 수, 경기당 득점률, 오버당 득점률 기준 상위 20명의 타자를 보여줘. 각 결과는 별도의 테이블로 제공하고, 각각에 대한 인사이트 차트도 추가해줘.
이 쿼리는 다음 기능을 모두 테스트합니다.
- SQL 생성
- 집계 계산
- 계산 컬럼 생성
- Excel 테이블 작성
- 차트 생성
즉 전체 파이프라인을 검증할 수 있는 좋은 테스트입니다.
처음에는 특정 선수 이름 검색 쿼리는 피하는 것이 좋습니다.
선수 이름이:
- 이니셜만 있는 경우
- 전체 이름인 경우
- 여러 표기 방식이 존재하는 경우
가 있기 때문입니다.
다음과 같은 LIKE 검색이 더 안정적입니다.
WHERE striker LIKE '%Kohli%'
보안
이 서버는 체험용 공개 서버이므로 OAuth나 권한 관리는 적용하지 않았습니다.
하지만 기본적인 보안 장치는 모두 적용되어 있습니다.
- Postgres 계정 자체를 읽기 전용으로 설정
- default_transaction_read_only = on
- DuckDB read_only 모드 사용
- 외부 접근 비활성화
- INSERT, DROP, ALTER, CREATE, COPY, LOAD, ATTACH 등 위험 SQL 차단
- SELECT, SHOW, DESCRIBE, EXPLAIN, WITH만 허용
- 30초 쿼리 타임아웃
- IP당 시간당 60회 요청 제한
- 쿼리당 최대 1,000행 반환
보다 정교한 접근 제어가 필요한 경우 MCP의 OAuth 기능을 사용할 수 있습니다.
Claude Custom Connector에서도 OAuth Client ID 및 Client Secret을 지원합니다.
이론적으로는 Auth0 같은 인증 시스템을 연결하여 역할 기반 접근 제어를 구현할 수 있습니다.
다만 현재 이 공개 서버에서는 적용하지 않았으며, Claude in Excel과 OAuth 연동은 아직 충분히 테스트하지 못했습니다.
현재 고객 프로젝트에서는 API 토큰 기반 인증을 사용하고 있습니다.
MCP 보안에 대한 일반적인 조언
무작위 MCP 서버에 연결하지 않는 것이 좋습니다.
결국 다른 사람이 운영하는 코드를 실행하는 것과 비슷하기 때문입니다.
해당 서버가 여러분의 질의나 데이터를 어떻게 처리하는지 알 수 없습니다.
이번 서버는 GitHub에 전체 소스코드를 공개했습니다.
Python 코드 전체를 직접 확인할 수 있습니다.
만약 제 공개 서버를 신뢰하지 않는다면 저장소를 복제한 뒤 코드를 검토하고 직접 배포할 수도 있습니다.
또는 읽기 전용 서버이므로 우선 공개 엔드포인트로 테스트해 보는 것도 가능합니다.
소스 코드 및 재현 방법
전체 소스 코드는 GitHub 공개 저장소에서 제공됩니다.
README에는 다음 내용이 포함되어 있습니다.
- 저장소 복제
- 패키지 설치
- Postgres 연결 문자열 설정
- 서버 실행 방법
또한 T20 데이터가 포함된 DuckDB 파일도 함께 제공됩니다.
전체 구현은 하나의 Python 파일로 작성되어 있습니다.
사용된 주요 라이브러리는 다음과 같습니다.
- FastAPI
- asyncpg
- duckdb
- fastapi-mcp
- slowapi
구조가 매우 단순하고 깔끔하기 때문에 한 번에 전체 코드를 읽고 이해할 수 있습니다.
Resources
- Documentation page
- MCP Endpoint: https://db-mcp.tigzig.com/mcp
- API Docs (Swagger)
- Source Code on GitHub
- Sample spreadsheet with charts
Previous posts on Claude in Excel and MCP:
- Power User Guide to Claude in Excel & PowerPoint — 26 Working Tips
- Claude in Excel with MCP Connector — Talk to Your Backends from Inside Excel
- Claude in Excel — Nifty50 Return Distribution Analysis
- Claude in Excel built a 50-chart India Macroeconomic Dashboard from RBI data
- Claude in Excel just one-shotted an XGBoost response model
'EPL과 유튜브 데이터로 배우는 DuckDB' 카테고리의 다른 글
| 맨체스터 시티와 토튼햄 홋스퍼 경기당 점유율 변화(24-25 EPL) (0) | 2026.06.17 |
|---|---|
| 엘링 홀란과 모하메드 살라의 득점맵 비교(24-25 EPL) (0) | 2026.06.17 |
| DuckDB CLI 닷 커맨드 (0) | 2026.06.16 |
| DuckDB 익스텐션 (0) | 2026.06.16 |
| DuckDB 메타 데이터 함수 (0) | 2026.06.16 |
댓글