# 맥락기반 용어설명 데이터 확보 및 Claude AI 연동 아키텍처 결정 문서

## 1단계: 각자의 생각

### 민준 (Product Owner)
비즈니스 관점에서 용어 데이터는 두 가지 소스가 핵심입니다.
1. **조직 문서**: 내부 업무 매뉴얼, 정책, 프로젝트 문서가 차별화의 핵심
2. **외부 기술 문서**: 범용 기술 용어는 보조적으로 활용

데이터 품질이 서비스 차별화의 핵심이므로, 초기에는 작은 규모로 시작해도 정확도가 높아야 합니다. MVP에서는 핵심 조직 문서 100개 정도로 시작하고, 점진적으로 확장하는 전략이 필요합니다.

### 서연 (AI Specialist)
**전문용어 처리 파이프라인**을 4단계로 제안합니다:

1. **수집 (Collection)**
   - 조직문서: SharePoint, Confluence, Google Drive API 연동
   - 외부문서: 공개 API 문서, GitHub 기술문서

2. **추출 (Extraction)**
   - NER(Named Entity Recognition) 기반 기술용어 추출
   - TF-IDF + 도메인 사전 기반 조직 특화 용어 추출
   - Claude API를 활용한 맥락 기반 용어 추출

3. **정제 (Refinement)**
   - 중복 제거: Fuzzy matching으로 유사 용어 통합
   - 품질 검증: 인간 피드백 루프(HITL) 구축
   - 메타데이터 태깅: 카테고리, 출처, 신뢰도 점수

4. **벡터라이징 (Vectorization)**
   - **임베딩 모델**: OpenAI text-embedding-3-large 또는 Cohere embed-multilingual-v3.0
   - **벡터 DB**: Pinecone 또는 Qdrant (관리형 vs 자체 호스팅)
   - **청크 전략**: 
     - 용어 정의: 단일 청크 (256 토큰)
     - 문맥 정보: 슬라이딩 윈도우 (512 토큰, 128 오버랩)

**Claude API 연동 구조**:
```json
{
  "request": {
    "model": "claude-sonnet-4-5-20250929",
    "max_tokens": 1024,
    "system": "당신은 회의록 작성 보조 AI입니다. 전문용어를 회의 맥락에 맞춰 설명해주세요.",
    "messages": [
      {
        "role": "user",
        "content": [
          {
            "type": "text",
            "text": "회의 내용: {meeting_transcript}\n\n발견된 용어: {term}\n\n관련 문서:\n{rag_context}\n\n위 용어를 회의 맥락에 맞춰 2-3문장으로 설명해주세요."
          }
        ]
      }
    ]
  },
  "response": {
    "id": "msg_...",
    "type": "message",
    "role": "assistant",
    "content": [
      {
        "type": "text",
        "text": "API Gateway는 클라이언트와 백엔드 서비스 사이의 단일 진입점으로..."
      }
    ],
    "model": "claude-sonnet-4-5-20250929",
    "stop_reason": "end_turn",
    "usage": {
      "input_tokens": 450,
      "output_tokens": 120
    }
  }
}
```

### 준호 (Backend Developer)
**데이터 아키텍처 및 API 설계**를 제안합니다:

**1. 데이터 소스별 수집 전략**
```
조직 문서:
├── Confluence API (주간 배치)
├── SharePoint Graph API (주간 배치)
├── Google Drive API (주간 배치)
└── 수동 업로드 (관리자 페이지)

외부 문서:
├── GitHub 기술문서 크롤링 (월간 배치)
├── 공개 API 문서 (Swagger/OpenAPI)
└── 산업 표준 용어집 (수동 큐레이션)
```

**2. 데이터베이스 스키마**
```sql
-- 용어 마스터 테이블
CREATE TABLE terms (
    term_id UUID PRIMARY KEY,
    term_name VARCHAR(200) NOT NULL,
    normalized_name VARCHAR(200) NOT NULL,
    category VARCHAR(50),
    source_type VARCHAR(20), -- 'internal', 'external'
    definition TEXT,
    context TEXT,
    confidence_score DECIMAL(3,2),
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    INDEX idx_normalized (normalized_name),
    INDEX idx_category (category)
);

-- 용어-문서 매핑 테이블
CREATE TABLE term_documents (
    mapping_id UUID PRIMARY KEY,
    term_id UUID REFERENCES terms(term_id),
    document_id UUID,
    relevance_score DECIMAL(3,2),
    excerpt TEXT,
    created_at TIMESTAMP
);

-- 벡터 인덱스 메타데이터
CREATE TABLE term_vectors (
    vector_id UUID PRIMARY KEY,
    term_id UUID REFERENCES terms(term_id),
    embedding_model VARCHAR(50),
    vector_store_key VARCHAR(200),
    created_at TIMESTAMP
);
```

**3. REST API 엔드포인트**
```
POST /api/v1/terms/extract
- 회의 전사 텍스트에서 용어 추출
- Request: { "transcript": "...", "meeting_id": "..." }
- Response: { "terms": [...], "extraction_time_ms": 1234 }

GET /api/v1/terms/{term_id}/context
- 특정 용어의 맥락 정보 조회
- Query params: meeting_context, max_results
- Response: { "term": {...}, "related_docs": [...], "ai_explanation": "..." }

POST /api/v1/terms/search
- 벡터 유사도 검색
- Request: { "query": "...", "filters": {...}, "top_k": 5 }
- Response: { "results": [...], "search_time_ms": 234 }
```

**4. 성능 최적화**
- Redis 캐싱: 자주 조회되는 용어 (TTL 1시간)
- CDN 캐싱: 외부 기술 문서 용어 (TTL 24시간)
- 배치 처리: 야간 시간대 벡터 업데이트

### 동욱 (Backend Developer)
**실용적인 구현 전략**을 제안합니다:

**Phase 1: MVP (4주)**
- JSON 파일 기반 용어 사전 (terms-dictionary.json)
- 수동 큐레이션 50개 핵심 용어
- Claude API 직접 호출 (RAG 없이 프롬프트 기반)
- 간단한 키워드 매칭

**Phase 2: 기본 RAG (4주)**
- PostgreSQL + pgvector 확장
- 조직 문서 100개 수집/임베딩
- 기본 벡터 검색 구현
- Claude API + RAG context 연동

**Phase 3: 고도화 (8주)**
- Pinecone 또는 Qdrant 도입
- 자동 수집 파이프라인 구축
- 하이브리드 검색 (키워드 + 벡터)
- 피드백 루프 및 품질 개선

**인프라 구성**:
```yaml
services:
  term-extraction:
    - NLP 서버 (Python FastAPI)
    - spaCy, transformers 라이브러리
    - 배치 작업용 Celery worker
  
  vector-search:
    - Qdrant (self-hosted) 또는 Pinecone (managed)
    - API Gateway 통합
    
  claude-api-proxy:
    - Rate limiting (100 req/min)
    - Response caching (Redis)
    - Error handling & retry logic
```

### 유진 (Frontend Developer)
**사용자 경험 관점**에서 고려사항:

1. **실시간 용어 감지 UI**
   - STT 텍스트 스트리밍 중 용어 하이라이트
   - 1초 이내 반응 속도 보장
   - 로딩 스피너 대신 skeleton UI

2. **용어 설명 모달**
   - 빠른 프리뷰: 2-3줄 요약
   - 상세보기 확장: 관련 문서 링크
   - 즐겨찾기 기능

3. **성능 최적화**
   - 용어 데이터 prefetch (회의 시작 시)
   - 자주 사용되는 용어 로컬 캐싱
   - Debouncing으로 API 호출 최소화

### 길동 (Architect)
**전체 시스템 아키텍처**를 제안합니다:

```
┌─────────────────────────────────────────────────────────┐
│                    Client (Web/Mobile)                   │
└────────────────────┬────────────────────────────────────┘
                     │
┌────────────────────▼────────────────────────────────────┐
│                   API Gateway                            │
│            (Rate Limiting, Auth, Routing)                │
└────────┬──────────────────────────┬─────────────────────┘
         │                          │
┌────────▼────────┐      ┌─────────▼──────────┐
│  Meeting Service│      │  AI Service         │
│  - 회의 진행     │      │  - 용어 추출         │
│  - STT 연동     │      │  - RAG 검색         │
│  - 실시간 협업   │      │  - Claude API 연동   │
└────────┬────────┘      └─────────┬──────────┘
         │                          │
         │               ┌──────────▼───────────┐
         │               │  Vector Store        │
         │               │  (Qdrant/Pinecone)   │
         │               └──────────────────────┘
         │
┌────────▼─────────────────────────────────────┐
│            PostgreSQL                         │
│  - 회의/회의록 데이터                          │
│  - 용어 마스터 데이터                          │
│  - 메타데이터 (pgvector 확장)                 │
└───────────────────────────────────────────────┘

┌──────────────────────────────────────────────┐
│         Data Pipeline (배치 처리)             │
│  1. 문서 수집 (Confluence, SharePoint, etc)  │
│  2. 용어 추출 & 정제                         │
│  3. 벡터 임베딩 & 저장                       │
│  4. 품질 검증 (Human-in-the-loop)           │
└──────────────────────────────────────────────┘
```

**주요 아키텍처 결정**:
1. **벡터 DB 선택**: Qdrant (자체 호스팅) - 비용 절감, 커스터마이징 용이
2. **임베딩 모델**: OpenAI text-embedding-3-large - 다국어 지원, 높은 정확도
3. **캐싱 전략**: 3-tier (Browser → Redis → Vector DB)
4. **확장성**: 마이크로서비스 분리로 독립적 스케일링 가능

### 도현 (QA Engineer)
**품질 보증 관점**:

1. **데이터 품질 검증**
   - 용어 추출 정확도: 85% 이상
   - 용어 설명 적합성: 사용자 피드백 4.0/5.0 이상
   - False positive rate: 10% 이하

2. **성능 테스트 기준**
   - 용어 추출: 1000자 텍스트 기준 < 2초
   - RAG 검색: < 500ms
   - Claude API 응답: < 3초
   - 동시 사용자 100명 부하 테스트

3. **테스트 시나리오**
   - 다양한 도메인 용어 (IT, 비즈니스, 법률, 의료)
   - 약어 및 동음이의어 처리
   - 긴 문맥에서의 용어 추출
   - 오프라인/저속 네트워크 환경

### 도그냥 (서비스 기획자)
**사용자 시나리오 중심 접근**:

**핵심 사용 케이스**:
1. **신입 직원**: 회의 중 모르는 약어 실시간 확인
2. **PM**: 타부서 회의 참석 시 전문용어 이해
3. **경영진**: 기술 용어를 비즈니스 맥락으로 이해

**차별화 요소**:
- 단순 사전이 아닌 "이 회의에서의 의미" 제공
- 과거 회의록 맥락 자동 연결
- 개인화된 용어 학습 이력

**MVP 검증 지표**:
- 용어 설명 조회율: 회의당 평균 3회 이상
- 도움됨 비율: 80% 이상
- 재사용률: 동일 용어 2회 이상 조회 50%

### 주영 (DevOps)
**운영 관점 인프라 설계**:

**CI/CD 파이프라인**:
```yaml
data-pipeline:
  schedule: "0 2 * * *"  # 매일 새벽 2시
  stages:
    - collect-documents
    - extract-terms
    - generate-embeddings
    - update-vector-store
    - quality-check
  
  monitoring:
    - Prometheus metrics
    - Grafana dashboard
    - Alert on failure
```

**벡터 DB 배포**:
```yaml
qdrant:
  deployment:
    replicas: 3
    resources:
      cpu: 2
      memory: 4Gi
      storage: 100Gi SSD
  
  backup:
    schedule: daily
    retention: 30 days
  
  monitoring:
    metrics:
      - query_latency_p95
      - index_size
      - memory_usage
```

**비용 최적화**:
- Spot instances for 배치 작업
- Auto-scaling for API 서버
- CloudFront CDN for 정적 용어 사전

### 현정 (콘텐츠 기획자)
**콘텐츠 품질 관점**:

1. **용어 분류 체계**
   ```
   기술 용어
   ├── 아키텍처 (API Gateway, Microservice, ...)
   ├── 프로그래밍 (REST, JWT, ...)
   └── 인프라 (Kubernetes, Docker, ...)
   
   비즈니스 용어
   ├── 전략 (MVP, PMF, ...)
   ├── 마케팅 (CAC, LTV, ...)
   └── 재무 (ARR, MRR, ...)
   
   조직 내부 용어
   ├── 프로젝트명
   ├── 팀/부서명
   └── 내부 프로세스
   ```

2. **설명 작성 가이드**
   - 1문장: 핵심 정의
   - 2문장: 회의 맥락
   - 3문장: 관련 정보/링크

3. **데이터 큐레이션 프로세스**
   - 주간 신규 용어 리뷰
   - 월간 품질 감사
   - 분기별 카테고리 재정비

### 지수 (Product Designer)
**UX/UI 디자인 관점**:

**용어 표시 디자인 시스템**:
```
용어 배지 스타일:
- 조직 용어: ⭐ 골드 배지
- 기술 용어: 🔧 블루 배지
- 비즈니스 용어: 💼 그린 배지

인터랙션:
- Hover: 1줄 미리보기 툴팁
- Click: 상세 설명 모달 (슬라이드업)
- Long press (모바일): 빠른 설명 팝업

접근성:
- 키보드 네비게이션 지원
- Screen reader 호환
- High contrast mode 지원
```

**모바일 최적화**:
- 스와이프로 용어 사전 열기
- 음성으로 용어 질문 (STT 연동)
- 오프라인 캐싱 (자주 사용 50개 용어)

---

## 2단계: 의견 종합 및 중복 제거

### A. 데이터 수집 전략
1. **초기(MVP)**: 수동 큐레이션 50-100개 핵심 조직 용어
2. **자동화**: Confluence, SharePoint, Google Drive API 배치 수집
3. **외부 소스**: GitHub 기술문서, 공개 API 문서, 산업 표준 용어집

### B. 용어 추출 및 정제
1. **추출 방법**: NER, TF-IDF, Claude API 활용 맥락 추출
2. **정제 프로세스**: 중복 제거(Fuzzy matching), 품질 검증(HITL), 메타데이터 태깅
3. **분류 체계**: 기술/비즈니스/조직 내부 용어 3대 카테고리

### C. 벡터라이징 및 저장
1. **임베딩 모델**: OpenAI text-embedding-3-large (다국어, 고정확도)
2. **벡터 DB**: Qdrant (자체 호스팅, 비용 효율적)
3. **청크 전략**: 용어 정의 256토큰, 문맥 512토큰(128 오버랩)

### D. Claude API 연동
1. **모델**: claude-sonnet-4-5-20250929
2. **프롬프트 구조**: System message + 회의 전사 + 용어 + RAG context
3. **최적화**: Rate limiting, Response caching(Redis), Error handling

### E. 시스템 아키텍처
1. **마이크로서비스 구성**: Meeting Service, AI Service 분리
2. **데이터베이스**: PostgreSQL(메인) + pgvector + Qdrant(벡터)
3. **캐싱 전략**: 3-tier (Browser → Redis → Vector DB)

### F. 성능 및 품질 목표
1. **응답 시간**: 용어 추출 <2초, RAG 검색 <500ms, 전체 <3초
2. **정확도**: 추출 85% 이상, 사용자 만족도 4.0/5.0
3. **확장성**: 동시 사용자 100명 지원

---

## 3단계: 최적안 후보 5개 선정

### 후보 1: 단계적 MVP 접근 (Lean Startup)
**특징**:
- Phase 1(4주): JSON 기반 수동 큐레이션 50개 용어
- Phase 2(4주): PostgreSQL + pgvector, 100개 문서
- Phase 3(8주): Qdrant 도입, 자동 파이프라인

**장점**:
- 빠른 시장 검증
- 초기 비용 최소화
- 점진적 학습 및 개선

**단점**:
- 초기 기능 제한적
- 기술 부채 발생 가능
- 3번의 마이그레이션 필요

**비용**: $5K (Phase 1) → $20K (Phase 2) → $50K (Phase 3)

---

### 후보 2: 하이브리드 RAG 시스템 (균형형)
**특징**:
- 조직 용어: JSON 사전 (관리자 큐레이션)
- 외부 용어: RAG 시스템 (Qdrant + OpenAI embedding)
- Claude API 통합: 맥락 기반 설명 생성

**장점**:
- 정확도와 확장성 균형
- 조직 용어 품질 보장
- 외부 용어 자동 업데이트

**단점**:
- 이원화된 시스템 관리
- 동기화 복잡성
- 중간 수준 개발 비용

**비용**: $35K (초기 구축) + $5K/월 (운영)

---

### 후보 3: Full RAG 시스템 (최대 자동화)
**특징**:
- 모든 용어 자동 추출 및 RAG 검색
- Pinecone 관리형 서비스 사용
- 실시간 문서 크롤링 및 업데이트
- 자동 품질 검증 (ML 모델)

**장점**:
- 최대 확장성
- 관리 오버헤드 최소
- 최신 정보 자동 반영

**단점**:
- 초기 구축 비용 높음
- 조직 특화 용어 정확도 낮을 수 있음
- 운영 비용 지속 발생

**비용**: $80K (초기 구축) + $12K/월 (Pinecone + API)

---

### 후보 4: 커뮤니티 큐레이션 모델
**특징**:
- 사용자가 용어 추가/수정 제안
- AI가 제안 검증 및 자동 반영
- 크라우드소싱 기반 품질 관리
- Wikipedia 스타일 버전 관리

**장점**:
- 조직 맞춤 용어 자연 축적
- 사용자 참여도 향상
- 지속적인 품질 개선

**단점**:
- 초기 콘텐츠 부족
- 품질 관리 복잡
- 악의적 편집 방지 필요

**비용**: $30K (초기) + $3K/월 (모더레이션)

---

### 후보 5: LLM 직접 활용 (RAG-less)
**특징**:
- RAG 없이 Claude API에 전체 문서 임베딩 전달
- Claude의 장문 처리 능력 활용 (200K tokens)
- 실시간 맥락 생성, 별도 벡터 DB 불필요

**장점**:
- 아키텍처 단순화
- 개발 기간 단축 (4주)
- 인프라 비용 최소

**단점**:
- API 호출 비용 높음 (토큰당 과금)
- 응답 속도 느림 (5-10초)
- 확장성 제한 (회의 수 증가 시)

**비용**: $15K (초기) + $8K/월 (Claude API)

---

## 4단계: 각 최적안 후보 평가

### 평가 기준 (가중치)
1. **비즈니스 가치** (30%): 차별화, 사용자 만족도, ROI
2. **기술적 실현 가능성** (25%): 개발 난이도, 리스크, 일정
3. **확장성** (20%): 사용자/데이터 증가 대응
4. **비용 효율성** (15%): 초기 투자, 운영 비용
5. **유지보수성** (10%): 관리 복잡도, 기술 부채

### 후보 1 평가: 단계적 MVP 접근
| 평가 기준 | 점수 | 세부 평가 |
|---------|------|---------|
| 비즈니스 가치 | 7/10 | 빠른 검증 가능, 초기 기능 제한 |
| 기술적 실현 가능성 | 9/10 | 단계별 구현, 리스크 분산 |
| 확장성 | 6/10 | Phase 3 이후 확장 가능 |
| 비용 효율성 | 9/10 | 최소 초기 투자 |
| 유지보수성 | 7/10 | 마이그레이션 필요, 기술 부채 |
| **총점** | **7.6/10** | **실용적, 리스크 최소** |

**종합 의견**:
- **민준**: 비즈니스 검증에 최적. MVP 철학에 부합.
- **동욱**: 실무적으로 가장 현실적. 팀 역량 고려 시 추천.
- **도현**: 단계별 테스트 가능, 품질 관리 용이.

---

### 후보 2 평가: 하이브리드 RAG 시스템
| 평가 기준 | 점수 | 세부 평가 |
|---------|------|---------|
| 비즈니스 가치 | 9/10 | 조직 용어 품질 + 확장성 균형 |
| 기술적 실현 가능성 | 7/10 | 이원화 시스템 복잡도 |
| 확장성 | 8/10 | 외부 용어 자동 확장 |
| 비용 효율성 | 7/10 | 중간 수준 비용 |
| 유지보수성 | 6/10 | 두 시스템 동기화 필요 |
| **총점** | **7.7/10** | **균형잡힌 솔루션** |

**종합 의견**:
- **서연**: 기술적으로 가장 합리적. RAG의 장점 활용.
- **준호**: API 설계 명확, 확장 경로 분명.
- **길동**: 아키텍처 관점에서 장기적으로 유지 가능.

---

### 후보 3 평가: Full RAG 시스템
| 평가 기준 | 점수 | 세부 평가 |
|---------|------|---------|
| 비즈니스 가치 | 8/10 | 최대 확장성, 높은 비용 |
| 기술적 실현 가능성 | 6/10 | 복잡도 높음, 개발 기간 길어짐 |
| 확장성 | 10/10 | 무제한 확장 가능 |
| 비용 효율성 | 4/10 | 높은 초기/운영 비용 |
| 유지보수성 | 8/10 | 관리형 서비스로 간소화 |
| **총점** | **7.0/10** | **오버엔지니어링 리스크** |

**종합 의견**:
- **민준**: 초기 스타트업에 과도한 투자.
- **주영**: 운영 비용 부담, 단계적 접근 권장.
- **도그냥**: 사용자 검증 전 과한 투자.

---

### 후보 4 평가: 커뮤니티 큐레이션 모델
| 평가 기준 | 점수 | 세부 평가 |
|---------|------|---------|
| 비즈니스 가치 | 7/10 | 사용자 참여 높으나 초기 부족 |
| 기술적 실현 가능성 | 6/10 | 모더레이션 시스템 복잡 |
| 확장성 | 8/10 | 자연스러운 콘텐츠 성장 |
| 비용 효율성 | 8/10 | 중간 비용, 모더레이션 필요 |
| 유지보수성 | 5/10 | 품질 관리 지속 필요 |
| **총점** | **6.9/10** | **차별화되나 리스크 있음** |

**종합 의견**:
- **도그냥**: 장기적으로 차별화 포인트, MVP에는 부적합.
- **현정**: 콘텐츠 품질 관리 어려움.
- **지수**: UX는 흥미롭지만 초기 경험 부족.

---

### 후보 5 평가: LLM 직접 활용
| 평가 기준 | 점수 | 세부 평가 |
|---------|------|---------|
| 비즈니스 가치 | 6/10 | 빠른 구현, 성능 이슈 |
| 기술적 실현 가능성 | 8/10 | 단순 구조, 쉬운 구현 |
| 확장성 | 4/10 | API 비용 및 속도 문제 |
| 비용 효율성 | 5/10 | 낮은 초기, 높은 운영 비용 |
| 유지보수성 | 9/10 | 매우 단순한 구조 |
| **총점** | **6.1/10** | **단기 솔루션, 확장 제한** |

**종합 의견**:
- **서연**: 기술적으로 단순하나 성능 문제 예상.
- **준호**: 확장 시 비용 폭발 가능성.
- **도현**: 3초 응답 시간은 UX에 부정적.

---

## 5단계: 최적안 선정 (1차)

**선정 결과**: **후보 2 - 하이브리드 RAG 시스템** (7.7/10)

**선정 이유**:
1. 조직 특화 용어의 높은 정확도 보장 (JSON 큐레이션)
2. 외부 용어의 확장성 확보 (RAG 시스템)
3. 합리적인 비용 구조 ($35K 초기 + $5K/월)
4. 명확한 아키텍처, 유지보수 가능
5. 차별화 포인트 구현 가능

---

## 반복 2-10: 개선 및 최종 선정

### 반복 2: 하이브리드 모델 개선안

**개선 포인트**:
- Phase 1에서 JSON 사전으로 시작 (후보 1의 장점)
- Phase 2에서 RAG 추가 (점진적 확장)
- 비용 최적화: pgvector 우선 사용 → Qdrant는 필요 시 전환

**개선된 점수**: 8.0/10

---

### 반복 3-9: 세부 조정
(각 반복마다 팀원들의 피드백을 반영하여 아키텍처 미세 조정)

---

### 반복 10: 최종 최적안

**최종 선정**: **하이브리드 RAG 시스템 (개선안)**

**최종 아키텍처**:

```
Phase 1 (MVP - 4주):
├── JSON 기반 용어 사전 (50개 핵심 조직 용어)
├── Claude API 직접 연동
├── 간단한 키워드 매칭
└── 수동 큐레이션 프로세스

Phase 2 (기본 RAG - 6주):
├── PostgreSQL + pgvector 확장
├── 조직 문서 100개 임베딩
├── OpenAI text-embedding-3-small 사용 (비용 절감)
├── 기본 벡터 검색 + Claude API 연동
└── 자동 배치 수집 파이프라인

Phase 3 (고도화 - 8주):
├── Qdrant 도입 (성능 개선)
├── 하이브리드 검색 (키워드 + 벡터)
├── 자동 품질 검증 시스템
├── 사용자 피드백 루프
└── 외부 문서 자동 크롤링
```

---

## 6단계: Architectural Decision Records (ADR)

### ADR-001: 벡터 데이터베이스 선택

**결정**: Phase 1-2는 PostgreSQL + pgvector, Phase 3에서 Qdrant로 전환

**컨텍스트**:
- 초기에는 데이터량이 적어 pgvector로 충분
- Qdrant는 전문 벡터 DB로 성능 우수하나 인프라 복잡도 증가
- 단계적 접근으로 리스크 분산

**대안 고려**:
1. **Pinecone**: 관리형 서비스, 쉬운 시작 vs 높은 운영 비용 ($70/월~)
2. **Weaviate**: 오픈소스, 풍부한 기능 vs 학습 곡선 높음
3. **pgvector**: 간단한 설정, 기존 DB 활용 vs 성능 제한

**결정 근거**:
- MVP 단계에서는 pgvector의 단순성 우선
- 사용자 1000명 이상 시 Qdrant 전환 (명확한 마이그레이션 기준)
- 비용 효율성: pgvector 무료 vs Qdrant 자체 호스팅 $500/월 vs Pinecone $1000/월

**결과**:
- 초기 인프라 비용 절감 (PostgreSQL 활용)
- 검증된 기술 스택 사용으로 팀 학습 부담 감소
- 명확한 확장 경로 확보

---

### ADR-002: 임베딩 모델 선택

**결정**: OpenAI text-embedding-3-small (Phase 1-2), text-embedding-3-large (Phase 3)

**컨텍스트**:
- 한국어/영어 혼용 문서 처리 필요
- 비용과 성능의 균형 필요
- 임베딩 차원수와 정확도 트레이드오프

**대안 고려**:
1. **OpenAI text-embedding-3-small**: 
   - 1536 차원, $0.02/1M tokens
   - 적절한 정확도, 낮은 비용
   
2. **OpenAI text-embedding-3-large**: 
   - 3072 차원, $0.13/1M tokens
   - 최고 정확도, 높은 비용
   
3. **Cohere embed-multilingual-v3.0**: 
   - 1024 차원, $0.10/1M tokens
   - 다국어 특화, 중간 비용

**결정 근거**:
- Phase 1-2: small 모델로 MVP 검증 (월 1,000,000 토큰 = $20)
- Phase 3: 사용자 피드백 기반으로 large 모델 전환 고려
- OpenAI 에코시스템 통일 (Claude 대안으로 GPT 활용 가능)

**결과**:
- 초기 월 $20-50 임베딩 비용
- 필요 시 모델 업그레이드 가능한 구조
- 다국어 지원 검증 필요 (한국어 테스트)

---

### ADR-003: 용어 수집 전략

**결정**: 수동 큐레이션 (Phase 1) → 반자동 (Phase 2) → 자동 (Phase 3)

**Phase 1 - 수동 큐레이션**:
```json
{
  "terms": [
    {
      "id": "term-001",
      "name": "API Gateway",
      "category": "기술-아키텍처",
      "definition": "클라이언트와 백엔드 서비스 사이의 단일 진입점",
      "context": "우리 시스템에서는 AWS API Gateway를 사용하여...",
      "synonyms": ["게이트웨이", "API 게이트웨이"],
      "source": "internal",
      "confidence": 1.0,
      "created_at": "2025-01-15",
      "updated_at": "2025-01-15"
    }
  ]
}
```

**Phase 2 - 반자동 수집**:
```python
# 배치 수집 스크립트
def collect_documents():
    sources = [
        ConfluenceAPI(url="...", token="..."),
        SharePointAPI(site_url="...", token="..."),
        GoogleDriveAPI(folder_id="...", token="...")
    ]
    
    for source in sources:
        documents = source.fetch_recent_documents(days=7)
        for doc in documents:
            terms = extract_terms(doc.content)
            # 관리자 승인 대기열에 추가
            await add_to_approval_queue(terms)
```

**Phase 3 - 자동 수집**:
- ML 기반 자동 승인 (신뢰도 > 0.9)
- 주간 배치로 신규 용어 자동 추가
- 품질 모니터링 대시보드

**결정 근거**:
- 초기 품질 보장 (수동 검증)
- 점진적 자동화로 관리 부담 감소
- 조직 특화 용어의 정확도 우선

---

### ADR-004: Claude API 연동 구조

**결정**: RAG context + Structured prompt

**API 요청 구조**:
```json
{
  "model": "claude-sonnet-4-5-20250929",
  "max_tokens": 1024,
  "temperature": 0.3,
  "system": "당신은 전문 용어를 회의 맥락에 맞춰 설명하는 AI 어시스턴트입니다. 2-3문장으로 간결하게 설명하세요.",
  "messages": [
    {
      "role": "user",
      "content": [
        {
          "type": "text",
          "text": "=== 회의 정보 ===\n회의 제목: API 설계 리뷰\n참석자: 김민준(PO), 이준호(BE), 박서연(AI)\n시간: 2025-01-15 14:00\n\n=== 회의 내용 (STT 전사) ===\n민준: 이번 프로젝트에서 API Gateway를 도입하려고 하는데...\n준호: REST API 설계는 이미 완료했고, 인증은 JWT로...\n서연: AI 서비스와의 연동은 비동기로 처리하면...\n\n=== 관련 문서 (RAG 검색 결과) ===\n[문서 1] API Gateway 설계 가이드 (2024-12-01)\n- API Gateway는 마이크로서비스 아키텍처에서 단일 진입점 역할\n- 요청 라우팅, 인증/인가, Rate limiting 기능 제공\n- AWS API Gateway 사용 시 Lambda 통합 가능\n\n[문서 2] 사내 기술 스택 표준 (2024-11-15)\n- API Gateway: AWS API Gateway 권장\n- 인증: JWT 토큰 기반 (만료 시간 1시간)\n\n=== 질문 ===\n용어: API Gateway\n\n위 회의 맥락에 맞춰 'API Gateway'를 2-3문장으로 설명해주세요."
        }
      ]
    }
  ]
}
```

**응답 처리**:
```json
{
  "id": "msg_01ABC...",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "API Gateway는 클라이언트와 백엔드 마이크로서비스 사이의 단일 진입점으로, 요청 라우팅, 인증, Rate limiting을 담당합니다. 이 회의에서는 AWS API Gateway 도입을 논의하고 있으며, JWT 기반 인증과 Lambda 통합을 통해 AI 서비스를 비동기로 연동하려는 계획입니다. 사내 기술 스택 표준에 따라 AWS API Gateway 사용이 권장됩니다."
    }
  ],
  "model": "claude-sonnet-4-5-20250929",
  "usage": {
    "input_tokens": 523,
    "output_tokens": 87
  }
}
```

**최적화 전략**:
1. **캐싱**: Redis에 (용어 + 회의 맥락 해시) → 설명 저장 (TTL 24시간)
2. **Rate limiting**: 사용자당 분당 10회, 회의당 시간당 100회
3. **Fallback**: API 실패 시 RAG 문서 직접 반환
4. **비용 관리**: 월 예산 $500 초과 시 알림 (input 500K tokens 기준)

**결정 근거**:
- Claude의 장문 이해 능력 활용 (200K tokens)
- Structured prompt로 일관된 응답 품질
- RAG context로 정확도 향상
- 캐싱으로 중복 호출 방지 (비용 절감)

---

### ADR-005: 데이터베이스 스키마 설계

**결정**: 정규화된 관계형 스키마 + JSON 메타데이터

**스키마 구조**:
```sql
-- 용어 마스터 테이블
CREATE TABLE terms (
    term_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    term_name VARCHAR(200) NOT NULL,
    normalized_name VARCHAR(200) NOT NULL,  -- 소문자, 공백 제거
    category VARCHAR(50),  -- '기술-아키텍처', '비즈니스-전략' 등
    source_type VARCHAR(20) CHECK (source_type IN ('internal', 'external')),
    is_company_specific BOOLEAN DEFAULT false,
    
    -- 용어 정보
    definition TEXT NOT NULL,
    context TEXT,  -- 회사 내 사용 맥락
    synonyms JSONB,  -- ["게이트웨이", "API GW"]
    related_terms JSONB,  -- [{"term_id": "...", "relation": "related"}]
    
    -- 메타데이터
    usage_count INTEGER DEFAULT 0,
    confidence_score DECIMAL(3,2),  -- 0.00 ~ 1.00
    last_used_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by UUID REFERENCES users(user_id),
    
    -- 인덱스
    INDEX idx_normalized_name (normalized_name),
    INDEX idx_category (category),
    INDEX idx_source_type (source_type),
    INDEX idx_usage_count (usage_count DESC),
    UNIQUE INDEX uniq_normalized_name (normalized_name, source_type)
);

-- 용어-문서 매핑 (RAG용)
CREATE TABLE term_documents (
    mapping_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    term_id UUID REFERENCES terms(term_id) ON DELETE CASCADE,
    
    -- 문서 정보
    document_id VARCHAR(200) NOT NULL,  -- 외부 시스템 ID (Confluence, SharePoint)
    document_title VARCHAR(500),
    document_url TEXT,
    document_type VARCHAR(50),  -- 'confluence', 'sharepoint', 'gdrive'
    
    -- 관련성 정보
    relevance_score DECIMAL(3,2),  -- 0.00 ~ 1.00
    excerpt TEXT,  -- 용어가 등장하는 문맥 (최대 500자)
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    INDEX idx_term_id (term_id),
    INDEX idx_document_id (document_id),
    INDEX idx_relevance_score (relevance_score DESC)
);

-- 벡터 임베딩 메타데이터
CREATE TABLE term_vectors (
    vector_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    term_id UUID REFERENCES terms(term_id) ON DELETE CASCADE,
    
    -- 임베딩 정보
    embedding_model VARCHAR(50),  -- 'text-embedding-3-small'
    embedding_dimension INTEGER,  -- 1536
    vector_store_type VARCHAR(20),  -- 'pgvector', 'qdrant'
    vector_store_key VARCHAR(200),  -- 벡터 DB 내 키
    
    -- pgvector 사용 시 직접 저장
    embedding vector(1536),  -- pgvector 확장 타입
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    INDEX idx_term_id (term_id),
    INDEX idx_embedding_model (embedding_model)
);

-- 용어 사용 이력 (분석용)
CREATE TABLE term_usage_logs (
    log_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    term_id UUID REFERENCES terms(term_id) ON DELETE CASCADE,
    
    -- 사용 컨텍스트
    meeting_id UUID REFERENCES meetings(meeting_id),
    user_id UUID REFERENCES users(user_id),
    action VARCHAR(20),  -- 'view', 'search', 'feedback'
    
    -- 피드백 정보 (선택)
    feedback_rating INTEGER CHECK (feedback_rating BETWEEN 1 AND 5),
    feedback_comment TEXT,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    INDEX idx_term_id_created (term_id, created_at DESC),
    INDEX idx_meeting_id (meeting_id),
    INDEX idx_user_id (user_id)
);
```

**데이터 예시**:
```sql
INSERT INTO terms (term_name, normalized_name, category, source_type, is_company_specific, definition, context, synonyms, confidence_score) VALUES
(
    'API Gateway',
    'api gateway',
    '기술-아키텍처',
    'internal',
    true,
    '클라이언트와 백엔드 마이크로서비스 사이의 단일 진입점으로, 요청 라우팅, 인증, Rate limiting을 담당합니다.',
    '우리 시스템에서는 AWS API Gateway를 사용하며, Lambda와 통합하여 서버리스 아키텍처를 구현합니다. API 설계 리뷰 회의(2024-09-28)에서 공식 채택되었습니다.',
    '["게이트웨이", "API GW", "에이피아이 게이트웨이"]'::jsonb,
    0.95
);
```

**결정 근거**:
- 정규화로 데이터 일관성 보장
- JSONB로 유연한 메타데이터 저장
- 인덱스로 검색 성능 최적화
- 사용 이력 로그로 품질 개선 데이터 확보

---

### ADR-006: API 엔드포인트 설계

**결정**: RESTful API + GraphQL (Phase 3)

**Phase 1-2: REST API**
```
=== 용어 추출 ===
POST /api/v1/terms/extract
Request:
{
  "meeting_id": "uuid",
  "transcript": "회의 전사 텍스트...",
  "language": "ko",
  "options": {
    "include_external": true,
    "confidence_threshold": 0.7
  }
}

Response:
{
  "terms": [
    {
      "term_id": "uuid",
      "name": "API Gateway",
      "category": "기술-아키텍처",
      "confidence": 0.95,
      "is_company_specific": true,
      "mention_count": 3,
      "positions": [142, 456, 789]
    }
  ],
  "extraction_time_ms": 1234,
  "total_terms": 12
}

=== 용어 설명 조회 ===
GET /api/v1/terms/{term_id}/explanation
Query params:
- meeting_id (optional): 회의 맥락 포함
- include_rag (optional): RAG 문서 포함 여부
- max_context_docs (optional): 최대 문서 수 (기본 3)

Response:
{
  "term": {
    "term_id": "uuid",
    "name": "API Gateway",
    "definition": "...",
    "category": "기술-아키텍처",
    "is_company_specific": true
  },
  "explanation": {
    "text": "API Gateway는 클라이언트와 백엔드...",
    "context": "이 회의에서는 AWS API Gateway 도입을...",
    "generated_by": "claude-sonnet-4.5",
    "cached": false
  },
  "related_documents": [
    {
      "title": "API 설계 가이드",
      "url": "https://confluence.../123",
      "relevance_score": 0.92,
      "excerpt": "..."
    }
  ],
  "related_terms": [
    {
      "term_id": "uuid",
      "name": "Microservice",
      "relation": "related"
    }
  ]
}

=== 용어 검색 (벡터 유사도) ===
POST /api/v1/terms/search
Request:
{
  "query": "서비스 간 통신",
  "filters": {
    "category": ["기술-아키텍처"],
    "source_type": "internal",
    "is_company_specific": true
  },
  "top_k": 5,
  "search_type": "hybrid"  // 'keyword', 'vector', 'hybrid'
}

Response:
{
  "results": [
    {
      "term_id": "uuid",
      "name": "API Gateway",
      "similarity_score": 0.87,
      "definition": "...",
      "relevance_reason": "키워드 매칭 + 벡터 유사도"
    }
  ],
  "search_time_ms": 234,
  "total_results": 12
}

=== 용어 피드백 ===
POST /api/v1/terms/{term_id}/feedback
Request:
{
  "meeting_id": "uuid",
  "user_id": "uuid",
  "rating": 5,  // 1-5
  "comment": "매우 도움되었습니다",
  "feedback_type": "helpful"  // 'helpful', 'inaccurate', 'irrelevant'
}

Response:
{
  "feedback_id": "uuid",
  "message": "피드백이 등록되었습니다"
}

=== 관리자 API ===
POST /api/v1/admin/terms
PUT /api/v1/admin/terms/{term_id}
DELETE /api/v1/admin/terms/{term_id}
GET /api/v1/admin/terms/pending  // 승인 대기 용어
POST /api/v1/admin/terms/{term_id}/approve
```

**Phase 3: GraphQL 추가**
```graphql
query GetTermWithContext($termId: ID!, $meetingId: ID) {
  term(id: $termId) {
    id
    name
    definition
    category
    isCompanySpecific
    
    explanation(meetingId: $meetingId) {
      text
      context
      generatedBy
      cached
    }
    
    relatedDocuments(limit: 3) {
      title
      url
      relevanceScore
      excerpt
    }
    
    relatedTerms {
      id
      name
      relation
    }
    
    usageStats {
      totalViews
      averageRating
      lastUsedAt
    }
  }
}
```

**결정 근거**:
- REST API: 간단한 CRUD, 캐싱 용이
- GraphQL: 복잡한 관계 조회, Over-fetching 방지
- 단계적 도입으로 학습 곡선 완화

---

## 7단계: 데이터 소스별 수집 전략

### 조직 문서 수집

**1. Confluence API 연동**
```python
from atlassian import Confluence

class ConfluenceCollector:
    def __init__(self, url, username, api_token):
        self.confluence = Confluence(
            url=url,
            username=username,
            password=api_token
        )
    
    def collect_documents(self, space_key, days=7):
        """최근 7일간 업데이트된 문서 수집"""
        cql = f'space = {space_key} AND lastModified >= now("-{days}d") ORDER BY lastModified DESC'
        results = self.confluence.cql(cql, limit=100)
        
        documents = []
        for page in results['results']:
            doc = {
                'document_id': page['id'],
                'title': page['title'],
                'url': page['_links']['webui'],
                'content': self.confluence.get_page_by_id(page['id'], expand='body.storage')['body']['storage']['value'],
                'updated_at': page['lastModified'],
                'type': 'confluence'
            }
            documents.append(doc)
        
        return documents
    
    def extract_terms_from_doc(self, document):
        """문서에서 용어 추출"""
        # HTML 파싱
        soup = BeautifulSoup(document['content'], 'html.parser')
        text = soup.get_text()
        
        # NER 기반 용어 추출
        terms = self.ner_extractor.extract(text)
        
        # TF-IDF 기반 중요 키워드
        keywords = self.tfidf_extractor.extract(text, top_n=20)
        
        # Claude API로 맥락 기반 용어 추출
        claude_terms = self.claude_extractor.extract(text)
        
        # 통합 및 중복 제거
        all_terms = self.merge_and_deduplicate(terms, keywords, claude_terms)
        
        return all_terms
```

**2. SharePoint Graph API 연동**
```python
from microsoft_graph import GraphAPI

class SharePointCollector:
    def __init__(self, tenant_id, client_id, client_secret):
        self.graph = GraphAPI(tenant_id, client_id, client_secret)
    
    def collect_documents(self, site_id, library_name, days=7):
        """SharePoint 문서 라이브러리에서 최근 문서 수집"""
        delta_url = f'/sites/{site_id}/drives/{library_name}/root/delta'
        results = self.graph.get(delta_url, params={'$filter': f'lastModifiedDateTime ge {days}daysAgo'})
        
        documents = []
        for item in results['value']:
            if item['file']:  # 파일인 경우
                content = self.graph.download_file(item['@microsoft.graph.downloadUrl'])
                
                doc = {
                    'document_id': item['id'],
                    'title': item['name'],
                    'url': item['webUrl'],
                    'content': self.extract_text_from_file(content, item['file']['mimeType']),
                    'updated_at': item['lastModifiedDateTime'],
                    'type': 'sharepoint'
                }
                documents.append(doc)
        
        return documents
    
    def extract_text_from_file(self, content, mime_type):
        """파일 타입에 따라 텍스트 추출"""
        if mime_type == 'application/pdf':
            return self.pdf_extractor.extract(content)
        elif mime_type in ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']:
            return self.docx_extractor.extract(content)
        elif mime_type in ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet']:
            return self.excel_extractor.extract(content)
        else:
            return content.decode('utf-8')
```

**3. Google Drive API 연동**
```python
from google_drive_api import DriveAPI

class GoogleDriveCollector:
    def __init__(self, credentials_file):
        self.drive = DriveAPI(credentials_file)
    
    def collect_documents(self, folder_id, days=7):
        """Google Drive 폴더에서 최근 문서 수집"""
        query = f"'{folder_id}' in parents and modifiedTime > '{days}daysAgo' and mimeType != 'application/vnd.google-apps.folder'"
        results = self.drive.files().list(q=query, pageSize=100).execute()
        
        documents = []
        for file in results.get('files', []):
            # Google Docs는 export, 일반 파일은 download
            if file['mimeType'] == 'application/vnd.google-apps.document':
                content = self.drive.export_doc(file['id'], 'text/plain')
            else:
                content = self.drive.download_file(file['id'])
            
            doc = {
                'document_id': file['id'],
                'title': file['name'],
                'url': file['webViewLink'],
                'content': content,
                'updated_at': file['modifiedTime'],
                'type': 'google_drive'
            }
            documents.append(doc)
        
        return documents
```

**수집 스케줄**:
```yaml
# Airflow DAG 예시
schedule_interval: "0 2 * * *"  # 매일 새벽 2시

tasks:
  - task_id: collect_confluence
    python_callable: collect_confluence_documents
    retries: 3
  
  - task_id: collect_sharepoint
    python_callable: collect_sharepoint_documents
    retries: 3
  
  - task_id: collect_google_drive
    python_callable: collect_google_drive_documents
    retries: 3
  
  - task_id: extract_terms
    python_callable: extract_terms_from_documents
    depends_on: [collect_confluence, collect_sharepoint, collect_google_drive]
  
  - task_id: generate_embeddings
    python_callable: generate_and_store_embeddings
    depends_on: [extract_terms]
  
  - task_id: quality_check
    python_callable: validate_term_quality
    depends_on: [generate_embeddings]
```

### 외부 문서 수집

**1. GitHub 기술 문서 크롤링**
```python
import requests
from github import Github

class GitHubDocCollector:
    def __init__(self, access_token):
        self.github = Github(access_token)
    
    def collect_readme_files(self, repo_list):
        """인기 오픈소스 프로젝트의 README 수집"""
        documents = []
        
        for repo_name in repo_list:
            repo = self.github.get_repo(repo_name)
            readme = repo.get_readme()
            
            doc = {
                'document_id': f'github-{repo.id}',
                'title': f'{repo.name} README',
                'url': readme.html_url,
                'content': readme.decoded_content.decode('utf-8'),
                'type': 'github',
                'category': 'external-tech'
            }
            documents.append(doc)
        
        return documents

# 수집 대상 저장소 예시
TECH_REPOS = [
    'kubernetes/kubernetes',
    'docker/docker',
    'facebook/react',
    'tensorflow/tensorflow',
    'pytorch/pytorch'
]
```

**2. API 문서 수집 (Swagger/OpenAPI)**
```python
class APIDocCollector:
    def collect_swagger_docs(self, swagger_url_list):
        """공개 API 문서 수집"""
        documents = []
        
        for url in swagger_url_list:
            response = requests.get(url)
            swagger_spec = response.json()
            
            # Swagger 스펙에서 용어 추출
            terms = self.extract_terms_from_swagger(swagger_spec)
            
            doc = {
                'document_id': f'swagger-{hash(url)}',
                'title': swagger_spec.get('info', {}).get('title', 'API Documentation'),
                'url': url,
                'content': self.convert_swagger_to_text(swagger_spec),
                'type': 'api_doc',
                'category': 'external-tech'
            }
            documents.append(doc)
        
        return documents
    
    def extract_terms_from_swagger(self, swagger_spec):
        """Swagger 스펙에서 API 용어 추출"""
        terms = []
        
        # Paths에서 엔드포인트 용어
        for path, methods in swagger_spec.get('paths', {}).items():
            for method, details in methods.items():
                if 'summary' in details:
                    terms.append({
                        'name': details['summary'],
                        'definition': details.get('description', ''),
                        'category': 'API 엔드포인트'
                    })
        
        # Schemas에서 데이터 모델 용어
        for schema_name, schema in swagger_spec.get('components', {}).get('schemas', {}).items():
            terms.append({
                'name': schema_name,
                'definition': schema.get('description', ''),
                'category': 'Data Model'
            })
        
        return terms
```

**3. 산업 표준 용어집**
```python
class StandardTermCollector:
    """산업 표준 용어집 수집"""
    
    STANDARD_SOURCES = {
        'iso': 'https://www.iso.org/obp/ui/',
        'ieee': 'https://www.ieee.org/standards/',
        'w3c': 'https://www.w3.org/standards/'
    }
    
    def collect_iso_terms(self):
        """ISO 표준 용어 수집 (수동 큐레이션 필요)"""
        # 실제로는 웹 크롤링 또는 공식 API 사용
        # 여기서는 예시로 하드코딩
        terms = [
            {
                'name': 'Microservice Architecture',
                'definition': 'An approach to developing a single application as a suite of small services...',
                'source': 'ISO/IEC 29148',
                'category': 'Architecture Pattern',
                'type': 'external'
            }
        ]
        return terms
```

---

## 8단계: 구현 예시 코드

### 전체 파이프라인 통합

```python
# main_pipeline.py
import asyncio
from collectors import ConfluenceCollector, SharePointCollector, GoogleDriveCollector
from extractors import TermExtractor, VectorEmbedder
from storage import PostgreSQLStore, QdrantStore
from claude_client import ClaudeAPIClient

class TermManagementPipeline:
    def __init__(self, config):
        self.config = config
        
        # 수집기 초기화
        self.collectors = {
            'confluence': ConfluenceCollector(config['confluence']),
            'sharepoint': SharePointCollector(config['sharepoint']),
            'google_drive': GoogleDriveCollector(config['google_drive'])
        }
        
        # 추출기 초기화
        self.term_extractor = TermExtractor()
        self.vector_embedder = VectorEmbedder(
            model='text-embedding-3-small',
            api_key=config['openai_api_key']
        )
        
        # 저장소 초기화
        self.postgres = PostgreSQLStore(config['postgres'])
        self.vector_store = QdrantStore(config['qdrant']) if config.get('use_qdrant') else None
        
        # Claude API 클라이언트
        self.claude = ClaudeAPIClient(api_key=config['claude_api_key'])
    
    async def run_daily_pipeline(self):
        """매일 실행되는 파이프라인"""
        
        # 1. 문서 수집
        print("📥 1단계: 문서 수집 중...")
        all_documents = []
        for source_name, collector in self.collectors.items():
            try:
                docs = await collector.collect_recent_documents(days=1)
                all_documents.extend(docs)
                print(f"  ✓ {source_name}: {len(docs)}개 문서 수집")
            except Exception as e:
                print(f"  ✗ {source_name} 수집 실패: {e}")
        
        print(f"총 {len(all_documents)}개 문서 수집 완료\n")
        
        # 2. 용어 추출
        print("🔍 2단계: 용어 추출 중...")
        all_terms = []
        for doc in all_documents:
            terms = await self.term_extractor.extract_terms(doc)
            all_terms.extend(terms)
        
        print(f"  ✓ {len(all_terms)}개 용어 추출 완료\n")
        
        # 3. 중복 제거 및 정제
        print("🧹 3단계: 용어 정제 중...")
        unique_terms = self.term_extractor.deduplicate_terms(all_terms)
        validated_terms = await self.validate_terms(unique_terms)
        
        print(f"  ✓ {len(validated_terms)}개 유효 용어 (중복 제거: {len(all_terms) - len(validated_terms)}개)\n")
        
        # 4. 벡터 임베딩 생성
        print("🧮 4단계: 벡터 임베딩 생성 중...")
        embeddings = await self.vector_embedder.generate_embeddings(validated_terms)
        
        print(f"  ✓ {len(embeddings)}개 벡터 생성 완료\n")
        
        # 5. 데이터베이스 저장
        print("💾 5단계: 데이터베이스 저장 중...")
        await self.postgres.save_terms(validated_terms)
        
        if self.vector_store:
            await self.vector_store.upsert_vectors(embeddings)
        else:
            await self.postgres.save_vectors(embeddings)
        
        print("  ✓ 저장 완료\n")
        
        # 6. 품질 검증
        print("✅ 6단계: 품질 검증 중...")
        quality_report = await self.validate_quality(validated_terms)
        
        print(f"  ✓ 정확도: {quality_report['accuracy']}%")
        print(f"  ✓ 신뢰도 > 0.8: {quality_report['high_confidence_ratio']}%")
        print(f"  ✓ 조직 특화 용어: {quality_report['company_specific_count']}개\n")
        
        return {
            'documents_collected': len(all_documents),
            'terms_extracted': len(validated_terms),
            'quality_report': quality_report
        }
    
    async def validate_terms(self, terms):
        """용어 유효성 검증"""
        validated = []
        
        for term in terms:
            # 1. 길이 검증 (2-200자)
            if not (2 <= len(term['name']) <= 200):
                continue
            
            # 2. 신뢰도 임계값 (0.7 이상)
            if term.get('confidence', 0) < 0.7:
                continue
            
            # 3. 중복 체크
            if await self.postgres.term_exists(term['normalized_name']):
                continue
            
            validated.append(term)
        
        return validated
    
    async def validate_quality(self, terms):
        """품질 지표 계산"""
        total = len(terms)
        high_confidence = sum(1 for t in terms if t.get('confidence', 0) > 0.8)
        company_specific = sum(1 for t in terms if t.get('is_company_specific', False))
        
        return {
            'accuracy': round(high_confidence / total * 100, 2) if total > 0 else 0,
            'high_confidence_ratio': round(high_confidence / total * 100, 2) if total > 0 else 0,
            'company_specific_count': company_specific
        }

# 실행
if __name__ == '__main__':
    config = load_config('config.yaml')
    pipeline = TermManagementPipeline(config)
    
    # 비동기 실행
    result = asyncio.run(pipeline.run_daily_pipeline())
    
    print("\n" + "="*50)
    print("📊 파이프라인 실행 완료")
    print("="*50)
    print(f"수집된 문서: {result['documents_collected']}개")
    print(f"추출된 용어: {result['terms_extracted']}개")
    print(f"품질 점수: {result['quality_report']['accuracy']}%")
```

---

## 9단계: Claude API 요청/응답 JSON 구조

### 용어 설명 요청

```json
{
  "model": "claude-sonnet-4-5-20250929",
  "max_tokens": 1024,
  "temperature": 0.3,
  "top_p": 0.95,
  "system": "당신은 전문 용어를 회의 맥락에 맞춰 설명하는 AI 어시스턴트입니다. 다음 규칙을 따르세요:\n1. 2-3문장으로 간결하게 설명\n2. 회의 맥락을 반영하여 실용적인 정보 제공\n3. 관련 문서 정보가 있으면 활용\n4. 기술 용어는 비전공자도 이해할 수 있게 설명",
  "messages": [
    {
      "role": "user",
      "content": "=== 회의 정보 ===\n회의 제목: Q4 회의록 작성 가이드 배포\n참석자: 김민준(PO), 이준호(BE), 박서연(AI), 최유진(FE)\n시간: 2024-10-01 14:00\n\n=== 회의 내용 (STT 전사) ===\n민준: 이번 분기 회의록 시스템 개발을 위해 먼저 API Gateway 구조부터 설계해야 할 것 같습니다.\n준호: 네, 저희가 마이크로서비스 아키텍처를 채택했으니 API Gateway가 필수겠네요. RESTful API로 설계하는 게 좋을까요?\n서연: AI 서비스와 연동할 때는 비동기 처리가 중요할 것 같아요. Claude API 호출 시간이 좀 걸리거든요.\n유진: 프론트엔드에서는 실시간으로 용어 설명을 보여줘야 하는데, API Gateway에서 캐싱을 지원하면 좋겠어요.\n\n=== 관련 문서 (RAG 검색 결과) ===\n[문서 1] API 설계 리뷰 회의록 (2024-09-28, 관련도 95%)\n제목: API Gateway 아키텍처 결정\n내용: \"RESTful API 설계 원칙과 보안 정책 확정. AWS API Gateway 채택 결정. JWT 토큰 기반 인증, Rate limiting 적용. Lambda 통합으로 서버리스 아키텍처 구현.\"\n\n[문서 2] 사내 기술 스택 가이드 (2024-08-15, 관련도 78%)\n제목: 마이크로서비스 표준 아키텍처\n내용: \"API Gateway는 클라이언트와 백엔드 서비스 사이의 단일 진입점. 요청 라우팅, 인증/인가, 로깅, Rate limiting 기능 제공. 회사 표준은 AWS API Gateway 사용.\"\n\n[문서 3] 신제품 개발 킥오프 회의록 (2024-09-15, 관련도 65%)\n제목: 1분기 신제품 개발 방향성\n내용: \"협업 도구 시장 분석 및 차별화 전략 수립. 기술 스택으로 마이크로서비스 아키텍처 선정, API Gateway 패턴 적용 예정.\"\n\n=== 질문 ===\n용어: API Gateway\n\n위 회의 맥락에 맞춰 'API Gateway'를 2-3문장으로 설명해주세요. 이 회의에서 API Gateway가 어떤 역할을 하는지 포함해주세요."
    }
  ]
}
```

### Claude API 응답

```json
{
  "id": "msg_01XyZ123AbC456",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "API Gateway는 클라이언트와 백엔드 마이크로서비스 사이의 단일 진입점으로, 요청 라우팅, 인증/인가, Rate limiting, 로깅 등을 담당합니다. 이 회의에서는 회의록 시스템 개발을 위해 AWS API Gateway를 도입하기로 했으며, Claude AI 서비스 연동 시 비동기 처리와 캐싱 기능을 활용하여 실시간 용어 설명 기능을 구현할 계획입니다. 사내 표준 아키텍처에 따라 JWT 인증과 Lambda 통합을 통한 서버리스 구조로 설계됩니다."
    }
  ],
  "model": "claude-sonnet-4-5-20250929",
  "stop_reason": "end_turn",
  "stop_sequence": null,
  "usage": {
    "input_tokens": 523,
    "output_tokens": 147
  }
}
```

### 에러 응답 처리

```json
{
  "type": "error",
  "error": {
    "type": "rate_limit_error",
    "message": "Rate limit exceeded. Please try again later."
  }
}
```

**에러 핸들링 코드**:
```python
class ClaudeAPIClient:
    async def explain_term(self, term, context, rag_docs):
        """용어 설명 요청 with 에러 핸들링"""
        
        max_retries = 3
        retry_delay = 1  # 초
        
        for attempt in range(max_retries):
            try:
                response = await self.call_claude_api(term, context, rag_docs)
                
                # 캐시 저장
                await self.cache.set(
                    key=self.generate_cache_key(term, context),
                    value=response['content'][0]['text'],
                    ttl=86400  # 24시간
                )
                
                return {
                    'explanation': response['content'][0]['text'],
                    'cached': False,
                    'tokens_used': response['usage']['input_tokens'] + response['usage']['output_tokens']
                }
            
            except RateLimitError as e:
                if attempt < max_retries - 1:
                    await asyncio.sleep(retry_delay * (2 ** attempt))  # Exponential backoff
                    continue
                else:
                    # Fallback: RAG 문서 직접 반환
                    return {
                        'explanation': self.generate_fallback_explanation(rag_docs),
                        'cached': False,
                        'error': 'rate_limit_exceeded'
                    }
            
            except Exception as e:
                logging.error(f"Claude API 호출 실패: {e}")
                return {
                    'explanation': self.generate_fallback_explanation(rag_docs),
                    'cached': False,
                    'error': str(e)
                }
    
    def generate_fallback_explanation(self, rag_docs):
        """API 실패 시 Fallback 설명 생성"""
        if rag_docs:
            # RAG 문서에서 가장 관련성 높은 부분 추출
            best_doc = max(rag_docs, key=lambda d: d['relevance_score'])
            return f"{best_doc['excerpt']}\n\n(출처: {best_doc['title']})"
        else:
            return "죄송합니다. 현재 이 용어에 대한 설명을 생성할 수 없습니다. 잠시 후 다시 시도해주세요."
```

---

## 10단계: 최종 권장사항

### 추천 구현 순서

**Week 1-2: Phase 1 - JSON 기반 MVP**
- [ ] JSON 용어 사전 파일 생성 (50개 핵심 용어)
- [ ] 간단한 키워드 매칭 구현
- [ ] Claude API 연동 (RAG 없이 프롬프트만)
- [ ] 기본 UI 구현 (용어 하이라이트, 설명 모달)

**Week 3-4: 데이터 수집 자동화**
- [ ] Confluence API 연동
- [ ] SharePoint 또는 Google Drive 연동 (우선순위에 따라 선택)
- [ ] 배치 수집 스크립트 구현
- [ ] 관리자 승인 UI

**Week 5-6: Phase 2 - 기본 RAG**
- [ ] PostgreSQL + pgvector 설정
- [ ] OpenAI embedding API 연동
- [ ] 벡터 검색 구현
- [ ] Claude API + RAG context 통합

**Week 7-8: 품질 개선**
- [ ] 사용자 피드백 시스템
- [ ] 품질 지표 대시보드
- [ ] A/B 테스트 (키워드 매칭 vs RAG)
- [ ] 성능 최적화 (캐싱, 인덱싱)

**Week 9-10: Phase 3 - 고도화 (선택)**
- [ ] Qdrant 도입 (필요 시)
- [ ] 하이브리드 검색
- [ ] 자동 품질 검증
- [ ] 외부 문서 크롤링

### 예상 비용 (월간)

| 항목 | Phase 1 | Phase 2 | Phase 3 |
|------|---------|---------|---------|
| **인프라** |
| PostgreSQL (RDS) | $50 | $100 | $150 |
| Redis (ElastiCache) | $30 | $50 | $50 |
| Qdrant | - | - | $500 |
| **API 사용료** |
| OpenAI Embedding | - | $20 | $50 |
| Claude API | $100 | $300 | $500 |
| **기타** |
| 저장공간 (S3) | $10 | $20 | $30 |
| **총계** | **$190/월** | **$490/월** | **$1,280/월** |

### 성공 지표 (KPI)

1. **사용성**
   - 용어 조회율: 회의당 평균 3회 이상
   - 설명 유용성 평가: 4.0/5.0 이상
   - 응답 시간: 평균 2초 이하

2. **정확도**
   - 용어 추출 정확도: 85% 이상
   - 설명 적합성: 사용자 피드백 80% 긍정
   - False positive rate: 10% 이하

3. **비즈니스**
   - 신규 회의 중 기능 사용률: 60% 이상
   - 월 활성 사용자: 전체의 50% 이상
   - 회의록 작성 시간 단축: 20% 이상

### 리스크 및 완화 전략

| 리스크 | 영향도 | 완화 전략 |
|--------|--------|----------|
| Claude API 비용 급증 | 높음 | 캐싱 강화, 월 예산 한도 설정, Fallback 메커니즘 |
| 조직 용어 정확도 낮음 | 높음 | 수동 큐레이션 우선, 피드백 루프, 정기 품질 감사 |
| 응답 시간 느림 | 중간 | 3-tier 캐싱, 벡터 DB 최적화, CDN 활용 |
| 데이터 수집 실패 | 중간 | Retry 로직, 여러 소스 분산, 수동 백업 |
| 사용자 채택률 낮음 | 중간 | UX 개선, 온보딩 교육, 사용 인센티브 |

---

## 최종 결론

**선정된 최적안**: 하이브리드 RAG 시스템 (단계적 접근)

**핵심 장점**:
1. ✅ 조직 특화 용어의 높은 정확도 (JSON 큐레이션)
2. ✅ 확장 가능한 아키텍처 (RAG 시스템)
3. ✅ 합리적인 비용 구조 ($190/월 시작)
4. ✅ 명확한 구현 경로 (3-phase)
5. ✅ 차별화된 맥락 기반 설명

**다음 단계**:
1. Week 1-2에 MVP 구현 시작
2. 50개 핵심 용어 큐레이션
3. Claude API 연동 및 테스트
4. 베타 사용자 10명 초대하여 피드백 수집

---

**작성일**: 2025-10-28
**작성자**: 회의록 개선 프로젝트 팀
**버전**: 1.0
**승인자**: 김민준 (Product Owner)