83 lines
6.4 KiB
Markdown
83 lines
6.4 KiB
Markdown
# 윈도우 데스크톱 런처 (WebView2 로 2_frontend 감싸기) — 설계
|
|
|
|
작성일: 2026-08-04
|
|
스코프: **B (껍데기 + 창 관리)** — raycast/wox/alfred 스타일 런처 셸
|
|
상태: 설계 승인됨 → 구현 계획(writing-plans) 대기
|
|
|
|
## 1. 뭘 만드나 / 왜
|
|
|
|
지금 `2_frontend/` React SPA 를 **윈도우 닷넷(WPF + WebView2)** 앱 안에 담아서, 전역 단축키로 소환하는 런처처럼 쓴다. 알맹이(챗·기능)는 지금 React 앱 그대로. 이번에 만드는 건 **껍데기(셸)** — 어떻게 뜨고 사라지고 상주하냐.
|
|
|
|
## 2. 핵심 전략 — V1 껍데기 재활용
|
|
|
|
`d:\project\021.code-assistant\3_windowsApp\` 에 V1 이 있음. 런처 껍데기(단축키·트레이·창관리)는 거기 다 만들어져 있어서 **그대로 이식**하고, "바뀐 로직"(닷넷이 챗·인증을 네이티브로 하던 부분)만 버린다. V2 는 React 가 `/api` 를 직접 부르니 그 네이티브 로직이 필요 없음.
|
|
|
|
| V1 요소 | V2 처리 |
|
|
|---|---|
|
|
| `CodeAssist.Shell` 전체 (HotKeyService·SingleInstanceGuard·ForegroundWindow·PasteService·ClipboardBackup·TrayIconHost·FramelessPaletteWindow·JsonWindowPlacementStore·ViteDevServer) | **그대로 이식** — 런처 원시기능, 로직 안 바뀜 |
|
|
| `App.xaml.cs` 뼈대 (단일인스턴스→핫키→포그라운드 캡처→팔레트 토글→트레이) | **이식** — V1 이 디버그용으로 주석 처리해둔 트레이·blur-to-hide 를 되살림 |
|
|
| WebView A/B 로딩 (DEBUG=vite, RELEASE=가상호스트 `SetVirtualHostNameToFolderMapping`) | **이식** — 소스 경로만 V1 의 `web/` → V2 의 `2_frontend/` 로 교체 |
|
|
| `Core.Chat`·`Core.Auth`·네이티브 `ChatView`/ViewModels·브릿지의 chat/auth/session 핸들러·Markdig | **버림** (지금은). V2 React 가 `/api` 직접 호출로 다 함 |
|
|
| 브릿지 `paste.code`·`window.hide`·`window.resize` | **v1 제외, 다음 단계** — 런처 감칠맛(직전 창에 붙여넣기·Esc숨김·자동높이). React 쪽 `postMessage` 한 줄 필요해서 v1 필수 아님 |
|
|
|
|
> **Core 는 나중에 참고할 것.** V1 의 `CodeAssist.Core`(Auth·Chat: AuthClient, DpapiTokenStore, SseChatClient, HttpSessionClient, 토큰 브릿지 등)는 지금은 안 쓰지만 버리는 게 아니라 **레퍼런스로 남긴다.** 나중에 (1) auth 브릿지를 되살려 C#↔JS 로 refresh 토큰 영속·자동 재인증을 붙이거나, (2) RELEASE `/api` 프록시를 네이티브로 처리할 때 이 코드가 출발점이 됨. 구현 시 V1 `Core` 를 열어보고 참고.
|
|
|
|
## 3. 프로젝트 구조 (V2)
|
|
|
|
```
|
|
2_frontend/ (그대로, 손 안 댐)
|
|
3_windowsApp/
|
|
CodeAssist.App/ WPF 진입점 + PaletteWindow + WebHostView (챗/인증 로직 뺀 WebChatView)
|
|
CodeAssist.Shell/ V1 그대로 이식 (재활용 핵심)
|
|
CodeAssist.Tests/ Shell 관련 테스트만 이식 (WindowPlacement, SingleInstance 등)
|
|
```
|
|
|
|
- **`Core` 프로젝트는 이번에 안 만든다** — 네이티브 챗/인증이 사라져 쓸 데 없음. auth 브릿지 되살릴 때 그때 V1 Core 참고해서 추가.
|
|
- 스택: .NET 8 (`net8.0-windows`) · WPF · WebView2 · (WPF-UI 는 창 스타일용, 옵션)
|
|
|
|
## 4. 동작 흐름
|
|
|
|
1. 부팅 → 트레이 상주 (단일 인스턴스 — 두 번째 실행은 기존 창 소환 후 종료)
|
|
2. `Ctrl+Alt+Space` → 직전 창 HWND 캡처 → 팔레트 Show (마지막 위치/크기 복원)
|
|
3. 창 안엔 **2_frontend React 앱** (DEBUG=vite 핫리로드 / RELEASE=dist 가상호스트)
|
|
4. `Esc` 또는 포커스 잃음(Deactivated) → Hide (위치·크기 저장)
|
|
5. 트레이 우클릭 → "종료" (평소 X 는 종료 대신 숨김)
|
|
|
|
## 5. 창·단축키 기본값 (V1 준용)
|
|
|
|
- 전역 단축키: **`Ctrl+Alt+Space`** (`Alt+Space` 시스템 메뉴 충돌 회피)
|
|
- 창: 테두리 있는 크기조절 가능한 일반 창, `CenterScreen` 최초 위치, 위치·크기 기억(`JsonWindowPlacementStore`)
|
|
- (다음 단계) web 이 알려준 컨텐츠 높이로 스르륵 리사이즈 — spotlight 느낌. 브릿지 `window.resize` 되살릴 때.
|
|
|
|
## 6. WebView 로딩 (A/B 둘 다 지원, 소스 주소만 분기)
|
|
|
|
V1 `WebChatView.OnLoaded` 패턴 그대로:
|
|
|
|
- **DEBUG**: `ViteDevServer` 로 `2_frontend` 의 `npm run dev` 를 띄우고 포트 대기 → `http://localhost:<port>` navigate. 핫리로드. `/api` 는 vite 가 백엔드로 프록시(지금 그대로).
|
|
- **RELEASE**: `2_frontend/dist` 를 출력 폴더로 복사 → `SetVirtualHostNameToFolderMapping("appassets.example", wwwroot, ...)` → `https://appassets.example/index.html` navigate.
|
|
- `UserDataFolder` 는 temp 로 명시(초기화 실패 방지), 초기화/네비 로그를 temp 파일에 남김 — V1 패턴 유지.
|
|
|
|
주의: 2_frontend 는 **BrowserRouter** 라 RELEASE 가상호스트에서 딥링크 새로고침 시 404 가능 → 필요하면 그때 HashRouter 전환이나 fallback 처리. v1(DEBUG 중심)에선 문제 없음.
|
|
|
|
## 7. 알려진 미결(다음 단계) — RELEASE `/api` 프록시
|
|
|
|
- **DEBUG(vite)**: vite 가 `/api` 프록시 → 지금 인증/쿠키 그대로 동작. **v1 은 여기까지 완전히 굴러감.**
|
|
- **RELEASE(가상호스트)**: React 가 `/api` 부르면 가상호스트 폴더에서 찾다 404. 닷넷이 `/api` 를 백엔드로 프록시해줘야 함(`WebResourceRequested` 가로채기 등). 근데 이게 **쿠키 origin·Entra 로그인과 엮여서 이번에 제외한 auth 스코프와 겹침.**
|
|
- **결정**: v1 = **DEBUG 모드로 런처 껍데기 완성·검증**(단축키·트레이·창관리·React 로딩 확인). RELEASE 패키징의 `/api` 프록시 + 쿠키 origin + Entra 로그인은 **auth 스코프 되살릴 때 함께 푸는 다음 단계.** (V1 `Core` 참고)
|
|
|
|
## 8. 이번 스코프에서 명시적으로 제외
|
|
|
|
- Entra/MSAL 로그인 데스크톱 처리 (Q3 제외됨)
|
|
- 런처 전용 신규 UI (C안 — 나중에)
|
|
- 브릿지 paste/hide/resize (다음 단계)
|
|
- RELEASE 패키징의 `/api` 프록시 (7번, auth 와 함께)
|
|
|
|
## 9. 성공 기준 (v1)
|
|
|
|
- [ ] `Ctrl+Alt+Space` 로 창이 뜨고/사라진다
|
|
- [ ] 트레이 상주 + 우클릭 종료, X 는 숨김
|
|
- [ ] 단일 인스턴스 (두 번째 실행이 기존 창 소환)
|
|
- [ ] 창 위치·크기가 기억된다
|
|
- [ ] 창 안에 2_frontend React 앱이 뜬다 (DEBUG=vite 핫리로드, `/api` 정상)
|
|
- [ ] Shell 이식분 테스트 통과 (WindowPlacement, SingleInstance 등)
|