Appearance
아키텍처 개요
Canvas 프로젝트의 전체 아키텍처와 설계 원칙입니다.
시스템 구성
캔버스 노드(nodes, nodeOrder)는 PostgreSQL Node 테이블에 저장됩니다. UI 설정(속성 패널·라벨 표시)만 localStorage에 persist됩니다.
인증은 Google OAuth → JWT httpOnly 쿠키 방식입니다. 워크스페이스 API는 JWT가 필요하며, 멤버가 아닌 워크스페이스 접근은 403으로 차단됩니다.
설계 원칙
1. 단일 진실 공급원 (Store-first)
Fabric.js 객체는 뷰 표현이고, Zustand store의 nodes가 런타임 데이터 진실 공급원입니다. hooks가 양방향 동기화를 담당하고, 서버에는 문서 스냅샷으로 debounce 저장합니다.
2. 커맨드 패턴
모든 에디터 동작(도구 전환, 줌, 선택, 삭제)은 Command 인터페이스로 선언됩니다. 단축키(useGlobalShortcuts)와 UI가 동일한 executeCommand를 호출합니다. 실행 취소/다시 실행 커맨드는 있으나, 히스토리 스택은 아직 도구 변경만 추적하도록 설계되어 있습니다.
3. 선언적 노드 확장
새 노드 타입은 NodeDefinition 하나로 등록하면 도구 커맨드, 배치, 동기화가 자동 연결됩니다.
4. Feature 모듈화
캔버스 관련 로직은 features/canvas/에 hooks + utils로 분리하고, components/canvas/는 얇은 React 래퍼만 유지합니다. 워크스페이스·인증은 features/workspace/, features/auth/에 분리합니다.
5. 모노레포 공유
타입·DTO·설정은 packages/에서 공유해 web/api 간 중복을 방지합니다.
프로젝트 개요·변경 이력
기술 스택·타임라인·일자별 PR 기록은 프로젝트 개요 · 업데이트 노트를 참고하세요.
레이어 구조 (web)
routes/ → 페이지 & 레이아웃 (/ , /login , /canvas , /canvas/:id)
components/ → 재사용 UI (canvas, sidebar, ui)
features/ → 도메인 hooks & utils (canvas, workspace, auth, shortcuts)
stores/ → 전역 상태 (commands, nodes, workspace, persistence)
lib/ → 범용 유틸레이어 구조 (api)
auth/ → Google OAuth, JWT, logout
users/ → 사용자 조회 (/users/me)
workspaces/ → 워크스페이스 CRUD, 노드 문서 동기화
prisma/ → PrismaService (@Global)
links/ → CRUD 예제 (스캐폴딩)주요 데이터 타입
typescript
// AppState = Canvas + History + Selection + Editor + Nodes + Workspace
type AppState = CanvasState & HistoryState & SelectionState & EditorState & NodesState & WorkspaceState;
// Tool = 'move' | NodeTool
type Tool = 'move' | 'text' | ...;
// CanvasNodeState = TextNodeState | ...
type CanvasNodeState = TextNodeState | ...;