Skip to content

fix: 코드 리뷰 지적사항 일괄 수정 (Critical 5건 · High 3건 · Medium 다수) - #11

Merged
Jeongwoo Choi (lanslote) merged 2 commits into
mainfrom
lanslote-ideal-broccoli
Jul 25, 2026
Merged

fix: 코드 리뷰 지적사항 일괄 수정 (Critical 5건 · High 3건 · Medium 다수)#11
Jeongwoo Choi (lanslote) merged 2 commits into
mainfrom
lanslote-ideal-broccoli

Conversation

@lanslote

Copy link
Copy Markdown
Collaborator

개요

전체 코드베이스(src/main, src/preload, src/renderer, src/shared) 리뷰에서 발견된 CRITICAL 5건 / HIGH 3건 / MEDIUM 다수 결함을 수정하고, 재발 방지용 회귀 테스트와 린트 게이트를 추가했습니다.


🔴 CRITICAL

# 문제 수정
C-1 Conversations 페이지가 가짜 데이터를 렌더링 — 실제 수집 결과 대신 하드코딩된 mock Copilot 대화(2,491자)를 화면에 표시. 감사·규정준수 도구에서 조작된 데이터가 실제처럼 보이는 치명적 결함 mock 전면 삭제. 로드 실패/데이터 없음 시 명시적 오류 상태 표시, 언마운트 가드 추가
C-2 HTTP 타임아웃 부재 — Graph/Dataverse/Consumption/eDiscovery 전 경로에 타임아웃·재시도가 없어 응답 지연 시 수집이 영구 정지 공용 클라이언트 src/main/http.ts 도입: 타임아웃(기본 60s, 다운로드 20m), 429/5xx 지수 백오프(Retry-After 초·HTTP-date 모두 파싱), 401 1회 재인증, 호출자 취소 신호 결합. src/ 내 raw fetch( 0건
C-3 재수집 시 에이전트 귀속 정보 소실upsertThreadsINSERT OR REPLACE(SQLite에서는 DELETE+INSERT) 사용 → 수집할 때마다 agent_key/agent_id/agent_name 컬럼이 NULL로 초기화. 귀속 백필은 프로필당 1회만 실행되므로 영구 손실 INSERT ... ON CONFLICT(id) DO UPDATE SET(수집기 소유 14개 컬럼만 갱신)로 교체 + 회귀 테스트 추가
C-4 단일 인스턴스 잠금 부재 — 여러 프로세스가 같은 SQLite 파일에 동시 쓰기 가능 (DB 손상 위험) requestSingleInstanceLock() + second-instance 시 기존 창 포커스, before-quit 시 WAL 체크포인트/DB close/타이머 정리, unhandledRejection/uncaughtException 핸들러
C-5 eDiscovery ZIP 파서의 ZIP64 미지원 — 4GiB 초과 또는 65,535개 초과 항목 아카이브를 조용히 "빈 결과"로 처리. 대형 테넌트 내보내기가 소리 없이 누락 ZIP64 EOCD locator/record, per-entry ZIP64 extra field(0x0001) 파싱, 경계 검사, 항목별 경고 추가

🟠 HIGH

  • 트랜잭션 부재 — 대량 쓰기 12곳이 행 단위 자동커밋이라 중간 실패 시 부분 반영. 재진입 가능한 transaction<T>() 헬퍼(BEGIN IMMEDIATE)로 래핑. 아울러 busy_timeout=10000, journal_mode=WAL, foreign_keys=ON PRAGMA 적용 및 실제 open 오류를 삼키지 않고 보고하도록 수정.
  • 포털 창 하드닝 미흡 — 외부 링크가 임의 HTTPS 주소로 열릴 수 있었고, 포털 BrowserWindow 4개에 팝업/네비게이션 가드가 없었음. Microsoft/GitHub 도메인 접미사 허용목록(15개), setWindowOpenHandler(비-웹 스킴 차단 + 허용 팝업에 안전한 webPreferences 강제), will-navigate 스킴 검증, will-attach-webview 차단 추가.
  • 조용한 데이터 손실 — 날짜 파싱 실패 시 new Date()(수집 시각)로 대체, 응답이 JSON이 아니면 {}로 격하, 페이지네이션 maxPages 절단 무고지, 손상된 ZIP 항목을 빈 버퍼로 치환. 각각 경고·오류·__created_at_unknown 표식으로 표면화.

🟡 MEDIUM

  • LIKE 검색어의 %, _, \ 미이스케이프 → ESCAPE '\' 적용 (likeNeedle())
  • dateTo 필터가 종료일 하루를 통째로 누락하던 경계 오류 → endOfDay() (4곳)
  • 보안 이벤트 KPI(total/blocked/uniqueUsers/topOperation)가 현재 페이지만 집계 → 필터 전체 집합에 대한 SQL 집계로 교체 + 절단 여부 UI 표시
  • Conversations.tsx의 stale closure 유발 useEffect 의존성 수정 (basePayload useMemo)
  • CSP에서 외부 CDN(jsdelivr) 제거, 폰트를 로컬 번들(pretendard)로 대체
  • 로그 12곳에서 PII 제거(logError), 개발 전용 테스트 하니스(CWT_*_TEST 10개 분기)를 devHarness.ts로 분리하고 !app.isPackaged일 때만 lazy import
  • 하드코딩된 ko-KR 숫자 포맷터 및 한국어 폴백 문자열 → i18n 키로 교체, document.documentElement.lang 동기화

🔧 Tooling / Tests

  • ESLint 9 flat config 신규 도입 (typescript-eslint, react-hooks/exhaustive-deps: error, no-explicit-any: error, no-console, eqeqeq) — 현재 0 problems. CI에 npm run lint 단계 추가
  • electron-builder 25 → 26.15.3 — critical node-tar 취약점 해소, 프로덕션 의존성 취약점 0건
  • 회귀 테스트 추가: HTTP 클라이언트 14 · ZIP64 파서 6 · 스레드 귀속 보존 4 · CSV 직렬화 5 · 창 보안 정책 보강 → 38 → 69 테스트 (13 파일)
  • README/package.json의 Node 요구 버전 20+ → 22+ 정정 (node:sqlite 필요), engines 필드 추가

✅ 검증

npm run lint      → 0 problems
npm run typecheck → PASS
npm test          → 13 files / 69 tests PASS
npm run build     → PASS
npm audit --omit=dev → 0 vulnerabilities

📋 후속 과제 (의도적으로 이번 PR 범위 밖)

  1. 메인 프로세스 i18n — 메인 프로세스에 하드코딩된 한국어 문자열 약 255개 × 5개 언어. 기계번역 리스크가 있어 별도 기능 단위 작업 필요
  2. legacy/ 제거 — 2.6MB의 사용되지 않는 Python/웹 코드. README에서 참조 중이라 문서 정리와 함께 진행 필요
  3. tsconfig.json 프로젝트 분리 — main/preload/renderer가 단일 tsconfig를 공유해 DOM 타입이 메인 프로세스에도 노출됨

Jeongwoo Choi (lanslote) and others added 2 commits July 25, 2026 18:10
전체 코드 리뷰(main/preload/renderer/shared) 결과 확인된 데이터 정합성,
보안, 안정성 결함을 수정하고 회귀 테스트와 린트 게이트를 추가한다.

CRITICAL
- Conversations 페이지가 실제 수집 데이터 대신 하드코딩된 가짜 Copilot
  대화("mock thread")를 렌더링하던 문제 제거. 이제 로드 실패/미존재 시
  오류 상태를 표시한다.
- 모든 HTTP 호출에 타임아웃이 없어 Graph/Dataverse 응답 지연 시 수집이
  무한 대기하던 문제 해결. 공용 클라이언트(src/main/http.ts)를 도입해
  타임아웃, 429/5xx 백오프(Retry-After 초·HTTP-date 모두 지원), 401 1회
  재인증, 호출자 취소 신호 결합을 일원화하고 src/ 내 raw fetch를 전부 제거.
- upsertThreads가 INSERT OR REPLACE(SQLite에서 DELETE+INSERT)를 사용해
  재수집 때마다 agent_key/agent_id/agent_name 귀속 정보가 소실되던 문제를
  ON CONFLICT DO UPDATE로 수정.
- 단일 인스턴스 잠금이 없어 같은 SQLite 파일을 여러 프로세스가 동시에
  쓰던 문제 해결. requestSingleInstanceLock + 기존 창 포커스, 종료 시
  WAL 체크포인트/DB 정리, 전역 예외 핸들러 추가.
- eDiscovery 내보내기 ZIP 파서가 ZIP64를 지원하지 않아 4GiB 초과 또는
  65,535개 초과 항목 아카이브를 조용히 빈 결과로 처리하던 문제 수정.

HIGH
- 대량 쓰기 12곳을 트랜잭션으로 묶고(재진입 가능 transaction 헬퍼),
  busy_timeout/WAL/foreign_keys PRAGMA 및 실제 open 오류 보고 추가.
- 포털 창 하드닝: 외부 링크 허용 도메인 목록 적용, setWindowOpenHandler /
  will-navigate 스킴 검증, will-attach-webview 차단.
- 조용한 데이터 손실 제거: 날짜 파싱 실패·응답 비-JSON·페이지네이션
  절단·ZIP 항목 손상을 각각 경고/오류로 표면화.

MEDIUM
- LIKE 검색어의 %, _, \ 이스케이프 처리(ESCAPE 절 사용).
- dateTo 필터가 해당 일자 마지막 하루를 누락하던 경계 오류 수정.
- 보안 이벤트 KPI를 페이지가 아닌 필터 전체 집합에 대해 SQL로 집계하고
  절단 여부를 UI에 표시.
- Conversations의 stale closure 유발 useEffect 의존성 수정.
- CSP에서 외부 CDN 제거하고 폰트를 로컬 번들로 대체.
- 로그에서 PII 제거, 개발 전용 테스트 하니스를 별도 모듈로 분리해
  패키징 빌드에서 로드되지 않도록 변경.

Tooling / tests
- ESLint 9 flat config 도입(react-hooks/exhaustive-deps, no-explicit-any
  등 error) 및 CI에 lint 단계 추가.
- electron-builder 25 → 26으로 올려 critical node-tar 취약점 해소.
- 회귀 테스트 추가: http 클라이언트(14), ZIP64 파서(6), 스레드 귀속
  보존(4), CSV 직렬화(5). 총 38 → 69 테스트.
- README/package.json의 Node 요구 버전을 22+로 정정(node:sqlite 필요).

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
npm 11이 vitest의 중첩 esbuild@0.28.1 서브트리를 optional이 아닌
extraneous로 표기해 CI의 `npm ci`가 EBADPLATFORM/Missing 오류로
실패하던 문제 해결. CI(Node 22)와 동일한 npm 10으로 lockfile을
재생성해 플랫폼별 optional 패키지 49개의 optional 플래그를 복원.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@lanslote
Jeongwoo Choi (lanslote) merged commit bfed60c into main Jul 25, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant