오늘은 코드를 거의 안 짰다. 대신 "레시피 공유 서비스"라는 사이드 프로젝트를 설계 문서만으로 처음부터 끝까지 밟아봤다. 그 과정에서 배운 것들을 정리한다.
1. 모노레포에서 설정을 상속받는 법 — tsconfig.base.json
pnpm workspace로 여러 패키지(api, web, shared, ui)를 굴리는 프로젝트를 만졌는데, tsconfig.json마다 strict: true 같은 공통 옵션을 매번 반복 작성하고 있었다.
알고 보니 TypeScript는 extends라는 필드로 다른 tsconfig를 상속할 수 있었다.
// tsconfig.base.json (공통 규칙)
{ "compilerOptions": { "strict": true, "target": "ES2022" } }
// packages/api/tsconfig.json (자기만의 규칙만 추가)
{
"extends": "../../tsconfig.base.json",
"compilerOptions": { "module": "CommonJS" }
}
tsconfig.base.json이라는 이름 자체는 아무 의미가 없다. TypeScript가 특별 취급하는 파일명이 아니라, 그냥 extends로 연결된 "부모 설정 파일"일 뿐이다. 부모 파일 하나만 고치면 상속받는 자식들 전체에 반영된다 — 4개 패키지 전부 고칠 필요 없이.
단, include/exclude는 상속되지 않는다. 그래서 각 패키지가 자기 include는 따로 적어줘야 한다.
2. ESLint가 완전히 바뀌었다
예전에 봤던 .eslintrc.js 파일을 만들려고 했는데, 최신 ESLint(9+)에서는 아예 인식을 안 했다. 이유는 ESLint가 "flat config"라는 새 설정 방식으로 갈아탔기 때문. 이제는 eslint.config.mjs가 그 자리를 대신한다.
// eslint.config.mjs
import tseslint from "typescript-eslint";
export default tseslint.config(
{ ignores: ["**/dist/**", "**/node_modules/**"] },
...tseslint.configs.recommended,
);
하는 일은 똑같다("어떤 규칙을 어디에 적용할지"). 문법만 module.exports = {...} (객체 하나) 에서 export default [...] (설정 배열) 로 바뀐 것. 최신 ESLint를 쓴다면 .eslintrc.js를 만들어도 그냥 무시된다.
3. CLI가 프로젝트마다 설정을 "기억"하게 만들기
Claude Code 같은 CLI 도구를 쓸 때, 매번 새 세션을 열 때마다 MCP 서버 같은 걸 다시 등록하기 귀찮았다. 답은 프로젝트 폴더 안에 설정 파일을 두는 것이었다.
.mcp.json— 이 폴더에서 CLI를 열 때마다 자동으로 읽어서 MCP 서버를 연결해줌CLAUDE.md— 마찬가지로 자동으로 읽어서 프로젝트별 지침을 적용해줌
세션이 끝나도 "날아가는" 게 아니라, 애초에 파일로 저장해두면 세션과 무관하게 항상 로드된다는 걸 알았다.
4. 코드 짜기 전에 문서부터 쓰면 뭐가 좋은가
이번에 직접 겪은 사례로 설명하는 게 제일 빠르다.
레시피 공유 서비스를 설계하면서 "백엔드는 SQLite(개발용)" 라고 정해뒀는데, 리스크 분석 문서를 쓰다가 이런 문제를 발견했다:
SQLite는 파일 하나짜리 DB다. 그런데 만약 이 Next.js 앱을 Vercel 같은 서버리스 환경에 배포하면? 서버리스는 함수가 실행될 때마다 파일시스템이 초기화되거나 인스턴스마다 분리돼 있다. 즉 SQLite에 쓴 데이터가 그냥 사라진다.
이걸 코드를 다 짜고 배포한 후에 알았다면? DB를 Postgres로 바꾸고, ORM 스키마 다시 만지고, 이미 짠 API 코드를 재검증해야 했을 것이다 — 최소 며칠 작업.
문서 단계에서 잡으니 고치는 비용은 표 한 줄이었다. 이게 "설계 문서를 먼저 쓰라"는 말의 진짜 의미였다. 같은 실수라도 발견하는 시점에 따라 고치는 비용이 완전히 달라진다.
5. 설계 문서도 순서가 있다
이번에 밟은 순서:
프로젝트 초기화 → 기능 명세 → 아키텍처 → WBS → 리스크 분석이 순서가 임의가 아니라, 각 단계가 다음 단계의 재료가 되는 구조였다.
- 기능 명세 없이 아키텍처부터 그리면 → 뭘 위한 구조인지 모른 채 설계
- 아키텍처 없이 WBS를 짜면 → 무슨 작업을 해야 하는지가 불분명
- WBS 없이 리스크 분석을 하면 → 뭘 분석해야 할지 기준이 없음
그리고 이 각 단계는 다 이름 붙은 정식 출처가 있었다.
| 단계 | 출처 |
|---|---|
| 기능 명세 (사용자 스토리) | Mike Cohn, User Stories Applied |
| 아키텍처 문서 | Malte Ubl, "Design Docs at Google" |
| WBS / 리스크 분석 | PMI PMBOK Guide |
| 아키텍처 결정 기록(ADR) | Michael Nygard, "Documenting Architecture Decisions" (2011) |
Rust나 Kubernetes 같은 큰 오픈소스 프로젝트들도 "코드 PR 전에 설계 문서(RFC) 먼저 승인받기"를 공식 프로세스로 쓰고 있었다 (Rust RFC, Kubernetes KEP).
6. ADR을 "Y-statement"로 쓰는 법
ADR(아키텍처 결정 기록)을 쓸 때, 한 문장으로 결정을 요약하는 포맷이 있었다:
[상황]에서, [문제]에 직면하여, 우리는 [선택한 옵션]을 택하고 [대안]을 택하지 않기로 했다. 이를 통해 [얻으려는 것]을 달성하고자 하며, [감수할 단점]을 감수한다.
이 한 문장 안에 "왜 이렇게 정했는지"가 전부 들어간다. 나중에 "왜 MongoDB 안 쓰고 Postgres 썼어요?" 라는 질문에 코드가 아니라 이 문서 한 줄로 답할 수 있게 된다.
오늘 만든 것들
| 프로젝트 | 만든 문서 |
|---|---|
| online-shopping | README, ADR(DB 선택), WBS, 리스크 분석, ESLint/Prettier/husky/VS Code 설정 |
| recipe-share | 기능 명세, 아키텍처 다이어그램(Mermaid), 리스크 분석 |
다음에 할 일
- recipe-share: 실제 Prisma 스키마 + JWT 인증 + API 라우트 구현 시작
- online-shopping: WBS 기반으로 GitHub 이슈 자동 생성 스크립트 실행
'인공지능 > MCP' 카테고리의 다른 글
| [TIL] Windows(Git Bash)에서 PostgreSQL + Claude Code MCP 연결하기 (0) | 2026.09.16 |
|---|---|
| [MCP] FastAPI + MCP SSE 서버/클라이언트와 LangChain Function Calling 실습기 (2) | 2025.08.24 |
