234 lines
6.5 KiB
Markdown
234 lines
6.5 KiB
Markdown
# 로빙 상태(Stats) 표시 안됨 문제 트러블슈팅
|
|
|
|
## 작성일: 2025-08-25 (수정: 2025-08-28)
|
|
## 작성자: 서버 관리자
|
|
## 상태: ✅ 해결 완료
|
|
|
|
---
|
|
|
|
## 문제 요약
|
|
사용자가 로그인 후 프론트엔드에서 로빙의 실제 상태(레벨, 경험치, 스탯)가 표시되지 않고 하드코딩된 기본값만 표시됨
|
|
|
|
---
|
|
|
|
## 증상
|
|
- 프론트엔드에서 항상 "LV.12", "350 코인", "75% 경험치" 표시 (하드코딩)
|
|
- 실제 DB에는 rb8001이 레벨 20이지만 UI에 반영 안됨
|
|
- 게이트웨이 로그: `/api/stats/undefined` 호출 (robeing_id 미전달)
|
|
|
|
---
|
|
|
|
## 문제 분석
|
|
|
|
### 1. 프론트엔드 문제 (51123 서버)
|
|
|
|
#### 1.1 하드코딩된 UI
|
|
**위치**: `/home/admin/frontend-customer/src/components/game-layout.tsx:97-101`
|
|
```jsx
|
|
<div className="bg-amber-400 text-black px-1.5 py-0.5 rounded text-xs font-bold">
|
|
LV.12 // 하드코딩
|
|
</div>
|
|
<div className="bg-violet-600 text-white px-1.5 py-0.5 rounded text-xs font-bold">
|
|
<span>💎</span> 350 // 하드코딩
|
|
</div>
|
|
```
|
|
|
|
#### 1.2 Stats API 호출 누락
|
|
- 프론트엔드에서 `/api/stats/{robeing_id}` 호출 로직 없음
|
|
- useEffect나 데이터 fetching 코드 부재
|
|
- SimpleStatsPanel도 props 기본값만 사용
|
|
|
|
#### 1.3 Robeing ID 미전달
|
|
- 게이트웨이 로그 확인:
|
|
```
|
|
GET /api/stats/undefined HTTP/1.0" 200 OK
|
|
Stats request from user: happybell80 for robeing: undefined
|
|
```
|
|
- 프론트엔드가 사용자의 robeing_id를 가져오지 못함
|
|
|
|
### 2. 게이트웨이 동작 (51123 서버) - 정상
|
|
|
|
#### 2.1 사용자-로빙 매핑 정상
|
|
```sql
|
|
-- DB 확인 결과
|
|
happybell80 (goeun2dc@gmail.com) → rb8001 정상 매핑
|
|
```
|
|
|
|
#### 2.2 프록시 정상 작동
|
|
```bash
|
|
# 직접 테스트 시 정상 응답
|
|
curl http://localhost:8100/api/stats/rb8001
|
|
→ 51124 서버로 정상 프록시
|
|
```
|
|
|
|
### 3. 51124 서버 문제 (rb8001 서비스)
|
|
|
|
#### 3.1 하드코딩된 응답
|
|
**문제 위치**: `rb8001/main.py:116`
|
|
```python
|
|
@app.get("/stats")
|
|
async def get_stats():
|
|
# DB 조회 없이 하드코딩된 값 반환
|
|
return {
|
|
"level": 1, # 항상 1
|
|
"experience": 0,
|
|
"stats": {
|
|
"memory": 10,
|
|
"compute": 10,
|
|
"empathy": 10,
|
|
"leadership": 10,
|
|
"ethics": 0
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 3.2 ~~State Service 미연결~~ (제거됨 - State Service 사용 안 함)
|
|
- ~~State Service는 더 이상 사용하지 않음~~
|
|
- rb8001이 직접 DB 접근하여 스탯 조회 필요
|
|
|
|
#### 3.3 DB 값과 불일치
|
|
```sql
|
|
-- DB의 실제 값
|
|
robeing_stats 테이블:
|
|
- robeing_id: rb8001
|
|
- level: 20
|
|
- experience: 2000
|
|
|
|
-- API 응답값
|
|
- level: 1
|
|
- experience: 0
|
|
```
|
|
|
|
---
|
|
|
|
## 문제 플로우 다이어그램
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant User as 사용자<br/>(goeun2dc)
|
|
participant Frontend as 프론트엔드<br/>(51123)
|
|
participant Gateway as 게이트웨이<br/>(51123:8100)
|
|
participant RB8001 as rb8001<br/>(51124:8001)
|
|
participant DB as PostgreSQL<br/>(51123:5432)
|
|
|
|
User->>Frontend: 로그인
|
|
Frontend->>Frontend: auth_token 저장
|
|
Note over Frontend: ❌ robeing_id 가져오기 누락
|
|
|
|
Frontend->>Frontend: game-layout 렌더링
|
|
Note over Frontend: ❌ 하드코딩된 값 표시<br/>LV.12, 350코인, 75%
|
|
|
|
Frontend->>Gateway: GET /api/stats/undefined ❌
|
|
Note over Gateway: robeing_id가 undefined
|
|
|
|
Gateway->>Gateway: 캐시에서 사용자 조회<br/>happybell80 → rb8001
|
|
Gateway->>RB8001: GET /stats (rb8001로 프록시)
|
|
|
|
RB8001->>RB8001: ❌ DB 조회 없음
|
|
RB8001-->>Gateway: 하드코딩된 응답<br/>level: 1, 모든 스탯: 10
|
|
Gateway-->>Frontend: 응답 전달
|
|
|
|
Frontend->>Frontend: ❌ 응답 무시<br/>여전히 하드코딩 표시
|
|
|
|
Note over DB: 실제 값 (미사용):<br/>level: 20<br/>experience: 2000
|
|
```
|
|
|
|
---
|
|
|
|
## 해결 방안
|
|
|
|
### 단기 (즉시 적용 가능) - 51123 서버
|
|
|
|
#### 1. 프론트엔드 수정 필요
|
|
```typescript
|
|
// game-layout.tsx 수정 예시
|
|
const [stats, setStats] = useState(null);
|
|
|
|
useEffect(() => {
|
|
const fetchStats = async () => {
|
|
const userId = localStorage.getItem('user_id');
|
|
// 1. 먼저 사용자의 robeing_id 가져오기
|
|
const robeingResponse = await fetch(`/api/user/${userId}/robeing`);
|
|
const { robeing_id } = await robeingResponse.json();
|
|
|
|
// 2. stats 가져오기
|
|
const statsResponse = await fetch(`/api/stats/${robeing_id}`);
|
|
const statsData = await statsResponse.json();
|
|
setStats(statsData);
|
|
};
|
|
|
|
fetchStats();
|
|
}, []);
|
|
|
|
// 하드코딩 대신 동적 표시
|
|
<div>LV.{stats?.level || 1}</div>
|
|
<div>💎 {stats?.coins || 0}</div>
|
|
```
|
|
|
|
### ✅ 해결 완료 (2025-08-28)
|
|
|
|
#### 최종 해결
|
|
1. robeing-monitor 활용: state_service를 `/api` 경로 마운트
|
|
2. Gateway 통합: 모든 stats → robeing-monitor (포트 9024)
|
|
3. DB 스키마: 누락 컬럼 추가 (memory, compute 등)
|
|
4. Frontend: rb8001 레벨 20 정상 표시 ✅
|
|
|
|
---
|
|
|
|
## 임시 해결책 (권장하지 않음)
|
|
|
|
### DB 직접 수정
|
|
```sql
|
|
-- rb8001의 레벨을 1로 낮추기 (비추천)
|
|
UPDATE robeing_stats
|
|
SET level = 1, experience = 0
|
|
WHERE robeing_id = 'rb8001';
|
|
```
|
|
→ 근본 해결 아님, API가 여전히 DB 무시
|
|
|
|
---
|
|
|
|
## 관련 파일
|
|
- **프론트엔드**:
|
|
- `/home/admin/frontend-customer/src/components/game-layout.tsx`
|
|
- `/home/admin/frontend-customer/src/components/simple-stats-panel.tsx`
|
|
- `/home/admin/frontend-customer/src/contexts/auth-context.tsx`
|
|
|
|
- **게이트웨이**:
|
|
- `/home/admin/robeing-gateway/app/main.py` (정상)
|
|
|
|
- **51124 서버** (수정 필요):
|
|
- `rb8001/main.py:116` - 하드코딩된 /stats
|
|
- ~~`rb8001/app/services/state_service.py`~~ - 사용 안 함
|
|
|
|
- **DB 테이블**:
|
|
- `robeing_stats` - 실제 스탯 저장
|
|
- `workspace_members` - 사용자-로빙 매핑
|
|
|
|
---
|
|
|
|
## 모니터링 명령어
|
|
```bash
|
|
# 게이트웨이 로그 확인
|
|
docker logs robeing-gateway --tail 50 | grep stats
|
|
|
|
# DB 상태 확인
|
|
PGPASSWORD=robeings psql -h localhost -U robeings -d main_db \
|
|
-c "SELECT * FROM robeing_stats WHERE robeing_id = 'rb8001';"
|
|
|
|
# API 직접 테스트
|
|
curl http://localhost:8100/api/stats/rb8001
|
|
```
|
|
|
|
---
|
|
|
|
## 참고 문서
|
|
- [일일 브리핑 시퀀스](/home/admin/DOCS/300_architecture/sequences/daily_briefing_sequences.md) - 비슷한 DB 연동 문제
|
|
- [OAuth 스코프 문제](/home/admin/DOCS/troubleshooting/250824_gmail_oauth_scope_issue.md)
|
|
|
|
---
|
|
|
|
## 추가 확인 사항
|
|
1. 프론트엔드에서 사용자의 robeing_id를 어떻게 가져올지 결정 필요
|
|
2. stats 업데이트 주기 (실시간 vs 폴링)
|
|
3. 캐싱 전략 (게이트웨이 캐시 활용) |