DOCS/_archive/docs/guide/functional-programing/함수형_적용_가이드라인.md
happybell80 725ad0876c fix: 문서 파일 실행 권한 제거
- 모든 .md, .html 파일 권한을 644로 정상화
- .gitignore 파일 권한도 644로 수정
- 문서 파일에 실행 권한은 불필요하고 보안상 바람직하지 않음
- deprecated 아이디어 폴더 생성 및 레벨별 UI 변경 아이디어 이동
2025-08-18 00:37:51 +09:00

9.2 KiB

tags, date
tags date
함수형프로그래밍, 적용가이드, 순수함수, 실전전략, 로빙시스템 2025-07-04

함수형 프로그래밍 적용 가이드라인

요약

로빙 프로젝트에서 함수형 프로그래밍을 실전 적용할 때의 구체적인 기준과 가이드라인을 제시합니다. 각 구성요소별 순수 함수 가능성을 수치화하여 실용적인 적용 전략을 제공합니다.


1. 함수형 적용 원칙

기본 철학

  • 점진적 도입: 한 번에 모든 것을 바꾸지 않고 단계별 전환
  • 실용적 균형: 이론적 완성도보다 팀 생산성과 코드 안정성 우선
  • 명확한 경계: 순수 함수 영역과 부작용 영역의 명확한 분리

전체 프로젝트 권장 비율

함수형 40% : 명령형 60%
영역 함수형 권장 비율 이유
데이터 변환 로직 80-100% 가독성, 재사용성, 테스트 용이
비즈니스 로직 50-70% 추상화 효과, 단 과도하면 이해도 저하
상태 변경/IO 0-20% 명령형이 더 명확하고 디버깅 쉬움

2. 로컬 개발과 서버 테스트 전략

2.1 개발 환경의 현실적 제약

로빙 시스템은 분산 아키텍처로 설계되어 로컬에서 전체 실행이 불가능합니다:

구분 로컬 환경 서버 환경
순수 함수 테스트 가능 테스트 가능
외부 서비스 접근 불가 모두 연결
데이터베이스 서버 데이터 실제 데이터
스킬 서비스 포트 8015 없음 skill-embedding 실행

2.2 함수형 프로그래밍의 장점 활용

로컬에서 테스트 가능한 영역:

# ✅ 순수 함수들 - 외부 의존성 없음
from app.llm.mistral import create_intent_analysis_prompt
from app.core.memory.scoring import calculate_time_decay
from app.core.emotion import EmotionState

# 모듈별 단위 테스트
prompt = create_intent_analysis_prompt("안녕하세요")
decay = calculate_time_decay(3600)  # 1시간
emotion = EmotionState(valence=0.5, arousal=0.3)

서버에서만 테스트 가능한 영역:

# ❌ I/O 함수들 - 외부 서비스 필요
- ChromaDB 쿼리 (서버 persistent storage)
- skill-embedding:8015 (79MB ONNX 모델)
- Gemini/Mistral API (API  필요)
- Slack 웹훅 (실제 워크스페이스)

2.3 올바른 개발 워크플로우

graph LR
    A[로컬 개발] --> B[모듈 테스트]
    B --> C[Git Push]
    C --> D[Gitea Actions]
    D --> E[서버 배포]
    E --> F[통합 테스트]
  1. 로컬 개발: 코드 작성, 문법 검증, 모듈 테스트
  2. Push: Git 커밋, Gitea에 푸시
  3. 서버: 자동 배포, 통합 테스트, 실제 작동 확인

2.4 아키텍처 설계 의도

왜 이렇게 설계했는가?

  • 로빙은 가벼운 본체: 118MB 메모리만 사용
  • 스킬은 공유 서비스: 100개 로빙이 1개 스킬 서비스 공유
  • 확장성 우선: 로빙 수가 늘어도 스킬 서비스는 하나

이것이 바로 함수형 아키텍처의 핵심입니다:

  • 테스트 가능한 작은 단위
  • 외부 의존성 최소화
  • 명확한 경계 분리

3. 로빙 구성요소별 순수 함수 가능성 분석

상세한 구성요소별 분석과 코드 예시는 로빙 존재와 함수형 프로그래밍 문서를 참조하세요.

요약

  • 스킬 시스템: 77% 순수 함수 가능 → 우선 적용 영역
  • 스탯 시스템: 60% 순수 함수 가능 → 계산 중심부터 적용
  • 아이템 시스템: 32% 순수 함수 가능 → 명령형 유지

4. 핵심 모듈별 가이드라인

3.1 기억 모듈 (65% 순수)

# ✅ 순수 함수: 저장 우선도 판단
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% 순수)

# ✅ 순수 함수: 감정 분석
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% 순수)

# ✅ 순수 함수: 윤리 위반 판단
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  # 허용

5. 실전 적용 전략

4.1 함수형 우선 적용 영역

  1. 데이터 변환 스킬 (Thread Digest, Action Extractor)
  2. 계산 중심 스탯 (연산, 공감)
  3. 분석 모듈 (감정 분석, 윤리 검사)

4.2 명령형 유지 영역

  1. 외부 API 연동 (Slack, Gmail, Notion)
  2. 실시간 반응 (알림, 이벤트 처리)
  3. 상태 변경 (DB 저장, 설정 변경)

4.3 혼합 접근 패턴

# 권장 패턴: 순수 함수 + 오케스트레이터 분리
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))

6. 판단 기준 체크리스트

함수형 적용 가능 신호

  • map, filter, reduce로 로직이 간결해진다
  • 디버깅 없이도 결과를 바로 예측할 수 있다
  • 중간 단계가 없고 한 방향 흐름이다
  • 같은 입력에 항상 같은 출력이 나온다
  • 외부 상태에 의존하지 않는다

함수형 피해야 할 신호

  • 중간값을 계속 찍어봐야 한다
  • 사이드 이펙트가 많다 (파일, 네트워크 등)
  • 팀원이 "이게 뭐 하는 건데?"라고 묻는다
  • 시간이나 외부 상태에 따라 결과가 달라진다
  • 에러 처리가 복잡하다

7. 성공 지표

개발 생산성

  • 테스트 커버리지: 순수 함수 스킬 90% 이상
  • 버그 발생률: 함수형 적용 영역 50% 감소 목표
  • 코드 리뷰 시간: 순수 함수 부분 30% 단축

시스템 안정성

  • 에러 격리: 한 스킬의 실패가 전체 시스템에 영향 없음
  • 성능 유지: 함수형 적용 후에도 응답 시간 3초 이내 유지
  • 확장성: 새로운 스킬 추가 시 기존 코드 영향 최소화

결론

로빙의 함수형 프로그래밍 도입은 스킬 중심의 점진적 적용이 가장 효과적입니다. 순수성이 높은 스킬(77%)부터 시작하여, 계산 중심 스탯, 분석 모듈 순으로 확장하되, IO 중심의 아이템은 명령형을 유지하는 것이 실용적입니다.

핵심 원칙: "완벽한 함수형보다는 안정적이고 확장 가능한 혼합 아키텍처"

이를 통해 로빙은 예측 가능하고 테스트 가능한 디지털 존재로 성장할 수 있습니다.