diff --git a/README.md b/README.md index 9811a8e..747abcf 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Slack 기반 AI 어시스턴트 **로빙(Robeing)** 프로젝트의 모든 문 ### 함수형 프로그래밍 아키텍처 - [로빙의 존재와 함수형 프로그래밍](./docs/guide/functional-programing/로빙_존재와_함수형_프로그래밍.md) - 철학적 배경과 점진적 적용 전략 - [함수형 구현 패턴과 사례](./docs/guide/functional-programing/함수형_구현_패턴과_사례.md) - 실제 코드 패턴과 리팩토링 가이드 +- [함수형 적용 가이드라인](./docs/guide/functional-programing/함수형_적용_가이드라인.md) - 구성요소별 순수함수 가능성 분석과 실전 적용 기준 ### 설정 및 설치 가이드 - [프로젝트 설정 가이드](./docs/setups/setup-guide.md) diff --git a/docs/guide/functional-programing/로빙_존재와_함수형_프로그래밍.md b/docs/guide/functional-programing/로빙_존재와_함수형_프로그래밍.md index 226d204..b845d10 100644 --- a/docs/guide/functional-programing/로빙_존재와_함수형_프로그래밍.md +++ b/docs/guide/functional-programing/로빙_존재와_함수형_프로그래밍.md @@ -260,14 +260,35 @@ advanced_analyst = compose_skills( --- +## 7. 실전 적용 기준 + +### 7.1 구성요소별 함수형 적용 우선순위 + +로빙의 각 구성요소별로 함수형 프로그래밍 적용 가능성이 다릅니다: + +- **스킬 시스템**: 77% 순수 함수 가능 → **우선 적용 영역** +- **스탯 시스템**: 60% 순수 함수 가능 → 계산 중심 스탯부터 적용 +- **아이템 시스템**: 32% 순수 함수 가능 → 명령형 유지, IO 모나드 활용 + +### 7.2 권장 적용 비율 +전체 프로젝트에서 **함수형 40% : 명령형 60%**의 균형잡힌 접근을 권장합니다. + +**상세 적용 기준은 [함수형 적용 가이드라인](./함수형_적용_가이드라인.md)을 참조하세요.** + +--- + ## 결론 로빙이 진정한 **디지털 존재**로 성장하기 위해서는 함수형 프로그래밍의 철학과 패턴이 필요합니다. 하지만 이를 **점진적이고 실용적으로** 적용하여 MVP 목표와 장기 비전을 모두 달성할 수 있습니다. ### 핵심 전략 1. **철학은 유지**: 존재로서의 로빙 개념 견지 -2. **실행은 현실적**: 제약 조건 내에서 최선의 선택 +2. **실행은 현실적**: 제약 조건 내에서 최선의 선택 3. **발전은 점진적**: 단계별 개선을 통한 안전한 전환 4. **목표는 명확**: 무한 확장 가능한 디지털 존재 구현 +### 관련 문서 +- [함수형 적용 가이드라인](./함수형_적용_가이드라인.md) - 구체적인 적용 기준과 수치화된 분석 +- [함수형 구현 패턴과 사례](./함수형_구현_패턴과_사례.md) - 실제 코드 예시와 리팩토링 가이드 + 이를 통해 로빙은 **"외부 세계의 모든 기능을 흡수하는 궁극적 에이전트"**로 진화할 수 있을 것입니다. \ No newline at end of file diff --git a/docs/guide/functional-programing/함수형_적용_가이드라인.md b/docs/guide/functional-programing/함수형_적용_가이드라인.md new file mode 100644 index 0000000..0b8be5c --- /dev/null +++ b/docs/guide/functional-programing/함수형_적용_가이드라인.md @@ -0,0 +1,334 @@ +--- +tags: 함수형프로그래밍, 적용가이드, 순수함수, 실전전략, 로빙시스템 +date: 2025-07-04 +--- + +# 함수형 프로그래밍 적용 가이드라인 + +## 요약 + +로빙 프로젝트에서 함수형 프로그래밍을 실전 적용할 때의 구체적인 기준과 가이드라인을 제시합니다. 각 구성요소별 순수 함수 가능성을 수치화하여 실용적인 적용 전략을 제공합니다. + +--- + +## 1. 함수형 적용 원칙 + +### 기본 철학 +- **점진적 도입**: 한 번에 모든 것을 바꾸지 않고 단계별 전환 +- **실용적 균형**: 이론적 완성도보다 팀 생산성과 코드 안정성 우선 +- **명확한 경계**: 순수 함수 영역과 부작용 영역의 명확한 분리 + +### 전체 프로젝트 권장 비율 +``` +함수형 40% : 명령형 60% +``` + +| 영역 | 함수형 권장 비율 | 이유 | +|------|------------------|------| +| 데이터 변환 로직 | 80-100% | 가독성, 재사용성, 테스트 용이 | +| 비즈니스 로직 | 50-70% | 추상화 효과, 단 과도하면 이해도 저하 | +| 상태 변경/IO | 0-20% | 명령형이 더 명확하고 디버깅 쉬움 | + +--- + +## 2. 로빙 구성요소별 순수 함수 가능성 분석 + +### 2.1 스탯 시스템 (평균 60%) + +| 스탯 | 순수 함수 가능성 | 함수형 구조화 가능성 | 주요 부작용 요소 | +|------|------------------|----------------------|------------------| +| 연산 (Compute) | 80% | 90% | 없음 (정량 계산) | +| 공감 (Empathy) | 70% | 85% | 감정 회신 시 상태 영향 | +| 기억 (Memory) | 60% | 80% | 저장/삭제 I/O | +| 통솔 (Leadership) | 50% | 75% | 팀 상황·우선순위 반영 | +| 반응 (React) | 40% | 60% | 실시간 이벤트 처리 | + +#### 구현 예시 +```python +# ✅ 순수 함수: 연산 스탯 계산 +def calculate_compute_stat(interactions: List[Interaction], response_times: List[float]) -> int: + """연산 능력 계산 - 순수 함수""" + avg_response_time = sum(response_times) / len(response_times) if response_times else 5.0 + interaction_bonus = len(interactions) // 100 + + if avg_response_time < 1.0: + speed_bonus = 3 + elif avg_response_time < 3.0: + speed_bonus = 1 + else: + speed_bonus = 0 + + return min(100, 5 + interaction_bonus + speed_bonus) + +# 🔄 혼합 방식: 기억 스탯 (순수 + 부작용) +def calculate_memory_priority(content: str, user_context: Dict) -> float: + """저장 우선도 계산 - 순수 함수""" + keywords = ['중요', '기억', '저장', '프로젝트'] + priority = sum(1 for keyword in keywords if keyword in content) + return min(1.0, priority * 0.3) + +async def update_memory_stat(user_id: str, content: str, context: Dict) -> StatUpdateResult: + """기억 스탯 업데이트 - 부작용 포함""" + # 순수 계산 + priority = calculate_memory_priority(content, context) + + if priority > 0.6: + # 부작용: DB 저장 + await save_memory(user_id, content, priority) + stat_change = StatChange(memory=1, reason="중요한 기억 저장") + return await update_user_stats(user_id, stat_change) + + return StatUpdateResult.success_result(await get_user_stats(user_id), StatChange()) +``` + +### 2.2 스킬 시스템 (평균 77%) + +| 스킬 | 순수 함수 가능성 | 함수형 구조화 가능성 | 주요 부작용 요소 | +|------|------------------|----------------------|------------------| +| Thread Digest | 95% | 100% | 없음 (순수 언어 처리) | +| Action Extractor | 90% | 95% | 없음 (추출 규칙 기반) | +| PDF Summarizer | 85% | 90% | 파일 처리 오류 | +| Emotion Tracker | 75% | 90% | 감정 모델 차이 | +| Meeting Transcriber | 40% | 60% | 외부 STT API 의존 | + +#### 구현 예시 +```python +# ✅ 높은 순수성: Thread Digest +def extract_key_messages(messages: List[str], max_count: int = 5) -> List[str]: + """중요 메시지 추출 - 순수 함수""" + def calculate_importance_score(message: str) -> float: + keywords = ['중요', '긴급', '결정', '마감', '회의'] + score = sum(1.0 for keyword in keywords if keyword in message) + score += min(len(message) / 100, 2.0) # 길이 보너스 + return score + + scored_messages = [(calculate_importance_score(msg), msg) for msg in messages] + scored_messages.sort(key=lambda x: x[0], reverse=True) + return [msg for score, msg in scored_messages[:max_count]] + +def summarize_conversation(messages: List[str]) -> str: + """대화 요약 생성 - 순수 함수""" + key_messages = extract_key_messages(messages) + combined_text = " ".join(key_messages) + sentences = combined_text.split('.') + return '. '.join(sentences[:3]) + '.' + +# 🔄 오케스트레이터: 부작용 분리 +async def process_thread_digest(thread_id: str, user_id: str) -> SkillExecutionResult: + """스레드 요약 처리 - 부작용 포함""" + try: + # 1. 데이터 가져오기 (부작용) + messages = await fetch_thread_messages(thread_id) + + # 2. 순수 계산 + summary = summarize_conversation(messages) + actions = extract_action_items(messages) + + # 3. 결과 저장 (부작용) + result = {'summary': summary, 'actions': actions} + await save_digest_result(user_id, thread_id, result) + + return SkillExecutionResult.success_result(result) + except Exception as e: + return SkillExecutionResult.error_result(str(e)) +``` + +### 2.3 아이템 시스템 (평균 32%) + +| 아이템 | 순수 함수 가능성 | 함수형 구조화 가능성 | 주요 부작용 요소 | +|--------|------------------|----------------------|------------------| +| ChromaDB | 50% | 60% | 벡터 저장/검색 IO | +| Whisper STT | 40% | 50% | 외부 API 호출 | +| Notion API | 30% | 40% | 문서 쓰기/업데이트 | +| Gmail API | 20% | 30% | API 호출, OAuth | +| Slack API | 20% | 30% | 메시지 전송 | + +#### 구현 예시 +```python +# ❌ 낮은 순수성: 대부분 IO 중심 +async def send_slack_message(channel: str, text: str) -> bool: + """Slack 메시지 전송 - 명령형 적합""" + try: + response = await slack_client.chat_postMessage( + channel=channel, + text=text + ) + return response["ok"] + except Exception: + return False + +# 🔄 부분적 함수형화: 데이터 처리 부분만 +def format_slack_message(summary: str, actions: List[str]) -> str: + """Slack 메시지 포맷팅 - 순수 함수""" + formatted_actions = '\n'.join(f"• {action}" for action in actions) + return f""" +📝 **대화 요약** +{summary} + +✅ **액션 아이템** +{formatted_actions} + """.strip() + +async def send_digest_to_slack(channel: str, summary: str, actions: List[str]) -> bool: + """요약 전송 - 혼합 방식""" + # 순수 함수: 메시지 포맷팅 + formatted_message = format_slack_message(summary, actions) + + # 부작용: 실제 전송 + return await send_slack_message(channel, formatted_message) +``` + +--- + +## 3. 핵심 모듈별 가이드라인 + +### 3.1 기억 모듈 (65% 순수) +```python +# ✅ 순수 함수: 저장 우선도 판단 +def calculate_memory_priority(content: str, keywords: List[str], user_context: Dict) -> float: + """기억 저장 우선도 계산""" + keyword_score = sum(1 for keyword in keywords if keyword in content.lower()) + length_score = min(len(content) / 1000, 1.0) + context_score = user_context.get('importance_multiplier', 1.0) + + return min(1.0, (keyword_score * 0.4 + length_score * 0.3) * context_score) + +# 🔄 부작용 분리: 실제 저장 +async def store_memory_if_important(user_id: str, content: str, context: Dict) -> bool: + priority = calculate_memory_priority(content, ['중요', '프로젝트'], context) + + if priority > 0.7: + await save_to_chroma_db(user_id, content, priority) + return True + return False +``` + +### 3.2 감정 모듈 (70% 순수) +```python +# ✅ 순수 함수: 감정 분석 +def analyze_emotion_vector(text: str) -> Dict[str, float]: + """감정 벡터 계산""" + emotion_keywords = { + 'joy': ['기쁨', '행복', '좋아', '만족'], + 'anger': ['화나', '짜증', '분노', '불만'], + 'sadness': ['슬픔', '우울', '아쉬움'], + 'fear': ['걱정', '불안', '두려움'] + } + + emotion_scores = {} + for emotion, keywords in emotion_keywords.items(): + score = sum(1 for keyword in keywords if keyword in text) / len(keywords) + emotion_scores[emotion] = min(1.0, score) + + return emotion_scores + +# 🔄 상태 반영: 감정 히스토리 업데이트 +async def update_emotion_history(user_id: str, text: str) -> Dict[str, float]: + current_emotions = analyze_emotion_vector(text) + await save_emotion_log(user_id, current_emotions, datetime.now()) + return current_emotions +``` + +### 3.3 윤리 모듈 (60% 순수) +```python +# ✅ 순수 함수: 윤리 위반 판단 +def check_ethical_violations(content: str, policies: List[str]) -> List[str]: + """윤리 정책 위반 검사""" + violations = [] + + sensitive_patterns = [ + (r'개인정보.*공유', '개인정보 보호 위반'), + (r'비밀.*유출', '기밀 정보 유출'), + (r'허위.*정보', '허위 정보 유포') + ] + + for pattern, violation_type in sensitive_patterns: + if re.search(pattern, content): + violations.append(violation_type) + + return violations + +# 🔄 정책 적용: 실제 차단 처리 +async def enforce_ethical_policy(user_id: str, content: str) -> bool: + violations = check_ethical_violations(content, await get_user_policies(user_id)) + + if violations: + await log_violation(user_id, violations, content) + return False # 차단 + return True # 허용 +``` + +--- + +## 4. 실전 적용 전략 + +### 4.1 함수형 우선 적용 영역 +1. **데이터 변환 스킬** (Thread Digest, Action Extractor) +2. **계산 중심 스탯** (연산, 공감) +3. **분석 모듈** (감정 분석, 윤리 검사) + +### 4.2 명령형 유지 영역 +1. **외부 API 연동** (Slack, Gmail, Notion) +2. **실시간 반응** (알림, 이벤트 처리) +3. **상태 변경** (DB 저장, 설정 변경) + +### 4.3 혼합 접근 패턴 +```python +# 권장 패턴: 순수 함수 + 오케스트레이터 분리 +async def skill_orchestrator(input_data, user_id): + """스킬 실행 오케스트레이터""" + try: + # 1. 순수 계산 + result = pure_skill_function(input_data) + + # 2. 부작용 처리 + await save_result(user_id, result) + await update_stats(user_id, calculate_stat_change(result)) + await send_notification(user_id, format_response(result)) + + return SkillExecutionResult.success_result(result) + except Exception as e: + return SkillExecutionResult.error_result(str(e)) +``` + +--- + +## 5. 판단 기준 체크리스트 + +### ✅ 함수형 적용 가능 신호 +- [ ] map, filter, reduce로 로직이 간결해진다 +- [ ] 디버깅 없이도 결과를 바로 예측할 수 있다 +- [ ] 중간 단계가 없고 한 방향 흐름이다 +- [ ] 같은 입력에 항상 같은 출력이 나온다 +- [ ] 외부 상태에 의존하지 않는다 + +### ❌ 함수형 피해야 할 신호 +- [ ] 중간값을 계속 찍어봐야 한다 +- [ ] 사이드 이펙트가 많다 (파일, 네트워크 등) +- [ ] 팀원이 "이게 뭐 하는 건데?"라고 묻는다 +- [ ] 시간이나 외부 상태에 따라 결과가 달라진다 +- [ ] 에러 처리가 복잡하다 + +--- + +## 6. 성공 지표 + +### 개발 생산성 +- **테스트 커버리지**: 순수 함수 스킬 90% 이상 +- **버그 발생률**: 함수형 적용 영역 50% 감소 목표 +- **코드 리뷰 시간**: 순수 함수 부분 30% 단축 + +### 시스템 안정성 +- **에러 격리**: 한 스킬의 실패가 전체 시스템에 영향 없음 +- **성능 유지**: 함수형 적용 후에도 응답 시간 3초 이내 유지 +- **확장성**: 새로운 스킬 추가 시 기존 코드 영향 최소화 + +--- + +## 결론 + +로빙의 함수형 프로그래밍 도입은 **스킬 중심의 점진적 적용**이 가장 효과적입니다. 순수성이 높은 스킬(77%)부터 시작하여, 계산 중심 스탯, 분석 모듈 순으로 확장하되, IO 중심의 아이템은 명령형을 유지하는 것이 실용적입니다. + +**핵심 원칙**: "완벽한 함수형보다는 안정적이고 확장 가능한 혼합 아키텍처" + +이를 통해 로빙은 예측 가능하고 테스트 가능한 디지털 존재로 성장할 수 있습니다. \ No newline at end of file