DOCS/journey/troubleshooting/250822_happybell80_사용자격리_404에러_해결.md
Claude-51124 22557e7132 docs: 오래된 트러블슈팅 아카이브 및 구조 정리
- 7-8월 초기 구축 문서 12개를 _archive/troubleshooting/2025_07-08_initial_setup/로 이동
- book/300_architecture/390_human_in_the_loop_intent_learning.md를 journey/research/intent_classification/로 이동 (개발 여정 문서)
- 빈 폴더 제거 (journey/assets/*)
2025-11-17 14:06:05 +09:00

6.1 KiB

사용자 격리 및 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의 MessageRequestuser_id 기본값 "default_user" 하드코딩
  • Gateway가 username을 UUID로 변환하지 않음
  • JWT 파싱 로직이 잘못되어 사용자 식별 실패

2.2 OAuth DB 저장 문제

auth-server/app/providers/gmail.py:163-175

# 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

# 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

# 주석 해제 및 수정
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

# 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

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 추가

@router.get("/gmail")
@router.get("/items/gmail")  # 프론트엔드 호환성

시도 2: Gateway에서 경로 변환

# /api/items/gmail → /api/gmail로 변환
if path.startswith("gmail"):
    actual_path = path
else:
    actual_path = f"items/{path}"

시도 3: Frontend API 경로 수정

// 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.tsrobeing-api.ts
  • robing-avatar.pngrobeing-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 경로 수정

문서 끝