--- tags: 함수형 프로그래밍,부작용 분리,에이전트 설계,스킬,실전 사례 date: 2025-06-17 --- 요약 - 함수형 프로그래밍은 입력과 출력만을 다루는 **순수 함수**를 통해 코드의 예측 가능성과 테스트 효율을 극대화합니다. - 데이터베이스 쓰기나 네트워크 호출처럼 외부 상태를 변경하는 **부작용**은 별도의 오케스트레이터 계층에서 처리해야 합니다. - 이렇게 계층을 분리하면 스킬·아이템 모듈을 안전하게 병렬 실행하고, 버전 교체와 롤백을 간단하게 수행할 수 있습니다. # 함수형과 부작용 분리 실전 사례 ## 1. 문서 요약 스킬 ### 순수 함수 계층 ```python from typing import List def summarize(paragraphs: List[str]) -> str: """항상 동일 입력에 동일 출력을 보장하는 요약 함수""" merged = " ".join(paragraphs) sentences = merged.split(".") return ". ".join(sentences[:3]) + "." ``` ### 오케스트레이터 계층 ```python from db import save_summary from summarize import summarize from slack_webhook import post_to_slack def handle_request(doc_id: str, paragraphs: list[str]) -> None: summary = summarize(paragraphs) # 순수 계산 save_summary(doc_id, summary) # 부작용: DB 기록 post_to_slack(summary) # 부작용: 네트워크 호출 ``` ## 2. 전자상거래 수수료·세금 계산 ### 순수 함수 계층 ```typescript // fee.ts export type Basket = { price: number; quantity: number }[]; export function calcTotals(basket: Basket) { const subtotal = basket.reduce( (acc, item) => acc + item.price * item.quantity, 0); const vat = subtotal * 0.1; const platformFee = subtotal * 0.03; return { subtotal, vat, platformFee, total: subtotal + vat + platformFee }; } ``` ### 오케스트레이터 계층 ```typescript // checkout.ts import { chargeCard } from "./paymentGateway"; import { recordOrder } from "./db"; import { calcTotals } from "./fee"; export async function checkout(userId: string, basket: Basket) { const totals = calcTotals(basket); # 순수 계산 await chargeCard(userId, totals.total); # 부작용: 결제 게이트웨이 await recordOrder(userId, basket, totals); # 부작용: DB 기록 } ``` ## 3. 실시간 알림 브로드캐스트 (Elixir OTP) ### 순수 함수 계층 ```elixir defmodule Alerts.Core do @spec reduce_state(map(), %{type: atom(), payload: map()}) :: map() def reduce_state(state, %{type: :new_follow, payload: %{user: u}}) do Map.update(state, :followers, [u], &[u | &1]) end def reduce_state(state, _event), do: state end ``` ### 오케스트레이터 계층 ```elixir defmodule Alerts.Server do use GenServer alias Alerts.Core def handle_cast({:event, event}, state) do new_state = Core.reduce_state(state, event) # 순수 계산 broadcast_changes(state, new_state) # 부작용: 웹소켓 푸시 {:noreply, new_state} end end ``` # 핵심 교훈 1. **순수 함수 계층**은 입력만 받아 동일한 출력을 보장하므로 테스트가 간단하고 캐싱·병렬 실행에 유리합니다. 2. **오케스트레이터 계층**은 순수 함수의 결과를 실제로 저장하거나 전송하면서 부작용을 집중 관리하므로 감사·롤백·보안 검증이 명확해집니다. 3. 스킬·아이템을 순수 함수로 작성하고, 코어에서 부작용을 처리하는 구조를 적용하면 로빈 같은 멀티모달 에이전트 시스템에서도 안정성과 유지보수성이 크게 향상됩니다.