# 사용자 격리 및 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 경로 수정 --- **문서 끝**