# 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 활용
- [ ] 슬래시 커맨드 확장

---

**문서 끝**
