wiki: Topic_Blog 신규 문서 일괄 추가 + ASTRA 성장 자산 동기화
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
---
|
||||
id: pattern-api-client
|
||||
title: "API Client Pattern"
|
||||
category: "Pattern_Web"
|
||||
status: "draft"
|
||||
verification_status: "applied"
|
||||
canonical_id: ""
|
||||
aliases: ["API client", "HTTP client", "API 클라이언트 패턴", "adapter", "SDK wrapper"]
|
||||
duplicate_of: ""
|
||||
source_trust_level: "A"
|
||||
confidence_score: 0.88
|
||||
created_at: 2026-06-13
|
||||
updated_at: 2026-06-13
|
||||
review_reason: ""
|
||||
merge_history: []
|
||||
tags: ["pattern", "web", "api", "http", "platform-independent"]
|
||||
raw_sources: ["일반 소프트웨어 공학 지식", "AstraAI/src/features/providers/*, src/integrations/telegram/telegramClient.ts (적용 예)"]
|
||||
applied_in: ["AstraAI"]
|
||||
github_commit: ""
|
||||
---
|
||||
|
||||
# [[API Client Pattern]]
|
||||
|
||||
## 🎯 한 줄 통찰 (One-line insight)
|
||||
API Client 패턴은 "외부 HTTP/SDK 호출을 한 모듈로 캡슐화" 해 인증·재시도·타임아웃·에러 정규화·취소를 한 곳에서 관리하고, 호출부는 깨끗한 메서드만 보게 한다.
|
||||
|
||||
## 🧠 핵심 개념 (Core concepts)
|
||||
1. **단일 클라이언트:** baseURL/헤더/인증을 한 곳에.
|
||||
2. **횡단 관심사:** 재시도·타임아웃·취소(AbortSignal)·로깅·에러 변환을 내장.
|
||||
3. **응답 정규화:** 다양한 응답을 내부 표준 형태로.
|
||||
4. **인증 주입:** 토큰을 getter 로(갱신 반영).
|
||||
5. **에러 passthrough/translate:** 실패를 호출부가 쓸 수 있는 형태로.
|
||||
|
||||
## 📖 세부 내용 (Details · 패턴 명세)
|
||||
- **Problem (언제 쓰나):** 외부 API/SDK 를 여러 곳에서 호출, 인증·재시도·에러 처리가 반복될 때.
|
||||
- **사용 조건:** 호출 인터페이스 정의 가능; 인증/설정 중앙화 가능.
|
||||
- **장점:** 중복 제거, 일관된 에러/재시도/취소, 교체·모킹 용이, 테스트성.
|
||||
- **단점:** 추상화 비용, 만능 클라이언트화 위험.
|
||||
- **대안:** fetch 직접(소규모), 생성된 SDK, GraphQL 클라이언트.
|
||||
- **실패 사례:** 타임아웃/취소 누락으로 멈춤; 토큰 하드코딩(갱신 안 됨); 에러 삼킴; 재시도에 backoff 없어 폭주; 응답 형식 호출부 산재.
|
||||
|
||||
## 💻 코드 패턴 (Code patterns)
|
||||
```text
|
||||
class Client {
|
||||
constructor({ getToken, baseUrl }) # 인증은 getter 주입
|
||||
async call(path, body, { signal }) {
|
||||
const s = combine(signal, timeout(ms)) # 취소+타임아웃
|
||||
res = await fetch(baseUrl+path, { headers:{Authorization:getToken()}, signal:s })
|
||||
if (!res.ok) return normalizeError(res) # 에러 정규화/passthrough
|
||||
return parse(res) # 응답 정규화
|
||||
}
|
||||
}
|
||||
```
|
||||
적용 예: AstraAI 의 provider 어댑터(공급자별 차이 흡수→공통 SSE)와 TelegramHttpClient(getToken 게터). → [[LLM 프로바이더 추상화]], [[AITRAIN 프로바이더 추상화]].
|
||||
|
||||
## ⚖️ 모순 및 업데이트 (Contradictions & updates)
|
||||
얇은 호출이면 fetch 직접이 낫다 — 인증/재시도/에러가 반복될 때만 클라이언트 추상화가 이득.
|
||||
|
||||
## 🛠️ 적용 사례 (Applied in summary)
|
||||
AstraAI providers + telegramClient.
|
||||
|
||||
## 🔗 지식 그래프 (Knowledge Graph)
|
||||
- **상위/루트:** [[패턴 카탈로그 인덱스]]
|
||||
- **관련 개념:** [[Async Concurrency Pattern]], [[Error Handling Pattern]], [[Caching Pattern]], [[Tool Calling Pattern]]
|
||||
- **참조 맥락:** 작은 모델이 외부 API 통합 코드를 작성할 때 참조.
|
||||
|
||||
## 📚 출처 (Sources)
|
||||
- [S1] 일반 API 클라이언트 지식
|
||||
- [S2] AstraAI/src/features/providers/*, integrations/telegram/telegramClient.ts — 적용 예
|
||||
|
||||
## 📝 변경 이력 (Change history)
|
||||
- 2026-06-13: 프로젝트 독립 패턴 카드 작성.
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
id: pattern-infinite-scroll
|
||||
title: "Infinite Scroll Pattern"
|
||||
category: "Pattern_Web"
|
||||
status: "draft"
|
||||
verification_status: "conceptual"
|
||||
canonical_id: ""
|
||||
aliases: ["infinite scroll", "무한 스크롤", "pagination", "cursor pagination", "virtualization"]
|
||||
duplicate_of: ""
|
||||
source_trust_level: "A"
|
||||
confidence_score: 0.85
|
||||
created_at: 2026-06-13
|
||||
updated_at: 2026-06-13
|
||||
review_reason: ""
|
||||
merge_history: []
|
||||
tags: ["pattern", "web", "frontend", "pagination", "platform-independent"]
|
||||
raw_sources: ["일반 프런트엔드 공학 지식"]
|
||||
applied_in: []
|
||||
github_commit: ""
|
||||
---
|
||||
|
||||
# [[Infinite Scroll Pattern]]
|
||||
|
||||
## 🎯 한 줄 통찰 (One-line insight)
|
||||
무한 스크롤은 "사용자가 끝에 도달하면 다음 페이지를 자동 로드" 하는 패턴으로, *커서 기반 페이징 + DOM 가상화 + 중복/경쟁 요청 방지* 가 없으면 성능과 정확성이 무너진다.
|
||||
|
||||
## 🧠 핵심 개념 (Core concepts)
|
||||
1. **트리거:** IntersectionObserver 로 sentinel 가시화 감지.
|
||||
2. **커서 페이징:** offset 대신 cursor(마지막 항목 키) — 삽입/삭제에 안정.
|
||||
3. **가상화:** 화면 밖 항목은 DOM 에서 제거(react-window 등).
|
||||
4. **중복/경쟁 방지:** 진행 중 로드 잠금, 이전 요청 취소.
|
||||
5. **상태:** 로딩/끝(hasMore)/에러 표시.
|
||||
|
||||
## 📖 세부 내용 (Details · 패턴 명세)
|
||||
- **Problem (언제 쓰나):** 큰 목록(피드/검색결과)을 점진 로드해 초기 부하를 줄일 때.
|
||||
- **사용 조건:** 페이징 API(가급적 커서); 항목 높이 처리.
|
||||
- **장점:** 빠른 초기 로드, 자연스러운 UX, 대용량 처리.
|
||||
- **단점:** 푸터 도달 불가, 딥링크/뒤로가기 어려움, 접근성/SEO 약함, 구현 복잡.
|
||||
- **대안:** 일반 페이지네이션(점프/SEO 좋음), "더 보기" 버튼(제어 명확).
|
||||
- **실패 사례:** offset 페이징 중 삽입→항목 중복/누락; 가상화 없이 DOM 폭증 렉; 중복 트리거로 같은 페이지 N번; 경쟁 요청 순서 꼬임; hasMore 미처리로 무한 호출.
|
||||
|
||||
## 💻 코드 패턴 (Code patterns)
|
||||
```text
|
||||
observer.observe(sentinel)
|
||||
onIntersect: if (!loading && hasMore) { loading=true; signal=abortPrev()
|
||||
page = await api.list({ cursor, signal }); items.push(...page.items)
|
||||
cursor = page.nextCursor; hasMore = !!cursor; loading=false }
|
||||
render: virtualize(items) # 화면 밖 제거
|
||||
```
|
||||
|
||||
## ⚖️ 모순 및 업데이트 (Contradictions & updates)
|
||||
무한 스크롤이 항상 옳지 않다 — 작업형 목록(테이블/검색)엔 페이지네이션이 제어·딥링크 면에서 낫다. 피드형에만 적합.
|
||||
|
||||
## 🛠️ 적용 사례 (Applied in summary)
|
||||
일반 웹/모바일 피드. (AstraAI 직접 사례 없음.)
|
||||
|
||||
## 🔗 지식 그래프 (Knowledge Graph)
|
||||
- **상위/루트:** [[패턴 카탈로그 인덱스]]
|
||||
- **관련 개념:** [[React State Pattern]], [[Async Concurrency Pattern]], [[Caching Pattern]], [[웹 개발 가이드]]
|
||||
- **참조 맥락:** 작은 모델이 큰 목록 UI 를 구현할 때 참조.
|
||||
|
||||
## 📚 출처 (Sources)
|
||||
- [S1] 일반 프런트엔드 페이징/가상화 지식
|
||||
|
||||
## 📝 변경 이력 (Change history)
|
||||
- 2026-06-13: 프로젝트 독립 패턴 카드 작성.
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
id: pattern-jwt-authentication
|
||||
title: "JWT Authentication Pattern"
|
||||
category: "Pattern_Web"
|
||||
status: "draft"
|
||||
verification_status: "conceptual"
|
||||
canonical_id: ""
|
||||
aliases: ["JWT", "토큰 인증", "access token", "refresh token", "stateless auth"]
|
||||
duplicate_of: ""
|
||||
source_trust_level: "A"
|
||||
confidence_score: 0.86
|
||||
created_at: 2026-06-13
|
||||
updated_at: 2026-06-13
|
||||
review_reason: ""
|
||||
merge_history: []
|
||||
tags: ["pattern", "web", "auth", "jwt", "security", "platform-independent"]
|
||||
raw_sources: ["일반 웹 보안 공학 지식"]
|
||||
applied_in: []
|
||||
github_commit: ""
|
||||
---
|
||||
|
||||
# [[JWT Authentication Pattern]]
|
||||
|
||||
## 🎯 한 줄 통찰 (One-line insight)
|
||||
JWT 인증은 "서명된 토큰에 사용자 정보를 담아 *서버 세션 없이* 상태 무관(stateless) 인증" 을 하는 패턴으로, 확장성은 좋지만 *토큰을 즉시 무효화하기 어렵다* 는 본질적 약점이 있다.
|
||||
|
||||
## 🧠 핵심 개념 (Core concepts)
|
||||
1. **access token(짧은 수명) + refresh token(긴 수명):** 짧은 access 로 노출 위험↓, refresh 로 재발급.
|
||||
2. **서명 검증:** 서버 비밀키로 서명, 변조 시 검증 실패(저장 불필요).
|
||||
3. **claims:** sub/exp/role 등 페이로드(민감정보 금지 — base64 는 암호화 아님).
|
||||
4. **저장 위치:** httpOnly 쿠키(XSS 안전) vs localStorage(XSS 취약).
|
||||
5. **무효화:** 블랙리스트/짧은 만료/회전으로 보완.
|
||||
|
||||
## 📖 세부 내용 (Details · 패턴 명세)
|
||||
- **Problem (언제 쓰나):** 분산/무상태 API, 여러 서비스가 같은 토큰 검증(SSO), 모바일+웹 공용.
|
||||
- **사용 조건:** 비밀키 안전 보관; HTTPS; 토큰 수명 정책.
|
||||
- **장점:** 무상태(수평 확장), 서비스 간 공유, DB 조회 없이 검증.
|
||||
- **단점:** 즉시 무효화 어려움(로그아웃/탈취), 페이로드 노출, 토큰 비대.
|
||||
- **대안:** 서버 세션(즉시 무효화 쉬움, 상태 필요), OAuth/OIDC(위임), API key(머신).
|
||||
- **실패 사례:** localStorage 저장→XSS 탈취; refresh 회전 없이 탈취 지속; 민감정보를 claims 에; 만료 너무 길어 탈취 피해 확대; 서명 알고리즘 `none` 허용.
|
||||
|
||||
## 💻 코드 패턴 (Code patterns)
|
||||
```text
|
||||
login: verify(creds) -> access=sign({sub,exp:15m}), refresh=sign({sub,exp:7d}); setHttpOnlyCookie
|
||||
request: verifySignature(access) && !expired -> allow ; else 401
|
||||
refresh: verify(refresh) && !revoked -> rotate(new access+refresh), invalidate old
|
||||
logout: revoke(refresh) # 블랙리스트/회전
|
||||
```
|
||||
|
||||
## ⚖️ 모순 및 업데이트 (Contradictions & updates)
|
||||
"JWT 가 세션보다 낫다" 는 과장 — 즉시 무효화·서버측 제어가 중요하면 세션이 낫다. JWT 는 *무상태 확장* 이 목적일 때.
|
||||
|
||||
## 🛠️ 적용 사례 (Applied in summary)
|
||||
일반 웹/모바일 API 인증. (AstraAI 는 로컬 도구라 직접 사례 없음 — provider API key 는 [[API Client Pattern]] 참조.)
|
||||
|
||||
## 🔗 지식 그래프 (Knowledge Graph)
|
||||
- **상위/루트:** [[패턴 카탈로그 인덱스]]
|
||||
- **관련 개념:** [[API Client Pattern]], [[웹 개발 가이드]], [[소프트웨어 실패 라이브러리]]
|
||||
- **참조 맥락:** 작은 모델이 웹/모바일 인증을 구현할 때 참조.
|
||||
|
||||
## 📚 출처 (Sources)
|
||||
- [S1] 일반 웹 보안/JWT 지식(RFC 7519, OWASP)
|
||||
|
||||
## 📝 변경 이력 (Change history)
|
||||
- 2026-06-13: 프로젝트 독립 패턴 카드 작성.
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
id: pattern-react-state
|
||||
title: "React State Pattern"
|
||||
category: "Pattern_Web"
|
||||
status: "draft"
|
||||
verification_status: "conceptual"
|
||||
canonical_id: ""
|
||||
aliases: ["React state", "리액트 상태 패턴", "hooks", "lifting state up", "server state"]
|
||||
duplicate_of: ""
|
||||
source_trust_level: "A"
|
||||
confidence_score: 0.85
|
||||
created_at: 2026-06-13
|
||||
updated_at: 2026-06-13
|
||||
review_reason: ""
|
||||
merge_history: []
|
||||
tags: ["pattern", "web", "react", "frontend", "state", "platform-independent"]
|
||||
raw_sources: ["일반 프런트엔드 공학 지식"]
|
||||
applied_in: []
|
||||
github_commit: ""
|
||||
---
|
||||
|
||||
# [[React State Pattern]]
|
||||
|
||||
## 🎯 한 줄 통찰 (One-line insight)
|
||||
React(및 유사 선언형 UI) 상태의 핵심 규칙은 "**상태를 필요한 가장 낮은 곳에 두되, 공유되면 끌어올리고, 서버 데이터는 UI 상태와 분리**" 하는 것 — 이는 [[State Management Pattern]] 의 프런트엔드 구체화다.
|
||||
|
||||
## 🧠 핵심 개념 (Core concepts)
|
||||
1. **로컬 상태(useState):** 한 컴포넌트만 쓰는 상태.
|
||||
2. **lifting state up:** 두 형제가 공유하면 공통 부모로.
|
||||
3. **전역 상태(Context/Zustand/Redux):** 앱 전반 공유(과용 금지).
|
||||
4. **서버 상태(react-query/SWR):** 원격 데이터는 캐시·동기화 라이브러리로 분리.
|
||||
5. **파생 상태:** useMemo 로 계산, 저장하지 않음.
|
||||
|
||||
## 📖 세부 내용 (Details · 패턴 명세)
|
||||
- **Problem (언제 쓰나):** 컴포넌트 트리에서 상태 위치·공유 범위를 정할 때.
|
||||
- **사용 조건:** 선언형 UI; 단방향 데이터.
|
||||
- **장점:** 예측 가능 렌더, 재사용, 테스트성.
|
||||
- **단점:** prop drilling(전역 미사용 시), 과한 전역화는 리렌더·결합, 서버/클라 상태 혼동.
|
||||
- **대안:** 전역 store(공유 많을 때), 서버 상태 라이브러리, URL 상태(공유 가능 상태).
|
||||
- **실패 사례:** 서버 데이터를 useState 에 복사→stale·동기화 버그; 모든 걸 전역 store 에→불필요 리렌더·결합; 파생값 저장; 깊은 prop drilling.
|
||||
|
||||
## 💻 코드 패턴 (Code patterns)
|
||||
```text
|
||||
const [v, setV] = useState(init) # 로컬
|
||||
// 공유되면 부모로 올리고 props/context 로 전달
|
||||
const data = useQuery('key', fetcher) # 서버 상태는 분리(캐시/리페치)
|
||||
const total = useMemo(() => sum(items), [items]) # 파생은 계산
|
||||
```
|
||||
|
||||
## ⚖️ 모순 및 업데이트 (Contradictions & updates)
|
||||
"Redux 가 정석" 은 옛말 — 서버 상태는 react-query, 지역은 useState, 진짜 전역만 가벼운 store. 도구보다 *상태의 출처/수명* 으로 위치를 정하라.
|
||||
|
||||
## 🛠️ 적용 사례 (Applied in summary)
|
||||
일반 React 앱. (AstraAI 웹뷰는 메시지 기반 — 원리는 [[State Management Pattern]] 와 동일.)
|
||||
|
||||
## 🔗 지식 그래프 (Knowledge Graph)
|
||||
- **상위/루트:** [[패턴 카탈로그 인덱스]]
|
||||
- **관련 개념:** [[State Management Pattern]], [[Data Flow Pattern]], [[Infinite Scroll Pattern]], [[웹 개발 가이드]]
|
||||
- **참조 맥락:** 작은 모델이 프런트엔드 상태를 설계할 때 참조.
|
||||
|
||||
## 📚 출처 (Sources)
|
||||
- [S1] 일반 React/프런트엔드 상태 지식
|
||||
|
||||
## 📝 변경 이력 (Change history)
|
||||
- 2026-06-13: 프로젝트 독립 패턴 카드 작성.
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
id: pattern-repository
|
||||
title: "Repository Pattern"
|
||||
category: "Pattern_Web"
|
||||
status: "draft"
|
||||
verification_status: "applied"
|
||||
canonical_id: ""
|
||||
aliases: ["Repository", "리포지토리 패턴", "data access layer", "DAO"]
|
||||
duplicate_of: ""
|
||||
source_trust_level: "A"
|
||||
confidence_score: 0.88
|
||||
created_at: 2026-06-13
|
||||
updated_at: 2026-06-13
|
||||
review_reason: ""
|
||||
merge_history: []
|
||||
tags: ["pattern", "web", "backend", "data-access", "platform-independent"]
|
||||
raw_sources: ["일반 소프트웨어 공학 지식", "AstraAI/src/features/_shared/eventSourcedStore.ts (적용 예)"]
|
||||
applied_in: ["AstraAI"]
|
||||
github_commit: ""
|
||||
---
|
||||
|
||||
# [[Repository Pattern]]
|
||||
|
||||
## 🎯 한 줄 통찰 (One-line insight)
|
||||
Repository 는 "도메인 코드와 데이터 저장 방식 사이에 *컬렉션처럼 보이는* 인터페이스를 두어, 비즈니스 로직이 DB/파일/API 의 세부를 모르게" 하는 패턴이다.
|
||||
|
||||
## 🧠 핵심 개념 (Core concepts)
|
||||
1. **인터페이스로 저장 추상화:** `find/save/delete` 같은 도메인 언어 메서드.
|
||||
2. **구현 교체:** 같은 인터페이스로 메모리/파일/SQL/원격 구현.
|
||||
3. **도메인 모델 반환:** raw 행이 아니라 도메인 객체.
|
||||
4. **쿼리 캡슐화:** 복잡 쿼리를 repository 안에.
|
||||
|
||||
## 📖 세부 내용 (Details · 패턴 명세)
|
||||
- **Problem (언제 쓰나):** 도메인 로직을 저장 기술과 분리하고 테스트(가짜 repo)하고 싶을 때.
|
||||
- **사용 조건:** 도메인 모델 정의; 저장 연산을 인터페이스로 표현 가능.
|
||||
- **장점:** 저장 교체 용이, 테스트성(in-memory repo), 도메인 순수, 쿼리 한 곳.
|
||||
- **단점:** 추상화 비용, 단순 CRUD 엔 과설계, leaky abstraction 위험.
|
||||
- **대안:** ORM 직접 사용(소규모), Active Record, 쿼리 빌더 직접.
|
||||
- **실패 사례:** repository 가 DB 세부를 누수(IQueryable 노출); 만능 repository(God repo); 도메인이 SQL 을 알게 됨.
|
||||
|
||||
## 💻 코드 패턴 (Code patterns)
|
||||
```text
|
||||
interface UserRepo { findById(id): User?; save(u: User): Result; list(): User[] }
|
||||
class FileUserRepo implements UserRepo { ... } # 교체 가능 구현
|
||||
class SqlUserRepo implements UserRepo { ... }
|
||||
service(repo: UserRepo) # 도메인은 인터페이스만 의존(주입)
|
||||
```
|
||||
적용 예: AstraAI 의 `createEventStore<E>` 가 read/append/count 로 저장을 추상화하고 도메인은 인터페이스만 사용([[이벤트 소싱 스토어 패턴]], [[AITRAIN 이벤트소싱 저장]]).
|
||||
|
||||
## ⚖️ 모순 및 업데이트 (Contradictions & updates)
|
||||
ORM 이 이미 repository 유사 추상을 주므로, 그 위에 또 repository 를 얹으면 중복일 수 있다 — 교체/테스트 필요가 명확할 때만.
|
||||
|
||||
## 🛠️ 적용 사례 (Applied in summary)
|
||||
AstraAI eventSourcedStore(도메인별 store 인스턴스화).
|
||||
|
||||
## 🔗 지식 그래프 (Knowledge Graph)
|
||||
- **상위/루트:** [[패턴 카탈로그 인덱스]]
|
||||
- **관련 개념:** [[의존성 주입과 서비스 인터페이스]], [[Architecture Separation Pattern]], [[Local Storage Pattern]], [[백엔드 API 개발 가이드]]
|
||||
- **참조 맥락:** 작은 모델이 데이터 접근 계층을 설계할 때 참조.
|
||||
|
||||
## 📚 출처 (Sources)
|
||||
- [S1] 일반 DDD/Repository 지식
|
||||
- [S2] AstraAI/src/features/_shared/eventSourcedStore.ts — 적용 예
|
||||
|
||||
## 📝 변경 이력 (Change history)
|
||||
- 2026-06-13: 프로젝트 독립 패턴 카드 작성.
|
||||
Reference in New Issue
Block a user