이 레포가 무엇을 하는 물건인가.
OpenSEO는 셀프호스팅 가능한 풀스택 SEO 분석 앱이다. 키워드 리서치·백링크·순위 추적·사이트 오디트를 하나의 모던 UI에서 제공하되, 실제 SEO 데이터는 DataForSEO API를 통해 가져온다. 앱 자체 비용은 $0 — 쓴 만큼만 API 비용이 청구된다.
더 독특한 점은 MCP(Model Context Protocol) 서버를 내장해, Claude Code·Hermes 같은 AI 에이전트가 OpenSEO의 SEO 데이터를 직접 도구로 호출할 수 있다는 것. 에이전트 스킬 7개(keyword-research, competitor-analysis 등)도 함께 제공된다.
Semrush·Ahrefs 대비 오픈소스의 포지셔닝 — 그리고 솔직한 한계.
| 도구 | 월 비용(2026) | 주요 한계 |
|---|---|---|
| Semrush Pro | $139.95~$499.95 | 데이터 내보내기 제한, API 별도 과금 |
| Ahrefs Standard | $229~$449 | 팀 좌석당 추가 비용, 셀프호스팅 불가 |
| Moz Pro | $99~$599 | 기능이 위 둘보다 제한적 |
| OpenSEO | 앱 $0 + DataForSEO API 종량제 | 아래 참조 |
앱 코드를 직접 포크해 커스터마이즈할 수 있다. DataForSEO의 신규 계정 $1 무료 크레딧으로 먼저 테스트해볼 수 있고, 이후에도 쓴 만큼만 낸다. 100개 키워드 주간 추적 비용은 약 $1.20/월에 불과하다. MCP 서버 내장으로 AI 에이전트가 SEO 데이터를 직접 사용하는 워크플로가 가능하다.
OpenSEO 자체는 SEO 데이터를 수집하지 않는다. 모든 키워드 볼륨·백링크·SERP 데이터는 DataForSEO(유료 서드파티)에서 가져온다. 즉 "오픈소스"는 앱 레이어에만 해당하며, 실제 데이터 소스는 여전히 유료 외부 서비스다.
DataForSEO 최솟값은 $50 충전. 대량 사용 시 비용이 빠르게 늘어날 수 있다 (100개 백링크 완전 탐색 ≈ $10.94). Semrush/Ahrefs 대비 데이터 신선도·커버리지가 같다는 보장은 없다.
v0.0.21 단계로, 프로덕션 성숙도보다는 빠르게 성장 중인 초기 오픈소스 프로젝트에 가깝다. 스케줄 사이트 오디트, 클라이언트 맞춤 리포트, 로컬 SEO 등 핵심 기능이 아직 로드맵 단계다.
MCP + AI 에이전트 통합이 핵심 차별점이다. SEO 도구가 Claude Code 같은 AI 에이전트에 직접 연결되는 사례는 흔치 않다. "AI 에이전트가 SEO 전략을 자율적으로 실행"하는 워크플로를 가장 쉽게 구현할 수 있는 오픈소스 도구로 포지셔닝됐다. TanStack + Cloudflare Workers 에지 풀스택이라는 최신 아키텍처도 개발자 관심을 끌었다.
프론트엔드·백엔드·DB·데이터·인프라 각 레이어를 상세 분석.
| 기술 | 역할 | 선택 이유 |
|---|---|---|
| React 19 | UI 컴포넌트 렌더링 | 최신 동시성 렌더링·Server Actions 지원 |
| TanStack Start | 풀스택 프레임워크 (라우팅·SSR) | Next.js 대안 — Cloudflare Workers 네이티브 지원, 타입 안전 라우팅 |
| TanStack Router | 파일 기반 타입 안전 라우팅 | 라우트 파라미터·검색 파라미터 타입 추론 |
| TanStack Query | 서버 상태 관리·캐싱 | SEO 데이터 특성상 stale-while-revalidate 패턴 최적 |
| TanStack Table | 키워드·백링크 테이블 렌더링 | 대용량 데이터 정렬·필터·페이징 |
| TanStack Form | 폼 상태 관리 | 타입 안전 폼 밸리데이션 |
| Tailwind CSS v4 | 유틸리티 CSS | v4의 CSS-first 설정 방식 채택 |
| daisyUI v5 | UI 컴포넌트 라이브러리 | Tailwind 기반 미리 만든 컴포넌트 |
| Recharts | 순위 추적·트렌드 차트 | React 네이티브 반응형 차트 |
| Lucide React | 아이콘 | 경량 트리쉐이킹 가능 아이콘셋 |
| Vite 7 | 빌드 도구 | @cloudflare/vite-plugin으로 Workers 환경 빌드 |
| 기술 | 역할 | 비고 |
|---|---|---|
| Cloudflare Workers | 서버리스 엣지 런타임 | workerd(V8 기반), Node.js 아님 — 전 세계 엣지 실행 |
| Cloudflare Workflows | 장기 실행 비동기 작업 | 사이트 오디트처럼 시간이 걸리는 크롤링 작업 처리 |
| Cloudflare Durable Objects | 상태 있는 실시간 객체 | 온보딩 채팅 에이전트 세션 관리에 사용 |
| Better Auth | 인증·세션 관리 | 이메일/비번 + Google OAuth. 3가지 AUTH_MODE 지원 |
| MCP SDK | AI 에이전트 연동 프로토콜 | @modelcontextprotocol/sdk 1.29.0 — 18개 툴 노출 |
| Cloudflare Workers OAuth | MCP OAuth 2.0 인증 | 에이전트 클라이언트 등록·토큰 관리 |
| AI SDK (Vercel) | LLM 호출 추상화 | @ai-sdk/react + OpenRouter 프로바이더로 다양한 모델 지원 |
| agents 0.15.0 | AI 에이전트 런타임 | 온보딩 채팅 에이전트 구현에 사용 |
| Drizzle ORM | 타입 안전 DB 쿼리 | SQLite/D1 방언, 마이그레이션 관리 |
| 기술 | 역할 | 비고 |
|---|---|---|
| Cloudflare D1 | 메인 관계형 DB (SQLite) | Workers에 바인딩된 서버리스 SQLite — 26개 마이그레이션 파일 |
| Cloudflare KV | OAuth 토큰·세션 저장 | OAUTH_KV 바인딩 — MCP 클라이언트 등록 정보 |
| Cloudflare R2 | Lighthouse 결과 JSON 저장 | 사이트 오디트 대용량 리포트 파일 |
| API | 제공 데이터 | 비용 구조 |
|---|---|---|
| DataForSEO SERP API | SERP 결과, 키워드 순위, 광고 | 요청당 과금 ($0.0006~$0.0035) |
| DataForSEO Labs API | 키워드 메트릭, 검색량, KD, CPC | 1,000 키워드당 $0.0035~ |
| DataForSEO Backlinks API | 백링크 목록, 도메인 권위도 | 도메인당 $0.063~$0.109 |
| DataForSEO Lighthouse API | Core Web Vitals, 성능 점수 | 페이지당 과금 |
| Google Search Console API | 실제 검색 노출·클릭 데이터 | 무료 (OAuth 연동 필요) |
| 도구 | 용도 |
|---|---|
| Vitest | 유닛·통합 테스트 (MCP 툴, DB 쿼리 등) |
| Playwright | E2E 테스트 (도메인 오버뷰, 키워드 탐색 흐름) |
| oxlint | Rust 기반 고속 ESLint 대체 린터 |
| Prettier | 코드 포매터 |
| knip | 미사용 exports·의존성 탐지 |
| Wrangler | Cloudflare Workers 로컬 개발·배포 CLI |
| pnpm 10 | 패키지 매니저 |
| PostHog | 프로덕션 에러 추적·분석 |
ASCII 구조도 + 핵심 설계 패턴.
OpenSEO는 단일 AUTH_MODE 환경 변수로 배포 시나리오를 전환한다.
빌드 시 AUTH_MODE 값이 Vite에 의해 클라이언트 번들에 인라인된다. 그래서 Docker 이미지 빌드는 컨테이너 시작 시점에 이뤄진다 — 런타임에서야 AUTH_MODE를 알 수 있기 때문.
OpenSEO는 DataForSEO를 단순히 통과시키지 않는다. 자체 D1 DB에 결과를 캐싱한다. 예를 들어 키워드 메트릭(keywordMetrics 테이블)은 한 번 불러오면 이후 같은 프로젝트의 요청에서 재사용된다. 이는 DataForSEO API 비용을 절감하는 핵심 설계다.
코드가 어디에 어떻게 배치돼 있는가.
routes/_project/p/$projectId/가 SEO 기능의 심장이다. 파일 하나가 곧 페이지 하나다. domain.tsx는 도메인 오버뷰, keywords.tsx는 키워드 리서치 — TanStack Router의 파일 기반 라우팅 덕분에 URL 구조가 디렉토리 구조와 1:1 대응된다.
src/server/mcp/가 AI 에이전트 연동의 전부다. 여기에 툴을 추가하면 Claude Code가 새로운 SEO 기능에 접근할 수 있게 된다.
이 레포에서 무엇을 배울 수 있는가.
TanStack Start + Router + Query + Table + Form을 모두 하나의 프로젝트에서 볼 수 있다. React 생태계에서 Next.js가 아닌 대안적 풀스택 구성의 실제 사례를 보기 드문데, OpenSEO가 그 교과서다.
src/routes/_project/p/$projectId/keywords.tsx를 열고 useParams(), useSearch()의 타입이 어떻게 자동 추론되는지 확인해보자. Route 파일의 validateSearch가 URL 쿼리스트링을 Zod로 검증하는 패턴도 학습 포인트다.
Cloudflare Workers는 Node.js가 아닌 workerd(V8 아이솔레이트) 환경이다. 파일시스템 없음, 실행 시간 제한, Worker 간 상태 공유 불가. 이 제약에 맞게 아키텍처를 짜는 방법을 OpenSEO에서 직접 볼 수 있다. D1(SQLite), KV, R2, Durable Objects, Workflows를 각 용도에 맞게 조합하는 패턴이 핵심이다.
src/server/mcp/server.ts에서 18개 MCP 툴이 어떻게 등록되는지 보자. 각 툴은 입력 스키마(Zod), 핸들러 함수, 출력 스키마로 구성된다. instrumentMcpToolHandler로 모든 툴 호출이 PostHog에 추적되는 계측 패턴도 실무에 바로 적용 가능하다.
src/db/app.schema.ts는 실무 수준의 SQLite 스키마 예시다. 소프트 삭제(archivedAt), 복합 유니크 인덱스, 부분 인덱스(WHERE status IN ('pending','running'))로 중복 실행 방지, 의도적 FK 없는 스냅샷 테이블 등 실제 프로덕션 패턴이 담겼다.
DataForSEO API를 어떻게 호출하고 캐싱하고 정규화하는지 볼 수 있다. dataforseo-client npm 패키지 사용법, 비용 최적화를 위한 배치 요청 패턴, 결과를 D1에 저장해 재사용하는 캐싱 전략이 핵심이다.
Docker로 5분 만에 시작하거나, Cloudflare 에지에 직접 배포.
| 항목 | 최솟값 | 비고 |
|---|---|---|
| Docker | Docker Desktop 설치 | 로컬 셀프호스팅 경로 (권장) |
| DataForSEO API 키 | 신규 계정 $1 무료 크레딧 | 최소 충전액 $50 |
| Node.js (로컬 개발) | v22 | pnpm 10 필요 |
| Cloudflare 계정 (CF 배포) | 무료 플랜 가능 | Workers + D1 + KV + R2 사용 |
| Google OAuth (선택) | Google Cloud 프로젝트 | Search Console 연동 시만 |
| RAM | 4GB+ | Dockerfile에서 --max-old-space-size=4096 설정됨 |
# 1. 레포 클론
git clone https://github.com/every-app/open-seo.git
cd open-seo
# 2. 환경 변수 파일 복사
cp .env.example .env
# 3. DataForSEO API 키 설정 (.env 편집)
# DATAFORSEO_API_KEY=your_base64_encoded_login:password
# 4. 컨테이너 시작
docker compose up -d
# 5. 브라우저에서 접속
open http://localhost:3001
Dockerfile.selfhost를 보면 빌드가 이미지 빌드 시가 아닌 컨테이너 시작 시에 이뤄진다. AUTH_MODE 같은 환경 변수가 Vite에 의해 클라이언트 번들에 인라인되기 때문이다. CMD가 pnpm run db:migrate:local && NODE_OPTIONS=--max-old-space-size=4096 pnpm run build && vite preview를 순서대로 실행한다.
# Wrangler 로그인
npx wrangler login
# D1 DB 마이그레이션 (프로덕션)
pnpm run db:migrate:prod
# 빌드 & 배포
pnpm run deploy
# 또는 GitHub 리포지토리의 "Deploy to Cloudflare" 버튼 클릭
# 의존성 설치
pnpm install
# .env.local 파일 생성 후 DataForSEO 키 설정
cp .env.example .env.local
# D1 로컬 마이그레이션 (Wrangler 로컬 SQLite 사용)
pnpm run db:migrate:local
# 개발 서버 시작
pnpm run dev
# 테스트 실행
pnpm test # 유닛 테스트
pnpm test:e2e # E2E 테스트 (Playwright)
난이도별로 단계적으로 도전해보자.
Docker 빠른 시작 가이드를 따라 앱을 띄우고, DataForSEO 신규 계정의 $1 무료 크레딧으로 키워드 리서치를 3개 해보자. DataForSEO 대시보드에서 실제 API 호출 비용이 얼마나 차감됐는지 확인한다.
앱의 "AI & Agents" 메뉴를 열고 MCP 연결 가이드를 따라 Claude Code에 OpenSEO를 MCP 서버로 등록한다. 그런 다음 .agents/skills/keyword-research/SKILL.md를 읽고, Claude Code에서 직접 키워드 리서치 스킬을 실행해본다.
src/server/mcp/tools/ 안의 기존 툴(예: research-keywords.ts)을 참고해 DataForSEO의 다른 API(예: Google Trends API)를 새로운 MCP 툴로 구현해보자. src/server/mcp/server.ts에 등록하고, 유닛 테스트도 작성한다.
TanStack Start로 새 페이지를 추가하는 것을 실습한다. 예시: "내 도메인의 Google 검색 노출 트렌드" 페이지. src/routes/_project/p/$projectId/에 새 파일을 만들고, Google Search Console API 데이터를 TanStack Query로 패칭하고, Recharts로 시각화한다.
코드를 포크해 커스텀 기능(예: 팀용 공유 키워드 리스트, Slack 알림 통합)을 추가한 뒤 Cloudflare Workers에 배포한다. Wrangler의 D1·KV·R2 바인딩을 직접 설정하고, AUTH_MODE=cloudflare_access로 Cloudflare Access 인증을 붙여 안전하게 공개 URL로 서비스해보자.
OpenSEO를 이해하고 확장하기 위한 주차별 학습 계획.
| 주차 | 주제 | 목표 | 학습 자료 |
|---|---|---|---|
| 1주 | Cloudflare Workers 기초 | workerd 환경 이해, wrangler CLI, D1·KV 바인딩 실습 | Cloudflare Workers 공식 문서, Workers Playground |
| 2주 | TanStack Router + Start | 파일 기반 라우팅, 타입 안전 URL 파라미터, SSR 모드 | TanStack 공식 문서 + 예제 레포 |
| 3주 | TanStack Query + Table | 서버 상태 관리, stale-while-revalidate, 가상 스크롤 테이블 | TanStack Query v5 공식 가이드 |
| 4주 | Drizzle ORM + SQLite 설계 | 스키마 정의, 마이그레이션, 복합 인덱스, 소프트 삭제 패턴 | Drizzle ORM 문서, SQLite 공식 문서 |
| 5주 | MCP(Model Context Protocol) | MCP 스펙 이해, 서버 구현, OAuth 2.0 인증 플로우 | modelcontextprotocol.io, MCP SDK 문서 |
| 6주 | DataForSEO API 활용 | SERP·Keywords·Backlinks API 각 엔드포인트, 비용 최적화 | DataForSEO 공식 API 문서 |
| 7주 | Better Auth + OAuth | 이메일/비번·소셜 로그인 구현, 세션 관리, JWT 검증 | better-auth.js 공식 문서 |
| 8주 | Cloudflare Workflows + Durable Objects | 장기 실행 비동기 워크플로, 상태 있는 서버리스 객체 | Cloudflare Workflows·DO 문서, 공식 예제 |
| 9주 | AI SDK + 에이전트 스킬 | Vercel AI SDK로 LLM 호출, 스킬 마크다운 설계 패턴 | sdk.vercel.ai, OpenSEO .agents/skills/ 소스 |
| 10주 | SEO 도메인 지식 | 키워드 의도 분류, 백링크 품질 평가, Core Web Vitals, Lighthouse 점수 | Google Search Central 문서, Ahrefs SEO Blog |
이 레포를 이해하는 데 필요한 핵심 용어 정리.
| 용어 | 정의 | OpenSEO에서의 역할 |
|---|---|---|
| DataForSEO | SEO 데이터 제공 B2B API 서비스 | OpenSEO의 모든 SEO 데이터 소스. SERP·키워드·백링크·Lighthouse 데이터 제공 |
| MCP (Model Context Protocol) | AI 에이전트가 외부 도구를 표준 방식으로 호출하는 프로토콜 | Claude Code·Hermes 등이 OpenSEO SEO 데이터를 직접 사용하게 하는 연결 레이어 |
| Cloudflare Workers | V8 아이솔레이트 기반 서버리스 엣지 런타임 | OpenSEO의 서버 실행 환경. Node.js와 다르게 파일시스템 없음, 전 세계 엣지 실행 |
| D1 (Cloudflare) | Cloudflare의 서버리스 SQLite 데이터베이스 | 프로젝트·키워드·순위 추적·오디트 결과 저장 (26개 테이블) |
| KV (Key-Value) | Cloudflare의 글로벌 분산 KV 스토어 | OAuth 토큰·MCP 클라이언트 등록 정보 저장 |
| Durable Objects | Cloudflare의 상태 있는 서버리스 객체 | 온보딩 채팅 에이전트의 대화 상태 유지 |
| Cloudflare Workflows | 장기 실행·재시도·체크포인트 지원 비동기 워크플로 | 사이트 오디트 크롤링처럼 수 분이 걸리는 작업 처리 |
| TanStack Start | TanStack Router 기반의 풀스택 React 프레임워크 | Next.js 대안. SSR + 파일 기반 라우팅 + Workers 네이티브 지원 |
| Drizzle ORM | 타입스크립트 최우선 SQL ORM | D1에 대한 타입 안전 쿼리, 스키마 정의, 마이그레이션 관리 |
| Better Auth | 타입스크립트 인증 라이브러리 | 이메일/비번, Google OAuth, 조직 멤버십, 세션 관리 |
| SERP Feature | 구글 검색 결과 페이지의 특수 블록 | 이미지 팩·Featured Snippet·People Also Ask 등. OpenSEO가 순위 스냅샷에 함께 저장 |
| Keyword Difficulty (KD) | 특정 키워드로 1페이지 상위에 오르기 얼마나 어려운가를 0~100으로 나타낸 점수 | DataForSEO Labs API에서 제공, 키워드 메트릭에 캐싱 |
| Core Web Vitals | 구글이 정한 웹 성능 핵심 지표 (LCP, CLS, INP) | Lighthouse API로 측정해 auditLighthouseResults에 저장 |
| workerd | Cloudflare의 오픈소스 서버리스 JS 런타임 | Workers의 실제 실행 엔진. V8 기반으로 Node.js와 호환성 주의 필요 |
| oxlint | Rust로 작성된 고속 JavaScript 린터 | ESLint 대신 사용. 타입 인식(--type-aware) 린팅 지원 |
출처·심화 학습 자료 모음.