GITHUB 레포 딥다이브 · 2026-08-04 · VERCEL/NEXT-FORGE · Vercel이 만든 프로덕션급 Next.js SaaS 스타터 — 그리고 "요즘 웹앱은 어떻게 조립하는가"의 정답지

next-forge 딥다이브
"빈 종이"가 아니라 "이미 배선된 집" : 20여 개 최고급 서비스가 타입으로 연결된 Next.js 모노레포 표본

vercel/next-forge는 Next.js로 SaaS(구독형 웹 서비스)를 만들 때 처음부터 다시 배선하지 않도록 미리 다 연결해 둔 "프로덕션급 스타터 템플릿"이다. 인증·결제·데이터베이스·이메일·분석·보안·관측(모니터링)까지, 실무에서 반드시 붙이게 되는 조각들을 각각 최고로 꼽히는 서비스로 미리 배선해 놓고, 명령어 하나(npx next-forge@latest init)면 그 전체 골격이 내 컴퓨터에 복제된다.

하지만 이 딥다이브가 next-forge를 고른 진짜 이유는 "빠른 시작"이 아니다. next-forge의 소스 자체가 "2026년에 실무용 웹앱을 어떻게 구조화하는가"에 대한 살아 있는 참조 아키텍처이기 때문이다. Turborepo 모노레포 안에 7개 앱 + 20개 공유 패키지가 나뉘고, Clerk(인증)·Stripe(결제)·Prisma+Neon(DB)·Resend(이메일)·Arcjet(보안)·Sentry(에러추적)·PostHog(제품분석) 같은 서비스가 각각 @repo/* 패키지 뒤에 캡슐화된다. 그리고 그 모든 경계를 TypeScript 타입 + Zod 검증이 관통한다.

압권은 두 가지 설계 철학이다. 첫째, "우아한 성능 저하(graceful degradation)" — 어떤 서비스의 환경변수(API 키)를 안 넣으면 에러가 나는 게 아니라 그 기능만 조용히 꺼진다. 둘째, "내가 소스를 소유한다" — next-forge는 설치되는 라이브러리가 아니라 내 저장소로 복제되는 코드라, 마음대로 뜯어고치고 공급자(provider)를 갈아 끼울 수 있다.

(저장소 vercel/next-forge · 라이선스 MIT (© 2025 Vercel) · 언어 TypeScript · 버전 v6.0.2 · Next.js 16.1.6 · React 19.2.4 · Turborepo 2.8.14 · 패키지매니저 Bun 1.3.10 · ★ 약 7,000 · 원작 Hayden Bleasel, 현재 Vercel 공식 관리 · TrendShift Daily #19)
목차
  1. 한 줄 정체
  2. 왜 주목받는가 — 스타터가 아니라 "참조 아키텍처"
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 — 타입세이프 env·우아한 성능저하·Turbo 파이프라인
  5. 디렉토리 구조 해부
  6. 학습 포인트 — 기술별 배울 것
  7. 시스템 요구사항 & 배포
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 로드맵 (주차별)
  10. 핵심 키워드 사전
  11. 참고 링크

1한 줄 정체

이 프로젝트가 정확히 무엇인지 한 문장으로

next-forge는 "Next.js로 SaaS를 만들 때 필요한 골격 전체를 미리 조립해 둔, 명령어 하나로 내 저장소에 복제되는 프로덕션급 모노레포 템플릿"이다. 마케팅 사이트, 로그인 뒤의 본 앱, 웹훅·크론을 받는 API 서버, 문서 사이트, 이메일 템플릿, 컴포넌트 작업실(Storybook)까지 — 실무 SaaS가 결국 갖게 되는 앱들을 처음부터 나눠 두고, 인증·결제·DB 같은 기능은 갈아끼울 수 있는 패키지로 분리해 둔다.

한 장의 비유

"빈 대지에 집을 처음부터 짓기" 대신 "전기·수도·가스가 이미 들어온 골조 완성 주택"

create-next-app으로 시작하는 건 빈 대지를 받는 것과 같다. 자유롭지만, 전기 배선(인증)·상하수도(DB)·도시가스(결제)·보안 시스템(방화벽)을 전부 내가 끌어와 연결해야 한다. 실무 SaaS 하나를 세우려면 이 "배관 공사"에만 몇 주가 걸린다.

next-forge는 그 배관이 이미 다 들어온 골조 주택을 준다. 벽에 콘센트(인증 훅)가 있고, 수도꼭지(DB 클라이언트)를 틀면 물이 나오고, 보안 패널(Arcjet)이 현관에 붙어 있다. 당신은 이제 벽지를 고르고 가구를 배치하는(=제품 기능을 만드는) 일부터 시작한다.

결정적 차이: 이 집의 설계도(소스코드)를 당신이 소유한다. 가스회사가 마음에 안 들면 배관을 뜯어 다른 회사로 바꿀 수 있다(=Clerk를 다른 인증으로 교체). 세 들어 사는 SaaS 보일러플레이트와 다른 점이다.

용어
스타터/보일러플레이트 · 모노레포 · SaaS · 프로바이더(provider)
스타터(starter)/보일러플레이트는 매번 반복되는 초기 설정을 미리 해 둔 "출발용 코드 묶음"이다. 모노레포(monorepo)는 여러 개의 앱·라이브러리를 한 저장소 안에서 함께 관리하는 방식(mono=하나 + repo=저장소). SaaS는 Software as a Service, 즉 구독형으로 파는 웹 서비스(Notion·Slack 같은 것). 프로바이더는 특정 기능을 대신 해 주는 외부 업체/서비스를 뜻한다 — 인증 프로바이더 Clerk, 결제 프로바이더 Stripe처럼. next-forge의 핵심은 "각 기능을 프로바이더 뒤에 숨겨 두고 갈아끼울 수 있게" 만든 점이다.

기술적으로 더 정확히 말하면, next-forge는 Turborepo가 관리하는 Bun 워크스페이스 모노레포다. apps/ 폴더에는 배포 가능한 앱 7개가, packages/ 폴더에는 앱들이 공유하는 패키지 20개가 들어 있다. 각 패키지는 @repo/이름 형태로 import되며(예: @repo/auth, @repo/database), 자기 환경변수를 Zod 스키마로 검증하는 keys.ts를 품고 있다. 즉 "기능 = 패키지 = 갈아끼울 수 있는 부품"이라는 등식이 프로젝트 전체를 관통한다.

2왜 주목받는가 — 스타터가 아니라 "참조 아키텍처"

Next.js 보일러플레이트는 수백 개다. next-forge가 상위에 오른 차별점

첫째, Vercel 공식 프로젝트로 편입됐다. 원래 Hayden Bleasel 개인이 만든 next-forge가 지금은 Next.js를 만든 회사 Vercel의 공식 저장소(vercel/next-forge)로 관리된다. "Next.js 팀이 직접 권장하는 SaaS 구조"라는 신뢰가 붙는다. Vercel은 자체 아카데미에 "next-forge 프로덕션 패턴" 강의까지 두고 있다.

둘째, "설치하는 라이브러리"가 아니라 "복제되는 코드"다. 대부분의 프레임워크는 node_modules에 숨어 있어 내부를 못 고친다. next-forge는 init 순간 create-next-app의 --example 기능으로 저장소 전체를 내 프로젝트로 복사한다. 그 뒤로는 100% 내 코드 — 마음대로 뜯어고칠 수 있다. 이걸 요즘은 "fork-and-own(복제해서 소유)" 방식이라 부르고, shadcn/ui가 대중화한 흐름이다.

셋째, "의견이 강하지만(opinionated), 갈아끼울 수 있다". 각 기능이 최고급 프로바이더 하나로 기본 선택되어 있어 초보자는 고민 없이 시작한다. 동시에 각 프로바이더가 @repo/* 패키지 뒤에 캡슐화돼 있어, 나중에 "Clerk 대신 다른 인증", "Resend 대신 다른 이메일"로 바꾸는 마이그레이션 가이드까지 문서로 제공한다. "빠른 시작"과 "장기 유연성"을 동시에 노린 설계다.

차별 포인트
우아한 성능 저하(graceful degradation)가 기본값

보통의 보일러플레이트는 모든 API 키를 다 넣어야 앱이 겨우 켜진다. next-forge는 반대다. DB(DATABASE_URL) 하나만 있으면 뜨고, 나머지 결제·이메일·분석은 환경변수가 없으면 그 기능만 조용히 비활성된다(stripe?.prices.list()처럼 옵셔널 체이닝으로). "일단 돌려 보고, 필요한 것부터 하나씩 켠다"가 가능해 학습 곡선이 확 낮아진다.

항목next-forgecreate-next-app / 일반 보일러플레이트
시작점배관 완료된 SaaS 골격빈 앱(CNA) 또는 관리 안 되는 템플릿
구조모노레포 7앱·20패키지단일 앱(대개)
기능 통합인증·결제·DB·이메일·보안·관측 미리 배선직접 하나씩 붙여야 함
공급자 교체패키지 캡슐화 + 가이드 제공강결합이라 교체 어려움
키 없을 때기능만 꺼짐(우아한 저하)대개 에러/크래시
소유권내 저장소로 복제(fork-and-own)제각각
유지보수Vercel 공식 + update 명령방치되기 쉬움

넷째, 타입 안전이 "선택"이 아니라 "강제"다. 환경변수조차 문자열로 대충 읽지 않고 @t3-oss/env-nextjs + Zod로 빌드 시점에 검증한다. 예컨대 Clerk 비밀키는 반드시 sk_로 시작해야 한다는 규칙까지 스키마에 박혀 있어, 오타 난 키로 배포되는 사고를 컴파일 단계에서 잡는다. 이런 "실무에서 실제로 데는 부분"을 미리 막아 둔 게 인기의 본질이다.

3기술 스택 전체 지도

모노레포 뼈대 → 7개 앱 → 20개 패키지 → 외부 서비스까지 층층이

① 모노레포 뼈대 (빌드 · 언어 · 품질)

역할도구한 줄 설명
모노레포 오케스트레이터Turborepo 2.8여러 앱·패키지의 build/test/dev를 캐시하고 병렬 실행. 안 바뀐 건 다시 안 돎
패키지 매니저 · 런타임Bun 1.3설치·스크립트 실행이 빠른 올인원 런타임. 워크스페이스로 여러 패키지 연결
프레임워크Next.js 16 (App Router)React 서버 컴포넌트 기반 풀스택 프레임워크
UI 런타임React 19서버 컴포넌트 · 액션 등 최신 기능 사용
언어TypeScript 5.9앞뒤·패키지 경계까지 타입이 관통
린트 · 포맷Ultracite (Biome 2 래퍼)ESLint+Prettier 대신 Rust 기반 초고속 통합 도구
테스트Vitest 4Vite 기반 초고속 유닛 테스트
환경변수 검증@t3-oss/env-nextjs + Zodenv를 스키마로 검증, 타입까지 부여

② 앱 7종 (apps/ — 각각 독립 배포 가능)

포트역할
app3000로그인 뒤의 본 애플리케이션 — 인증·DB 붙은 SaaS 본체
web3001마케팅 웹사이트 — CMS·SEO·블로그·다국어
api3002서버리스 API — Stripe 웹훅·크론 등을 수신
email3003React Email 미리보기 서버(템플릿 개발용)
docs3004문서 사이트 — Mintlify 기반
studio3005Prisma Studio — DB를 표로 보고 편집
storybook6006디자인 시스템 컴포넌트 작업실

③ 패키지 20종 (packages/ — @repo/* 로 공유)

패키지기본 프로바이더 / 기술역할
authClerk로그인·회원가입·세션·조직
databasePrisma + Neon(서버리스 Postgres)타입세이프 ORM + 서버리스 DB 어댑터
paymentsStripe (+ agent-toolkit)구독·결제·웹훅
emailResend + React Email트랜잭션 이메일 발송·템플릿
design-systemshadcn/ui + Radix (53개 UI 컴포넌트)다크모드 포함 공용 컴포넌트 라이브러리
analyticsPostHog + Vercel Analytics + GA제품 분석 + 웹 분석
observabilitySentry + Logtail(BetterStack)에러 추적·로깅·가동 모니터링
securityArcjet + nosecone봇 차단·앱 보안·보안 헤더
rate-limitUpstash Redis요청 속도 제한
cmsBaseHub타입세이프 콘텐츠 관리(블로그·문서)
notificationsKnock인앱 알림
feature-flagsVercel flags + toolbar기능 플래그(A/B·점진 배포)
internationalizationLanguine다국어(i18n) 번역 관리
webhookssvix아웃바운드 웹훅 발송
storageVercel Blob파일 업로드·저장
aiAI SDK + OpenAI + streamdownLLM 연동 유틸(스트리밍 응답)
collaboration실시간 협업아바타·라이브 커서 등
seo메타데이터·sitemap·JSON-LD검색엔진 최적화 유틸
next-config공용 next.config모든 앱이 공유하는 Next 설정
typescript-config공용 tsconfig모든 패키지가 상속하는 TS 설정
용어
ORM · 서버리스 Postgres · 웹훅(webhook) · 기능 플래그
ORM(Object-Relational Mapping)은 SQL을 직접 쓰는 대신 코드 객체로 DB를 다루게 해 주는 계층 — 여기선 Prisma. 서버리스 Postgres(Neon)는 서버를 켜 두지 않고 요청이 올 때만 붙는 DB라, Vercel 같은 서버리스 환경과 궁합이 좋다. 웹훅은 외부 서비스가 "결제 완료!" 같은 사건이 생기면 내 API로 먼저 전화를 걸어(HTTP 요청) 알려 주는 방식. 기능 플래그는 코드를 다시 배포하지 않고 스위치로 특정 기능을 켜고 끄는 장치(점진 출시·A/B 테스트에 씀).

4아키텍처 심화 — 타입세이프 env·우아한 성능저하·Turbo 파이프라인

"앱은 패키지를 조립하고, 패키지는 외부 서비스를 캡슐화한다"는 3층 구조

next-forge의 아키텍처를 한 문장으로 요약하면 "앱(apps)은 여러 패키지(packages)를 레고처럼 조립하고, 각 패키지는 외부 서비스를 감싸 타입세이프한 문 하나로 노출한다"이다. 그림으로 보면 이렇다.

┌──────────────────────────────────────────────────────────────┐ │ apps/ (배포 단위) │ │ │ │ app(3000) web(3001) api(3002) docs/email/… │ │ 본 앱 마케팅 웹훅·크론 부속 앱들 │ │ │ │ │ │ │ └──────┬───────┴──────┬───────┘ │ │ │ import "@repo/*" │ │ ▼ │ ├────────────────────────────────────────────────────────────── │ │ packages/ (공유 부품) │ │ │ │ @repo/auth @repo/database @repo/payments @repo/email │ │ @repo/security @repo/observability @repo/analytics … │ │ │ │ │ │ │ │ 각 패키지 = index.ts(기능) + keys.ts(env 검증 · Zod) │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ │ ├────────────────────────────────────────────────────────────── │ │ 외부 서비스 (프로바이더) │ │ Clerk Neon(Postgres) Stripe Resend │ │ Arcjet Sentry PostHog Upstash … │ └──────────────────────────────────────────────────────────────┘ ▲ ▲ │ Turborepo가 전체 build/test/dev를 │ │ 캐시 + 의존성 순서대로 병렬 실행 │ └──────────────────────────────────────────┘

핵심 패턴 ① — 타입세이프 환경변수 (keys.ts + Zod)

next-forge에서 가장 자주 마주치는 파일이 keys.ts다. 각 패키지가 자기가 필요한 환경변수를 Zod 스키마로 선언하고, @t3-oss/env-nextjs가 이를 검증한다. 문자열을 그냥 process.env.X로 읽는 게 아니라, "이 값은 sk_로 시작해야 한다" 같은 규칙까지 코드에 박는다.

// packages/auth/keys.ts — 인증 패키지의 env 계약서
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";

export const keys = () =>
  createEnv({
    // 키가 없어도 앱이 죽지 않게 검증 건너뛰기 스위치
    skipValidation: process.env.SKIP_ENV_VALIDATION === "true",
    server: {
      // 서버 전용 비밀키 — 반드시 sk_ 로 시작(optional=없어도 됨)
      CLERK_SECRET_KEY: z.string().startsWith("sk_").optional(),
    },
    client: {
      // NEXT_PUBLIC_ 접두사 = 브라우저에 노출되는 공개키(pk_)
      NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().startsWith("pk_").optional(),
    },
    runtimeEnv: { /* 실제 process.env 매핑 */ },
  });
비유

keys.ts는 각 부품에 붙은 "전원 규격 라벨"이다. "이 기기는 220V, 둥근 2핀 플러그"처럼 필요한 전기(환경변수)의 모양을 명시해 둔다. 규격이 안 맞는 플러그(오타 난 키)를 꽂으려 하면 빌드 단계에서 즉시 거부당한다 — 배포 후 런타임에 터지는 대신.

핵심 패턴 ② — 우아한 성능 저하 (옵셔널 체이닝)

모든 프로바이더 클라이언트는 키가 없으면 null이 되고, 호출은 옵셔널 체이닝(?.)으로 감싼다. 그래서 Stripe 키를 안 넣어도 결제 기능만 조용히 꺼질 뿐, 앱 전체는 멀쩡히 돈다.

// 키가 있으면 Stripe 인스턴스, 없으면 undefined
export const stripe = env.STRIPE_SECRET_KEY
  ? new Stripe(env.STRIPE_SECRET_KEY)
  : undefined;

// 호출부: stripe가 없으면 그냥 아무 일도 안 일어남(에러 X)
const prices = await stripe?.prices.list();
왜 좋은가
"전부 아니면 전무"가 아니라 "켜진 것만 작동"

초보자가 20개 서비스 키를 다 발급받아야 앱이 뜨는 지옥을 피한다. DB 하나만 연결하면 일단 실행되고, 결제가 필요해지면 그때 Stripe 키만 추가하면 된다. 학습·프로토타이핑 단계에서 특히 강력하다.

핵심 패턴 ③ — 서버 컴포넌트 우선 (Server Components First)

Next.js App Router 규칙을 그대로 따른다. page.tsx·layout.tsx는 항상 서버 컴포넌트라, DB·비밀키·서버 전용 API를 브라우저로 내보내지 않고 직접 다룰 수 있다. 버튼 클릭 같은 상호작용이 필요한 부분만 'use client'를 붙인 별도 파일로 분리한다.

용어
서버 컴포넌트(RSC) vs 클라이언트 컴포넌트
서버 컴포넌트는 서버에서만 실행돼 HTML을 만들어 보내는 컴포넌트다. DB 조회·비밀키 사용이 안전하고, 자바스크립트를 브라우저로 안 보내 화면이 가볍다. 클라이언트 컴포넌트('use client' 표시)는 브라우저에서 실행돼 클릭·입력 같은 상호작용을 담당한다. next-forge는 "기본은 서버, 필요할 때만 클라이언트"를 규칙으로 삼는다.

핵심 패턴 ④ — Turborepo 파이프라인 (캐시 + 의존성 순서)

turbo.json이 "무엇을 어떤 순서로, 무엇을 캐시하며 돌릴지"를 정의한다. 예컨대 build는 의존 패키지의 build가 먼저 끝나야(^build) 하고, test도 통과해야 실행된다. 한 번 돌린 결과는 캐시돼, 안 바뀐 패키지는 다시 빌드하지 않는다 — 모노레포가 커져도 빌드가 느려지지 않는 비결이다.

// turbo.json (요약)
{
  "tasks": {
    "build": {
      "dependsOn": ["^build", "test"], // 의존성 build + 자기 test 후
      "outputs": [".next/**", "!.next/cache/**"]  // 캐시할 산출물
    },
    "dev": { "cache": false, "persistent": true }  // dev는 캐시 X, 계속 실행
  }
}

핵심 패턴 ⑤ — init CLI (복제 → env 세팅 → ORM → git)

npx next-forge@latest init의 속을 열어 보면 의외로 담백하다. commander로 명령을 파싱하고 @clack/prompts로 예쁜 대화형 질문을 던진 뒤, 실제 복제는 create-next-app의 --example에 next-forge 저장소 URL을 넘겨 처리한다. 그 후 패키지매니저 설정 보정 → .env 파일 생성 → 의존성 설치 → Prisma 빌드 → git 초기화를 순서대로 밟는다.

npx next-forge@latest init │ ├─ 1. 프로젝트 이름 · 패키지매니저 질문 (@clack/prompts) ├─ 2. create-next-app --example <next-forge repo> → 저장소 통째 복제 ├─ 3. (bun이 아니면) 워크스페이스·packageManager 필드 보정 ├─ 4. 각 앱/패키지의 .env.example → .env.local 복사 ├─ 5. 의존성 설치 (nypm) ├─ 6. @repo/database 빌드 (Prisma generate) └─ 7. git init + 첫 커밋 ✨

흥미로운 건 update 명령도 있다는 점이다. 특정 버전 사이의 파일 변경분을 가져와 이미 만든 프로젝트를 최신 next-forge 구조로 따라잡게 돕는다. "복제해서 소유"의 약점(원본이 발전해도 내 프로젝트는 낡음)을 보완하는 장치다.

5디렉토리 구조 해부

폴더만 봐도 "무엇이 배포 단위이고 무엇이 부품인지" 읽힌다
next-forge/ ├─ apps/ # 배포 가능한 앱들(각각 독립 Vercel 프로젝트) │ ├─ app/ # 본 앱 (port 3000) — 인증·DB 붙은 SaaS 본체 │ ├─ web/ # 마케팅 사이트 (3001) — CMS·SEO·i18n │ ├─ api/ # API 서버 (3002) — Stripe 웹훅·크론 수신 │ ├─ email/ # 이메일 템플릿 미리보기 (3003) │ ├─ docs/ # 문서 (3004) — Mintlify(.mdx) │ ├─ studio/ # Prisma Studio (3005) — DB GUI │ └─ storybook/ # 컴포넌트 작업실 (6006) │ ├─ packages/ # 앱들이 공유하는 부품 (@repo/*) │ ├─ auth/ # Clerk 인증 │ ├─ database/ # Prisma + Neon (prisma/schema.prisma) │ ├─ payments/ # Stripe │ ├─ design-system/ # shadcn/ui 컴포넌트 53종 + 다크모드 │ ├─ security/ observability/ analytics/ … # 나머지 기능 패키지 │ ├─ next-config/ # 공용 next.config │ └─ typescript-config/ # 공용 tsconfig(모두 상속) │ ├─ skills/next-forge/ # AI 에이전트용 SKILL.md(레포 사용법을 AI에 주입) ├─ scripts/ # init·update CLI 소스(index.ts 등) ├─ turbo.json # Turborepo 파이프라인 정의 ├─ biome.jsonc # Ultracite/Biome 린트·포맷 설정 ├─ package.json # 루트 워크스페이스(apps/*, packages/*) └─ bun.lock # Bun 잠금 파일

패키지 하나의 해부 — @repo/auth 예시

패키지는 대개 세 조각이면 충분하다. 기능을 내보내는 index.ts(x), env를 검증하는 keys.ts, 정체를 밝히는 package.json. 이 패턴이 20개 패키지 전체에 반복되므로 하나만 이해하면 나머지는 자동으로 읽힌다.

packages/auth/
├─ package.json      # name: "@repo/auth", deps: @clerk/nextjs …
├─ keys.ts           # CLERK_SECRET_KEY 등 env를 Zod로 검증
├─ index.ts          # auth(), currentUser() 등 기능 export
├─ client.ts         # 'use client' — 브라우저용 훅/컴포넌트
└─ components/        # 로그인 버튼 등 UI
용어
워크스페이스 · workspace:* · @repo/* 별칭
워크스페이스(workspace)는 한 저장소 안의 여러 패키지를 서로 로컬에서 직접 참조하게 묶는 기능이다. 앱이 @repo/auth를 import하면 npm에서 받아오는 게 아니라 옆 폴더의 소스를 바로 쓴다. package.json"@repo/auth": "workspace:*"라 적으면 "이건 워크스페이스 내부 패키지"라는 뜻. 그래서 패키지를 고치면 앱에 즉시 반영된다.

6학습 포인트 — 기술별 배울 것

이 레포를 "교재"로 삼았을 때 뽑아낼 수 있는 것들

① 모노레포 설계 (Turborepo + Bun 워크스페이스)

여러 앱이 공용 코드를 어떻게 나눠 갖는지, 순환 참조 없이 의존성을 어떻게 계층화하는지 배운다. turbo.jsondependsOn·outputs를 읽으며 "빌드 캐시"가 실제로 어떻게 작동하는지 감을 잡을 수 있다.

실습 아이디어: packages/@repo/utils를 새로 만들어 앱 두 곳에서 import해 보기. 그 후 turbo run build를 두 번 돌려 "두 번째는 캐시로 즉시 끝남"을 눈으로 확인.

② 타입세이프 환경변수 (t3-env + Zod)

실무에서 "키 오타 하나로 프로덕션이 죽는" 사고를 구조적으로 막는 법. keys.ts를 여러 개 열어 보며 server / client / runtimeEnv 3분할과 NEXT_PUBLIC_ 접두사의 의미를 익힌다.

실습 아이디어: 새 패키지에 keys.ts를 만들고, 일부러 규칙에 안 맞는 값을 넣어 빌드가 막히는 걸 확인.

③ 프로바이더 캡슐화 (교체 가능한 아키텍처)

왜 Clerk를 앱 곳곳에서 직접 부르지 않고 @repo/auth로 한 번 감쌌는지 이해하면, "의존성 역전"과 "결합도 낮추기"를 실물로 체득한다. 이게 나중에 프로바이더를 갈아끼울 수 있게 하는 핵심이다.

실습 아이디어: @repo/analytics가 PostHog를 어떻게 감쌌는지 읽고, 호출부가 프로바이더 이름을 전혀 모른다는 점을 확인.

④ 서버 컴포넌트 / 서버 액션 (Next.js App Router)

app/ 안에서 서버 컴포넌트가 DB를 직접 조회하고, 폼 제출을 서버 액션으로 처리하는 최신 패턴을 실제 코드로 본다. "언제 'use client'를 붙여야 하는가"의 감을 잡는 데 최고의 교재다.

⑤ 디자인 시스템 중앙화 (shadcn/ui)

버튼·다이얼로그 같은 UI를 앱마다 만들지 않고 @repo/design-system 한 곳에 모아 모든 앱이 같은 룩앤필을 공유하는 법. components.json(new-york 스타일, neutral 베이스, lucide 아이콘)을 읽으며 shadcn 구성을 익힌다.

실습 아이디어: npx shadcn@latest add [컴포넌트] -c packages/design-system로 새 컴포넌트를 추가하고 두 앱에서 동시에 써 보기.

⑥ 서버리스 DB + ORM (Prisma + Neon)

schema.prisma로 모델을 정의하고 bun run migrate(format→generate→push)로 DB에 반영하는 흐름. 서버리스 환경에서 connection pooling을 어댑터(@prisma/adapter-neon)로 어떻게 푸는지도 볼 수 있다.

7시스템 요구사항 & 배포

노트북 한 대면 충분하다 — 무거운 건 외부 서비스가 대신 진다

next-forge는 특별한 하드웨어가 필요 없다. 계산·저장·분석 같은 무거운 일은 전부 외부 서비스(Neon·Vercel·Sentry…)가 클라우드에서 처리하므로, 개발자 컴퓨터는 코드를 편집하고 개발 서버를 띄울 정도면 된다.

항목요구사항메모
Node.js20+ 권장 (engines는 18+)런타임 기반
패키지매니저Bun 권장 (npm/yarn/pnpm 가능)init에서 선택 가능
데이터베이스PostgreSQL (Neon 권장)DATABASE_URL만 필수
Stripe CLI로컬 웹훅 테스트용결제 개발 시
Mintlify CLI문서 앱 로컬 실행용docs 작업 시
메모리/디스크일반 개발용 노트북 수준모노레포라 node_modules는 다소 큼
주의
모노레포 첫 설치는 무겁게 느껴질 수 있다

앱 7개 + 패키지 20개가 각자 의존성을 가지므로 install과 첫 build는 시간이 걸린다. 대신 Turborepo 캐시 덕분에 두 번째부터는 빠르다. 또한 필수는 DB뿐이라, 처음엔 나머지 키를 비워 두고 가볍게 시작하는 걸 권한다.

배포 — 앱마다 별도 Vercel 프로젝트

배포의 핵심 개념은 "앱 하나 = Vercel 프로젝트 하나"다. app·web·api를 각각 별도 프로젝트로 만들고, 각 프로젝트의 루트 디렉토리를 apps/app·apps/web·apps/api로 지정한다. 환경변수는 프로젝트별로 넣거나 Vercel의 팀 공용 환경변수를 쓴다. 그러면 app.내도메인.com, www.내도메인.com, api.내도메인.com처럼 서브도메인으로 나뉜 실서비스가 된다.

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

난이도별로 — 손이 기억하게 만드는 순서
실습 1 · 난이도 ★☆☆☆☆

프로젝트 생성하고 개발 서버 띄우기

npx next-forge@latest init으로 새 프로젝트를 만들고, packages/database/.env에 Neon에서 만든 DATABASE_URL만 넣은 뒤 bun run migratebun run dev. 브라우저로 3000·3001 포트를 열어 본 앱과 마케팅 사이트가 동시에 뜨는 걸 확인한다.

배우는 것: 모노레포가 여러 앱을 한 번에 실행하는 감각, "DB만 있으면 돈다"는 우아한 저하.

실습 2 · 난이도 ★★☆☆☆

마케팅 카피 바꾸고 shadcn 컴포넌트 추가

apps/web의 히어로 문구를 내 서비스 이름으로 바꾸고, npx shadcn@latest add badge -c packages/design-system로 Badge 컴포넌트를 추가해 appweb 양쪽에서 import해 본다.

배우는 것: 디자인 시스템 중앙화 — 한 곳에 추가하면 모든 앱이 공유한다.

실습 3 · 난이도 ★★★☆☆

Prisma 모델 추가하고 마이그레이션

packages/database/prisma/schema.prismaPost 모델(제목·본문)을 추가하고 bun run migrate를 실행한다. 그 후 studio 앱(apps/studio, 포트 3005)을 띄워 표에서 직접 행을 넣어 본다.

배우는 것: 스키마-우선 DB 워크플로우, generate/push 흐름, Prisma Studio 활용.

실습 4 · 난이도 ★★★★☆

Clerk 인증 켜고 라우트 보호하기

Clerk에서 키를 발급받아 apps/app/.env.local에 넣고(pk_·sk_), 로그인해야만 볼 수 있는 페이지를 하나 만든다. 키를 넣기 전과 후의 동작 차이(기능 꺼짐 → 켜짐)를 관찰한다.

배우는 것: env로 기능을 켜는 우아한 저하의 실제, 서버 컴포넌트에서의 인증 처리.

실습 5 · 난이도 ★★★★★

새 @repo/* 패키지 만들기 (또는 프로바이더 교체)

packages/@repo/pdf 같은 새 패키지를 만들어 index.ts+keys.ts+package.json 3종 세트를 갖추고 앱에서 import한다. 여력이 되면 @repo/analytics의 프로바이더를 PostHog에서 다른 도구로 호출부를 건드리지 않고 교체해 본다.

배우는 것: 패키지 아키텍처의 확장·교체 — next-forge 설계 철학의 최종 시험.

9관련 기술 심화 로드맵 (주차별)

next-forge를 온전히 소화하기 위한 6주 코스
주차주제핵심 목표
1주차Next.js App Router · RSC서버/클라이언트 컴포넌트 경계, 서버 액션, 라우팅. apps/app 코드 읽기
2주차모노레포 · Turborepo · Bun워크스페이스 개념, turbo.json 파이프라인, 빌드 캐시 실습
3주차타입세이프 env · 패키지 캡슐화t3-env+Zod, keys.ts 패턴, 프로바이더 감싸기(결합도)
4주차인증 · DB · 결제Clerk 세션, Prisma+Neon 마이그레이션, Stripe 웹훅(apps/api)
5주차관측 · 보안 · 분석Sentry 에러추적, Arcjet 봇차단·rate-limit, PostHog 이벤트
6주차배포 · 프로바이더 교체앱별 Vercel 프로젝트 배포, 공급자 마이그레이션, update 명령
학습 순서 팁

next-forge는 "큰 그림 → 부품" 순서로 접근하는 게 좋다. 처음부터 20개 패키지를 다 파려 하지 말고, 먼저 apps/app 하나가 어떻게 도는지만 따라가라. 그다음 그 앱이 import하는 패키지를 하나씩 열어 보면, "왜 이렇게 나눴는가"가 자연스럽게 이해된다. tree(구조)를 먼저, leaf(구현)를 나중에.

10핵심 키워드 사전

이 문서에 나온 용어를 한자리에
키워드
Turborepo모노레포의 build/test/dev를 캐시하고 병렬 실행하는 오케스트레이터
모노레포(monorepo)여러 앱·라이브러리를 한 저장소에서 함께 관리하는 방식
워크스페이스 / workspace:*저장소 내부 패키지끼리 로컬에서 직접 참조하게 묶는 기능
@repo/*next-forge 내부 공유 패키지의 이름 접두사(예: @repo/auth)
App RouterNext.js의 최신 라우팅 방식(app/ 폴더 기반)
RSC(서버 컴포넌트)서버에서만 실행돼 HTML을 보내는 컴포넌트 — DB·비밀키 안전
'use client'이 파일은 브라우저에서 실행되는 클라이언트 컴포넌트라는 표시
t3-env + Zod환경변수를 스키마로 검증하고 타입을 부여하는 조합
graceful degradation키가 없으면 기능만 꺼지고 앱은 계속 도는 "우아한 성능 저하"
fork-and-own라이브러리로 설치하지 않고 소스를 복제해 내가 소유·수정하는 방식
Prisma / Neon타입세이프 ORM / 서버리스 PostgreSQL
Clerk · Stripe · Resend기본 인증 · 결제 · 이메일 프로바이더
Arcjet봇 차단·rate-limit·보안 헤더를 다루는 앱 보안 서비스
shadcn/ui복사해서 소유하는 컴포넌트 방식의 UI 라이브러리(Radix 기반)
Ultracite / BiomeESLint+Prettier를 대체하는 Rust 기반 초고속 린트·포맷
Mintlify · BaseHub · svix문서 사이트 · 타입세이프 CMS · 웹훅 발송 서비스

11참고 링크

더 파고들 곳