TRENDSHIFT 딥다이브 · 일간 #8 · 2026-06-18

freeCodeCamp 딥다이브
— 45만 ★ '실서비스 풀스택 모노레포'를 통째로 뜯어보기

freeCodeCamp는 흔히 '무료 코딩 강의 사이트'로만 알려져 있지만, 이 저장소의 진짜 가치는 수백만 명이 매일 접속하는 실서비스를 어떻게 하나의 거대한 모노레포로 구성·운영하는가에 있다. 프론트(Gatsby·React) + 백엔드(Fastify·MongoDB) + 마크다운 기반 커리큘럼 빌드 파이프라인 + i18n·테스트·Dockerpnpm 워크스페이스 + Turborepo로 한 지붕 아래 묶여 있다. 이 문서는 README가 아니라 package.json·Dockerfile·소스 트리를 직접 분석해, "거대 OSS를 실제로 어떻게 굴리는가"를 코드베이스 관점에서 해부한다. (저장소: freeCodeCamp/freeCodeCamp · TypeScript 모노레포 · ★449k · 라이선스 BSD-3-Clause(소프트웨어))
목차
  1. 프로젝트 한줄 요약
  2. 왜 주목받는가
  3. 기술 스택 전체 지도
  4. 아키텍처 심화 분석
  5. 디렉토리 구조 해부
  6. 학습 포인트 (기술별)
  7. 하드웨어 / 시스템 요구사항
  8. 직접 해볼 수 있는 실습 과제
  9. 관련 기술 심화 학습 로드맵
  10. 핵심 키워드 사전
  11. 참고 링크

1프로젝트 한줄 요약

한 문장으로 이 프로젝트가 뭘 하는지부터.

freeCodeCamp = "수백만 명이 쓰는 무료 코딩 학습 플랫폼의 전체 소스 + 수천 개 강의를, 하나의 모노레포에 담아 누구나 기여하게 만든 비영리 오픈소스." 단순히 강의를 보여주는 사이트가 아니다. 인터랙티브 코드 에디터, 진도·인증서 관리, 결제(기부), 다국어, 시험 환경까지 갖춘 완결된 풀스택 웹 서비스이고, 그 코드 전부가 공개돼 있다.

🏗️ 한 줄 비유

"강의 영상 하나"가 아니라, "학교 건물 전체 + 교실 + 행정실 + 수천 권의 교재"를 통째로 공개한 것

보통 '코딩 강의'라고 하면 영상이나 글 한 편을 떠올린다. freeCodeCamp는 다르다. 학생이 코드를 직접 짜는 교실(클라이언트), 진도와 성적을 기록하는 행정실(API+DB), 수천 개의 교재(커리큘럼), 외국어 번역실(i18n), 시험장(exam-environment)이 한 캠퍼스 안에 다 들어 있다.

그리고 그 캠퍼스의 설계도(소스코드) 전체가 공개돼 있어, 전 세계 자원봉사자 누구나 교재를 고치거나 새 교실을 지을 수 있다. "실제로 돌아가는 대형 서비스를 통째로 들여다보는 교본"이라는 게 이 저장소의 진짜 매력이다.

용어
모노레포 (Monorepo)
여러 개의 독립된 프로젝트(여기선 client·api·curriculum 등)를 하나의 git 저장소에 모아 관리하는 방식. 폴더마다 별도 저장소를 두는 '폴리레포'와 반대다. 공통 코드를 공유하기 쉽고, 한 번의 PR로 프론트·백을 같이 고칠 수 있다.
용어
워크스페이스 (Workspace)
모노레포 안의 개별 패키지(하위 프로젝트). 각자 자기 package.json을 갖는다. freeCodeCamp는 pnpm-workspace.yamlapi·client·curriculum·e2e·shared·tools/*·packages/*를 워크스페이스로 등록한다.
용어
비영리 / 501(c)(3)
freeCodeCamp.org는 미국의 기부로 운영되는 비영리 자선단체(501(c)(3))다. 그래서 코드 안에 Stripe·PayPal·Patreon 같은 기부(donate) 결제 연동이 들어 있다 — 상업적 과금이 아니라 후원을 받는 구조다.

규모 감각을 잠깐 — 이 저장소는 git에 약 1만 9천 개 이상의 파일을 담고 있고, README가 밝히듯 freeCodeCamp 커뮤니티는 이미 10만 명 이상이 첫 개발자 일자리를 얻도록 도왔다. 코드 자체도 GitHub에서 가장 많은 별(★449k)과 포크(45k)를 가진 저장소 중 하나다. 즉 "학습 자료"인 동시에 "초대형 오픈소스 협업의 표본"이다.

2왜 주목받는가

TrendShift 일간 8위 — 늘 상위권에 머무는 '스테디셀러'의 이유.

freeCodeCamp는 반짝 트렌드가 아니라 수년째 GitHub 최상위권을 지키는 스테디셀러다. 2014년 시작해 지금도 매일 커밋이 쌓인다(이 분석 시점 기준 마지막 푸시도 하루 전). 왜 개발자들이 계속 이 저장소로 모이는지를 다섯으로 정리한다.

① "기여하기 가장 좋은 OSS" — first-timers-only 친화

README 최상단에 first-timers-only friendly 배지가 붙어 있다. 오픈소스 기여가 처음인 사람도 커리큘럼의 오타 수정·번역·새 챌린지 추가처럼 진입 장벽 낮은 일부터 시작할 수 있게 설계됐다. 실제 기여 가이드(contribute.freecodecamp.org)가 별도 사이트로 잘 정리돼 있다.

② 학습 자료이자, 실서비스 코드 그 자체

대부분의 '학습용 레포'는 장난감 예제다. freeCodeCamp는 반대로 진짜 수백만 명이 쓰는 프로덕션 서비스의 코드다. 인증(Auth0), 결제(Stripe), 모니터링(Sentry), 기능 플래그(GrowthBook), 검색(Algolia) 같은 실무에서 진짜 쓰는 도구들의 통합 사례를 한곳에서 볼 수 있다.

③ 풀스택 모노레포의 모범 답안

프론트(Gatsby/React)·백(Fastify)·콘텐츠(마크다운 커리큘럼)·테스트(Playwright)가 pnpm 워크스페이스 + Turborepo로 깔끔하게 분리·연결돼 있다. "여러 팀이 하나의 큰 코드베이스를 어떻게 나눠 갖고 빌드를 캐싱하는가"를 배우기에 더없이 좋은 표본이다.

④ 콘텐츠를 '코드처럼' 다루는 설계

수천 개의 강의가 전부 마크다운 파일 + 프론트매터로 저장되고, 빌드 파이프라인이 이를 curriculum.json으로 변환한다. "교육 콘텐츠를 Git으로 버전 관리하고, PR로 리뷰하고, 테스트로 검증한다"는 발상은 그 자체로 배울 거리다(이른바 Docs/Content-as-Code).

⑤ 거대한 다국어·접근성 운영

플랫폼과 커리큘럼이 수십 개 언어로 번역된다. i18next(클라이언트), Crowdin 연동(tools/crowdin), i18n-curriculum 서브모듈까지 — 국제화(i18n)를 대규모로 굴리는 실전 구조를 통째로 보여준다.

구분흔한 '강의 사이트'freeCodeCamp
코드 공개비공개(상용)전체 공개(BSD-3 + 콘텐츠 라이선스)
실행 환경영상 재생브라우저 안에서 코드 작성·자동 채점
콘텐츠 관리CMS 입력마크다운 + Git + PR 리뷰 + 테스트
수익 모델구독·광고기부(비영리)
학습 관점의 강점
"읽을 수 있는 대형 코드베이스"라는 희소가치

실무에서 다루는 대형 서비스는 거의 다 비공개다. freeCodeCamp는 그 규모의 코드를 합법적으로, 깔끔한 구조로, 한국어 커뮤니티까지 갖춘 채 공개해 준다. "큰 프로젝트는 폴더를 어떻게 나누고, 빌드를 어떻게 엮고, 인증·결제·테스트를 어디에 두는가"를 직접 눈으로 확인할 수 있다는 게 핵심 가치다.

냉정하게 보기
규모가 곧 진입장벽 — "처음부터 다 돌리려" 하지 말 것

1만 9천 개 파일, 7~8개 워크스페이스, MongoDB·Auth0·Algolia 등 외부 의존성이 많아 로컬에서 전체를 띄우는 것 자체가 만만치 않다. 초보자가 "일단 전부 실행"부터 시도하면 환경 설정에서 좌절하기 쉽다. 이 문서의 권장 경로는 ① 한 워크스페이스(예: curriculum)만 골라 구조를 읽고 → ② 작은 기여(오타·번역)부터 → ③ Docker로 단계적 셋업이다. 자세한 셋업은 7번 섹션.

3기술 스택 전체 지도

루트·각 워크스페이스의 package.json에서 직접 확인한 실제 구성.

freeCodeCamp는 처음부터 끝까지 TypeScript/JavaScript 기반이다. 한 언어로 프론트·백·도구·테스트를 모두 작성해, 공통 코드(packages/shared)를 양쪽에서 재사용한다. 레이어별로 끊어 보자.

ⓐ 모노레포 기반 — 빌드·패키지 관리

구성요소버전/도구역할
pnpm10.x (workspace)패키지 매니저. pnpm-workspace.yaml로 모든 하위 패키지를 묶고, 디스크 절약형 설치.
Turborepo2.8.x모노레포 빌드 오케스트레이터. turbo build 한 줄로 워크스페이스 의존 순서대로 빌드·캐싱.
Node.js≥24 (.nvmrc=24)런타임. 전 워크스페이스가 engines.node ≥24로 통일.
TypeScript5.9.x전체 공통 언어. 루트 tsconfig-base.json을 각 워크스페이스가 상속.

ⓑ 프론트엔드 — client/ (Gatsby + React)

구성요소버전역할
Gatsby5.16React 기반 정적 사이트 생성기(SSG). 빌드 시 페이지를 미리 만들어 빠르게 서빙. 마크다운 강의를 gatsby-transformer-remark로 읽어 페이지화.
React18.3UI 라이브러리. 강의 화면·에디터·진도판 컴포넌트.
Redux Toolkit + Redux-Saga2.11 / 1.x전역 상태 + 비동기 흐름(saga). 로그인·진도 저장·기부 같은 부수효과를 saga로 처리.
Monaco Editor0.52VS Code의 그 에디터. 브라우저 안에서 코드를 작성하는 학습 환경의 심장.
i18next + react-i18next25.x다국어. UI 문자열을 언어별로 교체.
Algolia (instantsearch)4.x강의·뉴스 검색 인덱스. 빠른 검색창 제공.
Tailwind CSS + PostCSS유틸리티 기반 스타일링(tailwind.config.js).
@freecodecamp/ui6.0자체 디자인 시스템(별도 패키지로 분리된 공용 컴포넌트).

ⓒ 백엔드 — api/ (Fastify + MongoDB)

구성요소버전역할
Fastify5.8고성능 Node 웹 프레임워크(Express의 빠른 대안). 플러그인 구조가 핵심.
TypeBox + Ajv스키마 우선 검증. 타입과 런타임 검증을 한 정의로(@fastify/type-provider-typebox).
Prisma6.19ORM. schema.prismaprovider="mongodb" — 즉 MongoDB를 Prisma로 다룬다.
MongoDB8.2 (Docker)주 데이터베이스(NoSQL). 사용자·진도·인증서를 도큐먼트로 저장.
@fastify/oauth2 + jsonwebtoken인증. Auth0 OAuth2 로그인 + JWT 쿠키 세션.
@fastify/csrf-protection, cookie보안 플러그인(CSRF 토큰, 서명 쿠키).
Stripe16.x기부 결제. (+ PayPal·Patreon 연동 env)
Sentry, Pino에러 추적 + 구조적 로깅.
Nodemailer6.x이메일 발송(로컬은 Mailpit로 캡처).

ⓓ 콘텐츠 & 도구 — curriculum/, tools/, packages/

구성요소역할
curriculum/수천 개 강의(마크다운+프론트매터) + 빌드 파이프라인(build-curriculum.ts)이 curriculum.json 생성.
packages/shared프론트·백이 함께 쓰는 설정·유틸(예: config/challenge-types). 모노레포의 '공용 부품함'.
tools/challenge-parser마크다운 챌린지를 파싱하는 커스텀 파서(설명/힌트/테스트 블록 분해).
tools/challenge-helper-scripts새 챌린지·스텝·퀴즈를 만드는 CLI 생성기 모음.
tools/crowdin, scripts/sync-i18n번역 플랫폼 Crowdin 연동·동기화.

ⓔ 테스트 & 인프라

구성요소역할
Vitest단위·통합 테스트(client/api/curriculum 각각). Jest 호환의 빠른 러너.
Playwright (e2e/)브라우저 E2E 테스트. 실제 로그인·강의 풀이 흐름을 자동 검증.
Docker Compose로컬 인프라: MongoDB 8.2(레플리카셋) + Mailpit(메일 캐처).
Dev Container.devcontainer로 VS Code/Codespaces에서 즉시 개발 환경 구성.
ESLint 9 + Prettier + Stylelint + Husky코드 품질·포맷·커밋 훅. lint-staged로 커밋 전 자동 검사.
Renovate, knip의존성 자동 업데이트 + 미사용 코드/파일 탐지.
용어
SSG (Static Site Generation, 정적 사이트 생성)
방문 시점에 서버가 페이지를 만드는 대신, 빌드할 때 미리 HTML을 다 만들어 두는 방식. Gatsby가 대표 도구. 강의처럼 내용이 자주 안 바뀌는 페이지에 적합 — 빠르고, 서버 부하가 적다.
용어
ORM · Prisma
ORM(Object-Relational Mapping)은 코드의 객체와 DB를 이어 주는 다리. SQL을 직접 쓰지 않고 타입 안전하게 DB를 다룬다. freeCodeCamp는 Prisma의 MongoDB 커넥터를 써, NoSQL인 MongoDB도 타입 정의(schema.prisma)로 안전하게 접근한다.
용어
Fastify 플러그인
Fastify의 핵심 철학 — 모든 기능을 '플러그인'이라는 캡슐로 등록한다. 인증·CORS·쿠키·에러처리·DB 연결이 각각 독립 플러그인(plugins/ 폴더)이고, app.ts가 이들을 순서대로 조립한다. 기능을 켜고 끄거나 테스트하기 쉽다.

4아키텍처 심화 분석

소스가 어떻게 짜여 한 서비스가 되는가 — 모노레포 구조 + 두 갈래 흐름.

freeCodeCamp의 아키텍처는 세 가지 큰 그림으로 이해하면 된다 — ① 모노레포가 어떻게 묶여 빌드되는가, ② 사용자가 강의를 풀 때 요청이 어떻게 흐르는가, ③ 마크다운 강의가 어떻게 화면이 되는가. 차례로 본다.

그림 1 — 모노레포 전체 구조

┌────────────────── freeCodeCamp/freeCodeCamp (1개의 git 저장소) ──────────────────┐ │ │ │ pnpm-workspace.yaml ──→ 아래 워크스페이스들을 하나로 묶음 │ │ turbo.json ──→ 빌드 순서·캐싱 규칙(의존성 그래프) │ │ │ │ ┌────────────┐ ┌────────────┐ ┌───────────────┐ ┌──────────┐ │ │ │ client/ │ │ api/ │ │ curriculum/ │ │ e2e/ │ │ │ │ Gatsby+ │ │ Fastify+ │ │ 마크다운 강의 │ │Playwright│ │ │ │ React 18 │ │ MongoDB │ │ +빌드 스크립트│ │ E2E │ │ │ └─────┬──────┘ └─────┬──────┘ └──────┬────────┘ └──────────┘ │ │ │ │ │ │ │ └────────┬───────┴────────┬────────┘ │ │ ▼ ▼ │ │ ┌───────────────┐ ┌──────────────────────────────┐ │ │ │ packages/ │ │ tools/ │ │ │ │ shared (공용 │ │ challenge-parser / -helpers │ │ │ │ 설정·유틸) │ │ crowdin / daily-challenges │ │ │ │ ui / eslint │ │ scripts/seed (데모 데이터) │ │ │ └───────────────┘ └──────────────────────────────┘ │ │ │ │ docker/ : MongoDB 8.2(레플리카셋) + Mailpit | .devcontainer/ : 개발 컨테이너 │ └───────────────────────────────────────────────────────────────────────────────────┘ turbo build ──→ shared 빌드 → curriculum.json 생성 → api·client 빌드 (의존 순서)

핵심은 turbo.json의 의존 그래프다. 예컨대 buildsetup에 의존하고 setup^build(상위 의존 패키지의 build)에 의존한다. 그래서 shared가 먼저 빌드되고, 그걸 쓰는 api·client가 나중에 빌드되도록 순서가 자동으로 정렬된다. 한 번 빌드한 결과는 캐싱돼, 안 바뀐 워크스페이스는 다시 빌드하지 않는다.

그림 2 — 강의를 풀고 제출할 때의 요청 흐름

[학습자 브라우저] │ Monaco 에디터에서 코드 작성 → 브라우저 안에서 테스트 자동 실행(채점) │ 통과하면 "제출" → POST /challenge-completed ▼ ┌────────────────────── api/ (Fastify 서버) ──────────────────────┐ │ app.ts 가 플러그인들을 순서대로 조립: │ │ │ │ cors → cookies → csrf → auth(Auth0/JWT) → bouncer(인가) → ... │ │ │ │ │ ▼ 요청이 보호 라우트로 들어옴 │ │ routes/protected/challenge.ts │ │ │ ① JWT 쿠키에서 사용자 식별 (auth 플러그인) │ │ │ ② TypeBox 스키마로 요청 본문 검증 (잘못되면 400) │ │ │ ③ 비즈니스 로직: 완료 챌린지 기록·포인트 계산 │ │ ▼ │ │ Prisma ──→ MongoDB (user 도큐먼트의 completedChallenges 갱신) │ └────────────────────────────────────────────────────────────────────┘ │ 응답(갱신된 진도) → 클라이언트 Redux 스토어 업데이트(saga) ▼ [화면 갱신: 다음 강의 잠금 해제 / 진도판 반영]

이 그림에서 배울 패턴은 라우트의 공개/보호 분리다. routes/public/(로그인·상태·기부 등 누구나)와 routes/protected/(진도·설정 등 로그인 필요)가 폴더로 나뉘고, auth·bouncer 플러그인이 보호 라우트 앞에서 "이 사람이 누구인지(인증)"와 "이 작업을 할 권한이 있는지(인가)"를 차례로 검사한다.

// api/src/app.ts — 플러그인 조립 순서(개념 요약)
await app.register(cors);
await app.register(cookies);
await app.register(auth);      // JWT 쿠키 → req.user 채움
await app.register(bouncer);   // 비로그인 차단(인가 게이트)
await app.register(csrf);
await app.register(prismaPlugin); // req.server.prisma 로 DB 접근
// 그리고 라우트 등록
await app.register(publicRoutes,    { prefix: '/' });
await app.register(protectedRoutes, { prefix: '/' });

그림 3 — 마크다운 강의 → 화면이 되는 빌드 파이프라인

freeCodeCamp에서 가장 독창적인 부분. 강의 하나하나가 코드가 아니라 구조화된 마크다운 파일이다. 실제 챌린지 파일은 이렇게 생겼다.

# curriculum/challenges/english/blocks/react/...md
---
id: 5a24c314108439a4d4036183
title: Use Advanced JavaScript in React Render Method
challengeType: 6
dashedName: use-advanced-javascript-in-react-render-method
---

# --description--      # 설명 (학습자에게 보여줄 본문)
... 마크다운 설명 ...

# --instructions--     # 지시문 (무엇을 하라)
... 할 일 ...

# --hints--            # 채점 테스트 (통과해야 완료)
```js
assert.strictEqual(Enzyme.mount(...).length, 1);
```
수천 개의 .md 강의 파일 (curriculum/challenges/english/...) │ │ ① challenge-parser : 프론트매터 + --description-- / --hints-- 블록 분해 ▼ 구조화된 챌린지 객체 (설명·지시문·채점 테스트·시드 코드 분리) │ │ ② build-curriculum.ts : 슈퍼블록→블록→챌린지 계층으로 조립·정렬·검증 ▼ curriculum/generated/curriculum.json ← 단일 빌드 산출물(거대한 JSON) │ ├──→ api/ 가 읽어서: 채점 기준·인증서 판정에 사용 └──→ client/(Gatsby) 가 읽어서: 강의 페이지를 정적 생성 │ ▼ 학습자 화면: 설명 + Monaco 에디터 + (브라우저에서) 테스트 채점

이 설계의 묘미 — 콘텐츠와 코드가 분리돼 있다. 강의를 고치는 사람은 마크다운만 건드리면 되고(번역가·교육자 친화), 플랫폼 개발자는 파서·빌더만 다루면 된다. 그리고 강의의 --hints-- 블록(채점 테스트)이 곧 콘텐츠의 일부라, "강의가 제대로 작동하는지"를 자동 테스트로 검증할 수 있다(test-content).

핵심 설계 패턴 정리

패턴어디서왜 중요한가
워크스페이스 분리pnpm-workspace + turbo프론트·백·콘텐츠를 독립 개발하되 공용 코드(shared)는 공유. 빌드 캐싱으로 속도 확보.
플러그인 아키텍처api/src/plugins/*인증·보안·DB를 캡슐로 분리. app.ts가 조립. 테스트·교체 용이.
스키마 우선 검증TypeBox + Ajv타입 정의 하나로 컴파일타임 타입 + 런타임 검증 동시 확보(잘못된 요청 차단).
Content-as-Codecurriculum/ + 파서/빌더교육 콘텐츠를 Git·PR·테스트로 관리. 콘텐츠/코드 책임 분리.
공개/보호 라우트 분리routes/public · protected인증이 필요한 엔드포인트를 폴더 단위로 격리 → 실수로 보호를 빠뜨릴 위험 감소.
용어
슈퍼블록 / 블록 / 챌린지 (Superblock / Block / Challenge)
커리큘럼의 3단 계층. 슈퍼블록=인증서 단위(예: 'JavaScript 알고리즘'), 블록=강의 묶음(한 챕터), 챌린지=개별 문제(마크다운 1개). build-superblock.ts·build-curriculum.ts가 이 계층을 조립한다.
용어
CSRF (Cross-Site Request Forgery)
사용자가 로그인된 틈을 노려, 악성 사이트가 사용자 몰래 요청을 보내는 공격. freeCodeCamp는 @fastify/csrf-protection 플러그인으로 요청마다 비밀 토큰을 확인해 이를 막는다. 인증(누구냐)과는 다른, '요청의 출처'를 지키는 방어다.

5디렉토리 구조 해부

저장소를 열었을 때 어느 폴더부터 봐야 하는가.

처음 열면 폴더가 많아 압도된다. 핵심만 추리면 네 개의 큰 워크스페이스(client·api·curriculum·e2e) + 두 개의 공용 묶음(packages·tools)이다. 나머지는 설정·인프라다.

freeCodeCamp/ ├── client/ ← 프론트엔드 (Gatsby + React 18) │ ├── src/ │ │ ├── components/ 공용 UI 컴포넌트 │ │ ├── templates/ ★ 강의 화면 템플릿 │ │ │ ├── Challenges/ classic·projects·exam·fill-in-the-blank ... │ │ │ └── Introduction/ 슈퍼블록 소개 페이지 │ │ ├── redux/ 전역 상태 + saga(로그인·진도·기부 부수효과) │ │ ├── pages/ 라우트 페이지 │ │ └── analytics/ GTM 등 분석 │ ├── gatsby-node.ts ★ 빌드 시 강의→페이지 생성 로직 │ └── gatsby-config.ts Gatsby 플러그인 설정 │ ├── api/ ← 백엔드 (Fastify + MongoDB) │ ├── src/ │ │ ├── app.ts ★ 플러그인·라우트 조립의 중심 │ │ ├── server.ts 서버 부팅·graceful shutdown │ │ ├── plugins/ ★ auth·csrf·cors·cookies·mailer·bouncer ... │ │ ├── routes/ │ │ │ ├── public/ 로그인·상태·기부·인증서(공개) │ │ │ └── protected/ 진도·설정·challenge 제출(로그인 필요) │ │ ├── db/ prisma 플러그인(DB 연결) │ │ ├── schemas/ TypeBox 요청/응답 스키마 │ │ └── exam-environment/ 시험 환경 전용 로직 │ └── prisma/ schema.prisma(MongoDB) + 시험용 스키마 │ ├── curriculum/ ← 콘텐츠(수천 개 강의) + 빌드 │ ├── challenges/english/ ★ 원본 강의(마크다운) │ │ ├── blocks/ 블록별 강의 묶음(react, workshop-*, lab-* ...) │ │ └── certifications/ 인증서 정의 │ ├── src/ build-curriculum.ts · build-superblock.ts 등 │ ├── structure/ 블록·슈퍼블록 구조 메타 │ └── i18n-curriculum/ 번역 커리큘럼(git 서브모듈) │ ├── e2e/ ← Playwright E2E 테스트(실제 흐름 검증) ├── packages/ ← 공용 패키지 │ ├── shared/ ★ 프론트·백 공용 설정·유틸 │ ├── eslint-config/ 공용 ESLint 규칙 │ └── challenge-builder / challenge-linter ├── tools/ ← 개발·콘텐츠 도구 │ ├── challenge-parser/ 마크다운 챌린지 파서 │ ├── challenge-helper-scripts/ 새 챌린지 생성 CLI │ ├── daily-challenges/ 일일 코딩 챌린지 │ ├── crowdin/ 번역 동기화 │ └── scripts/seed/ 데모 사용자·설문 시드 │ ├── docker/ ← docker-compose(MongoDB·Mailpit) + api Dockerfile ├── .devcontainer/ ← VS Code/Codespaces 개발 컨테이너 ├── pnpm-workspace.yaml 워크스페이스 정의(단일 진실원) ├── turbo.json 빌드 그래프·캐싱 └── sample.env 환경변수 견본(MongoDB·Auth0·Stripe·Algolia ...)
위치역할 / 언제 보나
api/src/app.ts백엔드 전체의 조립도. "이 서비스가 어떤 플러그인·라우트로 구성되는가"를 한눈에. 백엔드 공부의 출발점.
api/src/plugins/인증·보안·DB의 실제 구현. Fastify 플러그인 패턴을 배우기에 최적.
client/src/templates/Challenges/강의 유형별 화면(classic·projects·exam ...). 프론트가 강의를 어떻게 렌더링하는지.
curriculum/challenges/english/실제 강의 원본. 가장 기여하기 쉬운 곳(오타·번역·새 문제).
curriculum/src/build-curriculum.ts마크다운→curriculum.json 빌드의 심장. Content-as-Code의 핵심 로직.
packages/shared/프론트·백 공용 부품. "모노레포에서 코드를 어떻게 공유하나"의 답.

6학습 포인트 (기술별)

이 레포에서 실제로 무엇을 배울 수 있는가 — 기술별 + 실습 아이디어.

학습 포인트 ①

모노레포 운영 — pnpm 워크스페이스 + Turborepo

여러 프로젝트를 한 저장소에서 굴리는 실전 구조를 통째로 본다. pnpm-workspace.yaml로 패키지를 묶고, turbo.json의존 그래프로 빌드 순서를 자동 정렬·캐싱하는 방식이 핵심. "왜 shared가 먼저 빌드되어야 하는가"를 그래프로 이해하면 대형 프로젝트의 빌드가 보인다.

실습 아이디어: turbo build --dry-run으로 빌드 그래프를 출력해, 어떤 워크스페이스가 어떤 순서로 빌드되는지 그려 본다.

학습 포인트 ②

Fastify 플러그인 아키텍처 — 백엔드를 캡슐로 조립

api/src/plugins/의 auth·csrf·cors·bouncer·mailer를 읽으면, 기능을 독립 플러그인으로 쪼개 app.ts에서 순서대로 조립하는 패턴이 손에 잡힌다. Express의 미들웨어와 비교하면서 읽으면 "왜 Fastify가 구조적으로 깔끔한가"가 보인다.

실습 아이디어: plugins/auth.ts가 어떻게 req.user를 채우고, bouncer.ts가 비로그인 요청을 어디서 막는지 호출 순서를 따라가 본다.

학습 포인트 ③

Content-as-Code — 콘텐츠를 Git·테스트로 관리

강의를 마크다운+프론트매터로 두고, 파서·빌더로 curriculum.json을 만드는 파이프라인은 문서·블로그·교육 플랫폼을 만들 때 그대로 응용할 수 있는 패턴이다. 특히 채점 테스트(--hints--)가 콘텐츠에 들어 있어 자동 검증까지 된다는 점이 인상적이다.

실습 아이디어: 챌린지 마크다운 하나를 열어 --description--/--hints-- 구조를 파악하고, challenge-parser가 이를 어떻게 객체로 쪼개는지 추적.

학습 포인트 ④

스키마 우선 API — TypeBox로 타입+검증 한 방에

api/src/schemas/의 TypeBox 정의는 하나의 스키마에서 컴파일타임 타입과 런타임 검증을 동시에 얻는다. "타입과 검증을 따로 쓰다 어긋나는" 흔한 문제를 구조적으로 없애는 방법을 배운다.

실습 아이디어: 한 라우트의 요청 스키마를 찾아, 일부러 잘못된 본문을 보내면 Ajv가 어떤 에러를 내는지 확인.

학습 포인트 ⑤

Redux Toolkit + Saga로 비동기 흐름 다루기

로그인·진도 저장·기부 같은 부수효과(side effect)client/src/redux/*-saga에서 어떻게 선언적으로 다루는지 본다. "API 호출 → 성공/실패 → 상태 갱신"의 흐름을 saga로 분리하는 실전 패턴이다.

실습 아이디어: fetch-user-saga를 따라가, 앱이 처음 뜰 때(app-mount) 사용자 정보를 어떻게 불러와 스토어에 넣는지 추적.

학습 포인트 ⑥

대규모 i18n & E2E 테스트 운영

수십 개 언어를 Crowdin·i18next·서브모듈로 굴리는 국제화 구조와, Playwright로 실제 로그인·강의 풀이 흐름을 자동 검증하는 E2E 설계를 함께 볼 수 있다. "사용자 수가 많은 서비스는 품질을 어떻게 지키는가"의 답.

실습 아이디어: e2e/의 테스트 하나를 골라, 어떤 사용자 시나리오(예: 챌린지 제출)를 어떤 셀렉터로 검증하는지 읽어 본다.

7하드웨어 / 시스템 요구사항

로컬에서 띄우려면 무엇이 필요한가 — 솔직한 난이도와 권장 경로.

먼저 솔직하게 — freeCodeCamp 전체를 로컬에서 띄우는 건 가벼운 작업이 아니다. Node 24, pnpm 10, 그리고 Docker(MongoDB)가 필요하고, 빌드 단계에서 메모리도 꽤 먹는다(클라이언트 빌드는 --max-old-space-size=7168, 즉 약 7GB 힙을 잡는다). 공식 권장의 핵심을 정리한다.

항목요구/권장비고
Node.js≥24 (.nvmrc=24)nvm으로 버전 맞추기 권장.
pnpm≥10패키지 매니저(npm/yarn 아님).
Docker (+Compose)필수에 가까움MongoDB 8.2(레플리카셋) + Mailpit를 컨테이너로 띄움.
RAM최소 8GB, 16GB 권장클라이언트 빌드가 ~7GB 힙 사용. 4GB로는 빌드가 OOM 위험.
디스크수 GB+ 여유의존성(거대한 pnpm-lock.yaml) + 빌드 산출물.
OSmacOS / Linux / Windows(WSL2)Windows는 WSL2 강력 권장(빌드 스크립트가 POSIX 가정).

로컬 셋업의 큰 그림 (개념)

# 0) Node 24 + pnpm 10 준비 (nvm 권장)
nvm install 24 && nvm use 24
npm i -g pnpm@10

# 1) 의존성 설치 (모든 워크스페이스 한 번에)
pnpm install

# 2) DB·메일 인프라 띄우기 (MongoDB 레플리카셋 + Mailpit)
docker compose -f docker/docker-compose.yml up -d

# 3) 환경변수 견본 복사 후 채우기
cp sample.env .env

# 4) 데모 데이터 시드 (설문·시험·데모 사용자)
pnpm seed

# 5) 개발 서버 가동 (turbo가 client+api 동시 구동)
pnpm develop   # client :8000, api :3000
실무 팁
"전부 띄우지 말고, 워크스페이스 하나만 만져라"

초보자가 첫날부터 전체 스택을 띄우려다 환경 설정에서 지친다. 더 똑똑한 출발은 curriculum/의 마크다운 강의 구조만 읽기 → ② api/src/app.ts로 백엔드 조립도 파악 → ③ 작은 콘텐츠 기여(오타·번역)로 PR 흐름 익히기다. 전체 실행은 그다음이다. .devcontainer(VS Code/Codespaces)를 쓰면 환경 구성 부담을 크게 줄일 수 있다.

함정
MongoDB는 '레플리카셋'이어야 한다

그냥 mongod 하나만 띄우면 Prisma의 일부 기능(트랜잭션 등)이 동작하지 않는다. docker-compose.yml--replSet rs0 + rs.initiate()로 단일 노드 레플리카셋을 자동 구성하는 이유다. 직접 MongoDB를 깔 거면 이 설정을 꼭 재현해야 한다. 메일도 실제 발송 대신 Mailpit(:8025)로 캡처해 확인한다.

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

난이도별로 — '실행'보다 '읽고 추적'이 먼저인 거대 레포다.

이 레포는 규모가 커서, 코드를 읽고 구조를 추적하는 과제부터 시작하는 게 효율적이다. 아래로 갈수록 난이도가 올라간다.

실습 1

모노레포 지도 그리기난이도 ★☆☆ 입문

pnpm-workspace.yaml과 각 워크스페이스의 package.json name을 모아, "이 저장소에 몇 개의 패키지가 있고 서로 어떻게 의존하는지" 한 장의 다이어그램으로 그린다. workspace:* 의존을 따라가면 누가 shared를 쓰는지 보인다.

실습 2

챌린지 마크다운 해부난이도 ★☆☆ 입문

curriculum/challenges/english/blocks/react/에서 .md 하나를 열어 프론트매터(id·title·challengeType)--description--/--instructions--/--hints-- 블록을 구분해 본다. "어디가 학습자에게 보이는 본문이고, 어디가 자동 채점 테스트인가?"를 색칠해 표시.

실습 3

요청 흐름 추적 — 챌린지 제출난이도 ★★☆ 중급

api/src/routes/protected/challenge.ts를 출발점으로, 요청이 어떤 플러그인(auth→bouncer)을 거쳐, 어떤 스키마로 검증되고, Prisma로 어떤 도큐먼트를 갱신하는지 호출 경로를 따라 적어 본다. app.ts의 등록 순서와 대조하면 그림이 완성된다.

실습 4

커리큘럼 빌드 직접 돌려 보기난이도 ★★☆ 중급

pnpm build:curriculum(또는 cd curriculum && pnpm build)을 실행해 curriculum/generated/curriculum.json이 생성되는 과정을 관찰한다. 생성된 JSON에서 슈퍼블록→블록→챌린지 계층이 어떻게 펼쳐지는지 확인.

실습 5

실제로 기여하기 — 첫 PR난이도 ★★★ 고급

contribute.freecodecamp.org 가이드를 따라 작은 개선(강의 오타 수정·번역 보강·문서 개선)으로 첫 PR을 올려 본다. 포크→브랜치→커밋(Husky 훅 통과)→PR→리뷰의 전체 OSS 협업 사이클을 몸으로 익히는 게 목표다. e2e/·test-content가 PR에서 어떻게 게이트 역할을 하는지도 관찰.

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

freeCodeCamp를 발판으로 '대형 풀스택 모노레포'를 제대로 — 6주 계획.

주차주제학습 자료 / 할 일
1주차모노레포 기초pnpm 워크스페이스 + Turborepo 개념. 이 레포의 turbo.json·pnpm-workspace.yaml을 읽고 빌드 그래프를 그려 보기.
2주차Fastify 백엔드Fastify 플러그인·라이프사이클 공식 문서. api/src/app.ts·plugins/를 따라 인증·보안 조립 이해.
3주차스키마·DB 계층TypeBox/Ajv 검증 + Prisma(MongoDB 커넥터). schema.prisma·schemas/로 "타입=검증=DB" 한 줄기 파악.
4주차Gatsby·React 프론트Gatsby SSG + Redux Toolkit·Saga. client/gatsby-node.ts가 강의를 어떻게 페이지로 만드는지.
5주차Content-as-Code마크다운 파서·빌드 파이프라인 설계. challenge-parser·build-curriculum.ts 정독 후 미니 버전 직접 구현.
6주차테스트·i18n·기여Vitest·Playwright(E2E) + Crowdin i18n. 실제로 첫 PR 올리고 CI 게이트 통과 경험.

10핵심 키워드 사전

문서·코드·설정에 자주 나오는 용어 — 한 줄 정의.

용어의미
Monorepo여러 프로젝트를 하나의 git 저장소에서 관리하는 방식. client·api·curriculum이 한 지붕 아래.
Workspace모노레포 안의 개별 패키지(자기 package.json 보유). pnpm-workspace.yaml에 등록.
pnpm디스크 효율형 패키지 매니저. 워크스페이스를 묶고 의존성을 공유.
Turborepo빌드 오케스트레이터. 의존 그래프로 순서 정렬 + 결과 캐싱.
GatsbyReact 기반 정적 사이트 생성기(SSG). 빌드 때 강의를 페이지로 미리 생성.
Fastify고성능 Node 웹 프레임워크. 모든 기능을 플러그인으로 조립.
Prisma타입 안전 ORM. 여기선 MongoDB 커넥터로 NoSQL을 타입으로 접근.
TypeBox / Ajv스키마 우선 검증. 하나의 정의로 타입 + 런타임 검증.
Auth0 / OAuth2 / JWT외부 인증 + 표준 인가 프로토콜 + 토큰 기반 세션(쿠키).
CSRF protection요청마다 비밀 토큰을 확인해 위조 요청 차단(인증과 별개의 방어).
Superblock / Block / Challenge커리큘럼 3단 계층(인증서 → 강의 묶음 → 개별 문제).
Content-as-Code콘텐츠를 마크다운+Git+테스트로 관리. curriculum이 대표 사례.
--description-- / --hints--챌린지 마크다운의 섹션 마커. hints=자동 채점 테스트.
Redux Toolkit / Saga전역 상태 + 비동기 부수효과(로그인·진도·기부)를 선언적으로 처리.
Vitest / Playwright단위·통합 테스트 러너 / 브라우저 E2E 테스트.
Crowdin / i18next번역 협업 플랫폼 / 클라이언트 국제화 라이브러리.
Dev ContainerVS Code/Codespaces용 표준 개발 환경 정의(.devcontainer).
Replica SetMongoDB 복제 구성. 로컬은 단일 노드 rs0로 초기화(트랜잭션 등에 필요).

11참고 링크

원문으로 더 깊이 — 공식 소스 위주.