diff --git a/troubleshooting/250809_happybell80_robing-gateway구현.md b/troubleshooting/250809_happybell80_robing-gateway구현.md new file mode 100644 index 0000000..d49ffba --- /dev/null +++ b/troubleshooting/250809_happybell80_robing-gateway구현.md @@ -0,0 +1,320 @@ +# robing-gateway API 게이트웨이 구현 및 배포 + +**날짜**: 2025-08-09 +**작업자**: happybell80 & Claude & 23서버팀 +**관련 서버**: 51123 (Gateway 실행), 51124 (로빙 서비스) + +## 배경 + +서비스 재구조화 계획에 따라 Frontend와 로빙 서비스 간 중앙 라우팅 레이어 구현 필요. +기존 frontend-base의 일부 기능을 분리하여 독립적인 API Gateway 서비스로 구축. + +## 오전 10시 30분 - 초기 구현 + +### 구현 내용 + +**프로젝트 구조**: +``` +robing-gateway/ +├── app/ +│ ├── main.py # FastAPI 메인 앱 +│ ├── cache.py # 메모리 캐시 (30분 TTL) +│ ├── database.py # PostgreSQL 연결 +│ └── models.py # SQLAlchemy 모델 +├── scripts/ +│ ├── init_db.sql # 테스트 데이터 +│ └── health_check.sh # 헬스체크 스크립트 +├── docker-compose.yml +├── Dockerfile +└── .gitea/workflows/deploy.yml +``` + +**핵심 기능**: +1. 사용자-로빙 매핑 관리 +2. 메모리 캐시로 성능 최적화 +3. 기존 auth_db 테이블 활용 (workspaces, workspace_members) +4. 헬스체크 및 모니터링 엔드포인트 + +### 23서버팀 피드백 + +**중요 변경사항 - 새 테이블 불필요**: +- 기존 auth_db의 workspaces, workspace_members 테이블 활용 +- workspace_members에서 user_id로 robing 정보 조회 +- JOIN 쿼리로 사용자 → 워크스페이스 → 로빙 매핑 + +## 오전 11시 00분 - 배포 문제 해결 + +### 문제 1: API 엔드포인트 불일치 + +**원인**: +- Gateway가 `/api/chat`으로 프록시 시도 +- rb10508_micro는 `/api/message` 엔드포인트 사용 + +**해결**: +```python +# app/main.py 수정 +target_url = f"{base_url}/api/message" # rb10508_micro uses /api/message +``` + +### 문제 2: 요청 body 형식 불일치 + +**원인**: +- Frontend는 `message` 필드 전송 +- rb10508_micro는 `text` 필드 예상 + +**해결**: +```python +# MessageRequest 형식으로 변환 +body = { + 'text': original_body.get('message', original_body.get('text', '')), + 'user_id': x_user_id, + 'context': original_body.get('context', {}) +} +``` + +### 문제 3: Docker 컨테이너 DB 연결 실패 + +**원인**: +- 컨테이너 내부에서 localhost는 컨테이너 자신을 가리킴 +- 호스트의 PostgreSQL 접근 불가 + +**해결**: +```yaml +# .env.example 수정 +DATABASE_URL=postgresql+asyncpg://robeings:패스워드@host.docker.internal:5432/auth_db +``` + +### 문제 4: Gitea Actions 환경변수 + +**원인**: +- `${{ gitea.workspace }}` 변수 인식 실패 + +**해결**: +- `${{ github.workspace }}` 사용 (Gitea가 GitHub Actions 호환 변수 지원) + +## 오전 11시 45분 - 최종 배포 성공 + +### 배포 결과 + +**정상 작동 확인**: +```bash +# 헬스체크 +curl http://localhost:8100/health +# 결과: {"status":"healthy","cache_size":0,"database":"connected"} + +# DB 테이블 확인 +SELECT COUNT(*) FROM workspaces; # 2 (테스트 데이터) +``` + +**현재 상태**: +- robing-gateway 포트 8100에서 정상 실행 +- PostgreSQL auth_db 연결 성공 +- DEFAULT_ROBING_ID: rb10508_micro 설정 +- 메모리 캐시 활성화 (30분 TTL) + +## 시스템 아키텍처 + +``` +Frontend (React) + ↓ POST /api/chat (message, user_id) +Gateway (8100) + ↓ 캐시 확인 → DB 조회 → 라우팅 결정 + ↓ POST /api/message (text, user_id, context) +rb10508_micro (10508) +``` + +## 다음 단계 (Phase 2) + +### 1. Frontend 연동 테스트 +```javascript +// Frontend 요청 예시 +fetch('http://localhost:8100/api/chat', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'x-user-id': 'user-uuid-here' + }, + body: JSON.stringify({ + message: '안녕하세요', + context: {} + }) +}) +``` + +### 2. 워크스페이스 할당 테스트 +```sql +-- 사용자를 워크스페이스에 할당 +INSERT INTO workspace_members ( + id, user_id, workspace_id, role, robing_id, is_active +) VALUES ( + gen_random_uuid(), + 'USER_UUID', -- 실제 사용자 ID + (SELECT id FROM workspaces WHERE subdomain = 'test'), + 'member', + 'rb10508_micro', + true +); +``` + +### 3. 모니터링 구현 +- robing-control 서비스 분리 (관리 대시보드) +- robing-monitor 서비스 구현 (24서버 모니터링) +- 메트릭 수집 및 시각화 + +### 4. 인증 통합 +- auth-server와 연동 +- JWT 토큰 검증 +- 세션 관리 + +## 오후 1시 30분 - Frontend 통합 및 프로덕션 배포 + +### Frontend 연동 작업 + +**nginx 설정 추가**: +```nginx +# HTTP와 HTTPS 모두에 추가 +location ^~ /gateway/ { + proxy_pass http://localhost:8100/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; +} +``` + +**Frontend 수정**: +```javascript +// robing-api.ts 변경사항 +// 1. 엔드포인트: /api/message → /api/chat +// 2. X-User-Id 헤더 추가 +// 3. 요청 body: text → message 필드 + +headers: { + 'Content-Type': 'application/json', + 'X-User-Id': userId +}, +body: JSON.stringify({ + message: text, // Gateway가 text로 변환 + user_id: userId +}) +``` + +### 통합 테스트 결과 + +**시스템 상태 (오후 1:44 기준)**: +- Gateway 컨테이너: 2시간째 안정 운영 (healthy) +- nginx 프록시: 정상 작동 +- Frontend: 최신 빌드 배포 완료 (13:39) +- rb10508_micro: 정상 응답 + +**통신 경로 검증**: +``` +https://ro-being.com/gateway/api/chat +→ nginx (/gateway/) +→ Gateway (localhost:8100) +→ rb10508_micro (192.168.219.52:10508) +→ 응답: "안녕하세요. 로빙입니다. 무엇을 도와드릴까요?" +``` + +**운영 지표**: +- Health Check: ✅ (cache_size: 1, DB 연결 정상) +- 캐시 TTL: 30분 (사용자 매핑 유지) +- 기본 로빙: rb10508_micro (워크스페이스 미할당 사용자용) + +## 교훈 + +1. **기존 스키마 활용**: 새 테이블 생성보다 기존 구조 재사용이 효율적 +2. **Docker 네트워킹**: 컨테이너에서 호스트 DB 접근 시 host.docker.internal 사용 +3. **API 명세 확인**: 프록시 대상 서비스의 정확한 엔드포인트와 요청 형식 사전 확인 필수 +4. **단계적 구현**: Phase 1에서 기본 기능 구현 후 점진적 기능 추가 +5. **nginx 프록시 설정**: proxy_pass 끝에 `/` 필수, HTTP/HTTPS 모두 설정 +6. **환경변수 관리**: 서버 .env와 프론트 .env 분리 관리 (VITE_ prefix) + +## 오후 2시 00분 - 테스트 데이터 생성 및 전체 시스템 통합 완료 + +### 테스트 데이터 SQL 작성 문제 + +**첫 번째 시도 - UUID 형식 오류**: +```sql +-- 잘못된 형식 (문자열을 UUID 컬럼에 삽입 시도) +INSERT INTO workspaces (id, ...) VALUES ('ws-ivada-001', ...); +INSERT INTO users (id, ...) VALUES ('user-happybell80', ...); +``` + +**두 번째 시도 - role 값 오류**: +```sql +-- role은 대문자여야 함 +INSERT INTO workspace_members (..., role, ...) VALUES (..., 'owner', ...); -- X +INSERT INTO workspace_members (..., role, ...) VALUES (..., 'OWNER', ...); -- O +``` + +**최종 수정 버전**: +```sql +-- 올바른 UUID 형식과 대문자 role +INSERT INTO workspaces (id, ...) VALUES +('11111111-1111-1111-1111-111111111111'::uuid, ...); + +INSERT INTO users (id, email, name) VALUES +('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'::uuid, 'goeun2dc@gmail.com', '김종태'), +('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb'::uuid, '0914eagle@gmail.com', '전희재'), +('cccccccc-cccc-cccc-cccc-cccccccccccc'::uuid, 'hhyong91@gmail.com', '황한용'); + +INSERT INTO workspace_members (..., role, ...) VALUES +(..., 'OWNER', ...), -- 김종태 +(..., 'MEMBER', ...); -- 전희재, 황한용 +``` + +### 전체 시스템 통합 테스트 결과 + +**데이터베이스 상태**: +- workspaces: 1개 (ivada-robeing) +- users: 3개 (김종태, 전희재, 황한용) +- workspace_members: 3개 (모두 rb10508_micro 할당) + +**통합 테스트 성공 (오후 2:13)**: +1. **인증 흐름**: + - 구글 OAuth 로그인 → auth-server + - User ID 발급: `aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa` + +2. **Gateway 라우팅**: + - X-User-Id 헤더로 사용자 식별 + - DB 조회: workspace_members → robing_id 확인 + - rb10508_micro (192.168.219.52:10508)로 라우팅 + +3. **개인화된 응답**: + - 요청: "안녕하세요" + - 응답: "안녕하세요, 김종태님. 로빙입니다." + +**시스템 구조 검증**: +``` +Frontend → nginx(/gateway/) → Gateway(8100) → DB 조회 + ↓ + workspace_members + ↓ + rb10508_micro → 맞춤 응답 +``` + +## 교훈 + +1. **기존 스키마 활용**: 새 테이블 생성보다 기존 구조 재사용이 효율적 +2. **Docker 네트워킹**: 컨테이너에서 호스트 DB 접근 시 host.docker.internal 사용 +3. **API 명세 확인**: 프록시 대상 서비스의 정확한 엔드포인트와 요청 형식 사전 확인 필수 +4. **단계적 구현**: Phase 1에서 기본 기능 구현 후 점진적 기능 추가 +5. **nginx 프록시 설정**: proxy_pass 끝에 `/` 필수, HTTP/HTTPS 모두 설정 +6. **환경변수 관리**: 서버 .env와 프론트 .env 분리 관리 (VITE_ prefix) +7. **PostgreSQL UUID 타입**: 문자열이 아닌 UUID 형식 사용, `::uuid` 캐스트 필수 +8. **ENUM 값 확인**: role 같은 ENUM 타입은 대소문자 확인 필수 (OWNER, MEMBER) + +## 최종 성과 + +- **완전한 사용자-로빙 매핑 시스템 구축** +- **3명의 테스트 사용자로 멀티테넌시 검증** +- **Gateway를 통한 지능형 라우팅 구현** +- **개인화된 응답 시스템 완성** + +## 참고 자료 + +- 서비스 재구조화 계획: `/DOCS/ideas/250807_서비스_재구조화_계획.md` +- Gateway 저장소: `https://git.ro-being.com/ivada_Ro-being/robeing-gateway` +- 포트 정보: 8100 (현재) → 8000 (프로덕션, frontend-base 대체 시) +- 테스트 데이터: `/scripts/test_data.sql` \ No newline at end of file