# Slack 기반 인터페이스 아키텍처 ## 작성일: 2025-08-21 ## 작성자: Claude (51123 서버 관리자) --- ## 1. 개요 Slack을 통한 로빙 서비스 접근 아키텍처. 실시간 대화형 인터페이스를 제공하며, 51123 매핑 API 기반 사용자 식별 체계를 사용합니다. --- ## 2. 시스템 구조 ### 2.1 전체 플로우 ```mermaid sequenceDiagram participant User as Slack 사용자 participant Slack as Slack API participant RB as rb10508_micro participant Gateway as Gateway(8100) participant Auth as auth-server(9000) participant DB as PostgreSQL participant Skill as 스킬 서비스 User->>Slack: 메시지 전송 Slack->>RB: Event Webhook Note over RB: Slack User ID: U0925SXQFDK RB->>Auth: 매핑 API 호출 Note over RB: /api/slack/mapping/{slack_id} Auth-->>RB: UUID 반환 RB->>DB: 사용자 조회 (UUID) DB-->>RB: 사용자 정보 RB->>RB: 의도 분류 RB->>Skill: 필요시 스킬 호출 Skill-->>RB: 처리 결과 RB->>Skill: Slack 전송 요청 Skill-->>Slack: chat.postMessage Slack-->>User: 메시지 표시 ``` ### 2.2 사용자 식별 체계 #### 매핑 API 호출 ```python import httpx async def get_user_uuid(slack_user_id: str) -> str: """51123 매핑 API를 통해 UUID 조회""" async with httpx.AsyncClient() as client: response = await client.get( f"http://192.168.0.100:9000/api/slack/mapping/{slack_user_id}" ) if response.status_code == 200: return response.json()["user_id"] return None # 예시 slack_id = "U0925SXQFDK" user_uuid = await get_user_uuid(slack_id) # DB에서 UUID 조회 ``` #### 사용자 데이터 구조 ```sql -- users 테이블 CREATE TABLE user ( id UUID PRIMARY KEY, -- slack_user_mapping에서 조회 username VARCHAR(50), -- slack_U0925SXQ 형태 email VARCHAR(255), name VARCHAR(255), oauth_provider VARCHAR(50) DEFAULT 'slack', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ``` --- ## 3. 서비스 구성 ### 3.1 서버 배치 | 서버 | 서비스 | 포트 | 역할 | |------|--------|------|------| | 51123 | auth-server | 9000 | OAuth 인증 | | 51123 | robeing-gateway | 8100 | API 프록시 | | 51124 | rb10508_micro | 10508 | Slack 이벤트 처리 | | 51124 | rb8001 | 8001 | 프로덕션 로빙 | ### 3.2 Slack 앱 설정 #### Event Subscriptions ```yaml Request URL: https://[도메인]/api/slack/events Events: - app_mention - message.channels - message.groups - message.im - message.mpim ``` #### OAuth Scopes ```yaml Bot Token Scopes: - app_mentions:read - channels:read - chat:write - chat:write.public - im:read - im:write - users:read ``` --- ## 4. 메시지 처리 플로우 ### 4.1 일반 대화 ```mermaid flowchart TD A[Slack 메시지] --> B{이벤트 타입} B -->|app_mention| C[멘션 처리] B -->|message| D[일반 메시지] C --> E[매핑 API 호출] D --> E E --> F[사용자 컨텍스트 로드] F --> G[의도 분류] G --> H{의도 타입} H -->|대화| I[LLM 응답 생성] H -->|이메일| J[skill-email 호출] H -->|뉴스| K[skill-news 호출] I --> L[Slack 응답] J --> L K --> L ``` ### 4.2 Gmail 연동 플로우 ```mermaid sequenceDiagram participant User as Slack 사용자 participant RB as rb10508_micro participant Monitor as robeing-monitor participant Skill as skill-email participant Gmail as Gmail API User->>RB: "이메일 보내줘" RB->>Auth: 매핑 API 호출 Auth-->>RB: UUID 반환 RB->>Monitor: Gmail 아이템 확인 alt 아이템 미장착 Monitor-->>RB: NOT_EQUIPPED RB-->>User: "Gmail 연결이 필요합니다" else 아이템 장착됨 Monitor-->>RB: EQUIPPED RB->>Skill: 이메일 발송 요청 Skill->>Gmail: API 호출 Gmail-->>Skill: 발송 완료 Skill-->>RB: 성공 RB-->>User: "메일을 보냈습니다" end ``` --- ## 5. 3초 룰 대응 ### 5.1 비동기 처리 패턴 ```python @app.post("/api/slack/events") async def handle_slack_event(request: Request): # 1. 즉시 응답 (3초 내) background_tasks.add_task(process_event, event_data) return {"status": "ok"} async def process_event(event_data): # 2. 실제 처리 (백그라운드) response = await generate_response(event_data) # 3. skill-slack을 통해 응답 전송 async with httpx.AsyncClient() as client: await client.post( "http://skill-slack:8502/api/v1/send", json={"channel": event_data["channel"], "text": response} ) ``` ### 5.2 타이핑 인디케이터 ```python async def show_typing(channel: str): """처리 중임을 표시 (전송은 skill-slack 경유)""" # 구현 시 skill-slack 지원 엔드포인트 사용 또는 안내 메시지를 /send로 전달 ``` --- ## 6. 데이터베이스 구조 ### 6.1 Slack 관련 테이블 ```sql -- Slack 사용자 매핑 (slack_user_mapping 테이블 사용) -- 대신 users 테이블에서 직접 관리 -- 대화 로그 CREATE TABLE conversation_log ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID, -- slack_user_mapping에서 조회한 UUID robeing_id VARCHAR(50), channel_id VARCHAR(50), message_type VARCHAR(20), -- 'user' or 'bot' message TEXT, metadata JSONB, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ``` --- ## 7. 에러 처리 ### 7.1 일반 에러 응답 ```python ERROR_MESSAGES = { "NO_USER": "사용자를 찾을 수 없습니다. 관리자에게 문의하세요.", "TIMEOUT": "처리 시간이 초과되었습니다. 다시 시도해주세요.", "SKILL_ERROR": "기능 실행 중 오류가 발생했습니다.", "AUTH_ERROR": "인증이 필요합니다." } ``` ### 7.2 재시도 로직 ```python @retry(max_attempts=3, delay=1) async def send_slack_message(channel: str, text: str): """실패시 재시도하는 메시지 전송 (skill-slack 경유)""" async with httpx.AsyncClient() as client: return await client.post( "http://skill-slack:8502/api/v1/send", json={"channel": channel, "text": text} ) ``` --- ## 8. 모니터링 ### 8.1 메트릭 수집 - 응답 시간 - 에러율 - 사용자별 요청 수 - 스킬 사용 통계 ### 8.2 로그 구조 ```json { "timestamp": "2025-08-21T10:30:00Z", "user_id": "매핑된-UUID", "slack_user_id": "U0925SXQFDK", "channel": "C1234567890", "message": "사용자 메시지", "response": "로빙 응답", "processing_time": 1.5, "status": "success" } ``` --- ## 9. 보안 고려사항 ### 9.1 인증 - Slack 서명 검증 필수 - 재전송 공격 방지 (timestamp 검증) ### 9.2 권한 관리 - 채널별 접근 권한 - 사용자별 기능 제한 - 레벨 기반 스킬 접근 --- ## 10. 향후 개선사항 ### 10.1 단기 - [ ] 스레드 대화 지원 - [ ] 이모지 반응 처리 - [ ] 파일 업로드 지원 ### 10.2 장기 - [ ] Slack 워크플로우 통합 - [ ] 블록 UI 활용 - [ ] 슬래시 커맨드 확장 --- **문서 끝**