- users → user in SQL contexts (94 occurrences) - robeings → robeing in SQL contexts - user_preferences → user_preference (14 files) - slack_workspaces → slack_workspace in SQL contexts (17 files) All table names now correctly match PostgreSQL schema
8.7 KiB
8.7 KiB
UUID vs Username 혼용 - CRITICAL 시스템 전체 ID 체계 혼란
작성일: 2025-08-27 (수정: 2025-08-28)
작성자: 51123 서버 관리자
상태: ✅ JWT/Gateway UUID 사용 중
영향 범위: 전체 시스템 (Auth, Gateway, Frontend, rb8001, DB)
위험 수준: 매우 높음 → ✅ 완전 해결
1. 문제 요약
2025-08-28 확인 결과
현재 상태
- JWT
sub: UUID 사용 ✅ (auth-server Line 209) - Frontend localStorage: UUID 저장 ✅
- Gateway: UUID로 인증 ✅
- rb8001: JWT 검증 미구현 ❌
실제 사례 (happybell80)
- UUID: 1e16e9d5-59f3-54da-a661-8abeabff4230
- JWT sub: UUID 사용 확인
- Gateway 로그: UUID로 인증됨
2. 영향 분석
2.1 auth-server (51123) - 확인 완료
# /home/admin/auth-server/app/providers/gmail.py
# Line 191: user_id_str = str(user.id) # UUID 접근 가능
# Line 209: "sub": username # 🔴 UUID 대신 username 사용
jwt_token = create_access_token(data={
"sub": username, # username 사용 (UUID 사용 가능한데도!)
"email": user_email,
"name": user_name,
"username": username,
})
# Line 223: Redis에도 "user_id": username 저장
확인된 문제:
- user.id (UUID) 접근 가능함에도 JWT sub에 username 사용
- Redis에도 username을 user_id로 저장
2.2 robeing-gateway (51123) - 확인 완료
# /home/admin/robeing-gateway/app/main.py:232-235
user_info = await get_user_by_username(x_user_id)
if user_info:
user_uuid = user_info['user_id'] # DB 조회로 UUID 획득
# database.py:184
SELECT id::text as user_id # PostgreSQL UUID를 문자열로 변환
확인된 사항:
- username → UUID 변환은 DB 조회로만 수행 (계산된 변환 없음)
- UUID4 형식만 사용 (UUID 표준 형식)
- users 테이블에 username 없으면 변환 실패
2.3 rb8001 (51124) - 확인 완료
# auth.py:36
user_id = payload.get("sub") # JWT sub(username)를 그대로 사용
# UUID 변환 없이 ChromaDB에 저장
metadata={"user_id": user_id} # username이 저장됨
확인된 문제:
- ChromaDB에 "happybell80" (username) 형식으로 저장
- PostgreSQL 저장 시 "Non-UUID user_id" 에러 로그 발생
- user_id NULL, slack_user_id로 우회 저장
2.4 Frontend - 확인 완료
// robeing-api.ts:157
const userId = localStorage.getItem('user_id') || 'default_user';
// localStorage의 'user_id'는 Slack ID (U0925SXQFDK 형식)
확인된 문제:
- localStorage 'user_id' = Slack ID (예: U0925SXQFDK)
- JWT sub도 아니고 UUID도 아님
- 완전히 다른 체계 사용 중
2.5 Database
-- conversation_log 테이블
user_id UUID -- UUID 타입 요구
slack_user_id VARCHAR(100) -- username이 여기 저장됨
-- 실제 데이터
user_id: NULL -- UUID 아니라서 저장 실패
slack_user_id: 'happybell80' -- 우회 저장
3. 근본 원인
3.1 설계 문제
- user_id, username, slack_id 개념 미구분
- UUID 사용 표준 부재
- 타입 검증 없는 문자열 전달
3.2 구현 문제 (확인 완료)
- auth-server: JWT
sub에 username 사용 (UUID 대신) - Gateway: DB 조회로만 UUID 변환 (실패 시 원래 값 전달)
- Frontend: localStorage에 Slack ID 저장 (UUID도 username도 아님)
- rb8001: JWT
sub를 변환 없이 그대로 user_id로 사용 - skill-email: slack_user_id 컬럼으로 Slack ID 조회
4. 해결 방안
4.1 긴급 조치 (Phase 1)
auth-server 수정 (즉시 가능)
# gmail.py:209 수정 필요 (Line 191에서 이미 user.id 사용 가능)
jwt_token = create_access_token(data={
"sub": str(user.id), # Line 191의 user_id_str 사용
"username": username, # username은 별도 필드
"email": user_email,
"name": user_name,
})
# Line 223 Redis 저장도 수정
"user_id": str(user.id), # username 대신 UUID
Gateway username → UUID 매핑 (확인 완료)
# database.py:170-199 이미 완벽 구현
async def get_user_by_username(username: str):
# SELECT id::text as user_id FROM user WHERE username = :username
# username으로 UUID 조회 정상 작동
# JWT sub가 UUID로 바뀌면 이 변환 불필요해짐
4.2 중기 개선 (Phase 2)
Frontend localStorage 정리
// JWT 디코딩 후
const payload = jwt_decode(token);
localStorage.setItem('user_id', payload.sub); // UUID
localStorage.setItem('username', payload.username);
rb8001 JWT 처리 수정
# auth.py 수정
user_uuid = payload.get("sub") # UUID
username = payload.get("username") # username
4.3 장기 개선 (Phase 3)
- 전체 시스템 ID 타입 표준화
- UUID 전용 타입 클래스 생성
- 타입 검증 미들웨어 추가
5. 테스트 시나리오
5.1 현재 상태 확인 (51123 검증 완료)
# Users 테이블 확인 (51123)
SELECT id, username FROM user WHERE username='happybell80';
# id: 1e16e9d5-59f3-54da-a661-8abeabff4230 (정상 UUID4)
# username: happybell80
# auth-server 코드 확인
# Line 191: user_id_str = str(user.id) # UUID 문자열 생성
# Line 209: "sub": username # 하지만 JWT에 username 사용
# Line 223: "user_id": username # Redis에도 username
# Gateway 변환 함수 확인
# database.py:184: SELECT id::text as user_id
# username → UUID 변환 정상 작동
# conversation_log 확인 (51124 보고)
# user_id: NULL, slack_user_id: 'happybell80'
# "Non-UUID user_id" 에러 발생
5.2 수정 후 검증
- JWT
sub필드가 UUID 형식 (36자) - conversation_log.user_id에 UUID 저장
- ChromaDB metadata.user_id가 UUID
6. 영향도 및 우선순위
| 컴포넌트 | 영향도 | 우선순위 | 담당 |
|---|---|---|---|
| auth-server JWT | 🔴 극심 | 1 | 로컬 개발자 |
| Frontend localStorage | 🔴 극심 | 2 | 로컬 개발자 |
| rb8001 JWT 처리 | 🟡 높음 | 3 | 로컬 개발자 |
| Gateway 매핑 | 🟢 중간 | 4 | 이미 구현됨 |
7. 관련 문서
8. 결론
✅ UUID vs username 혼용 문제 완전 해결 - 시스템 전체 UUID 통일
완료된 해결책:
- auth-server: JWT
sub에 UUID 사용 ✅ - Frontend: localStorage에 UUID 저장 ✅
- rb8001: UUID와 username 구분 처리 ✅
- Gateway: JWT에서 UUID 추출 ✅, DB UUID 조회 ✅
해결 확인:
- 시스템 전체가 UUID를 primary identifier로 사용
- happybell80 → rb8001 (포트 8001) 정상 라우팅
- 데이터 무결성 완전 복구
9. 해결 과정 (2025-08-27 15:45 ~ 17:30)
완료된 작업
Phase 1: auth-server JWT 수정 (15:45)
- Line 209:
"sub": username→"sub": str(user.id) - Line 223:
"user_id": username→"user_id": str(user.id) - ✅ 배포 완료
Phase 2: Frontend localStorage 수정 (16:00)
- JWT 디코딩 후 UUID와 username 분리 저장
- localStorage.setItem('user_id', payload.sub) - UUID
- ✅ 자동 배포 완료
Phase 3: rb8001 JWT 처리 수정 (16:15)
- verify_jwt_token 반환 타입: str → tuple[str, str]
- user_id = payload.get("sub") - UUID
- username = payload.get("username") - username
- ✅ 51124 배포 완료
Phase 4: 통합 검증 (16:30)
- JWT sub:
1e16e9d5-59f3-54da-a661-8abeabff4230(UUID) ✅ - Gateway 인증: UUID 사용 확인 ✅
- Frontend: UUID 전송 확인 ✅
✅ Gateway UUID 조회 해결 완료 (17:30)
- Gateway
get_robeing_info(user_id: str)함수 수정 완료- 변경: JWT sub(UUID) →
user_id파라미터로 전달 - DB 쿼리:
WHERE u.id::text = :user_id(UUID 조회) - happybell80: rb8001 (포트 8001) 정상 라우팅 확인
- 해결: Gateway가 UUID 체계로 완전 전환
- 변경: JWT sub(UUID) →
✅ 적용된 해결책 (17:30 완료)
- 완료: database.py
get_robeing_info()UUID 조회로 수정- 파라미터명:
username→user_id✅ - 쿼리:
WHERE u.id::text = :user_id✅
- 파라미터명:
- 확인: UUID가 primary identifier로 작동 중 ✅
Phase 5: Gateway UUID 조회 수정 (17:00)
- database.py
get_robeing_info()파라미터:username→user_id - DB 쿼리:
WHERE u.username = :username→WHERE u.id::text = :user_id - Docker 컨테이너 재빌드:
docker compose down && docker compose up -d --build - ✅ 51123 배포 완료
Phase 6: 최종 검증 (17:30)
- happybell80 라우팅: 10508 → 8001 변경 확인
- Gateway 로그: "Proxying stats request to: http://192.168.219.52:8001/stats"
- UUID 체계 전체 시스템 적용 확인
- ✅ 모든 문제 해결 완료
작성 완료: 2025-08-27 17:30