OAuth, 토큰 갱신, 동기화, 웹훅까지. SaaS 통합의 모든 반복 작업을 흡수하는 오픈소스 인프라. Replit, Ramp, Mercor가 프로덕션에서 쓰는 그 도구를 코드 단위로 해부한다.
이 레포가 정확히 뭘 하는가.
Nango(낭고)는 OAuth 인증, 토큰 갱신, API 프록시, 데이터 동기화, 웹훅 처리, AI 에이전트용 도구 노출까지 — SaaS 통합에서 매번 다시 짜는 골치 아픈 인프라를 한 곳에 모아 놓은 플랫폼이다. 사용자는 TypeScript 함수만 쓰면 되고, 나머지는 Nango 런타임이 알아서 한다.
오픈소스(Elastic License), 셀프호스팅 가능, 7.4k 스타. 96% TypeScript로 짜인 npm 모노레포에 Postgres와 Redis(+선택적 Elasticsearch)를 곁들인 풀스택 서비스다.
"외부 API 하나 붙이는 데 OAuth 토큰 관리, 재발급, 레이트 리밋, 재시도, 멀티 테넌시 처리하다가 또 하루가 갔다" — 이런 경험이 있다면 Nango가 정조준한 문제다. Auth + Proxy + Functions라는 3가지 원시 기능(primitive)으로 모든 통합 패턴을 흡수한다.
AI 에이전트 시대가 만든 새로운 수요.
2026년 현재 Nango가 TrendShift 상위에 오른 이유는 단순한 "OAuth 라이브러리"가 아니다. AI 에이전트가 외부 SaaS를 호출해야 한다는 새로운 요구가 폭발하면서, 800개 API에 즉시 인증·호출할 수 있는 인프라가 갑자기 인기 카테고리가 된 것이다.
Merge·Finch는 카테고리별로 통합 API를 미리 정의해서 던져주는 폐쇄형 SaaS다. 빠르지만 카테고리 밖으로 못 나가고, 비싸고, 블랙박스다.
Nango는 반대로 코드를 직접 보여준다. AI 빌더가 TypeScript 통합 함수를 생성하면 그걸 사용자가 리뷰·편집·버전 관리할 수 있다. "AI 생성, 인간 통제(AI-generated, human-controlled)"가 슬로건이다.
Zapier 류는 노코드 워크플로 빌더지, 제품 내장 통합 도구가 아니다. 내 SaaS 안에 "Slack 연결하기" 버튼을 박을 때는 도움이 안 된다.
Nango는 embeddable Auth UI(앱에 박는 인증 화면)와 SDK를 준다. 내 사용자가 내 앱 안에서 OAuth를 마치면 토큰은 Nango가 안전하게 보관·갱신한다.
2025-2026년 AI 에이전트용 도구 호출(tool calling) 플랫폼이 우후죽순 등장했다. Nango는 그중 가장 오래된 OAuth 인프라(2022년 시작)에 MCP 서버, AI 빌더, 액션 함수까지 후속 레이어로 붙여 "제품 통합 + AI 통합"을 한 곳에서 처리한다.
다른 솔루션은 통합 로직이 SaaS 안에 갇혀 있어서 수정·디버깅·이전이 어렵다. Nango는 통합을 TypeScript 함수로 보고 만질 수 있게 한다. Git에 커밋 가능. CI로 테스트 가능. 그래서 진지한 엔지니어링 팀이 좋아한다.
96% TypeScript 모노레포. 백엔드·프론트엔드·인프라 한눈에.
packages/server의 package.json을 직접 까보면 무엇으로 만들어졌는지 분명하다.
packages/database/lib/knexfile.cjs 기준으로 관리. 큰 모노레포에서 ORM 추상화가 발목 잡지 않게 한 선택.NANGO_LOGS_ENABLED=true로 켬), 트레이싱은 Datadog APM, 에러는 Sentry. 자체 @nangohq/logs 패키지가 추상화 레이어. Elasticsearch는 옵션이라 자체호스팅 시 빼도 동작한다.e2b 클라우드 샌드박스 + packages/runner가 별도 프로세스로 떠서 코드를 받아 실행한다. 멀티 테넌트 환경에서 한 고객 코드가 다른 고객 환경을 깨면 안 되므로 필수.packages/webapp은 Nango 클라우드 대시보드, packages/connect-ui는 사용자 제품에 박는 OAuth 화면, packages/frontend는 브라우저 SDK.
@vitejs/plugin-react-swc로 빌드 속도 우선. 모노레포 안에서 @nangohq/frontend는 npm에 따로 배포되는 사용자용 SDK.services:
nango-db: postgres:16.0-alpine # 핵심 메타데이터
nango-server: nangohq/nango-server # API + 대시보드 + Connect UI
nango-redis: redis:7.2.4 # 큐 신호, 캐시
nango-elasticsearch: elasticsearch:8.13 # (옵션) 로그 검색
docker-compose.yaml 한 파일로 풀스택이 뜬다. 이게 셀프호스팅을 가능하게 하는 핵심. Dockerfile은 멀티스테이지 빌드(precompile → build → web)로 npm workspaces 37개 패키지를 한 이미지에 담는다.
ASCII 다이어그램으로 본 데이터 흐름.
┌────────────────────────────────────────────────────────────────┐
│ 사용자 제품 (앱) │
│ ┌──────────────┐ ┌────────────────┐ │
│ │ Connect UI │ │ @nangohq/node │ ← 백엔드 SDK │
│ │ (브라우저 임베드)│ │ @nangohq/frontend│ ← 프론트엔드 SDK │
│ └──────┬───────┘ └────────┬───────┘ │
└─────────┼─────────────────────┼─────────────────────────────────┘
│ OAuth callback │ REST API
▼ ▼
┌────────────────────────────────────────────────────────────────┐
│ Nango Server (포트 3003) │
│ Express 5 + Helmet + Session │
│ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌──────────────┐ │
│ │ Auth │ │ Proxy │ │ Connect │ │ MCP Server │ │
│ │ 라우터 │ │ 라우터 │ │ Sessions │ │ (tool calling)│ │
│ └────┬─────┘ └────┬─────┘ └─────┬─────┘ └──────┬───────┘ │
└────────┼──────────────┼─────────────┼────────────────┼───────────┘
│ │ │ │
▼ ▼ ▼ ▼
┌────────────────────────────────────────────────────────────────┐
│ Orchestrator ─── Scheduler (작업 큐, 자체 구현) │
│ │ │
│ ▼ │
│ Runner (격리 프로세스, e2b 샌드박스 옵션) │
│ ↓ │
│ 사용자가 작성한 TypeScript 통합 함수 실행 │
└────────┬───────────────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ PostgreSQL 16: 연결·토큰·records·로그메타 │
│ Redis 7: 큐 신호, 레이트리밋 카운터 │
│ Elasticsearch: 통합 실행 로그 (옵션) │
└──────────────────────────────────────────┘
800개 API마다 OAuth URL, 토큰 엔드포인트, 스코프, 헤더 형식이 다르다. Nango는 이걸 코드가 아니라 packages/providers/providers.yaml 한 파일로 선언한다. 새 API 추가는 PR 한 줄.
사용자가 작성한 sync/action 함수를 Temporal 같은 외부 워크플로 엔진 없이 직접 만든 Scheduler + Orchestrator에서 돌린다. 이유는 통합 도메인 특유의 요구(체크포인트, 점진 동기화, 레이트 리밋 백오프, 멀티 테넌시)를 일반 워크플로 엔진으로 풀기 어려워서다.
packages/scheduler + packages/orchestrator + packages/runner가 한 묶음. 큐 상태는 Postgres에 있고 Redis는 신호 채널일 뿐.
한 Nango 계정 안에 prod/staging/dev 같은 environment가 있고, 각 environment 안에 connection(연결된 사용자 계정), integration(API 설정), record(동기된 데이터)가 모두 격리된다. DB 스키마부터 이 격리가 강제된다.
(1) 사용자 클릭 ──→ 내 앱 프론트엔드
│
│ nango.openConnectUI()
▼
(2) Connect UI 모달 열림 (Nango가 호스팅)
│
│ 사용자가 "Slack 연결" 클릭
▼
(3) Nango Server가 OAuth URL 생성 → Slack으로 리다이렉트
│
│ 사용자가 Slack에서 권한 승인
▼
(4) Slack → Nango callback URL로 code 전달
│
│ Nango가 code를 token으로 교환
│ 토큰을 암호화해서 Postgres에 저장
│ connectionId 생성
▼
(5) 모달이 onEvent("CONNECT") 이벤트 발사
│
▼
(6) 내 앱은 connectionId만 받아서 보관
이후 nango.get({ connectionId, endpoint })로 API 호출
토큰 만료되면 Nango가 알아서 갱신
호텔의 발레파킹 같은 구조다. 손님(사용자)이 차(OAuth 토큰)를 직접 주차하지 않고 호텔 직원(Nango)에게 키만 넘긴다. 손님은 차 번호표(connectionId)만 들고 다니다가 "내 차 가져와줘"(API 호출) 하면 직원이 알아서 처리한다. 차 검사(토큰 갱신)도 직원이 한다.
npm workspaces 37개 패키지를 의미별로 묶어보면.
nango/
├── packages/ ← npm workspaces 본진
│ │
│ ├── ▼ 핵심 서버 4종
│ ├── server/ ← Express 5 메인 서버 (포트 3003)
│ ├── jobs/ ← cron, 정기 작업
│ ├── orchestrator/ ← 작업 큐 관리, 스케줄러 위 한 단계
│ ├── persist/ ← 작업 결과 영속화 전용 서비스
│ │
│ ├── ▼ 워크플로 엔진
│ ├── scheduler/ ← 자체 작업 스케줄러 (Postgres + Redis)
│ ├── fleet/ ← Runner 인스턴스 풀 관리
│ ├── runner/ ← 사용자 함수 격리 실행 프로세스
│ ├── runner-sdk/ ← 함수가 import하는 SDK (nango.get 등)
│ ├── sandbox/ ← 코드 실행 샌드박스 추상화
│ ├── lambda-runner/ ← AWS Lambda 기반 Runner 구현
│ ├── tasks/ ← 작업 단위 정의·추적
│ ├── data-ingestion/← 외부 데이터 수집 파이프라인
│ │
│ ├── ▼ 도메인 패키지
│ ├── providers/ ← providers.yaml + 800개 API 메타데이터
│ ├── records/ ← 동기된 데이터 저장소 추상화
│ ├── webhooks/ ← 외부·내부 웹훅 처리
│ ├── nango-yaml/ ← nango.yaml DSL 파서
│ │
│ ├── ▼ 데이터·저장소
│ ├── database/ ← Postgres + Knex 마이그레이션
│ ├── kvstore/ ← Redis 키밸류 추상화
│ ├── logs/ ← Elasticsearch 로그 인덱싱
│ ├── keystore/ ← 토큰 암호화 보관소
│ ├── kms/ ← 키 관리 서비스 추상화
│ ├── feature-flags/ ← 기능 플래그 관리
│ │
│ ├── ▼ 프론트엔드 3종
│ ├── webapp/ ← Nango 클라우드 대시보드 (React + Vite)
│ ├── connect-ui/ ← 사용자 제품에 박는 OAuth UI
│ ├── frontend/ ← 브라우저 SDK (npm: @nangohq/frontend)
│ ├── design-system/ ← Storybook 컴포넌트 라이브러리
│ │
│ ├── ▼ SDK·CLI
│ ├── node-client/ ← Node.js SDK (npm: @nangohq/node)
│ ├── cli/ ← nango CLI 명령어
│ ├── types/ ← 모든 패키지가 쓰는 TypeScript 타입
│ ├── shared/ ← 서버 측 공통 비즈니스 로직
│ ├── utils/ ← 작은 헬퍼들
│ │
│ ├── ▼ 빌링·과금
│ ├── billing/ ← Stripe 통합
│ ├── usage/ ← API 호출량 측정
│ ├── metering/ ← 과금용 미터링 서비스
│ ├── pubsub/ ← 내부 이벤트 전파
│ ├── email/ ← 트랜잭션 메일
│ └── authz/ ← 권한 체크
│
├── docs/ ← Mintlify 기반 공식 문서
├── scripts/ ← provider 스코프 동기화, llms.txt 생성 등
├── tests/ ← 통합·E2E 테스트
├── dev/ ← docker-compose.dev.yaml (개발용 의존성)
├── github-actions/ ← 커스텀 GitHub Actions
├── .agents/skills/ ← AI 에이전트가 읽는 스킬 가이드
├── .claude/ ← Claude Code 전용 설정
├── docker-compose.yaml
├── Dockerfile ← 프로덕션용 멀티스테이지
└── Dockerfile.self_hosted
각 패키지가 자기 영역(server는 HTTP, runner는 실행, scheduler는 큐)만 책임지고, 의존성은 "@nangohq/utils": "file:../utils" 형식으로 명시적으로 걸려 있다. tsconfig.build.json의 references로 TypeScript가 빌드 순서를 자동 계산한다. "모노레포에서 코드 분리"의 모범 사례.
이게 흥미롭다. 레포 루트에 .agents/skills/와 .claude/가 있다는 건 Nango 자체 개발에 AI 에이전트(Claude Code 등)를 적극 사용한다는 뜻이다. 자기 제품(AI 빌더로 통합 함수 생성)을 자기들이 먼저 쓴다는 dogfooding의 흔적.
이 레포에서 뽑아낼 수 있는 기술별 인사이트.
각 provider마다 OAuth flow 코드를 짜면 8만 줄이 된다. packages/providers/providers.yaml을 보면 한 provider당 10~30줄 YAML로 끝낸다. "데이터로 다룰 수 있는 건 코드로 두지 마라"의 교과서.
비슷한 패턴이 적용 가능한 곳: webhook 시그니처 검증, 레이트 리밋 정책, 페이지네이션 방식.
토큰 만료 직전(보통 5분 전)에 갱신해야 하는데, 여러 워커가 동시에 같은 connection으로 API를 때리면 갱신이 N번 발생한다. Nango는 Redis 분산 락(@nangohq/kvstore)으로 connection별 갱신을 직렬화한다. 코드를 까보면 락 패턴이 깔끔하다.
tsconfig.build.json이 packages별 tsconfig를 references로 연결한다. tsc -b 한 번에 의존 순서대로 빌드. 빌드 캐시(tsbuildinfo)로 변경된 패키지만 재빌드한다. 큰 모노레포의 빌드 시간 절약 핵심.
npm run dev:watch:apps 명령어 안에 concurrently --names 'srv,web,job,prs,orc,met,con'로 server·webapp·jobs·persist·orchestrator·metering·connect-ui를 한 터미널에서 띄운다. 멀티 프로세스 개발 환경의 정석.
다른 솔루션(Material UI, Chakra)에 비해 Radix는 접근성·키보드 인터랙션만 책임지고 스타일은 손대지 않는다. 결과적으로 Tailwind와 만나 디자인 자유도가 매우 높다. webapp의 radix-ui, @radix-ui/react-* 임포트를 보면 학습 자료가 된다.
고객 앱에 박는 OAuth 모달(packages/connect-ui)을 별도 빌드로 빼서 iframe·postMessage 패턴으로 호스트 앱과 통신한다. Stripe Elements, Plaid Link 같은 임베드 SDK 만드는 법을 배울 수 있는 사례.
Temporal, Inngest, BullMQ 같은 기성 솔루션이 있는데도 자체 스케줄러를 만든 결정의 무게를 느껴볼 만하다. "기성 도구가 도메인 요구를 100% 충족하지 못할 때 어디까지 직접 만들 것인가" 의 실제 사례.
셀프호스팅 / 로컬 개발에 필요한 것.
package.json의 "engines": { "node": ">=20.0.0" }가 명시. Dockerfile은 22.22.2 사용. nvm으로 22 깔면 안전.docker compose --file dev/docker-compose.dev.yaml up -d로 Postgres와 Redis만 띄우면 충분. 로그 검색이 필요하면 Elasticsearch까지.최소 권장 구성
─────────────────────────────────────────
nango-server 2 vCPU / 4GB RAM
nango-runner(s) 1 vCPU / 2GB RAM × N개 (멀티 인스턴스)
postgres-16 2 vCPU / 4GB RAM / 50GB SSD
redis-7 1 vCPU / 1GB RAM
elasticsearch-8 2 vCPU / 4GB RAM / 100GB SSD (옵션)
docker-compose.yaml의 nango-server에 platform: linux/amd64가 박혀 있다. Apple Silicon(M1/M2/M3) Mac에서는 Rosetta 에뮬레이션으로 돌아간다. ARM 네이티브 이미지는 아직 공식 배포 안 함.
NANGO_ENCRYPTION_KEY # 토큰 암호화 키 (32바이트 base64)
NANGO_DB_PASSWORD # Postgres 비밀번호
NANGO_SERVER_URL # 외부 callback용 공개 URL
SERVER_PORT=3003
NANGO_LOGS_ENABLED=false # Elasticsearch 안 쓰면 false
초급부터 상급까지 4단계.
docker compose up → 대시보드 접속 → GitHub integration 생성 → Connect UI로 내 GitHub 계정 연결 → nango.get({ endpoint: '/user' })로 내 프로필 조회까지. 약 30분 소요.
배우는 것: OAuth 흐름 전체, providerConfigKey vs connectionId 개념, 토큰이 어디 저장되는지.
nango-integrations/ 디렉토리에 sync 함수를 작성. nango.yaml에 schedule을 5min으로 설정. CLI로 deploy. 대시보드에서 동기화된 issue 레코드가 records 테이블에 쌓이는 걸 확인. 약 1~2시간.
배우는 것: 점진적 동기화(incremental sync), 체크포인트, 자동 페이지네이션 SDK 사용법.
Nango가 아직 지원 안 하는 작은 SaaS의 OAuth를 providers.yaml에 정의 → 로컬에서 동작 확인 → PR. 메인테이너 리뷰 거치며 OAuth flow 디버깅을 배운다. 약 반나절.
배우는 것: OAuth provider별 quirk (스코프 콤마/스페이스 구분, refresh token 헤더 차이 등), 오픈소스 기여 사이클.
내가 만든 action 함수를 Nango MCP 엔드포인트(@modelcontextprotocol/sdk)로 노출 → Claude Desktop의 claude_desktop_config.json에 등록 → 채팅에서 "내 Slack에 메시지 보내줘"가 실제로 동작하는 걸 확인. 약 1일.
배우는 것: MCP 프로토콜 구조, tool schema 작성, AI 에이전트와 외부 API 연결 패턴.
코드에 이미 @workos-inc/node가 들어있다. WorkOS 계정 생성 → SAML connection 설정 → Nango 대시보드에 SSO 로그인 추가. enterprise self-hosted 시나리오 시뮬레이션. 약 2~3일.
배우는 것: SAML 흐름, IdP/SP 관계, 엔터프라이즈 인증 구성 실전.
8주짜리 커리큘럼으로 정리.
RFC 6749 (OAuth 2.0), RFC 6750 (Bearer Token), RFC 7636 (PKCE), OpenID Connect Core 1.0. spec을 직접 읽는 게 결국 빠르다. Authorization Code, Client Credentials, Device Code 흐름 차이까지.
병행해서 Nango providers.yaml에서 OAuth 2.0과 OAuth 1.0a, API key, Basic Auth가 각각 어떻게 다르게 표현되는지 비교.
npm workspaces 공식 문서 → pnpm workspaces 비교 → Nx, Turborepo는 왜 안 썼는지 추측해보기. TypeScript project references, tsc -b 빌드 캐시. 빌드 그래프 시각화 시도.
BullMQ → Temporal → Inngest → Restate 순서로 비교. 각각이 어떤 도메인 문제에서 빛나는지. 마지막에 Nango의 자체 scheduler 코드를 까서 "왜 직접 만들었나"를 추론.
Vite 7 + SWC, Tailwind 4의 새 빌드 파이프라인, Radix UI primitive 사용법. Tanstack Query vs SWR. Nango webapp의 라우팅 구조 따라가기.
Idempotency key, exponential backoff with jitter, circuit breaker, dead letter queue. exponential-backoff, rate-limiter-flexible 라이브러리가 Nango에서 어떻게 쓰이는지 추적.
Anthropic MCP 공식 spec → @modelcontextprotocol/sdk 코드 읽기 → Nango가 어떻게 동적으로 tool schema를 생성하는지 추적. 직접 MCP 서버 하나 만들어보기.
Elastic License v2 vs AGPL vs BSL 비교. "오픈코어(open core)" 전략. Nango가 어디까지 오픈하고 어디부터 닫는지 LICENSE_SHORT 읽기. Cal.com, Supabase, Posthog와 모델 비교.
Nango 문서·코드에서 자주 만나는 용어들.
packages/records가 담당. 사용자는 records를 SDK로 조회하거나 webhook으로 변경 알림을 받는다.packages/runner. tRPC로 메인 서버와 통신한다.packages/scheduler 위에서 동작한다. p-queue로 동시성 제어.nango.openConnectUI() 한 줄로 띄운다. 사용자가 직접 외부 API 키나 OAuth 화면을 만질 필요가 없게 만드는 화이트라벨 UI.더 깊이 들어가려면.
GitHub 레포 · github.com/NangoHQ/nango — 6,418 commits, 7.4k stars, 189 releases. master 브랜치가 활발.
공식 문서 · nango.dev/docs — Mintlify 기반. https://nango.dev/docs/llms.txt에 LLM이 읽기 좋게 정리된 인덱스가 있다.
800+ API 카탈로그 · nango.dev/docs/integrations/overview — 어느 API를 지원하는지 한눈에.
packages/providers/providers.yaml — OAuth 메타데이터 800개의 정수.
packages/server/lib — Express 라우터 구조.
packages/scheduler/lib — 자체 스케줄러 구현.
Dockerfile — 모노레포 멀티스테이지 빌드 모범 사례.
docs/spec.yaml — OpenAPI 스펙. API 표면 전체 파악용.
MCP 공식 · modelcontextprotocol.io
Express 5 마이그레이션 · expressjs.com/en/guide/migrating-5.html
npm workspaces · docs.npmjs.com/cli/v10/using-npm/workspaces
Elastic License v2 비교 · elastic.co/licensing/elastic-license
git clone → docker compose up → 대시보드 접속. 토큰 갱신이 실제로 어떻게 일어나는지 Slack OAuth 한 번 끼워서 직접 본다. README만 100번 읽는 것보다 빠르다.