diff --git a/apps/desktop/src/renderer/pages/MeetingModePage.tsx b/apps/desktop/src/renderer/pages/MeetingModePage.tsx index d223bbb..0444d2a 100644 --- a/apps/desktop/src/renderer/pages/MeetingModePage.tsx +++ b/apps/desktop/src/renderer/pages/MeetingModePage.tsx @@ -163,6 +163,9 @@ export function MeetingModePage(): React.ReactElement { const handleMemoKeyDown = useCallback( (e: React.KeyboardEvent) => { + // 한글 IME 조합 중 Enter는 keydown을 2번 발화(조합 확정 + 실제 Enter)하므로 + // isComposing=true인 이벤트는 무시해 addMemo 중복 호출 방지 + if (e.nativeEvent.isComposing || e.keyCode === 229) return if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault() handleAddMemo() diff --git a/memory/project_status.md b/memory/project_status.md index d5486c6..bc6a148 100644 --- a/memory/project_status.md +++ b/memory/project_status.md @@ -208,6 +208,60 @@ OAuth provider도 아직 Supabase에 설정 안 된 상태. 강제 게이트는 - `~/Library/Application Support/d3ro-voice/users/${uuid}/d3ro.db` 파일 생성 확인 - 기존 `d3ro-voice.db`가 있는 환경에서 archive rename 동작 확인 +### SaaS [11] Meeting pre-push 직접 실증 + IME Enter 중복 addMemo 픽스 (Phase 5 Part 4, 2026-04-11) + +> **U2 해소.** Meeting 모드 녹음을 직접 돌려 Fix 1(startRecording pre-push) + addMemo hook을 실시간 로그로 증명. 부수적으로 발견된 한글 IME Enter 중복 addMemo 버그(Bug 10)를 `isComposing` 가드로 픽스. + +**직접 실증 타임라인 (session 78421e75, 21:51:24~21:51:50)** +``` +21:51:24.937 pushOne meetings/78421e75 ok ← Fix 1 pre-push (813ms after startRecording) +21:51:30.499 pushOne meeting_memos/4ed7e59a ok ← addMemo #1 "메모가" +21:51:32.202 pushOne meeting_memos/de011c15 ok ← addMemo #2 "두번씩" +21:51:35.893 pushOne meeting_memos/3184fe5e ok ← addMemo #3 "입력되는걸 막아야합니다." +21:51:38.263 pushOne meeting_memos/00f041ef ok ← addMemo #4 "잘되는지 봅시다." +21:51:40.740 pushOne meeting_memos/0808c4d2 ok ← addMemo #5 "잘되는 것 같네요." +21:51:50.681 pushOne meetings/78421e75 ok ← _runPostProcessing hook +21:51:50.709 pushOne history/70388090 ok ← CaptionService → HistoryService.create +``` +- **meetings/78421e75가 녹음 시작 + 종료 두 번 push** → Fix 1 완전 증명 (부모 row가 메모 push 시점에 이미 Supabase에 존재해서 자식 RLS/FK 통과) +- **메모 5건 전부 100ms 내 1:1 push** → addMemo hook 정상, RLS 에러 0 +- **history push 출처 확인**: `CaptionService.ts:459`에서 회의 전사가 완료되면 전체 텍스트를 HistoryService에도 저장하는 기존 경로. Phase 3.3 훅이 `HistoryService.create()` 끝에 걸려 있어 자동으로 따라옴. 의도대로 동작. + +**발견+픽스한 버그 — Bug 10: 한글 IME Enter 중복 addMemo** +- 증상: 첫 번째 시연 녹음(bd7f2367)에서 "메모 기능이 잘 작동하는지 봅니다"가 **2ms 간격으로 2번** 저장됨 (UUID c7f0db45 + a6e442cc, 로그 21:47:57.410/.412). 다른 메모들은 1회. +- 원인: 한글 IME 조합 중 Enter 키는 Chromium이 `keydown`을 두 번 발화 — (1) IME 조합 확정용(`isComposing=true`, keyCode=229) + (2) 실제 Enter 액션. 기존 `handleMemoKeyDown`(MeetingModePage.tsx:164-174)은 `e.key === 'Enter' && !e.shiftKey`만 검사하고 `isComposing`을 무시해 두 이벤트 모두에서 `handleAddMemo()` 발화 → IPC 2회 → `MeetingModeService.addMemo()` 2회 → DB insert 2건 → `pushOne meeting_memos` 2회. 중복이 다른 메모에서 안 난 이유는 해당 메모들은 IME 조합이 이미 확정된 상태(공백/한자 변환 등)에서 Enter를 쳤기 때문. +- Fix: `MeetingModePage.tsx:168`에 이중 가드 추가. `if (e.nativeEvent.isComposing || e.keyCode === 229) return` — `isComposing`은 모던 표준, `keyCode === 229`는 Chromium 엣지 케이스(조합 확정 시점에 isComposing이 false로 내려가면서 keyCode만 229로 주는 경우) 호환. +- 검증: 두 번째 녹음(78421e75)에서 한글 메모 5건 연속 입력 → **전원 1:1 매핑**, 중복 0. Vite HMR로 즉시 반영, 별도 재기동 없이 fix 유효. + +**잠재 IME 버그 — 다른 Enter 핸들러 7곳 (다음 `/simplify` 때 일괄 처리 예정)** +| 파일 | 라인 | 용도 | 한글 위험도 | +|---|---|---|---| +| `KnowledgeBasePage.tsx` | 85 | RAG 쿼리 | 높음 | +| `VoiceConversationPage.tsx` | 114 | 텍스트 채팅 | 높음 | +| `components/meeting/MeetingChatPanel.tsx` | 113 | 미팅 챗 | 높음 | +| `components/meeting/EditableSegment.tsx` | 72 | 전사 세그먼트 편집 | 높음 | +| `components/meeting/MeetingDetailTabs.tsx` | 242 | 미팅 타이틀 | 중간 | +| `components/shared/HistoryEntryCard.tsx` | 65 | 태그 추가 | 중간 | +| `CommandsPage.tsx` | 337 | 키워드 추가 | 중간 | + +(LicenseModal.tsx:196은 ASCII 전용이라 제외) + +**검증** +- desktop `tsc --noEmit` ✅ (EXIT=0) +- Meeting 모드 녹음 1회차(bd7f2367): Fix 1 + addMemo hook 증명, IME 중복 1건 발견 +- Meeting 모드 녹음 2회차(78421e75): IME fix 적용 후 메모 5건 전부 1:1 ✅ +- Realtime 채널 상태: 여전히 U1 TIMED_OUT (블로커 아님, Phase 3.3 auto push가 대체 경로) + +**빅뱅 성공 기준 상태 — 이번 세션 갱신 없음** (8개 중 7개 완료, Phase 3.2 PREMIUM_LLM만 잔존) + +**다음 세션 권장 액션** +- `/simplify` 실행 — Phase 3.3 + Bug 10 fix 코드 품질 리뷰 + 위 7개 IME Enter 핸들러 일괄 가드 추가 +- Phase 3.2 PREMIUM_LLM Edge Function 경로 (Anthropic/OpenAI key 주입 필요, 사용자 의사결정 대기) +- U1 Realtime TIMED_OUT 원인 조사 (선택) +- `package-lock.json` optional dep 정리 (Phase 5 Part 2부터 이월) + +--- + ### SaaS [10] Phase 3.3 Auto push on write + 웹 transcript fallback + Dashboard Link 픽스 (Phase 5 Part 3, 2026-04-11) > **수동 Push 버튼이 사라졌다.** 로컬 SQLite write가 일어나는 모든 경로(8곳)에서 `CloudSyncService.pushOne`이 fire-and-forget으로 즉시 실행되어 Supabase에 반영. 웹 Dashboard 새로고침 한 번이면 방금 녹음한 미팅/메모/전사까지 전부 보인다. 이번 세션 한 번에 end-to-end 실증까지 통과.