SharedLedger Journey Part 1: From Zero to Phoenix
posted by donghyun
last updated
9 min read
๐ The Context: Berlin, New Life, New Needs
2025๋ 9์, ๋ฒ ๋ฅผ๋ฆฐ์ผ๋ก ์ด์ฌ๋ฅผ ์๋ค. ์๋ก์ด ๋์, ์๋ก์ด ์ํ, ๊ทธ๋ฆฌ๊ณ ํํธ๋์ ํจ๊ป ๊ด๋ฆฌํด์ผ ํ ์๋ก์ด ์ฌ์ . EUR(์ ๋ก)์ KRW(์ํ)๋ฅผ ๋์ ์ฌ์ฉํ๊ฒ ๋๋ฉด์, ๊ธฐ์กด์ ๊ฐ๊ณ๋ถ ์ฑ๋ค์ ์ฐ๋ฆฌ์ ๋์ฆ๋ฅผ ์ถฉ์กฑ์ํค์ง ๋ชปํ๋ค:
- ๋ค์ค ํตํ ์ง์ (EUR โ KRW real-time conversion)
- ๊ณต์ ๊ณ์ข ๊ฐ๋ (shared ledger for couples)
- ๊ฑฐ๋๋ณ ์นดํ ๊ณ ๋ฆฌ ๋ถ๋ฅ
- ์๊ฐ/์ฐ๊ฐ ์์ฝ ๋ฐ ๋ถ์
๊ทธ๋ฆฌ๊ณ ๋์์, ๋๋ AI ์ฝ๋ฉ ๋๊ตฌ ๋ถ์ผ๋ฅผ ๊น์ด ํ๊ตฌํ๊ณ ์ถ์๋ค.
โ๊ทธ๋ ๋ค๋ฉด, ์ง์ ๋ง๋ค์ด๋ณด๋ฉด ์ด๋จ๊น? AI ๋๊ตฌ์ ํจ๊ป.โ
๐ค Why AI-Assisted Development?
์ด ํ๋ก์ ํธ๋ ์ฒ์๋ถํฐ AI ์ฝ๋ฉ ๋๊ตฌ ์คํ์ ์ผ๋์ ๋๊ณ ์์ํ๋ค:
- Claude Code์ ์ค์ ํ๋ก์ ํธ ์ ์ฉ ๋ฅ๋ ฅ ํ ์คํธ
- AI ๋๊ตฌ์ ๊ฐ์ ๊ณผ ํ๊ณ ํ์
- ํจ๊ณผ์ ์ธ AI ํ์ฉ ํจํด ํ์ต
- Elixir/Phoenix ์ํ๊ณ์์์ AI ๋๊ตฌ ํ์ฉ ๊ฐ๋ฅ์ฑ ๊ฒ์ฆ
๐ก Honest Expectations Setup
์์ํ๊ธฐ ์ ์์์ผ ํ ๊ฒ๋ค:
์ด ํ๋ก์ ํธ๋ โAI๊ฐ ๋ชจ๋ ๊ฑธ ์๋ฒฝํ๊ฒ ๋ง๋ค์ด์คโ ์ด์ผ๊ธฐ๊ฐ ์๋๋ค. ํ์ค์:
- โ My Role: Architecture design, planning, decision making, extensive refactoring, fixing broken implementations
- ๐ค Claude Codeโs Role: Code generation, boilerplate creation, initial feature implementation
- โฐ Time Reality: ~30% planning, ~40% AI-assisted coding, ~30% refactoring/fixing what AI messed up
AI ๋๊ตฌ๋ ๊ฐ๋ ฅํ์ง๋ง, ํนํ Ash Framework ๊ฐ์ ํน์ํ ํ๋ ์์ํฌ์์๋ ๋ง์ ์์ ๊ณผ ๊ฐ์ ์ด ํ์ํ๋ค. ์ด ์๋ฆฌ์ฆ๋ ๊ทธ ํ์ค์ ์ธ ์ฌ์ ์ ๋ค๋ฃฌ๋ค.
๐ง Technology Choices
Why Elixir?
์ด๋ฌ๋ ์ ๋ฌ๋ Elixir๋ ๋์ favorite language์ด๊ณ , ์ต๊ทผ์๋ ์ ๋ฌด์์ ๋ค๋ฅธ ์ธ์ด๋ค์ ์ฐ๊ณ ์๋ค๋ณด๋, Elixir ํ๋ก์ ํธ๋ฅผ ํ๊ณ ์ถ์ ์๊ตฌ๊ฐ ๋ ๋ง์ด ์๊ธฐ๋๋ผ. ์ค์ค๋ก Elixir ์ ๋ฌธ๊ฐ๋ผ๊ณ ์๊ฐํ๊ณ ์๊ธฐ ๋๋ฌธ์, Claude Code๊ฐ ๋ง๋๋ Elixir ์ฝ๋๋ฅผ ๋ด๊ฐ ์ผ๋ง๋ ์ ๊ฒ์ฆํ ์ ์์์ง๋ ๊ถ๊ธํ๋ค.
Why Phoenix LiveView?
์ฌ์ค ์์ง๋ ๋ณต์กํ SPA ์์ค์ ์๋น์ค๋ฅผ Phoenix LiveView๋ก ๋ง๋ค ์ ์์์ง ์ ๋ชจ๋ฅด๊ฒ ๋ค. ๋ถํธํ ๋ถ๋ถ์ด ๋ง๊ณ , ๊ทธ๋งํผ ํ๋ฐํ๊ฒ ๋ณํ๊ฐ ์ด๋ค์ง๊ณ ์์ด์, ๊ณ์ ์ซ์๊ฐ๋ ์ ์ฅ์ด๋ค. ์ธ์ ๊ฐ LiveView๊ฐ ์๋ฒฝํ๊ฒ ํ๋ก ํธ์๋๋ฅผ ๋์ฒดํ ๋ ์ด ์ฌ์ง ์ ๋ง ๊ถ๊ธํ๋ค.
Why Ash Framework?
Ash Framework๋ ์ต๊ทผ ์ ๋ง ํซํ๋ค๊ณ ๋๊ผ๋๋ฐ, ๊ทธ๋งํผ ๋ฌ๋์ปค๋ธ๋ ํฌ๋ค๊ณ ๋๋ผ๊ณ ์๋ค. ์ธ์ ๋ ๋๋ผ๋ ๊ฑฐ์ง๋ง ๊ฐ๋ ฅํ ํ๋ ์์ํฌ๋ฅผ ์ด๋ค๋ ๊ฒ์ ๊ทธ๋งํผ ์์ ๋ฅผ ํฌ๊ธฐํ๋ค๋ ๋ป์ด๋ค. ์ด ํ๋ก์ ํธ์์๋ ํนํ ์ด Ash๋ฅผ Claude Code๊ฐ ์ผ๋ง๋ ์ ๋ค๋ฃฐ์ ์์์ง๊ฐ ๊ถ๊ธํ๋ค.
Key Decision: PostgreSQL (not ETS/SQLite)
- Initial plan: SQLite for MVP
- Reality: Switched to PostgreSQL early
- Reason: Production-ready from day one
๐ Project Initialization
Day 1: Setting Up
-
Documentation phase with Claude (17+ files, ~5,500 lines):
Architecture Documents (in
docs/architecture/):-
DOMAIN_MODEL.md(1,066 lines) - 4๊ฐ domain ์ ์ (Identity, Accounts, Ledger, Currency) -
UI_COMPONENTS.md(1,026 lines) - Atomic Design ๊ธฐ๋ฐ ์์ ํ UI ์คํ -
API_SPECIFICATION.md(645 lines) - LiveView event contracts -
DATABASE_DESIGN.md(489 lines) - ์ ์ฒด ์คํค๋ง ๊ตฌ์กฐ -
ASH_FRAMEWORK_ANALYSIS.md(355 lines) - Ash ํ๋ ์์ํฌ ํ๊ฐ ๋ฐ ์ฌ์ฉ ์ ๋ต -
SYSTEM_ARCHITECTURE.md(292 lines) - ๋ ์ด์ด ์ํคํ ์ฒ ๋ฐ ํจํด
Project Documents (in
docs/):-
REQUIREMENTS_SPECIFICATION.md(815 lines) - ๊ธฐ๋ฅ/๋น๊ธฐ๋ฅ ์๊ตฌ์ฌํญ -
PROJECT_PLAN.md(572 lines) - MVP โ Phase 2 โ Phase 3 ๋ก๋๋งต -
TECHNICAL_SPECIFICATION.md- ๊ตฌํ ์ธ๋ถ์ฌํญ -
CLAUDE.md(229 lines) - AI ์ด์์คํดํธ ๊ฐ์ด๋ - Plus: PROJECT_STATUS, DEPLOYMENT_OPERATIONS_GUIDE, DATA_FLOW_INTEGRATION
-
-
Project initialization:
-
mix phx.new shared_ledger -
mix igniter.installfor Ash Framework and dependencies
-
๐ First Lesson with Claude Code
Day 1: ์๋ฒฝํ ๊ณํ
์ค์ mix new ๋ช
๋ น์ ์คํํด ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ ์, ๋ฌธ์๋ฅผ ์ ๋๋ก ๋ง๋๋ ๊ฒ์ ์ง์คํ๋ค. ํ์ฌ ํ๋ก์ ํธ๋ฅผ ํ๋ฉฐ ์์ ๋
ธํ์ฐ๋ก ํ์ํ ํต์ฌ ๋ฌธ์๋ค์ ์ญ์ Claude๋ฅผ ์ด์ฉํด ๋ง๋ค๊ธฐ ์์ํ๋ค. ์ฌ๊ธฐ์ ์ ๋๋ก ํ ์๋ก, ๋ค์ ๋ค์ด๊ฐ๋ ๋ถํ์ํ ๋
ธ๋ ฅ์ด ์ค์ด๋ ๋ค.
๋ฌธ์๋ฅผ ์ ๋ง๋ค๋ฉด:
- โ AI๊ฐ ๋ด ์ํคํ ์ฒ ์๋๋ฅผ ์ดํดํ๋ค
- โ ์ผ๊ด๋ ํจํด์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ค
- โ ๊ฐ์ ์ค์๋ฅผ ๋ฐ๋ณตํ์ง ์๋๋ค
ํ์ง๋ง ํจ์ ์ด ์์๋คโฆ
Day 2: ํ์ค๊ณผ์ ์ถฉ๋
# Day 1์ ์๋ฒฝํ๊ฒ ๊ณํํ ์ฝ๋
changeset = Ash.Changeset.for_action(User, :create, %{})
form = to_form(changeset) # ๐ฅ Protocol error!
์๋ฌ ๋ฉ์์ง: Protocol Phoenix.HTML.FormData not implemented for Ash.Changeset
์๋ฒฝํ ๋ฌธ์๊ฐ ์์ด๋, Ash Framework์ ํน์ํ integration ์ด์๋ ๋ง์ ์ ์์๋ค. ์ด๋ ์๋ก์ด ๋ฌธ์๋ค์ด ์๊ฒผ๋ค:
-
DEVELOPMENT_CONVENTIONS.md- Ash+Phoenix ํจํด -
ADR-005: Ash-Phoenix Form Integration- ์ ์ด๋ ๊ฒ ํ๋์ง
๋ ์ข ๋ฅ์ ๋ฌธ์:
- Proactive (Day 1) - ๋ฌธ์ ๋ฅผ ์๋ฐฉํ๋ ๋ฌธ์
- Reactive (Day 2) - ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ๊ธฐ๋กํ๋ ๋ฌธ์
AI Agent๋ ๋์์์ด ๋ด๊ฐ ์ํ๋ ๋ฐฉํฅ๊ณผ ๋ค๋ฅธ ์ ๋ณด๋ฅผ ์๋์น ์๊ฒ ์ฌ๊ธฐ ๋๋ฌธ์, ๋ฌธ์๋ฅผ ๋ฉด๋ฐํ ๊ฒํ ํ๊ณ ๊ณ์ ์ ๋ฐ์ดํธํ ํ์๊ฐ ์์๋ค.
๊ตํ: ๋ฌธ์๋ one-and-done์ด ์๋๋ค. ์ด์์๋ ๋ฌธ์์ฌ์ผ ํ๋ค.
๐๏ธ Architecture Planning
Domain Contexts
Initial planning led to 4 main contexts:
- Identity - Users, authentication, sessions
- Accounts - Shared accounts, memberships, roles
- Ledger - Transactions, categories, summaries
- Currency - Exchange rates, conversions
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Phoenix UI โ
โ (LiveView Components) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Domain Layer โ
โ Identity โ Accounts โ Ledger โ Currency โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Ash Resources Layer โ
โ (Declarative definitions + Actions) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PostgreSQL โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ค Architecture Decision Challenges
์ด๊ธฐ ์ํ: Elixir๋ ์์ ์์์ง๋ง, domain modeling๊ณผ relationship ์ค๊ณ๋ ๊ณ ๋ฏผ์ด ๋ง์ ๋ถ๋ถ์ด๋ผ, ์ด๋ฒ์ Claude์ ๊ตฌ์ฒด์ ์ด๊ณ ์ข ํฉ์ ์ธ ์ค๊ณ๋ฅผ ๋ฐ๋ผ๋ณด๊ธฐ๋ก ํ๋ค.
ํต์ฌ ์ค์: โ์ค๋ช ์ด ๋ ผ๋ฆฌ์ ์ด๋๊น ๋ง๊ฒ ์งโ ํ๋ฉฐ ๋นํ ์์ด ์์ฉ.
์ฃผ์ ์ฌ๋ก๋ค:
- 4-domain structure โ Week 5์ domain boundary refactoring
-
Many-to-many + RBAC โ
manage_relationship์ดํด ์์ด ๊ตฌํ โ 2์ฃผ ๋๋ฒ๊น - SQLite โ PostgreSQL ๊ฐ์ migration (Day 7)
- 403 Forbidden โ 404 NotFound (security ์ด์)
ํจํด: Claude ์ ์ โ โ๊ทธ๋ด๋ฏโ โ ๊ตฌํ โ ๋ฌธ์ ๋ฐ๊ฒฌ โ refactoring
Time Cost: Architecture review 10์๊ฐ vs. ๋์ค์ ๊ณ ์น๊ธฐ 3-4์ฃผ (1:20~30 ratio)
๊ตํ: AI๋ ํจํด์ ์๋ค. ํ์ง๋ง ๋ด ๋ฌธ์ , trade-offs, security implications๋ ๋ชจ๋ฅธ๋ค. โAI๋ ์ต์ ์ ์. ๊ฒฐ์ ์ ๋ด๊ฐ.โ
โ Part 2์์ domain ์ค๊ณ ์ธ๋ถ ์ฌํญ ๋ค๋ฃธ
๐ Initial Feature Planning
MVP Scope (Week 1 Planning)
Must Have:
- โ User authentication (email/password)
- โ Create/join shared accounts
- โ Add transactions (amount, category, date, note)
- โ Multi-currency support (EUR, KRW)
- โ Basic transaction list view
- โ Monthly summary
Nice to Have (Later):
- โ Budget tracking
- โ Recurring transactions
- โ Advanced analytics
- โ Mobile app (PWA instead)
๐ก Lesson: Pattern Pollution
AI์ ์์ ํ๋ฉด์ ๊ฐ์ฅ ์ํํ๋ ํจํด: ๋์ ์ฝ๋๊ฐ ๋๋ฉ์ด์ฒ๋ผ ์ปค์ง๋ ๊ฒ
์๋๋ฆฌ์ค: ํฐ feature ์์ฒญ (500์ค) โ ๋๋ถ๋ถ ์ ์๋ โ ๊ท์ฐฎ์์ ์ธ๋ถ ๋ฆฌ๋ทฐ ์๋ต โ 10์ค์ ์๋ชป๋ ์ฝ๋ ์จ์ด์์ โ Claude๊ฐ ๊ทธ๊ฑธ ํ์ต โ ๋ค์ feature์์ ๋ฐ๋ณต.
Real Example:
-
Week 1: Transaction LiveView์์
Ash.Query์ง์ ์ฌ์ฉ (๋ฆฌ๋ทฐ ์ ํจ) - Week 2-3: Category, Summary LiveView โ ๊ฐ์ ํจํด ๋ณต์ฌ
-
Week 5:
git grep "Ash.Query"โ 12๊ฐ ํ์ผ ๋ฐ๊ฒฌ โ 2์ฃผ refactoring
๋ ๋ค๋ฅธ ์: Money ๋์ Decimal ์ฌ์ฉ โ ๋ชจ๋ calculation์ ํ์ฐ โ Currency ์ ๋ณด ์์ค.
ํต์ฌ:
- โ์๋ โ ์ณ์โ
- ํ ๋ฒ์ ์ค์ = 12๋ฒ์ ๋ฒ๊ทธ
- Review 30๋ถ vs. Refactoring 2์ฃผ (1:40 ratio)
ํด๊ฒฐ:
- ํฐ feature๋ ์ธ๋ถ ๋ฆฌ๋ทฐ ํ์
- ์๋ชป๋ ํจํด ์ฆ์ ์์ (๋์ค์ โ)
- Anti-patterns๋ฅผ CLAUDE.md์ ๊ธฐ๋ก
-
์ฃผ๊ธฐ์ audit (
git grep๊ธ์ง ํจํด)
โ Part 4์์ refactoring ์์ธํ ๋ค๋ฃธ
๐ฏ Documentation-Driven Development
One of the best decisions: Creating comprehensive documentation for Claude Code.
Files created:
-
CLAUDE.md- Project-specific guidelines -
AGENTS.md- Phoenix/LiveView/Elixir rules (later) -
ASH_DEVELOPMENT_GUIDE.md- Ash framework patterns -
ASH_LIVEVIEW_STRICT_RULES.md- Quick checklist
๐ Why This Mattered
ROI: ๋ฌธ์ ์์ฑ 12-16์๊ฐ vs. ์ ์ฝ 30-40์๊ฐ (์ฝ 2-3๋ฐฐ)
ํจ๊ณผ:
- Claude๊ฐ ์ผ๊ด๋ ํจํด ๋ฐ๋ฆ
- ๊ฐ์ ์ค์ ๋ฐ๋ณต ์ค์ด๋ฆ
- ๋ฉํฐํ์คํน ๊ฐ๋ฅ (๋ฌธ์๊ฐ ๋๋ฅผ ๋์ )
Trade-offs:
- ๋ฌธ์ ์์ฑ ์๊ฐ ๋ง์ด ๋ฆ
- ๊ณ์ ์ ๋ฐ์ดํธ ํ์
- Claude๊ฐ ๊ฐ๋ ๋ฌธ์ ๋ฌด์ํจ
๊ฒฐ๋ก : ๋ณต์กํ ํ๋ ์์ํฌ (Ash, LiveView)๋ ๋ฌธ์ ํ์. ๊ฐ๋จํ ํ๋ก์ ํธ๋ ๋ถํ์.
๐ Development Workflow Setup
Tools & Environment
# Docker for PostgreSQL
docker-compose up -d postgres
# Development commands (Makefile)
make dev-setup # First time
make dev # Daily use
make test # Run tests
make format # Code formatting
๐ค Workflow with Claude Code
ํ๋ฆฝ๋ ํจํด:
-
Feature ์์: ๋ธ๋์น ์์ฑ โ Claude์๊ฒ context ์ ๊ณต (
DOMAIN_MODEL.md๋ฑ) - ์์ ์ค: ์ฆ์ ๋ฆฌ๋ทฐ, ํจํด ์๋ฐ ์ ์ค๋จ, ๊ฐ ๋จ๊ณ compile ํ์ธ
- Iteration: ํ๊ท 3-4๋ฒ (Ash ์ง์ ์ฌ์ฉ โ Domain ํจ์ โ Authorization โ Error handling)
- Commit: Claude ์ ์ message ๊ฑฐ๋ถ, ์ง์ ์์ฑ
์ญํ ๋ถ๋ด:
- Claude: Boilerplate, ๋ฐ๋ณต CRUD, test ์ด์
- ๋: Architecture ๊ฒฐ์ , ๋ณต์กํ ๋น์ฆ๋์ค ๋ก์ง
ํต์ฌ: Pair programmer๋ก ์ฐ๋, final decision์ ๋ด๊ฐ.
๐ First Week Results
By the end of first week (Sep 11-18):
โ
Project initialized
โ
Ash framework integrated
โ
Basic domain structure defined
โ
SQLite setup (later migrated to PostgreSQL)
โ
Initial documentation written
โ
Core features implemented (but needed fixes)
โ ๏ธ Many compilation errors to resolve
Git commits tell the story:
dd3de03 - docs: Add comprehensive Ash framework implementation
4377a84 - docs: Add complete Ash framework architecture
b010fc3 - feat: Implement core MVP features with Ash
394878a - feat: Implement Phoenix LiveView UI
๐ก Key Insight
Planning์ด ์๊ฐ์ ์ ์ฝํ๋ค:
- ๋ฌธ์ ๋จผ์ : 48์๊ฐ ์ด ํฌ์
- ๋ฌธ์ ์์ด (์ถ์ ): 60์๊ฐ+ (architecture ๋ฆฌํฉํ ๋ง, ๋ฐ๋ณต ์ค์)
- ์ ์ฝ: ~20%
๋ ์ค์ํ ๊ฒ: ์ฌ๋ฐ๋ฅธ ๊ตฌ์กฐ, ์ผ๊ด๋ ํจํด, ์ ์ technical debt.
ํ์ง๋ง: ๋ฌธ์๊ฐ ์๋ฒฝํ๊ฒ ๋ง์ง ๋ชปํจ. Week 5-6์ 26๊ฐ refactoring commits ํ์. AI ์์ฑ ์ฝ๋๋ ์ฌ์ ํ ๋ฆฌ๋ทฐ์ refactoring ํ์.
๐ฌ Whatโs Next?
In Part 2, weโll dive into:
- Implementing the four domain contexts with Ash
- Resource definitions and relationships
- Authorization setup (RBAC)
- Testing in IEx before touching LiveView
- Lessons learned about guiding Claude with Ash patterns