---
title: "작업보고 — 코치노트 AI RC2 spec02 운동데이터 주입 엔진"
category: "workreport"
document_type: "작업보고"
source_status: "generated"
knowledge_group: "03_history"
priority: "High"
purpose: "코치노트 AI v1.0-rc2 순차 분할 구현 중 2/6 담당분(spec_rc2_02_data_injection) 완료 기록. AI가 최근 14일만 보는 얕은 코치가 되지 않도록 운동데이터 주입(injection) 엔진을 구현 — 14일 스냅샷 + 전체 여정 요약 + 반자동 확장조회 + 반복패턴 압축. spec01 주입 슬롯 위에 얹는 클라이언트 집계 엔진(SQL 없음, spec01 산출물 무수정)."
read_when: ["최신상태복구","코치노트AI·RC2","데이터주입·요약엔진"]
updated: "2026-06-06"
work_timestamp: "20260606_112347"
context: "달록본레포CC (D:\\dallog\\dallog_git)"
source_of_truth: "https://dallog-tools.hansbridge.co.kr/knowledge/"
---

# 작업보고 — 코치노트 AI RC2 spec02 (운동데이터 주입 엔진)

> RC2 코치노트 AI 순차 분할 구현 중 **2/6 (spec_rc2_02_data_injection)** 담당 스레드 완료 기록. spec01(foundation) 산출물을 인계받아 그 위에 운동데이터 주입(injection·운동기록을 글자로 정리해 AI 입력에 끼워넣기) 엔진을 얹고, spec03(guardrail·system prompt)으로 인계했다.
> **용어 병기** — injection/운동데이터 주입, snapshot/운동기록 요약본, compression/반복패턴 압축, prompt caching/프롬프트 캐싱, RLS/행 수준 접근제어, system prompt/시스템 지시문.

## 목차
- [0. 문서 정보](#0-문서-정보)
- [1. 작업 배경 (왜 했는가)](#1-작업-배경-왜-했는가)
- [2. 적용 기준](#2-적용-기준)
- [3. 구현 범위](#3-구현-범위)
- [4. 수정/신규 파일](#4-수정신규-파일)
- [5. SQL 적용 여부](#5-sql-적용-여부)
- [6. 빌드 결과](#6-빌드-결과)
- [7. 기능 검증 결과 (MCP 브라우징 N/A)](#7-기능-검증-결과-mcp-브라우징-na)
- [8. 명세 대비 구현 완료 여부 (PASS/FAIL)](#8-명세-대비-구현-완료-여부-passfail)
- [9. 미구현/보류/축소 의심 항목](#9-미구현보류축소-의심-항목)
- [10. 발견된 이슈와 해결](#10-발견된-이슈와-해결)
- [11. 후속 작업](#11-후속-작업)
- [12. 최종 판단](#12-최종-판단)
- [13. 의사결정 기록 (5요소)](#13-의사결정-기록-5요소)
- [부록. 변경 구조 Before/After](#부록-변경-구조-beforeafter)

---

## 0. 문서 정보

| 항목 | 내용 |
|---|---|
| 작성일 | 2026-06-06 |
| 작업 발생 시점 | 2026-06-06 11:13~11:23 (구현) |
| 담당 작업 단위 | spec_rc2_02_data_injection (운동데이터 주입 엔진), 총 6개 중 2/6 |
| 관련 명세 | go_work/spec_rc2_02_data_injection.md · spec_rc2_00_master_index.md |
| 관련 결정로그 | decision_log_rc2 #8(주입구조) · #9(확장조회·압축) |
| 작성자 | 달록본레포CC (Claude Code Opus 4.8) |

## 1. 작업 배경 (왜 했는가)

코치노트 AI(운동기록 기반 코칭 대화)가 **"최근 14일만 보는 얕은 코치"가 되지 않도록** 운동데이터 주입 엔진을 구현했다.

**사용자 의도·정서(생략 금지)** — 달록의 제품 철학(decision_log #8)은 사용자가 직접 강하게 강조한 그대로다: "전체적으로 내가 어디서부터 어디까지 왔는가, 어디서부터 성장해왔는가, 문제가 생겼다면 어디서부터 잘못됐는가를 따져보기 위해 만든 앱." AI도 이 정신을 따라 최근 흐름과 장기 여정을 함께 봐야 한다. 그래서 두 극단을 모두 배제하고 균형점을 코드로 고정했다.

- ❌ 최근 14일만 주입 (얕은 코치 — 철학 위배)
- ❌ 전체 원자료 매번 주입 (토큰·비용·프록시 본문 50KB 한도 위배)
- ✅ **14일 스냅샷 + 전체 여정 요약 + 반자동 확장조회 + 반복패턴 압축**

또 사용자는 본인 기록(체성분 정체·유사 조깅 반복)을 예로 들며 "같은 패턴 반복은 포괄 압축 가능, 돈도 막고 성능도 낫다"고 직접 제안했다(decision_log #9). 원자료를 많이 먹인다고 답이 좋아지는 게 아니라 의미 있는 구조로 압축할 때 좋아진다는 통찰을 압축 엔진에 반영했다.

## 2. 적용 기준

| 구분 | 내용 |
|---|---|
| 명세 | §1 3층 구조 · §2.1 14일 5항목 · §2.2 여정 7축 · §3 반자동 확장 · §4 압축+이벤트 · §5 완료 정의 |
| 결정로그 | #8(14일+여정 기본, 원자료 상시주입 배제) · #9(반자동 트리거·"애매하면 확인" 기본값·반복패턴 압축) |
| 금지사항 | 14일만 축소 금지 · 원자료 무차별 주입 금지 · 모델 하드코딩 금지 · spec01 로그/원가 재설계 금지 · chat-proxy 구조 유지 · brief-proxy 훼손 금지 · 대화 원문 저장 테이블 임의 생성 금지(spec04) · git add/commit/push 금지 · 마이그레이션 자동 적용 금지 |

## 3. 구현 범위

| 구분 | 구현 내용 | 관련 파일 | 상태 |
|---|---|---|---|
| ① 14일 스냅샷 | 체성분 변화·러닝(횟수·총거리·평균페이스·심박·케이던스)·근력 수행량·통증/회복 메모·루틴 변경 5항목 | snapshot.ts | 완료 |
| ② 전체 여정 7축 | 시작점·현재위치·누적변화·최고/최저·정체구간·통증/부상 이벤트·큰 루틴 변경 | journey.ts | 완료 |
| ③ 반자동 확장조회(판정) | auto(기간·날짜 지정)/confirm(모호·추적성)/none rule-based | expansion.ts | 완료 |
| ③ 반자동 확장조회(상세도) | 1~7일 상세 / 8~31일 일별요약+이벤트 / 1~3개월 주간요약+변화점 / 전체 월별요약+이벤트 | expansion.ts | 완료 |
| ④ 반복패턴 압축+이벤트 | run_type별 패턴·체중 정체구간 압축 + 통증/기록/루틴/급변 변화점 별도 표시 | compression.ts | 완료 |
| 데이터 소스 | 기존 테이블 타입드 fetch(기간 인자·병렬·RLS 본인만) | exerciseData.ts | 완료 |
| spec01 슬롯 연결 | buildInjectionBlock() 결과 → assembleCoachChat의 injectionBlock(캐싱 제외 영역) | injection.ts | 완료 |

## 4. 수정/신규 파일

전부 신규 추가(`src/lib/coachChat/`). **spec01 산출물·본레포 기존 파일 단 한 줄도 수정 안 함.**

| 파일 | 역할 |
|---|---|
| exerciseData.ts | 운동기록 타입드 fetch 계층(공유 데이터 소스) |
| compression.ts | 반복패턴 압축·변화점 이벤트·날짜/수치 공용 유틸(분석 수학 허브) |
| snapshot.ts | 14일 스냅샷 5항목 빌더 |
| journey.ts | 전체 여정 7축 이력카드 빌더 |
| expansion.ts | 반자동 트리거 판정 + 기간별 4단계 확장조회 |
| injection.ts | 3층 주입 오케스트레이터 + spec01 슬롯 연결 + 확장조회 해소 API |

## 5. SQL 적용 여부

**N/A.** 주입 엔진은 기존 테이블(body_records·running_logs·strength_logs/exercises/sets·coach_notes)만 읽는다. 신규 테이블·RPC·마이그레이션 없음. 집계·압축은 클라이언트 수행(spec01 "계산은 클라이언트, DB는 누락방지·감사" 철학 일관). `migrations/2026-06-06_coachchat_foundation.sql`은 spec01 산출물로 spec02 소관 아님.

## 6. 빌드 결과

| 항목 | 결과 |
|---|---|
| npm run build (tsc strict + vite) | ✅ PASS (~3s) |
| 신규 모듈 타입 오류 | 0건 |
| 경고 | 청크 500KB 경고 — 기존부터 존재, 순수 lib 코드와 무관 |

## 7. 기능 검증 결과 (MCP 브라우징 N/A)

spec02는 **UI 화면 없는 순수 로직 단계** → MCP 브라우징 테스트(MCP browsing test) **N/A**. 함수·타입·빌드 검증으로 대체.

| 검증 항목 | 결과 | 근거 |
|---|---|---|
| MCP 브라우징 테스트 | N/A | UI 없음 — 화면 검증은 spec06 |
| 타입·빌드 | PASS | npm run build |
| 반복패턴 압축·정체구간·변화점 이벤트(4종) | PASS | vitest mock |
| 반자동 판정 auto/confirm/none(7케이스) | PASS | vitest mock |
| 명확 범위 파싱("5월 전체"→05-01~05-31 등) | PASS | vitest mock |
| 기간별 상세도 4단계 | PASS | vitest mock |
| 14일 스냅샷 5항목 / 여정 7축 | PASS | vitest mock |
| spec01 통합(고정 system 무가변·주입블록 messages 앞단) | PASS | vitest mock |

**검증 증거 한계(정직 고지)** — 함수 검증 임시 vitest(10건 PASS) 후 산출물 오염 방지로 삭제. 재실행 가능 아티팩트는 빌드뿐. Supabase 실데이터 런타임 검증은 채팅 UI가 붙는 spec06 통합 시점에 수행.

## 8. 명세 대비 구현 완료 여부 (PASS/FAIL)

| 명세 요구사항 | 판정 | 근거 |
|---|---|---|
| §1 기본 주입 3층(14일+여정 함께) | PASS | injection.buildBaseInjection |
| §2.1 14일 스냅샷 5항목 | PASS | snapshot.ts |
| §2.2 전체 여정 7축 | PASS | journey.ts |
| §3.1 반자동 트리거(명확=자동/애매=확인) | PASS | expansion.classifyExpansionRequest |
| §3.1 "명확" 기본값(기간·날짜 직접 지정만 자동) | PASS | rule-based 날짜파싱 |
| §3.1 키워드 범위(운동·체성분·러닝·근력·회복) | PASS | fetch 대상 테이블 한정 |
| §3.2 기간별 상세도 4단계 | PASS | expansion.buildExpansionView |
| §4 반복패턴 압축 | PASS | compression.compressRuns/detectPlateaus |
| §4 변화점 이벤트 별도 표시 | PASS | compression.detectEvents |
| §4 확장조회 원자료 일자별 전부 나열 배제 | PASS | 8일+ 단계는 요약/이벤트만 |
| §5 완료정의: 매 대화 14일+여정 함께 주입 | PASS | buildInjectionBlock |

**전체: 11/11 PASS (구현 + 단위 검증).** 통합(런타임 실데이터)은 spec06 소관.

## 9. 미구현/보류/축소 의심 항목

**명세 축소 없음.** 아래는 명세상 층위 분리로 후속에 연결되는 정상 항목.

| 항목 | 상태 | 이유 | 후속 |
|---|---|---|---|
| 확장조회 "사용자 확인" UI(버튼/모달)·클릭 와이어링 | 후속 | 판정·데이터(엔진) vs UI 노출(화면) 층위 분리(decision_log #9 "모순 아님") | spec06 |
| system prompt "확장 필요 시 확인 요청" 톤 지시문 | 후속 | 시스템 지시문 전문은 spec03 소관 | spec03 |
| Supabase 실데이터 e2e 검증 | 후속 | 채팅 UI 미존재 단계 | spec06 |

## 10. 발견된 이슈와 해결

| 이슈 | 원인 | 해결 |
|---|---|---|
| 빌드 타입 오류 TS2339 4건 (`Property 'order' does not exist on type 'never'`) | applyRange 제네릭 헬퍼가 Supabase 쿼리 빌더 체이닝 타입을 never로 붕괴 | 제네릭 헬퍼 제거 → 각 fetch에 .gte/.lte 인라인 적용, 빌더 체인 타입 보존, 재빌드 PASS |

## 11. 후속 작업

| 후속 | 이어받을 내용 | 담당 |
|---|---|---|
| spec_rc2_03 | FIXED_SYSTEM_PROMPT 전문 교체 + 메모리 프로필 생성 + "확장 필요 시 확인" 톤. injectionBlock/memoryProfile 슬롯 수신 | spec03 스레드 |
| spec_rc2_06 | confirm 확인 UI + confirmExpansion(range) 호출 + 채팅 화면이 buildInjectionBlock 호출 | spec06 스레드 |

## 12. 최종 판단

| 판단 | 결론 |
|---|---|
| 완료로 볼 수 있는가 | 예 — 명세 11/11 구현+단위검증 PASS, 빌드 PASS, 축소 없음 |
| Phase0 종료 영향 | 핵심 주입 엔진 완료. 런타임 검증은 spec06 통합 시점에 함께 닫혀야 Phase0 전체 완결 |
| 사용자 확인 필요 | spec02 단독으로는 불요. RC2 전체 KB 일괄 편입 시 사용자 승인 절차 |

## 13. 의사결정 기록 (5요소)

| 결정 | 선택된 안 | 배제된 대안 | 선택 이유 | 사용자 의견·정서 | 재검토 조건 |
|---|---|---|---|---|---|
| 집계 위치 | 클라이언트 집계(SQL 없음) | 서버 RPC 집계(service_role 필요) | spec01 "계산은 클라이언트·RLS 본인만" 일관 | 보안 우선·책임 범위 처음부터 | 전체기간 조회 부하 시 |
| 확장조회 판정 | rule-based 날짜파싱 | LLM 자동분류 | Phase0 기본값(#9/C-4)·비용·오판 회피 | "애매하면 사용자 확인" 직접 요구 | Phase1 정교화 시 |
| 확장 확인 UI 위치 | 엔진은 판정·데이터까지, UI는 spec06 | 엔진에서 UI까지 | 명세상 층위 분리 | 작업 편의 축소 경계 | — |
| 압축/이벤트 결합 | 동일 모듈·항상 동반 산출 | 압축만/이벤트만 | 압축 과잉의 변화점 누락 방지(§5 재검토 트리거) | 반복은 압축하되 변화는 놓치지 말 것 | 변화점 누락 보고 시 |

## 부록. 변경 구조 Before/After

**Before (spec01 완료 시점)** — 주입 슬롯 `CoachChatVariableContext.injectionBlock`은 존재하나 **채우는 엔진 없음**(빈 자리).

**After (spec02)** — 엔진이 슬롯을 채운다.

```
운동기록 테이블(body/running/strength/coach_notes)
        │  fetchExerciseData (읽기 전용, RLS 본인만)
        ▼
  injection.ts (오케스트레이터)
   buildBaseInjection = snapshot.ts(14일) + journey.ts(여정)
   + (옵션) expansion.ts(확장조회 4단계)
   ↑ 전부 compression.ts(압축·이벤트·날짜/수치 유틸) 공유
        │  buildInjectionBlock() → 문자열
        ▼
  systemPrompt.ts  assembleCoachChat(conversation, { injectionBlock })
   (캐싱 제외 영역 = messages 앞단. 고정 system 불변 → 캐시 유지)
        ▼
  chatApi.ts → workers/chat-proxy (spec01)
```
