---
title: "📓 작업일지 — 러닝플랜 AI서포트 승격(실데이터 연결) 배치"
category: "worklog"
parent: "Claude Code 작업일지"
updated: "2026-07-08"
priority: "Medium"
purpose: "러닝플랜(데모전용) AI서포트 기능을 목업 상태에서 실데이터 연결 상태로 승격하고, 그 과정에서 발견된 버그(복사 오류·하드코딩 목표·origin 차단·달력 밀림)를 같은 날 연속으로 수정한 작업을 기록."
read_when: ["러닝플랜", "AI서포트", "brief-proxy", "running_plan_support", "demo.dallog.kr"]
document_type: "개발일지"
source_status: "generated"
knowledge_group: "03_history"
work_timestamp: "20260708_112428"
source_of_truth: "https://dallog-tools.hansbridge.co.kr/knowledge/"
context: "달록 본레포(ccy-hansbridge/dallog), 커밋 a4fe97f, e6ef7f8, d1e0f8a, caf0e9f, 69f397b, b86e769, 0ea7cf1, db79f76, 529423b."
---

# 작업일지 — 러닝플랜 AI서포트 승격(실데이터 연결) 배치

> 러닝플랜(데모전용 기능) 화면의 "AI서포트" 카드를 목업 데이터에서 실제 사용자 데이터로 바꾸고, 그 과정에서 나온 버그들을 하루 동안 순서대로 고친 기록입니다.

## 1. 무엇을 했나

### 1-1. AI공유 버튼 워딩·색상 다듬기 (a4fe97f, e6ef7f8, d1e0f8a)
- '복사' 버튼 라벨을 '내 AI공유'로 바꾸고 아이콘을 '스파클(4점별)' SVG로 통일.
- 코치저널 띠밴드 색을 회색에서 메인색(다크 라임/라이트 틸)으로 확정. `.tl-card.tl-card--ai`의 CSS 특이도를 2배로 올려 `index.css`의 shorthand 우선순위를 이겼다.
- 모바일 표 좌우 padding을 0으로 낮춰 대시보드/기록 화면과 여백을 맞춤(~12px).
- '내 AI공유' 복사 시 토스트 안내(`복사되었습니다. 내 AI한테 붙여넣기 후 서포트 조언을 받아보세요`) 추가.

### 1-2. 복사 프롬프트 버그수정 + 서포트 멘션 국면 반영 (caf0e9f)
- 버그: '내 AI공유(복사)' 버튼이 코치 응답문(MOCK_EVAL)을 복사하고 있었음 → 원래 의도인 §프롬프트 구조 마크다운(계획표+최근6주 기록+평가요청 6항목+체성분/메모 블록) 복사로 수정. 외부 LLM에 붙여넣을 입력 프롬프트가 목적.
- 서포트 출력(코치챗) 목업 멘션 예시를 "빌드업 중간 국면"으로 교정(반복 템플릿 회피·자연스러운 시작·수행률 우선·자극성 세션 시기 판단).
- 명세(zz.storage spec)에 "서포트 멘션 생성 로직" 항목 추가: 6주 데이터 취합, 국면 판단(초반/빌드업/막바지·대회직전), 문체, 정보 우선순위.

### 1-3. 승격 — 실데이터 연결 (69f397b)
가장 큰 변경. `RunningPlanPage`를 목업(로컬 상태) 구조에서 실 Supabase 데이터 연결로 전환.
- `run_routines`(플랜) · `running_plan_days`(계획) · `running_logs`(실제·6주 지표) · `running_plan_support`(서포트 내역) 4개 테이블 연결.
- 셀 편집/붙여넣기는 `savePlanDay`로 실저장(낙관적 업데이트 + 실패 시 재동기화).
- 서포트 출력은 `fetchBrief`(brief-proxy)로 명세 로직 프롬프트를 만들어 호출하고, 결과를 내역에 누적(최신이 최상단 펼침, 이전은 접힘, 코치저널 `tl-card` 컴포넌트 재사용).
- `src/lib/runningPlan.ts`에 `loadRecentRunStats`(최근 6주 러닝 지표: 거리·페이스·심박·케이던스·신발), `loadSupportHistory`, `saveSupportMention` 함수 신설.
- 플랜 CRUD(`run_routines`)가 실제로 저장되도록 전환: 새 플랜·삭제·프리셋 적용 실동작. 진입점 3곳(피트로그·설정·기록).
- `running_plan_support` 테이블 마이그레이션(RLS로 본인 데이터만 접근, 내역은 누적 방식). 이 기능 전체는 여전히 `IS_DEMO_HOST` 게이트 아래(데모 전용).
- 과금: 서포트 생성은 코치챗 과금에 편입(데모에서는 차감 없음), 복사는 무료.

```ts
// src/lib/runningPlan.ts — 신설된 최근 러닝 지표 로더
export async function loadRecentRunStats(routineId: string, start: string, end: string): Promise<RunStat[]> {
  const { data } = await supabase.from('running_logs')
    .select('recorded_at, distance_km, pace_sec_per_km, avg_bpm, max_bpm, cadence_spm, shoe, run_type, is_record')
    .eq('routine_id', routineId).gte('recorded_at', start).lte('recorded_at', end)
    .order('recorded_at', { ascending: false })
  ...
}
```

### 1-4. Codex 검수 반영 — 조용한 실패 제거 (b86e769)
- 조회 함수 4종(`loadPlanDays`/`loadActuals`/`loadRecentRunStats`/`loadSupportHistory`)이 에러를 삼키고 빈 데이터처럼 보이던 것을, 에러를 던지고 `reloadPlan`의 catch에서 실패 토스트를 띄우도록 수정.
- 플랜 CRUD 저장 직전에 fresh read를 한 번 더 해서 변경사항을 반영(설정 화면과의 동시 수정으로 인한 lost update 완화).
- `upsertAppSetting` 실패 시 토스트 + 재동기화 추가.
- 서포트 저장이 실패(user_id 없음)할 때도 토스트 안내(`fetchBrief` 호출 비용을 들인 후 결과가 유실되는 것을 막기 위함).
- `fetchBrief`에 `AbortController`로 30초 타임아웃 추가(무응답 시 버튼이 무한정 잠기는 것 방지).
- 새 플랜 생성 시 종료일이 시작일보다 빠른 경우 검증 추가.

### 1-5. 서포트 출력 실패(origin) 해소 + UX 보강 (0ea7cf1)
- 서포트 출력이 실패하던 근본 원인: `brief-proxy`의 `ALLOWED_ORIGINS` 목록에 `demo.dallog.kr`이 빠져 있어 403(forbidden_origin)이 발생. `workers/brief-proxy/index.js`에 도메인 추가 후 재배포.

```diff
   'https://dallog-demo.pages.dev', // 데모/스테이징 — AI 기능(브리프) 검증 허용
+  'https://demo.dallog.kr', // 데모 커스텀 도메인 — AI 기능(브리프·러닝 서포트) 검증 허용
```

- 주범위 "플랜기간 ±2주" 옵션: 플랜에 기간(period)이 없으면 recent8로 fallback되어 버튼이 무반응이었는데, 이 경우 안내 토스트로 "플랜 관리에서 기간 설정" 유도.
- 수정모드(입력/수정 ON) 상태에서 표 전체에 굵은 메인색 아웃라인을 둘러 게시 상태와 시각적으로 구분.

### 1-6. 복사 프롬프트 하드코딩 목표 제거 (db79f76)
- 버그: `buildAiPrompt`에 "목표는 감량기 중…"이라는 예시 문구가 하드코딩되어 있어 모든 사용자·모든 플랜에 동일하게 찍히고 있었음. 이를 제거하고 데이터 블록의 플랜(routine) `goal` 필드를 사용하도록 수정(없으면 생략). 명세에도 "하드코딩 예시 목표 금지" 규칙을 박제.

### 1-7. 서포트 내역 오버레이 모달 (529423b)
- AI카드에는 최신 멘션 1건만 인라인 표시해 표(달력) 위치를 고정.
- 이전 내역은 "이전 내역 보기 (N)" 버튼으로 열리는 오버레이 모달에서 타임라인(코치저널 `tl-card` 접힘/펼침) 스크롤로 확인.
- 모바일/태블릿에서 서포트가 누적될수록 달력이 아래로 무한정 밀리던 문제를 해소. 데스크탑·태블릿·모바일 공통 적용.

## 2. 주요 변경 파일

| 파일 | 내용 |
|---|---|
| `src/pages/RunningPlanPage.tsx` | 목업 → 실데이터 연결 핵심 로직, 프롬프트 조립, 서포트 출력/복사, 오버레이 모달, CRUD |
| `src/lib/runningPlan.ts` | `loadRecentRunStats`/`loadSupportHistory`/`saveSupportMention` 신설 |
| `src/lib/briefApi.ts` | `fetchBrief` 30초 타임아웃(AbortController) |
| `src/components/runningPlan/running-plan.css` | AI공유 버튼·띠밴드 색·모바일 여백·수정모드 아웃라인·모달 스타일 |
| `src/components/runningPlan/RunningPlanTable.tsx` | 수정모드 아웃라인 반영 |
| `workers/brief-proxy/index.js` | `ALLOWED_ORIGINS`에 `demo.dallog.kr` 추가 |

## 3. 관련 커밋

- `a4fe97f` fix(running-plan): AI공유 버튼 워딩·아이콘 + 띠밴드 메인색 확정 (2026-07-08)
- `e6ef7f8` fix(running-plan): 모바일 표 좌우여백을 대시보드·기록모드와 동일하게 (2026-07-08)
- `d1e0f8a` feat(running-plan): '내 AI공유' 복사 시 토스트 안내 추가 (2026-07-08)
- `caf0e9f` fix(running-plan): 내 AI공유 복사 오류수정(응답문→입력프롬프트) + 서포트 멘션 목업 국면 반영 (2026-07-08)
- `69f397b` feat(running-plan): 승격 — 실데이터 연결 + 서포트 실생성/내역누적 + 복사 실프롬프트 (demo) (2026-07-08)
- `b86e769` fix(running-plan): 승격 Codex 검수 반영 — 조용한 실패 제거·플랜CRUD lost update 완화 (2026-07-08)
- `0ea7cf1` fix(running-plan): 서포트 출력 실패(origin) 해소 + 주범위 안내 + 수정모드 아웃라인 (2026-07-08)
- `db79f76` fix(running-plan): 복사 프롬프트 하드코딩 목표 제거 → 플랜 goal 사용 (2026-07-08)
- `529423b` feat(running-plan): 서포트 내역 오버레이 모달 — 누적돼도 표(달력) 안 밀림 (2026-07-08)

## 4. 남은 이슈

커밋 기준 별도로 언급된 남은 이슈 없음. 다만 이 기능 전체가 `IS_DEMO_HOST` 게이트 아래 데모 전용으로 유지되고 있으므로, main(dallog.kr) 승격 여부는 별도 컨펌이 필요한 상태로 보인다(35f9ec6/9e55bbf 커밋 메시지에서도 "컨펌 후 승격" 표현 반복).

