https://github.com/modu-ai/moai-adk
Modu-AI's Agentic Development Kit
https://github.com/modu-ai/moai-adk
Last synced: about 2 months ago
JSON representation
Modu-AI's Agentic Development Kit
- Host: GitHub
- URL: https://github.com/modu-ai/moai-adk
- Owner: modu-ai
- License: mit
- Created: 2025-09-16T13:07:11.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2025-10-03T08:14:52.000Z (about 2 months ago)
- Last Synced: 2025-10-03T08:46:48.862Z (about 2 months ago)
- Language: TypeScript
- Size: 15.2 MB
- Stars: 5
- Watchers: 0
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-AI-driven-development - ๐ฟ MoAI-ADK - an open-source framework that combines SPEC-First development, Test-Driven Development (TDD), and AI agents to create a complete, transparent development lifecycle. (Frameworks & Libraries / Copilot Extensions & Alternatives)
README
# MoAI-ADK (Agentic Development Kit)
[](https://www.npmjs.com/package/moai-adk)
[](https://opensource.org/licenses/MIT)
[](https://www.typescriptlang.org/)
[](https://nodejs.org/)
[](https://bun.sh/)
## MoAI-ADK
### ๋ชจ๋์AI ์์ด์ ํฑ ์ฝ๋ฉ ๊ฐ๋ฐ ํ๋ ์์ํฌ
**์๋ด:** MoAI-ADK๋ ๋ชจ๋์AI ์ฐ๊ตฌ์ค์์ ์งํ ์ค์ธ "(๊ฐ์นญ) ์์ด์ ํฑ ์ฝ๋ฉ" ์์ ์ ๋ณ์ฑ
๋ถ๋ก ์คํ ์์ค ํ๋ก์ ํธ ์์ ๋ฐํ ๋ก๋๋ค.

> "SPEC์ด ์์ผ๋ฉด CODE๋ ์๋ค."
---
## ๋ชฉ์ฐจ
- [Meet Alfred](#-meet-alfred---your-ai-development-partner)
- [Quick Start](#-quick-start-3๋ถ-์ค์ )
- [The Problem](#-the-problem---๋ฐ์ด๋ธ-์ฝ๋ฉ์-ํ๊ณ)
- [The Solution](#-the-solution---moai-adks-3-step-workflow)
- [How Alfred Works](#๏ธ-how-alfred-works---10๊ฐ-ai-์์ด์ ํธ-ํ)
- [Output Styles](#-alfreds-output-styles)
- [Language Support](#-universal-language-support)
- [Future Roadmap](#-future-roadmap)
- [CLI Reference](#-cli-reference)
- [FAQ](#-faq)
- [Support](#-support)
---
## Meet โถโ Alfred - Your AI Development Partner
์๋
ํ์ธ์, ๋ชจ๋์AI SuperAgent **AI โถโ Alfred**์
๋๋ค!

์ ๋ MoAI-ADK(๋ชจ๋์AI Agentic Development Kit)์ SuperAgent์ด์ ์ค์ ์ค์ผ์คํธ๋ ์ดํฐ(Central Orchestrator) AI, Alfred์
๋๋ค. MoAI-ADK๋ Alfred๋ฅผ ํฌํจํ์ฌ **์ด 10๊ฐ์ AI ์์ด์ ํธ๋ก ๊ตฌ์ฑ๋ ์์ด์ ํฑ ์ฝ๋ฉ AI ํ**์
๋๋ค. ์ ๋ 9๊ฐ์ ์ ๋ฌธ ์์ด์ ํธ(spec-builder, code-builder, doc-syncer ๋ฑ)๋ฅผ ์กฐ์จํ์ฌ ์ฌ๋ฌ๋ถ์ Claude Code ํ๊ฒฝ ์์์ ๊ณต๋ ๊ฐ๋ฐ ์์
์ ์๋ฒฝํ๊ฒ ์ง์ํฉ๋๋ค.
**Alfred๋ผ๋ ์ด๋ฆ์ ์ ๋**: ๋ฐฐํธ๋งจ ์ํ์ ๋์ค๋ ์ถฉ์คํ ์ง์ฌ Alfred Pennyworth์์ ์๊ฐ์ ๋ฐ์ ์ง์๋ค๊ณ ํฉ๋๋ค. ์ง์ฌ Alfred๊ฐ ๋ฐฐํธ๋งจ(Bruce Wayne)์ ์ํด ๋ชจ๋ ์ค๋น๋ฅผ ์๋ฒฝํ๊ฒ ๊ฐ์ถ๊ณ , ์ํ์ ์ฒํ์ ๋ ์ฆ๊ฐ์ ์ธ ์ง์์ ์ ๊ณตํ๋ฉฐ, ํญ์ ํ ๊ฑธ์ ์์ ์๊ฐํ๋ฏ์ด, ์ ๋ํ ์ฌ๋ฌ๋ถ์ ๊ฐ๋ฐ ๊ณผ์ ์์์ ํ์ํ ๋ชจ๋ ๊ฒ์ ๋ฏธ๋ฆฌ ์ค๋นํ๊ณ , ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ฉด ์ฆ์ ํด๊ฒฐ์ฑ
์ ์ ์ํ๋ฉฐ, ์ธ์ ๋ ์ฌ๋ฌ๋ถ์ด ์ฐฝ์์ ์ธ ๋ฌธ์ ํด๊ฒฐ์๋ง ์ง์คํ ์ ์๋๋ก ๋ท๋ฐ์นจํฉ๋๋ค. ์ฌ๋ฌ๋ถ์ ์ฝ๋์ "**์(Why)**"์ ์ง์คํ์๊ณ , "**์ด๋ป๊ฒ(How)**"๋ ์ ๊ฐ ์ฑ
์์ง๊ฒ ์ต๋๋ค.
### ๐ ํฅ๋ฏธ๋ก์ด ์ฌ์ค: AI๊ฐ ๋ง๋ AI ๊ฐ๋ฐ ๋๊ตฌ
์ด ํ๋ก์ ํธ์ ๋ชจ๋ ์ฝ๋๋ **100% AI์ ์ํด ์์ฑ**๋์์ต๋๋ค. AI๊ฐ ์ง์ ์ค๊ณํ๊ณ ๊ตฌํํ AI ๊ฐ๋ฐ ํ๋ ์์ํฌ์
๋๋ค.
**์ค๊ณ ๋จ๊ณ๋ถํฐ AI ํ์
**: ์ด๊ธฐ ์ํคํ
์ฒ ์ค๊ณ ๋จ๊ณ๋ถํฐ **GPT-5 Pro**์ **Claude 4.1 Opus** ๋ AI ๋ชจ๋ธ์ด ํจ๊ป ์ฐธ์ฌํ์ต๋๋ค. ๋ AI๊ฐ ์๋ก ๋ค๋ฅธ ๊ด์ ์์ ์ค๊ณ๋ฅผ ๊ฒํ ํ๊ณ ํ ๋ก ํ๋ฉฐ, ๋ ๋์ ๋ฐฉํฅ์ ์ ์ํ๊ณ , ์ต์ ์ ์ํคํ
์ฒ๋ฅผ ํจ๊ป ๋ง๋ค์ด๋์ต๋๋ค. GPT-5 Pro๋ ํญ๋์ ์ฌ๋ก ๋ถ์์, Claude 4.1 Opus๋ ๊น์ด ์๋ ์ฝ๋ ๊ตฌ์กฐ ์ค๊ณ๋ฅผ ๋ด๋นํ๋ฉฐ ์๋ก ๋ณด์ํ์ต๋๋ค.
**Agentic Coding ๋ฐฉ๋ฒ๋ก ์ ์ค์ ์ ์ฉ**: **๋ชจ๋์AI**ํ์ด Claude Code์ Agentic Coding ๋ฐฉ๋ฒ๋ก ์ ํ์ฉํ์ฌ ๊ฐ๋ฐํ์ต๋๋ค. ์ ํต์ ์ธ ๋ฐฉ์์ฒ๋ผ ์ฌ๋์ด ํค๋ณด๋ ์์ ์์ ๋ชจ๋ ์ฝ๋๋ฅผ ์ง์ ํ์ดํํ๋ ๋์ , AI ์์ด์ ํธ๋ค์ด SPEC์ ์ฝ๊ณ ์ดํดํ๊ณ , ํ
์คํธ๋ฅผ ๋จผ์ ์์ฑํ๊ณ (TDD Red), ๊ตฌํ ์ฝ๋๋ฅผ ๋ง๋ค๊ณ (TDD Green), ๋ฆฌํฉํ ๋งํ๊ณ (TDD Refactor), ๋ฌธ์๋ฅผ ๋๊ธฐํํ๋ ์ ๊ณผ์ ์ **์์จ์ ์ผ๋ก** ์ํํ์ต๋๋ค. ์ Alfred์ 9๊ฐ ์ ๋ฌธ ์์ด์ ํธ๋ก ๊ตฌ์ฑ๋ **10๊ฐ AI ์์ด์ ํธ ํ**์ด ์ง์ `.moai/specs/` ํด๋์ SPEC ๋ฌธ์๋ฅผ ์์ฑํ๊ณ , `tests/` ํด๋์ ํ
์คํธ ์ฝ๋๋ฅผ ๋ง๋ค๊ณ , `src/` ํด๋์ ๊ตฌํ ์ฝ๋๋ฅผ ์์ฑํ์ต๋๋ค.
**100% AI ์์ฑ ์ฝ๋์ ์ง์ค**: ์ด ํ๋ก์ ํธ๋ 100% AI๋ก ๋ง๋ค์ด์ง ์คํ์์ค์ด๊ธฐ ๋๋ฌธ์, ์ฝ๋๋ฒ ์ด์ค์์ ๋ค์ ์ ๋ฆฌ๋์ง ์์ ๋ถ๋ถ์ด๋ ๊ฐ์ ์ด ํ์ํ ์์ญ์ด ๋ณด์ผ ์ ์์ต๋๋ค. ํ์ง๋ง ์ด๊ฒ์ด ์ด ํ๋ก์ ํธ์ ํต์ฌ ์ฒ ํ์
๋๋ค.
**ํฌ๋ช
์ฑ๊ณผ ์ง์์ ๊ฐ์ **: ์๋ฒฝํ์ง ์์ ์ฝ๋๋ฅผ ์จ๊ธฐ๋ ๋์ , AI ๊ฐ๋ฐ ๋๊ตฌ๊ฐ ์ค์ ๋ก ์ด๋ป๊ฒ ๋ง๋ค์ด์ง๋์ง ๊ทธ๋๋ก ๋ณด์ฌ์ฃผ๊ณ , ์ปค๋ฎค๋ํฐ์ ํจ๊ป ๋ ๋์ ๋ฐฉํฅ์ผ๋ก ๋ฐ์ ์์ผ ๋๊ฐ๊ณ ์ ํฉ๋๋ค. ์ฌ๋ฌ๋ถ์ ์ฌ์ฉ ๊ฒฝํ๊ณผ ํผ๋๋ฐฑ์ด ์ด ํ๋ก์ ํธ๋ฅผ ๋์ฑ ๊ฐ๋ ฅํ๊ฒ ๋ง๋ญ๋๋ค. [GitHub Issues](https://github.com/modu-ai/moai-adk/issues)๋ [Discussions](https://github.com/modu-ai/moai-adk/discussions)์ ํผ๋๋ฐฑ์ ๋จ๊ฒจ์ฃผ์๋ฉด, **์ต๋ํ ๋น ๋ฅด๊ฒ ์
๋ฐ์ดํธํ๊ณ ๋ฐฐํฌํ ๊ฒ์ ์ฝ์๋๋ฆฝ๋๋ค**. AI๊ฐ ๋ง๋ ๋๊ตฌ๋ฅผ ํจ๊ป ๋ ๋์ ๋๊ตฌ๋ก ๋ง๋ค์ด๊ฐ๋ ์ฌ์ ์ ๋์ฐธํด์ฃผ์ธ์!
### โถโ Alfred๊ฐ ์ ๊ณตํ๋ 4๊ฐ์ง ํต์ฌ ๊ฐ์น
#### 1๏ธโฃ ์ผ๊ด์ฑ(Consistency): ํ๋์ผ์ํ์ธ ์ฝ๋๋ฅผ ๋ฐฉ์งํ๋ 3๋จ๊ณ ํ์ดํ๋ผ์ธ
Alfred๋ ๋ชจ๋ ๊ฐ๋ฐ ์์
์ **SPEC โ TDD โ Sync**๋ผ๋ 3๋จ๊ณ ํ์ดํ๋ผ์ธ์ผ๋ก ํ์คํํฉ๋๋ค. ์์์ผ์ ChatGPT๋ก ๋ง๋ ์ฝ๋, ์์์ผ์ Claude๋ก ๋ง๋ ์ฝ๋, ๊ธ์์ผ์ Gemini์ผ๋ก ๋ง๋ ์ฝ๋๊ฐ ์๋ก ๋ค๋ฅธ ์คํ์ผ, ๋ค์ด๋ฐ ๊ท์น, ์ํคํ
์ฒ ํจํด์ ๊ฐ์ง๋ "ํ๋์ผ์ํ์ธ ์ฝ๋"์ ๋ฌธ์ ๋ฅผ **์์ฒ์ ์ผ๋ก ์ฐจ๋จ**ํฉ๋๋ค. ๊ฐ์ ํ๋ก์ ํธ ์์์ `getUserInfo()`, `fetchUser()`, `retrieveUserData()` ๊ฐ์ ์ด๋ฆ์ผ๋ก ๋๊ฐ์ ๊ธฐ๋ฅ์ด 3๋ฒ ๊ตฌํ๋๋ ์
๋ชฝ์ ๊ฒฝํํด๋ณด์
จ๋์? Alfred๋ ์ด๋ฐ ์ผ์ด ์ ๋ ์ผ์ด๋์ง ์๋๋ก ๋ณด์ฅํฉ๋๋ค.
์ด 3๋จ๊ณ ํ์ดํ๋ผ์ธ์ ๋ง์น ์๋์ฐจ ๊ณต์ฅ์ ์กฐ๋ฆฝ ๋ผ์ธ์ฒ๋ผ ์๋ํฉ๋๋ค. ์ด๋ค ๊ธฐ๋ฅ์ ๋ง๋ค๋ (์ฌ์ฉ์ ์ธ์ฆ, ๊ฒฐ์ ์์คํ
, ์๋ฆผ ๊ธฐ๋ฅ), ๋๊ฐ ๋ง๋ค๋ (์ ์
๊ฐ๋ฐ์, ์๋์ด ๊ฐ๋ฐ์, AI ๋๊ตฌ), ์ธ์ ๋ง๋ค๋ (์์์ผ ์ค์ , ๊ธ์์ผ ๋ฐค) ํญ์ ๊ฐ์ ํ๋ก์ธ์ค๋ฅผ ๊ฑฐ์น๊ฒ ๋ฉ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก **6๊ฐ์ ํ์ ์ฝ๋๋ฅผ ๋ค์ ๋ด๋**, **์๋ก์ด ํ์์ด ์ฝ๋๋ฅผ ์ฒ์ ๋ด๋**, "์, ์ด๊ฑด Alfred ๋ฐฉ์์ผ๋ก ๋ง๋ค์ด์ก๊ตฌ๋. SPEC์ ๋จผ์ ๋ณด๊ณ , ํ
์คํธ๋ฅผ ๋ณด๊ณ , ๊ตฌํ์ ๋ณด๋ฉด ๋๊ฒ ๋ค"๋ผ๊ณ ์ฆ์ ์ดํดํ ์ ์์ต๋๋ค. ์ผ๊ด์ฑ์ ์ ์ง๋ณด์์ฑ์ ํต์ฌ์ด๋ฉฐ, **๊ธฐ์ ๋ถ์ฑ๋ฅผ ์ค์ด๋ ๊ฐ์ฅ ๊ฐ๋ ฅํ ๋ฌด๊ธฐ**์
๋๋ค.
#### 2๏ธโฃ ํ์ง(Quality): TRUST 5์์น์ผ๋ก ์๋ ๋ณด์ฅ๋๋ ์ฝ๋ ํ์ง
Alfred๋ ๋ชจ๋ ์ฝ๋์ **TRUST 5์์น**(Test First, Readable, Unified, Secured, Trackable)์ ์๋์ผ๋ก ์ ์ฉํ๊ณ ๊ฒ์ฆํฉ๋๋ค. ์ฌ๋์ด ์ผ์ผ์ด ์ฒดํฌ๋ฆฌ์คํธ๋ฅผ ๋ค๊ณ "ํ
์คํธ ์ปค๋ฒ๋ฆฌ์ง ํ์ธํ๋? ํจ์ ๊ธธ์ด ํ์ธํ๋? ๋ณด์ ์ทจ์ฝ์ ํ์ธํ๋?"๋ฅผ ๋ฌผ์ด๋ณผ ํ์๊ฐ ์์ต๋๋ค. Alfred๊ฐ **์๋์ผ๋ก** ํ
์คํธ ์ปค๋ฒ๋ฆฌ์ง๋ฅผ ์ธก์ ํ๊ณ (โฅ85% ํ์), ์ฝ๋ ๋ณต์ก๋๋ฅผ ๋ถ์ํ๊ณ (๋ณต์ก๋ โค10), ๋ณด์ ์ทจ์ฝ์ ์ ์ค์บํ๊ณ (SQL Injection, XSS ์ฒดํฌ), TAG ์ถ์ ์ฑ์ ๋ณด์ฅํฉ๋๋ค(๊ณ ์ TAG ์๋ ํ์ง).
์๋ฅผ ๋ค์ด, ํจ์๊ฐ 50์ค์ ๋์ด๊ฐ๋ฉด Alfred๊ฐ ์ฆ์ ๊ฒฝ๊ณ ํฉ๋๋ค: "์ด ํจ์๋ ๋๋ฌด ๊ธธ์ด์. ์์ ํจ์๋ก ๋ถ๋ฆฌํด์ฃผ์ธ์." ํ
์คํธ ์ปค๋ฒ๋ฆฌ์ง๊ฐ 85% ๋ฏธ๋ง์ด๋ฉด ๋น๋๋ฅผ ๋ฉ์ถฅ๋๋ค: "ํ
์คํธ๊ฐ ๋ถ์กฑํฉ๋๋ค. ์ฃ์ง ์ผ์ด์ค๋ฅผ ๋ ํ
์คํธํด์ฃผ์ธ์." SQL ์ฟผ๋ฆฌ์ ์ฌ์ฉ์ ์
๋ ฅ์ ์ง์ ๋ฃ๋ ์ฝ๋๊ฐ ๋ฐ๊ฒฌ๋๋ฉด ๋ณด์ ๊ฐ์ด๋๋ฅผ ์ ์ํฉ๋๋ค: "SQL Injection ์ทจ์ฝ์ ์ด ์์ต๋๋ค. Prepared Statement๋ฅผ ์ฌ์ฉํ์ธ์." ์ด๋ฐ ์๋ ๊ฒ์ฆ ์์คํ
๋๋ถ์ ์ฌ๋ฌ๋ถ์ "์ข์ ์ฝ๋๋ฅผ ์์ฑํด์ผ์ง"๋ผ๊ณ **์์์ ์ผ๋ก ์๊ฐํ ํ์ ์์ด**, ์์ฐ์ค๋ฝ๊ฒ ์ข์ ์ฝ๋๋ฅผ ์์ฑํ๊ฒ ๋ฉ๋๋ค. ํ์ง์ ์ ํ์ด ์๋๋ผ ๊ธฐ๋ณธ๊ฐ(default)์
๋๋ค.
#### 3๏ธโฃ ์ถ์ ์ฑ(Traceability): 6๊ฐ์ ํ์๋ "์"๋ฅผ ์ฐพ์ ์ ์๋ @TAG ์์คํ
Alfred์ **@TAG ์์คํ
**์ ๋ชจ๋ ์ฝ๋ ์กฐ๊ฐ์ `@SPEC:ID โ @TEST:ID โ @CODE:ID โ @DOC:ID`๋ก ์๋ฒฝํ๊ฒ ์ฐ๊ฒฐํฉ๋๋ค. 6๊ฐ์ ํ ๋๊ตฐ๊ฐ "์ ์ด ํจ์๋ ์ด๋ ๊ฒ ๋ณต์กํ๊ฒ ๊ตฌํํ๋์? ๋ ๊ฐ๋จํ๊ฒ ํ ์ ์์ง ์๋์?"๋ผ๊ณ ๋ฌผ์ด๋ณด๋ฉด, **@TAG๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉด ๋ต์ ์ฐพ์ ์ ์์ต๋๋ค**. SPEC ๋ฌธ์๋ฅผ ์ด์ด "์, ์ด๊ฑด ๊ธ์ต ๊ท์ ๋๋ฌธ์ 3๋จ๊ณ ๊ฒ์ฆ์ด ํ์๊ตฌ๋"๋ฅผ ํ์ธํ๊ณ , TEST ์ฝ๋๋ฅผ ๋ณด๋ฉฐ "์ด ์ฃ์ง ์ผ์ด์ค๋ค์ด ์ค์ ๋ก ํ๋ก๋์
์์ ๋ฐ์ํ๋ ๋ฒ๊ทธ๊ตฌ๋"๋ฅผ ์ดํดํ๊ณ , CODE๋ฅผ ๋ณด๋ฉฐ "์ด๋ ๊ฒ ๊ตฌํํ ์ด์ ๊ฐ ์์๊ตฌ๋"๋ฅผ ๋ฉ๋ํ๊ณ , DOC์ ๋ณด๋ฉฐ "๋ค๋ฅธ ํ์๋ค๋ ์ด ๋ฌธ์ ๋ฅผ ๊ฒช์๊ณ ํด๊ฒฐ์ฑ
์ ๊ณต์ ํ๊ตฌ๋"๋ฅผ ๋ฐฐ์๋๋ค.
ํนํ Alfred์ TAG ์์คํ
์ **CODE-FIRST** ๋ฐฉ์์ ์ฌ์ฉํฉ๋๋ค. ์ค๊ฐ์ ๋ณ๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ YAML ํ์ผ, JSON ์บ์ ํ์ผ์ ๋์ง ์๊ณ , **์ฝ๋ ์์ฒด๋ฅผ ์ง์ ์ค์บ**ํ์ฌ TAG๋ฅผ ์ฐพ์ต๋๋ค(`rg '@CODE:AUTH-001' -n`). ์ด๋ "**์ฝ๋๊ฐ ์ง์ค์ ์ ์ผํ ์์ฒ(single source of truth)**"์ด๋ผ๋ ์ฒ ํ์ ๋ฐ์ํ ๊ฒ์
๋๋ค. TAG๋ ์ธ๋ถ ๋ฌธ์๊ฐ ์๋๋ผ ์ด์์๋ ์ฝ๋ ์์ ์ฃผ์์ผ๋ก ์กด์ฌํ๋ฉฐ, ์ฝ๋๊ฐ ๋ณ๊ฒฝ๋๋ฉด TAG๋ ํจ๊ป ๋ณ๊ฒฝ๋ฉ๋๋ค. ์ฝ๋์ ๋ฌธ์๊ฐ ๋ฐ๋ก ๋ ์ ์์ต๋๋ค. ์ถ์ ์ฑ์ ๋ฌธ์ํ์ ๋ถ์ฐ๋ฌผ์ด ์๋๋ผ **์ฝ๋์ ์ผ๋ถ**์
๋๋ค.
#### 4๏ธโฃ ๋ฒ์ฉ์ฑ(Universality): ํ ๋ฒ ๋ฐฐ์ฐ๋ฉด ์ด๋์๋ ์ธ ์ ์๋ ์ํฌํ๋ก์ฐ
Alfred๋ ํน์ ์ธ์ด๋ ํ๋ ์์ํฌ์ ์ข
์๋์ง ์์ต๋๋ค. **Python, TypeScript, Java, Go, Rust, Dart, Swift, Kotlin** ๋ฑ ๋ชจ๋ ์ฃผ์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ฅผ ์ง์ํ๋ฉฐ, ๊ฐ ์ธ์ด์ ์ต์ ํ๋ ๋๊ตฌ ์ฒด์ธ(ํ
์คํธ ํ๋ ์์ํฌ, ๋ฆฐํฐ, ํ์
์ฒด์ปค)์ ์๋์ผ๋ก ์ ํํฉ๋๋ค. ๋ฐฑ์๋ ๊ฐ๋ฐ์๊ฐ Python FastAPI๋ก API ์๋ฒ๋ฅผ ๋ง๋ค๋ , ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๊ฐ TypeScript React๋ก ์น์ฑ์ ๋ง๋ค๋ , ๋ชจ๋ฐ์ผ ๊ฐ๋ฐ์๊ฐ Flutter๋ก ์ฑ์ ๋ง๋ค๋ , **๋ชจ๋ ๊ฐ์ 3๋จ๊ณ ์ํฌํ๋ก์ฐ**๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์๋ฅผ ๋ค์ด, Python ํ๋ก์ ํธ์์๋ `pytest`(ํ
์คํธ)์ `ruff`(๋ฆฐํฐ)์ `mypy`(ํ์
์ฒด์ปค)๋ฅผ ์๋์ผ๋ก ์ฌ์ฉํ๊ณ , TypeScript ํ๋ก์ ํธ์์๋ `Vitest`์ `Biome`๋ฅผ ์ฌ์ฉํ๊ณ , Go ํ๋ก์ ํธ์์๋ `go test`์ `golint`๋ฅผ ์ฌ์ฉํ๊ณ , Rust ํ๋ก์ ํธ์์๋ `cargo test`์ `clippy`๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ฌ๋ฌ๋ถ์ "๋ด ํ๋ก์ ํธ๋ Python์ด์ผ"๋ผ๊ณ ์ ํ๋ง ํ๋ฉด ๋๊ณ , ๋๋จธ์ง ๋๊ตฌ ์ ํ๊ณผ ์ค์ ์ **Alfred๊ฐ ์์์** ํฉ๋๋ค. ํ์ ๋ฐฑ์๋ ๊ฐ๋ฐ์, ํ๋ก ํธ์๋ ๊ฐ๋ฐ์, ๋ชจ๋ฐ์ผ ๊ฐ๋ฐ์๊ฐ ์์ฌ ์์ด๋ ๋ชจ๋๊ฐ "Alfred ์ํฌํ๋ก์ฐ"๋ผ๋ ๊ณตํต ์ธ์ด๋ก ์ํตํ ์ ์์ต๋๋ค. ๋ฒ์ฉ์ฑ์ **ํ ํ์
์ ํต์ฌ**์ด๋ฉฐ, ๊ฐ๋ฐ์ ์จ๋ณด๋ฉ ์๊ฐ์ ํ๊ธฐ์ ์ผ๋ก ์ค์ฌ์ค๋๋ค.
---
## ๐ Quick Start (3๋ถ ์ค์ )
### ๐ ์ค๋น๋ฌผ
- โ
Bun ๋๋ npm ์ค์น๋จ
- โ
Claude Code ์คํ ์ค
- โ
Git ์ค์น๋จ (์ ํ์ฌํญ)
### โก 3๋จ๊ณ๋ก ์์ํ๊ธฐ
#### 1๏ธโฃ ์ค์น (30์ด)
```bash
# Bun ๊ถ์ฅ (5๋ฐฐ ๋น ๋ฅธ ์ฑ๋ฅ)
curl -fsSL https://bun.sh/install | bash
bun add -g moai-adk
# ๋๋ npm ์ฌ์ฉ
npm install -g moai-adk
# ์ค์น ํ์ธ
moai --version
# ์ถ๋ ฅ: v0.x.x
```
#### 2๏ธโฃ ์ด๊ธฐํ (1๋ถ)
**ํฐ๋ฏธ๋์์:**
```bash
# ์ ํ๋ก์ ํธ ์์ฑ
moai init my-project
cd my-project
# ๊ธฐ์กด ํ๋ก์ ํธ์ ์ค์น
cd existing-project
moai init .
# Claude Code ์คํ
claude
```
**Claude Code์์** (ํ์):
```text
/alfred:8-project
```
Alfred๊ฐ ์๋์ผ๋ก ์ํ:
- `.moai/project/` ๋ฌธ์ 3์ข
์์ฑ (product/structure/tech.md)
- ์ธ์ด๋ณ ์ต์ ๋๊ตฌ ์ฒด์ธ ์ค์
- ํ๋ก์ ํธ ์ปจํ
์คํธ ์๋ฒฝ ์ดํด
#### 3๏ธโฃ ์ฒซ ๊ธฐ๋ฅ ๊ฐ๋ฐ (1๋ถ 30์ด)
**Claude Code์์ 3๋จ๊ณ ์ํฌํ๋ก์ฐ ์คํ:**
```text
# SPEC ์์ฑ
/alfred:1-spec "JWT ๊ธฐ๋ฐ ์ฌ์ฉ์ ๋ก๊ทธ์ธ API"
# TDD ๊ตฌํ
/alfred:2-build AUTH-001
# ๋ฌธ์ ๋๊ธฐํ
/alfred:3-sync
```
### ๐ ์๋ฃ
**์์ฑ๋ ๊ฒ๋ค:**
- โ
`.moai/specs/SPEC-AUTH-001.md` (๋ช
์ธ)
- โ
`tests/auth/login.test.ts` (ํ
์คํธ)
- โ
`src/services/auth.ts` (๊ตฌํ)
- โ
`docs/api/auth.md` (๋ฌธ์)
- โ
`@SPEC โ @TEST โ @CODE โ @DOC` TAG ์ฒด์ธ
---
## ๐จ The Problem - ๋ฐ์ด๋ธ ์ฝ๋ฉ์ ํ๊ณ
AI ๋๊ตฌ(Codex, Claude, Gemini)๋ก ๋น ๋ฅด๊ฒ ์ฝ๋ฉํ๋ ์๋๊ฐ ์ด๋ ธ์ต๋๋ค. ๊ฐ๋ฐ ์๋๋ ํ์คํ ๋นจ๋ผ์ก์ง๋ง, **์๋ก์ด ์ข
๋ฅ์ ๋ฌธ์ **๋ค์ด ์๊ฒจ๋ฌ์ต๋๋ค. ์๋ 5๊ฐ์ง ํ์ค์ ์ธ ๋ฌธ์ ๋ค์ ์ดํด๋ณด์ธ์.
### 1. ์๋ฆ๋ต์ง๋ง ์๋ํ์ง ์๋ ์ฝ๋
**๋ฌธ์ ์ํฉ**: AI๊ฐ ์์ฑํ ์ฝ๋๋ ๋ฌธ๋ฒ์ ์ผ๋ก ์๋ฒฝํ๊ณ ๊ตฌ์กฐ๋ ์ฐ์ํฉ๋๋ค. ์ฝ๋ ๋ฆฌ๋ทฐ๋ฅผ ํ๋ฉด "์, ๊น๋ํ๋ฐ?"๋ผ๋ ๋ฐ์์ด ๋์ต๋๋ค. ํ์ง๋ง ์ค์ ๋ก ์คํํด๋ณด๋ฉด...
- **์ปดํ์ผ์ ๋์ง๋ง ์คํ์ ์ ๋จ**: TypeScript ํ์
์ ์๋ฒฝํ๊ฒ ๋ง๋๋ฐ, ๋ฐํ์์ `undefined` ์๋ฌ๊ฐ ๋ฐ์ํฉ๋๋ค. "๋ถ๋ช
ํ์
์ฒดํฌ๋ ํต๊ณผํ๋๋ฐ ์?"
- **์ฃ์ง ์ผ์ด์ค ์ฒ๋ฆฌ ๋ถ์กฑ**: ์ ์ ์๋๋ฆฌ์ค(happy path)๋ง ๊ณ ๋ คํ๊ณ , ๋น ๋ฐฐ์ด, null ๊ฐ, ๋คํธ์ํฌ ํ์์์ ๊ฐ์ ์์ธ ์ํฉ์ ์์ ํ ๋ฌด์ํฉ๋๋ค.
- **์ฑ๋ฅ ๋ฌธ์ **: ์๊ณ ๋ฆฌ์ฆ์ ๋ง๋๋ฐ `O(nยณ)` ๋ณต์ก๋๋ก ๊ตฌํ๋์ด, ๋ฐ์ดํฐ๊ฐ 100๊ฐ์ผ ๋๋ ๊ด์ฐฎ์ง๋ง 10,000๊ฐ๊ฐ ๋๋ฉด ์๋ฒ๊ฐ ๋ฉ์ถฅ๋๋ค.
- **์์กด์ฑ ์ง์ฅ**: ๋จ์ํ ๋ ์ง ํฌ๋งทํ
์ ์ํด ๋ค์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ถ์ฒ๋ฐ์ ์ค์นํ๊ณ , ๋์ค์ ๋ณด์ ์ทจ์ฝ์ ๊ฒฝ๊ณ ๊ฐ ์์์ง๋๋ค.
**AI ์์ธก ์ฌ๋ก**: ํ ๊ฐ๋ฐ์๊ฐ ChatGPT๋ก ์ฌ์ฉ์ ์ธ์ฆ ์ฝ๋๋ฅผ ์์ฑํ์ต๋๋ค. ์ฝ๋๋ ์๋ฆ๋ค์ ๊ณ ์ปดํ์ผ๋ ์๋ฒฝํ์ต๋๋ค. ํ์ง๋ง ์ค์ ๋ก ๋ฐฐํฌ ํ, ๋น๋ฐ๋ฒํธ๊ฐ ํ๋ฌธ(plain text)์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ๋๊ณ ์์์ต๋๋ค. AI๋ "์ฌ์ฉ์ ์ธ์ฆ"์ด๋ผ๋ ์์ฒญ๋ง ๋ฐ์์ง, "๋ณด์ ์๊ตฌ์ฌํญ"์ ๋ช
์์ ์ผ๋ก ๋ฃ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์
๋๋ค. ์ค์ ๋ก ๋๋ ค๋ณด๊ธฐ ์ ๊น์ง๋ ์ด๋ฐ ์น๋ช
์ ์ธ ๋ฌธ์ ๋ฅผ ์ ์ ์์ต๋๋ค.
### 2. ํ๋์ผ์ํ์ธ ์ฝ๋์ ํ์
**๋ฌธ์ ์ํฉ**: ์ฌ๋ฌ AI ๋๊ตฌ๋ฅผ ๋ฒ๊ฐ์ ์ฌ์ฉํ๊ฑฐ๋, ๊ฐ์ AI๋ผ๋ ๋ค๋ฅธ ์ธ์
์์ ์ฝ๋๋ฅผ ์์ฑํ๋ค ๋ณด๋ฉด ์ผ๊ด์ฑ ์๋ ์ฝ๋๋ฒ ์ด์ค๊ฐ ๋ง๋ค์ด์ง๋๋ค.
- **์ผ๊ด์ฑ ์๋ ์ฝ๋ฉ ์คํ์ผ**: ์์์ผ์ ChatGPT๊ฐ ๋ง๋ ์ฝ๋๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์คํ์ผ, ์์์ผ์ Claude๊ฐ ๋ง๋ ์ฝ๋๋ ๊ฐ์ฒด์งํฅ ์คํ์ผ, ๊ธ์์ผ์ Gemini๊ฐ ๋ง๋ ์ฝ๋๋ ์ ์ฐจํ ์คํ์ผ. ๊ฐ์ ํ๋ก์ ํธ ์์์ 3๊ฐ์ง ํจ๋ฌ๋ค์์ด ํผ์ฌํฉ๋๋ค.
- **์ค๋ณต ๋ก์ง ๋๋ฌด**: ๊ฐ์ ๊ธฐ๋ฅ(์: ์ด๋ฉ์ผ ์ ํจ์ฑ ๊ฒ์ฆ)์ `validateEmail()`, `checkEmailFormat()`, `isEmailValid()`๋ผ๋ ์ด๋ฆ์ผ๋ก 3๋ฒ ๊ตฌํํฉ๋๋ค. ๊ฐ AI ์ธ์
์ด ์ด์ ์ฝ๋๋ฅผ ๋ชจ๋ฅด๊ธฐ ๋๋ฌธ์
๋๋ค.
- **์ํคํ
์ฒ ๋ถ๊ดด**: ํ๋ก์ ํธ๋ MVC ํจํด์ผ๋ก ์์ํ๋๋ฐ, ์ด๋์ Hexagonal Architecture์ Clean Architecture๊ฐ ํผ์ฌ๋๊ณ , ์ผ๋ถ๋ CQRS ํจํด๊น์ง ์์ฌ์์ต๋๋ค.
- **๋ค์ด๋ฐ ํผ๋**: `getUserData()`, `fetchUser()`, `retrieveUserInfo()`, `loadUserProfile()` ๋ชจ๋ ๊ฐ์ ๊ธฐ๋ฅ์ธ๋ฐ ์ด๋ฆ๋ง ๋ค๋ฆ
๋๋ค.
**AI ์์ธก ์ฌ๋ก**: ์คํํธ์
ํ์ด 1๊ฐ์๊ฐ AI๋ก ๋น ๋ฅด๊ฒ ํ๋กํ ํ์
์ ๋ง๋ค์์ต๋๋ค. ๊ธฐ๋ฅ์ ๋ชจ๋ ์๋ํ์ง๋ง, ์ฝ๋๋ฒ ์ด์ค๋ ๊ฐ ๊ฐ๋ฐ์๊ฐ ๋ค๋ฅธ AI๋ก ๋ง๋ ์ฝ๋๋ค์ด ๋ค์์ธ "ํ๋์ผ์ํ์ธ"์ด ๋์์ต๋๋ค. ๊ฐ ๋ถ๋ถ์ ํ๋ฅญํ์ง๋ง, ์ ์ฒด๋ ์ฌ์์ด์์ต๋๋ค. ๊ฒฐ๊ตญ ๊ธฐ์ ๋ถ์ฑ๋ฅผ ๊ฐ๊ธฐ ์ํด 3๊ฐ์์ ํฌ์ํ๊ณ , ๊ทธ ์ฌ์ด ๊ฒฝ์์ฌ์ ์์ฅ์ ๋นผ์๊ฒผ์ต๋๋ค. "๋น ๋ฅด๊ฒ ๋ง๋ค์์ง๋ง, ๋๋ฆฌ๊ฒ ๋งํ๋ค"๋ ๊ตํ๋ง ๋จ์์ต๋๋ค.
### 3. ๋๋ฒ๊น
์ง์ฅ
**๋ฌธ์ ์ํฉ**: ํ๋ก๋์
์์ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ์ ๋, ์์ธ์ ์ฐพ๋ ๊ฒ์ด ๊ฑฐ์ ๋ถ๊ฐ๋ฅํฉ๋๋ค.
- **์์ธ ์ถ์ ๋ถ๊ฐ**: "์ด ํจ์๊ฐ ์ ์ด๋ ๊ฒ ๋ณต์กํ๊ฒ ๊ตฌํ๋์์ง?" โ AI ์ฑํ
ํ์คํ ๋ฆฌ๋ ์ด๋ฏธ ์ญ์ ๋์๊ณ , ๋น์ ๊ฐ๋ฐ์๋ ๊ธฐ์ต์ด ์ ๋ฉ๋๋ค.
- **์ฌ์ด๋ ์ดํํธ ํ์
๋ถ๊ฐ**: "์ด ์ฝ๋๋ฅผ ์์ ํ๋ฉด ๋ค๋ฅธ ๊ณณ์ด ๊นจ์ง๊น?" โ ํ
์คํธ๊ฐ ์์ผ๋ ์ง์ ์คํํด๋ด์ผ ํ๋๋ฐ, ๋ชจ๋ ๊ฒฝ์ฐ์ ์๋ฅผ ๋ค ํ
์คํธํ ์ ์์ต๋๋ค.
- **ํ
์คํธ ๋ถ์ฌ**: AI์๊ฒ "ํ
์คํธ๋ ์์ฑํด์ค"๋ผ๊ณ ์์ฒญํ๋ฉด ํ
์คํธ๋ ๋ง๋ค์ด์ฃผ์ง๋ง, ์ค์ ๋ก ์คํํด๋ณด์ง ์์๊ธฐ ๋๋ฌธ์ ๊ทธ ํ
์คํธ์กฐ์ฐจ ์ ๋๋ก ์๋ํ๋์ง ํ์ธ์ด ์ ๋ฉ๋๋ค. "ํ
์คํธ๋ ๋์ค์"๋ผ๋ ์๊ฐ์ผ๋ก ๋ฏธ๋ฃจ๋ฉด, ๋์ค์ ์์ํ ์ค์ง ์์ต๋๋ค.
- **๋ฌธ์ ์์**: AI๋ ์ฝ๋๋ง ๋ง๋ค์ด์ฃผ์ง, README๋ API ๋ฌธ์๋ ์ ์จ์ค๋๋ค. ์ค์ฌ ๋ฌธ์๋ฅผ ๋ง๋ค์ด๋ฌ๋ผ๊ณ ํด๋, ์ฝ๋๊ฐ ๋ณ๊ฒฝ๋๋ฉด ๋ฌธ์๋ outdated ์ํ๊ฐ ๋ฉ๋๋ค.
**AI ์์ธก ์ฌ๋ก**: ๊ธ์์ผ ์ ๋
6์, ํ๋ก๋์
์์ ๊ฒฐ์ ์คํจ ๋ฒ๊ทธ๊ฐ ๋ณด๊ณ ๋์์ต๋๋ค. ๊ฐ๋ฐ์๋ 3๊ฐ์ ์ ์ AI๋ก ์์ฑํ ๊ฒฐ์ ๋ก์ง์ ์ด์ด๋ดค์ง๋ง, ์ ์ด๋ ๊ฒ ๊ตฌํํ๋์ง ์ ํ ๊ธฐ์ต์ด ์ ๋ฌ์ต๋๋ค. AI ์ฑํ
์ ์ญ์ ๋์๊ณ , ์ฃผ์๋ ์์์ต๋๋ค. ๊ฒฐ๊ตญ `console.log()`๋ฅผ ์์ญ ๊ฐ ์ฐ์ด๊ฐ๋ฉฐ ๋๋ฒ๊น
ํ๊ณ , ์์ธ์ ์ฐพ๋ ๋ฐ ์ฃผ๋ง ์ดํ์ด ๊ฑธ๋ ธ์ต๋๋ค. ๋ฌธ์ ๋ ๋จ์ํ ํ์์กด ์ฒ๋ฆฌ ๋ฒ๊ทธ์์ง๋ง, ์ถ์ ์ฑ์ด ์์ด์ ์ฐพ๊ธฐ๊ฐ ๋๋ฌด ์ด๋ ค์ ์ต๋๋ค.
### 4. ์๊ตฌ์ฌํญ ์ถ์ ์ฑ ์์ค
**AI ์์ธก ์ฌ๋ก**: ์๊ฐ์ด ์ง๋ ์๋ก "์ ์ด ์ฝ๋๋ฅผ ์ด๋ ๊ฒ ๋ง๋ค์๋์ง" ๋งฅ๋ฝ์ ์์ด๋ฒ๋ฆฝ๋๋ค.
- **"์"๋ฅผ ์์ด๋ฒ๋ฆผ**: ๋น์ฆ๋์ค ๋ก์ง์ ๋ฐฐ๊ฒฝ๊ณผ ์ด์ ๋ฅผ ๋ชจ๋ฆ
๋๋ค. "์ ๊ฒฐ์ ๊ธ์ก์ด 10๋ง์์ ๋์ผ๋ฉด ์ถ๊ฐ ์ธ์ฆ์ ์๊ตฌํ๋์?" โ "๊ธ์์, AI๊ฐ ๊ทธ๋ ๊ฒ ๋ง๋ค์๋๋ฐ์..."
- **๋ณ๊ฒฝ ์ด๋ ฅ ๋ถ์ฌ**: ๋๊ฐ, ์ธ์ , ์ ์ด ์ฝ๋๋ฅผ ๋ฐ๊ฟจ๋์ง ๊ธฐ๋ก์ด ์์ต๋๋ค. Git ์ปค๋ฐ ๋ฉ์์ง๋ "fix bug", "update code" ๊ฐ์ ๋ฌด์๋ฏธํ ๋ฉ์์ง๋ฟ์
๋๋ค.
- **์์ฌ๊ฒฐ์ ๊ทผ๊ฑฐ ์ฌ๋ผ์ง**: "์ JWT๋ฅผ ์ ํํ๊ณ , Session ๋์ ์ฌ์ฉํ๋์?" โ "๊ธฐ์ต ์ ๋์. AI๊ฐ ์ถ์ฒํด์์."
**AI ์์ธก ์ฌ๋ก**: ํํ
ํฌ ์คํํธ์
์ด ๊ฐ์ฌ๋ฅผ ๋ฐ์์ต๋๋ค. ๊ฐ์ฌ๊ด์ด "์ด ๊ณ ๊ฐ ์ ์ฉ ํ๊ฐ ๋ก์ง์ ๊ทผ๊ฑฐ๋ฅผ ์ค๋ช
ํด์ฃผ์ธ์"๋ผ๊ณ ์์ฒญํ์ง๋ง, ์ฝ๋๋ง ์๊ณ SPEC ๋ฌธ์๊ฐ ์์์ต๋๋ค. ๋๊ฐ ์ ์ด ์๊ณ ๋ฆฌ์ฆ์ ์ ํํ๋์ง, ์ด๋ค ๋น์ฆ๋์ค ์๊ตฌ์ฌํญ์ ๋ฐ์ํ ๊ฒ์ธ์ง ์๋ฌด๋ ๋ชฐ๋์ต๋๋ค. AI๊ฐ ์์ฑํ ์ฝ๋์๊ณ , ์๋ํ๋๊น ๊ทธ๋ฅ ์ฌ์ฉํ๋ ๊ฒ์
๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๊ธ์ต ๋ผ์ด์ ์ค ์น์ธ์ด 6๊ฐ์ ์ง์ฐ๋์์ต๋๋ค. ์ฝ๋๋ ์๋๋ฐ ์ปจํ
์คํธ๊ฐ ์์ด์ ์๊ธด ๋น๊ทน์
๋๋ค.
### 5. ํ ํ์
๋ถ๊ดด
**๋ฌธ์ ์ํฉ**: ์ฌ๋ฌ ๊ฐ๋ฐ์๊ฐ ๊ฐ์ AI๋ฅผ ์ฌ์ฉํ๋ฉด์ ํ์
์ด ๋ฌด๋์ง๋๋ค.
- **์คํ๊ฒํฐ ์ฝ๋ ์์ฐ**: A ๊ฐ๋ฐ์๋ ChatGPT๋ก, B ๊ฐ๋ฐ์๋ Claude๋ก, C ๊ฐ๋ฐ์๋ Gemini์ผ๋ก ๊ฐ์ ์ฝ๋๋ฅผ ๋ง๋ค์ด์ Git์ ํธ์ํฉ๋๋ค. ์ฝ๋ ๋ฆฌ๋ทฐ ์์ด ๊ทธ๋ฅ ๋จธ์งํฉ๋๋ค. 3๊ฐ์ ํ ์ฝ๋๋ฒ ์ด์ค๋ ์คํ๊ฒํฐ๊ฐ ๋ฉ๋๋ค.
- **์ฝ๋ ๋ฆฌ๋ทฐ ๋ถ๊ฐ**: ๋ฆฌ๋ทฐ์ด๊ฐ "์ด๊ฒ ๋ญ ํ๋ ์ฝ๋์ธ์ง ๋ชจ๋ฅด๊ฒ ์ด์. ์ค๋ช
๋ถํ๋๋ ค์"๋ผ๊ณ ํ๋ฉด, ์์ฑ์๋ "์ ๋ AI๊ฐ ๋ง๋ ๊ฑด๋ฐ, ์ ๋ชจ๋ฅด๊ฒ ์ด์"๋ผ๊ณ ๋ตํฉ๋๋ค.
- **์จ๋ณด๋ฉ ์
๋ชฝ**: ์๋ก ์
์ฌํ ๊ฐ๋ฐ์๊ฐ ์ฝ๋๋ฒ ์ด์ค๋ฅผ ์ดํดํ๋ ๋ฐ ํ ๋ฌ ์ด์ ๊ฑธ๋ฆฝ๋๋ค. ๋ฉํ ๊ฐ "์ด ๋ถ๋ถ์... ์... ์์งํ ์ ๋ ์ ๋ชจ๋ฅด๊ฒ ๋ค์"๋ผ๊ณ ๋ตํ๋ ์๊ฐ, ์ ์
์ ์ ๋งํฉ๋๋ค.
- **๊ธฐ์ ๋ถ์ฑ ํญ๋ฐ**: "์ด ์ฝ๋ ๊ฑด๋๋ฆฌ๋ฉด ๋ญ๊ฐ ๊นจ์ง ๊ฒ ๊ฐ์์ ๋ชป ๊ฑด๋๋ฆฌ๊ฒ ์ด์"๋ผ๋ "๊ธ๊ธฐ ์ฝ๋" ์์ญ์ด ์ ์ ํ๋๋ฉ๋๋ค. ๋ฆฌํฉํ ๋ง์ ๋ถ๊ฐ๋ฅํด์ง๊ณ , ์ ๊ธฐ๋ฅ์ ๋์ง๋์ง ๋ถ์ฌ๋๊ฐ๋๋ค.
**AI ์์ธก ์ฌ๋ก**: 10๋ช
๊ท๋ชจ์ ๊ฐ๋ฐ ํ์ด ๊ฐ์ AI๋ก ๋น ๋ฅด๊ฒ ๊ธฐ๋ฅ์ ๋ง๋ค์์ต๋๋ค. ๊ฐ๋ณ ๊ธฐ๋ฅ์ ๋ชจ๋ ์๋ํ์ง๋ง, ํตํฉํ๋ ์ถฉ๋์ด ๋ฐ์ํ์ต๋๋ค. ๊ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ
์ด๋ธ์ ์๋ก ๋ค๋ฅธ ๋ฐฉ์์ผ๋ก ์ ๊ทผํ๊ณ , API ์๋ต ํ์๋ ์ ๊ฐ๊ฐ์ด์์ต๋๋ค. ์ฝ๋ ๋ฆฌ๋ทฐ๋ฅผ ํ๋ ค ํด๋, ๊ฐ์๊ฐ ๋ง๋ ์ฝ๋๋ฅผ ๋ณธ์ธ๋ ์์ ํ ์ดํดํ์ง ๋ชปํ๊ธฐ ๋๋ฌธ์ ๋ฆฌ๋ทฐ๊ฐ ๋ถ๊ฐ๋ฅํ์ต๋๋ค. ๊ฒฐ๊ตญ CTO๊ฐ "์ด ํ๋ก์ ํธ๋ ์ ์ง๋ณด์๊ฐ ๋ถ๊ฐ๋ฅํ๋ค. ์ฒ์๋ถํฐ ๋ค์ ๋ง๋ค์"๋ ๊ฒฐ๋ก ์ ๋ด๋ ธ๊ณ , 6๊ฐ์์ ๊ฐ๋ฐ์ด ๋ฌผ๊ฑฐํ์ด ๋์์ต๋๋ค.
### ๐ ๋ฐ์ด๋ธ ์ฝ๋ฉ์ ์ญ์ค
**์๋์ ํ์ง์ ํธ๋ ์ด๋์คํ**: AI๊ฐ ์ฝ๋๋ฅผ ๋น ๋ฅด๊ฒ ์์ฑํด์ฃผ์ง๋ง, ๊ทธ ์ฝ๋๋ **์ ์ง๋ณด์ํ ์ ์๋ ๋ธ๋๋ฐ์ค**๊ฐ ๋ฉ๋๋ค. ์์ฐ์ฑ์ ๋์์ก๋๋ฐ ํ์ง์ ๋ฎ์์ง๋ ๋๋ ๋ง์ ๋น ์ง๋๋ค. 1์ฃผ์ผ ๋ง์ ๋ง๋ ํ๋กํ ํ์
์ด 3๊ฐ์ ๋์ ๊ธฐ์ ๋ถ์ฑ๋ฅผ ๋ง๋ค์ด๋
๋๋ค.
**๋จ๊ธฐ ์ด์ต, ์ฅ๊ธฐ ์ํด**: ์ฒ์์ "์, AI ๋๋ถ์ ๊ฐ๋ฐ์ด ๋นจ๋ผ์ก์ด!"๋ผ๊ณ ๊ธฐ๋ปํ์ง๋ง, 3๊ฐ์ ํ์ "์ด ์ฝ๋ ์ด๋ป๊ฒ ์ ์ง๋ณด์ํ์ง?"๋ผ๊ณ ๊ณ ๋ฏผํ๊ณ , 6๊ฐ์ ํ์ "์ฐจ๋ผ๋ฆฌ ์ฒ์๋ถํฐ ๋ค์ ๋ง๋ค๊น?"๋ผ๊ณ ์ข์ ํฉ๋๋ค.
**ํด๊ฒฐ์ฑ
์ ํ์์ฑ**: ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด, AI์ ์๋๋ ์ ์งํ๋ฉด์๋ ์ฝ๋์ **์ผ๊ด์ฑ, ํ์ง, ์ถ์ ์ฑ**์ ๋ณด์ฅํ๋ ์ฒด๊ณ์ ์ธ ๋ฐฉ๋ฒ๋ก ์ด ํ์ํฉ๋๋ค. ๋ฐ๋ก ์ฌ๊ธฐ์ **Alfred์ MoAI-ADK**๊ฐ ๋ฑ์ฅํฉ๋๋ค.
---
## โจ The Solution - MoAI-ADK's 3-Step Workflow
Alfred๋ Agentic AI ์๋์ ์ฝ๋ ํ์ง ๋ฌธ์ ๋ฅผ **์ฒด๊ณ์ ์ธ 3๋จ๊ณ MoAI-ADK ์ํฌํ๋ก์ฐ**๋ก ํด๊ฒฐํฉ๋๋ค. ๋ฐ์ด๋ธ ์ฝ๋ฉ์ ํผ๋์ **์ผ๊ด์ฑ, ํ์ง, ์ถ์ ์ฑ**์ด ๋ณด์ฅ๋๋ ์ฒด๊ณ์ ์ธ ํ๋ก์ธ์ค๋ก ์ ํํฉ๋๋ค.
์ด 3๋จ๊ณ ์ํฌํ๋ก์ฐ๋ ์ํํธ์จ์ด ๊ณตํ์ ์ค๋ ์งํ(๋ช
์ธ ์์ฑ, TDD, ๋ฌธ์ํ)๋ฅผ AI ์๋์ ๋ง๊ฒ ์ฌํด์ํ ๊ฒ์
๋๋ค. ์ฌ๋์ด ์ผ์ผ์ด ํ๊ธฐ์ ๋ฒ๊ฑฐ๋กญ์ง๋ง, AI ์์ด์ ํธ๊ฐ ์๋ํํ๋ฉด ๋๋ผ์ธ ์ ๋๋ก ํจ์จ์ ์
๋๋ค. ์ด์ **์ฝ๋/๋ฌธ์ ์์ฑ์ AI, ๊ฒํ ๋ ์ฌ๋ฌ๋ถ**์ด ํ์๋ฉด ๋ฉ๋๋ค.
```mermaid
graph LR
A[1๏ธโฃ SPEC] --> B[2๏ธโฃ BUILD]
B --> C[3๏ธโฃ SYNC]
C --> D[โ
Production Ready]
D -.๋ฐ๋ณต.-> A
```
### 1๏ธโฃ SPEC - ๋ช
์ธ ์์ฑ (Specification)
**๋ช
๋ น์ด**: `/alfred:1-spec "JWT ๊ธฐ๋ฐ ์ฌ์ฉ์ ๋ก๊ทธ์ธ API"`
**ํต์ฌ ์ฒ ํ**: "์ฝ๋๋ฅผ ์ฐ๊ธฐ ์ ์ ๋ฌด์์ ๋ง๋ค์ง ๋จผ์ ์ ์ํ๋ผ." SPEC ์์ด ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ง๋ ์์ด ์ฌํ์ ๋ ๋๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
**Alfred๊ฐ ์๋์ผ๋ก ์ํํ๋ ์์
**:
1. **EARS ํ์ ๋ช
์ธ ์๋ ์์ฑ**: Alfred๊ฐ ์ฌ๋ฌ๋ถ์ ๊ฐ๋จํ ์์ฒญ("JWT ๋ก๊ทธ์ธ")์ ๊ตฌ์กฐํ๋ EARS ๋ฌธ๋ฒ์ผ๋ก ๋ณํํฉ๋๋ค.
- **Ubiquitous**: "์์คํ
์ JWT ํ ํฐ ๊ธฐ๋ฐ ์ธ์ฆ์ ์ ๊ณตํด์ผ ํ๋ค"
- **Event-driven**: "WHEN ์ฌ์ฉ์๊ฐ ์ ํจํ ์ด๋ฉ์ผ/๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํ๋ฉด, ์์คํ
์ JWT ํ ํฐ์ ๋ฐ๊ธํด์ผ ํ๋ค"
- **State-driven**: "WHILE ํ ํฐ์ด ์ ํจํ ๋์, ์์คํ
์ ์ธ์ฆ๋ ์์ฒญ์ ํ์ฉํด์ผ ํ๋ค"
- **Constraints**: "IF ํ ํฐ์ด ๋ง๋ฃ๋์์ผ๋ฉด, ์์คํ
์ 401 ์๋ฌ๋ฅผ ๋ฐํํด์ผ ํ๋ค"
2. **`@SPEC:ID` TAG ๋ถ์ฌ**: ์๊ตฌ์ ์ธ ์ถ์ ID๋ฅผ ์์ฑํฉ๋๋ค (์: `@SPEC:AUTH-001`). ์ด ID๋ ์ ๋ ๋ณํ์ง ์์ผ๋ฉฐ, ์์ผ๋ก ๋ชจ๋ ํ
์คํธ, ์ฝ๋, ๋ฌธ์๊ฐ ์ด ID๋ฅผ ์ฐธ์กฐํฉ๋๋ค.
3. **Git ๋ธ๋์น ์๋ ์์ฑ**: `feature/SPEC-AUTH-001-jwt-login` ๋ธ๋์น๋ฅผ ๋ง๋ค๊ณ ์ ํํฉ๋๋ค. GitFlow ์ ๋ต์ ์๋์ผ๋ก ์ ์ฉํฉ๋๋ค.
4. **HISTORY ์น์
์๋ ์ถ๊ฐ**: ๋ณ๊ฒฝ ์ด๋ ฅ์ ์ถ์ ํฉ๋๋ค.
```yaml
## HISTORY
- v1.0.0 (2025-10-02): INITIAL - JWT ์ธ์ฆ SPEC ์ต์ด ์์ฑ
```
**์ค์ ์์ฑ๋๋ ํ์ผ ์์** (`.moai/specs/SPEC-AUTH-001.md`):
```markdown
---
id: AUTH-001
title: JWT ๊ธฐ๋ฐ ์ฌ์ฉ์ ๋ก๊ทธ์ธ API
version: 1.0.0
status: Draft
created: 2025-10-02
author: AI Alfred
tags: [authentication, jwt, api]
---
# @SPEC:AUTH-001 | JWT ๊ธฐ๋ฐ ์ฌ์ฉ์ ๋ก๊ทธ์ธ API
## ์๊ตฌ์ฌํญ (EARS)
### Ubiquitous
- ์์คํ
์ JWT ํ ํฐ ๊ธฐ๋ฐ ์ฌ์ฉ์ ์ธ์ฆ์ ์ ๊ณตํด์ผ ํ๋ค
### Event-driven
- WHEN ์ฌ์ฉ์๊ฐ POST /api/auth/login์ ์ด๋ฉ์ผ/๋น๋ฐ๋ฒํธ๋ฅผ ์ ์กํ๋ฉด
- ์์คํ
์ DB์์ ์ฌ์ฉ์๋ฅผ ์กฐํํด์ผ ํ๋ค
- ๋น๋ฐ๋ฒํธ๊ฐ ์ผ์นํ๋ฉด JWT ํ ํฐ์ ์์ฑํด์ผ ํ๋ค
- ์๋ต์ผ๋ก { token, expiresIn } JSON์ ๋ฐํํด์ผ ํ๋ค
### Constraints
- IF ์ด๋ฉ์ผ์ด ์กด์ฌํ์ง ์์ผ๋ฉด, 404 ์๋ฌ๋ฅผ ๋ฐํํด์ผ ํ๋ค
- IF ๋น๋ฐ๋ฒํธ๊ฐ ํ๋ฆฌ๋ฉด, 401 ์๋ฌ๋ฅผ ๋ฐํํด์ผ ํ๋ค
- IF ํ ํฐ ๋ง๋ฃ ์๊ฐ์ 24์๊ฐ์ด์ด์ผ ํ๋ค
## HISTORY
- v1.0.0 (2025-10-02): INITIAL - JWT ์ธ์ฆ SPEC ์ต์ด ์์ฑ
```
**Why it matters**: 6๊ฐ์ ํ ๋๊ตฐ๊ฐ "์ ํ ํฐ ๋ง๋ฃ ์๊ฐ์ด 24์๊ฐ์ด์ง?"๋ผ๊ณ ๋ฌผ์ด๋ณด๋ฉด, SPEC ๋ฌธ์๋ฅผ ์ด์ด HISTORY๋ฅผ ํ์ธํ๋ฉด ๋ฉ๋๋ค. "์, v1.0.0์์ ๋ณด์ํ ์๊ตฌ์ฌํญ์ผ๋ก 24์๊ฐ์ผ๋ก ๊ฒฐ์ ๋์๊ตฌ๋" ๊ฐ์ ๋งฅ๋ฝ์ ์ฆ์ ํ์
ํ ์ ์์ต๋๋ค.
### 2๏ธโฃ BUILD - TDD ๊ตฌํ (Test-Driven Development)
**๋ช
๋ น์ด**: `/alfred:2-build AUTH-001`
**ํต์ฌ ์ฒ ํ**: "ํ
์คํธ๋ฅผ ๋จผ์ ์์ฑํ๊ณ , ๊ทธ ๋ค์ ์ฝ๋๋ฅผ ์์ฑํ๋ผ." TDD๋ ์ฝ๋์ ์์ ๋ง์ด์, ์ด์์๋ ๋ฌธ์์ด๋ฉฐ, ๋ฆฌํฉํ ๋ง์ ์์ ๊ฐ์
๋๋ค.
**Alfred๊ฐ ์ํํ๋ TDD ์ฌ์ดํด**:
```mermaid
graph LR
A[SPEC ์ฝ๊ธฐ] --> B[๐ด RED
ํ
์คํธ ์์ฑ]
B --> C{ํ
์คํธ ์คํ}
C -->|์คํจ| D[๐ข GREEN
์ต์ ๊ตฌํ]
D --> E{ํ
์คํธ ์คํ}
E -->|ํต๊ณผ| F[๐ต REFACTOR
์ฝ๋ ๊ฐ์ ]
F --> G{ํ
์คํธ ์คํ}
G -->|ํต๊ณผ| H[โ
์๋ฃ]
G -->|์คํจ| F
style A fill:#e1f5ff
style B fill:#ffcdd2
style D fill:#c8e6c9
style F fill:#bbdefb
style H fill:#fff9c4
```
#### ๐ด RED Phase - ์คํจํ๋ ํ
์คํธ ์์ฑ
Alfred๊ฐ SPEC์ ์ฝ๊ณ ํ
์คํธ ์ฝ๋๋ฅผ ๋จผ์ ์์ฑํฉ๋๋ค (`@TEST:AUTH-001`).
```typescript
// tests/auth/login.test.ts
// @TEST:AUTH-001 | SPEC: SPEC-AUTH-001.md
import { describe, it, expect } from 'vitest';
import { loginUser } from '@/services/auth';
describe('JWT ๋ก๊ทธ์ธ API', () => {
it('์ ํจํ ์ด๋ฉ์ผ/๋น๋ฐ๋ฒํธ๋ก ๋ก๊ทธ์ธ ์ JWT ํ ํฐ์ ๋ฐํํ๋ค', async () => {
const result = await loginUser('user@example.com', 'password123');
expect(result.token).toBeDefined();
expect(result.expiresIn).toBe(86400); // 24์๊ฐ = 86400์ด
expect(result.token).toMatch(/^eyJ/); // JWT ํ์ ํ์ธ
});
it('์กด์ฌํ์ง ์๋ ์ด๋ฉ์ผ๋ก ๋ก๊ทธ์ธ ์ 404 ์๋ฌ', async () => {
await expect(
loginUser('nonexistent@example.com', 'password')
).rejects.toThrow('User not found');
});
it('ํ๋ฆฐ ๋น๋ฐ๋ฒํธ๋ก ๋ก๊ทธ์ธ ์ 401 ์๋ฌ', async () => {
await expect(
loginUser('user@example.com', 'wrongpassword')
).rejects.toThrow('Invalid password');
});
});
// TDD History:
// - 2025-10-02: RED - ํ
์คํธ ์ต์ด ์์ฑ (๋น์ฐํ ์คํจ)
```
์ด ํ
์คํธ๋ฅผ ์คํํ๋ฉด **๋น์ฐํ ์คํจ**ํฉ๋๋ค. ์์ง `loginUser` ํจ์๋ฅผ ๊ตฌํํ์ง ์์์ผ๋๊น์. ์ด๊ฒ์ด RED ๋จ๊ณ์
๋๋ค.
#### ๐ข GREEN Phase - ์ต์ ๊ตฌํ์ผ๋ก ํ
์คํธ ํต๊ณผ
์ด์ Alfred๊ฐ ํ
์คํธ๋ฅผ ํต๊ณผ์ํค๋ **์ต์ํ์ ์ฝ๋**๋ง ์์ฑํฉ๋๋ค (`@CODE:AUTH-001`).
```typescript
// src/services/auth.ts
// @CODE:AUTH-001 | SPEC: SPEC-AUTH-001.md | TEST: tests/auth/login.test.ts
import jwt from 'jsonwebtoken';
import bcrypt from 'bcrypt';
import { getUserByEmail } from '@/db/users';
export async function loginUser(email: string, password: string) {
// ์ฌ์ฉ์ ์กฐํ
const user = await getUserByEmail(email);
if (!user) {
throw new Error('User not found'); // 404
}
// ๋น๋ฐ๋ฒํธ ๊ฒ์ฆ
const isValid = await bcrypt.compare(password, user.hashedPassword);
if (!isValid) {
throw new Error('Invalid password'); // 401
}
// JWT ํ ํฐ ์์ฑ
const token = jwt.sign(
{ userId: user.id, email: user.email },
process.env.JWT_SECRET!,
{ expiresIn: '24h' } // 24์๊ฐ
);
return {
token,
expiresIn: 86400 // 24์๊ฐ = 86400์ด
};
}
// TDD History:
// - 2025-10-02: GREEN - ํ
์คํธ ํต๊ณผํ๋ ์ต์ ๊ตฌํ
```
ํ
์คํธ๋ฅผ ๋ค์ ์คํํ๋ฉด **๋ชจ๋ ํต๊ณผ**ํฉ๋๋ค. ์ด๊ฒ์ด GREEN ๋จ๊ณ์
๋๋ค.
#### ๐ต REFACTOR Phase - ์ฝ๋ ํ์ง ๊ฐ์
์ด์ Alfred๊ฐ ์ฝ๋๋ฅผ ๋ฆฌํฉํ ๋งํ์ฌ ํ์ง์ ๋์
๋๋ค. TRUST 5์์น์ ์ ์ฉํฉ๋๋ค.
```typescript
// src/services/auth.ts
// @CODE:AUTH-001 | SPEC: SPEC-AUTH-001.md | TEST: tests/auth/login.test.ts
import jwt from 'jsonwebtoken';
import bcrypt from 'bcrypt';
import { getUserByEmail } from '@/db/users';
import { UnauthorizedError, NotFoundError } from '@/errors';
const TOKEN_EXPIRY = '24h';
const TOKEN_EXPIRY_SECONDS = 86400;
interface LoginResult {
token: string;
expiresIn: number;
}
export async function loginUser(
email: string,
password: string
): Promise {
// ์
๋ ฅ ๊ฒ์ฆ (Secured)
if (!email || !password) {
throw new UnauthorizedError('Email and password required');
}
// ์ฌ์ฉ์ ์กฐํ
const user = await getUserByEmail(email);
if (!user) {
throw new NotFoundError('User not found');
}
// ๋น๋ฐ๋ฒํธ ๊ฒ์ฆ
const isValid = await verifyPassword(password, user.hashedPassword);
if (!isValid) {
throw new UnauthorizedError('Invalid password');
}
// JWT ํ ํฐ ์์ฑ
const token = generateJwtToken(user);
return {
token,
expiresIn: TOKEN_EXPIRY_SECONDS
};
}
// ์์ ํจ์๋ก ๋ถ๋ฆฌ (Readable)
async function verifyPassword(
plain: string,
hashed: string
): Promise {
return bcrypt.compare(plain, hashed);
}
function generateJwtToken(user: User): string {
return jwt.sign(
{ userId: user.id, email: user.email },
getJwtSecret(),
{ expiresIn: TOKEN_EXPIRY }
);
}
function getJwtSecret(): string {
const secret = process.env.JWT_SECRET;
if (!secret) {
throw new Error('JWT_SECRET not configured');
}
return secret;
}
// TDD History:
// - 2025-10-02: RED - ํ
์คํธ ์ต์ด ์์ฑ
// - 2025-10-02: GREEN - ํ
์คํธ ํต๊ณผ
// - 2025-10-02: REFACTOR - ํจ์ ๋ถ๋ฆฌ, ํ์
์ถ๊ฐ, ์๋ฌ ์ฒ๋ฆฌ ๊ฐ์
```
ํ
์คํธ๋ฅผ ๋ค์ ์คํํ๋ฉด **์ฌ์ ํ ํต๊ณผ**ํฉ๋๋ค. ๋ฆฌํฉํ ๋ง์ ์ธ๋ถ ๋์์ ๋ฐ๊พธ์ง ์๊ณ ๋ด๋ถ ๊ตฌ์กฐ๋ง ๊ฐ์ ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
**Why it matters**: ํ
์คํธ๊ฐ ์์ ๋ง ์ญํ ์ ํฉ๋๋ค. ๋์ค์ ๋๊ตฐ๊ฐ ์ด ์ฝ๋๋ฅผ ์์ ํ๋๋ผ๋, ํ
์คํธ๊ฐ ๊นจ์ง๋ฉด ์ฆ์ ์ ์ ์์ต๋๋ค. "๋ฆฌํฉํ ๋ง์ ์ํํด"๊ฐ ์๋๋ผ "ํ
์คํธ๋ง ํต๊ณผํ๋ฉด ์์ ํด"๋ก ๋ฐ๋๋๋ค.
### 3๏ธโฃ SYNC - ๋ฌธ์ ๋๊ธฐํ (Synchronization)
**๋ช
๋ น์ด**: `/alfred:3-sync`
**ํต์ฌ ์ฒ ํ**: "์ฝ๋์ ๋ฌธ์๋ ํญ์ ๋๊ธฐํ๋์ด์ผ ํ๋ค." ๋ฌธ์๊ฐ outdated๋๋ ์๊ฐ, ์๋ฌด๋ ๋ฌธ์๋ฅผ ๋ฏฟ์ง ์๊ฒ ๋ฉ๋๋ค.
**Alfred๊ฐ ์๋์ผ๋ก ์ํํ๋ ์์
**:
1. **TAG ์ฒด์ธ ๊ฒ์ฆ**: `@SPEC:AUTH-001` โ `@TEST:AUTH-001` โ `@CODE:AUTH-001` ์ฒด์ธ์ด ์์ ํ์ง ๊ฒ์ฆํฉ๋๋ค.
```bash
โ
SPEC-AUTH-001.md์ @SPEC:AUTH-001 ์กด์ฌ
โ
tests/auth/login.test.ts์ @TEST:AUTH-001 ์กด์ฌ
โ
src/services/auth.ts์ @CODE:AUTH-001 ์กด์ฌ
โ
TAG ์ฒด์ธ ์์ ํจ
```
2. **๊ณ ์ TAG ์๋ ํ์ง**: SPEC ์์ด CODE๋ง ์๊ฑฐ๋, TEST ์์ด CODE๋ง ์๋ ๊ฒฝ์ฐ๋ฅผ ์ฐพ์๋
๋๋ค.
```bash
โ ๏ธ ๊ฒฝ๊ณ : @CODE:PAYMENT-005๊ฐ src/payment.ts์ ์์ง๋ง
@SPEC:PAYMENT-005๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค
โ ๊ณ ์ TAG ๋ฐ๊ฒฌ! ๋ฌธ์ํ ํ์
```
3. **Living Document ์๋ ์์ฑ**: ์ฝ๋์์ ์ถ์ถํ ์ ๋ณด๋ก ์ต์ ๋ฌธ์๋ฅผ ์์ฑํฉ๋๋ค (`docs/api/auth.md`).
```markdown
# ์ธ์ฆ API ๋ฌธ์
๋ง์ง๋ง ์
๋ฐ์ดํธ: 2025-10-02 (์ฝ๋์ ์๋ ๋๊ธฐํ๋จ)
## POST /api/auth/login
JWT ํ ํฐ ๊ธฐ๋ฐ ์ฌ์ฉ์ ๋ก๊ทธ์ธ
- SPEC: SPEC-AUTH-001.md
- ๊ตฌํ: src/services/auth.ts
- ํ
์คํธ: tests/auth/login.test.ts
### ์์ฒญ
```json
{
"email": "user@example.com",
"password": "password123"
}
```
### ์๋ต (200 OK)
```json
{
"token": "eyJhbGc...",
"expiresIn": 86400
}
```
### ์๋ฌ
- 404: ์ฌ์ฉ์๋ฅผ ์ฐพ์ ์ ์์
- 401: ๋น๋ฐ๋ฒํธ๊ฐ ํ๋ฆผ
```
4. **PR ์ํ ์ ํ**: GitHub PR์ Draft์์ Ready for Review๋ก ์ ํํฉ๋๋ค.
```bash
๐ PR #42 ์ํ ๋ณ๊ฒฝ: Draft โ Ready for Review
๐ ๋ฆฌ๋ทฐ์ด: @team-lead, @security-team ์๋ ํ ๋น
```
**Why it matters**: ์ฝ๋์ ๋ฌธ์๊ฐ ํญ์ ๋๊ธฐํ๋์ด ์ถ์ ์ฑ์ด 100% ๋ณด์ฅ๋ฉ๋๋ค. 6๊ฐ์ ํ์๋ "์ด API๊ฐ ์ด๋ป๊ฒ ์๋ํ์ง?"๋ฅผ ๊ถ๊ธํดํ์ง ์์๋ ๋ฉ๋๋ค. Living Document๋ฅผ ์ด์ด๋ณด๋ฉด ์ต์ ์ ๋ณด๊ฐ ์์ต๋๋ค.
---
**3๋จ๊ณ ์ํฌํ๋ก์ฐ์ ์ ์ํ**:
```
SPEC (๋ฌด์์) โ BUILD (์ด๋ป๊ฒ + ๊ฒ์ฆ) โ SYNC (์ถ์ ์ฑ ๋ณด์ฅ)
โ
๋ค์ SPEC
```
์ด ์ฌ์ดํด์ ๋ฐ๋ณตํ๋ฉด ํ ์๋ก ์ฝ๋๋ฒ ์ด์ค๋ ๋ ์ฒด๊ณ์ ์ด๊ณ , ๋ ์์ ํ๊ณ , ๋ ์ถ์ ๊ฐ๋ฅํด์ง๋๋ค. ๋ฐ์ด๋ธ ์ฝ๋ฉ์ ํผ๋์์ ๋ฒ์ด๋ **์์ง๋์ด๋ง์ ํ๊ฒฉ**์ ๋์ฐพ์ต๋๋ค.
---
## ๐๏ธ How Alfred Works - 10๊ฐ AI ์์ด์ ํธ ํ
MoAI-ADK๋ **Alfred (SuperAgent) + 9๊ฐ ์ ๋ฌธ ์์ด์ ํธ = ์ด 10๊ฐ AI ์์ด์ ํธ**๋ก ๊ตฌ์ฑ๋ ์์ด์ ํฑ ์ฝ๋ฉ ํ์
๋๋ค. ๊ฐ ์์ด์ ํธ๋ IT ์
๊ณ์ ์ค์ ์ง๋ฌด์ ๋งคํ๋์ด ๋ช
ํํ ์ญํ ์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
### โถโ Alfred - SuperAgent (1๋ฒ์งธ ์์ด์ ํธ)
**์ญํ **: ์ค์ ์ค์ผ์คํธ๋ ์ดํฐ (Central Orchestrator)
**์ฑ
์**:
- ์ฌ์ฉ์ ์์ฒญ ๋ถ์ ๋ฐ ์์
๋ถํด
- ์ ์ ํ ์ ๋ฌธ ์์ด์ ํธ ์ ํ ๋ฐ ์กฐ์จ
- ์์ด์ ํธ ๊ฐ ํ์
๊ด๋ฆฌ
- ํ์ง ๊ฒ์ดํธ ๊ฒ์ฆ ๋ฐ ๊ฒฐ๊ณผ ํตํฉ
**์๋ ๋ฐฉ์**:
```mermaid
graph TD
A[์ฌ์ฉ์ ์์ฒญ] --> B[Alfred ๋ถ์]
B --> C{์์
๋ณต์ก๋}
C -->|๊ฐ๋จ| D[์ง์ ์ฒ๋ฆฌ]
C -->|๋จ์ผ| E[Single Agent ์์]
C -->|์์ฐจ| F[Sequential ์กฐ์จ]
C -->|๋ณ๋ ฌ| G[Parallel ์กฐ์จ]
D --> H[๊ฒฐ๊ณผ ๋ฐํ]
E --> I[์์ด์ ํธ ์คํ]
F --> J[์์ฐจ ์คํ
1-spec โ 2-build โ 3-sync]
G --> K[๋ณ๋ ฌ ์คํ
test + lint + build]
I --> L[ํ์ง ๊ฒ์ดํธ ๊ฒ์ฆ]
J --> L
K --> L
L --> M[Alfred ๊ฒฐ๊ณผ ํตํฉ]
M --> H
style A fill:#e1f5ff
style B fill:#fff4e1
style H fill:#e8f5e9
style L fill:#fce4ec
```
---
### ์ ๋ฌธ๊ฐ AI ์๋ธ ์์ด์ ํธ
Alfred๊ฐ ์กฐ์จํ๋ ์ ๋ฌธ AI ์์ด์ ํธ๋ค์
๋๋ค.
#### ํต์ฌ 3๋จ๊ณ ์์ด์ ํธ (์๋ ํธ์ถ)
| ์์ด์ ํธ | ํ๋ฅด์๋ | ์ ๋ฌธ ์์ญ | ํธ์ถ ์์ |
| ------------------ | --------------- | -------------- | ----------------- |
| **spec-builder** ๐๏ธ | ์์คํ
์ํคํ
ํธ | EARS ๋ช
์ธ ์์ฑ | `/alfred:1-spec` |
| **code-builder** ๐ | ์์ ๊ฐ๋ฐ์ | TDD ๊ตฌํ | `/alfred:2-build` |
| **doc-syncer** ๐ | ํ
ํฌ๋์ปฌ ๋ผ์ดํฐ | ๋ฌธ์ ๋๊ธฐํ | `/alfred:3-sync` |
#### ํ์ง ๋ณด์ฆ ์์ด์ ํธ (์จ๋๋งจ๋)
| ์์ด์ ํธ | ํ๋ฅด์๋ | ์ ๋ฌธ ์์ญ | ํธ์ถ ๋ฐฉ๋ฒ |
| ------------------- | --------------- | -------------- | ---------------------- |
| **tag-agent** ๐ท๏ธ | ์ง์ ๊ด๋ฆฌ์ | TAG ์ฒด์ธ ๊ฒ์ฆ | `@agent-tag-agent` |
| **debug-helper** ๐ฌ | SRE ์ ๋ฌธ๊ฐ | ์ค๋ฅ ์ง๋จ | `@agent-debug-helper` |
| **trust-checker** โ
| QA ๋ฆฌ๋ | TRUST ๊ฒ์ฆ | `@agent-trust-checker` |
| **git-manager** ๐ | ๋ฆด๋ฆฌ์ค ์์ง๋์ด | Git ์ํฌํ๋ก์ฐ | `@agent-git-manager` |
#### ์์คํ
๊ด๋ฆฌ ์์ด์ ํธ
| ์์ด์ ํธ | ํ๋ฅด์๋ | ์ ๋ฌธ ์์ญ | ํธ์ถ ๋ฐฉ๋ฒ |
| --------------------- | ----------------- | ---------------- | ------------------- |
| **cc-manager** ๐ ๏ธ | ๋ฐ๋ธ์ต์ค ์์ง๋์ด | Claude Code ์ค์ | `@agent-cc-manager` |
| **project-manager** ๐ | ํ๋ก์ ํธ ๋งค๋์ | ํ๋ก์ ํธ ์ด๊ธฐํ | `/alfred:8-project` |
### ์์ด์ ํธ ํ์
์ํคํ
์ฒ
```mermaid
graph TB
Alfred["โถโ Alfred
(SuperAgent)
์ค์ ์ค์ผ์คํธ๋ ์ดํฐ"]
subgraph core["ํต์ฌ 3๋จ๊ณ ์์ด์ ํธ"]
Spec["๐๏ธ spec-builder
๋ช
์ธ ์์ฑ"]
Code["๐ code-builder
TDD ๊ตฌํ"]
Doc["๐ doc-syncer
๋ฌธ์ ๋๊ธฐํ"]
end
subgraph quality["ํ์ง ๋ณด์ฆ ์์ด์ ํธ"]
Tag["๐ท๏ธ tag-agent
TAG ๊ฒ์ฆ"]
Trust["โ
trust-checker
TRUST ๊ฒ์ฆ"]
Debug["๐ฌ debug-helper
์ค๋ฅ ์ง๋จ"]
Git["๐ git-manager
Git ์ํฌํ๋ก์ฐ"]
end
subgraph system["์์คํ
๊ด๋ฆฌ ์์ด์ ํธ"]
CC["๐ ๏ธ cc-manager
์ค์ ๊ด๋ฆฌ"]
PM["๐ project-manager
ํ๋ก์ ํธ ์ด๊ธฐํ"]
end
Alfred --> core
Alfred --> quality
Alfred --> system
style Alfred fill:#fff4e1,stroke:#333,stroke-width:3px
style core fill:#e1f5ff
style quality fill:#fce4ec
style system fill:#e8f5e9
```
### ํ์
์์น
**๋จ์ผ ์ฑ
์ (Single Responsibility)**:
- ๊ฐ ์์ด์ ํธ๋ ์์ ์ ์ ๋ฌธ ์์ญ๋ง ๋ด๋น
- ๋ค๋ฅธ ์์ด์ ํธ์ ์์ญ์ ์นจ๋ฒํ์ง ์์
**์ค์ ์กฐ์จ (Central Orchestration)**:
- Alfred๋ง์ด ์์ด์ ํธ ๊ฐ ์์
์ ์กฐ์จ
- ์์ด์ ํธ๋ผ๋ฆฌ ์ง์ ํธ์ถ ๊ธ์ง
**ํ์ง ๊ฒ์ดํธ (Quality Gates)**:
- ๊ฐ ๋จ๊ณ ์๋ฃ ์ TRUST ์์น ์๋ ๊ฒ์ฆ
- TAG ๋ฌด๊ฒฐ์ฑ ์๋ ํ์ธ
---
### TRUST 5์์น (ํ์ง ๋ณด์ฆ)
Alfred๋ ๋ชจ๋ ์ฝ๋์ TRUST 5์์น์ ์ ์ฉํฉ๋๋ค:
#### T - Test First
- SPEC โ Test โ Code ์์ ์์
- ํ
์คํธ ์ปค๋ฒ๋ฆฌ์ง โฅ 85%
#### R - Readable
- ํ์ผ โค300 LOC, ํจ์ โค50 LOC
- ๋ณต์ก๋ โค10, ๋งค๊ฐ๋ณ์ โค5๊ฐ
#### U - Unified
- SPEC ๊ธฐ๋ฐ ์ํคํ
์ฒ
- ํ์
์์ ์ฑ ๋ณด์ฅ
#### S - Secured
- ์
๋ ฅ ๊ฒ์ฆ, SQL Injection ๋ฐฉ์ด
- XSS/CSRF ๋ฐฉ์ด, ๋น๋ฐ๋ฒํธ ํด์ฑ
#### T - Trackable
- CODE-FIRST @TAG ์์คํ
- ์์ ํ ์ถ์ ์ฒด์ธ ๋ณด์ฅ
### @TAG ์์คํ
๋ชจ๋ ์ฝ๋๋ 4๊ฐ์ง TAG๋ก ์๋ฒฝํ๊ฒ ์ถ์ ๋ฉ๋๋ค:
```mermaid
graph LR
A["@SPEC:AUTH-001
.moai/specs/SPEC-AUTH-001.md
์๊ตฌ์ฌํญ ๋ช
์ธ"]
B["@TEST:AUTH-001
tests/auth/login.test.ts
ํ
์คํธ ์ฝ๋"]
C["@CODE:AUTH-001
src/services/auth.ts
๊ตฌํ ์ฝ๋"]
D["@DOC:AUTH-001
docs/api/auth.md
API ๋ฌธ์"]
A -->|์ฐธ์กฐ| B
B -->|์ฐธ์กฐ| C
C -->|์ฐธ์กฐ| D
E[TAG ์ฒด์ธ ๊ฒ์ฆ
rg '@SPEC:AUTH-001' -n] -.->|์ค์บ| A
E -.->|์ค์บ| B
E -.->|์ค์บ| C
E -.->|์ค์บ| D
style A fill:#e1f5ff
style B fill:#ffcdd2
style C fill:#c8e6c9
style D fill:#fff9c4
style E fill:#f3e5f5
```
**TAG ID ๊ท์น**: `<๋๋ฉ์ธ>-<3์๋ฆฌ>` (์: `AUTH-001`, `PAYMENT-042`)
**๊ฒ์ฆ ๋ฐฉ๋ฒ**:
```bash
# ์ ์ฒด TAG ์ค์บ
rg '@(SPEC|TEST|CODE|DOC):' -n
# ํน์ TAG ์ถ์
rg 'AUTH-001' -n
```
---
## ๐จ Alfred's Output Styles
Alfred๋ ๊ฐ๋ฐ ์ํฉ์ ๋ฐ๋ผ **4๊ฐ์ง ๋ํ ์คํ์ผ**์ ์ ๊ณตํฉ๋๋ค. Claude Code์์ `/output-style` ๋ช
๋ น์ด๋ก ์ธ์ ๋ ์ ํํ ์ ์์ต๋๋ค.
### ๐ ์ ๊ณต๋๋ Output Styles
| ์คํ์ผ ์ด๋ฆ | ์ค๋ช
|
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **MoAI Professional** | SPEC-First TDD ์ ๋ฌธ๊ฐ๋ฅผ ์ํ ๊ฐ๊ฒฐํ๊ณ ๊ธฐ์ ์ ์ธ ๊ฐ๋ฐ ์คํ์ผ. Alfred SuperAgent๊ฐ 9๊ฐ ์ ๋ฌธ ์์ด์ ํธ๋ฅผ ์กฐ์จํ์ฌ TRUST 5์์น๊ณผ @TAG ์ถ์ ์ฑ์ ์๋ ์ ์ฉํฉ๋๋ค. |
| **MoAI Beginner Learning** | ๊ฐ๋ฐ ์ด๋ณด์๋ฅผ ์ํ ์์ธํ๊ณ ์น์ ํ ๋จ๊ณ๋ณ ํ์ต ๊ฐ์ด๋ (ํ์ต ์ ์ฉ) |
| **MoAI Pair Collaboration** | AI์ ํจ๊ป ๋ธ๋ ์ธ์คํ ๋ฐ, ๊ณํ ์๋ฆฝ, ์ค์๊ฐ ์ฝ๋ ๋ฆฌ๋ทฐ๋ฅผ ์งํํ๋ ํ์
๋ชจ๋. Alfred SuperAgent๊ฐ 9๊ฐ ์ ๋ฌธ ์์ด์ ํธ๋ฅผ ์กฐ์จํ์ฌ ์ต์ ์ ํ์
๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค. |
| **MoAI Study Deep** | ์๋ก์ด ๊ฐ๋
, ๋๊ตฌ, ์ธ์ด, ํ๋ ์์ํฌ๋ฅผ ์ฒด๊ณ์ ์ผ๋ก ํ์ตํ๋ ์ฌํ ๊ต์ก ๋ชจ๋. Alfred SuperAgent๊ฐ 9๊ฐ ์ ๋ฌธ ์์ด์ ํธ์ ์ ๋ฌธ ์ง์์ ํ์ฉํ์ฌ ๊น์ด ์๋ ํ์ต ๊ฒฝํ์ ์ ๊ณตํฉ๋๋ค. |
### ๐ ์คํ์ผ ์ ํ ๋ฐฉ๋ฒ
Claude Code์์ `/output-style` ๋ช
๋ น์ด๋ก ์ ํ:
```bash
/output-style alfred-pro # MoAI Professional (๊ธฐ๋ณธ๊ฐ)
/output-style beginner-learning # MoAI Beginner Learning
/output-style pair-collab # MoAI Pair Collaboration
/output-style study-deep # MoAI Study Deep
```
### ๐ฏ ์คํ์ผ ์ ํ ๊ฐ์ด๋
| ์ํฉ | ์ถ์ฒ ์คํ์ผ | ๋์ | ํน์ง |
| ------------------------ | ------------------- | -------------------------- | ---------------------------- |
| ์ค๋ฌด ํ๋ก์ ํธ ๋น ๋ฅธ ๊ฐ๋ฐ | `alfred-pro` | ์ค๋ฌด ๊ฐ๋ฐ์, ํ๋ก์ ํธ ๋ฆฌ๋ | ๊ฐ๊ฒฐ, ๊ธฐ์ ์ , ๊ฒฐ๊ณผ ์ค์ฌ |
| ํ๋ก๊ทธ๋๋ฐ ์ฒ์ ๋ฐฐ์ฐ๊ธฐ | `beginner-learning` | ๊ฐ๋ฐ ์
๋ฌธ์ | ์น์ , ์์ธ ์ค๋ช
, ๋จ๊ณ๋ณ ์๋ด |
| ํ ๊ธฐ์ ์ ํ & ์ค๊ณ ๋
ผ์ | `pair-collab` | ํ์
๊ฐ๋ฐ์, ์ํคํ
ํธ | ์ง๋ฌธ ๊ธฐ๋ฐ, ๋ธ๋ ์ธ์คํ ๋ฐ |
| ์๋ก์ด ๊ธฐ์ ํ์ต | `study-deep` | ์ ๊ธฐ์ ํ์ต์ | ๊ฐ๋
โ ์ค์ต โ ์ ๋ฌธ๊ฐ ํ |
### ๐ก ๋ชจ๋ ์คํ์ผ์์ ๋์ผํ๊ฒ ์๋
- โ
9๊ฐ ์ ๋ฌธ ์์ด์ ํธ ์กฐ์จ
- โ
SPEC-First TDD ์ํฌํ๋ก์ฐ
- โ
TRUST 5์์น ์๋ ๊ฒ์ฆ
- โ
@TAG ์ถ์ ์ฑ ๋ณด์ฅ
**์ฐจ์ด์ ์ ์ค์ง ์ค๋ช
๋ฐฉ์**:
- ๐ ๊ฐ๊ฒฐ vs ์์ธ
- ๐ ๋น ๋ฅธ ๊ตฌํ vs ๊ฐ๋
ํ์ต
- ๐ฌ ๊ธฐ์ ์ vs ์น์ vs ํ์
์ vs ๊ต์ก์
---
### 1๏ธโฃ MoAI Professional
**๋ช
๋ น์ด**: `/output-style alfred-pro`
**์๋ต ๋ฐฉ์**: ๊ฐ๊ฒฐ, ๊ฒฐ๊ณผ ์ค์ฌ, ์ต์ ์ค๋ช
**๋์**: ์ค๋ฌด ๊ฐ๋ฐ์, ํ๋ก์ ํธ ๋ฆฌ๋, SPEC-First TDD ์ ๋ฌธ๊ฐ
์ถ๋ ฅ ์์
```
JWT ์ธ์ฆ ๊ตฌํ ์์.
/alfred:1-spec "JWT ๊ธฐ๋ฐ ์ฌ์ฉ์ ์ธ์ฆ API"
โ
SPEC-AUTH-001.md ์์ฑ
โ
feature/SPEC-AUTH-001-jwt-auth ๋ธ๋์น ์์ฑ
/alfred:2-build AUTH-001
๐ด RED: tests/auth/jwt.test.ts (์ปค๋ฒ๋ฆฌ์ง: 90%)
๐ข GREEN: src/auth/jwt.service.ts, src/middleware/auth.middleware.ts
๐ต REFACTOR: TRUST ๊ฒ์ฆ ์๋ฃ, ๋ณต์ก๋โค10, LOCโค50
/alfred:3-sync
โ
@SPEC โ @TEST โ @CODE ์ฒด์ธ ๊ฒ์ฆ
โ
docs/api/auth.md ์์ฑ
โ
PR #42 Ready for Review
๊ตฌํ ์๋ฃ.
```
---
### 2๏ธโฃ MoAI Beginner Learning
**๋ช
๋ น์ด**: `/output-style beginner-learning`
**์๋ต ๋ฐฉ์**: ์์ธํ ๋จ๊ณ๋ณ ์ค๋ช
, ๊ฐ๋
๋จผ์ ์ค๋ช
**๋์**: ๊ฐ๋ฐ ์
๋ฌธ์ ๋ฐ ํ๋ก๊ทธ๋๋ฐ ์ด๋ณด์ (ํ์ต ์ ์ฉ)
์ถ๋ ฅ ์์
```
JWT ์ธ์ฆ ๊ตฌํ์ ์์ํฉ๋๋ค.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ฏ ๋ชฉํ: JWT ๊ธฐ๋ฐ ๋ก๊ทธ์ธ ์์คํ
๊ตฌํ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
**JWT (JSON Web Token)**
์ฌ์ฉ์ ์ธ์ฆ์ ์ํ ํ ํฐ ๊ธฐ๋ฐ ๋ฐฉ์.
๋ก๊ทธ์ธ ์ ํ ํฐ์ ๋ฐ๊ธํ๊ณ , ์ดํ ์์ฒญ์์ ํ ํฐ์ผ๋ก ์ธ์ฆ ํ์ธ.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ 1๋จ๊ณ: SPEC ์์ฑ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๊ตฌํ ์ ์ ๋ช
์ธ๋ฅผ ๋จผ์ ์์ฑํฉ๋๋ค.
/alfred:1-spec "JWT ๊ธฐ๋ฐ ์ฌ์ฉ์ ์ธ์ฆ API"
โ
.moai/specs/SPEC-AUTH-001.md ์์ฑ
โ ์๊ตฌ์ฌํญ, ์ ์ฝ์ฌํญ, ํ
์คํธ ์๋๋ฆฌ์ค ํฌํจ
โ ๋์ค์ "์ ์ด๋ ๊ฒ ๋ง๋ค์์ง?" ๊ถ๊ธํ ๋ ์ฐธ์กฐ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐งช 2๋จ๊ณ: TDD ๊ตฌํ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
ํ
์คํธ๋ฅผ ๋จผ์ ์์ฑํ๊ณ , ๊ทธ ๋ค์ ์ฝ๋๋ฅผ ์์ฑํฉ๋๋ค.
/alfred:2-build AUTH-001
๐ด RED (ํ
์คํธ ์์ฑ):
- tests/auth/jwt.test.ts ์์ฑ
- ์์ง ๊ตฌํ ์ฝ๋๊ฐ ์์ด์ ์คํจ (์ ์)
๐ข GREEN (์ต์ ๊ตฌํ):
- src/auth/jwt.service.ts ์์ฑ
- ํ
์คํธ ํต๊ณผํ๋ ์ต์ ์ฝ๋ ์์ฑ
๐ต REFACTOR (์ฝ๋ ํ์ง ๊ฐ์ ):
- ํจ์ ๋ถ๋ฆฌ, ํ์
์ถ๊ฐ, ์๋ฌ ์ฒ๋ฆฌ
- TRUST 5์์น ์ ์ฉ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ 3๋จ๊ณ: ๋ฌธ์ ๋๊ธฐํ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
/alfred:3-sync
โ
@TAG ์ถ๊ฐ: @SPEC โ @TEST โ @CODE ์ฒด์ธ ์์ฑ
โ
API ๋ฌธ์ ์๋ ์์ฑ: docs/api/auth.md
โ
PR ์ํ ์ ํ: Draft โ Ready for Review
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
์๋ฃํ ์์
:
- SPEC ๋ฌธ์ ์์ฑ
- ํ
์คํธ ์ฐ์ ์์ฑ (TDD)
- ์ฝ๋ ๊ตฌํ ๋ฐ ๋ฆฌํฉํ ๋ง
- ๋ฌธ์ ์๋ ๋๊ธฐํ
๋ค์ ๊ธฐ๋ฅ ๊ตฌํ์ ์์ํ์๊ฒ ์ต๋๊น?
```
---
### 3๏ธโฃ MoAI Pair Collaboration
**๋ช
๋ น์ด**: `/output-style pair-collab`
**์๋ต ๋ฐฉ์**: ์ง๋ฌธ ๊ธฐ๋ฐ, ํธ๋ ์ด๋์คํ ๋ถ์, ์ ํ์ง ์ ์
**๋์**: ํ์
๊ฐ๋ฐ์, ์ํคํ
ํธ, ์ค๊ณ ์ธ์
, ์ฝ๋ ๋ฆฌ๋ทฐ
์ถ๋ ฅ ์์
```
JWT ์ธ์ฆ ๊ตฌํ ์ ์ ์ค๊ณ ๊ฒฐ์ ์ด ํ์ํฉ๋๋ค.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ค ์ค๊ณ ์ง๋ฌธ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
**Q1: ํ ํฐ ์ ์ฅ ๋ฐฉ์**
| ๋ฐฉ์ | ์ฅ์ | ๋จ์ | ์ฌ์ฉ ์๋๋ฆฌ์ค |
| --------------- | ------------------- | -------------------- | --------------- |
| localStorage | ๊ฐ๋จ, ์๋ก๊ณ ์นจ ์ ์ง | XSS ์ํ | ๋ด๋ถ ๋๊ตฌ |
| httpOnly Cookie | XSS ๋ฐฉ์ด | CSRF ๋์ ํ์ | ํ๋ก๋์
(๊ถ์ฅ) |
| memory (state) | ์ต๋ ๋ณด์ | ์๋ก๊ณ ์นจ ์ ๋ก๊ทธ์์ | ๊ธ์ต/์๋ฃ |
**๊ถ์ฅ**: httpOnly Cookie + CSRF ํ ํฐ
**Q2: ํ ํฐ ๋ง๋ฃ ์๊ฐ**
- Access Token: 15๋ถ (๋ณด์ ์ฐ์ )
- Refresh Token: 7์ผ (UX ์ฐ์ )
์๋น์ค ํน์ฑ์ ๋ฐ๋ผ ์กฐ์ ๊ฐ๋ฅ (์: ๋ฑ
ํน ์ฑ โ 5๋ถ/1์ผ)
**Q3: ํ ํฐ ๊ฐฑ์ ์ ๋ต**
```typescript
// ์ต์
A: ์๋ ๊ฐฑ์
if (tokenExpiresIn < 5 * 60) await refreshToken();
// ์ต์
B: ๋ง๋ฃ ํ ๊ฐฑ์
// 401 ์๋ฌ โ Refresh Token ์ฌ๋ฐ๊ธ
```
**ํธ๋ ์ด๋์คํ**:
- ์ต์
A: UX โ, ์๋ฒ ๋ถํ โ
- ์ต์
B: ๋ณด์ โ, ์ผ์์ ๋๊น
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ ๊ตฌํ ๊ณํ (httpOnly + ์๋ ๊ฐฑ์ ๊ธฐ์ค)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
**1. SPEC ๋ช
์ธ**:
- Storage: httpOnly Cookie
- Expiry: Access 15m, Refresh 7d
- Strategy: Auto-refresh at 5m remaining
- Security: Double Submit Cookie (CSRF)
**2. TDD ์๋๋ฆฌ์ค**:
- โ
๋ก๊ทธ์ธ โ 2๊ฐ ํ ํฐ ๋ฐ๊ธ
- โ
Access ๋ง๋ฃ โ ์๋ ๊ฐฑ์
- โ
Refresh ๋ง๋ฃ โ ์ฌ๋ก๊ทธ์ธ
- โ
CSRF ๊ณต๊ฒฉ โ ์ฐจ๋จ
**3. ๋ณด์ ์ฒดํฌ๋ฆฌ์คํธ**:
- [ ] XSS: httpOnly + Secure
- [ ] CSRF: SameSite=Strict
- [ ] Replay Attack: JWT ID + Redis
์ด ๋ฐฉํฅ์ผ๋ก ์งํํ์๊ฒ ์ต๋๊น? ์กฐ์ ์ฌํญ์ด ์์ผ๋ฉด ๋ง์ํ์ธ์.
```
---
### 4๏ธโฃ MoAI Study Deep
**๋ช
๋ น์ด**: `/output-style study-deep`
**์๋ต ๋ฐฉ์**: ๊ฐ๋
โ ์ค์ต โ ์ ๋ฌธ๊ฐ ํ (3๋จ๊ณ ํ์ต)
**๋์**: ์ ๊ธฐ์ ํ์ต์, ํ๋ ์์ํฌ ์ ํ์, ์ฌํ ์ด๋ก ํ๊ตฌ์
์ถ๋ ฅ ์์
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ 1๋จ๊ณ: ๊ฐ๋
(Concept)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
JWT (JSON Web Token)
Stateless ์ธ์ฆ์ ์ํ ํ ํฐ ๊ธฐ๋ฐ ๋ฐฉ์.
**Session vs JWT**
| ๋ฐฉ์ | ์ ์ฅ ์์น | ํ์ฅ์ฑ | ํน์ง |
| ------- | -------------- | ------ | ---------------------- |
| Session | ์๋ฒ ๋ฉ๋ชจ๋ฆฌ/DB | ๋ฎ์ | Stateful, ์๋ฒ ์์กด |
| JWT | ํด๋ผ์ด์ธํธ | ๋์ | Stateless, ๋ถ์ฐ ์์คํ
|
**JWT ๊ตฌ์กฐ (3 Parts)**
eyJhbGc.eyJzdWI.SflKxw
โ โ โ
Header Payload Signature
1. Header: {"alg": "HS256", "typ": "JWT"}
2. Payload: {"sub": "user-123", "email": "", "exp": 1735689600}
3. Signature: HMACSHA256(base64(header + payload), SECRET_KEY)
**๋ณด์**
- Payload๋ Base64 ์ธ์ฝ๋ฉ (์ํธํ ์๋)
- ๋ฏผ๊ฐ ์ ๋ณด ์ ๋ ํฌํจ ๊ธ์ง
- HTTPS ํ์, exp claim ํ์
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ ๏ธ 2๋จ๊ณ: ์ค์ต (Practice)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
MoAI-ADK๋ก TDD ๊ตฌํ.
/alfred:1-spec "JWT ๊ธฐ๋ฐ ์ฌ์ฉ์ ์ธ์ฆ API"
- WHEN POST /api/auth/login โ JWT ๋ฐํ
- IF ํ ํฐ ๋ง๋ฃ 15๋ถ
/alfred:2-build AUTH-001
๐ด RED: expect(token.split('.')).toHaveLength(3)
๐ข GREEN: jwt.sign(payload, SECRET, {expiresIn: '15m'})
๐ต REFACTOR: ํ์
์์ ์ฑ, ํ๊ฒฝ ๊ฒ์ฆ, ํ์ค claims
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ 3๋จ๊ณ: ์ ๋ฌธ๊ฐ ํ (Expert Tips)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
**1. Access + Refresh Token**
const accessToken = generateJWT(payload, '15m');
const refreshToken = generateRefresh(userId);
await saveRefreshToken(userId, refreshToken); // DB ์ ์ฅ
- Access ํ์ทจ โ 15๋ถ ํ ๋ฌดํจํ
- Refresh โ DB์์ ์ฆ์ ํ๊ธฐ ๊ฐ๋ฅ
**2. ์๊ณ ๋ฆฌ์ฆ**
| ์๊ณ ๋ฆฌ์ฆ | ์ฌ์ฉ ์ฌ๋ก |
| ---------------- | ---------------- |
| HS256 (๋์นญํค) | ๋จ์ผ ์๋ฒ |
| RS256 (๋น๋์นญํค) | MSA, ๋ฉํฐ ์๋น์ค |
**3. Payload ์ต์ ํ**
โ {userId, email, name, address} // ๋น๋
โ
{sub: '123', email, role} // ์ต์
**4. ๋ณด์ ์ฒดํฌ๋ฆฌ์คํธ**
- [ ] HTTPS ํ์
- [ ] SECRET_KEY โฅ256bit
- [ ] exp claim ํ์
- [ ] ๋ฏผ๊ฐ ์ ๋ณด ์ ์ธ
**5. ๋ผ์ด๋ธ๋ฌ๋ฆฌ**
| ์ธ์ด | ๋ผ์ด๋ธ๋ฌ๋ฆฌ |
| ---------- | -------------- |
| TypeScript | jsonwebtoken |
| Python | PyJWT |
| Go | golang-jwt/jwt |
| Rust | jsonwebtoken |
**ํ์ต ๊ฒฝ๋ก**
1. โ
JWT ๊ธฐ๋ณธ
2. โญ๏ธ Refresh Token
3. โญ๏ธ OAuth 2.0
4. โญ๏ธ Zero Trust
```
---
## ๐ Universal Language Support
MoAI-ADK๋ ๋ชจ๋ ์ฃผ์ ์ธ์ด๋ฅผ ์ง์ํ๋ฉฐ, ์ธ์ด๋ณ ์ต์ ๋๊ตฌ ์ฒด์ธ์ ์๋์ผ๋ก ์ ํํฉ๋๋ค.
### ์น/๋ฐฑ์๋
| ์ธ์ด | ํ
์คํธ | ๋ฆฐํฐ | ํ์
| ์ํ |
| -------------- | ----------- | ------------ | ---- | ---- |
| **TypeScript** | Vitest/Jest | Biome/ESLint | โ
| Full |
| **Python** | pytest | ruff/black | mypy | Full |
| **Java** | JUnit 5 | checkstyle | โ
| Full |
| **Go** | go test | golint | โ
| Full |
| **Rust** | cargo test | clippy | โ
| Full |
### ๋ชจ๋ฐ์ผ
| ์ธ์ด/ํ๋ ์์ํฌ | ํ
์คํธ | ๋ฆฐํฐ | ์ํ |
| ------------------ | ---------------- | ------------ | ---- |
| **Flutter/Dart** | flutter test | dart analyze | Full |
| **Swift/iOS** | XCTest | SwiftLint | Full |
| **Kotlin/Android** | JUnit + Espresso | detekt | Full |
| **React Native** | Jest + RNTL | ESLint | Full |
### ์๋ ์ธ์ด ๊ฐ์ง
์์คํ
์ด ํ๋ก์ ํธ๋ฅผ ์ค์บํ์ฌ ์๋์ผ๋ก ๊ฐ์ง:
- `package.json` โ TypeScript/JavaScript
- `requirements.txt` โ Python
- `go.mod` โ Go
- `Cargo.toml` โ Rust
- `pubspec.yaml` โ Flutter/Dart
---
## ๐ป CLI Reference
### ํต์ฌ ๋ช
๋ น์ด
```bash
# ํ๋ก์ ํธ ์ด๊ธฐํ
moai init [project] [options]
# ์์คํ
์ง๋จ
moai doctor [options]
# ํ๋ก์ ํธ ์ํ ํ์ธ
moai status [options]
# ๋ฐฑ์
๋ณต์
moai restore [options]
```
### Claude Code ์ ์ฉ ๋ช
๋ น์ด
```text
# ํ
ํ๋ฆฟ ์
๋ฐ์ดํธ (๊ถ์ฅ โญ)
/alfred:9-update
# ํ๋ก์ ํธ ์ด๊ธฐํ
/alfred:8-project
```
### moai init [project]
์ MoAI-ADK ํ๋ก์ ํธ๋ฅผ ์ด๊ธฐํํ๊ฑฐ๋ ๊ธฐ์กด ํ๋ก์ ํธ์ MoAI-ADK๋ฅผ ์ค์นํฉ๋๋ค.
**์ต์
**:
- `--personal`: Personal ๋ชจ๋๋ก ์ด๊ธฐํ (๊ธฐ๋ณธ๊ฐ)
- `--team`: Team ๋ชจ๋๋ก ์ด๊ธฐํ (GitHub ํตํฉ)
- `-b, --backup`: ์ค์น ์ ๋ฐฑ์
์์ฑ
- `-f, --force`: ๊ธฐ์กด ํ์ผ ๊ฐ์ ๋ฎ์ด์ฐ๊ธฐ
**์ฌ์ฉ ์์**:
```bash
# ์ ํ๋ก์ ํธ ์์ฑ (Personal ๋ชจ๋)
moai init my-project
# ํ์ฌ ๋๋ ํ ๋ฆฌ์ ์ค์น
moai init .
# Team ๋ชจ๋๋ก ์ด๊ธฐํ
moai init my-project --team
# ๋ฐฑ์
์์ฑ ํ ์ค์น
moai init . -b
# ๊ธฐ์กด ํ์ผ ๊ฐ์ ๋ฎ์ด์ฐ๊ธฐ
moai init . -f
```
### moai doctor
์์คํ
์ง๋จ์ ์คํํ์ฌ MoAI-ADK๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ์ค์น๋์๋์ง ํ์ธํฉ๋๋ค.
**์ต์
**:
- `-l, --list-backups`: ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฐฑ์
๋ชฉ๋ก ํ์
**์ฌ์ฉ ์์**:
```bash
# ์์คํ
์ง๋จ ์คํ
moai doctor
# ๋ฐฑ์
๋ชฉ๋ก ํ์ธ
moai doctor -l
```
### moai status
MoAI-ADK ํ๋ก์ ํธ ์ํ๋ฅผ ํ์ํฉ๋๋ค.
**์ต์
**:
- `-v, --verbose`: ์์ธ ์ํ ์ ๋ณด ํ์
- `-p, --project-path `: ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ ๊ฒฝ๋ก ์ง์ (๊ฒฝ๋ก ํ์)
**์ฌ์ฉ ์์**:
```bash
# ํ์ฌ ๋๋ ํ ๋ฆฌ ์ํ ํ์ธ
moai status
# ์์ธ ์ ๋ณด ํฌํจ
moai status -v
# ํน์ ๊ฒฝ๋ก ํ๋ก์ ํธ ์ํ ํ์ธ
moai status -p /path/to/project
# ์์ธ ์ ๋ณด + ํน์ ๊ฒฝ๋ก
moai status -v -p /path/to/project
```
### moai restore
๋ฐฑ์
๋๋ ํ ๋ฆฌ์์ MoAI-ADK๋ฅผ ๋ณต์ํฉ๋๋ค.
**์ธ์**:
- ``: ๋ณต์ํ ๋ฐฑ์
๋๋ ํ ๋ฆฌ ๊ฒฝ๋ก (ํ์)
**์ต์
**:
- `--dry-run`: ๋ณ๊ฒฝ ์์ด ๋ณต์ํ ๋ด์ฉ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
- `--force`: ๊ธฐ์กด ํ์ผ ๊ฐ์ ๋ฎ์ด์ฐ๊ธฐ
**์ฌ์ฉ ์์**:
```bash
# ๋ฐฑ์
์์ ๋ณต์ (๋ฏธ๋ฆฌ๋ณด๊ธฐ)
moai restore .moai-backup-2025-10-02 --dry-run
# ์ค์ ๋ณต์ ์คํ
moai restore .moai-backup-2025-10-02
# ๊ฐ์ ๋ณต์ (๊ธฐ์กด ํ์ผ ๋ฎ์ด์ฐ๊ธฐ)
moai restore .moai-backup-2025-10-02 --force
```
**์ฐธ๊ณ **: MoAI-ADK ์
๋ฐ์ดํธ๋ Claude Code์์ `/alfred:9-update` ๋ช
๋ น์ด๋ฅผ ์ฌ์ฉํ์ธ์.
---
## โ FAQ
### Q1: MoAI-ADK๋ ๋ฌด๋ฃ์ธ๊ฐ์?
โ
**๋ค, ์์ ๋ฌด๋ฃ์
๋๋ค!**
- MIT ๋ผ์ด์ ์ค ์คํ์์ค
- ์์
์ ์ฌ์ฉ ํฌํจ ๋ฌด๋ฃ
- Claude Code๋ Anthropic์ ์ ๋ฃ ์๋น์ค (๋ณ๋)
### Q2: ๊ธฐ์กด ํ๋ก์ ํธ์ ์ ์ฉ ๊ฐ๋ฅํ๊ฐ์?
โ
**๊ฐ๋ฅํฉ๋๋ค!**
```bash
cd existing-project
moai init .
```
Alfred๊ฐ ์๋์ผ๋ก:
- ์ธ์ด/ํ๋ ์์ํฌ ๊ฐ์ง
- ํด๋ ๊ตฌ์กฐ ๋ถ์
- ์ต์ ์ค์ ์ ์
### Q3: ์ด๋ค ์ธ์ด๋ฅผ ์ง์ํ๋์?
โ
**๋ชจ๋ ์ฃผ์ ์ธ์ด ์ง์!**
**์น/๋ฐฑ์๋**: TypeScript, JavaScript, Python, Java, Go, Rust
**๋ชจ๋ฐ์ผ**: Flutter/Dart, Swift/iOS, Kotlin/Android, React Native
โ ๋ชจ๋ ์ธ์ด์์ **๋์ผํ 3๋จ๊ณ ์ํฌํ๋ก์ฐ** ์ฌ์ฉ ๊ฐ๋ฅ!
### Q4: ํ์ต ๊ณก์ ์ ์ด๋ค๊ฐ์?
โ
**๋งค์ฐ ๋น ๋ฆ
๋๋ค!**
- โก **3๋ถ**: ์ฒซ ๊ธฐ๋ฅ ๊ฐ๋ฐ ์๋ฃ
- ๐ **1์๊ฐ**: 3๋จ๊ณ ์ํฌํ๋ก์ฐ ์์ ์ดํด
- ๐ท๏ธ **1์ผ**: TAG ์์คํ
์๋ฌ
- ๐ฅ **1์ฃผ**: ํ ํ๋ก์ ํธ ์ ์ฉ
### Q5: ์
๋ฐ์ดํธ๋ ์ด๋ป๊ฒ ํ๋์?
โ
**Claude Code์์ ๊ฐ๋จํ๊ฒ!**
```text
/alfred:9-update
```
**์ ์ด ๋ฐฉ๋ฒ์ ๊ถ์ฅํ๋์?**
- ์๋ ๋ฐฑ์
(์ฌ์ฉ์ ํ์ผ ๋ณดํธ)
- ๊ถํ ์๋ ์ค์ (`chmod +x`)
- 5๋จ๊ณ ๊ฒ์ฆ (ํ์ผ/๊ถํ/๋ฌด๊ฒฐ์ฑ)
- ์๋ฌ ๋ฐ์ ์ `debug-helper` ์๋ ์ง์
---
**๋ ๊ถ๊ธํ ์ ์ด ์์ผ์ ๊ฐ์?**
- ๐ฌ **์ง๋ฌธ & ํ ๋ก **: [GitHub Discussions](https://github.com/modu-ai/moai-adk/discussions)
- ๐ **๋ฒ๊ทธ ๋ฆฌํฌํธ**: [GitHub Issues](https://github.com/modu-ai/moai-adk/issues)
---
## ๐ Support
- **๋ฒ๊ทธ ๋ฆฌํฌํธ**: [GitHub Issues](https://github.com/modu-ai/moai-adk/issues)
- **์ง๋ฌธ & ํ ๋ก **: [GitHub Discussions](https://github.com/modu-ai/moai-adk/discussions)
- **npm ํจํค์ง**: [moai-adk](https://www.npmjs.com/package/moai-adk)
---
Made with MoAI's ๐ชฟ
---
## ๋ผ์ด์ ์ค
์ด ํ๋ก์ ํธ๋ [MIT License](LICENSE)๋ฅผ ๋ฐ๋ฆ
๋๋ค.