# task-1188.1: 대시보드 계정 사용량 "토큰 만료" 문제 해결

## SCQA

**S**: 대시보드 계정 전환 드롭다운에서 drumband 계정은 5h/7d 사용량이 정상 표시되지만, 활성 계정(jonghyuk)은 "토큰 만료" 경고만 표시되어 사용량을 확인할 수 없었다.

**C**: 원인은 2가지: (1) `server.py:3552`의 `if token_expired and not is_active:` 조건이 활성 계정의 토큰 갱신을 차단했고, (2) 활성 `.credentials.json`의 MD5 해시가 백업 `.credentials-jonghyuk.json`과 달라서 활성 계정이 "active"라는 이름으로 등록되어 프론트엔드에서 "jonghyuk" 키로 조회할 때 매칭이 실패했다.

**Q**: 토큰 만료 시 자동 갱신하고, 활성 계정 이름을 정확히 식별하여 사용량을 정상 표시할 수 있는가?

**A**: 4가지 백엔드 수정(fallback 이름 탐지, 토큰 갱신 조건 수정, credential 양방향 동기화, 캐시 무효화) + 1가지 프론트엔드 수정(에러 타입별 메시지 분기)으로 해결. 수정 후 API 테스트에서 jonghyuk 계정 사용량이 5h=69%, 7d=33%로 정상 표시 확인.

## 산출물

- `/home/jay/workspace/dashboard/server.py` (수정)
- `/home/jay/workspace/dashboard/components/App.js` (수정)

## 변경 상세

### server.py `_get_usage_status()` — 4가지 수정

**수정 1: active_account_name 탐지 fallback 추가 (라인 3526-3571)**
- MD5 해시 비교 실패 시 2단계 fallback:
  - Fallback A: refreshToken 값 비교 (가장 신뢰도 높음)
  - Fallback B: scopes 배열 비교 (유일 매치만 채택)
- 현재 환경에서는 Fallback B(scopes)로 jonghyuk 식별 성공 (jonghyuk만 `user:file_upload` scope 보유)

**수정 2: 토큰 갱신 조건 수정 (라인 3598)**
- 변경 전: `if token_expired and not is_active:` (비활성 계정만 갱신)
- 변경 후: `if token_expired:` (활성/비활성 모두 갱신)

**수정 3: credential 파일 양방향 동기화 (라인 3623-3641)**
- 활성 계정 토큰 갱신 시 → 백업 파일도 동기화
- 비활성 백업 갱신 시 → 활성 파일도 동기화 (같은 계정일 때)

**수정 4: 토큰 갱신 후 캐시 무효화 (라인 3643)**
- `_usage_cache_time = None` 설정으로 다음 요청 시 최신 데이터 보장

### App.js — 에러 표시 개선 (라인 337-348)
- 기존: `usage.error` → 무조건 "⚠️ 토큰 만료"
- 변경: 에러 타입별 분기
  - `token_expired` → "⚠️ 토큰 만료 — 재로그인 필요" (red)
  - `no access token` → "⚠️ 인증 없음" (red)
  - 기타 → "⚠️ 조회 실패" (amber)
  - `usage.message` 존재 시 하단에 상세 메시지 표시

## 테스트 결과

- API 응답: `{"accounts": {"jonghyuk": {"five_hour": {"used_percentage": 69.0}, "seven_day": {"used_percentage": 33.0}, "is_active": true}, "drumband": {"five_hour": {"used_percentage": 0.0}, "seven_day": {"used_percentage": 100.0}, "is_active": false}}}`
- generic "active" 키 없음 → 이름 탐지 성공 확인
- 서버 재시작 후 정상 동작 확인

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **활성 계정 이름 미식별 (MD5 해시 불일치)** — refreshToken/scopes 기반 fallback 탐지 로직 추가 (server.py:3526-3571)
2. **활성 계정 토큰 갱신 차단** — `not is_active` 조건 제거 (server.py:3598)
3. **credential 파일 비동기화** — 양방향 동기화 로직 추가 (server.py:3623-3641)

### 범위 외 미해결 (1건)
1. **Pyright 경고 10건 (server.py) + TypeScript 경고 3건 (App.js)** — 범위 외 사유: 모두 기존 코드의 pre-existing 이슈이며 본 작업 변경 범위에 해당하지 않음 (unused variables 경고)

## 셀프 QC
- [x] 1. 영향 파일: server.py (usage-status API만 변경), App.js (에러 표시만 변경). 다른 API 엔드포인트 영향 없음
- [x] 2. 엣지 케이스: credential 파일 없음, refreshToken 없음, scopes 동일한 다중 계정, OAuth 서버 타임아웃 — 모두 except 블록으로 처리
- [x] 3. 작업 지시와 일치: 토큰 만료 시 자동 갱신, 사용량 정상 표시, 구체적 에러 메시지 — 모두 충족
- [x] 4. 에러 처리: 모든 새 코드에 try/except 포함, 보안: 토큰 값 비노출 확인
- [x] 5. 테스트: API 응답 정상 확인 (5h=69%, 7d=33%)
- [x] 6. 발견 이슈 3건 모두 직접 해결
- [x] 7. 아키텍처: 기존 패턴(MD5→fallback) 확장, SOLID 위반 없음
- [x] 8. 인터페이스 변경: API 응답 구조 변경 없음 (기존 필드 유지)
