# Implementation Report: 국제 시세 커모디티 페이지 + 캐시 수리 ## Summary Alpha Vantage 기반 국제 시세 페이지 7종(구리·알루미늄·밀·섬유(면화)·설탕·커피·원자재 지수)을 단일 라우트 `Price/Global/{commodity}` + 공용 모델/뷰로 구현. `_Layout.cshtml` 국제 시세 드롭다운 복원(8개 링크). IMemoryCache DI 도입으로 캐시가 실제로 동작하게 수리(2차 요청 5ms 실측). 기존 버그 3건(원화 항상 0, 페이지네이션 interval 초기화, 환율 조회 레이스) 수정. 금/석유/배출권 조용한 실패에 alert 표출 추가. ## Assessment vs Reality | Metric | Predicted (Plan) | Actual | |---|---|---| | Complexity | Medium | Medium | | Confidence | 8/10 | 적중 (통합테스트에서 환경 이슈 1건 발견·수정) | | Files Changed | 9 | 11 | ## Tasks Completed | # | Task | Status | Notes | |---|---|---|---| | 1 | Commodity Request/Response 모델 | ✅ | | | 2 | GlobalModel GetCommodityPriceInfo + 캐시 | ✅ | 빈 응답 미캐시, JsonDocument 래퍼 제거 | | 3 | GlobalController 매핑+공용 액션+버그수정 | ✅ | GetExchangeValueAsync 헬퍼 추가(하단 Deviations) | | 4 | Commodity.cshtml 공용 뷰 | ✅ | interval 셀렉트, unit caption, KRW 열 토글 | | 5 | commodity.js | ✅ | interval 변경 시 page=1 리셋 | | 6 | Program.cs AddMemoryCache | ✅ | 인코딩 보존 위해 sed로 삽입(19행) | | 7 | _Layout.cshtml 메뉴 복원 | ✅ | 8개 링크, 기존 미커밋 변경 보존 | | 8 | 금/석유/배출권 오류 표출 | ✅ | else 분기 + ViewBag.isError | ## Validation Results | Level | Status | Notes | |---|---|---| | Build | ✅ Pass | `dotnet build` 0 errors (신규 경고: 뷰 CS8602 1건 — 기존 패턴과 동일 수준) | | Unit Tests | N/A | repo에 테스트 프로젝트 없음(계획에서 범위 외로 명시) | | Integration | ✅ Pass | 별도 출력 빌드 + localhost:5099 스모크 | | Edge Cases | ✅ Pass | 아래 표 | ### 통합 테스트 실측 (2026-07-22) | 케이스 | 결과 | |---|---| | `/Price/Global/copper` 1차 | 200, 3.7s (환율 3s 타임아웃 + Alpha 호출) | | `/Price/Global/copper` 2차 | 200, **0.005s** (캐시 적중) | | wheat/cotton/sugar/coffee/aluminum | 전부 200, ~0.2s | | `/Price/Global/allcommodities` | 200, 원화 열 없음·"지수" 헤더 확인 | | `/Price/Global/xyz` | 404 | | `/Price/Global/copper?interval=daily` | 400 (사전 차단) | | `/Price/Global/copper?interval=quarterly` | 200 | | `/Price/Global/NaturalGas` | 200 (기존 URL 유지) | | `/Price/Domestic/Gold` | 200 + 실데이터(20260721 행 확인 — data.go.kr 승인 반영) | | `/Price/Domestic/Oil`, `/Emission` | 200 | | 구리 페이지 본문 | 제목 "구리 시세", 단위 "dollar per metric ton", 값 "13,552.04" 포맷 확인 | ## Files Changed | File | Action | |---|---| | `Models/Request/Price/Global/Commodity.cs` | CREATED | | `Models/Response/Price/Global/Commodity.cs` | CREATED | | `Views/Price/Global/Commodity.cshtml` | CREATED | | `wwwroot/js/commodity.js` | CREATED | | `Controllers/Price/GlobalController.cs` | UPDATED (매핑, 공용 액션, 버그 3건, 환율 헬퍼) | | `Models/Price/GlobalModel.cs` | UPDATED (IMemoryCache 주입, GetCommodityPriceInfo, 캐시 키 수정) | | `Program.cs` | UPDATED (AddMemoryCache, 19행) | | `Views/Shared/_Layout.cshtml` | UPDATED (국제 시세 메뉴 복원) | | `Controllers/Price/Domestic/GoldController.cs` | UPDATED (오류 표출) | | `Controllers/Price/Domestic/OilController.cs` | UPDATED (오류 표출) | | `Controllers/Price/Domestic/EmissionController.cs` | UPDATED (오류 표출) | ## Deviations from Plan 1. **환율 조회 3초 타임아웃 + 실패값 5분 네거티브 캐시 추가** — 통합 테스트에서 한국수출입은행 API가 이 환경에서 SSL 오류/무응답 행(hang)을 일으켜 페이지가 HttpClient 기본 100초까지 지연되는 문제 발견. `Task.WhenAny` 3초 상한으로 페이지 지연 차단, 실패 시 원화 0 표시(기존 동작과 동일). 기존 코드는 fire-and-forget 레이스 버그 때문에 우연히 안 막혔던 것. 2. **feature 브랜치 미생성(main 유지)** — 사용자 워크플로가 main 직커밋이고, 더티 트리에 이 기능의 전제인 미커밋 변경(data.go.kr 키 교체)이 존재. 커밋은 사용자 지시 대기. 3. **NaturalGas 액션에도 오류 alert 추가** — 계획은 Commodity에만 명시했으나 일관성 위해 동일 적용. 4. Program.cs는 CP949로 추정되는 파일 인코딩 보존을 위해 Edit 대신 `sed` 바이트 삽입 사용. ## Issues Encountered - 빌드 시 `economy.exe` 잠김(사용자 실행 중 인스턴스 PID 75640) → 별도 출력 폴더(`-o`) 빌드로 우회, 실행 중 앱 무간섭. **사용자 앱 재시작 전까지 로컬 실행 인스턴스에는 변경이 반영되지 않음.** - 한국수출입은행 환율 API가 이 환경에서 SSL 실패/행 → Deviation 1로 해결. 운영 환경에서 정상이면 원화 열 자동 표시됨. ## Next Steps - [ ] 사용자 로컬 앱 재시작 후 메뉴 확인 - [ ] 커밋 + 운영 배포 (data.go.kr 신 키가 운영에 반영되어야 금/석유/배출권 정상화) - [ ] (선택) FinancialModel의 per-instance 캐시도 IMemoryCache 주입으로 전환