DOCS/troubleshooting/250809_happybell80_robing-gateway구현.md
happybell80 97e0888ce0 Fix more incorrect table names in documentation
- 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
2025-09-26 00:52:15 +09:00

9.7 KiB

robeing-gateway API 게이트웨이 구현 및 배포

날짜: 2025-08-09
작업자: happybell80 & Claude & 23서버팀
관련 서버: 51123 (Gateway 실행), 51124 (로빙 서비스)

배경

서비스 재구조화 계획에 따라 Frontend와 로빙 서비스 간 중앙 라우팅 레이어 구현 필요. 기존 frontend-base의 일부 기능을 분리하여 독립적인 API Gateway 서비스로 구축.

오전 10시 30분 - 초기 구현

구현 내용

프로젝트 구조:

robeing-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. 기존 main_db 테이블 활용 (workspaces, workspace_member)
  4. 헬스체크 및 모니터링 엔드포인트

23서버팀 피드백

중요 변경사항 - 새 테이블 불필요:

  • 기존 main_db의 workspaces, workspace_member 테이블 활용
  • workspace_member에서 user_id로 robeing 정보 조회
  • JOIN 쿼리로 사용자 → 워크스페이스 → 로빙 매핑

오전 11시 00분 - 배포 문제 해결

문제 1: API 엔드포인트 불일치

원인:

  • Gateway가 /api/chat으로 프록시 시도
  • rb10508_micro는 /api/message 엔드포인트 사용

해결:

# app/main.py 수정
target_url = f"{base_url}/api/message"  # rb10508_micro uses /api/message

문제 2: 요청 body 형식 불일치

원인:

  • Frontend는 message 필드 전송
  • rb10508_micro는 text 필드 예상

해결:

# 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 접근 불가

해결:

# .env.example 수정
DATABASE_URL=postgresql+asyncpg://robeings:패스워드@host.docker.internal:5432/main_db

문제 4: Gitea Actions 환경변수

원인:

  • ${{ gitea.workspace }} 변수 인식 실패

해결:

  • ${{ github.workspace }} 사용 (Gitea가 GitHub Actions 호환 변수 지원)

오전 11시 45분 - 최종 배포 성공

배포 결과

정상 작동 확인:

# 헬스체크
curl http://localhost:8100/health
# 결과: {"status":"healthy","cache_size":0,"database":"connected"}

# DB 테이블 확인
SELECT COUNT(*) FROM workspaces;  # 2 (테스트 데이터)

현재 상태:

  • robeing-gateway 포트 8100에서 정상 실행
  • PostgreSQL main_db 연결 성공
  • DEFAULT_ROBEING_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 연동 테스트

// 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. 워크스페이스 할당 테스트

-- 사용자를 워크스페이스에 할당
INSERT INTO workspace_member (
    id, user_id, workspace_id, role, robeing_id, is_active
) VALUES (
    gen_random_uuid(),
    'USER_UUID',  -- 실제 사용자 ID
    (SELECT id FROM workspaces WHERE subdomain = 'test'),
    'member',
    'rb10508_micro',
    true
);

3. 모니터링 구현

  • robeing-control 서비스 분리 (관리 대시보드)
  • robeing-monitor 서비스 구현 (24서버 모니터링)
  • 메트릭 수집 및 시각화

4. 인증 통합

  • auth-server와 연동
  • JWT 토큰 검증
  • 세션 관리

오후 1시 30분 - Frontend 통합 및 프로덕션 배포

Frontend 연동 작업

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 수정:

// robeing-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 형식 오류:

-- 잘못된 형식 (문자열을 UUID 컬럼에 삽입 시도)
INSERT INTO workspaces (id, ...) VALUES ('ws-ivada-001', ...);
INSERT INTO user (id, ...) VALUES ('user-happybell80', ...);

두 번째 시도 - role 값 오류:

-- role은 대문자여야 함
INSERT INTO workspace_member (..., role, ...) VALUES (..., 'owner', ...);  -- X
INSERT INTO workspace_member (..., role, ...) VALUES (..., 'OWNER', ...);   -- O

최종 수정 버전:

-- 올바른 UUID 형식과 대문자 role
INSERT INTO workspaces (id, ...) VALUES 
('11111111-1111-1111-1111-111111111111'::uuid, ...);

INSERT INTO user (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_member (..., role, ...) VALUES
(..., 'OWNER', ...),   -- 김종태
(..., 'MEMBER', ...);  -- 전희재, 황한용

전체 시스템 통합 테스트 결과

데이터베이스 상태:

  • workspaces: 1개 (ivada-robeing)
  • users: 3개 (김종태, 전희재, 황한용)
  • workspace_member: 3개 (모두 rb10508_micro 할당)

통합 테스트 성공 (오후 2:13):

  1. 인증 흐름:

    • 구글 OAuth 로그인 → auth-server
    • User ID 발급: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
  2. Gateway 라우팅:

    • X-User-Id 헤더로 사용자 식별
    • DB 조회: workspace_member → robeing_id 확인
    • rb10508_micro (192.168.219.52:10508)로 라우팅
  3. 개인화된 응답:

    • 요청: "안녕하세요"
    • 응답: "안녕하세요, 김종태님. 로빙입니다."

시스템 구조 검증:

Frontend → nginx(/gateway/) → Gateway(8100) → DB 조회
                                    ↓
                            workspace_member
                                    ↓
                            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