- 90% 완료 상태 - Gateway 라우팅, nginx 프록시, JWT 인증 모두 해결 - GET 요청 정상 작동 - PUT 요청 500 에러 디버깅 필요
9.2 KiB
9.2 KiB
Frontend ActivityPanel과 Backend user_preferences 연동 구현
작성일: 2025-08-27
작성자: happybell80 / 51123 서버 관리자
상태: 🟡 진행중 - Gateway 라우팅 추가 필요
영향: 사용자 설정 기능 연동
최종 업데이트: 2025-08-27 22:00
1. 현재 상황
✅ 완료된 작업
- Backend: robeing-monitor에 preferences API 구현 (GET/PUT)
- Frontend: localStorage → API 호출로 변경 완료
- 배포: robeing-monitor 51124:9024에서 실행 중
🔴 남은 문제
- Gateway 라우팅:
/api/preferences를 robeing-monitor로 프록시 안함 - 현재: 모든
/api/*요청이 rb8001로만 감
2. 현재 구현 상태
2.1 Frontend (ActivityPanel.tsx)
- 위치:
/frontend-customer/src/components/activity-panel.tsx - 구현 완료: UI 컴포넌트 및 로직
- 데이터 저장: localStorage (목업)
- 기능:
- 다중 브리핑 작업 관리 (task.id별)
- 키워드 추가/삭제
- 스케줄 설정 (매일/평일/주말/커스텀)
- 포함 항목 선택 (이메일/뉴스/캘린더/슬랙)
2.2 Backend (user_preferences 테이블)
- 위치: PostgreSQL main_db
- 구조:
CREATE TABLE user_preferences ( id SERIAL PRIMARY KEY, user_id UUID REFERENCES users(id), slack_user_id VARCHAR(100), news_keywords VARCHAR(128)[], -- 뉴스 키워드 배열 email_filter VARCHAR(128)[], -- 이메일 필터 (미사용) briefing_enabled BOOLEAN DEFAULT true, briefing_time TIME DEFAULT '09:00', updated_at TIMESTAMP DEFAULT NOW() );
2.3 rb8001 사용 현황
- dm_skill.py: user_preferences에서 news_keywords 조회
- 사용자별 맞춤 뉴스: 정상 작동 중
- 브리핑 시간: briefing_time 사용 중
3. 핵심 문제점
3.1 데이터 모델 불일치
| Frontend TaskSettings | Backend user_preferences | 불일치 내용 |
|---|---|---|
| keywords: string[] | news_keywords VARCHAR(128)[] | ✅ 호환 가능 |
| scheduleTime: string | briefing_time TIME | ⚠️ 타입 변환 필요 |
| scheduleType: 'everyday' | 'weekdays' | ... | - | ❌ 필드 없음 |
| scheduleDays: string[] | - | ❌ 필드 없음 |
| includeEmail: boolean | - | ❌ 필드 없음 |
| includeNews: boolean | - | ❌ 필드 없음 |
| includeCalendar: boolean | - | ❌ 필드 없음 |
| includeSlack: boolean | - | ❌ 필드 없음 |
3.2 다중 작업 관리 불가
- Frontend: 여러 개의 scheduledTask 관리 (일일 브리핑, 주간 리포트 등)
- Backend: 사용자당 1개 설정만 저장 가능
- 영향: "일일 브리핑", "주간 리포트" 등 구분 불가
3.3 Mock 데이터 하드코딩
// ActivityPanel.tsx:155-210
const conversations: ConversationSession[] = [...]; // 하드코딩
const activities: ActivityLog[] = [...]; // 하드코딩
const scheduledTasks: ScheduledTask[] = [...]; // 하드코딩
- 실제 데이터 조회 API 없음
- conversation_logs 테이블 조회 엔드포인트 필요
3.4 ✅ 해결됨: API 구현
- robeing-monitor: preferences API 완전 구현
- GET /api/preferences/{user_id}: 조회
- PUT /api/preferences/{user_id}: 업데이트
- 고정값 반환: 미구현 필드는 기본값 제공
3.5 🔴 Gateway 라우팅 문제
# robeing-gateway/main.py:407
@app.get("/api/{path:path}") # 모든 GET → rb8001로
# /api/preferences도 rb8001로 가서 404 발생
필요한 수정:
/api/preferences/*→ robeing-monitor(9024)로 프록시- JWT에서 UUID 추출하여 전달
3.6 실시간 동기화 부재
- localStorage 기반으로 다른 디바이스와 동기화 안됨
- WebSocket이나 polling 구현 없음
3.7 권한 검증 누락
- user_preferences 수정 시 본인 확인 로직 필요
- 다른 사용자 설정 수정 가능한 보안 문제
4. 해결 방안
4.1 단기 해결책 (최소 수정)
-
Backend 스키마 확장
ALTER TABLE user_preferences ADD COLUMN schedule_type VARCHAR(20); ALTER TABLE user_preferences ADD COLUMN schedule_days VARCHAR(10)[]; ALTER TABLE user_preferences ADD COLUMN include_email BOOLEAN DEFAULT true; ALTER TABLE user_preferences ADD COLUMN include_news BOOLEAN DEFAULT true; ALTER TABLE user_preferences ADD COLUMN include_calendar BOOLEAN DEFAULT false; ALTER TABLE user_preferences ADD COLUMN include_slack BOOLEAN DEFAULT false; -
robeing-monitor에 CRUD API 추가
GET /api/preferences/{user_id} PUT /api/preferences/{user_id} GET /api/conversations/{user_id}?limit=10 GET /api/activities/{user_id}?limit=10 -
ActivityPanel localStorage → API 호출 변경
4.2 중기 해결책 (구조 개선)
-
scheduled_tasks 테이블 생성
CREATE TABLE scheduled_tasks ( id SERIAL PRIMARY KEY, user_id UUID REFERENCES users(id), task_type VARCHAR(50), -- 'daily_briefing', 'weekly_report' 등 title VARCHAR(255), schedule_type VARCHAR(20), schedule_days VARCHAR(10)[], schedule_time TIME, settings JSONB, -- 유연한 설정 저장 enabled BOOLEAN DEFAULT true ); -
Frontend와 Backend 인터페이스 통일
- 공통 TypeScript 타입 정의
- API 응답 형식 표준화
4.3 장기 해결책 (완전 재설계)
-
마이크로서비스 분리
- user-preferences-service 별도 구현
- GraphQL 도입 검토
-
실시간 동기화
- WebSocket 구현
- 설정 변경 시 실시간 반영
5. 구현 현황 (2025-08-27 22:00)
✅ 완료
- Backend API: robeing-monitor에 구현 완료
- Frontend 수정: API 호출 코드 추가, 자동 저장
- UI 처리: 미구현 필드 비활성화 (opacity-50)
- 배포: 51124:9024 정상 작동
🟡 진행중
- Gateway 라우팅: preferences 전용 프록시 추가 필요
⚠️ 작동 방식
- 현재: Frontend → Gateway(8100) → rb8001 → 404
- 필요: Frontend → Gateway(8100) → robeing-monitor(9024)
6. 아키텍처 상세
데이터 흐름
Frontend (브라우저)
↓
[자동 저장 트리거]
↓
fetch('/api/preferences/{UUID}') # Gateway 경유
↓
Gateway (8100) + JWT 인증
↓
[라우팅 필요: preferences → 9024]
↓
robeing-monitor (9024)
↓
PostgreSQL user_preferences 테이블
UUID 체계
- JWT sub: UUID (1e16e9d5-59f3-54da-a661-8abeabff4230)
- localStorage: user_id에 UUID 저장
- API 경로:
/api/preferences/{UUID}
7. 관련 파일
Frontend
/home/happybell/projects/ivada/frontend-customer/src/components/activity-panel.tsx
Backend
/home/happybell/projects/ivada/robeing-monitor/app/api/items.py/home/happybell/projects/ivada/robeing-gateway/app/main.py/home/happybell/projects/ivada/rb8001/app/skills/dm_skill.py
문서
/home/happybell/projects/ivada/DOCS/troubleshooting/250826_slack_id_column_standardization.md
8. Gateway 라우팅 추가 코드
# /robeing-gateway/app/main.py (line 407 앞에 추가)
@app.api_route("/api/preferences/{path:path}", methods=["GET", "PUT"])
async def proxy_preferences(
path: str,
request: Request,
x_user_id: str = Depends(get_verified_user)
):
"""Proxy preferences to robeing-monitor"""
monitor_url = "http://192.168.219.52:9024"
full_path = f"/api/preferences/{path}"
if request.method == "GET":
response = await http_client.get(f"{monitor_url}{full_path}")
elif request.method == "PUT":
body = await request.json()
response = await http_client.put(
f"{monitor_url}{full_path}",
json=body,
headers={"X-User-Id": x_user_id}
)
return response.json() if response.status_code == 200 else {"error": "Failed"}
9. 결론
90% 완료 - PUT 요청 500 에러 해결 필요
- Backend API ✅
- Frontend 수정 ✅
- Gateway 라우팅 ✅
- nginx 프록시 ✅ (/gateway/ 사용)
- JWT 인증 ✅
- GET 요청 ✅ (200 OK)
- PUT 요청 ❌ (500 에러 - robeing-monitor 문제)
10. 구현 과정 (2025-08-27)
Phase 1: Backend API 구현 (20:00)
- robeing-monitor에 preferences API 추가
- 기존 컬럼만 사용 (news_keywords, briefing_time)
- 확장 필드는 고정값 반환
Phase 2: Frontend 수정 (21:00)
- localStorage → API 호출 변경
- 자동 저장 방식 구현
- 미구현 필드 UI 비활성화
Phase 3: Gateway 라우팅 (22:00)
- preferences 전용 라우팅 추가
- robeing-monitor(9024)로 프록시
Phase 4: 경로 문제 해결 (22:30)
- ❌ 처음: 직접 호출 (http://192.168.219.52:9024) - Mixed Content 에러
- ❌ 다음: /api/preferences - nginx가 frontend-base(8000)로 전달
- ✅ 해결: /gateway/api/preferences - Gateway(8100) 경유
Phase 5: JWT 인증 추가 (22:40)
- Frontend에서 Authorization 헤더 누락 발견
- localStorage의 'token' || 'auth_token' 사용
- Bearer 토큰 형식으로 전달
현재 상태 (22:45)
- GET /api/preferences/{user_id}: 200 OK ✅
- PUT /api/preferences/{user_id}: 500 에러 (robeing-monitor 내부 문제)
최종 수정: 2025-08-27 22:45 상태: robeing-monitor PUT 처리 디버깅 필요