Some checks are pending
Release Gate / gate (push) Waiting to run
- /permissions, /allowed-tools, /settings permissions를 동일 권한 상태 모델로 통합 - 권한 공통 처리 헬퍼 추가: 모드 적용(ask/auto/deny), 상태 요약 텍스트, 팝업 오픈 경로 통일 - /allowed-tools에서도 ask|auto|deny|status를 일관 동작으로 지원 - /mcp login/logout 및 reset 인증 초기화 반영 상태를 문맥에 맞게 유지 - 좌측/퀵 스트립 단순화 2차: 실패 필터는 rich 표현 레벨에서만 노출, balanced/simple 비노출 - 루프 복구 테스트 보강: unknown/disallowed/no-progress 혼합 관점 회귀 테스트 추가 - 문서 동기화: DEVELOPMENT.md, AGENT_ROADMAP.md에 2026-04-04 추가 진행 이력 반영 - 품질 게이트 확인: build 경고/오류 0, 전체 테스트 421 통과
2793 lines
180 KiB
Markdown
2793 lines
180 KiB
Markdown
# AX Commander — 개발 문서
|
||
|
||
---
|
||
|
||
## 📑 목차
|
||
|
||
1. [관련 문서](#관련-문서)
|
||
2. [사내 전용 프로그램 개발 원칙](#사내-전용-프로그램-개발-원칙)
|
||
3. [프로젝트 구조](#프로젝트-구조)
|
||
4. [아키텍처 개요](#아키텍처-개요)
|
||
5. [핵심 데이터 흐름](#핵심-데이터-흐름)
|
||
6. [각 핸들러 상세](#각-핸들러-상세)
|
||
7. [설정 UI (SettingsWindow)](#설정-ui-settingswindow)
|
||
8. [설정 스키마 (`settings.json`)](#설정-스키마-settingsjson)
|
||
9. [주요 기능 상세](#주요-기능-상세)
|
||
10. [데이터 저장 경로](#데이터-저장-경로)
|
||
11. [보안 고려사항](#보안-고려사항)
|
||
12. [테마 커스터마이징](#테마-커스터마이징)
|
||
13. [단위 테스트](#단위-테스트)
|
||
14. [코드 검토 이력](#코드-검토-이력)
|
||
15. [버그 수정 이력](#버그-수정-이력)
|
||
16. [알려진 제한사항 및 향후 개선](#알려진-제한사항-및-향후-개선)
|
||
17. [개발 환경](#개발-환경)
|
||
18. [경쟁 제품 기능 비교](#경쟁-제품-기능-비교)
|
||
19. [새로운 핸들러/키워드 추가 방법](#새로운-핸들러키워드-추가-방법-개발자-가이드)
|
||
20. [사내 LLM / AI Agent 연동 가이드](#사내-llm--ai-agent-연동-가이드-향후-확장)
|
||
21. [버전 이력](#버전-이력)
|
||
22. [개발 검토 — 워크플로우 병목 분석 그래프](#개발-검토--워크플로우-병목-분석-그래프)
|
||
23. [양식 기반 문서 생성 (Template Mode)](#양식-기반-문서-생성-template-mode)
|
||
|
||
---
|
||
|
||
## 관련 문서
|
||
|
||
| 문서 | 설명 |
|
||
|------|------|
|
||
| [AX Agent 로드맵](AGENT_ROADMAP.html) | AX Agent 대화 서비스 고도화 종합 계획 (Phase 2.5~11) |
|
||
| [AX Commander 로드맵](LAUNCHER_ROADMAP.html) | AX Commander 런처 고도화 계획 |
|
||
| [사용 가이드](../src/AxCopilot/Assets/AX%20Copilot%20사용가이드.htm) | 사용자용 단축키 & 예약어 가이드 |
|
||
|
||
---
|
||
|
||
## 사내 전용 프로그램 개발 원칙
|
||
|
||
> **AX Commander는 사내 전용 프로그램입니다.**
|
||
> 아래 원칙을 반드시 준수하여 개발하세요.
|
||
|
||
### 외부 연결 금지
|
||
|
||
| 금지 항목 | 설명 |
|
||
|-----------|------|
|
||
| 외부 HTTP/HTTPS 호출 | `HttpClient`, `WebClient`, `HttpWebRequest` 등으로 외부 서버에 요청 금지 |
|
||
| 외부 SDK 연동 | 서드파티 클라우드 SDK, AI API, SaaS 라이브러리 사용 금지 |
|
||
| 원격 플러그인 다운로드 | 런타임에 외부에서 DLL/코드 다운로드 금지 |
|
||
| 텔레메트리 / 오류 수집 | 사용 데이터를 외부 서버로 전송하는 일체의 코드 금지 |
|
||
| NuGet 패키지 | 외부 네트워크 통신이 내장된 패키지 신규 도입 금지 |
|
||
|
||
**허용**: 로컬 파일 시스템 접근, Windows API (P/Invoke), 사내 인트라넷 URL (명시적으로 허가된 경우만), 로컬 프로세스 실행.
|
||
|
||
### 외부 SDK 금지
|
||
|
||
기존에 등록된 `JsonSkillLoader`의 HTTP 스킬 기능(`type: "http"`)은 **사내 인트라넷 엔드포인트 전용**으로만 사용해야 합니다. 인터넷 접근이 필요한 기능은 구현하지 않습니다.
|
||
|
||
### 의존성 관리
|
||
|
||
신규 NuGet 패키지를 추가하기 전에 다음을 확인하세요:
|
||
1. 패키지가 외부 서버와 통신하는지 검토
|
||
2. 동일한 기능을 BCL(Base Class Library)이나 Windows API로 구현 가능한지 먼저 검토
|
||
3. 추가 시 `DEVELOPMENT.md`에 이유를 기록
|
||
|
||
### UI 색상·레이아웃 규칙
|
||
|
||
> **모든 UI 개발 시 아래 규칙을 반드시 준수하세요.** (상세: `docs/AI_Service_Review.html` §12.8)
|
||
|
||
1. **시스템 기본 컨트롤 사용 금지** — `ContextMenu`, `MessageBox`, `ComboBox` 드롭다운을 채팅 창에 사용하지 않음. 반드시 커스텀 `Popup` 기반으로 구현
|
||
2. **색상 하드코딩 금지** — `Brushes.White`, `#A0A4BE` 등 하드코딩하면 라이트/다크 테마 전환 시 대비가 깨짐
|
||
- XAML: `{DynamicResource PrimaryText}`, `{DynamicResource SecondaryText}` 등 리소스 키 사용
|
||
- 코드비하인드: `TryFindResource("PrimaryText") as Brush ?? Brushes.White` 패턴 사용
|
||
3. **수평 스크롤바 금지** — 아이콘/칩 목록은 `ScrollViewer` 가로 스크롤 대신 `WrapPanel`로 창 폭에 맞게 자동 줄바꿈
|
||
4. **Popup 내부에 `Button` 사용 금지** — 포커스 캡처로 팝업이 즉시 닫힘. `Border` + `MouseLeftButtonUp` 패턴 사용
|
||
5. **폰트 크기** — 메뉴 항목 13px 이상, 설명 텍스트 12px 이상 (가독성 확보)
|
||
6. **호버/클릭 효과 필수** — `#18FFFFFF` 반투명 배경 + 핸드 커서, 팝업 `PopupAnimation="Fade"` 기본 적용
|
||
7. **사용자 의사결정 UI = 하단 드롭다운 메뉴 패턴** — AI가 사용자에게 선택을 요청할 때(포맷, 디자인, 권한 등) 아이콘을 주욱 나열하지 않고 **컴팩트 드롭다운 버튼** `[라벨: 현재값 ▾]` → 클릭 시 `Popup` 메뉴 표시. 마지막 항목에 텍스트 입력 옵션 포함 가능.
|
||
- 설정(Settings)에서 해당 값의 기본값을 선택할 수 있어야 함
|
||
- 같은 패턴을 모든 탭(Chat, Cowork, Code)에 일관 적용
|
||
8. **프리뷰 패널 = 탭 기반** — 다중 파일 프리뷰를 탭으로 관리, 파일명 표시, 탭 축소, 외부 프로그램 실행 아이콘 포함
|
||
9. **켜기/끄기 UI = ToggleSwitch 스타일 사용** — 설정 창 등 모든 on/off 옵션에는 기본 `CheckBox`가 아닌 `Style="{StaticResource ToggleSwitch}"` 좌우 슬라이드 토글을 사용. 카테고리 선택 목록도 동일하게 적용 (Grid 좌: 라벨, 우: 토글)
|
||
10. **ContextMenu 사용 금지 → 커스텀 Popup 메뉴** — WPF 기본 `ContextMenu`/`MenuItem` 사용 금지. 모든 우클릭 메뉴·드롭다운을 커스텀 `Popup` (Border + MouseLeftButtonUp 패턴, 12px 라운드, 호버, 드롭섀도)으로 구현
|
||
9. **폴더 데이터 활용 시 관련성 검증 필수** — 적극 활용 모드에서도 대화 주제와 무관한 파일은 읽지 않음. 계획 단계에서 읽을 파일 목록과 이유를 먼저 제시
|
||
10. **인터랙티브 영역 최소 크기 36px** — 버튼·아이콘·메뉴 등 클릭 가능한 요소는 보내기 버튼(36×36)과 동일한 터치 크기 확보. FontSize 최소 12px, Padding 최소 6px. 폴더바·모델 선택 등 텍스트 영역도 MinHeight=34 이상
|
||
|
||
---
|
||
|
||
## 프로젝트 구조
|
||
|
||
```
|
||
AX Commander/
|
||
├── src/
|
||
│ ├── AxCommander/ # 메인 WPF 애플리케이션
|
||
│ │ ├── App.xaml / App.xaml.cs # 앱 진입점, 서비스 초기화, 트레이 아이콘
|
||
│ │ ├── Assets/
|
||
│ │ │ ├── icon.ico # 다이아몬드 픽셀 보석 아이콘 (7크기: 16~256px)
|
||
│ │ │ ├── diamond_pixel.svg # 아이콘 SVG 원본 (참고용)
|
||
│ │ │ ├── mascot.png # About 창 마스코트 이미지 (선택)
|
||
│ │ │ └── Quotes/
|
||
│ │ │ └── famous.json # 내장 명언 500개 (EmbeddedResource)
|
||
│ │ ├── Core/
|
||
│ │ │ ├── CommandResolver.cs # 프리픽스 기반 라우팅 테이블
|
||
│ │ │ ├── ContextManager.cs # 윈도우 스냅샷 & 복원 (워크스페이스)
|
||
│ │ │ ├── FuzzyEngine.cs # 퍼지 검색 + 한국어 초성 지원
|
||
│ │ │ ├── InputListener.cs # 전역 키보드 훅 (WH_KEYBOARD_LL)
|
||
│ │ │ └── PluginHost.cs # DLL/JSON 플러그인 로더
|
||
│ │ ├── Handlers/
|
||
│ │ │ ├── AliasHandler.cs # @(URL) ~(폴더) >(배치) 핸들러
|
||
│ │ │ ├── CalculatorHandler.cs # = 계산기 + 단위변환 + 통화변환
|
||
│ │ │ ├── ClipboardHandler.cs # $ 클립보드 변환 (12종 내장)
|
||
│ │ │ ├── ClipboardHistoryHandler.cs # # 클립보드 히스토리
|
||
│ │ │ ├── ColorHandler.cs # color HEX/RGB/HSL/HSV 변환기
|
||
│ │ │ ├── ColorPickHandler.cs # pick 스포이드 색상 추출
|
||
│ │ │ ├── DateCalcHandler.cs # date 날짜 계산/D-day/타임스탬프
|
||
│ │ │ ├── EncodeHandler.cs # encode base64/url/hex/md5/sha256
|
||
│ │ │ ├── EnvHandler.cs # env 환경변수 조회
|
||
│ │ │ ├── EmojiHandler.cs # emoji 이모지 피커 (300+ 이모지)
|
||
│ │ │ ├── JsonHandler.cs # json JSON 검증/포맷/미니파이
|
||
│ │ │ ├── JsonSkillLoader.cs # .skill.json HTTP API 연동
|
||
│ │ │ ├── NoteHandler.cs # note 빠른 메모 저장/조회
|
||
│ │ │ ├── PortHandler.cs # port 포트/프로세스 점검
|
||
│ │ │ ├── RecentFilesHandler.cs # recent Windows 최근 파일
|
||
│ │ │ ├── RenameHandler.cs # rename 파일 일괄 이름변경
|
||
│ │ │ ├── ScreenCaptureHandler.cs # cap 화면/창/스크롤 캡처
|
||
│ │ │ ├── ScaffoldHandler.cs # scaffold 프로젝트 스캐폴딩
|
||
│ │ │ ├── ServiceHandler.cs # svc Windows 서비스 관리
|
||
│ │ │ ├── SnapHandler.cs # snap 창 배치 레이아웃
|
||
│ │ │ ├── SnippetHandler.cs # ; 텍스트 스니펫
|
||
│ │ │ ├── SystemCommandHandler.cs # / 시스템 명령 + 타이머/알람
|
||
│ │ │ ├── TextStatsHandler.cs # stats 텍스트 통계 분석
|
||
│ │ │ ├── UninstallHandler.cs # uninstall 앱 제거 (레지스트리)
|
||
│ │ │ ├── FavoriteHandler.cs # fav 즐겨찾기 (파일·폴더)
|
||
│ │ │ ├── MonitorHandler.cs # monitor 시스템 리소스 모니터
|
||
│ │ │ └── WorkspaceHandler.cs # ! 워크스페이스 관리
|
||
│ │ ├── Models/
|
||
│ │ │ ├── AppSettings.cs # 설정 POCO (JSON 직렬화)
|
||
│ │ │ └── DailyUsageStats.cs # 일별 사용 통계 데이터 모델
|
||
│ │ ├── Services/
|
||
│ │ │ ├── ClipboardHistoryService.cs # WM_CLIPBOARDUPDATE 훅
|
||
│ │ │ ├── IndexService.cs # 파일 시스템 인덱서
|
||
│ │ │ ├── LogService.cs # 파일 로거
|
||
│ │ │ ├── NotificationService.cs # 트레이 풍선 알림 (타이머/알람)
|
||
│ │ │ ├── QuoteService.cs # 명언 JSON 로더 (famous.json 내장 리소스)
|
||
│ │ │ ├── SessionTrackingService.cs # PC 잠금/해제 시간 추적
|
||
│ │ │ ├── L10n.cs # 정적 다국어 서비스 (ko/en/ja/zh/vi)
|
||
│ │ │ ├── SettingsService.cs # settings.json 로드/저장
|
||
│ │ │ ├── UsageRankingService.cs # 실행 빈도 추적 & 퍼지 결과 정렬
|
||
│ │ │ ├── UsageStatisticsService.cs # 일별 통계 집계 (런처 호출/명령/활성시간)
|
||
│ │ │ ├── WindowTracker.cs # 이전 활성 창 핸들 보존 (snap/cap용)
|
||
│ │ │ └── WorktimeReminderService.cs # 잠금 해제 시 사용시간 알림 팝업 서비스
|
||
│ │ ├── Themes/
|
||
│ │ │ ├── Converters.cs # WPF 값 변환기
|
||
│ │ │ ├── Symbols.cs # Segoe MDL2 Assets 상수
|
||
│ │ │ ├── Dark.xaml / Light.xaml / OLED.xaml
|
||
│ │ │ ├── Nord.xaml / Monokai.xaml / Catppuccin.xaml / Sepia.xaml
|
||
│ │ │ ├── Alfred.xaml / AlfredLight.xaml
|
||
│ │ ├── ViewModels/
|
||
│ │ │ ├── LauncherViewModel.cs # 런처 MVVM ViewModel
|
||
│ │ │ ├── SettingsViewModel.cs # 설정 창 ViewModel + 보조 모델
|
||
│ │ │ │ # (ThemeCardModel, ColorRowModel,
|
||
│ │ │ │ # AppShortcutModel, SnippetRowModel)
|
||
│ │ │ └── StatisticsViewModel.cs # 사용 통계 창 ViewModel (DayBarItem, CommandStatItem)
|
||
│ │ └── Views/
|
||
│ │ ├── LauncherWindow.xaml/.cs # 메인 런처 UI
|
||
│ │ ├── LargeTypeWindow.xaml/.cs # Large Type 전체 화면 오버레이
|
||
│ │ ├── SettingsWindow.xaml/.cs # 설정 창 UI (좌측 사이드바 10탭)
|
||
│ │ ├── AboutWindow.xaml/.cs # 개발자 정보 창
|
||
│ │ ├── HelpDetailWindow.xaml/.cs # 도움말 전체 목록 카드 창
|
||
│ │ ├── EyeDropperWindow.xaml/.cs # 전체 화면 스포이드 오버레이
|
||
│ │ ├── ColorPickResultWindow.xaml/.cs # 색상 추출 결과 반투명 팝업
|
||
│ │ ├── ReminderPopupWindow.xaml/.cs # 잠금 해제 사용시간 알림 팝업
|
||
│ │ ├── StatisticsWindow.xaml/.cs # 사용 통계 차트 창
|
||
│ │ └── TrayContextMenu.cs # 트레이 컨텍스트 메뉴 팩토리 (모던 테마 인식)
|
||
│ ├── AxCommander.SDK/
|
||
│ │ └── IActionHandler.cs # 플러그인 계약 (LauncherItem, PluginMetadata)
|
||
│ ├── AxCommander.Tests/
|
||
│ │ ├── Core/FuzzyEngineTests.cs # 퍼지 엔진 단위 테스트 (19개)
|
||
│ │ ├── Handlers/ClipboardTransformTests.cs # 클립보드 변환 테스트 (21개)
|
||
│ │ └── Services/SettingsServiceTests.cs # 설정 서비스 테스트 (17개)
|
||
│ ├── AxCommander.Installer.Offline/ # 오프라인 인스톨러 (.NET 8, self-contained ZIP 내장)
|
||
│ │ ├── SetupForm.cs # 모던 WinForms UI (그라데이션 헤더, 설치/업그레이드/제거)
|
||
│ │ └── Program.cs
|
||
│ └── AxCommander.Installer.Online/ # 온라인 인스톨러 (.NET Framework 4.8, ~1MB)
|
||
│ ├── OnlineSetupForm.cs # .NET 4.8 WinForms UI + .NET 8 런타임 자동 다운로드
|
||
│ └── Program.cs
|
||
├── tools/
|
||
│ └── IconGenerator/ # 다이아몬드 픽셀 아이콘 생성 도구 (.NET 8 콘솔)
|
||
│ └── Program.cs # 보석 다이아몬드 컷 + RGBG 4색 → ICO 생성
|
||
├── docs/
|
||
│ └── DEVELOPMENT.md # 이 파일
|
||
├── build.bat # 3종 빌드 스크립트 (본체 + 오프라인 + 온라인)
|
||
└── README.md
|
||
```
|
||
|
||
---
|
||
|
||
## 아키텍처 개요
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ App.xaml.cs │
|
||
│ (서비스 초기화 · 핸들러 등록 · 트레이 아이콘 관리) │
|
||
└────────┬───────────────────────────────────────────┬────┘
|
||
│ │
|
||
┌────────▼────────┐ ┌──────────▼───────┐
|
||
│ LauncherWindow │ ◄─── MVVM ─────────► │ SettingsWindow │
|
||
│ (WPF, OLED 스타일)│ │ (좌측 사이드바) │
|
||
└────────┬────────┘ └──────────────────┘
|
||
│ 입력
|
||
┌────────▼────────┐
|
||
│ CommandResolver │ ← 프리픽스 라우터
|
||
└────────┬────────┘
|
||
│ 프리픽스 분기
|
||
┌────────┴────────────────────────────────────────────────┐
|
||
│ = Calculator/Currency /System+Timer ; Snippet │
|
||
│ # History @ UrlAlias ~ Folder > Batch $ Clip │
|
||
│ ! Workspace ? WebSearch emoji color recent │
|
||
│ note uninstall kill media info [plugin/skill] │
|
||
└────────────────────────────────────────────────────────┘
|
||
│ 프리픽스 없음
|
||
┌────────▼────────┐
|
||
│ FuzzyEngine │ ← 한국어 초성 + 퍼지 매칭
|
||
└─────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 핵심 데이터 흐름
|
||
|
||
### 검색 흐름
|
||
|
||
1. 사용자가 런처에 텍스트 입력
|
||
2. `LauncherViewModel.InputText` setter 트리거
|
||
3. `CommandResolver.ResolveAsync(input)` 호출
|
||
4. 프리픽스 일치 → 해당 `IActionHandler.GetItemsAsync()` 호출
|
||
5. 프리픽스 없음 → `FuzzyEngine.Search()` 호출
|
||
6. 결과를 `ObservableCollection<LauncherItem>`에 바인딩
|
||
7. `LauncherWindow` ListView 자동 갱신
|
||
|
||
### 실행 흐름
|
||
|
||
1. 사용자가 `Enter` 키 입력
|
||
2. `LauncherViewModel.ExecuteSelectedAsync()` 호출
|
||
3. `CommandResolver.ExecuteAsync(item, lastInput)` 호출
|
||
4. 프리픽스 있음 → `handler.ExecuteAsync(item)` 위임
|
||
5. 프리픽스 없음 → `IndexEntry.Path`를 `Process.Start`로 실행
|
||
6. 런처 창 자동 숨김
|
||
|
||
### 테마 전환 흐름
|
||
|
||
1. 설정 창 테마 탭에서 카드 클릭
|
||
2. `SettingsViewModel.SelectTheme(key)` 호출
|
||
3. `ThemePreviewRequested` 이벤트 발생
|
||
4. `App.PreviewCallback` → `LauncherWindow.ApplyTheme(key)` 호출
|
||
5. `Application.Current.Resources.MergedDictionaries` 교체 (런타임 핫스왑)
|
||
6. 설정 저장 없이 닫으면 `RevertCallback`으로 원복
|
||
|
||
---
|
||
|
||
## 각 핸들러 상세
|
||
|
||
### CalculatorHandler (`=`)
|
||
|
||
- **엔진**: `MathEvaluator` 재귀 하강 파서 (외부 의존성 없음)
|
||
- **연산자**: `+`, `-`, `*`, `/`, `%`, `^` (거듭제곱)
|
||
- **함수**: `sqrt`, `abs`, `ceil`, `floor`, `round`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan`, `log`, `log2`, `ln`, `exp`, `pow`, `min`, `max`
|
||
- **상수**: `pi`, `e`, `inf`
|
||
- **리터럴**: 일반 정수/소수, 16진수(`0xFF`), 과학적 표기(`1.5e3`)
|
||
- **단위 변환**: `100km in miles`, `32f in c`, `5lb to kg` 등 (길이/온도/무게/속도/데이터/넓이)
|
||
- **통화 변환**: `100 USD to KRW`, `50 EUR in JPY` — `open.er-api.com` 무료 API, 1시간 캐시
|
||
- **실행**: 결과를 클립보드에 복사
|
||
|
||
### SystemCommandHandler (`/`)
|
||
|
||
| 명령 | 기능 | P/Invoke |
|
||
|------|------|----------|
|
||
| `/lock` | 화면 잠금 | `user32.LockWorkStation` |
|
||
| `/sleep` | 절전 | `WinForms.SetSuspendState(Suspend)` |
|
||
| `/hibernate` | 최대 절전 | `WinForms.SetSuspendState(Hibernate)` |
|
||
| `/restart` | 재시작 | `shutdown /r /t 5` |
|
||
| `/shutdown` | 종료 | `shutdown /s /t 5` |
|
||
| `/logout` | 로그아웃 | `user32.ExitWindowsEx(EWX_LOGOFF)` |
|
||
| `/recycle` | 휴지통 비우기 | `shell32.SHEmptyRecycleBin` |
|
||
| `/timer 5m` | 타이머 | `Task.Delay` + `NotificationService.Notify` |
|
||
| `/timer 1h30m 회의` | 라벨 포함 타이머 | 위와 동일 |
|
||
| `/alarm 14:30` | 지정 시각 알람 | 목표 시각 미래 계산 + `Task.Delay` |
|
||
|
||
각 명령은 `SystemCommandSettings`에서 개별 활성화/비활성화 가능.
|
||
위험한 명령(재시작, 종료 등)은 실행 전 `MessageBox.Show` 확인 다이얼로그 표시.
|
||
타이머/알람 완료 시 트레이 풍선 알림(`NotificationService.Notify`).
|
||
|
||
**명령 별칭** (v0.8 추가): `CommandAliases` 딕셔너리로 명령키별 별칭 목록 설정 가능.
|
||
|
||
```json
|
||
"commandAliases": {
|
||
"lock": ["잠금", "l"],
|
||
"sleep": ["절전", "s"],
|
||
"restart": ["재시작", "r"],
|
||
"shutdown": ["종료"],
|
||
"logout": ["로그아웃"]
|
||
}
|
||
```
|
||
|
||
예) `/잠금` 또는 `/l` 입력 시 화면 잠금 실행. 설정 UI의 시스템 탭에서 쉼표 구분으로 편집 가능.
|
||
|
||
### EmojiHandler (`emoji`)
|
||
|
||
- 300+ 이모지 내장 (한국어+영어 키워드 태그)
|
||
- **사용**: `emoji 하트`, `emoji wave`, `emoji` (기본 30개)
|
||
- **실행**: 이모지 문자를 클립보드에 복사
|
||
- **카테고리**: 표정/감정, 손/몸, 하트/기호, 음식, 동물, 물건/도구, 이동수단, 장소, 기호
|
||
|
||
### ColorHandler (`color`)
|
||
|
||
- **입력 형식**: HEX(`#FF5500`), RGB(`255,85,0` / `rgb(255,85,0)`), RGBA, HSL(`hsl(24,100%,50%)`), 색상 이름(`red`, `빨강`)
|
||
- **출력**: HEX / RGB / HSL / HSV 4가지 형식 동시 표시
|
||
- **색상 이름**: 30+ 한/영 색상 이름 지원 (red, 빨강, skyblue, 하늘색 등)
|
||
- **실행**: 선택한 형식을 클립보드에 복사
|
||
|
||
### RecentFilesHandler (`recent`)
|
||
|
||
- `%APPDATA%\Microsoft\Windows\Recent` 폴더의 `.lnk` 파일 읽기
|
||
- 최근 수정 순 정렬, 최대 100개 스캔 → 20개 표시
|
||
- 10초 캐시
|
||
- **실행**: Windows 셸이 `.lnk` 링크를 따라 원본 파일 실행
|
||
|
||
### NoteHandler (`note`)
|
||
|
||
- **저장**: `note 내일 회의 9시` → `%APPDATA%\AxCommander\notes.txt` 에 타임스탬프와 함께 append
|
||
- **조회**: `note` → 최근 10개 역순 표시 (Enter로 클립보드 복사)
|
||
- **전체 삭제**: `note clear` 또는 목록 맨 아래 항목 선택
|
||
- **알림**: 저장 시 트레이 풍선 알림 표시
|
||
|
||
### UninstallHandler (`uninstall`)
|
||
|
||
- `HKLM\SOFTWARE\...\Uninstall` + `HKCU\SOFTWARE\...\Uninstall` 레지스트리 스캔
|
||
- `WOW6432Node` 경로도 포함 (32비트 앱)
|
||
- 이름 / 게시자로 검색, 30초 캐시
|
||
- **실행**: `UninstallString` 파싱 후 `Process.Start` — `msiexec` 자동 처리
|
||
- 시스템 구성 요소(`SystemComponent=1`) 및 KB 패치 자동 필터링
|
||
|
||
### SnippetHandler (`;`)
|
||
|
||
- 설정 `snippets[]` 배열에서 키워드를 퍼지 검색
|
||
- **변수 치환**: `{date}`, `{time}`, `{datetime}`, `{year}`, `{month}`, `{day}`
|
||
- **붙여넣기**: `Clipboard.SetText` 후 `SendInput(Ctrl+V)` 시뮬레이션 (100ms 지연)
|
||
|
||
### ClipboardHistoryService + ClipboardHistoryHandler (`#`)
|
||
|
||
- `HwndSource(HWND_MESSAGE)` 기반 숨겨진 메시지 창 생성
|
||
- `AddClipboardFormatListener` + `WM_CLIPBOARDUPDATE` 훅
|
||
- 최대 `maxItems`개 저장 (기본 50), FIFO 방식
|
||
- **보안 제외 패턴**: `ExcludePatterns` Regex 목록으로 민감 데이터 자동 제외
|
||
- `SuppressNextCapture()`: 자체 붙여넣기 시 중복 기록 방지
|
||
|
||
### ClipboardHandler (`$`)
|
||
|
||
12가지 내장 변환기:
|
||
|
||
| 키 | 변환 |
|
||
|----|------|
|
||
| `$json` | JSON 포맷팅 |
|
||
| `$upper` / `$lower` | 대/소문자 변환 |
|
||
| `$ts` | Unix 타임스탬프 → 날짜 |
|
||
| `$epoch` | 날짜 → Unix 타임스탬프 |
|
||
| `$urle` / `$urld` | URL 인코딩/디코딩 |
|
||
| `$b64e` / `$b64d` | Base64 인코딩/디코딩 |
|
||
| `$md` | Markdown 제거 |
|
||
| `$trim` | 공백 정리 |
|
||
| `$lines` | 빈 줄 제거 |
|
||
|
||
---
|
||
|
||
## 설정 UI (SettingsWindow)
|
||
|
||
### 레이아웃 구조
|
||
|
||
설정 창(`SettingsWindow.xaml`)은 **좌측 사이드바 + 우측 컨텐츠** 방식으로 구성됩니다.
|
||
WPF `TabControl`의 커스텀 `ControlTemplate`으로 구현되며, `TabStripPlacement="Left"`를 사용합니다.
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────────────┐
|
||
│ 820 × 610 │
|
||
│ ┌────────────┐ ┌────────────────────────────────────┐ │
|
||
│ │ AX │ │ │ │
|
||
│ │ Commander │ │ 선택된 탭의 컨텐츠 │ │
|
||
│ │────────────│ │ (ScrollViewer + StackPanel) │ │
|
||
│ │ ● 일반 │ │ │ │
|
||
│ │ 테마 │ │ │ │
|
||
│ │ 색상 편집 │ │ │ │
|
||
│ │ 스니펫 │ │ │ │
|
||
│ │ 클립보드 │ │ │ │
|
||
│ │ 시스템 │ │ │ │
|
||
│ │ 빠른 실행 │ │ │ │
|
||
│ │ 배치 명령 │ │ │ │
|
||
│ │ 캡처 │ │ │ │
|
||
│ │ 알림 │ │ │ │
|
||
│ └────────────┘ └────────────────────────────────────┘ │
|
||
│ ─────────────────────────────────────────────────────── │
|
||
│ AX Commander · v1.0 [취소] [💾 저장] │
|
||
└──────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 탭 구성
|
||
|
||
| 탭 | MDL2 아이콘 | 주요 설정 항목 |
|
||
|----|------------|--------------|
|
||
| 일반 | E713 | 글로벌 단축키, 최대 결과 수, **기본 검색 엔진**, 투명도, **런처 위치**, 인덱스 경로, **검색 확장자** (태그형 UI, 추가/삭제 가능) |
|
||
| 테마 | E790 | 11개 테마 카드 (클릭 → 즉시 미리보기): Dark/Light/OLED/Nord/Monokai/Catppuccin/Sepia/Alfred/Alfred Light/System/Custom |
|
||
| 색상 편집 | E771 | 커스텀 테마 14개 색상 (커스텀 선택 시만 활성) |
|
||
| 스니펫 | E70B | **자동 확장 토글**, 스니펫 추가/삭제, 변수 치환 안내 |
|
||
| 클립보드 | E77F | 활성화 토글, 최대 보관 개수, 보안 패턴 표시 |
|
||
| 시스템 | E7E8 | 7개 시스템 명령 개별 활성화/비활성화, **명령별 별칭 편집**, **별칭 기본값 초기화** |
|
||
| 빠른 실행 | E7C3 | 키워드→앱/URL/폴더 단축키 추가/삭제 |
|
||
| 배치 명령 | E756 | **`>` 프리픽스 배치 명령 추가/삭제, ShowWindow 옵션** |
|
||
| 캡처 | E722 | `cap` 프리픽스 문자열 변경, 파일 자동 저장 토글·저장 경로 설정 |
|
||
| 알림 | EA8F | 잠금 해제 알림 활성화 토글, 표시 위치(4방향), 표시 간격, 자동 닫힘 시간 |
|
||
|
||
### 디자인 시스템
|
||
|
||
**컬러 아이콘 박스** — 각 설정 행 좌측에 `36×36 CornerRadius="9"` 박스로 기능을 시각적으로 구분합니다.
|
||
|
||
| 기능 영역 | 배경색 |
|
||
|----------|--------|
|
||
| 단축키 / 빠른 실행 | `#4B5EFC` |
|
||
| 검색 | `#00A8CC` |
|
||
| 투명도 / 절전 | `#7B2FBE` |
|
||
| 스니펫 | `#FF6B35` |
|
||
| 클립보드 활성화 | `#20B2AA` |
|
||
| 보관 개수 | `#FF8C42` |
|
||
| 보안 / 화면 잠금 | `#C50F1F` |
|
||
| 재시작 | `#107C10` |
|
||
| 시스템 종료 | `#C50F1F` |
|
||
| 로그아웃 | `#CA5010` |
|
||
|
||
**토글 스위치** (`ToggleSwitch` 스타일) — iOS 스타일의 커스텀 `CheckBox` 스타일. 클립보드 활성화와 시스템 명령 7개에 적용.
|
||
|
||
```
|
||
OFF: [○──────] 배경: #D0D0E0
|
||
ON: [──────●] 배경: #4B5EFC
|
||
```
|
||
|
||
**SideNavItem 스타일** — 탭 선택 상태:
|
||
- 선택됨: 좌측 3px `#4B5EFC` accent bar + `#EEF0FF` 배경 + SemiBold 텍스트
|
||
- 호버: `#F4F4FF` 배경
|
||
- 비선택: 투명 배경
|
||
|
||
### SettingsViewModel 보조 모델
|
||
|
||
```csharp
|
||
// 테마 카드 (테마 탭)
|
||
class ThemeCardModel { Key, Name, PreviewBackground/Text/Accent/..., IsSelected }
|
||
|
||
// 커스텀 색상 행 (색상 편집 탭)
|
||
class ColorRowModel { Label, Property, Hex, Preview(SolidColorBrush) }
|
||
|
||
// 빠른 실행 단축키 (빠른 실행 탭)
|
||
class AppShortcutModel { Key, Description, Target, Type, TypeSymbol, TypeLabel }
|
||
|
||
// 스니펫 행 (스니펫 탭)
|
||
class SnippetRowModel { Key, Name, Content, Preview }
|
||
|
||
// 배치 명령 행 (배치 명령 탭)
|
||
class BatchCommandModel { Key, Command, ShowWindow }
|
||
```
|
||
|
||
---
|
||
|
||
## 설정 스키마 (`settings.json`)
|
||
|
||
```jsonc
|
||
{
|
||
"version": "1.0",
|
||
"hotkey": "Alt+Space",
|
||
"launcher": {
|
||
"opacity": 0.96,
|
||
"maxResults": 7,
|
||
"theme": "dark", // system|dark|light|oled|nord|monokai|catppuccin|sepia|custom
|
||
"width": 680,
|
||
"position": "center-top", // center-top|center|bottom
|
||
"webSearchEngine": "g", // g|n|d|y|w (Google|Naver|DuckDuckGo|YouTube|Wikipedia)
|
||
"snippetAutoExpand": true, // 글로벌 스니펫 자동 확장 활성화
|
||
"customTheme": { /* 14개 색상 키 */ }
|
||
},
|
||
"indexPaths": [
|
||
"%USERPROFILE%\\Desktop",
|
||
"%APPDATA%\\Microsoft\\Windows\\Start Menu"
|
||
],
|
||
"indexExtensions": [
|
||
".exe", ".lnk", ".bat", ".ps1", ".url", ".cmd", ".msi",
|
||
".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".hwp", ".hwpx",
|
||
".txt", ".md", ".csv", ".json", ".xml", ".yaml", ".yml", ".log", ".ini",
|
||
".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg", ".webp",
|
||
".zip", ".7z", ".rar"
|
||
],
|
||
"aliases": [
|
||
{ "key": "vscode", "type": "app", "target": "C:\\...\\Code.exe", "description": "VS Code" },
|
||
{ "key": "gh", "type": "url", "target": "https://github.com" },
|
||
{ "key": "dl", "type": "folder", "target": "%USERPROFILE%\\Downloads" },
|
||
{ "key": "build", "type": "batch", "target": "dotnet build", "description": "빌드", "showWindow": true },
|
||
{ "key": "test", "type": "batch", "target": "dotnet test", "description": "테스트", "showWindow": false }
|
||
],
|
||
"snippets": [
|
||
{ "key": "addr", "name": "회사 주소", "content": "서울시 강남구 ..." }
|
||
],
|
||
"clipboardHistory": {
|
||
"enabled": true,
|
||
"maxItems": 50,
|
||
"excludePatterns": ["^\\d{4}[\\s\\-]?\\d{4}[\\s\\-]?\\d{4}[\\s\\-]?\\d{4}$"]
|
||
},
|
||
"systemCommands": {
|
||
"showLock": true, "showSleep": true, "showRestart": true,
|
||
"showShutdown": true, "showHibernate": false,
|
||
"showLogout": true, "showRecycleBin": true,
|
||
"commandAliases": {
|
||
"lock": ["잠금", "l"],
|
||
"sleep": ["절전", "s"],
|
||
"restart": ["재시작"],
|
||
"shutdown": ["종료"],
|
||
"hibernate": [],
|
||
"logout": ["로그아웃"],
|
||
"recycle": []
|
||
}
|
||
},
|
||
"clipboardTransformers": [
|
||
{ "key": "$mine", "type": "regex", "pattern": "foo", "replace": "bar", "timeout": 2000 }
|
||
],
|
||
"screenCapture": {
|
||
"prefix": "cap", // cap 프리픽스 문자열 (변경 가능)
|
||
"saveToFile": false, // true면 캡처 결과를 파일로도 저장
|
||
"savePath": "" // 빈 문자열이면 %USERPROFILE%\Pictures\Screenshots\
|
||
},
|
||
"reminder": {
|
||
"enabled": false, // 잠금 해제 사용시간 알림 활성화
|
||
"position": "BottomRight", // TopLeft|TopRight|BottomLeft|BottomRight
|
||
"intervalMinutes": 60, // 알림 최소 간격 (분): 30|60|120|240
|
||
"autoDismissSeconds": 10 // 자동 닫힘 초: 5|10|15|20|30
|
||
},
|
||
"monitorMismatch": "warn", // fit|skip|warn
|
||
"profiles": [], // !save로 자동 관리
|
||
"plugins": [
|
||
{ "path": "C:\\Plugins\\MyPlugin.dll", "enabled": true }
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 주요 기능 상세
|
||
|
||
### 파일 액션 서브메뉴 (`→` 키)
|
||
|
||
검색 결과에서 파일이나 앱(IndexEntry)이 선택된 상태에서 `→` 키(커서가 입력 끝에 있을 때)를 누르면 파일 액션 서브메뉴로 진입합니다.
|
||
|
||
**진입 조건**: `InputBox.CaretIndex == Text.Length && Text.Length > 0 && SelectedItem.Data is IndexEntry`
|
||
|
||
**제공 액션**:
|
||
|
||
| 액션 | 설명 | 구현 |
|
||
|------|------|------|
|
||
| 경로 복사 | 파일 전체 경로를 클립보드에 복사 | `Clipboard.SetText(path)` |
|
||
| 파일 탐색기에서 열기 | 탐색기에서 해당 파일을 선택 상태로 표시 | `explorer.exe /select,"path"` |
|
||
| 관리자 권한으로 실행 | UAC 권한 상승 후 실행 (파일만, 폴더 제외) | `ProcessStartInfo { Verb = "runas" }` |
|
||
| 터미널에서 열기 | Windows Terminal 또는 cmd.exe로 해당 경로 열기 | `wt.exe -d "dir"` → 실패 시 `cmd.exe /k cd /d "dir"` |
|
||
|
||
**상태 흐름**:
|
||
```
|
||
일반 모드 → [→ 키] → 액션 모드 (breadcrumb 바 표시) → [Enter] → 액션 실행 + 닫기
|
||
→ [Esc] → 일반 모드 복귀 (이전 쿼리 복원)
|
||
```
|
||
|
||
**관련 코드**:
|
||
- `LauncherViewModel.EnterActionMode()` — 액션 항목 빌드 및 `_savedQuery` 저장
|
||
- `LauncherViewModel.ExitActionMode()` — 이전 쿼리 복원 및 재검색
|
||
- `LauncherViewModel.ExecuteFileAction()` — 정적 메서드로 액션 실행
|
||
- `LauncherWindow.xaml` — `Grid.Row="1"` breadcrumb 바 (ShowActionModeBar 바인딩)
|
||
|
||
---
|
||
|
||
### Large Type (`Shift+Enter`)
|
||
|
||
선택된 항목의 텍스트를 전체 화면 오버레이로 크게 표시합니다.
|
||
|
||
**표시 텍스트 우선순위**:
|
||
1. 계산기 결과 (`SelectedItem.Data is string`) → 계산 결과값
|
||
2. 클립보드 히스토리 텍스트 (`ClipboardEntry.IsText`) → 전체 텍스트
|
||
3. 기본 → `SelectedItem.Title`
|
||
|
||
**글꼴 크기 자동 결정** (`LargeTypeWindow`):
|
||
|
||
| 텍스트 길이 | FontSize |
|
||
|------------|---------|
|
||
| ≤ 10자 | 120 |
|
||
| ≤ 30자 | 96 |
|
||
| ≤ 60자 | 72 |
|
||
| ≤ 120자 | 52 |
|
||
| 그 외 | 38 |
|
||
|
||
`Viewbox Stretch=Uniform`으로 최종 크기를 화면에 맞게 스케일링합니다.
|
||
|
||
**닫기**: `Esc` 키 / 화면 클릭 / 우상단 버튼
|
||
|
||
**관련 코드**:
|
||
- `Views/LargeTypeWindow.xaml/.cs` — 전체 화면 오버레이 창
|
||
- `LauncherViewModel.GetLargeTypeText()` — 텍스트 추출 로직
|
||
- `LauncherWindow.xaml.cs` → `ShowLargeType()` → `new LargeTypeWindow(text).Show()`
|
||
|
||
> **주의**: 클립보드 병합 대기 항목이 있는 상태에서 `Shift+Enter`를 누르면 Large Type 대신 **클립보드 병합**이 실행됩니다.
|
||
|
||
---
|
||
|
||
### 클립보드 병합 (`Shift+↑↓`, `Shift+Enter`)
|
||
|
||
`#` 프리픽스(클립보드 히스토리) 모드에서 여러 항목을 선택하여 하나로 합쳐 클립보드에 복사합니다.
|
||
|
||
**조작법**:
|
||
|
||
| 키 | 동작 |
|
||
|----|------|
|
||
| `Shift+↓` | 현재 항목 선택/해제 후 다음 항목으로 이동 |
|
||
| `Shift+↑` | 현재 항목 선택/해제 후 이전 항목으로 이동 |
|
||
| `Shift+Enter` | 선택된 항목들을 `\n`으로 합쳐 클립보드에 복사 |
|
||
| `Esc` | 선택 취소 및 모드 종료 |
|
||
|
||
**힌트 바**: 선택 항목이 있으면 `Grid.Row="3"` 힌트 바 표시
|
||
```
|
||
✓ 2개 선택됨 · Shift+Enter로 합치기 · Esc로 취소
|
||
```
|
||
|
||
**병합 순서**: `Results` 컬렉션의 표시 순서 기준 (HashSet 순서 아님)
|
||
|
||
**관련 코드**:
|
||
- `LauncherViewModel._mergeQueue` — `HashSet<ClipboardEntry>` 병합 대기 큐
|
||
- `LauncherViewModel.ToggleMergeItem()` — 항목 추가/제거 토글
|
||
- `LauncherViewModel.ExecuteMerge()` — Results 순서 기준으로 `\n` 결합 후 클립보드 복사
|
||
- `LauncherViewModel.ClearMerge()` — 큐 초기화
|
||
|
||
---
|
||
|
||
### 런처 키 바인딩 전체 표
|
||
|
||
| 키 | 동작 |
|
||
|----|------|
|
||
| `↑` / `↓` | 결과 목록 탐색 |
|
||
| `Enter` | 선택 항목 실행 |
|
||
| `Shift+Enter` | Large Type 표시 (병합 항목 있으면 클립보드 병합) |
|
||
| `→` (커서 끝) | 파일 액션 서브메뉴 진입 |
|
||
| `Shift+↓` | 현재 항목 병합 선택 + 다음으로 이동 |
|
||
| `Shift+↑` | 현재 항목 병합 선택 + 이전으로 이동 |
|
||
| `Tab` | 선택 항목 제목을 입력창에 자동완성 |
|
||
| `Esc` | 액션 모드면 이전 화면 복귀 / 아니면 런처 닫기 |
|
||
| `Ctrl+,` | 설정 창 열기 |
|
||
|
||
---
|
||
|
||
## 데이터 저장 경로
|
||
|
||
모든 사용자 데이터는 `%APPDATA%\AxCommander\`에 저장됩니다. EXE 실행 파일 옆에는 어떤 파일도 생성하지 않으므로, 어느 경로에서 실행해도 실행 파일 폴더는 깨끗하게 유지됩니다.
|
||
|
||
```
|
||
%APPDATA%\AxCommander\
|
||
├── settings.json # 전체 설정 (JSON 평문)
|
||
├── clipboard_history.dat # 클립보드 히스토리 (DPAPI 암호화 바이너리)
|
||
├── usage.json # 실행 빈도 랭킹 데이터
|
||
├── notes.txt # 빠른 메모 저장
|
||
├── favorites.json # 즐겨찾기 목록
|
||
├── routines.json # 루틴 자동화 정의 (사용자 편집 가능)
|
||
├── logs/
|
||
│ └── app-YYYY-MM-DD.log # 일별 로그 (14일 자동 삭제)
|
||
├── stats/
|
||
│ └── YYYY-MM-DD.json # 일별 사용 통계 (30일 자동 삭제)
|
||
├── templates/
|
||
│ └── *.json # 프로젝트 스캐폴딩 사용자 템플릿
|
||
└── plugins/
|
||
└── *.dll # 외부 플러그인 (선택)
|
||
```
|
||
|
||
**자동 삭제 정책**:
|
||
|
||
| 파일 | 보존 기간 | 방식 |
|
||
|------|----------|------|
|
||
| 로그 (`logs/app-*.log`) | 14일 | 앱 시작 시 1회 `PurgeOldLogs()` |
|
||
| 통계 (`stats/*.json`) | 30일 | 통계 기록 시 `PurgeOldFiles()` |
|
||
| 클립보드 히스토리 | 무기한 (최대 항목 수 제한) | `maxItems` 설정값 기준 FIFO |
|
||
| 기타 (settings, notes 등) | 무기한 | 수동 관리 |
|
||
|
||
---
|
||
|
||
## 보안 고려사항
|
||
|
||
| 항목 | 구현 |
|
||
|------|------|
|
||
| URL 스킴 검증 | `http`, `https`, `ftp`, `ftps`, `ms-settings`, `mailto`, `file` 허용. `javascript:` 등 차단 |
|
||
| PowerShell 인젝션 방지 | `>` 명령어 입력의 `"` 이스케이프 처리 |
|
||
| ReDoS 방지 | 사용자 정의 Regex에 `TimeSpan` 타임아웃 적용 |
|
||
| 자격증명 저장 | Windows Credential Manager (`advapi32.dll`, DPAPI 암호화) |
|
||
| 클립보드 민감 데이터 | Regex 기반 제외 패턴 (`excludePatterns`) — 신용카드·IP 등 기본 차단 |
|
||
| API 타임아웃 | JSON 스킬 HTTP 요청 3초 제한 |
|
||
| 시스템 명령 확인 | 재시작·종료·로그아웃 실행 전 `MessageBox.Show` 2단계 확인 |
|
||
| **디컴파일 방지** | `Security/AntiTamper.cs` — 디버거 감지 (관리형+네이티브+원격), 디컴파일러 프로세스 감지 (dnSpy, ILSpy, dotPeek, x64dbg 등 15종), Release 빌드만 활성 |
|
||
| **PDB 제거** | Release 빌드 시 `DebugType=none`, `DebugSymbols=false`. build.bat에서 `.pdb`/`.xml` 전수 삭제 |
|
||
| **소스 링크 비활성** | `EnableSourceLink=false`, `EmbedAllSources=false` — 소스 코드 경로 노출 차단 |
|
||
| **난독화 호환** | `[assembly: Obfuscation]` 속성 적용. Obfuscar/ConfuserEx/Dotfuscator 연동 시 자동 난독화 |
|
||
|
||
---
|
||
|
||
## 테마 커스터마이징
|
||
|
||
테마 XAML 파일(`Themes/*.xaml`)은 색상 14개 + 모양 2개 = **총 16개 ResourceKey**를 정의합니다:
|
||
|
||
| 키 | 타입 | 용도 |
|
||
|----|------|------|
|
||
| `LauncherBackground` | SolidColorBrush | 전체 배경 |
|
||
| `ItemBackground` | SolidColorBrush | 항목 기본 배경 |
|
||
| `ItemSelectedBackground` | SolidColorBrush | 선택된 항목 배경 |
|
||
| `ItemHoverBackground` | SolidColorBrush | 호버 배경 |
|
||
| `PrimaryText` | SolidColorBrush | 주 텍스트 색상 |
|
||
| `SecondaryText` | SolidColorBrush | 보조 텍스트 색상 |
|
||
| `PlaceholderText` | SolidColorBrush | 플레이스홀더 텍스트 |
|
||
| `AccentColor` | SolidColorBrush | 강조색 (선택 바, 배지 등) |
|
||
| `SeparatorColor` | SolidColorBrush | 구분선 색상 |
|
||
| `HintBackground` | SolidColorBrush | 힌트 배경 |
|
||
| `HintText` | SolidColorBrush | 힌트 텍스트 |
|
||
| `BorderColor` | SolidColorBrush | 창 테두리 |
|
||
| `ScrollbarThumb` | SolidColorBrush | 스크롤바 색상 |
|
||
| `ShadowColor` | Color | 드롭 섀도우 색상 |
|
||
| `WindowCornerRadius` | CornerRadius | 창 전체 모서리 라운딩 |
|
||
| `ItemCornerRadius` | CornerRadius | 결과 항목 모서리 라운딩 |
|
||
|
||
**테마별 모서리 라운딩 값**:
|
||
|
||
| 테마 | WindowCornerRadius | ItemCornerRadius | 특징 |
|
||
|------|-------------------|-----------------|------|
|
||
| Dark / Light | 20 | 10 | 기본 부드러운 라운딩 |
|
||
| OLED | 26 | 13 | 가장 둥근 형태 |
|
||
| Catppuccin | 22 | 12 | 약간 더 둥근 파스텔 느낌 |
|
||
| Nord | 16 | 8 | 약간 각진 북유럽 스타일 |
|
||
| Monokai | 14 | 6 | 에디터 스타일 — 적당히 각진 |
|
||
| Sepia | 12 | 6 | 클래식하고 차분한 느낌 |
|
||
| Alfred / AlfredLight | 14 | 6 | Alfred 앱과 유사한 비율 |
|
||
|
||
**트레이 컨텍스트 메뉴**: `TrayContextMenu.cs`의 `ModernTrayRenderer`는 런타임에 `Application.Current.Resources`에서 WPF 테마 색상(`LauncherBackground`, `AccentColor` 등)을 읽어 트레이 메뉴 배경·텍스트·호버 색상에 그대로 적용합니다. 테마를 전환하면 다음 메뉴 오픈 시 새 테마가 반영됩니다.
|
||
|
||
**새 테마 추가 순서**:
|
||
1. `Themes/MyTheme.xaml` 작성 (위 16개 키 모두 정의, `WindowCornerRadius`·`ItemCornerRadius` 포함)
|
||
2. `.csproj`에 `<Resource Include="Themes/MyTheme.xaml"/>` 추가
|
||
3. `LauncherWindow.xaml.cs`의 `GetEffectiveThemeName()` switch에 케이스 추가
|
||
4. `SettingsViewModel.ThemeCards` 목록에 `ThemeCardModel` 항목 추가
|
||
|
||
---
|
||
|
||
## 단위 테스트
|
||
|
||
```bash
|
||
dotnet test src/AxCommander.Tests
|
||
```
|
||
|
||
| 파일 | 테스트 수 | 대상 |
|
||
|------|----------|------|
|
||
| `FuzzyEngineTests.cs` | 19 | CalculateScore, FuzzyMatch, 초성 검색 |
|
||
| `ClipboardTransformTests.cs` | 21 | 12개 내장 변환기 |
|
||
| `SettingsServiceTests.cs` | 17 | 기본값, JSON 직렬화 라운드트립 |
|
||
|
||
테스트 프로젝트는 `InternalsVisibleTo`로 `internal` 메서드에 접근합니다.
|
||
|
||
---
|
||
|
||
## 코드 검토 이력
|
||
|
||
### v0.3 최종 검토 결과 (2026-03-24)
|
||
|
||
전체 소스 코드 정적 분석 결과 **컴파일 오류 없음** 확인. v0.3 신규 코드 포함.
|
||
|
||
| 검토 항목 | 결과 |
|
||
|----------|------|
|
||
| 타입 참조 (`Symbols.Lock`, `Symbols.MediaPlay`, `Symbols.Computer`) | ✅ 모두 `Themes/Symbols.cs`에 정의됨 |
|
||
| XAML 컨버터 (`BoolToVisibility`, `CountToVisibility`, `SymbolToBackground` 등) | ✅ `App.xaml`에 모두 등록됨 |
|
||
| ViewModel 바인딩 (`ShowActionModeBar`, `ActionModeBreadcrumb`, `ShowMergeHint`, `MergeHintText`) | ✅ `LauncherViewModel`에 모두 정의됨 |
|
||
| `LauncherItem` 생성자 호출부 (`Symbol:` named parameter) | ✅ SDK 레코드 시그니처 일치 |
|
||
| `ClipboardEntry` `IsText` / `Text` 프로퍼티 | ✅ `ClipboardHistoryService.cs`에 정의됨 |
|
||
| `HashSet<ClipboardEntry>` 동등성 | ✅ record 구조적 동등성 + 동일 객체 참조로 정상 작동 |
|
||
| `IndexEntry.Path` 프로퍼티 | ✅ `IndexService.cs`에 정의됨 |
|
||
| `FileAction` enum / `FileActionData` record 접근성 | ✅ 동일 파일(ViewModels) 내 정의, 접근 가능 |
|
||
| `LargeTypeWindow` 네임스페이스 | ✅ `AxCommander.Views` — LauncherWindow와 동일 네임스페이스, import 불필요 |
|
||
| `LauncherWindow.xaml` Grid.Row 번호 | ✅ Row 0~4 순서 정확 (0:입력, 1:액션바, 2:구분선, 3:병합힌트, 4:리스트) |
|
||
|
||
---
|
||
|
||
## 버그 수정 이력
|
||
|
||
### v0.1 → v0.2
|
||
|
||
| 파일 | 문제 | 수정 내용 |
|
||
|------|------|----------|
|
||
| `InputListener.cs` | `LogService.Services.LogService.XXX()` — 존재하지 않는 네임스페이스 경로로 컴파일 오류 발생 | `using AxCommander.Services;` 추가 후 `LogService.XXX()` 직접 호출로 수정. 파일 하단의 빈 `namespace LogService { }` 선언 제거 |
|
||
|
||
### v0.2 → v0.3
|
||
|
||
| 파일 | 변경 내용 |
|
||
|------|----------|
|
||
| `Core/HotkeyParser.cs` (신규) | 핫키 문자열 파싱/포맷 — `"Alt+Space"` ↔ `HotkeyDefinition` 변환 |
|
||
| `Core/InputListener.cs` | 하드코딩 Alt+Space 제거 → `HotkeyDefinition` 기반 동적 핫키 + `SuspendHotkey` 지원 |
|
||
| `Views/SettingsWindow.xaml/.cs` | Alfred 스타일 핫키 레코더 UI (클릭 → 배지 표시 → 키 입력 캡처) |
|
||
| `Views/LargeTypeWindow.xaml/.cs` (신규) | 전체 화면 Large Type 오버레이 |
|
||
| `ViewModels/LauncherViewModel.cs` | 파일 액션 모드 + 클립보드 병합 + Large Type 텍스트 추출 추가 |
|
||
| `Views/LauncherWindow.xaml` | 액션 모드 breadcrumb 바 (Row 1) + 병합 힌트 바 (Row 3) 추가 |
|
||
| `Views/LauncherWindow.xaml.cs` | `→`, `Shift+Enter`, `Shift+↑↓` 키 핸들러 추가 / Esc 액션모드 분기 |
|
||
| `App.xaml.cs` | 설정 저장 후 핫키 갱신 + SuspendHotkey 콜백 주입 |
|
||
|
||
### v0.3 → v0.4 (Alfred 비교 기반 설정 UI 개선)
|
||
|
||
| 파일 | 변경 내용 |
|
||
|------|----------|
|
||
| `Models/AppSettings.cs` | `LauncherSettings`에 `WebSearchEngine`, `SnippetAutoExpand`, `Position` 필드 추가 |
|
||
| `Handlers/WebSearchHandler.cs` | 기본 검색 엔진을 하드코딩에서 `settings.Launcher.WebSearchEngine` 런타임 읽기로 전환 / 불필요한 `using AxCommander.Models` 제거 |
|
||
| `App.xaml.cs` | `WebSearchHandler` 생성자에 `settings` 주입 |
|
||
| `Core/SnippetExpander.cs` | `HandleKey()` 진입부에 `SnippetAutoExpand` 비활성화 시 즉시 반환 추가 |
|
||
| `ViewModels/LauncherViewModel.cs` | `WindowPosition` 프로퍼티 추가 (설정 연동) |
|
||
| `Views/LauncherWindow.xaml.cs` | `CenterOnScreen()` — `position` 설정 연동 + `ActualHeight/Width = 0` 방어 처리 |
|
||
| `ViewModels/SettingsViewModel.cs` | `LauncherPosition`, `WebSearchEngine`, `SnippetAutoExpand` 바인딩 프로퍼티 추가 / `BatchCommandModel` 및 배치 명령 CRUD 추가 |
|
||
| `Views/SettingsWindow.xaml` | 일반 탭: 기본 검색 엔진·런처 위치 ComboBox 추가 / 스니펫 탭: 자동 확장 토글 추가 / 8번째 탭 배치 명령 탭 추가 |
|
||
| `Views/SettingsWindow.xaml.cs` | `AddBatchCommand_Click`, `DeleteBatchCommand_Click` 핸들러 추가 |
|
||
|
||
**버그 수정**:
|
||
|
||
| 파일 | 버그 | 수정 |
|
||
|------|------|------|
|
||
| `Views/LauncherWindow.xaml.cs` | `CenterOnScreen()` — 첫 `Show()` 호출 시 레이아웃 패스 이전 `ActualHeight`가 0이 되는 타이밍 이슈 | `var h = ActualHeight > 0 ? ActualHeight : 80` 방어 처리 추가 |
|
||
| `Handlers/WebSearchHandler.cs` | `using AxCommander.Models` — 파일 내 Models 타입 미사용 불필요한 임포트 | 해당 `using` 제거 |
|
||
|
||
### v0.4 → v0.5 (배포 준비 + About 창 + 트레이 기능 강화)
|
||
|
||
| 파일 | 변경 내용 |
|
||
|------|----------|
|
||
| `App.xaml.cs` | 자동 시작 토글 — `HKCU\...\Run` 레지스트리 읽기/쓰기, 트레이 메뉴 체크박스 항목 추가 |
|
||
| `App.xaml.cs` | "정보" 트레이 메뉴 항목 추가 → `AboutWindow` 오픈 |
|
||
| `Views/AboutWindow.xaml/.cs` (신규) | 개발자 정보 창 — 그라데이션 헤더, 마스코트 이미지, 개발 목적, 블로그 링크, 버전 정보 |
|
||
| `AxCommander.csproj` | `Assets/mascot.png/.jpg/.webp` 조건부 CopyToOutputDirectory 추가 |
|
||
| `Views/SettingsWindow.xaml` | 단축키 아이콘 E704(InkingTool) → E765(Keyboard) 수정 |
|
||
| `Views/LargeTypeWindow.xaml` | `LineHeight="1.2"` 제거 — WPF LineHeight는 픽셀 단위, 1.2px는 런타임 오류 유발 |
|
||
| `AxCommander.csproj` | `<Using Remove="System.Windows.Forms"/>` 추가 — WPF+WinForms 동시 사용 시 `KeyEventArgs` 모호성 해소 |
|
||
|
||
**설정 파일 경로 확인**: `%APPDATA%\AxCommander\settings.json` — 이미 올바른 경로 사용 중, 별도 변경 없음.
|
||
|
||
**배포 방식**: `dotnet publish` → 단일 `.exe` 파일 (SelfContained, PublishSingleFile). 인스톨러 없이 EXE 복사 후 즉시 실행 가능.
|
||
|
||
### v0.5 → v0.6 (Alfred 비교 기반 7개 기능 추가)
|
||
|
||
| 파일 | 변경 내용 |
|
||
|------|----------|
|
||
| `Handlers/EmojiHandler.cs` (신규) | `emoji` 프리픽스, 300+ 이모지 내장 데이터베이스, 한/영 태그 검색, 클립보드 복사 |
|
||
| `Handlers/ColorHandler.cs` (신규) | `color` 프리픽스, HEX/RGB/RGBA/HSL/색상이름 → HEX+RGB+HSL+HSV 4종 변환 |
|
||
| `Handlers/SystemCommandHandler.cs` | `/timer`, `/alarm` 추가 — 시간 문자열 파싱(5m/1h30m/30s), Task.Delay 기반 백그라운드 타이머 |
|
||
| `Handlers/RecentFilesHandler.cs` (신규) | `recent` 프리픽스, Windows Recent .lnk 파싱, 최근순 정렬, 10초 캐시 |
|
||
| `Handlers/CalculatorHandler.cs` | `= 100 USD to KRW` 통화 변환 추가 — `CurrencyConverter` 내부 클래스, `open.er-api.com` 무료 API, 1시간 캐시, `async` 전환 |
|
||
| `Handlers/UninstallHandler.cs` (신규) | `uninstall` 프리픽스, 레지스트리 HKLM/HKCU/WOW6432Node 스캔, msiexec/exe 제거 실행 |
|
||
| `Handlers/NoteHandler.cs` (신규) | `note` 프리픽스, notes.txt append 저장, 역순 조회, clear 명령, ValueTuple 명시적 패턴 매칭 |
|
||
| `Services/NotificationService.cs` (신규) | static delegate 패턴 — App.xaml.cs에서 트레이 아이콘과 연결, 타이머/알람 알림에 사용 |
|
||
| `Themes/Symbols.cs` | Emoji/ColorPicker/Timer/RecentFiles/Currency/Uninstall/Note 심볼 추가 |
|
||
| `App.xaml.cs` | 5개 핸들러 등록 (Emoji/Color/Recent/Note/Uninstall) + `NotificationService.Initialize()` 연결 |
|
||
|
||
**버그 수정**:
|
||
|
||
| 파일 | 버그 | 수정 |
|
||
|------|------|------|
|
||
| `Handlers/NoteHandler.cs` | `case ("__SAVE__", string content):` — `object?` 타입에 대한 positional 패턴 컴파일 불안정 | `case ValueTuple<string, string> t when t.Item1 == "__SAVE__":` 명시적 타입 패턴으로 변경 |
|
||
| `Themes/Symbols.cs` | `Warning` 상수 중복 정의 (신규 추가 시 실수) | 하단 중복 제거 |
|
||
|
||
### v0.6 → v0.7 (개발자 도구 + 화면 캡처 + 랭킹 시스템)
|
||
|
||
| 파일 | 변경 내용 |
|
||
|------|----------|
|
||
| `Handlers/PortHandler.cs` (신규) | `port` 프리픽스, TCP 활성 연결 조회, 포트번호/프로세스명 검색, netstat -ano PID 매핑 |
|
||
| `Services/UsageRankingService.cs` (신규) | 실행 빈도 JSON 저장(`usage.json`), `SortByUsage<T>()` 제공 |
|
||
| `Core/CommandResolver.cs` | 퍼지 검색 결과를 `UsageRankingService.SortByUsage()`로 재정렬, IndexEntry 실행 시 `RecordExecution()` 호출 |
|
||
| `Handlers/EnvHandler.cs` (신규) | `env` 프리픽스, 우선순위 환경변수 20개 표시, 키/값 모두 검색, Enter로 복사 |
|
||
| `Handlers/JsonHandler.cs` (신규) | `json` 프리픽스, 클립보드 또는 인라인 JSON 파싱, `format`/`minify` 서브커맨드, `System.Text.Json` 내장 |
|
||
| `Handlers/EncodeHandler.cs` (신규) | `encode ` 프리픽스(뒤 공백), base64/url/hex/md5/sha1/sha256/sha512/html 인코딩 + decode 접두사로 역변환 |
|
||
| `Services/WindowTracker.cs` (신규) | `GetForegroundWindow()` P/Invoke, `Capture()` 호출 시 PreviousWindow 저장 |
|
||
| `Handlers/SnapHandler.cs` (신규) | `snap` 프리픽스, left/right/top/bottom/full/tl/tr/bl/br/center/restore, `SetWindowPos` + `GetMonitorInfo` |
|
||
| `Handlers/ScreenCaptureHandler.cs` (신규) | `cap` 프리픽스, screen(전체)/window(창)/scroll(스크롤 캡처), `PrintWindow`+`BitBlt`, 오버랩 검출 스티칭, `%USERPROFILE%\Pictures\Screenshots\` 저장 |
|
||
| `Themes/Symbols.cs` | PortIcon/EnvVar/JsonValid/JsonFormat/JsonMinify/EncodeIcon/SnapLayout/CaptureIcon/ScrollCapture 심볼 추가 |
|
||
| `App.xaml.cs` | 6개 핸들러 등록 (Port/Env/Json/Encode/Snap/ScreenCapture) + `OnHotkeyTriggered()`에 `WindowTracker.Capture()` 추가 |
|
||
|
||
**v0.7 코드 검토 후 즉시 수정 (버그 픽스):**
|
||
|
||
| 파일 | 수정 내용 |
|
||
|------|----------|
|
||
| `Handlers/PortHandler.cs` | `GetPidForPort()`가 루프마다 `netstat -ano` 실행하던 N+1 문제 → `RefreshProcessCache()` 내부에서 netstat 1회 실행 후 `_pidMap(포트→PID)` 캐시 구축. `GetPidForPort()`는 캐시 조회만 수행 |
|
||
| `Handlers/ScreenCaptureHandler.cs` | `AreSimilar()`/`FindOverlap()`의 `GetPixel()` 픽셀 비교 → `LockBits + unsafe 포인터` 연산으로 교체 (~50× 속도 향상) |
|
||
| `ViewModels/LauncherViewModel.cs` | `PrefixMap`에 v0.6 핸들러(emoji/color/recent/note/uninstall) + v0.7 핸들러(port/env/json/encode/snap/cap) + `/`(SystemCommand) 누락 항목 일괄 추가. `kill`/`media`/`info` 키를 공백 포함 버전으로 수정 |
|
||
| `AxCommander.csproj` | `<AllowUnsafeBlocks>true</AllowUnsafeBlocks>` 추가 |
|
||
|
||
**스크롤 캡처 동작 방식**:
|
||
1. `WindowTracker.PreviousWindow`에 저장된 이전 활성 창을 포그라운드로 활성화
|
||
2. `PrintWindow(PW_RENDERFULLCONTENT=2)` 또는 `CopyFromScreen` 폴백으로 첫 프레임 캡처
|
||
3. `WM_VSCROLL SB_PAGEDOWN` (스크롤 가능 자식 창이 있는 경우) 또는 `WM_KEYDOWN VK_NEXT` 전송
|
||
4. 120ms 대기 후 재캡처, 이전 프레임 하단 20%와 비교하여 97% 이상 유사하면 스크롤 종료 감지 → 중단
|
||
5. 각 프레임 사이 오버랩 픽셀 수를 픽셀 샘플링으로 계산하여 비겹치는 부분만 수직 스티칭
|
||
6. 결과를 `%USERPROFILE%\Pictures\Screenshots\scroll_yyyyMMdd_HHmmss.png`로 저장 + 클립보드 복사
|
||
|
||
**실행 빈도 랭킹 동작 방식**:
|
||
- 퍼지 검색(파일/앱/폴더) 실행 시 `IndexEntry.Path`를 키로 카운트 증가
|
||
- `usage.json`에 비동기 저장 (앱 종료 시에도 누적됨)
|
||
- 다음 검색부터 `SortByUsage`로 상위 항목이 결과 목록 최상단에 표시
|
||
|
||
### About 창 (`AboutWindow`)
|
||
|
||
```
|
||
┌─────────────────────────────┐
|
||
│ [블루-퍼플 그라데이션 헤더] │
|
||
│ (마스코트 이미지 원형) │
|
||
│ AX Commander │
|
||
│ v1.0 │
|
||
├─────────────────────────────┤
|
||
│ ┌─── 개발 목적 배너 ─────────┐ │
|
||
│ │ 업무 편의성 증가 및 LLM ... │ │
|
||
│ └─────────────────────────┘ │
|
||
│ │
|
||
│ 🏢 AX연구소 AI팀 │
|
||
│ 백승재 · SW Architect │
|
||
│ 🔗 www.swarchitect.net │
|
||
│ │
|
||
│ AX Commander · .NET 8 │
|
||
└─────────────────────────────┘
|
||
```
|
||
|
||
- 앱 아이콘: `Assets/icon.ico` — 다이아몬드 픽셀 보석 컷 디자인 (Blue/Green/Red/Green 4색, 흰색 facet 선)
|
||
- 7개 크기 (16, 24, 32, 48, 64, 128, 256px) 포함
|
||
- `tools/IconGenerator/` 콘솔 앱으로 재생성 가능: `dotnet run -- <출력경로>`
|
||
- SVG 원본: `Assets/diamond_pixel.svg`
|
||
- 마스코트 이미지: `Assets/mascot.png` (또는 .jpg/.webp) 존재 시 자동 로드, 없으면 앱 아이콘 표시
|
||
- 정보 창: 초기 표시 시 앱 아이콘, 개발자 이름 클릭 시 마스코트 오버레이
|
||
- 창 드래그 이동 가능 (`MouseDown` → `DragMove`)
|
||
- 블로그 링크 클릭 시 기본 브라우저로 열기
|
||
|
||
---
|
||
|
||
## v0.7 3차 전체 점검 수정 (버그·보안·스레딩)
|
||
|
||
> 빌드 오류 3건, 컴파일 경고 1건, 런타임 버그 6건, 보안 이슈 2건을 수정하였습니다.
|
||
|
||
### 컴파일 오류 수정
|
||
|
||
| 파일 | 수정 내용 | 오류 코드 |
|
||
|------|----------|----------|
|
||
| `Services/UsageRankingService.cs` | `using System.IO;` 누락 추가 (`Path`, `File`, `Directory` 인식 불가) | CS0103 |
|
||
| `Views/SettingsWindow.xaml.cs` | `Key.Enter`와 `Key.Return` 중복 switch 케이스 → `Key.Enter or Key.Return` 단일 arm으로 통합 | CS8510 |
|
||
| `Core/ContextManager.cs` | `EnumDisplayMonitors` 콜백 람다 파라미터 혼합 타입 (`ref RECT` + 암시적 `_`) → 전체 명시적 타입으로 수정 (×2) | CS0748 |
|
||
| `Assets/icon.ico` | 아이콘 파일 누락 → 다이아몬드 픽셀 보석 아이콘으로 교체 (`tools/IconGenerator`로 생성, 7크기 ICO) | CS7064 |
|
||
| `Views/SettingsWindow.xaml.cs` | `NewIndexPathBox` nullable 역참조 → null 조건 추가 | CS8602 |
|
||
|
||
### 런타임 버그 수정
|
||
|
||
| 파일 | 수정 내용 | 심각도 |
|
||
|------|----------|-------|
|
||
| `Handlers/JsonSkillLoader.cs` | `NavigatePath`: `field[0` 같이 `]` 없는 경로 파싱 시 `IndexOf` 반환 −1로 인한 예외 → `closingIdx < 0` 조기 반환 추가 | HIGH |
|
||
| `Services/ClipboardHistoryService.cs` | `_ignoreNext` 플래그를 `volatile bool`로 선언하여 스레드 간 가시성 보장 | MEDIUM |
|
||
| `Services/ClipboardHistoryService.cs` | `Initialize()` 호출 시 이미 초기화된 경우(`_msgSource != null`) 또는 `Dispose()` 후 재호출 방지 가드 추가 | MEDIUM |
|
||
| `Services/ClipboardHistoryService.cs` | `Dispose()` 중복 호출 방지를 위한 `_disposed` 플래그 추가 | MEDIUM |
|
||
| `Services/IndexService.cs` | `ScheduleRebuild`: `_debounceTimer` 교체 시 비원자적 Dispose + 재할당을 `_timerLock` 으로 보호 | MEDIUM |
|
||
| `Services/SettingsService.cs` | settings.json 백업 실패 시 빈 `catch {}` → `LogService.Warn`으로 원인 기록 | MEDIUM |
|
||
|
||
### 보안 수정
|
||
|
||
| 파일 | 수정 내용 | 심각도 |
|
||
|------|----------|-------|
|
||
| `Handlers/JsonSkillLoader.cs` | `ExecuteAsync`: `item.ActionUrl` 실행 전 `http`/`https` 스킴 검증 추가 — API 응답이 조작된 `file://` 등 비표준 URL 실행 방지 | MEDIUM |
|
||
|
||
### 데드 코드 제거
|
||
|
||
| 파일 | 수정 내용 |
|
||
|------|----------|
|
||
| `Handlers/SystemCommandHandler.cs` | `allCommands` 목록에서 `timer`·`alarm` no-op 항목 제거 — 두 명령은 `q.StartsWith` early-return으로 완전히 처리되며, `Action = () => Task.CompletedTask` 항목은 클릭 시 아무것도 하지 않아 사용자 혼란 유발 |
|
||
|
||
---
|
||
|
||
## v0.7 2차 코드 검토 수정 (컴파일러 경고 제거)
|
||
|
||
| 파일 | 수정 내용 | 경고 코드 |
|
||
|------|----------|----------|
|
||
| `Services/UsageRankingService.cs` | `using AxCommander.Services;` 자기 자신 namespace import 제거 | CS0105 |
|
||
| `Handlers/PortHandler.cs` | `UdpStatistics? udpStats = null;` 미사용 변수 제거 | CS0219 |
|
||
| `Handlers/PortHandler.cs` | `using System.Net;` 미사용 using 제거 (모든 네트워크 타입은 `System.Net.NetworkInformation`에서 확보) | IDE0005 |
|
||
| `Handlers/ScreenCaptureHandler.cs` | 미사용 P/Invoke `keybd_event` 선언 제거 (실제 키 전송은 `SendMessage`로 구현) | CS0649 |
|
||
| `Handlers/ScreenCaptureHandler.cs` | 미사용 상수 `KEYEVENTF_KEYUP`, `SB_BOTTOM` 제거 | CS0219 |
|
||
| `Handlers/SnapHandler.cs` | 주석 `"snap " 프리픽스` → `"snap" 프리픽스` (실제 Prefix 필드와 일치) | 문서 오류 |
|
||
|
||
### v0.7 → v0.8 (UI 개선 + 명령 별칭 + 사용 통계)
|
||
|
||
| 파일 | 변경 내용 |
|
||
|------|----------|
|
||
| `Views/SettingsWindow.xaml` | 스니펫 탭 "추가" 버튼 `Width="60"` → `MinWidth="72"` (텍스트 잘림 수정) |
|
||
| `Models/AppSettings.cs` | `SystemCommandSettings`에 `CommandAliases` 딕셔너리 추가 |
|
||
| `Handlers/SystemCommandHandler.cs` | `GetItemsAsync` 필터링에 별칭 매칭 추가 — `/잠금`, `/l` 등 사용자 정의 별칭으로도 명령 접근 가능 |
|
||
| `ViewModels/SettingsViewModel.cs` | `AliasLock`·`AliasSleep`·`AliasRestart`·`AliasShutdown`·`AliasHibernate`·`AliasLogout`·`AliasRecycle` 7개 별칭 프로퍼티 추가 / `ResetSystemCommandAliases()` 추가 |
|
||
| `Views/SettingsWindow.xaml` | 시스템 탭 행을 4열 레이아웃으로 재설계 — [아이콘][이름/프리픽스][별칭 TextBox][토글], "별칭 기본값 초기화" 버튼 추가 |
|
||
| `Views/SettingsWindow.xaml.cs` | `ResetCommandAliases_Click` 핸들러 추가 |
|
||
| `Models/DailyUsageStats.cs` (신규) | 일별 사용 통계 데이터 모델 — `LauncherOpens`, `CommandUsage`, `ActiveSeconds` |
|
||
| `Services/UsageStatisticsService.cs` (신규) | static 통계 서비스 — `%APPDATA%\AxCommander\stats\YYYY-MM-DD.json` 저장, 30일 롤링 삭제, `RecordLauncherOpen()` / `RecordCommandUsage()` / `AddActiveSeconds()` / `GetStats()` |
|
||
| `Services/SessionTrackingService.cs` (신규) | `SystemEvents.SessionSwitch` 기반 PC 활성 시간 추적 — 잠금 시 누적 초 기록, 해제 시 타이머 재개, `Dispose()` 시 플러시 |
|
||
| `ViewModels/StatisticsViewModel.cs` (신규) | `DayBarItem` / `CommandStatItem` 레코드, `LauncherOpenBars` / `ActiveTimeBars` / `TopCommands` 컬렉션, 요약 카드 문자열 |
|
||
| `Views/StatisticsWindow.xaml` (신규) | 다크 그라데이션 헤더, 4개 요약 카드, 런처 호출 막대 차트 (최근 14일), PC 활성 시간 막대 차트 (최근 14일), 상위 명령 순위 목록 |
|
||
| `Views/StatisticsWindow.xaml.cs` (신규) | 드래그 이동, 새로고침/닫기 버튼 핸들러 |
|
||
| `Views/TrayContextMenu.cs` | `GlyphStats = "\uE9D9"` (Chart) 상수 추가 |
|
||
| `App.xaml.cs` | `_sessionTracking` 필드 추가, `OnHotkeyTriggered()`에 `UsageStatisticsService.RecordLauncherOpen()` 추가, 트레이 메뉴 "사용 통계" 항목 추가, `OnExit()`에 `_sessionTracking?.Dispose()` 추가 |
|
||
| `Core/CommandResolver.cs` | `ExecuteAsync()`에 명령 사용 통계 기록 추가 — 프리픽스 + 첫 단어를 키로 `UsageStatisticsService.RecordCommandUsage()` 호출 |
|
||
|
||
**사용 통계 데이터 저장 경로**: `%APPDATA%\AxCommander\stats\`
|
||
|
||
**일별 JSON 형식**:
|
||
```json
|
||
{
|
||
"date": "2026-03-26",
|
||
"launcherOpens": 42,
|
||
"commandUsage": { "/lock": 3, "=": 8, ";addr": 5 },
|
||
"activeSeconds": 18432
|
||
}
|
||
```
|
||
|
||
**차트 구성**:
|
||
- 런처 호출 횟수: 최근 14일 막대 차트 (오늘 강조)
|
||
- PC 활성 시간: 최근 14일 막대 차트 (초 → 시간 환산)
|
||
- 상위 명령: 30일 합산 Top 10, 순위 + 명령키 + 사용횟수 + 비율 바
|
||
|
||
**빌드 검증**: `dotnet build --output "C:/Temp/axtest"` — **0 errors, 0 warnings** 확인
|
||
|
||
### v0.8 → v0.9 (UX 버그 수정 + 클립보드 영속성 + 다국어 + 단일 인스턴스)
|
||
|
||
| 파일 | 변경 내용 |
|
||
|------|----------|
|
||
| `Views/LauncherWindow.xaml` | `Window` 요소에 `PreviewKeyDown="Window_PreviewKeyDown"` 추가. TextBox에서 키 핸들러 제거 (ScrollViewer 키 소비 문제 해결) |
|
||
| `Views/LauncherWindow.xaml.cs` | `Window_PreviewKeyDown` 으로 Escape·Enter·Down·Up·Right·Tab 일괄 처리. Tab 커서 위치를 `Dispatcher.BeginInvoke(DispatcherPriority.Input)`으로 뒤로 이동 수정. `Window_KeyDown`은 Ctrl+, 전담 |
|
||
| `Services/ClipboardHistoryService.cs` | JSON 영속성 추가 — `%APPDATA%\AxCommander\clipboard_history.json`. `Initialize()` 시 로드, 항목 변경·삭제 시 비동기 저장, `Dispose()` 시 동기 저장 |
|
||
| `Handlers/ClipboardHistoryHandler.cs` | 클립보드 항목 선택 후 이전 창 포커스 복원 + Ctrl+V 자동 붙여넣기. `SetForegroundWindow` P/Invoke 추가, 150ms 딜레이 후 `WindowTracker.PreviousWindow`로 포커스 이동 |
|
||
| `App.xaml.cs` | 단일 인스턴스 Mutex (`Global\\AXCommander_SingleInstance`) 추가. 중복 실행 시 안내 메시지 후 `Shutdown()`. 트레이 `DoubleClick` → `MouseClick` (좌클릭 한 번으로 런처 토글). `L10n.SetLanguage(settings.Settings.Launcher.Language)` 호출 추가. `OnExit()`에 Mutex 해제 추가 |
|
||
| `Services/SettingsService.cs` | `CreateDefaults()` 에서 `D:\Non_Document` 존재 시 인덱스 경로에 자동 추가 |
|
||
| `Services/L10n.cs` (신규) | 정적 다국어 서비스 — `L10n.SetLanguage(lang)` / `L10n.Get(key)`. 지원 언어: ko·en·ja·zh·vi. 키: placeholder·loading·no_results·clipboard_empty·merge_hint 등 |
|
||
| `Models/AppSettings.cs` | `LauncherSettings`에 `Language` 프로퍼티 추가 (`"ko"` 기본값) |
|
||
| `ViewModels/SettingsViewModel.cs` | `Language` 프로퍼티 추가, `Save()` 시 `L10n.SetLanguage()` 호출 |
|
||
| `ViewModels/LauncherViewModel.cs` | `PlaceholderText` → `L10n.Get("placeholder")` 반환 |
|
||
| `Views/SettingsWindow.xaml` | 일반 탭 상단에 언어 선택 ComboBox 추가 (한국어/English/日本語/中文/Tiếng Việt) |
|
||
| `Handlers/HelpHandler.cs` | 헤더 항목 `Data = "__HELP_OVERVIEW__"` 설정. `ExecuteAsync` 에서 `HelpDetailWindow` 열기 |
|
||
| `Views/HelpDetailWindow.xaml` (신규) | 프레임리스 다크 창 (720×640). 모든 도움말 항목을 카드 형태로 표시. ESC 닫기, 드래그 이동 |
|
||
| `Views/HelpDetailWindow.xaml.cs` (신규) | `HelpItemModel` 클래스 (Category·Command·Title·Description·Example·Symbol·ColorBrush) |
|
||
| `Views/` | `AboutWindow`에 `mascot.png` 이미지 표시 — `Assets/mascot.png` 파일이 있을 때만 표시 (없으면 공간 숨김) |
|
||
|
||
**방향키 내비게이션 버그 원인 및 수정**:
|
||
|
||
TextBox 내부의 `PART_ContentHost`(ScrollViewer)가 터널링 단계(PreviewKeyDown)에서 Up/Down 키를 소비하므로 TextBox 레벨 이벤트 핸들러로는 차단 불가. 수정: Window 레벨 `PreviewKeyDown`으로 이동 — Window는 터널링 최상위이므로 모든 자식 요소보다 먼저 키 이벤트를 수신.
|
||
|
||
**Tab 커서 위치 버그 원인 및 수정**:
|
||
|
||
`_vm.InputText = title` 바인딩 업데이트는 렌더링 사이클 이후에 TextBox에 반영되므로 직후 `CaretIndex`를 설정해도 바인딩이 덮어씀. 수정: `Dispatcher.BeginInvoke(() => InputBox.CaretIndex = ..., DispatcherPriority.Input)` 으로 다음 입력 처리 사이클에 커서 위치 설정.
|
||
|
||
**클립보드 히스토리 JSON 형식** (`clipboard_history.json`):
|
||
```json
|
||
[
|
||
{ "text": "복사한 텍스트", "ts": "2026-03-26T10:30:00" },
|
||
{ "text": "이전 복사", "ts": "2026-03-26T10:25:00" }
|
||
]
|
||
```
|
||
이미지 타입은 직렬화하지 않음 (텍스트 전용 저장).
|
||
|
||
**빌드 검증**: `dotnet build --output "C:/Temp/axtest3"` — **0 errors, 0 warnings** 확인
|
||
|
||
### v0.9 2차 (잠금 해제 알림 + 화면 캡처 설정 + 테마 모양 + 트레이 메뉴 개선)
|
||
|
||
| 파일 | 변경 내용 |
|
||
|------|----------|
|
||
| `Assets/Quotes/famous.json` (신규) | 내장 명언 500개 JSON (EmbeddedResource) — 동서양 철학자·사상가·과학자·경영자·작가·한국 위인 등 다양한 인물 |
|
||
| `Services/QuoteService.cs` (신규) | `GetRandomQuote()` — `famous.json` EmbeddedResource 로드, 앱 생애 동안 한 번만 파싱, 랜덤 반환 |
|
||
| `Services/WorktimeReminderService.cs` (신규) | `SessionTrackingService`로부터 잠금 해제 이벤트를 구독하여 누적 사용시간 계산. 설정한 간격(30~240분) 이상 경과 시 `ReminderPopupWindow` 표시. `enabled` 설정이 꺼져 있으면 즉시 비활성 |
|
||
| `Views/ReminderPopupWindow.xaml/.cs` (신규) | 잠금 해제 팝업 — 사용 시간·격려 문구·명언 표시. 설정한 화면 모서리(4방향)에 위치. `SetNoActivate()` P/Invoke로 포커스 비활성 상태 유지. 설정한 초 후 자동 닫힘 |
|
||
| `Models/AppSettings.cs` | `ScreenCaptureSettings` 중첩 클래스 추가 (`Prefix`, `SaveToFile`, `SavePath`). `ReminderSettings` 중첩 클래스 추가 (`Enabled`, `Position`, `IntervalMinutes`, `AutoDismissSeconds`) |
|
||
| `Views/SettingsWindow.xaml/.cs` | 캡처 탭 추가 — `cap` 프리픽스 TextBox, 파일 저장 토글, 저장 경로 TextBox+폴더 선택 버튼. 알림 탭 추가 — 활성화 토글, 위치 ComboBox(4방향), 간격 ComboBox(30/60/120/240분), 자동 닫힘 ComboBox(5/10/15/20/30초) |
|
||
| `ViewModels/SettingsViewModel.cs` | `CapPrefix`, `SaveToFile`, `SavePath`, `ReminderEnabled`, `ReminderPosition`, `ReminderIntervalMinutes`, `ReminderAutoDismissSeconds` 프로퍼티 추가 |
|
||
| `Handlers/ScreenCaptureHandler.cs` | `Prefix` 프로퍼티를 `settings.ScreenCapture.Prefix` 런타임 값으로 교체. 캡처 성공 시 `settings.ScreenCapture.SaveToFile`이 true면 `SavePath`(빈 값이면 기본 경로)에 PNG 파일 저장 |
|
||
| `App.xaml.cs` | `WorktimeReminderService` 초기화 + `SessionTrackingService`와 연결. `OnExit()`에 `_worktimeReminder?.Dispose()` 추가 |
|
||
| `Themes/*.xaml` (9개 파일) | 각 테마에 `WindowCornerRadius`·`ItemCornerRadius` `CornerRadius` 리소스 추가 (테마별 고유 값 적용) |
|
||
| `Views/LauncherWindow.xaml` | 창 최상위 `Border.CornerRadius` → `{DynamicResource WindowCornerRadius}`. 항목 `ControlTemplate Border.CornerRadius` → `{DynamicResource ItemCornerRadius}` |
|
||
| `Views/LauncherWindow.xaml.cs` | `BuildCustomDictionary()`에 `WindowCornerRadius`·`ItemCornerRadius` 기본값(20, 10) 추가 |
|
||
| `Views/TrayContextMenu.cs` | `DarkTrayRenderer`/`DarkColorTable` → `ModernTrayRenderer`/`ModernColorTable` 전면 재작성. WPF `Application.Current.Resources`에서 `LauncherBackground`·`AccentColor`·`PrimaryText` 등을 읽어 테마 색상 반영. `SetWindowRgn` P/Invoke로 메뉴 창 모서리 라운딩. 시작 시 자동실행 항목 글리프 → 전구(`\uE82F`), 활성 시 앰버 색상(`#FFB300`) + 후광 효과. `OnRenderItemCheck` 빈 override로 기본 체크마크 억제 |
|
||
| `Themes/Symbols.cs` | `ReminderBell = "\uEA8F"` (벨 아이콘) + `Lightbulb = "\uE82F"` (전구 아이콘) 추가 |
|
||
| `Handlers/HelpHandler.cs` | `cap` 항목: 프리픽스 변경 가능·파일 저장 경로 설명 추가. `info` 항목: 커맨드 표시 `"info · *"`, `*` 단축키 설명 추가. 신규 `알림` 카테고리 항목 추가 (잠금 해제 사용시간 알림) |
|
||
|
||
**WorktimeReminderService 동작 흐름**:
|
||
```
|
||
SessionTrackingService.Unlocked 이벤트
|
||
→ WorktimeReminderService.OnUnlocked()
|
||
→ 설정 disabled? → 무시
|
||
→ 마지막 알림 이후 경과 시간 < IntervalMinutes? → 무시
|
||
→ ReminderPopupWindow(사용시간, 명언) 표시 (Dispatcher.Invoke)
|
||
→ _lastReminderTime 갱신
|
||
```
|
||
|
||
**트레이 메뉴 `ThemeColor()` 헬퍼**:
|
||
```csharp
|
||
private static Color ThemeColor(string key, Color fallback)
|
||
{
|
||
try {
|
||
if (Application.Current?.Resources[key]
|
||
is System.Windows.Media.SolidColorBrush b)
|
||
return Color.FromArgb(b.Color.A, b.Color.R, b.Color.G, b.Color.B);
|
||
} catch { }
|
||
return fallback;
|
||
}
|
||
```
|
||
WPF ResourceDictionary를 WinForms GDI 렌더러에서 안전하게 읽기 위해 try/catch로 감쌉니다.
|
||
|
||
**빌드 검증**: `dotnet build` — **0 errors, 0 warnings** 확인
|
||
|
||
### v0.9 3차 (보안 강화 + 글로벌 캡처 단축키 + 영역 미세조정)
|
||
|
||
| 파일 | 변경 내용 |
|
||
|------|----------|
|
||
| `Services/ClipboardHistoryService.cs` | 클립보드 히스토리 저장을 **DPAPI 암호화**로 전환. `clipboard_history.json`(평문) → `clipboard_history.dat`(DPAPI). 구버전 평문 파일 자동 마이그레이션 + 원본 삭제. `DataProtectionScope.CurrentUser` — 현재 Windows 사용자 계정에서만 복호화 가능 |
|
||
| `AxCommander.csproj` | `System.Security.Cryptography.ProtectedData 8.0.0` NuGet 패키지 추가 (로컬 전용, 네트워크 통신 없음) |
|
||
| `Models/AppSettings.cs` | `ScreenCaptureSettings`에서 `SaveToFile`, `SavePath` 완전 제거 (보안 정책). `GlobalHotkeyEnabled`, `GlobalHotkey`, `GlobalHotkeyMode`, `ScrollDelayMs` 추가. `CustomThemeColors`에 `WindowCornerRadius`, `ItemCornerRadius` 추가 |
|
||
| `Handlers/ScreenCaptureHandler.cs` | 파일 저장 로직(`ShouldSave`, `GetSaveDir`, `bmp.Save()`) 전면 제거 — 캡처 결과는 **클립보드에만 복사**. `CaptureDirectAsync(mode)` public 메서드 추가 (글로벌 단축키용). 스크롤 딜레이 하드코딩 120ms → `ScrollDelayMs` 설정값 사용 |
|
||
| `Core/InputListener.cs` | `_captureHotkey` + `CaptureHotkeyTriggered` 이벤트 추가. `UpdateCaptureHotkey(string, bool)` 메서드로 캡처 단축키 동적 등록/해제 |
|
||
| `Core/HotkeyParser.cs` | `PrintScreen`(0x2C), `Pause`(0x13), `ScrollLock`(0x91) 키 추가 |
|
||
| `App.xaml.cs` | `OnCaptureHotkeyTriggered` 핸들러 추가 — 런처 없이 `CaptureDirectAsync` 직접 호출. 설정 저장 시 캡처 단축키 갱신 |
|
||
| `ViewModels/SettingsViewModel.cs` | `CapGlobalHotkeyEnabled`, `CapGlobalHotkey`, `CapGlobalMode`, `CapScrollDelayMs/Str`, `CustomWindowCornerRadius`, `CustomItemCornerRadius` 프로퍼티 + Load/Save |
|
||
| `Views/SettingsWindow.xaml` | 캡처 탭: 파일 저장 UI 전면 제거, 글로벌 단축키 섹션 추가 (활성 토글·키 레코더·모드 선택·기본값 복원), 스크롤 딜레이 ComboBox. 색상 편집 탭: "모양 (모서리 라운딩)" 섹션 + 슬라이더 2개 (창/항목) |
|
||
| `Views/SettingsWindow.xaml.cs` | `CapHotkeyRecorder_PreviewKeyDown` 키 녹화 핸들러, `ResetCapGlobalHotkey_Click` 추가 |
|
||
| `Views/LauncherWindow.xaml.cs` | `BuildCustomDictionary()`가 커스텀 `WindowCornerRadius`/`ItemCornerRadius` 설정값 적용 (기존 하드코딩 20/10 → 사용자 값) |
|
||
| `Views/LauncherWindow.xaml` | 액션 breadcrumb 바 하드코딩 `#4B5EFC` → `{DynamicResource AccentColor}` 교체 |
|
||
| `Views/RegionSelectWindow.xaml.cs` | `_endPoint` 필드 추가, 드래그 종료 후 화살표 키(1px/Shift 10px) 미세조정 + Enter 확정 지원 |
|
||
| `Views/TrayContextMenu.cs` | `SetWindowRgn` 실패 시 `DeleteObject(rgn)` 호출 → GDI 핸들 누수 수정 |
|
||
| `Handlers/HelpHandler.cs` | `_entries.Length - 6` 하드코딩 → `_entries.Count(e => e.Category != "키보드")` 동적 계산. `cap` 항목 설명에 글로벌 단축키 언급 추가 |
|
||
| `Views/ReminderPopupWindow.xaml.cs` | `GetWindowLong`/`SetWindowLong` → `GetWindowLongPtr`/`SetWindowLongPtr` 64비트 안전 교체. 타이머 Tick 핸들러 해제. Esc 키 닫기 지원 |
|
||
| `Services/WorktimeReminderService.cs` | `lock(_lock)` 스레드 동기화 추가 (SessionSwitch 백그라운드 스레드 ↔ UI 스레드 레이스 컨디션 해소). `IntervalMinutes` 최소값 보호 (`Math.Max(1, ...)`) |
|
||
|
||
**보안 정책 변경**:
|
||
- 캡처: 파일 저장 기능 코드에서 완전 제거. 설정 UI에도 없음. 클립보드에만 복사.
|
||
- 클립보드 히스토리: DPAPI `DataProtectionScope.CurrentUser`로 암호화 저장. 파일 확장자 `.json` → `.dat`. 다른 사용자/PC에서 열 수 없음.
|
||
- 통계(`stats/*.json`): 민감 데이터 아님, 암호화 미적용.
|
||
|
||
**빌드 검증**: `dotnet build` — **0 errors, 0 warnings** 확인
|
||
|
||
### v0.9 → v1.0 (정식 릴리스 — 유틸리티 8종 + 스포이드 + 서비스 관리)
|
||
|
||
| 파일 | 변경 내용 |
|
||
|------|----------|
|
||
| `Handlers/ColorPickHandler.cs` (신규) | `pick` 프리픽스. 전체 화면 스포이드 모드(`EyeDropperWindow`) → 클릭 지점 색상 HEX 코드 추출 → 반투명 결과 창(`ColorPickResultWindow`) 5초 표시 → 클립보드 복사 |
|
||
| `Views/EyeDropperWindow.xaml/.cs` (신규) | 전체 화면 투명 오버레이. 마우스 따라다니는 돋보기 원 + 실시간 HEX 코드 레이블. `GetPixel` P/Invoke로 화면 픽셀 색상 읽기. 좌클릭 확정, 우클릭/Esc 취소 |
|
||
| `Views/ColorPickResultWindow.xaml/.cs` (신규) | 반투명 다크 팝업. 색상 미리보기 원 + HEX/RGB 텍스트 + 자동 닫힘 5초 타이머 |
|
||
| `Handlers/DateCalcHandler.cs` (신규) | `date` 프리픽스. `+30d`/`-100d` 가감, D-day 계산, Unix timestamp ↔ 날짜 변환, 요일·ISO 주차, `date unix` 현재 타임스탬프 |
|
||
| `Handlers/ServiceHandler.cs` (신규) | `svc` 프리픽스. `ServiceController` API로 Windows 서비스 검색·상태 조회. `svc start/stop/restart [이름]`으로 제어(관리자 권한 UAC). `svc restart clipboard` → AX 클립보드 히스토리 서비스 강제 재시작 |
|
||
| `Services/ClipboardHistoryService.cs` | `Reinitialize()` 메서드 추가 — Dispose 후 내부 상태 초기화 + 클립보드 모니터링 재개 |
|
||
| `AxCommander.csproj` | `System.ServiceProcess.ServiceController 8.0.1` NuGet 패키지 추가 (로컬 전용) |
|
||
| `Handlers/TextStatsHandler.cs` (신규) | `stats` 프리픽스. 클립보드 텍스트 글자·단어·줄 수, UTF-8 바이트, 키워드 빈도(Top 5), 읽기 시간 추정, 특정 키워드 검색 |
|
||
| `Handlers/FavoriteHandler.cs` (신규) | `fav` 프리픽스. 자주 쓰는 파일·폴더 경로를 `favorites.json`에 저장, `fav add/del` 서브커맨드 |
|
||
| `Handlers/RenameHandler.cs` (신규) | `rename` 프리픽스. 폴더\패턴 파일 목록, 템플릿 변수 `{n}`순번 `{date}`날짜 `{orig}`원본명, 미리보기 후 실행 |
|
||
| `Handlers/MonitorHandler.cs` (신규) | `monitor` 프리픽스. CPU·메모리(`GlobalMemoryStatusEx`)·디스크·가동시간·Top 5 프로세스 |
|
||
| `Handlers/ScaffoldHandler.cs` (신규) | `scaffold` 프리픽스. 내장 5개 + 사용자 JSON 템플릿 |
|
||
| `Themes/Symbols.cs` | EyeDropper·DateIcon·ServiceIcon + TextStats·Favorite·RenameIcon·MonitorIcon·ScaffoldIcon 8개 심볼 추가 |
|
||
| `Handlers/ClipboardPipeHandler.cs` (신규) | `pipe` 프리픽스. 19종 필터를 `>` 체이닝 — upper/lower/trim/sort/unique/reverse/number/quote/b64e/b64d/urle/urld/md/lines/count/csv/tab/trimall 등 |
|
||
| `Handlers/JournalHandler.cs` (신규) | `journal` 프리픽스. `UsageStatisticsService` 데이터 기반 업무 일지 마크다운 자동 생성 (활성 시간, 런처 호출, 명령어 사용 순위) |
|
||
| `Handlers/RoutineHandler.cs` (신규) | `routine` 프리픽스. `routines.json` + 내장 2개(morning/endofday). 앱·폴더·URL·명령을 순서대로 일괄 실행 |
|
||
| `Handlers/BatchTextHandler.cs` (신규) | `batch` 프리픽스. 클립보드 각 줄에 동시 변환 — prefix/suffix/wrap/number/sort/unique/trim/replace/csv/split/indent 등 14종 |
|
||
| `Handlers/DiffHandler.cs` (신규) | `diff` 프리픽스. 클립보드 최근 2개 비교 + 파일 2개 경로 비교 + **파일 선택 다이얼로그(OpenFileDialog)** 지원 |
|
||
| `Handlers/WindowSwitchHandler.cs` (신규) | `win` 프리픽스. `EnumWindows` P/Invoke로 열린 창 목록 조회·검색, `SetForegroundWindow`로 즉시 전환. 최소화 창 자동 복원 |
|
||
| `Handlers/HelpHandler.cs` | 14개 신규 핸들러 도움말 항목 추가 |
|
||
| `Views/HelpDetailWindow.xaml/.cs` | **카테고리별 페이지네이션 재설계** — 상단 카테고리 탭 바 + ← → 키 페이지 전환 + 이전/다음 버튼 + 페이지 인디케이터 |
|
||
| `App.xaml.cs` | 14개 핸들러 등록 + `DispatcherUnhandledException` 전역 예외 핸들러 + `LoadAppIcon` 내장 리소스 폴백 |
|
||
| `Services/ClipboardHistoryService.cs` | `Reinitialize()` 메서드 추가 (ServiceHandler의 클립보드 강제 재시작용) |
|
||
| `AxCommander.csproj` | `IncludeNativeLibrariesForSelfExtract=true` (단일 EXE 배포), `System.ServiceProcess.ServiceController 8.0.1` 추가, mascot/icon 내장 리소스 |
|
||
|
||
**배포** (`build.bat` 더블클릭으로 3종 자동 빌드):
|
||
|
||
| 파일 | 크기 | 용도 |
|
||
|------|------|------|
|
||
| `dist\AxCommander\` | 163MB (폴더) | 본체 EXE + DLL — 폴더째 복사해도 실행 가능 |
|
||
| `dist\AxCommander_Setup.exe` | ~136MB | 오프라인 인스톨러 (본체+런타임 모두 ZIP 내장, 인터넷 불필요) |
|
||
| `dist\AxCommander_Setup_Online.exe` | **~1MB** | 온라인 인스톨러 (.NET Framework 4.8 기반, 본체(~2MB) ZIP 내장 + .NET 8 Runtime 인터넷 자동 설치) |
|
||
|
||
인스톨러 기능: 설치 경로 선택 · 바탕화면 바로가기 · 시작 메뉴 · 자동 실행 · 프로그램 추가/제거 · 기존 설치 감지 → 업그레이드 · 제거
|
||
|
||
**v1.0 최종 수정 (디자인/오류 검수)**:
|
||
|
||
| 파일 | 수정 |
|
||
|------|------|
|
||
| `Views/SettingsWindow.xaml` | `{StaticResource ModernComboBox}` 참조 2곳 제거 — 해당 스타일 미정의로 설정 창 XamlParseException 크래시 수정 |
|
||
| `Views/TrayContextMenu.cs` | `MakeItem()`에 1×1 투명 더미 `Image` 설정 — `OnRenderItemImage` 콜백이 호출되지 않아 글리프 아이콘 미표시 문제 수정. `OnRenderItemCheck`에서도 `DrawGlyph()` 호출. 전구 꺼짐 색상 `#A0A08C` → `#78788C` 진한 회색으로 변경 |
|
||
| `App.xaml.cs` | 자동실행 `autoStartItem`에 `Image = new Bitmap(1,1)` 추가 |
|
||
| `Views/HelpDetailWindow.xaml.cs` | `NavigateToPage()` 빈 카테고리 방어 코드 |
|
||
| `Handlers/WindowSwitchHandler.cs` | 자기 프로세스 제외를 하드코딩 타이틀 대신 `Process.GetCurrentProcess().ProcessName` 비교로 변경 |
|
||
|
||
**v1.0 UI/UX 최종 수정**:
|
||
|
||
| 파일 | 수정 |
|
||
|------|------|
|
||
| `Views/SettingsWindow.xaml` | 사이드바 `TabPanel`을 `ScrollViewer`로 감싸 탭 10개+ 스크롤 지원. `ModernComboBox` 미정의 참조 제거 (XamlParseException 수정) |
|
||
| `Views/TrayContextMenu.cs` | `MakeItem()`에 1×1 더미 Image 설정 → 글리프 아이콘 표시. `DrawLightbulbGlow`를 `PathGradientBrush` 원형 그라데이션으로 교체 (빛 대칭). `OnRenderItemCheck`에서도 `DrawGlyph` 호출 |
|
||
| `Views/HelpDetailWindow.xaml` | 카테고리 탭 바 `ScrollViewer` → `WrapPanel` (스크롤 제거, 모두 표시). 창 크기 880×680 |
|
||
| `Views/HelpDetailWindow.xaml.cs` | 프로그램 개요 3개 항목(설명/사용법/저장경로) 자동 삽입. `NavigateToPage()` 빈 카테고리 방어 코드 |
|
||
| `Handlers/HelpHandler.cs` | `static _entries` → `_baseEntries` + `GetEntries()` 동적 메서드. 설정에서 변경한 캡처 프리픽스·글로벌 핫키 실시간 반영 |
|
||
| `Views/AboutWindow.xaml/.cs` | 상단 원형 → 앱 아이콘(icon.ico) 표시. 마스코트는 숨김 상태로 로드 → 사용자 클릭 시 오버레이만. 조직명 행에서 이름/직급 제거 (하단에만 표시). `TryLoadAppIcon()` + `TryLoadMascot()` 분리 |
|
||
| `Services/LogService.cs` | `PurgeOldLogs()` 추가 — 14일 초과 로그 자동 삭제 (앱 세션 당 1회) |
|
||
| `App.xaml.cs` | `DispatcherUnhandledException` 전역 예외 핸들러. `LoadAppIcon` pack:// 내장 리소스 폴백. `HelpHandler(settings)` 주입 |
|
||
|
||
**v1.0 추가 기능**:
|
||
|
||
| 파일 | 변경 |
|
||
|------|------|
|
||
| `Services/FaviconService.cs` (신규) | URL 별칭 항목에 사이트 favicon 표시. Google Favicon API → 디스크 캐시(`%APPDATA%\AxCommander\favicons\`) → `IconPath`에 경로 전달 |
|
||
| `Handlers/AliasHandler.cs` | `UrlAliasHandler.GetFaviconPath()` — favicon 캐시 경로 조회 + 백그라운드 다운로드 |
|
||
| `Views/LauncherWindow.xaml` | 아이템 아이콘 영역에 `IconPath` 이미지 표시 지원 (`NullToCollapsedConverter`로 심볼/이미지 자동 전환) |
|
||
| `Themes/Converters.cs` | `NullToCollapsedConverter` 추가 |
|
||
| `App.xaml` | `NullToCollapsedConverter` 글로벌 등록 |
|
||
| `Handlers/WebSearchHandler.cs` | `?ni`(네이버 이미지), `?gi`(구글 이미지) 엔진 추가 (총 10개) |
|
||
| `Handlers/HelpHandler.cs` | 웹 검색 항목에 10개 엔진 전체 목록 표시 |
|
||
| `ViewModels/SettingsViewModel.cs` | `ValidateBeforeSave()` — 예약어/프리픽스 충돌 감지. 충돌 시 `MessageBox` 알림 + 저장 거부 |
|
||
| `Views/SettingsWindow.xaml/.cs` | 하단 바에 **내보내기/불러오기** 버튼 추가 (`.axsettings` 파일) |
|
||
|
||
**v1.0 아이콘 교체 + 최종 디자인 검수**:
|
||
|
||
| 파일 | 수정 |
|
||
|------|------|
|
||
| `Assets/icon.ico` | 다이아몬드 픽셀 보석 컷 아이콘으로 교체 (Blue/Green/Red/Green 4색, 흰색 facet 선, 7크기 16~256px) |
|
||
| `Assets/diamond_pixel.svg` | 아이콘 SVG 원본 (참고용) |
|
||
| `tools/IconGenerator/` | 아이콘 생성 콘솔 앱 (.NET 8 WinForms, `System.Drawing`으로 보석 다이아몬드 렌더링 → ICO 출력) |
|
||
| `Views/AboutWindow.xaml` | 버전 텍스트 폴백 `"v1.0"` → `"v1.0.1"` (csproj `Version=1.0.1`과 일치) |
|
||
| `Views/SettingsWindow.xaml` | 사이드바 `ScrollViewer`에서 `DockPanel.Dock="Top"` 제거 → 마지막 자식으로 남은 공간 채워 스크롤 정상 동작 |
|
||
|
||
**최종 검수 결과**:
|
||
- 전체 빌드 (3개 프로젝트): **0 errors, 0 warnings**
|
||
- 버전 일치: csproj `1.0.1` = AboutWindow `v1.0.1` ✓
|
||
- CornerRadius DynamicResource 바인딩: 정상 ✓
|
||
- 사이드바 ScrollViewer: 수정 완료 (DockPanel.Dock 제거) ✓
|
||
- 전구 글로우: PathGradientBrush 중심 대칭 확인 ✓
|
||
- HelpHandler 항목: 전체 정확성 확인 ✓
|
||
- 아이콘 로딩: pack:// 리소스 + 파일시스템 폴백 정상 ✓
|
||
|
||
---
|
||
|
||
## 🚧 개발 예정 — `!` 예약어 LLM 대화 기능
|
||
|
||
> **상태**: 구현 완료 (핵심 기능)
|
||
> **버전**: v1.0.5
|
||
> **마지막 업데이트**: 2026-03-28
|
||
|
||
### 개요
|
||
|
||
`!` 예약어를 입력하면 LLM(대규모 언어 모델) 서비스에 질의를 보내고 응답을 받아 표시하는 **AI 대화 기능**. 런처 입력창에서 `!질문내용` 또는 `! 질문내용`으로 시작하면 전용 대화 창이 열리며, Claude Code / Gemini 스타일의 대화 인터페이스를 제공한다.
|
||
|
||
### 입력 방식
|
||
|
||
| 입력 | 동작 |
|
||
|------|------|
|
||
| `!안녕하세요` | `!` 제거 후 "안녕하세요"를 LLM에 전송 |
|
||
| `! 안녕하세요` | `!`와 텍스트 사이 공백 제거 후 "안녕하세요"를 LLM에 전송 |
|
||
| `!` (단독) | 대화 창만 열기 (빈 상태) |
|
||
|
||
### 대화 창 (ChatWindow) 설계
|
||
|
||
**레이아웃: 2패널 구조**
|
||
|
||
```
|
||
┌──────────────────────────────────────────────────┐
|
||
│ [≡] AX Commander — AI 대화 [_][□][✕] │
|
||
├──────────┬───────────────────────────────────────┤
|
||
│ [+ 새 대화] │ │
|
||
│ [🔍 검색] │ 대화 메시지 영역 │
|
||
│ │ (마크다운 렌더링) │
|
||
│ ── 고정 ── │ │
|
||
│ 📌 서버설정 │ │
|
||
│ 📌 코드리뷰 │ │
|
||
│ │ │
|
||
│ ── 오늘 ── │ │
|
||
│ API 오류.. │ │
|
||
│ 배포 방법.. │ │
|
||
│ │ │
|
||
│ ── 어제 ── │ ┌────────────────────────────────┐ │
|
||
│ 회의록 정리 │ │ 메시지를 입력하세요... [▶] │ │
|
||
│ │ └────────────────────────────────┘ │
|
||
├──────────┴───────────────────────────────────────┤
|
||
│ Ollama ▾ │ llama3:8b ▾ │ ● 연결됨 │ 토큰: 1.2k │
|
||
└──────────────────────────────────────────────────┘
|
||
```
|
||
|
||
**좌측 패널 — 대화 목록**:
|
||
- **새 대화** 버튼 (Ctrl+N)
|
||
- **검색** — 대화 제목·내용 필터
|
||
- **고정 대화** — 핀 고정 항목이 최상단에 위치 (우클릭 > 고정/해제)
|
||
- **날짜별 그룹** — 오늘 / 어제 / 이번 주 / 이전 순서
|
||
- **대화 삭제** — 우클릭 > 삭제 (확인 다이얼로그)
|
||
|
||
**우측 패널 — 대화 영역**:
|
||
- 메시지 버블 (사용자: 우측 / AI: 좌측)
|
||
- **마크다운 렌더링** — 코드 블록, 목록, 볼드 등 기본 지원
|
||
- **코드 블록 복사** 버튼
|
||
- **스트리밍 응답** — SSE/스트림 지원 시 한 글자씩 표시
|
||
- **재생성** 버튼 — 마지막 응답을 다시 요청
|
||
- **복사** 버튼 — 개별 메시지 클립보드 복사
|
||
|
||
**창 기능**:
|
||
- 창 크기 자유 조절 (가로·세로)
|
||
- 전체 화면 / 최소화 / 최대화 지원
|
||
- 테마 연동 (DynamicResource 사용, 런처와 동일한 8종 테마)
|
||
- 독립 창 (런처와 별도로 열림, 항상 위 선택 가능)
|
||
|
||
### 대화 저장 — 로컬 전용
|
||
|
||
**핵심**: LLM API(Ollama, vLLM, Gemini)는 모두 **무상태(stateless)**. 서버 측에서 이전 대화를 기억하지 않음. 따라서 **모든 대화는 로컬에 저장**하고, API 호출 시 이전 대화 맥락을 함께 전송해야 함.
|
||
|
||
```
|
||
%APPDATA%/AxCommander/
|
||
conversations/
|
||
{uuid}.json ← 개별 대화 파일
|
||
conversation-index.json ← 제목·날짜·고정 여부 인덱스
|
||
```
|
||
|
||
**대화 파일 구조 (예시)**:
|
||
```json
|
||
{
|
||
"id": "a1b2c3d4-...",
|
||
"title": "서버 설정 방법",
|
||
"createdAt": "2026-03-27T10:00:00",
|
||
"updatedAt": "2026-03-27T10:05:00",
|
||
"pinned": true,
|
||
"provider": "ollama",
|
||
"model": "llama3:8b",
|
||
"messages": [
|
||
{ "role": "user", "content": "nginx 설정 방법 알려줘", "timestamp": "..." },
|
||
{ "role": "assistant", "content": "nginx 설정은...", "timestamp": "..." }
|
||
]
|
||
}
|
||
```
|
||
|
||
**보관 정책**:
|
||
- 기본 보관 기간: **30일** (설정에서 변경 가능: 7일 / 30일 / 90일 / 무제한)
|
||
- 고정(📌)된 대화는 보관 기간과 무관하게 **영구 보관**
|
||
- 만료된 대화는 앱 시작 시 자동 정리
|
||
|
||
**대화 관리 동작**:
|
||
- **보관함으로 이동**: 우클릭 > "보관함으로 이동" — 보관 기간이 지나도 자동 삭제되지 않음 (수동 삭제만 가능)
|
||
- **삭제**: 우클릭 > "삭제" — 확인 대화상자("이 대화를 정말 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.") 표시 후 진행
|
||
- **보관함 탭**: 좌측 패널 하단에 "보관함" 탭 별도 표시, 보관된 대화 목록 열람 가능
|
||
- 보관함 내 대화도 삭제 가능 (동일한 확인 절차)
|
||
|
||
**API 호출 시 컨텍스트 전송**:
|
||
- 전체 대화 이력을 `messages` 배열로 전송 (OpenAI 호환 형식)
|
||
- 토큰 한도 초과 시 오래된 메시지부터 자동 잘라냄 (sliding window)
|
||
- 시스템 프롬프트는 설정에서 커스터마이징 가능
|
||
|
||
### 지원 LLM 서비스 (4종)
|
||
|
||
설정 창에서 서비스별 모델 등록 후, 대화 창 입력 바에서 모델 선택 Popup으로 전환 가능.
|
||
|
||
| 서비스 | 연결 방식 | 설정값 |
|
||
|--------|----------|--------|
|
||
| **Ollama** | 로컬 HTTP (`http://localhost:11434`) | 엔드포인트 URL, 모델명 |
|
||
| **vLLM** | HTTP API (OpenAI 호환) | 엔드포인트 URL, 모델명, API 키 |
|
||
| **Gemini API** | Google REST API | API 키, 모델명 (gemini-2.0-flash 등) |
|
||
| **Claude API** | Anthropic REST API | API 키, 모델명 (claude-sonnet-4-20250514 등) |
|
||
|
||
### API 키 암호화 체계
|
||
|
||
**암호화 모드 전환**: `settings.json` → `llm.encryptionEnabled` 설정으로 제어
|
||
|
||
| 모드 | `encryptionEnabled` | 설명 | 용도 |
|
||
|------|---------------------|------|------|
|
||
| **비암호화 (기본)** | `false` | API 키·모델명을 평문으로 저장/표시 | 내부 개발 배포, 테스트 |
|
||
| **암호화** | `true` | AES-256-CBC(앱 공용 키)로 암호화 저장 | 운영 배포 |
|
||
|
||
**비암호화 모드** (현재 기본값):
|
||
- API 키, 모델명이 settings.json에 **평문**으로 저장됨
|
||
- 설정 창에서 입력한 값이 그대로 보이고 저장됨
|
||
- 내부 개발자 배포 시 빠른 설정에 적합
|
||
|
||
**암호화 모드** (`encryptionEnabled: true`로 전환 시):
|
||
- 앱 내장 고정 키 + AES-256-CBC로 암호화
|
||
- PBKDF2(SHA-256, 100,000회 반복)로 256-bit 키 파생
|
||
- 관리자 PC에서 암호화한 값이 모든 PC에서 동일하게 복호화됨
|
||
- AxKeyEncryptor 도구로 사전 암호화 가능
|
||
- 설정 창에서 이미 저장된 키는 "(저장됨)"으로 표시
|
||
|
||
**운영 배포 시 암호화 전환 방법**:
|
||
1. `settings.json`에서 `"encryptionEnabled": true` 설정
|
||
2. 기존 평문 키/모델명은 앱 재시작 시 설정 저장하면 자동으로 암호화됨
|
||
3. 또는 AxKeyEncryptor 도구로 미리 암호화한 값 배포
|
||
|
||
**하위 호환**: 암호화 모드에서 복호화 실패 시 평문으로 간주하여 동작 (마이그레이션 안전)
|
||
|
||
> **대화 내역 암호화**는 `encryptionEnabled`와 별개로 항상 **PC별 AES-256-GCM + DPAPI**로 암호화됩니다. 이는 대화 프라이버시 보호를 위한 별도 계층입니다.
|
||
|
||
### 설정 UI (SettingsWindow — 새 탭 "AI 대화")
|
||
|
||
| 설정 항목 | 타입 | 기본값 |
|
||
|-----------|------|--------|
|
||
| LLM 서비스 선택 | ComboBox (Ollama/vLLM/Gemini) | Ollama |
|
||
| 엔드포인트 URL | TextBox | `http://localhost:11434` |
|
||
| 모델명 | TextBox / ComboBox | `llama3:8b` |
|
||
| API 키 (암호화) | PasswordBox | (없음) |
|
||
| 시스템 프롬프트 | TextBox (여러 줄) | "당신은 유능한 AI 비서입니다." |
|
||
| 대화 보관 기간 | ComboBox | 30일 |
|
||
| 최대 컨텍스트 토큰 | Slider / TextBox | 4096 |
|
||
| 스트리밍 응답 | ToggleSwitch | ON |
|
||
| 연결 테스트 | Button | "연결 테스트" |
|
||
|
||
### 구현 파일 구조 (예상)
|
||
|
||
```
|
||
src/AxCommander/
|
||
Models/
|
||
ChatMessage.cs ← 메시지 모델 (role, content, timestamp)
|
||
Conversation.cs ← 대화 모델 (id, title, messages, pinned, ...)
|
||
LlmSettings.cs ← LLM 설정 모델
|
||
Services/
|
||
LlmService.cs ← LLM API 추상화 (Ollama/vLLM/Gemini 통합)
|
||
OllamaClient.cs ← Ollama HTTP 클라이언트
|
||
VllmClient.cs ← vLLM (OpenAI 호환) 클라이언트
|
||
GeminiClient.cs ← Gemini REST 클라이언트
|
||
ConversationStore.cs ← 대화 로컬 저장/로드/삭제/만료 처리
|
||
KeyEncryptionService.cs ← API 키 암호화/복호화
|
||
ViewModels/
|
||
ChatViewModel.cs ← 대화 창 ViewModel
|
||
Views/
|
||
ChatWindow.xaml / .cs ← 전용 대화 창 (2패널)
|
||
Handlers/
|
||
LlmChatHandler.cs ← ! 예약어 핸들러 (런처에서 ChatWindow 열기)
|
||
|
||
src/AxKeyEncryptor/ ← 별도 프로젝트 (암호화 도구)
|
||
Program.cs ← 콘솔 또는 간단한 WinForms GUI
|
||
```
|
||
|
||
### 단계별 구현 현황
|
||
|
||
| 단계 | 내용 | 상태 |
|
||
|------|------|------|
|
||
| **1단계** | Ollama 연결 + 기본 대화 창 (단일 대화) | ✅ 완료 |
|
||
| **2단계** | 대화 목록 + 저장/로드 + 고정/삭제/분류/이름변경 | ✅ 완료 |
|
||
| **3단계** | vLLM / Gemini / Claude 연결 추가 + 설정 탭 | ✅ 완료 |
|
||
| **4단계** | 스트리밍 응답 + 마크다운/코드 구문 강조 렌더링 | ✅ 완료 |
|
||
| **5단계** | 프롬프트 카드 + 사용자 프롬프트 템플릿 | ✅ 완료 |
|
||
| **6단계** | 토큰 사용량(k/m 단위) + 응답 소요시간 표시 | ✅ 완료 |
|
||
| **7단계** | 타이핑 효과 + 피드백(좋아요/싫어요) 영속성 | ✅ 완료 |
|
||
| **8단계** | 커스텀 Popup 메뉴 통일 (ContextMenu 제거) | ✅ 완료 |
|
||
| **9단계** | 지연 캡처 (Shift+Enter 3/5/10초 타이머) | ✅ 완료 |
|
||
| **향후** | 멀티 에이전트, 내보내기, Cowork 탭 | 계획 중 |
|
||
|
||
---
|
||
|
||
## 알려진 제한사항 및 향후 개선
|
||
|
||
| 항목 | 현황 | 개선 방향 |
|
||
|------|------|----------|
|
||
| 클립보드 히스토리 이미지 | 텍스트만 지원 | `IDataObject` 이미지 타입 추가 |
|
||
| 클립보드 병합 항목 시각 표시 | 힌트 바로만 개수 표시 | 리스트 항목에 체크마크 아이콘 추가 |
|
||
| 스니펫 글로벌 확장 | 런처에서만 동작 | `WH_KEYBOARD_LL` 백그라운드 확장 |
|
||
| 인덱스 경로 | Desktop + Start Menu | Program Files 등 추가 옵션 |
|
||
| 보안 제외 패턴 편집 | 읽기 전용 표시 | 설정 UI에서 패턴 추가/삭제 지원 |
|
||
|
||
### 향후 개선 — ONNX 임베딩 코드 검색 (사양 확보 시)
|
||
|
||
현재 코드 검색은 **TF-IDF + SQLite 영속 인덱스** 방식을 사용합니다 (v1.5.x).
|
||
사내 PC 사양이 확보되면 ONNX 로컬 임베딩으로 업그레이드하여 시맨틱 검색 품질을 크게 개선할 수 있습니다.
|
||
|
||
#### 현재 구현 (TF-IDF + SQLite)
|
||
- **방식**: 키워드 기반 TF-IDF 코사인 유사도 + 바이그램 + 스톱워드 제거
|
||
- **저장**: `%APPDATA%\AxCopilot\index\{folderHash}.db` (SQLite)
|
||
- **장점**: 외부 의존 없음, 배포 +3MB, 저사양 PC에서도 동작
|
||
- **한계**: 동의어/의미 유사성 미지원 ("사용자 인증" ↔ "로그인 검증" 매칭 불가)
|
||
|
||
#### ONNX 임베딩 업그레이드 계획
|
||
|
||
| 항목 | 내용 |
|
||
|------|------|
|
||
| **NuGet** | `Microsoft.ML.OnnxRuntime` 1.17+ (CPU 전용) |
|
||
| **모델** | `all-MiniLM-L6-v2` (90MB, 384차원) 또는 `bge-small-en` (130MB) |
|
||
| **벡터 DB** | 기존 SQLite에 BLOB 컬럼 추가 (384×float32 = 1.5KB/청크) |
|
||
| **배포 크기** | 현재 ~20MB → ~160MB (+140MB) |
|
||
| **최소 사양** | RAM 4GB 이상, CPU AVX2 지원 권장 |
|
||
|
||
#### 업그레이드 절차 (개발자 가이드)
|
||
|
||
1. **NuGet 추가**:
|
||
```bash
|
||
dotnet add src/AxCopilot/AxCopilot.csproj package Microsoft.ML.OnnxRuntime --version 1.17.0
|
||
```
|
||
|
||
2. **모델 배치**: `Assets/models/all-MiniLM-L6-v2.onnx` (빌드 시 복사)
|
||
|
||
3. **CodeIndexService 수정**:
|
||
```csharp
|
||
// 인덱싱 시 청크별 임베딩 벡터 생성
|
||
var embedding = _onnxSession.Run(new[] { tokenizedInput });
|
||
// SQLite chunks 테이블에 embedding BLOB 컬럼 추가
|
||
// 검색 시 코사인 유사도를 벡터 간 계산
|
||
```
|
||
|
||
4. **SQLite 스키마 확장**:
|
||
```sql
|
||
ALTER TABLE chunks ADD COLUMN embedding BLOB;
|
||
-- 검색 시: SELECT ... ORDER BY cosine_similarity(query_vec, embedding) DESC
|
||
```
|
||
|
||
5. **설정 추가**: `AppSettings.Llm.Code.UseEmbeddingSearch` (bool, default false)
|
||
- false: 기존 TF-IDF 사용 (저사양 호환)
|
||
- true: ONNX 임베딩 사용 (고품질)
|
||
|
||
6. **폴백**: ONNX 로드 실패 시 자동으로 TF-IDF 모드로 전환
|
||
|
||
> **참고**: 사내 PC 사양(CPU, RAM)이 낮아 ONNX 런타임 로드 시간(3~5초)과
|
||
> 인덱싱 시간이 길어질 수 있음. 반드시 사양 확인 후 도입 결정.
|
||
|
||
### 미지원 — 개발 계획 없음
|
||
|
||
아래 기능은 Alfred 비교에서 언급된 바 있으나 **AX Commander에 불필요한 기능으로 확정**되어 구현하지 않습니다. 향후 Alfred 비교 시에도 이 항목들은 비교 대상에서 제외합니다.
|
||
|
||
| 기능 | 이유 |
|
||
|------|------|
|
||
| 워크플로우 자동화 체인 | 사내 업무 흐름상 불필요. 배치 명령(`>`)으로 충분히 대체 가능 |
|
||
| 연락처 검색 | MAPI/vCard 연동 복잡도 대비 사용 빈도 낮음 |
|
||
| 사전 (Dictionary) | OS 내장 사전 및 브라우저 검색으로 충분히 대체 가능 |
|
||
| QR코드 생성 | 업무 활용도 낮음, 외부 의존성 없는 구현 비용 대비 효용 낮음 |
|
||
|
||
---
|
||
|
||
## 개발 환경
|
||
|
||
- **IDE**: Visual Studio 2022 / JetBrains Rider / VS Code (C# Dev Kit)
|
||
- **SDK**: .NET 8 SDK
|
||
- **타겟**: `net8.0-windows`, `win-x64`
|
||
- **UI 프레임워크**: WPF (`UseWPF=true`) + WinForms (`UseWindowsForms=true`, ColorDialog 사용)
|
||
- **테스트**: xUnit 2.9.0, FluentAssertions 6.12.0
|
||
|
||
---
|
||
|
||
## 경쟁 제품 기능 비교
|
||
|
||
AX Commander v1.0 기준으로 macOS Alfred 5, macOS Spotlight, Windows PowerToys Run과 비교합니다.
|
||
|
||
| 기능 | AX Commander | Alfred 5 | Spotlight | PowerToys Run |
|
||
|------|:---:|:---:|:---:|:---:|
|
||
| 앱/파일 퍼지 검색 | O | O | O | O |
|
||
| 한국어 초성 검색 | **O** | X | X | X |
|
||
| 실행 빈도 학습 | O | O | O | O |
|
||
| 계산기 + 수학 함수 | O | O | △ (기본) | O |
|
||
| 단위 변환 | O | O | O | O |
|
||
| 통화 변환 (실시간) | O | O | X | X |
|
||
| 웹 검색 (다중 엔진) | O | O | O | O |
|
||
| 클립보드 히스토리 | O | O (Powerpack) | X | X |
|
||
| 클립보드 파이프라인 체이닝 | **O** | X | X | X |
|
||
| 텍스트 일괄 처리 (batch) | **O** | X | X | X |
|
||
| 텍스트 스니펫 + 자동 확장 | O | O (Powerpack) | X | X |
|
||
| 파일 액션 서브메뉴 | O | O | X | X |
|
||
| JSON 포맷/검증 | O | X | X | X |
|
||
| 인코딩/해싱 (Base64, SHA) | O | X | X | X |
|
||
| 색상 변환 (HEX/RGB/HSL) | O | X | X | X |
|
||
| 스포이드 색상 추출 | **O** | X | X | X |
|
||
| 포트/프로세스 조회 | O | X | X | X |
|
||
| 환경변수 조회 | O | X | X | X |
|
||
| 화면 캡처 (4모드) | O | X | △ (스크린샷) | X |
|
||
| 글로벌 캡처 단축키 | O | X | O | X |
|
||
| 스크롤 캡처 (자동 스티칭) | **O** | X | X | X |
|
||
| 영역 캡처 키보드 미세조정 | **O** | X | X | X |
|
||
| 창 스냅 레이아웃 | O | X | X | O |
|
||
| 워크스페이스 저장/복원 | O | X | X | X |
|
||
| 윈도우 스위처 (검색+전환) | **O** | X | X | O |
|
||
| 시스템 명령 (잠금/절전/종료) | O | O | X | O |
|
||
| 미디어 제어 | O | O | O | X |
|
||
| 타이머/알람 | O | X | X | X |
|
||
| 프로세스 종료 (kill) | O | X | X | O |
|
||
| 서비스 관리 (svc) | **O** | X | X | X |
|
||
| 날짜 계산/D-day/타임스탬프 | **O** | X | X | X |
|
||
| 파일 비교 (diff) | **O** | X | X | X |
|
||
| 파일 일괄 이름변경 | **O** | X | X | O |
|
||
| 프로젝트 스캐폴딩 | **O** | X | X | X |
|
||
| 즐겨찾기 관리 | O | X | X | X |
|
||
| 업무 일지 자동 생성 | **O** | X | X | X |
|
||
| 루틴 자동화 | **O** | △ (워크플로우) | X | X |
|
||
| 시스템 리소스 모니터 | O | X | X | O |
|
||
| 이모지 피커 | O | X | X | O |
|
||
| 최근 파일 | O | O | O | X |
|
||
| 빠른 메모 | O | X | X | X |
|
||
| 앱 제거 | O | X | X | X |
|
||
| 잠금 해제 사용시간 알림 | **O** | X | X | X |
|
||
| 테마 (9종 + 커스텀 + 모양) | O | O | X | △ (제한) |
|
||
| 다국어 (5개 언어) | O | O | O | O |
|
||
| 플러그인 DLL 확장 | O | O | X | O |
|
||
| DPAPI 클립보드 암호화 | **O** | X | X | X |
|
||
| 단일 EXE 배포 | **O** | X | N/A | X |
|
||
| 완전 오프라인 (외부 통신 없음) | **O** | △ | O | O |
|
||
|
||
**O** = 지원, **△** = 부분 지원, **X** = 미지원, **굵은 O** = AX Commander 고유 기능
|
||
|
||
---
|
||
|
||
## 새로운 핸들러/키워드 추가 방법 (개발자 가이드)
|
||
|
||
### 1단계: IActionHandler 구현
|
||
|
||
```csharp
|
||
// Handlers/MyNewHandler.cs
|
||
using AxCommander.SDK;
|
||
using AxCommander.Themes;
|
||
|
||
namespace AxCommander.Handlers;
|
||
|
||
public class MyNewHandler : IActionHandler
|
||
{
|
||
// 이 핸들러를 트리거하는 프리픽스 (null이면 퍼지 검색에 통합)
|
||
public string? Prefix => "myprefix";
|
||
|
||
public PluginMetadata Metadata => new(
|
||
"MyNew",
|
||
"내 새로운 기능 — myprefix",
|
||
"1.0",
|
||
"AX");
|
||
|
||
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
|
||
{
|
||
// query: 프리픽스 이후의 입력 텍스트
|
||
// LauncherItem의 Data 필드에 실행 시 필요한 데이터를 담아 반환
|
||
return Task.FromResult<IEnumerable<LauncherItem>>(
|
||
[
|
||
new LauncherItem(
|
||
"제목",
|
||
"설명 · Enter로 실행",
|
||
null,
|
||
"실행 시 전달될 데이터",
|
||
Symbol: Symbols.Info)
|
||
]);
|
||
}
|
||
|
||
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
|
||
{
|
||
// item.Data에서 데이터를 꺼내 실행
|
||
if (item.Data is string data)
|
||
{
|
||
// 작업 수행
|
||
}
|
||
return Task.CompletedTask;
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2단계: 핸들러 등록 (App.xaml.cs)
|
||
|
||
```csharp
|
||
// App.xaml.cs OnStartup() 내부, HelpHandler 위에 추가
|
||
commandResolver.RegisterHandler(new MyNewHandler());
|
||
```
|
||
|
||
### 3단계: 심볼 추가 (Symbols.cs)
|
||
|
||
```csharp
|
||
// Themes/Symbols.cs
|
||
public const string MyNewIcon = "\uE946"; // Segoe MDL2 Assets 유니코드
|
||
```
|
||
|
||
참고: [Segoe MDL2 Assets 아이콘 목록](https://learn.microsoft.com/en-us/windows/apps/design/style/segoe-ui-symbol-font)
|
||
|
||
### 4단계: 도움말 항목 추가 (HelpHandler.cs)
|
||
|
||
`_entries` 배열에 항목 추가 (키보드 섹션 위에):
|
||
|
||
```csharp
|
||
new("카테고리", "myprefix", "기능 제목",
|
||
"기능 설명",
|
||
"사용 예시",
|
||
Symbols.MyNewIcon, "#HEX색상"),
|
||
```
|
||
|
||
### 5단계: 설정이 필요한 경우
|
||
|
||
1. `Models/AppSettings.cs`에 설정 클래스 추가
|
||
2. `ViewModels/SettingsViewModel.cs`에 프로퍼티 추가
|
||
3. `Views/SettingsWindow.xaml`에 탭 또는 섹션 추가
|
||
|
||
### 6단계: 외부 DLL 플러그인
|
||
|
||
외부 개발자는 `AxCommander.SDK` 프로젝트의 `IActionHandler`를 구현하는 DLL을 만들어 `settings.json`의 `plugins` 배열에 등록합니다:
|
||
|
||
```json
|
||
"plugins": [
|
||
{ "path": "C:\\Plugins\\MyPlugin.dll", "enabled": true }
|
||
]
|
||
```
|
||
|
||
런타임에 `PluginHost`가 Assembly.LoadFrom()으로 로드하고 `IActionHandler` 구현체를 자동 검색하여 등록합니다.
|
||
|
||
---
|
||
|
||
## 사내 LLM / AI Agent 연동 가이드 (향후 확장)
|
||
|
||
AX Commander는 사내 LLM 또는 AI Agent를 연동하여 **자연어 질의-응답** 기능을 추가할 수 있도록 설계되어 있습니다.
|
||
|
||
### 연동 시나리오
|
||
|
||
1. **사내 인트라넷 LLM API**: 별도 프리픽스(`ai` 또는 `?? `) 입력 → 사내 AI 서버에 질의 → 응답을 런처 결과로 표시
|
||
2. **키워드 없는 자동 감지**: 프리픽스가 없고 퍼지 검색 결과가 없을 때 → 자동으로 AI에 질의 폴백
|
||
3. **클립보드 AI 분석**: 클립보드 텍스트를 AI에 전달하여 요약/번역/교정 결과 반환
|
||
|
||
### 구현 방법
|
||
|
||
#### 방법 A: 전용 핸들러 (권장)
|
||
|
||
```csharp
|
||
// Handlers/AiQueryHandler.cs
|
||
public class AiQueryHandler : IActionHandler
|
||
{
|
||
public string? Prefix => "ai"; // 또는 "??" 등
|
||
|
||
private readonly HttpClient _client; // 사내 인트라넷 전용
|
||
|
||
public AiQueryHandler(string intranetEndpoint)
|
||
{
|
||
_client = new HttpClient { BaseAddress = new Uri(intranetEndpoint) };
|
||
_client.Timeout = TimeSpan.FromSeconds(10);
|
||
}
|
||
|
||
public async Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(query))
|
||
return [new LauncherItem("AI에게 질문하세요", "사내 LLM에 질의합니다", null, null)];
|
||
|
||
try
|
||
{
|
||
// 사내 인트라넷 API 호출 (DEVELOPMENT.md 개발 원칙에 의거,
|
||
// 사내 명시 허가된 엔드포인트만 호출 가능)
|
||
var response = await _client.PostAsJsonAsync("/api/chat",
|
||
new { prompt = query }, ct);
|
||
var result = await response.Content.ReadAsStringAsync(ct);
|
||
|
||
return [new LauncherItem(
|
||
"AI 응답",
|
||
result.Length > 200 ? result[..197] + "…" : result,
|
||
null, result,
|
||
Symbol: Symbols.Lightbulb)];
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return [new LauncherItem("AI 응답 실패", ex.Message, null, null, Symbol: Symbols.Error)];
|
||
}
|
||
}
|
||
|
||
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
|
||
{
|
||
if (item.Data is string text)
|
||
Application.Current?.Dispatcher.Invoke(() => Clipboard.SetText(text));
|
||
return Task.CompletedTask;
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 방법 B: CommandResolver 폴백 통합
|
||
|
||
`Core/CommandResolver.cs`의 `ResolveAsync` 메서드에서 퍼지 검색 결과가 0건일 때 AI 핸들러로 폴백:
|
||
|
||
```csharp
|
||
// Core/CommandResolver.cs
|
||
if (fuzzyResults.Count == 0 && _aiHandler != null)
|
||
{
|
||
return await _aiHandler.GetItemsAsync(input, ct);
|
||
}
|
||
```
|
||
|
||
#### 방법 C: JSON 스킬 플러그인 (기존 인프라 활용)
|
||
|
||
기존 `JsonSkillLoader`가 이미 HTTP API 호출을 지원하므로, `.skill.json` 파일로 LLM API를 등록:
|
||
|
||
```json
|
||
{
|
||
"prefix": "ai",
|
||
"name": "사내 AI 질의",
|
||
"type": "http",
|
||
"url": "https://intranet.company.com/api/llm",
|
||
"method": "POST",
|
||
"bodyTemplate": "{\"prompt\": \"{{query}}\"}",
|
||
"responsePath": "data.answer"
|
||
}
|
||
```
|
||
|
||
### 보안 고려사항
|
||
|
||
| 항목 | 원칙 |
|
||
|------|------|
|
||
| 엔드포인트 | **사내 인트라넷 URL만 허용** — settings.json에 명시적 등록 필요 |
|
||
| 타임아웃 | 최대 10초 (런처 UX 유지) |
|
||
| 데이터 | 클립보드 내용을 AI에 전달할 때 보안 패턴 검사 선행 (기존 `excludePatterns` 활용) |
|
||
| 인증 | Windows 인증(SSPI) 또는 사내 토큰 — `CredentialManager` (advapi32.dll, DPAPI) 사용 |
|
||
| 로깅 | AI 질의 내용은 로그에 기록하지 않음 (민감 데이터 포함 가능) |
|
||
|
||
### 설정 UI 확장
|
||
|
||
설정 창에 **AI 탭**을 추가하여 다음을 관리:
|
||
|
||
| 설정 항목 | 설명 |
|
||
|----------|------|
|
||
| AI 연동 활성화 | 기능 전체 토글 |
|
||
| 사내 API 엔드포인트 | 인트라넷 URL 입력 |
|
||
| 프리픽스 | `ai`, `??`, 또는 빈 값 (자동 폴백) |
|
||
| 타임아웃 (초) | 1~30초 |
|
||
| 자동 폴백 | 검색 결과 0건 시 자동으로 AI 질의 |
|
||
|
||
### 로드맵
|
||
|
||
| 단계 | 내용 |
|
||
|------|------|
|
||
| Phase 1 | `ai` 프리픽스 핸들러 + 사내 REST API 연동 (텍스트 질의/응답) |
|
||
| Phase 2 | 자동 폴백 (퍼지 검색 결과 없을 때) |
|
||
| Phase 3 | 클립보드 AI 분석 (`ai summarize`, `ai translate`, `ai proofread`) |
|
||
| Phase 4 | Agent 모드 — 멀티턴 대화 + 도구 호출 (파일 읽기, 계산 등을 AI가 결정) |
|
||
|
||
---
|
||
|
||
## 슬래시 명령어 (/ Commands)
|
||
|
||
AX Agent 대화 입력창에서 `/`를 입력하면 자동완성 팝업이 표시됩니다. 현재 탭에 맞는 명령어만 필터링됩니다.
|
||
|
||
### 공통 명령어 (모든 탭)
|
||
|
||
| 명령어 | 기능 | 설명 |
|
||
|--------|------|------|
|
||
| `/summary` | Summary | 텍스트/문서를 핵심 포인트 중심으로 요약 |
|
||
| `/translate` | Translate | 텍스트를 영어로 번역 (원문 톤 유지) |
|
||
| `/explain` | Explain | 내용을 쉽고 자세하게 설명 (예시 포함) |
|
||
| `/fix` | Fix | 맞춤법, 문법, 자연스러운 표현 교정 |
|
||
| `/help` | Help | 슬래시 명령어 도움말 창 표시 |
|
||
|
||
### 개발 명령어 (Cowork/Code 탭 전용)
|
||
|
||
| 명령어 | 기능 | 사용 도구 |
|
||
|--------|------|-----------|
|
||
| `/review` | Code Review | `code_review` (diff_review) |
|
||
| `/pr` | PR Summary | `code_review` (pr_summary) |
|
||
| `/test` | Test | `test_loop` |
|
||
| `/structure` | Structure | `folder_map` |
|
||
| `/build` | Build | `build_run` |
|
||
| `/search` | Search | `search_codebase` |
|
||
|
||
### 스킬 명령어
|
||
|
||
`%APPDATA%\AxCopilot\skills\` 폴더에 `*.skill.md` 파일을 추가하면 슬래시 명령어로 자동 등록됩니다.
|
||
|
||
**스킬 파일 형식** (2종류 지원):
|
||
|
||
1) **기존 형식** (`*.skill.md` 단일 파일):
|
||
```markdown
|
||
---
|
||
name: skill-name
|
||
label: 표시 이름
|
||
description: 설명
|
||
icon: \uE768
|
||
---
|
||
시스템 프롬프트 내용...
|
||
```
|
||
|
||
2) **SKILL.md 표준** (agentskills.io 호환, Claude Code/Cursor/Windsurf 공통):
|
||
```
|
||
skill-name/
|
||
├── SKILL.md
|
||
├── scripts/ (선택)
|
||
└── references/ (선택)
|
||
```
|
||
```markdown
|
||
---
|
||
name: skill-name
|
||
description: 설명. 사용 시점 키워드 포함 권장.
|
||
license: Apache-2.0
|
||
compatibility: Requires Python 3.14+
|
||
metadata:
|
||
label: 표시 이름
|
||
icon: \uE768
|
||
author: team-name
|
||
version: "1.0"
|
||
allowed-tools: process file_read grep_tool
|
||
---
|
||
지시사항 마크다운...
|
||
```
|
||
|
||
**기본 제공 스킬** (자동 생성):
|
||
- `/daily-standup` — 데일리 스탠드업 보고서
|
||
- `/bug-hunt` — 잠재적 버그 패턴 검색
|
||
- `/code-explain` — 코드 상세 설명
|
||
|
||
### 에이전트 도구 목록 (v1.5.0)
|
||
|
||
| 도구명 | 기능 | 탭 |
|
||
|--------|------|----|
|
||
| `file_read` | 파일 읽기 | Cowork/Code |
|
||
| `file_write` | 파일 쓰기 | Cowork/Code |
|
||
| `file_edit` | 파일 편집 (줄 기반) | Cowork/Code |
|
||
| `glob` | 파일 패턴 검색 | Cowork/Code |
|
||
| `grep_tool` | 텍스트 검색 | Cowork/Code |
|
||
| `process` | 프로세스 실행 | Cowork/Code |
|
||
| `folder_map` | 폴더 구조 조회 | Cowork/Code |
|
||
| `document_read` | 문서 읽기 (PDF/DOCX) | Cowork/Code |
|
||
| `search_codebase` | 코드 시맨틱 검색 (TF-IDF) | Cowork/Code |
|
||
| `code_review` | AI 코드 리뷰 | Cowork/Code |
|
||
| `project_rules` | AX.md 개발 지침 관리 | Cowork/Code |
|
||
| `git_tool` | Git 작업 | Code |
|
||
| `build_run` | 빌드/테스트 실행 | Code |
|
||
| `dev_env_detect` | 개발 환경 감지 | Code |
|
||
| `lsp` | LSP 코드 인텔리전스 | Code |
|
||
| `test_loop` | 테스트 자동 루프 | Code |
|
||
| `spawn_agent` | 서브에이전트 생성 | Code |
|
||
| `wait_agents` | 서브에이전트 결과 대기 | Code |
|
||
| `skill_manager` | 스킬 관리 (list/info/reload) | Cowork/Code |
|
||
| `memory` | 에이전트 메모리 관리 | Cowork/Code |
|
||
| `excel_create` | Excel 생성 | Cowork/Code |
|
||
| `docx_create` | Word 생성 | Cowork/Code |
|
||
| `csv_create` | CSV 생성 | Cowork/Code |
|
||
| `markdown_create` | 마크다운 생성 | Cowork/Code |
|
||
| `html_create` | HTML 생성 | Cowork/Code |
|
||
| `chart_create` | 차트 생성 | Cowork/Code |
|
||
| `batch_create` | 배치 스크립트 생성 | Cowork/Code |
|
||
| `document_review` | 문서 품질 검증 | Cowork/Code |
|
||
| `format_convert` | 포맷 변환 | Cowork/Code |
|
||
|
||
---
|
||
|
||
## 버전 이력
|
||
|
||
> **⚠ 버전 변경 시 반드시 아래 모든 항목을 동시에 수정하세요. 하나라도 빠지면 버전 불일치가 발생합니다.**
|
||
>
|
||
> | # | 수정 대상 | 파일 경로 | 수정 내용 |
|
||
> |---|----------|----------|----------|
|
||
> | 1 | **프로젝트 버전** | `src/AxCopilot/AxCopilot.csproj` → `<Version>` | 버전 번호 변경 (설정 창·Windows 속성에 자동 반영) |
|
||
> | 2 | **인스톨러 프로젝트 버전** | `src/AxCopilot.Installer/AxCopilot.Installer.csproj` → `<Version>` | 인스톨러 어셈블리 버전 일치 |
|
||
> | 3 | **인스톨러 표시 버전** | `src/AxCopilot.Installer/SetupForm.cs` → `AppVer` 상수 | 설치 UI 헤더·레지스트리에 표시되는 버전 문자열 |
|
||
> | 4 | **개발 문서 버전 이력** | `docs/DEVELOPMENT.md` → 버전 이력 섹션 | 새 버전 항목 추가 (이 파일) |
|
||
> | 5 | **사용자 가이드 문서** | `src/AxCopilot/Assets/AX Copilot 사용가이드.htm` | 헤더 `version-tag` + 버전 이력 섹션에 새 항목 추가 |
|
||
> | 6 | **헬프 창 내용** | `src/AxCopilot/Views/HelpDetailWindow.xaml.cs` | `_overviewItems`의 신기능 항목·프리뷰 항목 갱신 |
|
||
> | 7 | **MCP 클라이언트 버전** | `src/AxCopilot/Services/McpClientService.cs` → `clientInfo.version` | MCP 프로토콜 클라이언트 버전 문자열 |
|
||
> | 8 | **로드맵 문서** | `docs/AGENT_ROADMAP.md`, `docs/AGENT_ROADMAP.html`, `docs/LAUNCHER_ROADMAP.md`, `docs/LAUNCHER_ROADMAP.html` | 푸터/헤더 버전 번호 갱신 |
|
||
>
|
||
> **인스톨러 주의**: `SetupForm.cs`의 `AppVer` 상수는 설치 UI 헤더 표시 + `RegAdd()`에서
|
||
> 레지스트리 `DisplayVersion`에 기록됩니다. 이 값이 앱 본체와 다르면 업그레이드 감지가 오작동합니다.
|
||
> **반드시 앱 본체 csproj `<Version>`과 동일하게 유지하세요.**
|
||
>
|
||
> 설정 창(`SettingsWindow.xaml.cs → SetVersionText()`)과 정보 창(`AboutWindow.xaml.cs`)은
|
||
> 앱 본체 csproj `<Version>`을 리플렉션으로 읽으므로 별도 수정 불필요합니다.
|
||
|
||
> **⚠ 사용자 노출 문서 작성 원칙 (사용자 가이드 · 헬프 창)**
|
||
>
|
||
> 사용자 가이드(`AX Copilot 사용가이드.htm`)와 헬프 창(`HelpDetailWindow.xaml.cs`)은
|
||
> **사용자가 직접 보는 문서**입니다. 외부에 내부 기술 스택이 노출되지 않도록 아래 원칙을 반드시 준수하세요.
|
||
>
|
||
> | 구분 | 사용 금지 (내부 기술) | 대신 사용 (사용자 관점) |
|
||
> |------|---------------------|----------------------|
|
||
> | 프로토콜/라이브러리 | MCP, JSON-RPC, stdio, P/Invoke, DPAPI, LCS, REST API | "외부 도구 연결", "암호화 저장" |
|
||
> | 클래스/서비스명 | McpClientService, TokenEstimator, AuditLogService, DiffService | 기능 설명으로 대체 |
|
||
> | 내부 구조 | ParentId/BranchLabel, FallbackModels, SettingsViewModel | "대화 분기", "자동 전환", "설정" |
|
||
> | 코드 패턴 | CJK 가중치, 동적 반복 한도, SWE-bench, 다단계 반성 | "더 정확한 분석", "AI 성능 개선" |
|
||
> | 파일명/경로 | english.json, movies.json, SetupForm.cs, endpoint/apiKey | 언급하지 않음 |
|
||
>
|
||
> **원칙**: 사용자에게는 "무엇을 할 수 있는지"만 전달합니다.
|
||
> "어떻게 구현했는지"는 이 개발 문서(`DEVELOPMENT.md`)에만 기록합니다.
|
||
>
|
||
> **적용 대상**: 버전 이력, 신기능 설명, 개요 항목, 모든 사용자 노출 텍스트
|
||
|
||
### v1.8.0
|
||
|
||
> **개발 범위**: 에이전트 인프라 전면 고도화 — Phase 17-UI, 17-A~G, 18-A~C, L3 완료. 사내/사외 네트워크 모드 추가.
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **에이전트 채팅 화면 개편 (Phase 17-UI)** | 채팅 창 서브 바에 Plan 모드 3상태 토글 (Off / Auto / Always) 추가. 클릭 시 순환 전환, 활성 상태 색상 강조. `LlmSettings.PlanMode` 설정 연동 |
|
||
| **Reflexion 강화 (Phase 17-A)** | `ReflexionService` 확장: 자기 평가 → 전략 수정 루프 구현. 도구 실행 실패 시 반성 기반 재시도 전략 자동 선택 |
|
||
| **구조화된 이벤트 로그 (Phase 17-B)** | `AgentEventLog` JSONL 기록 시스템. `AgentLoopService`에 세션 ID 생성 + SessionStart / ToolRequest / ToolResult / SessionEnd 이벤트 기록 통합 |
|
||
| **훅 시스템 고도화 (Phase 17-C)** | `ExtendedHookRunner`: PreCompact / UserPromptSubmit / AgentThinking 훅 이벤트 추가. `asyncRewake` 속성으로 비동기 훅 완료 후 에이전트 재개 가능 |
|
||
| **스킬 시스템 고도화 (Phase 17-D)** | `PathBasedSkillActivator`: 경로 패턴 기반 스킬 자동 활성화. `SkillExtensionStore` 사이드카 패턴으로 스킬 확장 메타데이터 관리 |
|
||
| **메모리/컨텍스트 고도화 (Phase 17-E)** | `ContextCondenser` 경로 규칙 연동. `PathScopedRuleInjector`로 작업 폴더에 따른 규칙 자동 주입. `@include` 지시문 처리 |
|
||
| **권한 시스템 고도화 (Phase 17-F)** | `PermissionSystem` Chain of Responsibility 패턴. Allow/Deny 규칙 설정 UI 연동. acceptEdits 모드에서 파일 편집 도구 자동 승인 |
|
||
| **멀티파일 Diff + 자동 컨텍스트 (Phase 17-G)** | `MultiFileDiffViewModel`: 파일별 diff 추적 + 일괄 수락. `AutoContextCollector`: `@파일명` 멘션 정규식 파싱 + 자동 파일 내용 주입. `ToolRiskMapper`: 도구별 Low/Medium/High 위험도 분류 |
|
||
| **멀티에이전트 팀 (Phase 18-A)** | `DelegateAgentTool` + `BackgroundAgentService` + `WorktreeManager`. `AgentLoopService`에 `RunSubAgentAsync` 위임 연결. ToolRegistry에 자동 등록 |
|
||
| **에이전트 리플레이 (Phase 18-B)** | `AgentReplayService`: JSONL 이벤트 로그 파일 열거 + 단계별 재생. `ReplayTimelineViewModel`: 재생 UI 바인딩 ViewModel |
|
||
| **플러그인 설치 서비스 (Phase 18-C)** | `PluginInstallService`: 로컬 zip 파일 기반 설치 (URL 다운로드 없음). `PluginManifest` / `InstalledPlugin` / `PluginInstallResult` 레코드. 레지스트리 JSONL 영속화 |
|
||
| **사내/사외 네트워크 모드** | `AppSettings.InternalModeEnabled` (기본: 사내 모드). 사외 전환 시 비밀번호 `axgo123!` 인증 필요. `WebSearchHandler` + `HttpTool` 에서 모드 체크 적용 |
|
||
| **알림 센터 (L3-7)** | `NotificationCenterService`: 알림 타입(Info/Success/Warning/Error) + 히스토리 큐(최대 50건). `NotificationRaised` 이벤트로 UI 구독 지원. 기존 `NotificationService` 트레이 BalloonTip 위임 |
|
||
| **플러그인 갤러리 ViewModel (L3-1)** | `PluginGalleryViewModel`: 설치된 플러그인 목록 + 설치/제거/활성화 커맨드 바인딩. `PluginItemViewModel` 래퍼 |
|
||
| **파라미터 퀵링크 (L3-4)** | `QuickLinkHandler` (`ql` 프리픽스) + `UrlTemplateEngine`. `{0}`, `{query}` 플레이스홀더 치환. 설정에서 `QuickLinkEntry` 목록 관리 |
|
||
| **AI 스니펫 (L3-3)** | `AiSnippetHandler` (`ai` 프리픽스) + `SnippetTemplateService`. 업무 이메일/요약/번역/코드리뷰/커밋 기본 템플릿 5종 내장. LLM 호출 후 클립보드 복사. AI 비활성화 시 항목 미표시 |
|
||
| **웹 검색 AI 요약 (L3-2)** | `WebSearchSummaryHandler` (`?!` 프리픽스) + `ContentExtractor`. URL 또는 검색어 입력 시 AI가 요약 생성 후 클립보드 복사. 사외 모드 + AI 활성화 상태에서만 동작 |
|
||
|
||
### v1.7.2
|
||
|
||
> **개발 범위**: 안정화 릴리즈 — 런처 속도, 에이전트 컨텍스트 압축, 대화 복원, 버그 수정 11건
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **컨텍스트 압축 (Context Condenser)** | 2단계 자동 압축 구현. 1단계: 오래된 도구 결과를 LLM 호출 없이 1500자로 축약. 2단계: 이전 대화를 LLM으로 요약하여 교체. 모델별 토큰 한도 자동 인식 (Claude 180K, Gemini 900K, GPT-4 120K, Ollama 16K). 65% 임계값에서 압축 시작 |
|
||
| **대화 이력 복원** | 앱 재시작 시 탭별 마지막 대화를 자동 복원. `LastConversationIds` 설정에 탭↔대화 ID 매핑 저장. 종료·탭 전환 시 자동 영속화 |
|
||
| **런처 속도 개선** | 핫키 응답 ~230ms 절감. `Thread.Sleep` 단축 (200→110ms), 애니메이션 최적화 (fade 160→100ms, slide 200→120ms). 텍스트 미사용 시 즉시 런처 표시 |
|
||
| **검증 리팩터링** | 도구 실행 후 검증을 읽기 전용(`file_read`, `directory_list`)으로 제한. 검증 결과를 보고만 하고 직접 수정하지 않도록 변경 — 문서 품질 저하 방지 |
|
||
| **설정 비밀번호 수정** | 개발자 모드·스텝바이스텝 토글이 설정 창 열 때마다 비밀번호 재입력을 요구하던 문제 수정. `IsLoaded` 가드 추가 |
|
||
| **계획 버튼 동기화** | PlanViewerWindow에서 승인 후 대화창 인라인 승인/취소 버튼이 자동 축소되지 않던 문제 수정. `TCS.ContinueWith` 콜백 추가 |
|
||
| **야간 시간 수정** | PC 미종료 상태에서 자정 넘길 때 근무 시간이 전날부터 누적되던 문제 수정. `_sessionStart`를 자정(DateTime.Today)으로 리셋 |
|
||
| **클립보드 붙여넣기 수정** | 이전 활성 창에 `SetForegroundWindow` 호출 후 `Ctrl+V` 전송하도록 변경 — 런처가 포커스를 뺏는 문제 해결 |
|
||
| **활성 창 캡처 수정** | 런처가 완전히 숨겨질 때까지 대기 + 대상 창에 `SetForegroundWindow` 호출 — 런처 자체가 캡처되던 문제 해결 |
|
||
| **스크롤 캡처 수정** | `FindOverlap` 다중 행 비교로 오버랩 감지 정확도 향상. `StitchFrames`를 증분 스티칭으로 변경 — 전체 프레임 중복 붙여넣기 문제 해결 |
|
||
| **런처 잔여 결과 제거** | `OnShown()`에서 `Results.Clear()` 호출 추가 — 런처 재표시 시 이전 검색 결과가 순간적으로 보이던 문제 해결 |
|
||
| **AI 모델 호환성 가이드** | 개발자 가이드에 도구 사용(Function Calling) 지원 모델 표 추가. 클라우드(Claude/Gemini) + Ollama 로컬 모델 15종 호환성 명시. 사내 환경 추천 조합 포함 |
|
||
|
||
### v1.7.1
|
||
|
||
> **개발 범위**: 에이전트 루프 검증 강제 + UI 개선 + 도구 스키마 수정
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **도구 실행 후 검증 강제 (Post-Tool Verification)** | 문서 생성 도구(`file_write`, `docx_create`, `html_create`, `excel_create` 등) 실행 후 LLM에 검증 전용 호출을 자동 삽입. 생성된 파일을 `file_read`로 읽고 내용 완전성·구조·맞춤법을 확인하도록 강제. 문제 발견 시 즉시 수정 도구 호출. OpenHands 등 오픈소스에는 없는 차별화 기능. `EnablePostToolVerification` 설정 토글 (기본 OFF) |
|
||
| **Gemini 배열 스키마 수정** | `MultiReadTool.paths`와 `UserAskTool.options`에 `Items` 필드 추가. Gemini API가 array 타입 파라미터에 items 필드를 필수로 요구하는 문제 해결 |
|
||
| **워크플로우 분석기 UI 개선** | 타이틀바 전체 영역 드래그 가능 (`Background="Transparent"` 추가), 활성 탭 텍스트 White 강조, 상태 텍스트 `TextTrimming` + `MaxWidth` 적용 |
|
||
| **플랜 뷰어 버튼 가시성** | 아웃라인 버튼 배경 `0x18` 틴트 + 테두리 `0x80` 불투명도 + `1.2px` 두께로 가시성 개선 |
|
||
| **워터마크 슬래시 칩 충돌 수정** | 슬래시 칩 활성 시 `InputWatermark` 즉시 숨김 처리 |
|
||
| **피드백 학습 컨텍스트** | `BuildFeedbackContext()`를 Cowork/Code 시스템 프롬프트에 주입. 최근 20건 대화의 좋아요/싫어요 패턴 분석 |
|
||
| **수정 후 재시도 버튼** | 두 번째 액션바에 재시도 버튼 추가 (사용자 피드백 입력 후 재생성) |
|
||
| **설정 추가** | `EnablePostToolVerification`(bool, 기본 false) — 문서 생성 후 검증 LLM 호출 강제 |
|
||
|
||
### v1.7.0
|
||
|
||
> **개발 범위**: Phase 16 — 에이전트 지능 강화 + 개발자 경험
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **플랜 모드 (Plan Mode)** | 에이전트 도구 실행 전 구조화된 계획 생성→사용자 검토/승인→실행 흐름. `PlanMode` 3모드(off/always/auto). always=LLM 텍스트 전용 계획 생성(최대 3회 수정 요청), auto=계획 감지 시 승인 요청 |
|
||
| **도구/커넥터 관리 UI** | 설정 › AX Agent › 도구 탭 신설. 52개 에이전트 도구를 6개 카테고리(파일/검색, 문서 생성, 문서 품질, 코드/개발, 데이터/유틸, 시스템)별 카드 표시. 개별 활성/비활성 토글 + MCP 서버 연결 상태 실시간 표시. `DisabledTools` 설정으로 영속 |
|
||
| **프로젝트 규칙 시스템** | `.ax/rules/*.md` YAML 프론트매터(name, description, applies-to, when) 파싱. glob 패턴 매칭, when 조건 필터링. 시스템 프롬프트에 "프로젝트 규칙" 섹션 자동 주입. ProjectRuleTool에 list_rules/read_rule 액션 추가. `EnableProjectRules` 토글 |
|
||
| **반복 테스트-수정 루프** | TestLoopTool `auto_fix` 액션 — 테스트 실행→구조화된 실패 파싱(.NET Failed/pytest FAILED, 파일 경로·라인 번호 추출)→`[AUTO_FIX:]` 마커 출력. AgentLoopService에서 test_loop+AUTO_FIX 감지 시 반복 예산 자동 확장. `MaxTestFixIterations` 설정 |
|
||
| **병렬 도구 실행** | 읽기 전용 도구(file_read, grep_tool, glob 등 12종 ReadOnlyTools 셋) 자동 분류 → `Task.WhenAll()` 병렬 실행, 쓰기 도구는 순차 유지. ParallelState 클래스로 async ref 제약 해결. `EnableParallelTools` 토글 |
|
||
| **SKILL.md 표준 호환** | 외부↔내부 도구 이름 매핑 테이블 20개(Bash→process, Read→file_read, Grep→grep_tool, execute_command→process 등). ParseSkillFile에서 스킬 본문 로드 시 자동 치환 |
|
||
| **사내 보안 예외** | AntiTamper 보안 감지에 사내 IP 대역(11.99/11.90/12.25/12.23/12.24) 예외 처리. IsTrustedNetwork()로 IPv4 프리픽스 매칭 |
|
||
| **설정 추가** | `PlanMode`(off/always/auto), `EnableProjectRules`(bool), `MaxTestFixIterations`(int), `EnableParallelTools`(bool), `DisabledTools`(List\<string\>) |
|
||
|
||
### v1.6.1
|
||
|
||
> **개발 범위**: 설정 UI 개선 + 헬프 IP 보호 + 모델 선택 버그 수정 + 차세대 고도화 계획 수립
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **고품질 문서 생성 설정** | 설정 › 에이전트 › 코워크에 "고품질 문서 생성" ToggleSwitch 추가. 멀티패스 문서 엔진 기본값 OFF (무료 API 환경 호환성). 비활성 시 `document_plan`/`document_assemble` 도구 차단 |
|
||
| **헬프 화면 IP 보호** | 버전별 신기능 항목 삭제, 영역별 핵심 기능 중심 재구성. 내부 기술 용어(SSE, AES-256-GCM, DPAPI, OpenXML 등) 노출 제거. CLAUDE.md에 헬프 IP 보호 규칙 추가 |
|
||
| **모델 선택 팝업 버그 수정** | 서비스만 변경 후 모델 미선택 시 팝업 닫으면 이전 서비스/모델로 롤백. 모델 확정(`Save`) 시에만 변경 반영 |
|
||
| **ESC 키 닫기 확장** | AboutWindow(개발 정보) ESC 키 닫기 추가 |
|
||
| **가이드 버전 표기 제거** | 사용자/개발자 가이드 헤더 version-tag 및 푸터 버전 번호 제거. CLAUDE.md에 가이드 버전 미표기 규칙 추가 |
|
||
| **차세대 고도화 계획 수립** | Phase 16(v1.7.0)~18(v2.0) 계획: 플랜 모드, 도구 관리 UI, 프로젝트 규칙, 자기 성찰, 멀티파일 Diff, 에이전트 팀 등 18개 기능 |
|
||
|
||
### v1.6.0
|
||
|
||
> **개발 범위**: Phase 15 — 멀티패스 문서 엔진 + 내장 스킬 29종 확장 + 에이전트 도구 42개 + PPT 네이티브 생성
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **멀티패스 문서 생성 엔진** | `document_plan` (개요 구조화) + `document_assemble` (섹션별 조립) 도구 신규 추가. 3페이지 이상 문서 작성 시 개요→섹션별 상세→조립 방식으로 품질 대폭 향상. 코워크 보고서/문서 프리셋에 멀티패스 지시문 자동 포함 |
|
||
| **PPT 네이티브 생성** | `pptx_create` 도구 — OpenXML SDK 기반 C# 네이티브 구현. Python/Node 없이 슬라이드 생성 (title/content/two_column/table/blank 레이아웃, 4종 테마) |
|
||
| **데이터 분석 도구** | `data_pivot` — CSV/JSON 그룹화·피벗·집계 (sum/avg/count/min/max), 필터·정렬·Top N 지원. LINQ 기반 순수 C# 구현 |
|
||
| **템플릿 렌더링** | `template_render` — Mustache 스타일 변수 치환 + 반복({{#list}}) + 조건부({{^cond}}) 렌더링. 정기 보고서 템플릿 자동화 |
|
||
| **이미지 분석** | `image_analyze` — LLM 멀티모달 활용 이미지 설명/텍스트 추출/차트 데이터 해석/비교 분석 |
|
||
| **파일 변경 감지** | `file_watch` — 폴더 내 최근 변경·생성 파일 탐지 (상대 시간 지원: 1h/24h/7d), 유형별 통계 |
|
||
| **텍스트 요약** | `text_summarize` — 긴 텍스트/문서 청크 분할 → 핵심 문장 추출 요약 (bullet/paragraph/executive/technical 스타일) |
|
||
| **내장 스킬 16종 추가** | email-draft, translate, compare, weekly-report, log-analyze, sql-report, data-convert, refactor, gen-test, impact + 외부 검증 스킬 6종: security-audit (보안 코드 감사/OWASP), prd-generator (요구사항 정의서/유저스토리), adr-writer (아키텍처 결정 기록), changelog (변경이력/릴리즈노트), dependency-audit (의존성 분석/라이선스), perf-audit (성능 감사/안티패턴) — **총 29종** |
|
||
| **설정 추가** | `EnableMultiPassDocument` (멀티패스 문서 ON/OFF), `MultiPassThresholdPages` (자동 멀티패스 기준 페이지 수, 기본 3) |
|
||
| **가이드 뷰어 버튼 수정** | 닫기/최소화/최대화 버튼 MouseLeftButtonDown + Handled로 DragMove 충돌 해결 |
|
||
| **ESC 키 닫기** | GuideViewerWindow, HelpDetailWindow에서 Escape 키로 창 닫기 지원 |
|
||
|
||
### v1.5.4
|
||
|
||
> **개발 범위**: Phase 12-3 완료 + 대화 UX 안정화 + 슬래시 팝업 고도화 + 설정 개선
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **Phase 12-3 완료** | 실행이력상세도를 개발자 탭으로 이동. Phase 12-3 (런타임 스킬 + 워크플로우 분석기 + 설정 개선) 전체 완료 |
|
||
| **글로우 효과 지속** | 레인보우 글로우가 스트리밍 종료 시까지 지속 (기존 3초 자동 꺼짐 → StopRainbowGlow 페이드아웃). Chat/Cowork/Code 전체 적용 |
|
||
| **스트리밍 경과 시간 표시** | 헤더 우측에 실시간 경과 시간 표시 (0s, 5s, 12s...). 완료 후 하단에 최종 시간 + 토큰 사용량 한 줄 TextBlock 표시 (줄바꿈 방지) |
|
||
| **슬래시 팝업 UX 개선** | ↑/↓ 방향키 아이템 단위 이동 + 선택 하이라이트, Enter로 실행, 마우스 휠 스크롤 지원, 기본 표시 7개 (최대 20), `/help` 직접 입력 시 도움말 창 표시, 슬라이더에 현재 값 실시간 표시 |
|
||
| **도움말 창 닫기 수정** | DragMove 충돌 해결 — MouseLeftButtonDown + Handled로 닫기 이벤트 우선 처리. 드래그는 헤더 영역에서만 동작 |
|
||
| **설정 접기/열기 수정** | 도구 카테고리·스킬 그룹 접기/열기를 MouseLeftButtonDown으로 변경 (ScrollViewer 내 MouseUp 소실 WPF 이슈 해결) |
|
||
| **설정 닫기 다이얼로그 제거** | 저장하지 않고 닫을 때 확인 팝업 + 하단 토스트 배너 제거, 바로 닫힘 (변경사항 자동 revert) |
|
||
| **설정 스킬 로딩 지연 해결** | 스킬 미로드 시 백그라운드 Task로 RuntimeDetector 포함 비동기 로드 후 UI 구성 |
|
||
| **탭 전환 시 대화 유지** | StopStreamingIfActive() — 탭 전환 시 스트리밍 즉시 중단 + 대화 즉시 저장. originTab 캡처로 올바른 탭에 ID 매핑. SendRegenerateAsync 이력 갱신 추가 |
|
||
| **섹션 간 간격 개선** | 차단 확장자 → 도구/커넥터 간 16px 마진, 도움말 창 스킬 항목 간격 확대, 명령어 열 너비 120px |
|
||
|
||
### v1.5.3
|
||
|
||
> **개발 범위**: Phase L2 클립보드 고도화 + Phase 14 에이전트 도구/스킬 확장 + 설정 UI 개선 + 가이드 시스템
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| 클립보드 이미지 원본 보존 | 원본 PNG를 `clipboard_images/` 캐시 폴더에 저장, 썸네일(80px)은 표시용으로만 사용. Enter 복원 시 원본 해상도로 클립보드 복사. 캐시 정리 정책 (30일/500MB) |
|
||
| Shift+Enter 자동 복사 | 히스토리 미리보기(Shift+Enter) 시 시스템 클립보드에 자동 복사 (텍스트/이미지 원본 해상도) |
|
||
| 스킬 갤러리 버그 수정 | YAML 아이콘 이스케이프 변환, DragMove 닫기 충돌 해결(3창), 카드 클릭 상세 팝업, 상단바 정렬 |
|
||
| **에이전트 도구 12종 추가** | json_tool, regex_tool, diff_tool, clipboard_tool, notify_tool, env_tool, zip_tool, http_tool, sql_tool, base64_tool, hash_tool, datetime_tool |
|
||
| **내장 스킬 3종 추가** | api-docs, db-schema, commit-review (총 13종 번들) |
|
||
| **설정 UI 개선** | 독 바 탭 3번째 위치로 이동 (테마 뒤), 기타 탭 접기/열기 섹션 (등록된 도구·MCP 커넥터·슬래시 스킬 각각 접기/펼치기) |
|
||
| **About 정보 변경** | 개발 정보에서 ".NET 8" 제거 → "Commander + Agent" 표시 (기술 스택 비노출) |
|
||
| **가이드 시스템 신설** | 사용자 가이드 + 개발자 가이드 분리 (개발자 가이드에만 버전 이력 포함). AES-256-CBC 고정 키 암호화 (.enc). GuideViewerWindow 내장 뷰어 (WebView2 비동기 초기화). 개발자 모드 ON→개발자 가이드, OFF→사용자 가이드. 트레이 메뉴 → 외부 브라우저 대신 앱 내 뷰어로 전환 |
|
||
| **가이드 암호화 도구** | GuideEncryptor.cs (AES-256-CBC 암호화/복호화 유틸리티), encrypt_guides.ps1 (빌드 전 암호화 스크립트) |
|
||
|
||
### v1.5.2
|
||
|
||
> **개발 범위**: Phase 12-4/12-5 런타임 스킬 + 워크플로우 분석기 + 개발자 탭 + 설정 개선
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **런타임 의존 스킬 (12-4)** | RuntimeDetector — Python/Node.js 설치 감지 (where.exe + --version, 5분 캐시). SkillDefinition.Requires/IsAvailable/UnavailableHint. 고급 스킬 4종 번들 (docx-creator, xlsx-analyzer, pdf-processor, pptx-creator). 슬래시 팝업에서 비가용 스킬 회색 표시. 기타 탭에 스킬 목록 카드 |
|
||
| **워크플로우 분석기 (12-5)** | WorkflowAnalyzerWindow — 세로 타임라인 실시간 시각화. AgentEvent 확장 (ElapsedMs/InputTokens/OutputTokens/ToolInput/Iteration). Stopwatch 타이밍 + LastTokenUsage 토큰. AgentLogLevel 3단계 분기 (simple/detailed/debug) |
|
||
| **개발자 탭 분리** | 설정 › 에이전트에 개발자 서브탭 신설. 비밀번호 보호 세션 전용. 개발자모드/실행이력상세도/스텝바이스텝/워크플로우 시각화/감사로그/에이전트고급/모델폴백/MCP서버 배치 |
|
||
| **설정 개선** | AgentLogLevel 기본값 simple, DevMode 세션 전용화 (매번 재인증), WorkflowVisualizer 토글 추가, 개발자모드 ? 툴팁 제거 |
|
||
| **UI 개선** | 훅/MCP 서버 추가 다이얼로그에 플레이스홀더 입력 예시, 좌우 패딩 증가, 훅 ESC 닫기, 코드 리뷰 툴팁 오탈자(변경사항) 수정 |
|
||
| **설정 기능 탭 개편** | 기능 설정 페이지를 3개 서브탭(AI 기능 / AX Commander / 디자인·기타)으로 분류. 클립보드 확장을 디자인·기타로 이동, 실행이력상세도를 코워크/코드 탭으로 복귀 |
|
||
| **Phase 13 계획 수립** | 스킬 생태계 + 에이전트 분석 고도화 5개 항목 (스킬 갤러리/편집기/가져오기·내보내기/통계 대시보드/AgentLogLevel 연동). AGENT_ROADMAP 문서 반영 |
|
||
| **스킬 시각적 편집기 (13-2)** | SkillEditorWindow — 폼 기반 스킬 생성/편집 GUI. 아이콘 선택기(MDL2 20종), 도구 체크리스트(ToolRegistry 연동), 템플릿 삽입(도구목록/출력형식/단계별), 토큰 예상 미리보기, YAML 프론트매터 + 마크다운 본문 자동 생성, 사용자 스킬 폴더 저장. 스킬 갤러리 연동 (새 스킬 → 편집기, 사용자 스킬 편집 → 시각적 편집기) |
|
||
|
||
### v1.5.1
|
||
|
||
> **개발 범위**: Phase 12 스킬/커넥터 고도화 + UI 개선 + 버그 수정
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **슬래시 명령 영어 전환** | 내장 슬래시 명령 11개를 한국어(/요약,/번역)에서 영어(/summary,/translate,/review,/pr 등)로 전환. IME 전환 없이 즉시 입력 가능 |
|
||
| **도구/커넥터 관리 UI (12-1)** | 설정 › 에이전트 › 기타 탭에 등록된 도구 29종을 5개 카테고리(파일/프로세스/코드분석/문서생성/에이전트)로 분류하여 표시. MCP 커넥터 안내 섹션 |
|
||
| **SKILL.md 표준 호환 (12-2)** | SkillService — *.skill.md (기존) + 폴더/SKILL.md (표준) 2형식 동시 지원. YAML metadata 맵 파싱, license/compatibility/allowed-tools 필드. SkillDefinition 확장 |
|
||
| **커스텀 ComboBox** | 전역 ComboBox/ComboBoxItem 스타일 — ControlTemplate 기반 모던 드롭다운, 호버/선택 효과, Slide 애니메이션. 설정창 전체(27개소) 자동 적용 |
|
||
| **BlockedPaths 패턴 수정** | `*\Documents\*` → `*Documents*` — 백슬래시 없는 패턴으로 수정하여 정상 차단 동작 |
|
||
| **사용자 가이드 정리** | v1.5.1 이력 추가, v1.4.0 이하 이전 이력으로 접기, 내부 기술 용어 제거(DPAPI, Ollama/vLLM, 클래스명 등), 푸터 버전 갱신 |
|
||
|
||
### v1.5.0
|
||
|
||
> **개발 범위**: 대화 서비스 Phase 9~11 완료 + 런처 Phase L1 추가 + 저장 공간 관리 + 문서 체계화
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **LSP 코드 인텔리전스 (9-1)** | LspClientService — C#/TS/Python/C++/Java 언어 서버 자동 감지. `lsp_code_intel` 도구 (goto_definition, find_references, symbols). 설정 `EnableLsp` 토글 |
|
||
| **서브에이전트 (9-2)** | SubAgentTool (`spawn_agent`) + WaitAgentsTool (`wait_agents`). 읽기 전용 격리 실행. `MaxSubAgents` 설정으로 동시 실행 제한 |
|
||
| **코드 시맨틱 검색 (9-3)** | CodeIndexService — TF-IDF 인덱싱 (camelCase 분할, 50라인 청크). `search_codebase` 도구. `EnableCodeIndex`/`CodeIndexMaxFileKb` 설정 |
|
||
| **자동 테스트 루프 (9-4)** | TestLoopTool — generate/run/analyze 3단계. .NET/Python/Node.js/Go 프레임워크 자동 감지 |
|
||
| **이벤트 트리거 (9-5)** | AgentTriggerService — FileSystemWatcher(파일 변경) + DispatcherTimer(스케줄). triggers.json 규칙 기반 |
|
||
| **PDF 내보내기 (9-6)** | PdfExportService — HTML 인쇄 최적화 + 브라우저 자동 인쇄. 대화 내보내기에 "PDF 인쇄용 HTML" 옵션 추가 |
|
||
| **diff 뷰어 (9-7)** | DiffViewerPanel — 라인 기반 diff (Added/Removed/Equal), 라인 번호, Accept/Reject 버튼 |
|
||
| **탐색기 셸 확장** | ShellExtensionService — HKCU 레지스트리 우클릭 메뉴 등록/해제. 파일/폴더/폴더배경 3종 |
|
||
| **저장 공간 관리** | StorageAnalyzer — 앱 데이터 사용량 분석 (대화/감사/로그/인덱스/클립보드), 드라이브 여유 공간, 7/14/30일 정리. 설정 공통 탭에 UI |
|
||
| **설정 도움말 아이콘** | AI 관련 설정 17개에 `?` 아이콘 + `HelpTooltipStyle` 커스텀 다크 툴팁 |
|
||
| **폴백 모델 개선** | 서비스별 그룹화 (Ollama/vLLM/Gemini/Claude). ViewModel과 AppSettings 동시 읽기로 저장 전 즉시 반영 |
|
||
| **클립보드 붙여넣기** | Alt+SetForegroundWindow 우회. TryGetSelectedText 후크 스레드 분리 |
|
||
| **독 바 개선** | 버튼 히트 테스트 수정 (MouseLeftButtonDown), 시작 시 자동 표시, 설정 실시간 반영 |
|
||
| **포맷 메뉴** | AI 자동 선택 맨 위로 이동 |
|
||
| **코드 탭 아이콘** | 파일(앰버)/권한(파랑·빨강)/데이터활용(녹·앰버·회) 색상 구분 |
|
||
| **사내 환경 원칙** | CLAUDE.md에 외부 의존 최소화, 데이터 로컬 저장, 텔레메트리 금지 지침 추가 |
|
||
| **문서 체계화** | CLAUDE.md 문서 관리 원칙 추가, AGENT/LAUNCHER ROADMAP Phase 9/L1 완료 표시, NEXT_ROADMAP 차기 계획 전면 업데이트 |
|
||
| **자동 모델 선택 (10-1)** | AutoRouterService — 질문 유형(코딩/번역/분석) 감지 → 최적 모델 자동 라우팅. 잠금 모드 지원 |
|
||
| **에이전트 메모리 (10-2)** | MemoryTool — 프로젝트 규칙, 코딩 선호도 자동 기억. 대화 간 영속 유지 |
|
||
| **멀티모달 입력 (10-4)** | 이미지/스크린샷 Ctrl+V 붙여넣기 → base64 인코딩 → Gemini/Claude/Ollama/OpenAI Vision API 직접 전달. 이미지 미리보기 UI |
|
||
| **코드 검색 개선 (10-5)** | TF-IDF + SQLite 영속 인덱스, 증분 업데이트, 바이그램 토큰, 스톱워드 필터링 |
|
||
| **에이전트 훅 시스템 (10-6)** | 도구 호출 전/후 사용자 정의 스크립트 실행. hooks.json 규칙 기반 |
|
||
| **스킬 시스템 (11-1)** | SkillService — *.skill.md YAML 프론트매터 파싱 → 슬래시 명령 자동 등록. 3폴더 우선순위(앱→%APPDATA%→커스텀). 기본 스킬 3종(daily-standup/bug-hunt/code-explain) 자동 생성. `skill_manager` 도구 |
|
||
| **AI 코드 리뷰 (11-2)** | CodeReviewTool — diff_review/file_review/pr_summary. 정적 분석(빈 catch/동기 대기/하드코딩 키/긴 메서드). Git diff 파서. 리뷰 초점(bugs/performance/security/style) |
|
||
| **드래그&드롭 AI (11-3)** | 파일 드래그 시 유형별 AI 액션 팝업(코드→리뷰/설명/리팩토링, 문서→요약/번역, 데이터→분석/시각화, 이미지→설명). "첨부만" 옵션. `EnableDragDropAiActions` 설정 |
|
||
| **프로젝트 지침 (11 추가)** | ProjectRuleTool — AX.md read/append/write. 사용자 승인 후 저장. 상위 3단계 탐색 |
|
||
| **슬래시 명령어 강화 (11 추가)** | 탭별 필터링(Chat=공통, Cowork/Code=공통+개발). `/help` 도움말 창. 총 12개 내장 명령 |
|
||
| **사용 통계 차트 확장** | 메인 탭 미니차트 2종, 커맨더 탭 요일별 평균차트, 에이전트 탭 탭비율+토큰비율 차트 |
|
||
| **인사 문구 외부화** | greetings.json 외부 파일 로딩 + 임베디드 리소스 폴백 + 5분 캐시 |
|
||
| **캡처 알림 개선** | 지연 캡처 카운트다운 알림 제거 (시작/초단위 모두). 완료 알림만 유지 |
|
||
| **알림 아이콘 수정** | ToolTipIcon.Info → ToolTipIcon.None 변경으로 앱 트레이 아이콘 표시 |
|
||
|
||
### v1.4.0
|
||
|
||
> **개발 범위**: 런처 고도화 Phase L1 (LAUNCHER_ROADMAP) + 대화 서비스 고도화 Phase 9 (AGENT_ROADMAP) 병행
|
||
>
|
||
> | 영역 | 문서 | 완료 항목 |
|
||
> |------|------|----------|
|
||
> | 런처 | `LAUNCHER_ROADMAP.md` | L1-1(선택 텍스트 AI), L1-5(독 바), L1-6(대화상자 통합), L1-7(클립보드 핀/카테고리) |
|
||
> | 대화 서비스 | `AGENT_ROADMAP.md` | Phase 8 완료, 기술부채 해결 |
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **선택 텍스트 AI 명령 (L1-1)** | TextActionPopup — 핫키 시 선택 텍스트 감지 (Ctrl+C 시뮬레이션), 커서 위치에 액션 팝업 표시 (번역/요약/교정/설명/다시쓰기), ↑↓/마우스 선택, Enter 실행 → AX Agent에 `!` 프리픽스로 전달 |
|
||
| **독 바 (L1-5)** | DockBarWindow — 화면 하단 고정 미니 바. 설정 기반 동적 아이템 빌드 (`DockBarItems`). CPU(PerformanceCounter)/RAM(GlobalMemoryStatusEx)/시계 실시간 표시. 무지개 글로우, 투명도(0.3~1.0), 위치 기억(`DockBarLeft/Top`), 드래그 이동. 트레이 메뉴 토글 |
|
||
| **대화상자 통합 (L1-6)** | FileDialogWatcher — `SetWinEventHook(EVENT_OBJECT_SHOW)` + `#32770` 클래스 감지. 열기/저장 대화상자 감지 시 런처 자동 열기 (`cd ` 프리픽스) |
|
||
| **클립보드 핀/카테고리 (L1-7)** | ClipboardEntry에 `IsPinned`/`Category` 추가. 자동 카테고리 분류 (URL/코드/경로/일반). 핀 항목 상단 고정 + 삭제 보호. `#pin`/`#url`/`#코드`/`#경로` 필터. Ctrl+P 핀 토글 |
|
||
| **아이콘 교체** | 다이아몬드 픽셀 ICO (7 sizes, 25% block, rounded) 생성. 상=파랑/하=빨강/좌=녹/우=녹. AboutWindow/LauncherWindow/SetupForm/SVG 전체 색상 통일. 모든 Window에 `Icon=` 속성 추가. 바로가기에 `IconLocation` 명시 |
|
||
| **독 바 설정 탭** | SettingsWindow에 독 바 탭 추가 — 자동 표시, 글로우 효과, 투명도 슬라이더, 위치 초기화 버튼, 표시 항목 토글 (8종) |
|
||
| **인스톨러** | UAC `requireAdministrator` 유지. SetupForm 다이아몬드 아이콘 `FillRoundRect`로 둥근 모서리. 바로가기 `IconLocation` 설정 |
|
||
| **UI 통일** | 알림 카테고리 CheckBox → ToggleSwitch. Ollama/vLLM 서버 주소 라벨 "기본 서버 주소"로 통일. 개발자 정보창 기여자 표시 (`about.json` contributors). 창 높이 조정 |
|
||
|
||
### v1.3.1
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **SnapHandler 레이아웃 확장** | 기존 11개 → 22개 스냅 옵션. 3등분(third-l/c/r), 2/3+1/3(two3-l/r), 3분할 조합(l-rt, l-rb, r-lt, r-lb) 추가 |
|
||
| **Everything SDK 연동** | `es` 프리픽스로 Everything 초고속 파일 검색 통합. Everything 미설치 시 graceful fallback. 파일 타입별 아이콘 구분 |
|
||
| **플러그인 자동 설치** | `PluginHost.InstallFromZip()` — 로컬 zip에서 DLL/JSON 스킬 자동 추출·등록·로드. `UninstallPlugin()` 제거 기능 포함. URL 기반 설치는 사내 보안 정책으로 제외 |
|
||
| **이미지 클립보드 영속화** | 클립보드 히스토리 이미지 항목을 PNG→Base64로 DPAPI 암호화 저장/복원. 앱 재시작 후에도 이미지 히스토리 유지 |
|
||
| **다크 테마 대비 강화** | 6종 다크 테마 SecondaryText/PlaceholderText/HintText 밝기 +12~20 추가 개선. 헬프/단축키 창 텍스트 가독성 향상 |
|
||
| **인스톨러 버전 동기화** | SetupForm.cs `AppVer` 1.2.2→1.3.1 수정. 버전 관리 체크리스트에 MCP 버전·로드맵 문서 항목 추가 |
|
||
| **사용자 가이드 업데이트** | version-tag v1.2.2→v1.3.1, v1.3.0/v1.3.1 버전 이력 추가, version-tag에 `color:#fff` 추가 |
|
||
| **헬프 창 업데이트** | v1.3.1 신기능 항목 추가, 파일 타입별 심볼 12종 추가 (Excel/Word/Pdf/Image/Video/Music/Archive/Code 등) |
|
||
| **문서 정비** | AI_Service_Review.html → AGENT_ROADMAP.html 병합 후 삭제, 기술부채 항목 완료 표시, LAUNCHER_ROADMAP 생성 |
|
||
|
||
### v1.3.0
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **MCP 클라이언트** | McpClientService (stdio/JSON-RPC 2.0). ConnectAsync → initialize → tools/list → tools/call. McpTool이 IAgentTool로 래핑 |
|
||
| **모델 폴백** | LlmService.SendAsync에 FallbackModels 순차 시도. 실패 시 토스트 알림으로 폴백 모델 안내 |
|
||
| **대화 분기** | ChatConversation.ParentId/BranchLabel, ForkConversation(). 우클릭 "여기서 분기" 메뉴. 사이드바 들여쓰기 표시 |
|
||
| **커맨드 팔레트** | CommandPaletteWindow (Ctrl+Shift+P). 16개 명령, 한글 초성 검색 |
|
||
| **보안 감사 로그** | AuditLogService — JSON 영속화, 30일 보관, 설정 토글 + 폴더 열기 버튼 |
|
||
| **에이전트 자율성** | 동적 반복 한도 (도구 15+회 → 한도 2배, 최대 50). 다단계 반성 |
|
||
| **토큰 관리** | TokenEstimator (모델별 비용, CJK 가중치). 상태바 비용 표시 |
|
||
| **스플릿 뷰** | Code 탭 파일 수정 시 자동 프리뷰, AutoPreview 설정 |
|
||
| **다중 서버** | RegisteredModel에 endpoint/apiKey 필드. 모델별 서버 라우팅 (Ollama/vLLM) |
|
||
| **대화별 설정** | Permission/DataUsage/Mood를 대화별 독립 저장·복원 |
|
||
| **DiffService** | LCS 기반 라인 diff (Added/Removed/Equal). GetSummary() 통계 |
|
||
|
||
### v1.2.2
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **AX.md 프로젝트 문맥 파일** | 작업 폴더에 AX.md를 만들면 Cowork/Code 시스템 프롬프트에 자동 주입. 상위 3단계까지 탐색, 최대 8000자 |
|
||
| **팁 알림 시스템** | Cowork/Code 탭 전환 시 24개 사용법 팁 랜덤 표시. 설정: 표시 여부(ShowTips) + 자동 사라짐 시간(TipDurationSeconds, 0~30초) |
|
||
| **개발자 모드** | 설정 → 공통 → 개발자 모드 (비밀번호 보호). 도구 호출 파라미터/결과 상세 표시 + 스텝별 승인/건너뛰기/중단 |
|
||
| **통계 강화** | DailyUsageStats에 ChatCounts(탭별), TotalTokens/PromptTokens/CompletionTokens 추가. 통계 윈도우에 대화 빈도 + 토큰 사용량 14일 막대 차트 |
|
||
| **무지개 글로우** | 메시지 전송 시 입력창 테두리에 7색 무지개 그라데이션 회전 애니메이션 (2초, LinearGradientBrush 회전) |
|
||
| **런처 중복 제거** | IndexService: Path 기반 중복 방지. CommandResolver: 검색 결과에서 같은 Path 필터링 (2중 방어) |
|
||
|
||
### v1.2.1
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **Code 시스템 프롬프트 고도화** | Claude Code/OpenCode 벤치마크 기반 8단계 워크플로우 (ORIENT→BASELINE→ANALYZE→PLAN→IMPLEMENT→VERIFY→GIT→REPORT). 테스트 우선, 변경 영향 분석, 자기 검증 |
|
||
| **GitTool** | 사내 GitHub Enterprise 연동. status/diff/log/add/commit/branch/checkout/stash/remote 지원. push/pull/fetch/rebase 차단 (사용자 직접 수행) |
|
||
| **BuildRunTool lint/format** | action="lint", action="format" 추가. ESLint/Prettier(JS), Ruff/Black(Python), dotnet format(C#), checkstyle(Maven) 자동 매핑 |
|
||
| **Grep 강화** | context_lines(0~5줄) 파라미터로 매치 전후 코드 표시, case_sensitive 파라미터로 대소문자 구분 제어 |
|
||
| **FileEdit replace_all** | replace_all=true 시 모든 매치 일괄 교체. false면 기존 유일성 검증 유지 |
|
||
| **루트 드라이브 차단** | C:\, D:\ 등 최상위 드라이브를 작업공간으로 설정하는 것을 차단 (하위 폴더 선택 필수) |
|
||
| **프리셋 순서 정렬** | TopicPreset.Order 필드 추가, JSON에서 order 값으로 표시 순서 제어 |
|
||
| **카테고리 필터 개선** | Cowork/Code: 프리셋 카테고리 기반 필터, 커스텀 프리셋 `__custom__` 통합 분류 |
|
||
| **에이전트 이름 매핑** | Code 카테고리별 에이전트 이름 (코드개발/리팩터링/코드리뷰/보안점검/테스트) + 대화 이력 아이콘 정확 표시 |
|
||
| **AI Agent 상세 가이드** | 사용자 가이드에 Chat/Cowork/Code 3탭 상세 설명, 경고 문구 (백업 필수), 공통 기능 안내 |
|
||
| **보안 점검 리네이밍** | "보안 취약점 점검" → "보안 점검"으로 간결하게 변경 |
|
||
|
||
### v1.2.0
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **Code 탭 활성화** | 코딩 에이전트 탭 활성화 — 코드 개발, 리팩터링, 코드 리뷰, 보안 점검, 테스트 작성 5개 프리셋 |
|
||
| **DevEnvDetectTool** | IDE(VS Code, Visual Studio, IntelliJ, PyCharm) + 런타임(dotnet, python/conda, java, node, gcc) + 빌드도구(MSBuild, Maven, Gradle, CMake) 자동 감지. 레지스트리+PATH+환경변수, 60초 캐시 |
|
||
| **BuildRunTool** | 프로젝트 타입 감지(*.csproj, pom.xml, package.json 등 7종) + 빌드/테스트/실행 명령 자동 매핑 |
|
||
| **CodeSettings** | Nexus URL, NuGet/PyPI/Maven/npm 저장소 설정, 선호 IDE 경로, 빌드 타임아웃(30~300초), 완료 알림 |
|
||
| **Code 시스템 프롬프트** | 분석→계획→구현→검증→보고 5단계 워크플로우, 언어별 가이드라인(C#/Python/Java/C++/JS), 패키지 저장소 주입 |
|
||
| **설정 UI** | Code 탭 전용 설정 패널 — Nexus 저장소, 언어별 소스 URL, IDE 경로, 빌드 타임아웃, 완료 알림 |
|
||
| **마크다운 렌더러 완성** | 테이블(`\|`), 인용(`>`), 취소선(`~~`), 링크(`[text](url)`) 지원 추가 |
|
||
| **메시지 삭제** | 우클릭 → "이후 메시지 모두 삭제" (확인 다이얼로그 + 재렌더링) |
|
||
| **탭 단축키** | Ctrl+1=Chat, Ctrl+2=Cowork, Ctrl+3=Code |
|
||
| **에러 복구 UI** | LLM 오류 시 "재시도" 버튼 자동 표시 |
|
||
| **카테고리 필터 개선** | Cowork/Code: 프리셋 카테고리 기반 필터, 커스텀 프리셋 통합 분류 |
|
||
| **에이전트 이름 확장** | Code 프리셋별 에이전트 이름 매핑 (코드 개발/리팩터링/리뷰/보안/테스트) |
|
||
| **최대화 버튼** | 타이틀바에 최소화-최대화-닫기 3버튼 |
|
||
| **서브 바** | 탭 바 아래에 대화 제목(좌) + 미리보기 버튼(우) 분리 배치 |
|
||
| **완료 알림** | Cowork/Code 에이전트 완료 시 시스템 트레이 알림 |
|
||
|
||
### v1.1.1
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **WebView2 프리뷰** | IE 기반 WebBrowser → Chromium 기반 WebView2 교체. AppData에 데이터 디렉터리 지정 |
|
||
| **Markdown 프리뷰** | Markdig NuGet으로 .md 파일을 무드 CSS 적용 HTML 렌더링 |
|
||
| **코드 블록 강화** | 라인 번호, 전체화면 팝업, 파일 저장 버튼, 언어별 확장자 자동 추천 |
|
||
| **무드 갤러리** | 텍스트 목록 → 2열 비주얼 카드 레이아웃으로 무드 미리보기 선택 |
|
||
| **에이전트 진행률 스티키 바** | 메시지 상단 고정 바 — 단계/퍼센트/경과시간, 완료 시 페이드아웃 |
|
||
| **파일 빠른 작업** | 생성 파일 배너에 [프리뷰][열기][폴더][복사] 4개 인라인 액션 버튼 |
|
||
| **작업 폴더 파일 탐색기** | 접이식 TreeView, 지연 로딩, 우클릭 메뉴(열기/삭제/이름변경), 에이전트 파일 생성 시 자동 새로고침, 상태 저장 |
|
||
| **document_review 도구** | 빈 섹션, 플레이스홀더, 날짜 정합성, HTML 태그 균형, 반복 텍스트, 기대 섹션 누락 검사 |
|
||
| **format_convert 도구** | md→html, html→txt, csv→html, md→txt 변환. 미지원 변환은 대안 워크플로우 안내 |
|
||
| **대화 내 검색** | Ctrl+F 검색 바, 이전/다음 탐색, 결과 개수 표시, ESC 닫기 |
|
||
| **메시지 우클릭 메뉴** | 텍스트 복사, 마크다운 복사, 인용 답장, 재생성 |
|
||
| **토스트 알림** | 복사/저장 등 액션 시 하단 중앙 페이드인-아웃 알림 |
|
||
| **대화 목록 성능** | 레이지 로딩 (50개 단위 + "더 보기"), 제목+내용 통합 검색 (Preview 필드) |
|
||
| **의사결정 UI** | 승인/수정/취소 버튼 선택 후 자동 숨김 + 결과 라벨 표시 |
|
||
| **채팅 반응형 너비** | 창 크기에 비례하여 메시지 버블 MaxWidth 자동 조절 (최소 500, 최대 1200) |
|
||
| **커스텀 프리셋/무드** | 아이콘 셋 선택 UI (5카테고리×8아이콘), 커스텀 무드 CSS 편집, 프리셋 배지 |
|
||
| **탭 전환 안정화** | Auto 권한 경고 초기화, 파일 탐색기 상태 복원, 안내문구 갱신 |
|
||
| **런처 개선** | 퍼지 검색 Shift+Enter로 폴더 열기, 웹검색 경고문 수정 |
|
||
|
||
### v1.1.0
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **Cowork 에이전트 루프 엔진** | LLM Function Calling 기반 Plan→Tool Execute→Observe→Re-evaluate 반복 루프. 최대 25회 반복, 실패 시 Self-Reflection 자동 재시도 (최대 3회) |
|
||
| **도구 시스템 (8종)** | file_read, file_write, file_edit, glob, grep, process, folder_map, document_read |
|
||
| **문서 생성 스킬 (6종)** | excel_create (.xlsx), docx_create (.docx), csv_create (.csv), markdown_create (.md), html_create (.html), script_create (.bat/.ps1) |
|
||
| **디자인 템플릿 시스템** | 10종 CSS 무드 템플릿 (modern, professional, creative, minimal, elegant, dark, colorful, corporate, magazine, dashboard). 대화창 하단 무드 아이콘 바로 선택 |
|
||
| **Task Decomposition** | LLM 응답에서 계획 단계 자동 추출 → 진행률 UI (단계 카드 + 프로그레스 바) |
|
||
| **Thinking UI** | LLM 추론 과정을 "Thinking..." 배너로 실시간 표시 |
|
||
| **Context Condenser** | 토큰 초과 시 이전 대화를 LLM으로 자동 요약하여 컨텍스트 윈도우 관리 |
|
||
| **Folder Map 도구** | 작업 폴더 디렉토리 트리 자동 생성 (depth/filter 지원, 빌드 산출물 자동 제외) |
|
||
| **Diff Preview** | file_edit 도구 실행 시 unified diff 생성 + 색상 하이라이팅 UI (추가=초록, 삭제=빨강) |
|
||
| **문서 읽기 도구** | PDF (PdfPig), DOCX, XLSX (OpenXml), CSV/TXT 등 다양한 형식 텍스트 추출. 보고서 작성 시 폴더 데이터 자동 참조 |
|
||
| **폴더 데이터 활용 설정** | 적극 활용(자동 탐색) / 소극 활용(요청 시) / 활용하지 않음 — 설정 + 대화창 하단 메뉴에서 전환 |
|
||
| **Cowork 설정 UI** | 파일 접근 권한, 출력 형식, 자동 미리보기, 에이전트 반복/재시도 횟수, 로그 상세도, 데이터 활용 수준 |
|
||
| **커스텀 폴더 메뉴** | 시스템 ContextMenu → 커스텀 Popup (Border+MouseLeftButtonUp 패턴, 14px 폰트) |
|
||
| **모델 선택기 개선** | 서비스 변경 시 팝업 유지, 모델 목록 동적 재구성 (closeOnClick 패턴) |
|
||
| **Gemini 모델 수정** | 존재하지 않는 모델 ID(gemini-3-flash 등) → 실제 모델(gemini-2.5-pro/flash 등)로 교체 |
|
||
| **에이전트 이벤트 UI** | Planning/StepStart/StepDone/ToolCall/ToolResult 배너 + 접이식 상세 보기 |
|
||
|
||
### v1.0.7
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **Chat/Cowork/Code 3탭 UI** | 상단 탭을 Agent 단일 → Chat \| Cowork \| Code 3탭으로 전환. Cowork/Code 탭 활성화 (Phase 2/3 준비) |
|
||
| **작업 폴더 선택 바** | 입력 바 상단에 폴더 경로 표시 + 선택/해제 버튼. Cowork/Code 탭에서 자동 표시. 최근 폴더 10개 기억 |
|
||
| **파일 컨텍스트 첨부** | 파일 첨부 버튼 + 드래그 앤 드롭으로 파일을 대화 컨텍스트에 추가 (최대 10MB). 텍스트 파일 내용 자동 삽입 |
|
||
| **권한 시스템 설계** | 3단계 파일 접근 권한: Ask(매번 확인) / Auto(자동 허용) / Deny(차단). 설정에서 기본값 변경 가능 |
|
||
| **대화 주제 프리셋 7종** | 일반/경영/연구개발/제품분석/수율분석/제조기술/시스템 — JSON 기반 프리셋 동적 로드 (EmbeddedResource) |
|
||
| **대화 내보내기 확장** | Markdown + JSON + HTML + Text 4종 포맷 지원. HTML은 다크 테마 스타일 내장 |
|
||
| **메시지 타임스탬프** | 사용자/AI 메시지에 HH:mm 시간 표시 |
|
||
| **격려 알림 주기 타이머** | 주기적 타이머 추가 — 화면 잠금 없이도 설정 간격마다 격려 문구 팝업 표시 |
|
||
| **커스텀 메시지 박스** | 앱 전체 기본 MessageBox를 테마 통합 커스텀 다이얼로그로 교체 (인스톨러 포함) |
|
||
|
||
### v1.0.6
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **스트리밍 실시간 표시 수정** | 80ms 쓰로틀 + Task.Delay → 청크 단위 갱신 + `Dispatcher.InvokeAsync(Background)` 방식으로 전환. 응답이 실시간으로 부드럽게 표시 |
|
||
| **Shift+Enter 줄바꿈** | `AcceptsReturn="True"` + PreviewKeyDown 핸들러. Shift+Enter=줄바꿈, Enter=전송. 입력 영역 자동 수직 확장 (MinHeight 40 → MaxHeight 160) |
|
||
| **프롬프트 카드 워터마크** | 프롬프트 카드 선택 시 안내 문구를 실제 텍스트가 아닌 워터마크(placeholder) 오버레이로 표시. 입력 시 자동 사라짐 |
|
||
| **좋아요/싫어요 상호 배타 토글** | 좋아요↔싫어요 상호 배타 — 하나를 누르면 다른 쪽 자동 해제. `resetSibling`/`registerReset` 콜백 패턴 |
|
||
| **디스크 용량 초과 자동 삭제** | 드라이브 사용률 98% 초과 시 핀 고정 제외 오래된 대화부터 자동 삭제 (`PurgeForDiskSpace`). 2% 여유 확보 후 중단 |
|
||
| **우클릭 컨텍스트 메뉴** | 대화 제목에서 우클릭 시 커스텀 메뉴 바로 표시 (펜 아이콘 클릭 불필요). `MouseRightButtonDown` 이벤트 |
|
||
| **대화 더블클릭 오류 수정** | Visual 자식 인덱스 충돌 오류 — `RemoveAt`+`Insert` 패턴으로 안전 교체 + 스트리밍 중 대화 전환 시 `_streamCts?.Cancel()` 처리 |
|
||
|
||
### v1.0.5
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **AX Agent 대화 창** | `!` 예약어로 AI 대화 창 (ChatWindow) 구현. 좌측 대화 목록 + 우측 메시지 영역 2패널 구조. Claude Desktop 스타일 디자인 |
|
||
| **LLM 4종 서비스 지원** | Ollama, vLLM(OpenAI 호환), Gemini, Claude API 통합. 설정 창에서 서비스/모델 등록 및 전환 |
|
||
| **스트리밍 + 타이핑 효과** | SSE 기반 스트리밍 응답. 12ms 타이머로 1~3글자씩 타이핑 효과 표시. 커서 깜빡임 애니메이션 |
|
||
| **마크다운 + 코드 구문 강조** | 코드 블록(10개 언어 키워드 하이라이팅), 목록, 볼드, 인라인 코드, 복사 버튼 |
|
||
| **토큰 사용량 표시** | 각 서비스별 실제 토큰 파싱. k/m 단위 표기 (1.2k, 2.3m). 응답 소요시간(초) 실시간 표시 |
|
||
| **프롬프트 카드** | 개발자 미리 설정 시스템 프롬프트 (Tag 형식). 카드 클릭 시 SystemCommand 자동 삽입 + placeholder 안내 |
|
||
| **사용자 프롬프트 템플릿** | 설정에서 추가/삭제 가능한 사용자 정의 프롬프트 템플릿. 입력 바 왼쪽 버튼으로 접근 |
|
||
| **대화 관리** | 고정/이름변경/분류(6종 카테고리)/삭제. 커스텀 Popup 메뉴. 인라인 제목 편집 (클릭 → 입력 → Enter) |
|
||
| **피드백 영속성** | 메시지별 좋아요/싫어요 상태 저장 및 대화 로드 시 복원 |
|
||
| **사용자 메시지 편집/복사** | 사용자 메시지에 편집/복사 버튼 추가. 편집 시 해당 메시지 이후 재생성 |
|
||
| **커스텀 Popup 메뉴 통일** | 모든 드롭다운 메뉴를 ContextMenu → 커스텀 Popup (12px 라운드, 호버, 드롭섀도) 으로 전환 |
|
||
| **캡처 순서 변경** | cap 명령 아이템 순서: 영역 선택 → 활성 창 → 스크롤 → 전체 화면 (사용 빈도순) |
|
||
| **지연 캡처** | Shift+Enter로 캡처 아이템 선택 시 타이머(3초/5초/10초) 선택 후 카운트다운 캡처 |
|
||
| **버그 수정** | 목록 텍스트 오버플로(StackPanel→Grid), 편집 Visual 자식 오류, + 버튼 클릭 불가, 제목 편집 이중 커밋 크래시 |
|
||
|
||
### v1.0.4
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **설정 알림 바로보기 버튼** | 알림 탭 하단에 "바로보기" 버튼 추가. 시간 미도래 시에도 설정한 위치·표시 시간으로 팝업 즉시 확인 가능 |
|
||
| **런처 안내 문구 랜덤화** | 고정 플레이스홀더 "무엇을 도와드릴까요?" → 25종 랜덤 문구. 정중한 인사 + 기능 홍보(계산기·클립보드·웹검색·즐겨찾기·스니펫·워크스페이스·캡처 등). 런처 열릴 때마다 교체. 5개국어 대응(ko/en/ja/zh/vi) |
|
||
| **다이아몬드 픽셀 아이콘 애니메이션** | 런처 입력창 좌측 4개 픽셀이 순차적으로 Opacity 점멸 (4초 주기 Forever). 디스플레이 패널 픽셀 점등 형상화 |
|
||
| **글로벌 단축키 콤보박스** | 불안정한 키 녹화 방식 제거 → 검증된 12종 키 조합 콤보박스 선택으로 변경. Alt+Space, Ctrl+Space, Ctrl+Alt+Space, Alt+X/A/Z, Ctrl+Shift+Space, Ctrl+`, Win+Space, Ctrl+Alt+A, Ctrl+;, F12 |
|
||
| **트레이 메뉴 개편** | "사용 가이드 문서보기" 항목 신규 추가 (GlyphGuide = `\uE736`). "정보" → "개발자 정보"로 이름 변경 + 종료 바로 위로 위치 이동 |
|
||
| **사용 통계 화면 FHD 최적화** | 창 높이 640→900px, MinHeight 540→700px. 차트 막대 높이 110→88px (MaxBarHeight 80→66). 자주 쓴 명령어 표시 개수 8→10개. 인기 명령어·즐겨찾기 섹션 간 마진 추가 |
|
||
| **사용 가이드 문서 배포** | `Assets/AX Commander 사용가이드.htm` 빌드 시 출력 폴더에 자동 복사. 트레이 메뉴에서 기본 브라우저로 열기. 버전 이력 섹션 포함 (v1.0.0 ~ v1.0.4) |
|
||
|
||
### v1.0.3
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **키보드 단축키 16종 추가** | 1차: F1(도움말), F5(인덱스 새로 고침), Delete(항목 제거+확인), Ctrl+L(입력 초기화), Ctrl+C(이름 복사), Ctrl+Shift+C(경로 복사), Ctrl+Shift+E(탐색기 열기), Ctrl+Enter(관리자 실행), Alt+Enter(속성 보기). 2차: Ctrl+H(히스토리), Ctrl+R(최근), Ctrl+B(즐겨찾기), Ctrl+K(단축키 도움말), Ctrl+1~9(N번째 실행), F2(이름 바꾸기), PageUp/Down(페이지 스크롤) |
|
||
| **결과 목록 번호 뱃지** | 1~9 번호 표시 (IndexToNumberConverter). Ctrl+N으로 즉시 실행 연동 |
|
||
| **토스트 오버레이** | 별도 ToastOverlay Border (녹색 배경+체크 아이콘). 경로 복사 등 결과 표시, 2초 자동 숨김 |
|
||
| **도움말 검색** | HelpDetailWindow 상단에 SearchBox 추가. 실시간 키워드 필터링 (제목/명령/설명/카테고리) |
|
||
| **액션 모드 확장** | → 진입 시 7개 옵션: 경로 복사, 전체 경로 복사, 탐색기, 관리자, 터미널, 속성 보기, 이름 바꾸기 |
|
||
| **도움말 창 3탭 메뉴 재설계** | 상단 메뉴를 개요/단축키 현황/예약어 현황 3탭으로 분리. 하위 카테고리 탭 유지. 숫자키 1/2/3으로 탭 전환 |
|
||
| **프리픽스 변경** | `~` → 워크스페이스 관리 (기존 `!`), `cd` → 폴더 별칭 (기존 `~`), `!` → 비어있음 (신기능 배정 가능) |
|
||
| **설정 버전 마이그레이션** | SettingsService에 `MigrateIfNeeded()` 프레임워크 추가. 이전 버전 settings.json을 최신 스키마로 자동 마이그레이션. 신규 프로퍼티는 C# 기본값 자동 적용. 구조 변경(키 이름 변경 등)은 버전별 마이그레이션 로직 순차 실행 |
|
||
| **파괴적 동작 확인** | Delete 키 실행 시 MessageBox 확인 다이얼로그 (OK/Cancel) |
|
||
| **토스트 알림** | LauncherWindow에 ShowToast() 메서드 추가. 경로 복사 등 결과를 IndexStatusText에 임시 표시 |
|
||
| **Windows 실행 명령 (`^`)** | `^ notepad`, `^ cmd`, `^ calc` 등 Win+R 실행 창과 동일한 명령 실행. RunHandler 신규 추가 |
|
||
| **기본 앱 별칭 강화** | `note`, `txt` → 메모장, `msword`/`msexcel`/`mspowerpoint` + 확장자(`docx`, `xlsx`, `pptx`, `csv`, `doc`, `xls`, `ppt`) → 해당 Office 앱. Score 부스트(95)로 항상 최상단 표시 |
|
||
| **인스톨러 UI 아이콘** | 폼 아이콘(타이틀바+작업표시줄)에 다이아몬드 픽셀 아이콘 반영 |
|
||
| **Help 창 확대** | 880→1020px 너비 확대 + 카테고리 탭 패딩 축소 → 가로 스크롤 없이 모든 탭 표시 |
|
||
| **Help 개요 갱신** | 개요 문구에 v1.0.3 표기, 폴더 검색·루틴·일지·한글 앱 실행 기능 반영, 웹검색 예시(`?n` 네이버) 추가 |
|
||
| **코드 품질 개선** | ShowIndexingProgress 오버레이 누수 수정(finally 제거), RunHandler Process.Dispose, IndexService volatile, HelpDetailWindow 상수 추출, SetupForm Icon null 체크 |
|
||
|
||
### v1.0.2
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **빠른 실행 Placeholder** | 입력 필드에 힌트 텍스트 표시 (키워드, 표시 이름, 경로). ModernTextBox 템플릿에 `Tag` 기반 워터마크 추가 |
|
||
| **기본 앱 별칭 19종** | 한글+영문 이름으로 즉시 실행: 메모장/notepad, 계산기/calc, 엑셀/excel, 워드/word, 파워포인트/ppt, 탐색기/explorer, cmd, powershell, 그림판/paint, 캡처/snip, Edge, Teams, VS Code, Outlook, 원격/rdp, 작업관리자/taskmgr 등. 실제 설치된 앱만 자동 감지 |
|
||
|
||
### v1.0.1
|
||
|
||
| 구분 | 내용 |
|
||
|------|------|
|
||
| **인스톨러 통합** | 온라인/오프라인 2종 → 오프라인 1종으로 통합. .NET Framework 4.8 기반 (Windows 기본 포함). 관리자 권한 자동 요청 (app.manifest `requireAdministrator`) |
|
||
| **검색 확장자 설정** | 설정 → 일반 탭에 태그형 확장자 UI. 기본 30+종 (실행/문서/텍스트/이미지). 사용자 추가/삭제 가능 |
|
||
| **폴더 인덱싱** | 인덱스 경로의 1단계 하위 폴더도 검색·열기 가능 |
|
||
| **인덱싱 현황 표시** | 런처 하단에 `✓ N개 항목 색인됨 (X.X초)` 자동 표시 → 5초 후 사라짐. 설정 저장 시 프로그레스 오버레이 |
|
||
| **Help 인기 탭** | ⭐ 인기 탭 추가 (2번째 위치). 파일검색/웹검색/클립보드 핵심 기능만 필터 |
|
||
| **다이아몬드 픽셀 아이콘** | 런처 입력창 좌측 + 정보 창 + 트레이 + 인스톨러 헤더에 벡터 다이아몬드 아이콘 적용 |
|
||
| **정보 창 아이콘** | 비트맵 ICO → 벡터 Canvas 렌더링 (해상도 독립, DPI 무관 선명) |
|
||
| **언어 라벨** | 설정 → Language (영어 표기로 변경, 다국어 사용자 접근성) |
|
||
| **버그 수정** | HelpDetailWindow 인기 탭 연산자 우선순위 버그 (`&&`/`||`), DispatcherTimer 중복 생성 방지, Installer nullable 경고 13개 해소 |
|
||
|
||
### v1.0.0
|
||
|
||
정식 릴리즈. 40개+ 명령어, 9종 테마, 11개 설정 탭, 클립보드 DPAPI 암호화, 잠금 해제 알림, 화면 캡처, 모던 트레이 메뉴, 설정 가져오기/내보내기.
|
||
|
||
---
|
||
|
||
## 개발 검토 — 워크플로우 병목 분석 그래프
|
||
|
||
> **상태**: 검토 완료 · 구현 대기
|
||
> **검토일**: 2026-03-30
|
||
> **대상**: 개발자 모드 전용 기능
|
||
|
||
### 배경
|
||
|
||
WorkflowAnalyzerWindow(타임라인 뷰)와 AgentStatsDashboardWindow(통계 대시보드)가 이미 구현되어 있으나,
|
||
**실시간으로 어디가 병목인지 시각적으로 보여주는 그래프**가 없음.
|
||
에이전트 실행 중 "LLM 호출이 느린 건지, 특정 도구가 느린 건지" 판단이 어려움.
|
||
|
||
### 현재 보유 기반
|
||
|
||
| 구성요소 | 상태 | 위치 |
|
||
|----------|:----:|------|
|
||
| WorkflowAnalyzerWindow | ✅ | `Views/WorkflowAnalyzerWindow.xaml(.cs)` — 이벤트 타임라인, 요약 카드 |
|
||
| AgentEvent.ElapsedMs | ✅ | 각 도구 실행 소요시간 수집중 |
|
||
| AgentEvent.InputTokens/OutputTokens | ✅ | LLM 호출별 토큰량 수집중 |
|
||
| AgentEvent.Iteration | ✅ | 반복 번호 수집중 |
|
||
| AgentStatsDashboardWindow | ✅ | `Views/AgentStatsDashboardWindow.xaml(.cs)` — 일별 바 차트, 도구 빈도 |
|
||
| LLM 호출 자체의 소요시간 | ❌ 미수집 | `SendWithToolsAsync` 전후 Stopwatch 추가 필요 |
|
||
| 차트 라이브러리 | ❌ 불필요 | 모든 차트를 WPF Canvas+Rectangle 직접 구현 |
|
||
|
||
### 추가 구현 대상 — 3종 시각화
|
||
|
||
#### ① 워터폴 차트 (시간 흐름 + 병목 색상)
|
||
|
||
```
|
||
시간 → 0s 2s 4s 6s 8s 10s
|
||
├───────┼───────┼───────┼───────┼───────┤
|
||
LLM 1 ████████ 2.1s (토큰 1.2K)
|
||
Tool 1 ███ 0.8s folder_map
|
||
LLM 2 ████████████ 3.5s (토큰 2.8K) ← 🔴 병목!
|
||
Tool 2 █ 0.2s file_read
|
||
LLM 3 ████ 1.2s (토큰 1.5K)
|
||
Tool 3 ██████ 1.8s html_create
|
||
```
|
||
|
||
- **빨간 바**: 가장 긴 구간 (병목), **주황**: 평균 이상, **녹색**: 정상
|
||
- LLM 호출과 도구 실행을 구분하여 시간 소비 패턴을 직관적으로 표현
|
||
- **구현**: Canvas + Rectangle, 색상 임계값 자동 계산 (평균 × 1.5 = 주황, × 2.0 = 빨강)
|
||
- **전제 조건**: LLM 호출 소요시간 수집 (`SendWithToolsAsync` 전후 Stopwatch)
|
||
|
||
#### ② 도구별 누적 소요시간 바 차트
|
||
|
||
```
|
||
도구별 소요시간 (이번 세션)
|
||
─────────────────────────────────────
|
||
html_create ████████████████████ 4.2s ← 🔴 최다
|
||
file_read ████████ 1.8s
|
||
folder_map ████ 0.9s
|
||
grep ██ 0.4s
|
||
LLM 호출 ██████████████████████████ 7.1s
|
||
```
|
||
|
||
- 현재 AgentStatsDashboardWindow의 도구 빈도 바 차트와 동일 패턴
|
||
- ElapsedMs 기준 내림차순 정렬
|
||
- 실시간: 이벤트 수신 시 `Dictionary<string, long>`에 누적 후 바 재렌더링
|
||
- **구현 난이도**: 낮음 — 기존 코드 복제 수준
|
||
|
||
#### ③ 반복별 토큰 추세선
|
||
|
||
```
|
||
토큰 ↑
|
||
3000 │ ●
|
||
│ ● ●
|
||
2000 │ ● ●
|
||
│● ●
|
||
1000 │
|
||
0 └───┬───┬───┬───┬───┬───┬──→ 반복
|
||
1 2 3 4 5 6
|
||
```
|
||
|
||
- 꺾은선 그래프: Canvas + WPF `Polyline` (기본 도형)
|
||
- 입력 토큰 지속 증가 패턴 감지 → **"⚠ 컨텍스트 크기 급증"** 경고 배지
|
||
- **구현 난이도**: 중간
|
||
|
||
### 구현 비용 분석
|
||
|
||
| 항목 | 예상 코드량 | 앱 크기 영향 | 비고 |
|
||
|------|------------|:----------:|------|
|
||
| LLM 호출 시간 수집 | ~5줄 | 0 | AgentLoopService에 Stopwatch 추가 |
|
||
| 워터폴 차트 | ~150줄 | 0 | Canvas+Rectangle |
|
||
| 도구별 바 차트 | ~80줄 | 0 | 기존 바 차트 패턴 복제 |
|
||
| 토큰 추세선 | ~100줄 | 0 | Canvas+Polyline |
|
||
| 외부 차트 라이브러리 | 불필요 | 0 | WPF 기본 기능으로 충분 |
|
||
| **합계** | **~335줄** | **0KB** | |
|
||
|
||
### 권장 구현 순서
|
||
|
||
| Phase | 범위 | 효과 |
|
||
|-------|------|------|
|
||
| **Phase 1** (즉시 가능) | LLM 호출 시간 수집 + 도구별 바 차트 | "어떤 도구가 느린지" 즉시 파악 |
|
||
| **Phase 2** (다음) | 워터폴 차트 | 시간 흐름에서 LLM vs 도구 비율 시각화 |
|
||
| **Phase 3** (선택) | 토큰 추세선 + 컨텍스트 폭발 경고 | 고급 디버깅용 |
|
||
|
||
### 결론
|
||
|
||
| 관점 | 평가 |
|
||
|------|------|
|
||
| 기술 가능성 | ✅ 높음 — 데이터 수집 90% 완성, 차트는 기존 패턴 재활용 |
|
||
| 구현 난이도 | 중~하 — 외부 라이브러리 불필요 |
|
||
| 사용자 가치 | 높음 — "왜 느린지" 원인 즉시 파악 가능 |
|
||
| 앱 크기 | 0 영향 — 코드만 추가 |
|
||
| 배치 위치 | WorkflowAnalyzerWindow 내부 (요약 카드 아래, 타임라인 위) |
|
||
|
||
---
|
||
|
||
## 개발 검토 — 에이전트 루프 검증 강제 (Post-Tool Verification)
|
||
|
||
> **상태**: 구현 완료
|
||
> **검토일**: 2026-03-31
|
||
> **대상**: Cowork/Code 모드 에이전트 루프
|
||
|
||
### 배경 — 업계 오픈소스와의 비교
|
||
|
||
에이전트 루프가 문서 생성 후 검수를 하지 않는 문제가 관찰됨. OpenHands(구 OpenDevin), Claude Code, Cursor 등 주요 오픈소스/상용 서비스의 에이전트 루프를 분석한 결과, **업계 전체가 동일한 구조적 한계**를 가지고 있음을 확인.
|
||
|
||
#### 아키텍처 비교
|
||
|
||
| 항목 | AX Copilot | OpenHands | Claude Code |
|
||
|------|-----------|-----------|-------------|
|
||
| 루프 구조 | while + SendWithToolsAsync | while + agent.step(state) | while + tool_use |
|
||
| **반복당 LLM 호출** | **1회** | **1회** | **1회** |
|
||
| **검증 강제** | **✅ v1.7.1 구현** | ❌ 없음 | ❌ 없음 |
|
||
| 계획 단계 | PlanMode 3모드 | 없음 (implicit) | 없음 |
|
||
| 종료 조건 | 도구 호출 없음 | AgentFinishAction | 도구 호출 없음 |
|
||
| 자기 반성 | Self-Reflection 프롬프트 | 없음 | 없음 |
|
||
| 사용자 승인 | UserDecisionCallback | SecurityAnalyzer | 권한 프롬프트 |
|
||
| 컨텍스트 압축 | ContextCondenser | 요약 기반 | 없음 |
|
||
|
||
#### OpenHands 루프 의사코드
|
||
|
||
```python
|
||
# OpenHands: agent.step() = 1 LLM 호출 + 1 도구 실행
|
||
while budget > 0:
|
||
action = agent.step(state) # 1 LLM call
|
||
observation = runtime.run(action) # 1 tool execution
|
||
state.update(action, observation)
|
||
if action == AgentFinishAction:
|
||
break
|
||
# 검증 없음 — LLM이 자율적으로 다음 반복에서 확인 여부 결정
|
||
```
|
||
|
||
#### AX Copilot 검증 강제 루프 (개선 후)
|
||
|
||
```
|
||
반복 1: LLM → "계획 수립" + file_read → 기존 파일 확인
|
||
반복 2: LLM → "실행" + html_create → 문서 생성
|
||
↳ ★검증 LLM 호출★ → file_read로 내용 확인 → 수정 필요 시 도구 호출
|
||
반복 3: LLM → 완료 응답 또는 추가 수정
|
||
```
|
||
|
||
### 구현 상세
|
||
|
||
| 구성요소 | 파일 | 내용 |
|
||
|----------|------|------|
|
||
| 설정 | `AppSettings.cs` | `EnablePostToolVerification` (bool, 기본 false) |
|
||
| UI | `SettingsWindow.xaml` | "고품질 문서" 섹션에 토글 추가 |
|
||
| 바인딩 | `SettingsViewModel.cs` | Load/Save 매핑 |
|
||
| 엔진 | `AgentLoopService.cs` | `RunPostToolVerificationAsync()` + `IsDocumentCreationTool()` |
|
||
|
||
#### 검증 대상 도구
|
||
|
||
| 도구명 | 설명 |
|
||
|--------|------|
|
||
| `file_write` | 일반 파일 쓰기 |
|
||
| `docx_create` | Word 문서 생성 |
|
||
| `html_create` | HTML 보고서 생성 |
|
||
| `excel_create` | Excel 파일 생성 |
|
||
| `csv_create` | CSV 파일 생성 |
|
||
| `script_create` | Python 스크립트 생성 |
|
||
| `pptx_create` | PowerPoint 생성 |
|
||
|
||
#### 검증 프롬프트 구조
|
||
|
||
검증 LLM 호출 시 다음 4단계 체크리스트를 주입:
|
||
1. `file_read`로 생성된 파일 내용 읽기
|
||
2. 사용자 요청 대비 완전성 확인
|
||
3. 구조·형식 올바름 확인
|
||
4. 문제 발견 시 즉시 수정 도구 호출
|
||
|
||
### 효과
|
||
|
||
| 관점 | Before (v1.7.0) | After (v1.7.1) |
|
||
|------|-----------------|-----------------|
|
||
| 문서 생성 후 확인 | LLM 자율 판단 (대부분 생략) | 강제 확인 + 수정 |
|
||
| 반복당 최소 LLM 호출 | 1회 | 문서 생성 시 2회 |
|
||
| 누락 섹션 | 사용자가 직접 발견 | AI가 자동 감지 |
|
||
| 업계 비교 | OpenHands와 동일 | **차별화 포인트** |
|
||
|
||
---
|
||
|
||
## 양식 기반 문서 생성 (Template Mode)
|
||
|
||
> **상태**: 구현 완료
|
||
> **적용일**: 2026-03-30
|
||
> **대상 스킬**: docx-creator, pptx-creator, xlsx-analyzer
|
||
|
||
### 개요
|
||
|
||
작업 폴더에 양식 파일(`.docx`, `.pptx`, `.xlsx`)을 넣어두면, 런타임 고급 스킬(`/docx-creator`, `/pptx-creator`, `/xlsx-analyzer`) 실행 시 **양식의 스타일·레이아웃을 자동으로 상속**하여 문서를 생성합니다.
|
||
|
||
### 동작 원리
|
||
|
||
```
|
||
사용자: "이번 달 보고서 작성해줘"
|
||
|
||
┌─ 스킬 시스템 프롬프트 ─────────────────────┐
|
||
│ 1. folder_map → 작업 폴더 스캔 │
|
||
│ 2. 양식 후보 탐색 (파일명 키워드 매칭) │
|
||
│ 3. 양식 발견 → document_read로 구조 파악 │
|
||
│ 4. Document('양식.docx') 기반 생성 │
|
||
│ (양식 없으면 → Document() 새 문서) │
|
||
└──────────────────────────────────────────┘
|
||
```
|
||
|
||
### 양식 감지 키워드
|
||
|
||
파일명에 다음 키워드가 포함되면 양식으로 자동 인식:
|
||
|
||
| 키워드 | 예시 파일명 |
|
||
|--------|------------|
|
||
| 양식 | `월간보고_양식.docx` |
|
||
| template | `report_template.pptx` |
|
||
| 서식 | `서식_공문.docx` |
|
||
| 표준 | `표준_발표자료.pptx` |
|
||
| 기본 | `기본양식.xlsx` |
|
||
|
||
사용자가 명시적으로 파일명을 지정하면 키워드 무관하게 해당 파일을 양식으로 사용합니다.
|
||
|
||
### 스킬별 양식 활용 방식
|
||
|
||
| 스킬 | 양식 로드 | 상속되는 요소 |
|
||
|------|----------|-------------|
|
||
| **docx-creator** | `Document('양식.docx')` | 스타일, 머리글/바닥글, 로고, 페이지 설정, 글꼴 |
|
||
| **pptx-creator** | `Presentation('양식.pptx')` | 마스터 슬라이드, 배경, 색 테마, 폰트, 레이아웃 |
|
||
| **xlsx-analyzer** | `load_workbook('양식.xlsx')` | 셀 서식, 병합, 테두리, 열 너비, 차트 영역 |
|
||
|
||
### 구현 방식
|
||
|
||
C# 코드 변경 없이 **스킬 프롬프트(`.skill.md`)만 확장**하여 구현:
|
||
|
||
- `skills/docx-creator.skill.md` — `## 양식 활용 (템플릿 모드)` 섹션 추가
|
||
- `skills/pptx-creator.skill.md` — `## 양식 활용 (마스터 슬라이드 템플릿)` 섹션 추가
|
||
- `skills/xlsx-analyzer.skill.md` — `## 양식 활용 (Excel 보고서 템플릿)` 섹션 추가
|
||
|
||
각 스킬의 Python 스크립트 템플릿에 양식 자동 감지 로직 포함:
|
||
|
||
```python
|
||
template_keywords = ['양식', 'template', '서식', '표준', '기본']
|
||
template_file = None
|
||
for f in os.listdir('.'):
|
||
if f.endswith('.docx') and any(kw in f.lower() for kw in template_keywords):
|
||
template_file = f
|
||
break
|
||
|
||
if template_file:
|
||
doc = Document(template_file) # 양식 스타일 상속
|
||
else:
|
||
doc = Document() # 새 문서
|
||
```
|
||
|
||
### 사내 활용 시나리오
|
||
|
||
| 시나리오 | 양식 파일 | 결과 |
|
||
|---------|----------|------|
|
||
| 월간 보고서 | `월간보고_양식.docx` (사내 표준 헤더·로고·페이지 설정) | 동일 규격의 보고서 자동 생성 |
|
||
| 팀 발표 | `팀발표_양식.pptx` (부서 마스터 슬라이드) | 부서 디자인 유지 + 새 내용 |
|
||
| 수율 분석 | `수율보고_양식.xlsx` (셀 서식·차트 영역 설정) | 양식에 데이터만 삽입 |
|
||
| 공문 작성 | `공문_서식.docx` (사내 공문 규격) | 규격 유지 + 내용 작성 |
|
||
|
||
### 향후 고도화
|
||
|
||
| 단계 | 내용 | 공수 |
|
||
|------|------|------|
|
||
| 현재 (v1.6.1) | 스킬 프롬프트에서 양식 자동 감지 안내 | 완료 |
|
||
| 다음 | 시스템 프롬프트에 양식 목록 자동 주입 (BuildCoworkSystemPrompt) | 낮음 |
|
||
| 장기 | `.ax/templates/` 공용 양식 폴더 + 프로젝트 규칙에서 기본 양식 지정 | 중간 |
|
||
|
||
---
|
||
|
||
## 2026-04-04 진행 기록 (AX Agent 명령/도구 보강)
|
||
|
||
### 1. 슬래시 명령 체계 보강
|
||
- `/chrome`: 인자 미입력 시 MCP 런타임 진단, 인자 입력 시 브라우저 작업 실행 경로로 라우팅.
|
||
- `/mcp`: `status`, `enable|disable`, `reconnect` 동작 정리 및 상태 라벨 표준화.
|
||
- `/settings`: `model|permissions|mcp|theme` 하위 액션 지원.
|
||
- `/permissions`: `ask|auto|deny|status` 하위 액션 지원.
|
||
- `/verify`: Cowork/Code 탭 전용 검증 프롬프트 경로로 고정.
|
||
- `/commit`: 승인 기반 커밋 실행 + `files:path1,path2 :: message` 부분 커밋 지원.
|
||
- `/compact`: 수동 컨텍스트 압축 명령 유지 및 slash 팝업 힌트/도움말 반영.
|
||
|
||
### 2. 도구/권한 정책 정렬
|
||
- `GitTool`의 commit 경로에서 레거시 비활성 응답(`커밋 비활성`) 제거.
|
||
- 세션 단위 MCP 활성/비활성 오버라이드 적용(영구 설정 미오염).
|
||
- `/chrome` 진단 실패 시 `/mcp reconnect all` 자동 1회 재시도 후 상태 재평가.
|
||
|
||
### 3. 테스트 보강
|
||
- `ChatWindowSlashPolicyTests`:
|
||
- 슬래시 파서(`ParseGenericAction`, `ParseMcpAction`) 검증.
|
||
- `/verify` 시스템 프롬프트 필수 섹션 검증.
|
||
- MCP 상태 라벨 매핑 검증.
|
||
- `/commit` 입력 파서 검증.
|
||
- `AgentParityToolsTests`:
|
||
- `git_tool commit` 레거시 비활성 메시지 회귀 방지 테스트 추가.
|
||
|
||
### 4. 품질 게이트 결과
|
||
- `dotnet build AxCopilot.sln` 통과 (경고 0, 오류 0).
|
||
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj` 통과.
|
||
- 기준 시점 전체 테스트: 403 passed, 0 failed.
|
||
|
||
|
||
## 2026-04-04 추가 진행 기록 (연속 실행 2차)
|
||
|
||
### A. /mcp 명령 확장
|
||
- `/mcp add <name> :: stdio <command> [args...]` 지원.
|
||
- `/mcp add <name> :: sse <url>` 지원.
|
||
- `/mcp remove <name|all>` 지원.
|
||
- `/mcp reset` 지원 (세션 오버라이드 초기화).
|
||
- 상태/도움말 문구를 확장 명령 기준으로 업데이트.
|
||
|
||
### B. Agentic loop 복구 가이드 강화
|
||
- 미등록/비허용 도구 복구 프롬프트에 `tool_search` 우선 사용 지침 추가.
|
||
- 반복 실패 중단 응답에도 `tool_search` 기반 재시도 루트를 명시.
|
||
|
||
### C. UI/UX 단순화(슬래시 팝업 힌트)
|
||
- `agentUiExpressionLevel`(`rich|balanced|simple`)에 따라 슬래시 팝업 힌트 밀도 조정.
|
||
- simple: 최소 정보, rich: 추천 명령 포함, balanced: 기본 정보.
|
||
|
||
### D. 설정값-실동작 점검(핵심)
|
||
- `MaxRetryOnError`, `EnableProactiveContextCompact`, `ContextCompactTriggerPercent`, `MaxContextTokens`, `AllowInsecureTls`, `AgentUiExpressionLevel` 항목의
|
||
모델/뷰모델/UI/런타임 참조 경로를 점검하여 동작 연결을 확인.
|
||
|
||
### E. 검증 결과
|
||
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
|
||
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj` 통과 (411 passed, 0 failed).
|
||
|
||
## 2026-04-04 추가 진행 기록 (연속 실행 3차)
|
||
|
||
### /mcp 인증 명령 추가
|
||
- `/mcp login <서버명> <토큰>`: 세션 인증 토큰 설정.
|
||
- `/mcp logout <서버명|all>`: 세션 인증 토큰 제거.
|
||
- `/mcp reset` 시 세션 MCP 활성/비활성 오버라이드와 인증 토큰을 함께 초기화.
|
||
|
||
### 런타임 반영 범위
|
||
- MCP 상태 점검(`/mcp status`)과 Chrome 진단(`/chrome`)에서 세션 토큰을 `MCP_AUTH_TOKEN` 환경변수로 합성 적용.
|
||
- 상태 출력에 `Auth(Session)` 표기 추가.
|
||
|
||
### 테스트 보강
|
||
- `ChatWindowSlashPolicyTests`에 `login/logout` 파서 및 로그인 입력 파서 테스트 추가.
|
||
|
||
### 검증 결과
|
||
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
|
||
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj` 통과 (415 passed, 0 failed).
|
||
|
||
## 2026-04-04 추가 진행 기록 (연속 실행 4차: 계획 1~4)
|
||
|
||
### 1) 권한/도구 UX 통합
|
||
- `/permissions`, `/allowed-tools`, `/settings permissions`가 동일한 권한 상태 모델을 사용하도록 정렬.
|
||
- 공통 처리 추가:
|
||
- 권한 모드 적용 헬퍼(`ask|auto|deny`)
|
||
- 권한 상태 요약 텍스트 생성
|
||
- 권한 팝업 오픈 경로 통일
|
||
- `/allowed-tools`에서도 `ask|auto|deny|status`를 동일하게 지원.
|
||
|
||
### 2) 루프 복구 테스트 확대
|
||
- `AgentLoopCodeQualityTests`에 unknown/disallowed/no-progress 혼합 관점 테스트 추가.
|
||
- unknown/disallowed 중단 응답에 `tool_search` 가이드가 유지되는지 회귀 검증.
|
||
|
||
### 3) 좌측 패널 단순화 2차
|
||
- 표현 레벨 기준 정리:
|
||
- `rich`: 실패 필터 노출
|
||
- `balanced/simple`: 실패 필터 비노출
|
||
- Quick strip 표시 조건도 위 정책과 연동해 실패 버튼이 숨겨진 모드에서 과밀 표시를 방지.
|
||
|
||
### 4) 품질 게이트
|
||
- `dotnet build src/AxCopilot/AxCopilot.csproj` 통과 (경고 0, 오류 0).
|
||
- `dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj` 통과 (421 passed, 0 failed).
|