docs: 사용자 격리 및 404 에러 해결 트러블슈팅
- 모든 사용자가 default로 처리되던 문제
- OAuth DB 저장 안 되던 문제
- /api/items/gmail 404 에러
- 철학과 기술의 균형 논의
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9eaa83a76e
commit
fc4c84d216
243
troubleshooting/250822_happybell80_사용자격리_404에러_해결.md
Normal file
243
troubleshooting/250822_happybell80_사용자격리_404에러_해결.md
Normal file
@ -0,0 +1,243 @@
|
||||
# 사용자 격리 및 404 에러 해결
|
||||
|
||||
## 날짜: 2025-08-22
|
||||
## 작성자: happybell80 & Claude
|
||||
## 관련 서비스: rb10508_micro, robeing-gateway, auth-server, robeing-monitor
|
||||
|
||||
---
|
||||
|
||||
## 1. 문제 상황 요약
|
||||
|
||||
### 발견된 문제들
|
||||
1. **모든 사용자가 "default"로 처리**
|
||||
- info@ro-being.com과 goeun2dc@gmail.com이 같은 대화 기록 공유
|
||||
- 보안 및 프라이버시 심각한 문제
|
||||
|
||||
2. **OAuth 사용자 DB 저장 안 됨**
|
||||
- info@ro-being.com이 로그인했지만 DB에 없음
|
||||
- auth-server의 DB 저장 코드가 주석 처리됨
|
||||
|
||||
3. **404 에러 지속 발생**
|
||||
- `/api/items/gmail` 엔드포인트 404
|
||||
- `/api/stats/{robeing_id}` 엔드포인트 404
|
||||
|
||||
---
|
||||
|
||||
## 2. 원인 분석
|
||||
|
||||
### 2.1 사용자 격리 문제
|
||||
|
||||
#### 근본 원인 체인
|
||||
```
|
||||
Frontend (JWT) → Gateway (username) → rb10508 (default) → ChromaDB (공유)
|
||||
```
|
||||
|
||||
#### 문제점들
|
||||
- rb10508_micro의 `MessageRequest`에 `user_id` 기본값 "default_user" 하드코딩
|
||||
- Gateway가 username을 UUID로 변환하지 않음
|
||||
- JWT 파싱 로직이 잘못되어 사용자 식별 실패
|
||||
|
||||
### 2.2 OAuth DB 저장 문제
|
||||
|
||||
#### auth-server/app/providers/gmail.py:163-175
|
||||
```python
|
||||
# TODO: 실제 DB 세션 사용
|
||||
# db = next(get_db())
|
||||
# user = db.query(User).filter(User.email == user_email).first()
|
||||
# ... (주석 처리된 DB 저장 코드)
|
||||
```
|
||||
|
||||
### 2.3 404 에러 원인
|
||||
|
||||
#### 라우팅 체인 문제
|
||||
```
|
||||
Frontend → Nginx → Gateway → robeing-monitor
|
||||
↓
|
||||
404 (경로 불일치)
|
||||
```
|
||||
|
||||
- 프론트엔드: `/api/items/gmail` 요청
|
||||
- robeing-monitor: `/api/gmail`만 구현
|
||||
- Gateway 프록시 설정 누락
|
||||
|
||||
---
|
||||
|
||||
## 3. 해결 과정
|
||||
|
||||
### 3.1 Phase 1: 사용자 격리 수정
|
||||
|
||||
#### rb10508_micro/app/api/endpoints.py
|
||||
```python
|
||||
# Before
|
||||
class MessageRequest(BaseModel):
|
||||
user_id: Optional[str] = "default_user" # 문제!
|
||||
|
||||
# After
|
||||
class MessageRequest(BaseModel):
|
||||
user_id: Optional[str] = None # 기본값 제거
|
||||
|
||||
# 임시 ID 생성 로직 추가
|
||||
if not user_id:
|
||||
client_ip = req.client.host if req.client else "unknown"
|
||||
user_id = f"guest_{client_ip}_{datetime.now().strftime('%Y%m%d%H%M%S')}"
|
||||
```
|
||||
|
||||
### 3.2 Phase 2: OAuth DB 저장 활성화
|
||||
|
||||
#### auth-server/app/providers/gmail.py
|
||||
```python
|
||||
# 주석 해제 및 수정
|
||||
db = SessionLocal()
|
||||
try:
|
||||
user = db.query(User).filter(User.email == user_email).first()
|
||||
if not user:
|
||||
user = User(
|
||||
id=uuid.uuid4(),
|
||||
email=user_email,
|
||||
username=username,
|
||||
name=user_name,
|
||||
oauth_provider='google',
|
||||
oauth_id=user_info.get('id', '')
|
||||
)
|
||||
db.add(user)
|
||||
db.commit()
|
||||
logger.info(f"New user created: {username} ({user_email})")
|
||||
```
|
||||
|
||||
### 3.3 Phase 3: Gateway UUID 변환
|
||||
|
||||
#### robeing-gateway/app/main.py
|
||||
```python
|
||||
# Username을 UUID로 변환
|
||||
from app.database import get_user_by_username
|
||||
user_uuid = x_user_id
|
||||
|
||||
if x_user_id and x_user_id != "default":
|
||||
user_info = await get_user_by_username(x_user_id)
|
||||
if user_info:
|
||||
user_uuid = user_info['user_id'] # UUID 사용
|
||||
logger.info(f"Username to UUID: {x_user_id} → {user_uuid}")
|
||||
```
|
||||
|
||||
### 3.4 Phase 4: JWT 파싱 개선
|
||||
|
||||
#### robeing-gateway/app/main.py
|
||||
```python
|
||||
def get_verified_user(authorization: Optional[str] = Header(None)):
|
||||
if not authorization or not authorization.startswith("Bearer "):
|
||||
logger.warning("No Authorization header or invalid format")
|
||||
return "default"
|
||||
|
||||
try:
|
||||
token = authorization.replace("Bearer ", "")
|
||||
payload = jwt.decode(token, JWT_SECRET_KEY, algorithms=["HS256"])
|
||||
|
||||
# JWT payload 로깅 (디버깅용)
|
||||
logger.info(f"JWT payload: {payload}")
|
||||
|
||||
# sub (subject)가 username임
|
||||
username = payload.get("sub") or payload.get("username") or payload.get("user_id")
|
||||
|
||||
if username:
|
||||
logger.info(f"Authenticated user: {username}")
|
||||
return username
|
||||
```
|
||||
|
||||
### 3.5 Phase 5: 404 에러 해결
|
||||
|
||||
#### 시도 1: robeing-monitor에 alias 추가
|
||||
```python
|
||||
@router.get("/gmail")
|
||||
@router.get("/items/gmail") # 프론트엔드 호환성
|
||||
```
|
||||
|
||||
#### 시도 2: Gateway에서 경로 변환
|
||||
```python
|
||||
# /api/items/gmail → /api/gmail로 변환
|
||||
if path.startswith("gmail"):
|
||||
actual_path = path
|
||||
else:
|
||||
actual_path = f"items/{path}"
|
||||
```
|
||||
|
||||
#### 시도 3: Frontend API 경로 수정
|
||||
```typescript
|
||||
// Before
|
||||
const response = await fetch(`/api/stats/${robeingId}`);
|
||||
|
||||
// After
|
||||
const response = await fetch(`${ROBEING_API_URL}/api/stats/${robeingId}`);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 테스트 결과
|
||||
|
||||
### 4.1 성공한 부분
|
||||
- ✅ OAuth DB 저장: info@ro-being.com 사용자 생성 확인
|
||||
- ✅ ChromaDB 정상 작동: 13개 컬렉션, 524개 문서
|
||||
- ✅ 메모리 저장 가능
|
||||
- ✅ POST 요청 도달 시작
|
||||
|
||||
### 4.2 남은 문제
|
||||
- ⚠️ 일부 사용자는 여전히 "default"로 처리
|
||||
- ⚠️ `/api/items/gmail` 404 지속 (Nginx 설정 필요)
|
||||
|
||||
---
|
||||
|
||||
## 5. 파일명 정리
|
||||
|
||||
### robing → robeing 변경
|
||||
- `robing-api.ts` → `robeing-api.ts`
|
||||
- `robing-avatar.png` → `robeing-avatar.png`
|
||||
|
||||
**"robing"은 금지된 용어**
|
||||
|
||||
---
|
||||
|
||||
## 6. 아키텍처 논의
|
||||
|
||||
### robeing-monitor의 존재 이유
|
||||
- **철학적**: 로빙의 "아이템 인벤토리" 개념
|
||||
- **기술적**: 불필요한 중간 계층
|
||||
|
||||
### 로빙 철학
|
||||
- 존재형 에이전트: 도구가 아닌 동료
|
||||
- 성장하는 디지털 생명체
|
||||
- 게임화된 인터페이스 (레벨, 스탯, 아이템)
|
||||
|
||||
---
|
||||
|
||||
## 7. 교훈
|
||||
|
||||
### 7.1 ID 체계 일관성
|
||||
- Frontend: username (JWT)
|
||||
- Backend: UUID (PostgreSQL)
|
||||
- 변환 로직 필수
|
||||
|
||||
### 7.2 코드 주석 주의
|
||||
- TODO 주석은 반드시 추적
|
||||
- 핵심 기능을 주석 처리하면 안 됨
|
||||
|
||||
### 7.3 디버깅 전략
|
||||
1. 각 서비스 개별 테스트
|
||||
2. 로그를 통한 데이터 흐름 추적
|
||||
3. curl로 직접 테스트
|
||||
|
||||
### 7.4 철학과 기술의 균형
|
||||
- 기술적 효율성 vs 프로젝트 비전
|
||||
- 로빙의 게임화 철학 존중 필요
|
||||
|
||||
---
|
||||
|
||||
## 8. 관련 커밋
|
||||
|
||||
- rb10508_micro: 사용자 격리 수정
|
||||
- auth-server: OAuth DB 저장 활성화
|
||||
- robeing-gateway: UUID 변환 및 JWT 파싱 개선
|
||||
- robeing-monitor: 경로 alias 추가
|
||||
- frontend-customer: 파일명 정리 및 API 경로 수정
|
||||
|
||||
---
|
||||
|
||||
**문서 끝**
|
||||
Loading…
x
Reference in New Issue
Block a user