# task-1158.1 완료 보고서 — 기록 탭 이미지 파일 클릭 링크 수정

**작업자**: 헤르메스 (개발1팀장)
**팀원**: 이리스(프론트엔드), 불칸(백엔드), 아르고스(테스터)
**작업일**: 2026-03-28

---

## SCQA

**S**: 대시보드 기록 탭에서 보고서 내 파일 경로(예: `memory/reports/task-100.md`)가 클릭 가능한 링크로 변환되어 FileViewerModal에서 열리는 기능이 이미 구현되어 있다.

**C**: 보고서 테이블에 이미지 파일명(예: `recruiting-angleA-meta-1080x1080-slide1-v1.png`)이 경로 없이 파일명만 표시되며, 기존 `pathPattern` 정규식은 디렉토리 구분자 `/`를 필수로 요구하여 이 파일명들이 클릭 가능한 링크로 변환되지 않는다. 저장 경로 정보(`/home/jay/workspace/output/meta-ads/angle-A/`)는 보고서 하단에 별도 존재한다.

**Q**: 경로 없는 이미지 파일명도 클릭 시 해당 이미지를 모달에서 표시할 수 있는가?

**A**: `linkifyFilePaths` 함수를 2-pass 구조로 확장하여 (1) 기존 경로 포함 파일, (2) 경로 없는 이미지 파일명을 모두 링크화. 클릭 시 보고서 HTML에서 "저장 경로" 텍스트를 파싱하여 전체 경로를 조합하고, fallback으로 `/api/file-search` API를 호출. pytest 7건 전체 통과, pyright 에러 0건, 테스트 assertion 23건 PASS.

---

## 수정 파일

- `/home/jay/workspace/dashboard/components/utils.js` — `linkifyFilePaths` 함수 2-pass 확장, 클릭 핸들러 저장 경로 파싱 추가
- `/home/jay/workspace/dashboard/server.py` — `GET /api/file-search` 엔드포인트 추가

## 변경 상세

### 1. linkifyFilePaths 2-pass 구조 (utils.js:534-565)
- **Pass 1** (기존 유지): `pathPattern` — 경로 포함 파일(`dir/file.ext`) 링크화
- **Pass 2** (신규): `imageFilenamePattern` — 경로 없는 이미지 파일명(`*.png|jpg|jpeg|gif|svg|webp`) 링크화, `data-filename-only="true"` 속성 추가
- 공통 HTML 파싱 로직을 `applyPattern()` 내부 함수로 추출하여 DRY 유지

### 2. 클릭 핸들러 분기 (utils.js:667-698)
- `data-filename-only="true"`인 링크 클릭 시:
  1. 보고서 HTML에서 "저장 경로" 파싱 (정규식: `<strong>` 태그 포함 형태 지원)
  2. 저장 경로 + 파일명 조합 → workspace prefix 제거 → 상대 경로로 `_showFileViewer` 호출
  3. 저장 경로 파싱 실패 시 `/api/file-search` API fallback

### 3. 서버 파일 검색 API (server.py:2917-2962)
- `GET /api/file-search?name=<filename>` — `output/` 하위 재귀 검색
- 보안: path traversal 차단, 확장자 화이트리스트, workspace 범위 검증, 파일명에 `/` 금지
- 최대 10건 반환, 응답: `{"results": ["output/meta-ads/angle-A/file.png"]}`

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **저장 경로 정규식 `<strong>` 태그 미처리 버그** — 정규식에 `(?:<[^>]+>)*` 패턴 추가하여 HTML 태그 건너뛰기 지원 (utils.js:678)
2. **서버 API 응답 형식 불일치** — 프론트엔드에서 `data.path` 대신 `data?.results?.[0]` 으로 수정 (utils.js:695)
3. **서버 404 응답 Pyright 에러** — 수동 `send_response(404)` 대신 `_send_error_response(404, ...)` 패턴 통일 (server.py:2959)

## 검증 결과

- **단위 테스트**: 23개 assertion 전체 PASS (test_linkify.js)
  - 기존 경로 링크화, 이미지 파일명 링크화, `<a>` 내부 스킵, 유니코드 × 처리, 저장 경로 파싱, 경로 조합/prefix 제거
- **pytest**: 7건 PASS (test_server.py, 0.26s)
- **pyright**: 0 errors, 0 warnings
- **style_check**: WARN (black 포매팅 — 기존 코드와 동일 수준)

## QC 자동 검증

```json
{
  "task_id": "task-1158.1",
  "test_runner": "PASS (7 passed in 0.26s)",
  "pyright_check": "PASS (0 errors)",
  "style_check": "WARN (black)",
  "data_integrity": "PASS"
}
```
