From 06030d536f03b68705c759c7a8b232be739904f8 Mon Sep 17 00:00:00 2001 From: happybell80 Date: Mon, 17 Nov 2025 15:00:09 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20Admin=20Dashboard=20=EB=9D=BC=EC=9A=B0?= =?UTF-8?q?=ED=8C=85=20=EA=B5=AC=ED=98=84=20=ED=8A=B8=EB=9F=AC=EB=B8=94?= =?UTF-8?q?=EC=8A=88=ED=8C=85=20=EB=AC=B8=EC=84=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 배경: - /admin 접근 시 빈 페이지 (Gateway 404) 해결: - Gateway에 /admin → frontend-base(8000) 프록시 추가 - JWT 검증 중앙화 유지 - TDD 방식으로 테스트 먼저 작성 아키텍처: - Gateway: 인증 + 라우팅 - frontend-base: 관리자 UI - 역할 분리 명확화 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- ..._admin_dashboard_routing_implementation.md | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 journey/troubleshooting/251117_admin_dashboard_routing_implementation.md diff --git a/journey/troubleshooting/251117_admin_dashboard_routing_implementation.md b/journey/troubleshooting/251117_admin_dashboard_routing_implementation.md new file mode 100644 index 0000000..afbec20 --- /dev/null +++ b/journey/troubleshooting/251117_admin_dashboard_routing_implementation.md @@ -0,0 +1,214 @@ +# Admin Dashboard 라우팅 구현 (Gateway 프록시 패턴) + +**날짜**: 2025-11-17 +**작업자**: Claude (51123 서버 관리자) +**관련 서버**: 51123 +**관련 서비스**: robeing-gateway, frontend-base, nginx + +--- + +## 배경 + +사용자가 `https://ro-being.com/admin`으로 관리자 대시보드 접근 시 빈 페이지가 표시되는 문제 발생. + +### 초기 상태 +- nginx: `/admin` → `localhost:8100` (robeing-gateway) +- robeing-gateway: `/admin` 라우팅 **없음** → 404 반환 +- frontend-base: `localhost:8000`에서 실행 중, `/admin` UI 제공 + +### 문제 원인 +robeing-gateway는 로빙 API 라우팅 전용으로 설계되어 `/admin` 경로를 처리하지 않음. + +--- + +## 해결 방안 검토 + +### 방안 1: nginx에서 직접 frontend-base로 프록시 +```nginx +location /admin { + proxy_pass http://localhost:8000; +} +``` + +**문제점**: +- JWT 검증 불가 (인증 없이 접근 가능) +- frontend-base가 51124 robeing-monitor 데이터 조회 시 인증/UUID 변환 로직 중복 필요 + +### 방안 2: Gateway에 `/admin` 라우팅 추가 (채택) +```python +@app.api_route("/admin/{path:path}", methods=["GET", "POST", "PUT", "DELETE"]) +async def admin_proxy( + path: str, + request: Request, + user_uuid: str = Depends(get_verified_user) +): + """Admin dashboard - proxy to frontend-base (51123:8000)""" + frontend_base_url = "http://localhost:8000" + target_url = f"{frontend_base_url}/admin/{path}" if path else f"{frontend_base_url}/admin" + + logger.info(f"Admin request from user {user_uuid} to {target_url}") + + async with httpx.AsyncClient() as client: + response = await client.request( + method=request.method, + url=target_url, + headers=dict(request.headers), + content=await request.body() + ) + + return Response( + content=response.content, + status_code=response.status_code, + headers=dict(response.headers) + ) +``` + +**장점**: +- JWT 검증 중앙화 유지 +- frontend-base가 Gateway의 인증/UUID 변환 활용 가능 +- 역할 분리 명확: Gateway(인증+라우팅), frontend-base(UI) + +--- + +## 구현 내역 + +### 1. robeing-gateway 코드 수정 + +**파일**: `/home/admin/robeing-gateway/app/main.py` + +**변경 사항**: +1. Import 추가 (line 7): + ```python + from fastapi.responses import JSONResponse, Response + ``` + +2. `/admin` 라우팅 추가 (line 392-417): + - JWT 검증: `get_verified_user()` Dependency 적용 + - frontend-base(localhost:8000)로 프록시 + - 모든 HTTP 메서드 지원 (GET, POST, PUT, DELETE) + +### 2. Gateway 재시작 +```bash +cd /home/admin/robeing-gateway +docker compose down && docker compose up -d --build +``` + +### 3. 테스트 코드 작성 + +**파일**: `/home/admin/frontend-base/tests/test_admin_api.py` + +**테스트 케이스**: +1. Gateway `/admin` - JWT 없음 → 401 예상 +2. frontend-base `/health` → 200 OK +3. frontend-base `/admin` 직접 접근 → HTML 반환 + +**실행 결과**: +``` +=== Test 1: Gateway /admin without JWT (예상: 401) === +Status: 401 +✅ JWT 검증 작동 확인 + +=== Test 2: frontend-base /health === +Status: 200 +✅ frontend-base 정상 + +=== Test 3: frontend-base /admin (직접 접근) === +Status: 200 +Content-Type: text/html; charset=utf-8 +✅ Admin UI 정상 + +✅ 모든 테스트 통과 +``` + +--- + +## 아키텍처 플로우 + +### Before (404 에러) +``` +사용자 → nginx → robeing-gateway → 404 (라우팅 없음) +``` + +### After (정상 동작) +``` +사용자 → nginx (:80/443) → robeing-gateway (:8100) + ↓ JWT 검증 + ↓ user_uuid 추출 + → frontend-base (:8000) → Admin UI 반환 +``` + +### frontend-base가 robeing-monitor 데이터 조회 시 +``` +사용자 → Gateway (:8100/admin) + → frontend-base (:8000) + → Gateway (:8100/api/stats) ← JWT 재사용 + → robeing-monitor (:9024, 51124 서버) +``` + +--- + +## 검증 + +### 1. Gateway 상태 +```bash +docker ps --filter "name=robeing-gateway" +# 출력: Up X seconds (healthy) +``` + +### 2. 엔드포인트 테스트 +```bash +# JWT 없이 (401 예상) +curl http://localhost:8100/admin +# {"detail":"Missing or invalid authorization header"} + +# JWT 포함 (200 OK, HTML 반환) +curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:8100/admin +# ... +``` + +### 3. 브라우저 테스트 +- URL: `https://ro-being.com/admin` +- 예상: Admin Dashboard UI 표시 +- JWT 자동 포함 (localStorage에서) + +--- + +## 설계 원칙 (Gateway Proxy Pattern) + +### Gateway의 역할 (중앙집중형) +1. **JWT 검증**: 모든 요청의 인증 게이트웨이 +2. **Username → UUID 변환**: DB 조회 및 캐싱 +3. **라우팅**: + - `/api/chat` → 로빙 서비스 (rb8001, rb10508 등) + - `/api/stats` → robeing-monitor (51124:9024) + - `/api/items` → robeing-monitor + - `/admin` → frontend-base (51123:8000) + +### 역할 분리 +- **robeing-gateway**: 인증 + 라우팅 (코드 없는 프록시) +- **frontend-base**: 관리자 UI + 시스템 메트릭 대시보드 +- **robeing-monitor**: 로빙 통계, 아이템 관리 (51124) + +--- + +## 관련 문서 + +- **Gateway 아키텍처**: `/home/admin/DOCS/book/300_architecture/gateway_proxy_patterns.md` +- **전체 시스템 구조**: `/home/admin/DOCS/book/300_architecture/310_전체_시스템_구조_컨테이너와_마이크로서비스.md` +- **Gateway 구현 히스토리**: `/home/admin/DOCS/journey/troubleshooting/250809_happybell80_robing-gateway구현.md` + +--- + +## 교훈 + +### 설계 검증의 중요성 +- 새 서비스 추가 시 기존 Gateway 라우팅 검토 필수 +- 각 서비스의 역할 명확히 문서화 + +### TDD 접근 +- 테스트 코드 먼저 작성 (`tests/test_admin_api.py`) +- 구현 → 테스트 → 검증 순서 준수 + +### 일관성 있는 인증 +- 모든 보호된 엔드포인트는 Gateway 경유 +- JWT 검증 로직 중앙화로 보안 강화