Skip to content

Commit 1618fb6

Browse files
committed
docs: OpenClaw 연동 아키텍처 수립 및 API 네임스페이스 분리 설계 반영
- 내부(`/local-api/`) 및 외부(`/api/`) API 경로 분리 결정 추가 (보안 및 AI 최적화) - OpenClaw 등 외부 에이전트용 Skill Manifest 및 Scoped API Key 인증 설계 - 모듈 간 서비스 호출(DI) 규약 및 자동 마이그레이션(Preprocessor 포함) 상세화 - 관련 기술 문서(인증, DB, 개발 가이드) 및 UI 백로그 동기화 완료
1 parent 3ec3528 commit 1618fb6

9 files changed

Lines changed: 518 additions & 335 deletions

File tree

docs/v2_FINANCIAL-LEDGER/architecture/01-decisions.md

Lines changed: 119 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,12 @@
9797
9898
2. 모달 표시: "설치 중..." (진행률 표시)
9999
100-
3. Backend 백그라운드 작업:
101-
- Git clone
102-
- 보안 검사
103-
- pnpm install
104-
- DB 마이그레이션
105-
- 런타임 로드
100+
3. Backend 백그라운드 작업:
101+
- Git clone
102+
- 보안 검사
103+
- pnpm install
104+
- DB 마이그레이션
105+
- 런타임 로드
106106
107107
4. WebSocket으로 Frontend에 알림
108108
@@ -119,16 +119,16 @@ installAndLoad 메서드는 모듈 설치를 총 6단계로 처리합니다. 첫
119119

120120
reloadModule 메서드는 개발 모드에서 사용되는 Hot Reload 기능입니다. 기존 모듈을 먼저 정리한 후, require.cache를 제거하고 모듈을 다시 로드합니다.
121121

122-
### 📚 관련 문서
123-
124-
> 📖 **상세 구현 가이드:**
125-
> `technical/module-loader.md` (작성 예정)
126-
127-
> 📖 **모듈 개발 가이드:**
128-
> `modules/01-development-guide.md`
129-
130-
> 📖 **사용자 설치 가이드:**
131-
> `marketplace/02-installation.md`
122+
### 📚 관련 문서
123+
124+
> 📖 **상세 구현 가이드:**
125+
> `technical/module-loader.md` (작성 예정)
126+
127+
> 📖 **모듈 개발 가이드:**
128+
> `modules/01-development-guide.md`
129+
130+
> 📖 **사용자 설치 가이드:**
131+
> `marketplace/02-installation.md`
132132
133133
### ⚠️ 주의사항
134134

@@ -148,9 +148,9 @@ reloadModule 메서드는 개발 모드에서 사용되는 Hot Reload 기능입
148148

149149
## 결정 #2: 관리자 인증 방식
150150

151-
### ✅ 결정 사항
152-
153-
**이메일/비밀번호 로그인 우선 + 선택적 OAuth + 4~6자리 관리자 PIN** 방식을 채택합니다.
151+
### ✅ 결정 사항
152+
153+
**이메일/비밀번호 로그인 우선 + 선택적 OAuth + 4~6자리 관리자 PIN** 방식을 채택합니다.
154154

155155
### 📖 배경
156156

@@ -160,7 +160,7 @@ reloadModule 메서드는 개발 모드에서 사용되는 Hot Reload 기능입
160160

161161
### 🔍 고려했던 옵션
162162

163-
#### Option A: OAuth 중심 로그인 + 복잡한 비밀번호
163+
#### Option A: OAuth 중심 로그인 + 복잡한 비밀번호
164164
```
165165
장점:
166166
- 높은 보안
@@ -181,7 +181,7 @@ reloadModule 메서드는 개발 모드에서 사용되는 Hot Reload 기능입
181181
- 관리자 설정 보호 안 됨
182182
```
183183

184-
#### Option C: 로컬 로그인 + 관리자 PIN ⭐ (선택)
184+
#### Option C: 로컬 로그인 + 관리자 PIN ⭐ (선택)
185185
```
186186
장점:
187187
- 간단하면서 적절한 보안
@@ -192,7 +192,7 @@ reloadModule 메서드는 개발 모드에서 사용되는 Hot Reload 기능입
192192
- 복잡한 비밀번호보다는 보안 낮음
193193
```
194194

195-
#### Option D: OAuth + 2FA
195+
#### Option D: OAuth + 2FA
196196
```
197197
장점:
198198
- 매우 높은 보안
@@ -204,10 +204,10 @@ reloadModule 메서드는 개발 모드에서 사용되는 Hot Reload 기능입
204204

205205
### 💡 선택 이유
206206

207-
**Option C**를 선택한 이유:
207+
**Option C**를 선택한 이유:
208208

209209
1. **적절한 보안 수준**
210-
- 홈서버 환경: 물리적 보안 + 로컬 로그인 + PIN으로 충분
210+
- 홈서버 환경: 물리적 보안 + 로컬 로그인 + PIN으로 충분
211211
- 4~6자리로도 충분한 보호
212212
- 30분 세션으로 재입력 최소화
213213

@@ -216,22 +216,22 @@ reloadModule 메서드는 개발 모드에서 사용되는 Hot Reload 기능입
216216
- 스마트폰 잠금과 동일한 UX
217217
- 숫자 패드로 빠른 입력
218218

219-
3. **구현 단순성**
220-
- Argon2id(비밀번호) / PBKDF2(PIN)로 목적별 저장
221-
- 세션 관리 간단
222-
- 2FA보다 복잡도 낮음
219+
3. **구현 단순성**
220+
- Argon2id(비밀번호) / PBKDF2(PIN)로 목적별 저장
221+
- 세션 관리 간단
222+
- 2FA보다 복잡도 낮음
223223

224224
### 🎯 구현 방향
225225

226226
#### 사용자 플로우
227227

228228
```
229-
일반 사용:
230-
이메일/비밀번호 로그인 (기본) → 앱 사용 (가계부 입력 등)
231-
또는 선택 로그인(OAuth/Passkey)
232-
233-
관리자 설정 접근:
234-
1차 로그인 완료 (이메일/비밀번호 또는 선택 로그인)
229+
일반 사용:
230+
이메일/비밀번호 로그인 (기본) → 앱 사용 (가계부 입력 등)
231+
또는 선택 로그인(OAuth/Passkey)
232+
233+
관리자 설정 접근:
234+
1차 로그인 완료 (이메일/비밀번호 또는 선택 로그인)
235235
236236
관리자 설정 메뉴 클릭
237237
@@ -248,7 +248,7 @@ reloadModule 메서드는 개발 모드에서 사용되는 Hot Reload 기능입
248248

249249
AdminAuthService 클래스는 관리자 PIN 인증을 담당합니다.
250250

251-
setupAdminPin 메서드는 초기 설치 시 관리자 PIN을 생성합니다. 먼저 PIN이 4~6자리 숫자인지 정규식으로 검증합니다. 통과하면 무작위 16바이트의 salt를 생성하고, PIN과 salt를 합쳐 pbkdf2로 100,000회 반복 해싱합니다. 그 결과를 사용자 테이블에 role, salt, hash와 함께 저장합니다.
251+
setupAdminPin 메서드는 초기 설치 시 관리자 PIN을 생성합니다. 먼저 PIN이 4~6자리 숫자인지 정규식으로 검증합니다. 통과하면 무작위 16바이트의 salt를 생성하고, PIN과 salt를 합쳐 pbkdf2로 100,000회 반복 해싱합니다. 그 결과를 사용자 테이블에 role, salt, hash와 함께 저장합니다.
252252

253253
verifyAndCreateSession 메서드는 PIN 검증과 세션 생성을 처리합니다. verifyPin을 호출하여 PIN이 올바른지 확인합니다. 검증 실패 시 감사 로그를 남기고 에러를 발생시킵니다. 검증 성공 시 무작위 UUID를 세션 ID로 생성하고, 현재 시간에서 30분을 더한 만료 시간과 함께 세션을 저장합니다.
254254

@@ -262,13 +262,13 @@ Rate Limiting은 5회 연속 실패 시 5분간 로그인을 잠급니다. 잠
262262

263263
감사 로그는 각 PIN 검증 시도마다 사용자 ID, 성공/실패 여부, IP 주소, 타임스탬프를 기록합니다.
264264

265-
### 📚 관련 문서
266-
267-
> 📖 **상세 인증 가이드:**
268-
> `technical/02-authentication.md § 3. 관리자 인증`
269-
270-
> 📖 **보안 정책:**
271-
> `security/access-control.md` (작성 예정)
265+
### 📚 관련 문서
266+
267+
> 📖 **상세 인증 가이드:**
268+
> `technical/02-authentication.md § 3. 관리자 인증`
269+
270+
> 📖 **보안 정책:**
271+
> `security/access-control.md` (작성 예정)
272272
273273
### ⚠️ 주의사항
274274

@@ -382,16 +382,16 @@ SQLiteProvider는 Query Builder를 SQLite SQL로 변환합니다. WHERE 절에
382382

383383
MongoDBProvider는 Query Builder를 MongoDB Query Object로 변환합니다. 예시로 userId와 날짜 조건은 `{ userId: xxx, date: { $gte: xxx } }` 형태로 변환됩니다.
384384

385-
### 📚 관련 문서
386-
387-
> 📖 **상세 DB 가이드:**
388-
> `technical/01-database.md § 2. DB 추상화`
389-
390-
> 📖 **Provider 개발:**
391-
> `technical/database-providers.md` (작성 예정)
392-
393-
> 📖 **마이그레이션:**
394-
> `technical/migrations.md` (작성 예정)
385+
### 📚 관련 문서
386+
387+
> 📖 **상세 DB 가이드:**
388+
> `technical/01-database.md § 2. DB 추상화`
389+
390+
> 📖 **Provider 개발:**
391+
> `technical/database-providers.md` (작성 예정)
392+
393+
> 📖 **마이그레이션:**
394+
> `technical/migrations.md` (작성 예정)
395395
396396
### ⚠️ 주의사항
397397

@@ -414,7 +414,13 @@ MongoDBProvider는 Query Builder를 MongoDB Query Object로 변환합니다. 예
414414
| 결정 | 선택 | 핵심 이유 | 상태 |
415415
|------|------|----------|------|
416416
| #1 Module Loader | 런타임 동적 Import | VSCode 방식 UX | ✅ 확정 |
417-
| #2 관리자 인증 | 로컬 로그인 우선 + PIN | 간단하면서 안전 | ✅ 확정 |
417+
| #2 관리자 인증 | 로컬 로그인 우선 + PIN | 간단하면서 안전 | ✅ 확정 |
418+
| #3 DB 추상화 | Query Builder | 적절한 레벨 | ✅ 확정 |
419+
| #5 API 네임스페이스 | Internal/External 분리 | 보안 및 AI 연동 최적화 | ✅ 확정 |
420+
421+
|------|------|----------|------|
422+
| #1 Module Loader | 런타임 동적 Import | VSCode 방식 UX | ✅ 확정 |
423+
| #2 관리자 인증 | 로컬 로그인 우선 + PIN | 간단하면서 안전 | ✅ 확정 |
418424
| #3 DB 추상화 | Query Builder | 적절한 레벨 | ✅ 확정 |
419425

420426
---
@@ -424,6 +430,7 @@ MongoDBProvider는 Query Builder를 MongoDB Query Object로 변환합니다. 예
424430
| 날짜 | 버전 | 변경 내용 |
425431
|------|------|----------|
426432
| 2025-01-29 | 1.0.0 | 최초 작성 (#1, #2, #3) |
433+
| 2026-03-05 | 1.1.0 | API 네임스페이스 분리 결정 추가 (#5) |
427434

428435
---
429436

@@ -433,10 +440,10 @@ MongoDBProvider는 Query Builder를 MongoDB Query Object로 변환합니다. 예
433440
- ✅ 핵심 결정 사항 문서화 완료
434441
- 🔄 기존 문서에 교차 참조 추가 시작
435442

436-
### 문서 정리 (Step 3)
437-
1. `architecture/00-overview.md` - Frontend 서빙 로직 명확화
438-
2. `technical/02-authentication.md` - 로컬 로그인 우선 + 선택 OAuth + PIN으로 수정
439-
3. `modules/01-development-guide.md` - 교차 참조 추가
443+
### 문서 정리 (Step 3)
444+
1. `architecture/00-overview.md` - Frontend 서빙 로직 명확화
445+
2. `technical/02-authentication.md` - 로컬 로그인 우선 + 선택 OAuth + PIN으로 수정
446+
3. `modules/01-development-guide.md` - 교차 참조 추가
440447

441448
### 구현 시작 (Step 2)
442449
- 문서 정리 완료 후 코어 구현 시작
@@ -445,4 +452,58 @@ MongoDBProvider는 Query Builder를 MongoDB Query Object로 변환합니다. 예
445452

446453
> 💡 **중요:**
447454
> 이 문서의 결정사항은 프로젝트 전반에 영향을 미칩니다.
448-
> 변경이 필요한 경우 반드시 문서를 업데이트하고 버전을 올립니다.
455+
> 변경이 필요한 경우 반드시 문서를 업데이트하고 버전을 올립니다.
456+
457+
458+
## 결정 #5: API 네임스페이스 분리 (Internal vs. External)
459+
460+
### ✅ 결정 사항
461+
462+
**내부 UI용 API(`/local-api/`)와 외부 AI/에이전트 연동용 API(`/api/`)를 완전히 분리**하여 운영합니다.
463+
464+
### 📖 배경
465+
466+
Fieldstack은 프라이버시 중심의 개인 시스템이지만, OpenClaw와 같은 외부 AI 에이전트와의 연동 필요성이 제기되었습니다. 내부 전용 API를 그대로 노출할 경우 보안 위험이 크고, AI가 이해하기 어려운 복잡한 구조를 가질 수 있습니다.
467+
468+
### 🔍 네임스페이스 구분
469+
470+
#### 1. Internal API (`/local-api/*`)
471+
- **대상**: Fieldstack 자체 프론트엔드 (React SPA)
472+
- **인증**: HttpOnly 쿠키 기반 세션 (보안 최우선)
473+
- **특징**: 고성능 통신, 모든 기능(CRUD) 노출, UI 최적화 데이터 구조
474+
475+
#### 2. External API (`/api/*`)
476+
- **대상**: OpenClaw, ChatGPT, 전용 모바일 앱 등 외부 서비스
477+
- **인증**: Scoped API Key 또는 OAuth2 (제한된 권한)
478+
- **특징**: AI 친화적 단순 데이터 구조, OpenAPI 명세 필수, 속도 제한(Rate Limit) 적용
479+
480+
### 💡 기대 효과
481+
482+
1. **보안 강화**: 실수로 중요 관리 기능을 외부에 노출할 위험을 원천 차단합니다.
483+
2. **AI 에이전트 연동 용이**: AI가 이해하기 쉬운 `manifest.json`과 단순화된 스키마를 제공할 수 있습니다.
484+
3. **독립적 버전 관리**: UI 변경에 따른 내부 API 수정이 외부 연동 서비스(스킬)를 깨뜨리지 않도록 보호합니다.
485+
486+
### 🎯 구현 방향
487+
488+
모듈 개발자는 `module.json`을 통해 외부 노출 여부를 결정합니다.
489+
```json
490+
{
491+
"name": "ledger",
492+
"exposedSkills": [
493+
{
494+
"id": "get-monthly-stats",
495+
"path": "/stats",
496+
"description": "월간 가계부 지출 통계를 조회합니다."
497+
}
498+
]
499+
}
500+
```
501+
외부 에이전트는 `/api/manifest.json`을 통해 사용 가능한 스킬 목록을 한눈에 파악할 수 있습니다.
502+
503+
### 📚 관련 문서
504+
505+
> 📖 **AI 통합 정책:**
506+
> `technical/03-ai-integration.md § 외부 AI Agent 연동`
507+
508+
> 📖 **OpenAPI Baseline:**
509+
> `technical/05-openapi-baseline.yaml`

docs/v2_FINANCIAL-LEDGER/modules/01-development-guide.md

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,23 @@ example 폴더를 복사하여 my-module이라는 새 폴더로 만들고, 해
1818

1919
### 2. module.json 수정
2020

21-
모듈의 메타데이터를 정의하는 파일입니다. name은 내부 식별명, version은 버전, displayName은 표시 이름, description은 설명, icon은 아이콘 이모지입니다. routes에는 프론트엔드 경로와 API 경로를 정의하고, permissions에는 필요한 권한(예: db:read, db:write)을 목록으로 넣습니다. dependencies는 의존하는 다른 모듈 목록이고, enabled는 활성화 여부입니다.
21+
모듈의 메타데이터를 정의하는 파일입니다.
22+
23+
```json
24+
{
25+
"name": "my-module",
26+
"version": "1.0.0",
27+
"displayName": "내 모듈",
28+
"exposedSkills": [
29+
{
30+
"id": "get-summary",
31+
"path": "/summary",
32+
"description": "모듈 데이터 요약을 외부 AI에 제공합니다."
33+
}
34+
]
35+
}
36+
```
37+
`exposedSkills`는 OpenClaw 같은 외부 AI 에이전트에게 노출할 기능을 정의합니다.
2238

2339
---
2440

@@ -77,6 +93,23 @@ DELETE /:id 엔드포인트는 삭제입니다. service.remove를 호출하여
7793
> `technical/01-database.md`
7894
> `architecture/01-decisions.md § 결정 #3: DB 추상화`
7995
96+
Core의 `db`, `eventBus`, `core` 컨텍스트를 주입받아 사용합니다.
97+
98+
### 서비스 호출 (Service-to-Service)
99+
다른 모듈의 기능이 필요한 경우 Core의 Registry를 통해 서비스를 요청합니다.
100+
```typescript
101+
const ledgerService = this.core.getService('ledger');
102+
if (ledgerService) {
103+
await ledgerService.createEntry({...});
104+
}
105+
```
106+
107+
### DB 및 이벤트
108+
109+
create 함수는 새 항목을 생성합니다. 완료 후 'my-module:created' 이벤트를 Event Bus에 발행합니다.
110+
111+
---
112+
80113
Core의 db와 eventBus를 가져와 사용합니다.
81114

82115
list 함수는 해당 사용자의 my_module_items를 생성 시간 내림차순으로 조회합니다.
@@ -243,16 +276,16 @@ module-registry 저장소에 PR 제출
243276
- 📖 `architecture/00-overview.md § Module Layer` - 모듈 레이어 설명
244277
- 📖 `architecture/04-directory-structure.md` - 디렉터리 구조
245278

246-
### 기술
247-
- 📖 `technical/01-database.md` - DB 추상화 레이어
248-
- 📖 `technical/04-scheduler.md` - Scheduler 사용법
249-
- 📖 `technical/05-openapi-baseline.yaml` - OpenAPI baseline
250-
- 📖 `modules/02-integrations.md` - 외부 서비스 통합
251-
252-
### 테스트 베이스라인 (Phase 1.4)
253-
- Vitest 기반 단위 테스트는 `packages/core/src/**/*.test.ts`에 추가합니다.
254-
- API 통합 스모크 테스트는 `apps/api/src/integration/*.test.ts`에 추가합니다.
255-
- 모듈 로더 계약 검증은 `apps/api/src/loader/index.test.ts`를 기준으로 확장합니다.
279+
### 기술
280+
- 📖 `technical/01-database.md` - DB 추상화 레이어
281+
- 📖 `technical/04-scheduler.md` - Scheduler 사용법
282+
- 📖 `technical/05-openapi-baseline.yaml` - OpenAPI baseline
283+
- 📖 `modules/02-integrations.md` - 외부 서비스 통합
284+
285+
### 테스트 베이스라인 (Phase 1.4)
286+
- Vitest 기반 단위 테스트는 `packages/core/src/**/*.test.ts`에 추가합니다.
287+
- API 통합 스모크 테스트는 `apps/api/src/integration/*.test.ts`에 추가합니다.
288+
- 모듈 로더 계약 검증은 `apps/api/src/loader/index.test.ts`를 기준으로 확장합니다.
256289

257290
### UI
258291
- 📖 `ui/01-core-components.md` - Core UI 컴포넌트
@@ -275,4 +308,4 @@ module-registry 저장소에 PR 제출
275308

276309
> 💬 **도움이 필요하신가요?**
277310
> → Discord: https://discord.gg/5m4aHKmWgg
278-
> → GitHub Discussions: https://github.com/.../discussions
311+
> → GitHub Discussions: https://github.com/.../discussions

0 commit comments

Comments
 (0)