---
title: "260522_C6-settings수정로그Supabase400"
notion_id: "368229620868817698e1d9cf7d8030bc"
notion_url: "https://app.notion.com/p/368229620868817698e1d9cf7d8030bc"
category: "workreport"
parent: "Claude Code 작업보고"
updated: "2026-05-22"
priority: "Low"
purpose: "/settings 수정 로그 진입 시 Supabase 400 에러 해결 (updated_at 컬럼 마이그레이션)"
---

**작업일**: 2026-05-22  
**작업자**: Claude Code (Opus 4.7, 1M context)  
**브랜치**: main  
**작업 시간**: 약 5분
---
## 1. 작업 목표
`/settings → 수정 로그` 진입 시 발생하는 Supabase 400 에러 정식 해결.
### 재현 쿼리 (실패)
```javascript
GET body_records?select=recorded_at,weight_kg,updated_at&order=updated_at.desc&limit=30  → 400
GET running_logs?select=recorded_at,distance_km,updated_at&order=updated_at.desc&limit=30  → 400
```
### 원인
`body_records` / `running_logs` 테이블에 `updated_at` 컬럼이 정의되어 있지 않음. `src/lib/supabase.ts`의 `BodyRecord` / `RunningLog` 타입에도 `created_at`만 있고 `updated_at`은 누락. PostgREST가 존재하지 않는 컬럼을 select·order 요청받으면 400 응답 반환.
---
## 2. 사전 확인
### 작업트리 상태 확인
`git status` 결과 — E-6 Markdown 렌더링 작업의 staged 잔여물 존재 (`src/components/MarkdownBriefRenderer.tsx`, `src/pages/CoachNotes.tsx` 등). 지시사항대로 건드리지 않고 C-6 작업만 추가 진행.
### 원격 동기화
`git fetch`만 실행 (pull 미실행). main과 origin/main은 동기 상태.
### 코드 위치 확인
Grep으로 수정 로그 관련 코드 위치 확인:
```javascript
src/pages/Settings.tsx:1697-1717 — 수정 로그 fetch 로직
src/lib/supabase.ts:8-19 — BodyRecord 타입 정의
src/lib/supabase.ts:21-39 — RunningLog 타입 정의
```
`Settings.tsx:1704-1705` 라인이 정확히 보고된 실패 쿼리를 발사하는 위치:
```typescript
supabase.from('body_records').select('recorded_at,weight_kg,updated_at').order('updated_at', { ascending: false }).limit(30),
supabase.from('running_logs').select('recorded_at,distance_km,updated_at').order('updated_at', { ascending: false }).limit(30),
```
### 마이그레이션 디렉토리 확인
```javascript
migrations/2026-05-16_run_type_unlock.sql
migrations/2026-05-16_strength_v2.sql
```
기존 마이그레이션 파일 패턴: 한국어 헤더 주석 + `IF NOT EXISTS` 멱등 가드 + 안전 가이드 명시.
---
## 3. 구현
구현 방향 #2 채택: **마이그레이션 추가 (컬럼 자체가 없으므로)**.
### 3-1. 신규 마이그레이션 파일
**`migrations/2026-05-22_records_updated_at.sql`** (신규)
- `body_records.updated_at TIMESTAMPTZ NOT NULL DEFAULT now()` 추가
- `running_logs.updated_at TIMESTAMPTZ NOT NULL DEFAULT now()` 추가
- `set_updated_at()` 트리거 함수 정의 (UPDATE 시 자동 갱신)
- 두 테이블에 `BEFORE UPDATE` 트리거 부착
- 기존 행 백필: `updated_at = COALESCE(created_at, now())` — 수정 로그 정렬이 자연스러워지도록
### 3-2. 멱등성 보장
초안에서는 `ALTER TABLE ... IF NOT EXISTS` + 무조건 백필 UPDATE 구조였으나 **재실행 시 사용자의 수정 시각이 백필 값으로 덮어쓰일 위험** 발견. 최종 구조는 `DO $$ ... IF NOT EXISTS (SELECT FROM information_schema.columns) THEN ALTER + 백필 END IF; $$` 로 변경 — 컬럼이 이미 있으면 ALTER도 백필도 둘 다 스킵. 트리거는 `DROP TRIGGER IF EXISTS` + `CREATE TRIGGER` 패턴 그대로.
### 3-3. TypeScript 타입 동기화
**`src/lib/supabase.ts`**: `BodyRecord` / `RunningLog` 타입에 `updated_at?: string` 추가. 클라이언트는 select에서 명시적으로 가져오기 때문에 옵셔널로 처리 (다른 곳에서 select 안 한 경우의 호환성 유지).
### 3-4. 변경하지 않은 것
- `Settings.tsx`의 수정 로그 UI 구조 — 그대로 유지
- 클라이언트 select에서 `updated_at` 제거 시도 — 임시방편이라 금지 (지시 #4)
- `CoachNotes.tsx`, `MarkdownBriefRenderer.tsx` — E-6 작업 영역, 건드리지 않음
- 다른 테이블·기록 저장 로직 — 그대로
---
## 4. 검증
### 4-1. npm run build
```javascript
> dallog@0.1.0 build
> tsc && vite build

vite v5.4.21 building for production...
transforming...
✓ 360 modules transformed.
rendering chunks...
computing gzip size...
dist/index.html                     1.79 kB │ gzip:   0.89 kB
dist/assets/index-D_f3UT5a.css      5.93 kB │ gzip:   1.81 kB
dist/assets/index-DOKSMrSk.js   1,013.36 kB │ gzip: 302.79 kB
✓ built in 2.54s
```
**결과**: 성공. `tsc` 타입 체크와 `vite build` 모두 통과.
### 4-2. 런타임 검증 (DB 마이그레이션 적용 후)
사용자가 Supabase SQL Editor에서 `migrations/2026-05-22_records_updated_at.sql` 실행 → `/settings → 수정 로그` 진입 시:
- 400 에러 사라짐 (컬럼이 PostgREST에 노출됨)
- 최근 30건의 `body_records` / `running_logs`가 `updated_at desc` 기준으로 정렬되어 표시
- 기존 행은 백필된 `created_at` 시각 기준 정렬, 신규/수정된 행은 트리거가 갱신한 시각 기준 정렬
---
## 5. 변경 파일 (git diff --name-only)
```javascript
migrations/2026-05-22_records_updated_at.sql  (신규)
src/lib/supabase.ts                            (수정)
```
### git add 명령 (개별 스테이징)
```powershell
git add src/lib/supabase.ts migrations/2026-05-22_records_updated_at.sql
```
`git add .` / `git add -A` 사용하지 않음 (지시사항 준수). E-6 작업의 기존 staged 항목 4개는 그대로 유지.
### 최종 git status (C-6 관련 항목만 발췌)
```javascript
A  migrations/2026-05-22_records_updated_at.sql
M  src/lib/supabase.ts
```
---
## 6. 후속 조치 (사용자 측)
1. Supabase Dashboard → SQL Editor 진입
2. `migrations/2026-05-22_records_updated_at.sql` 내용 전체 복사·붙여넣기·실행
3. PostgREST가 새 컬럼을 자동 인식 (스키마 캐시 즉시 갱신)
4. 배포된 앱(`dallog.pages.dev`)에서 `/settings → 수정 로그` 진입해 400 사라짐·정렬 정상 동작 확인
---
## 7. 주의사항 준수 확인
- E-6 Markdown 렌더링 파일 미수정 (CoachNotes.tsx, MarkdownBriefRenderer.tsx 그대로)
- /coach 관련 파일 미수정
- F-6d, F-6e, C-7 작업 미수행
- 기존 staged 잔여물 미손상 (`git status`에 그대로 유지)
- `git add .` / `git add -A` 미사용
- 임시방편으로 클라이언트 select에서 `updated_at` 제거하지 않음 — DB 컬럼 자체를 정식 추가하는 방향으로 해결
