Files
CODE_ASSISTANT/specs/004-tauri-shell/data-model.md
T
2026-09-16 17:22:14 +09:00

4.7 KiB

Phase 1: Data Model — Tauri 기준 데스크톱 앱

Created: 2026-08-11 | Updated: 2026-09-09 | Plan: plan.md

이 기능은 새 데이터를 거의 안 만든다. 기존 스니펫을 보존하고 Tauri의 창·화면 상태만 관리한다.


1. Snippet — 기존 데이터 유지

저장소: %LocalAppData%\CodeAssist\snippets.db (SQLite)

출처: 3_windowsApp/CodeAssist.Shell/Storage/SnippetRepository.cs가 현재 형식의 참고 원본이다. Tauri는 스키마를 바꾸지 않고 기존 파일을 직접 쓴다.

필드 타입 규칙
name string . 중복 생성 거부
desc string 설명
body string 본문. 붙여넣을 때 원문 그대로 (FR-013)
category string 분류
usageCount int 사용할 때마다 +1
lastUsed timestamp 사용 시각

검증 규칙:

  • name 중복 생성 → 거부, 한글 오류 메시지
  • 빈 필수 필드 → 거부, 한글 오류 메시지
  • 오류는 화면에 토스트로 뜬다 (FR-022)

상태 변화: 생성 → (수정)* → (사용 시 usageCount+1, lastUsed 갱신)* → 삭제

보존 규칙:

  • 스키마 변경 금지
  • SQLite 저널 모드 변경 금지
  • 기존 파일이 없으면 같은 형식의 빈 저장소를 만든다

2. WindowState — Tauri 앱 상태

필드 의미
위치 (x, y) 마지막 창 자리
크기 (w, h) 마지막 창 크기
pinned 항상 위 고정 여부

저장 위치: %LocalAppData%\com.codeassist.app\. 위치·크기는 window-state 플러그인, pinned는 별도 단일 파일로 저장한다.

복원 규칙: 화면 밖 자리로는 복원하지 않는다. 모니터 구성이 바뀌어 저장된 자리가 화면 밖이면 보이는 자리로 되돌린다.


3. PasteTarget — 기존, 휘발성

창을 부르기 직전에 한 번 찍는 스냅샷. 저장 안 함(앱 종료 시 사라짐).

필드 의미
창 핸들 붙여넣을 대상
name 창 제목
app 프로그램 이름 (예: Code, notepad)

왜 스냅샷인가: 나중에 그 창이 닫혀도 "어디에 붙는지" 표시는 남아야 한다(FR-015). 그래서 소환 시점에 제목·프로그램명을 값으로 복사해 둔다.

생명주기: 창 소환 시 갱신 → 화면에 배지로 표시 → 다음 소환 때 덮어씀


4. Routes — 기존, 껍데기 메모리

화면이 이동할 때마다 껍데기에 보고하는 값. 챗봇 단축키 토글 규칙(FR-011)에 쓴다.

필드 의미 초기값
current 화면이 지금 있는 자리 /snap
lastSnap 마지막으로 있던 비-스니펫 자리 /snap

갱신 규칙: 보고받은 경로가 /snippet 으로 시작하지 않으면 lastSnap 도 같이 갱신. current 는 항상 갱신.

토글 판정:

창이 보이는 중 AND current 가 /snippet 이 아님  →  숨긴다
그 외                                          →  띄우고 lastSnap 으로 이동

5. BridgeMessage — 기존 계약

진실원천은 여기가 아니다. 아래 두 문서가 원본:

  • specs/001-snippet-palette/contracts/bridge-messages.md
  • specs/002-capture-to-chat/contracts/bridge-capture.md

환경별 전달 수단 매핑만 contracts/transport-mapping.md에 있다.

이 기능이 계약에 더하는 제약 1개:

Tauri에서 아직 안 만든 메시지는 성공 응답을 흉내내지 않는다. 사람이 읽을 수 있는 "아직 안 됨" 오류로 답하고, 화면은 그걸 토스트로 띄운다. (FR-023)

왜 이게 데이터 규칙인가: 빈 목록([])으로 답하면 "스니펫이 0개"와 "기능이 없음"이 구분되지 않는다. 구현 중 빠진 기능을 성공으로 오판하지 않게 한다.


6. HostKind — 프론트 내부

프론트가 bridge 사용 시점에 판별하는 값. 저장하지 않는다.

판별 조건 동작
tauri typeof window.__TAURI_INTERNALS__?.invoke === "function" 기준 데스크톱 앱 방식
webview2 window.chrome?.webview 있음 참고용 legacy 방식
browser 둘 다 없음 데스크톱 기능 없음

판별 순서 고정: tauriwebview2browser. Windows Tauri가 WebView2를 사용해도 Tauri invoke 통로를 먼저 고른다.

노출 범위: isWebView() 같은 기존 함수의 속만 바뀐다. 화면 코드는 HostKind를 몰라야 한다(FR-002, SC-001).