엔지니어를 위한 Dify 마스터 클래스: 아키텍처 해부부터 실전 배포까지

구분전문가 심화편
버전Dify v1.x (2026년 5월)
GitHub Stars131,000+ (2026.05)
난이도중급 ~ 전문가
Dify Workflow 완전 정복 RAG 파이프라인 심화 에이전트 전략 MCP 양방향 연동 프로덕션 배포 n8n · Ollama 통합
Dify는 2026년 GitHub 스타 131,000+, $30M 시리즈 Pre-A 유치, Maersk·Novartis 등 280개 기업이 사용하는 오픈소스 AI 앱 플랫폼입니다. 단순 챗봇을 넘어 프로덕션 수준의 에이전트 워크플로우·RAG 파이프라인·MCP 양방향 연동·플러그인 에코시스템을 시각적으로 구축합니다. 이 글에서는 Docker 설치부터 전문가 수준의 워크플로우 설계, RAG 최적화, 에이전트 전략, MCP 서버 연동, n8n과의 통합까지 완전히 다룹니다.
SECTIOND1

Dify 아키텍처 & 앱 유형 완전 이해

Dify는 단순한 챗봇 빌더가 아닙니다. LLM 오케스트레이션 + 비주얼 워크플로우 + RAG 엔진 + LLMOps + 배포 허브를 통합한 프로덕션 AI 플랫폼입니다. 2026년 3월 $30M 시리즈 Pre-A를 유치했고, Fortune 500 기업 포함 280개 이상의 기업이 프로덕션에서 사용합니다.

🏗️ Dify 플랫폼 3계층 구조

🎨 Visual Studio (비주얼 빌더)
드래그 앤 드롭 캔버스에서 AI 워크플로우를 시각적으로 설계합니다. Prompt IDE, RAG 설정, 에이전트 전략 설정이 통합되어 있습니다.
⚙️ LLM Orchestration (모델 관리)
OpenAI, Claude, Gemini, Ollama, DeepSeek 등 100개+ LLM을 통합 관리합니다. 모델 간 전환, 폴백, 비용 추적을 중앙에서 처리합니다.
🚀 Deployment Hub (배포 허브)
만든 앱을 REST API, 웹 채팅 위젯, MCP 서버, 공개 URL 등 다양한 형태로 즉시 배포합니다. Backend-as-a-Service가 복잡도를 처리합니다.
📊 LLMOps (운영 도구)
로그 추적, 사용자 평가, 토큰 비용 모니터링, 응답 주석(Annotation), A/B 테스트를 내장합니다. Langfuse와의 네이티브 통합도 지원합니다.

📱 4가지 앱 유형 — 언제 무엇을 써야 하는가

앱 유형구조최적 용도특징
Chatbot대화형 · 메모리 보존고객 지원, 사내 Q&A, 상담 봇대화 기록 유지. 사람과 자연스럽게 여러 턴 대화
Text Generator단방향 생성이메일 초안, 번역, 요약, SEO 콘텐츠입력 → 출력. 대화 불필요한 일회성 텍스트 생성
Agent자율 추론 + 도구조사, 데이터 분석, 자율 코딩LLM이 상황 판단해 도구 자율 선택. ReAct/FC 전략
WorkflowDAG 방식 결정론적문서 처리, 다단계 파이프라인, 자동화노드 간 명확한 흐름. 분기·병렬·반복 제어 가능
💡
Agent vs Workflow — 언제 무엇을 선택해야 하는가

Workflow: 처리 단계가 정해져 있고 예측 가능한 결과가 필요할 때. 문서 → 요약 → 번역 → 저장 같은 파이프라인. Agent: LLM이 상황을 판단하고 도구를 자율 선택해야 할 때. “이 질문에 답하기 위해 웹을 검색하고 계산하고 판단한다”. 두 유형을 혼합한 Chatflow(대화형 Workflow + Agent Node)도 매우 강력합니다.

🔀 Dify vs n8n vs LangChain — 선택 기준

항목Difyn8nLangChain
주요 용도AI 앱 빌더 · RAG · 에이전트일반 워크플로우 자동화코드 기반 LLM 앱 개발
코딩 필요최소 (Code Node로 선택적)최소 (Function 노드)필수 (Python/TS)
RAG 기능🟢 최고 수준 (내장)🟡 별도 구성 필요🟡 직접 구현
AI 에이전트🟢 강력 (Agent Node)🟡 AI 노드 연동🟢 강력 (코드)
LLMOps🟢 내장🔴 없음🔴 별도 도구 필요
통합 서비스🟡 50+ 도구🟢 500+ 서비스🟢 수백 개
권장 조합Dify(AI 앱) + n8n(업무 자동화) 함께 쓰는 것이 최강
SECTIOND2

프로덕션 Docker 설치 & 환경 구성

🐳 Docker Compose 빠른 시작

bash — Dify 공식 Docker 설치 (권장)
# 1. 저장소 클론
git clone https://github.com/langgenius/dify.git
cd dify/docker

# 2. 환경변수 파일 복사
cp .env.example .env

# 3. .env 핵심 설정 (반드시 변경!)
nano .env

# 4. 서비스 시작
docker compose up -d

# 5. 상태 확인
docker compose ps
docker compose logs -f api

# 접속: http://서버IP
# 초기 관리자 계정 설정 후 사용 시작

📋 .env 핵심 환경변수 완전 해설

env — dify/docker/.env 필수 설정
# ── 보안 핵심 키 (반드시 변경!) ──────────────────────
# SECRET_KEY: Flask 세션 서명용. openssl rand -base64 42 로 생성
SECRET_KEY=your_very_long_random_secret_key_here

# 초기 관리자 이메일 & 비밀번호 (첫 실행 시만 적용)
INIT_PASSWORD=your_admin_password

# ── 외부 공개 URL ─────────────────────────────────────
# 도메인 연결 시 반드시 실제 URL로 변경
CONSOLE_API_URL=https://dify.yourcompany.com
CONSOLE_WEB_URL=https://dify.yourcompany.com
SERVICE_API_URL=https://dify.yourcompany.com
APP_WEB_URL=https://dify.yourcompany.com

# ── 데이터베이스 (PostgreSQL) ─────────────────────────
DB_USERNAME=postgres
DB_PASSWORD=difyai123456        # 반드시 변경!
DB_HOST=db
DB_PORT=5432
DB_DATABASE=dify

# ── 벡터 데이터베이스 선택 ────────────────────────────
# weaviate | qdrant | milvus | chroma | pgvector | opensearch
VECTOR_STORE=qdrant

# Qdrant 설정 (권장)
QDRANT_URL=http://qdrant:6333
QDRANT_API_KEY=difyai123456     # 변경 권장

# ── Redis ─────────────────────────────────────────────
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=difyai123456     # 변경 권장

# ── 파일 저장소 ───────────────────────────────────────
# local | s3 | azure-blob | google-storage
STORAGE_TYPE=local
STORAGE_LOCAL_PATH=/app/api/storage

# ── 모델 공급자 기본 설정 (선택) ──────────────────────
# 워크스페이스별로 설정하는 것이 더 권장되지만
# 기본값으로 넣을 수 있음
# ANTHROPIC_API_KEY=sk-ant-xxx
# OPENAI_API_KEY=sk-xxx

# ── 플러그인 설정 (v1.x) ──────────────────────────────
PLUGIN_DAEMON_URL=http://plugin_daemon:5003
PLUGIN_DAEMON_KEY=lYkiYYT6owG+71oLerGzA7GXCgOT++6dFUAg==  # 변경!

# ── 이메일 (비밀번호 재설정 등) ──────────────────────
MAIL_TYPE=smtp
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
[email protected]
SMTP_PASSWORD=your_app_password
[email protected]

📦 Dify Docker Compose 서비스 구조 해설

서비스명역할포트데이터 저장
apiDify 백엔드 API 서버 (Python/Flask)5001스토리지 볼륨
webDify 프론트엔드 (Next.js)3000없음 (정적)
workerCelery 비동기 태스크 (임베딩 등)없음Redis 큐
dbPostgreSQL 데이터베이스5432db 볼륨
redis캐시 & 태스크 큐6379redis 볼륨
qdrant (또는 다른 VDB)벡터 데이터베이스 (RAG)6333qdrant 볼륨
nginx내부 역방향 프록시80/443없음
plugin_daemon플러그인 실행 데몬 (v1.x)5003플러그인 볼륨
sandboxPython/JS 코드 노드 격리 실행8194없음

🌐 Nginx 역방향 프록시 설정 (외부 도메인 공개)

nginx — dify.yourcompany.com 역방향 프록시
server {
    listen 80;
    server_name dify.yourcompany.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name dify.yourcompany.com;

    ssl_certificate     /etc/letsencrypt/live/dify.yourcompany.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dify.yourcompany.com/privkey.pem;

    # 파일 업로드 크기 (대용량 문서 처리)
    client_max_body_size 100M;

    location / {
        proxy_pass http://localhost:80;  # Dify 내부 Nginx
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;

        # SSE(Server-Sent Events) 스트리밍 — 필수!
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 3600s;  # 긴 워크플로우 처리 시간
    }
}
SECTIOND3

워크플로우 노드 완전 정복 — 모든 노드 유형 해설

Dify 워크플로우는 노드(Node)를 캔버스에 연결하는 DAG(방향 비순환 그래프) 구조입니다. 각 노드는 특정 역할을 수행하고 결과를 다음 노드에 전달합니다. 노드를 이해하는 것이 고급 워크플로우 설계의 핵심입니다.

🧠 핵심 노드 완전 해설

노드역할주요 설정활용 패턴
Start워크플로우 진입점. 입력 변수 정의input 변수 스키마 정의모든 워크플로우의 시작
End워크플로우 종료. 출력 변수 정의output 변수 선택최종 결과 반환
LLMLLM 호출. 프롬프트 + 모델 선택시스템 프롬프트 · 사용자 프롬프트 · 모델 · 파라미터텍스트 생성, 분석, 분류
Knowledge RetrievalKnowledge Base에서 관련 청크 검색KB 선택 · Top K · Threshold · 검색 모드RAG 파이프라인 핵심
If/Else조건 분기. 변수 값에 따라 경로 분기조건식 (contains, =, >, < 등)분류 후 라우팅, 오류 처리
CodePython 또는 JavaScript 실행 (샌드박스)코드 입력 · 입출력 변수데이터 변환, 계산, 파싱
HTTP Request외부 API 호출 (GET/POST/PUT/DELETE)URL · 헤더 · 바디 · 인증외부 서비스 연동, 데이터 조회
Template TransformJinja2 템플릿으로 텍스트 조합Jinja2 템플릿 문자열여러 변수를 하나의 프롬프트로 조합
Variable Aggregator여러 분기의 결과를 하나로 통합통합할 변수 선택병렬 처리 후 결과 합치기
Iteration배열 데이터를 반복 처리입력 배열 · 내부 노드 구성여러 문서 처리, 배치 작업
AgentLLM이 자율적으로 도구를 선택·실행에이전트 전략 · 도구 목록 · 최대 반복자율 조사, 복잡한 멀티스텝
Tool특정 도구를 명시적으로 호출도구 선택 · 파라미터 매핑웹 검색, 이미지 생성, API 호출
Parameter ExtractorLLM을 이용해 텍스트에서 구조화 데이터 추출추출할 필드 스키마 정의사용자 입력 파싱, NLU
Document Extractor업로드된 파일에서 텍스트 추출파일 변수 선택PDF/DOCX 처리 파이프라인
List Filter배열 데이터 필터링, 정렬, 슬라이싱필터 조건 · 정렬 기준검색 결과 정제

🔢 변수 시스템 완전 이해

Dify 워크플로우에서 노드 간 데이터는 변수(Variable)로 전달됩니다. 변수 참조는 이중 중괄호로 작성합니다.

text — 변수 참조 문법 완전 가이드
# 기본 변수 참조 문법
{{노드ID.변수명}}

# 예시 — 이전 노드의 출력 참조
{{start.user_input}}          # Start 노드의 user_input 변수
{{llm_1.text}}               # LLM 노드 1의 텍스트 출력
{{knowledge_1.result}}       # Knowledge Retrieval의 결과
{{http_1.body}}              # HTTP 요청의 응답 본문
{{code_1.output.summary}}    # Code 노드의 출력 내 summary 필드

# 시스템 변수 (내장)
{{sys.query}}                # 사용자 질문 (Chatbot/Chatflow)
{{sys.user_id}}              # 현재 사용자 ID
{{sys.app_id}}               # 앱 ID
{{sys.conversation_id}}      # 대화 ID (Chatbot)

# Jinja2 템플릿에서 변수 사용
# Template Transform 노드에서:
사용자 {{sys.user_id}}님의 질문: {{start.query}}

관련 문서:
{% for item in knowledge_1.result %}
- {{item.content}} (점수: {{item.score}})
{% endfor %}

위 문서를 참고해 답변하세요.

🔀 고급 워크플로우 패턴

⚡ 병렬 처리 패턴
If/Else 없이 여러 노드를 동시에 실행합니다. 예: 한국어 요약 노드 + 영어 번역 노드를 동시에 → Variable Aggregator로 합치기. 처리 시간을 절반으로 단축합니다.
🔄 반복 처리 패턴
Iteration 노드로 배열 데이터를 순서대로 처리합니다. 예: 10개 문서를 하나씩 요약 → 결과 배열로 수집. Code 노드로 배열을 만들어 Iteration에 공급합니다.
🌳 분기 라우팅 패턴
Parameter Extractor로 의도 파악 → If/Else로 분기 → 각 경로별 전문 처리. 예: 기술 질문은 기술 KB, 인사 질문은 HR KB로 자동 라우팅.
🛡️ 오류 처리 패턴
노드별 오류 분기(Error Branch)를 설정합니다. API 실패 시 재시도 또는 폴백 경로로 전환. Retry 설정으로 자동 재시도 횟수와 간격 지정.

🐍 Code 노드 심화 — Python & JavaScript

python — Code 노드 실전 예시 3가지
# ── 예시 1: JSON 파싱 & 구조화 ──────────────────────
def main(raw_text: str) -> dict:
    """
    LLM이 생성한 JSON 텍스트를 안전하게 파싱합니다.
    입력: raw_text (이전 LLM 노드의 text 출력)
    """
    import json
    import re

    # JSON 블록 추출 (마크다운 코드블록 내 JSON 처리)
    json_match = re.search(r'```json\s*([\s\S]*?)\s*```', raw_text)
    if json_match:
        raw_text = json_match.group(1)

    try:
        parsed = json.loads(raw_text.strip())
        return {
            "success": True,
            "data": parsed,
            "error": ""
        }
    except json.JSONDecodeError as e:
        return {
            "success": False,
            "data": {},
            "error": str(e)
        }

# ── 예시 2: Knowledge 검색 결과 재정렬 & 포맷팅 ────
def main(knowledge_results: list, query: str) -> dict:
    """
    Knowledge Retrieval 결과를 점수순 정렬 후 포맷팅합니다.
    """
    # 점수 기준 정렬 (높은 것 우선)
    sorted_results = sorted(
        knowledge_results,
        key=lambda x: x.get('score', 0),
        reverse=True
    )

    # 마크다운 형식으로 포맷팅
    formatted = "## 관련 문서\n\n"
    for i, item in enumerate(sorted_results[:5], 1):  # 상위 5개만
        score = item.get('score', 0)
        content = item.get('content', '').strip()
        source = item.get('metadata', {}).get('source', '알 수 없음')
        formatted += f"**[{i}] {source}** (관련도: {score:.2%})\n{content}\n\n"

    return {
        "formatted_context": formatted,
        "count": len(sorted_results)
    }

# ── 예시 3: 배열 생성 (Iteration 노드 공급용) ────────
def main(file_urls: str) -> dict:
    """
    줄바꿈으로 구분된 URL 목록을 배열로 변환합니다.
    Iteration 노드에 공급하는 배열 생성.
    """
    urls = [url.strip() for url in file_urls.split('\n') if url.strip()]
    return {
        "url_list": urls,
        "total": len(urls)
    }
SECTIOND4

RAG 파이프라인 심화 — Knowledge Base 완전 최적화

Dify의 RAG 엔진은 문서 인덱싱부터 검색·리랭킹까지 완전히 내장되어 있습니다. LangChain이나 LlamaIndex 없이도 프로덕션 수준의 RAG를 구현할 수 있습니다.

📊 인덱싱 전략 3가지 완전 비교

인덱싱 방식특징토큰 비용검색 품질권장 상황
고품질 모드LLM이 각 청크를 분석해 Q&A 쌍 생성. 의미 기반 임베딩높음 $$🟢 최고중요 문서, 정확도 최우선
경제 모드임베딩 모델만 사용. LLM 호출 없음낮음 $🟡 중간대량 문서, 비용 절감
부모-자식 청킹큰 청크(부모)와 작은 청크(자식)를 동시 저장. 정밀 검색 + 맥락 보존중간 $$🟢 높음긴 법률/기술 문서

✂️ 청킹 전략 심화 설정

text — 문서 유형별 최적 청킹 설정 가이드
# ── 기술 문서 / API 매뉴얼 ───────────────────────────
청크 크기:   300~500 토큰  (짧고 정확한 기술 내용)
청크 오버랩: 50 토큰       (최소한의 중복)
구분자:      \n\n (단락 기준)
권장 임베딩: text-embedding-3-small (빠름)

# ── 법률 / 계약 문서 ──────────────────────────────────
청크 크기:   1000~1500 토큰 (조항 단위로 충분한 맥락)
청크 오버랩: 150 토큰
구분자:      제N조, 제N항, \n\n
권장 임베딩: BAAI/bge-m3 (한국어 법률 문서)

# ── 사내 FAQ / Q&A 문서 ───────────────────────────────
청크 크기:   200~400 토큰  (질문-답변 쌍이 하나의 청크)
청크 오버랩: 30 토큰
구분자:      Q:, 질문:, ##
권장 임베딩: BAAI/bge-m3

# ── 제품 카탈로그 / 스펙 문서 ────────────────────────
청크 크기:   400~800 토큰
청크 오버랩: 80 토큰
전처리:      표를 마크다운으로 변환 후 인덱싱 권장

# ── 공통 권장 설정 ────────────────────────────────────
• 하이브리드 검색 ON  (BM25 + 벡터 결합)
• 리랭킹 모델: BAAI/bge-reranker-v2-m3
• Top K: 5~8 (많을수록 맥락↑ 비용↑)
• Score Threshold: 0.3~0.5
• Summary Index: ON (긴 문서에서 관련 청크 발견 향상)

🔍 하이브리드 검색 & 리랭킹 완전 설정

검색 방식원리강점약점
Vector Only임베딩 유사도의미 이해. “빠른 차”→”스포츠카” 검색정확한 키워드 매칭 약함
Full-text (BM25)TF-IDF 키워드정확한 용어 매칭. 코드·고유명사의미 이해 없음
Hybrid (권장)Vector + BM25 결합의미 + 키워드 모두. 최고 재현율약간 느림
Reranking (추가)크로스 인코더로 재정렬최종 정밀도 20~40% 향상처리 시간 증가

🏷️ Metadata 필터 — 접근 제어 & 정밀 검색

Dify v1.1.0부터 Metadata를 청크에 붙여 검색 시 필터링이 가능합니다. 부서별 문서 접근 제어, 날짜 기반 필터, 문서 유형 분류 등에 활용합니다.

json — Metadata 설정 및 Knowledge Retrieval 노드 필터
// 문서 업로드 시 Metadata 추가 (API로 설정 가능)
{
  "document": "연봉 협상 가이드.pdf",
  "metadata": {
    "department": "HR",           // 부서 필터
    "access_level": "manager",    // 접근 레벨
    "doc_type": "policy",         // 문서 유형
    "valid_until": "2027-01-01",  // 유효 기간
    "language": "ko"              // 언어
  }
}

// Knowledge Retrieval 노드에서 Metadata 필터 적용
// 사용자가 "HR팀 소속, manager 역할"인 경우만 이 문서 검색
{
  "filters": [
    {
      "key": "department",
      "operator": "in",
      "value": ["HR", "ALL"]
    },
    {
      "key": "access_level",
      "operator": "=",
      "value": "{{start.user_role}}"  // 사용자 역할 변수 활용
    }
  ]
}

// 워크플로우에서 동적 필터 적용 예:
// Start 노드에서 user_department 변수 받기
// Knowledge Retrieval 노드에서 department = {{start.user_department}}
// 부서 전용 문서만 검색 → 데이터 격리 구현

📋 Summary Index — 긴 문서 검색 정확도 향상

Summary Index는 각 청크에 AI가 생성한 요약을 함께 저장합니다. 검색 시 요약과 원문 모두 매칭해 긴 문서에서 관련 청크를 놓치는 문제를 해결합니다. 2025년 Summer 업데이트에서 추가된 기능입니다.

text — Summary Index 활성화 방법
# Knowledge → 문서 업로드 또는 편집 → Indexing Settings

# Summary Index 활성화 시:
# 1. 각 청크 내용을 LLM이 1~2문장으로 요약 (인덱싱 시 실행)
# 2. 검색 시: 요약 텍스트 + 원본 텍스트 동시 매칭
# 3. 관련 청크가 반환될 때: 요약 + 원본 함께 전달

# 효과:
# - 긴 문서(100페이지 PDF)에서 관련 내용 발견율 30~50% 향상
# - 요약이 헤더나 제목 역할을 하여 청크 컨텍스트 보강

# 비용: 인덱싱 시 LLM 호출 추가 발생 (토큰 비용 증가)
SECTIOND5

Agent Node & 에이전트 전략 완전 구현

Agent Node는 “워크플로우 안의 두뇌”입니다. 고정된 흐름 대신 LLM이 상황을 판단해 도구를 자율 선택하고 실행합니다. 에이전트 전략(Agent Strategy)은 그 판단 방식을 정의하는 플러그인 모듈입니다.

🧠 에이전트 전략 비교

전략원리강점권장 모델
Function CallingLLM이 사전 정의된 함수 형식으로 도구 호출구조적. 예측 가능. 빠름GPT-4o, Claude, Gemini
ReActThought → Action → Observation 반복 루프복잡한 다단계 추론. 설명 가능GPT-4o, Claude Sonnet
CoT (Chain-of-Thought)단계별 사고 과정 명시. 도구 호출 전 계획정확도↑ 투명성↑o1, Claude Thinking
Custom StrategyYAML+Python으로 직접 전략 정의완전 커스터마이징. ToT, GoT 구현모델 무관
yaml — 커스텀 에이전트 전략 플러그인 구조
# 커스텀 에이전트 전략 플러그인 구조
# function_calling.yaml

parameters:
  - name: model
    type: model-selector
    scope: tool-call&llm
    label: "추론 모델"

  - name: tools
    type: array[tools]
    label: "사용 가능한 도구"

  - name: max_iterations
    type: number
    default: 5
    label: "최대 반복 횟수"
    description: "에이전트가 도구를 최대 몇 번 호출할 수 있는지"

  - name: reasoning_mode
    type: select
    options:
      - value: "standard"
        label: "표준"
      - value: "step_by_step"
        label: "단계별 (높은 정확도)"
    default: "standard"

extra:
  python:
    source: function_calling.py  # 실제 실행 로직
python — Agent Node 활용 실전 워크플로우 예시
# Agent Node 설정 예시 (Dify UI에서 설정하는 내용)

# 에이전트 전략: Function Calling
# 사용 가능한 도구:
#   - web_search (Brave Search API)
#   - calculator
#   - knowledge_search (사내 KB)
#   - code_interpreter

# 지시문 (Instruction):
"""
당신은 시장 조사 전문가입니다.
사용자가 요청한 주제에 대해 다음 단계로 조사하세요:

1. 웹 검색으로 최신 동향 파악
2. 사내 Knowledge Base에서 관련 선행 조사 확인
3. 수치 데이터가 있으면 계산기로 분석
4. 한국어로 체계적인 조사 보고서 작성

조사 결과에는 반드시:
- 핵심 통계 (출처 포함)
- 주요 플레이어 분석
- 리스크 & 기회 요인
를 포함하세요.
"""

# 쿼리 (Query):
# {{start.research_topic}} 시장에 대한 조사를 수행해줘

# 최대 반복: 10회
# 출력: 완성된 조사 보고서 텍스트

🤝 멀티에이전트 워크플로우 — 역할 분담 설계

text — 멀티에이전트 워크플로우 설계 패턴
# 패턴 1: 순차 파이프라인 (Orchestrator → Worker → Reviewer)
Start → [조사 에이전트] → [작성 에이전트] → [검토 에이전트] → End
         웹검색, KB조회     초안 작성         품질 검토, 개선

# 패턴 2: 병렬 전문가 (동시 실행)
Start → ┬→ [마케팅 에이전트] → ┐
         ├→ [기술 에이전트]   → Variable Aggregator → [통합 에이전트] → End
         └→ [재무 에이전트]   → ┘
             각자 전문 분야        결과 통합                최종 합성

# 패턴 3: 동적 라우팅 (의도 파악 후 전문가 선택)
Start → [Parameter Extractor: 의도 분류]
        → If: 기술 질문 → [기술 에이전트 (GPT-4o)]
        → If: 법률 질문 → [법률 에이전트 + 법률 KB]
        → If: 일반 질문 → [일반 에이전트 (Groq - 빠름)]
        → Variable Aggregator → End

# Dify에서 에이전트 간 데이터 전달:
# - 이전 Agent Node의 output을 다음 노드의 {{agent_1.output}}으로 참조
# - Template Transform으로 컨텍스트 조합 후 다음 에이전트에 전달
SECTIOND6

MCP 양방향 연동 — Dify를 MCP 허브로

Dify v1.6.0부터 MCP(Model Context Protocol)가 양방향으로 내장됩니다. Dify → MCP 서버 호출(MCP 클라이언트)과 Dify 워크플로우 → MCP 서버로 노출(MCP 서버) 모두 가능합니다.

📥 MCP 클라이언트 — 외부 MCP 서버를 도구로 사용

text — MCP 서버를 Dify 도구로 등록하는 방법
# Dify UI → Tools → MCP → Add Server

# 1. Linear (프로젝트 관리)
URL: https://mcp.linear.app/sse
인증: API Key (Linear Settings → API → Create Key)
→ 이슈 생성·수정·조회, 프로젝트 관리 22개 도구 추가

# 2. Notion
URL: https://mcp.notion.com/sse
인증: OAuth (Notion 연결)
→ 페이지 읽기·쓰기, 데이터베이스 쿼리

# 3. GitHub
URL: https://api.githubcopilot.com/mcp/
인증: Bearer Token (GitHub PAT)
→ 이슈, PR, 코드 검색, 저장소 관리

# 4. Zapier MCP (8,000개 앱 연결!)
URL: https://mcp.zapier.com/api/mcp/mcp  
인증: Zapier API Key
→ 단일 연결로 8,000개 서비스 도구 사용

# 5. Composio MCP (250개+ 앱)
URL: https://mcp.composio.dev/api/mcp
인증: Composio API Key
→ Salesforce, HubSpot, Jira 등 기업 도구

# 6. 홈랩 Ollama (로컬 모델을 도구로)
URL: http://192.168.1.253:11434/mcp  (MCP 지원 버전)
인증: 없음
→ 로컬 LLM을 특정 태스크 전용 도구로 활용

📤 Dify → MCP 서버 노출 — 워크플로우를 API로 공개

Dify 플러그인 마켓플레이스의 mcp-server 플러그인을 사용하면 만든 워크플로우를 MCP 서버로 노출할 수 있습니다. Claude Desktop, Cursor, Open WebUI 등 어떤 MCP 클라이언트에서도 Dify 워크플로우를 도구로 사용합니다.

text — Dify 워크플로우를 MCP 서버로 노출하는 방법
# ── 방법 1: 네이티브 mcp-server 플러그인 (권장) ──────

# 1. Dify Marketplace에서 'mcp-server' 플러그인 설치
#    (hjlarry 작성 / Marketplace에서 1-click 설치)

# 2. 노출할 앱 설정
#    Plugins → mcp-server → Configure:
{
  "apps": [
    {
      "app_id": "your-app-id",
      "app_name": "사내 문서 검색",
      "description": "사내 Knowledge Base를 검색하는 도구",
      "input_schema": {
        "query": "검색할 질문"
      }
    }
  ],
  "auth_token": "your_bearer_token"  // 선택적 인증
}

# 3. MCP 엔드포인트 확인
#    http://dify.yourcompany.com/api/mcp  (Streamable HTTP)

# ── Claude Desktop에서 사용 ─────────────────────────
# ~/Library/Application Support/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "dify-company": {
      "url": "https://dify.yourcompany.com/api/mcp",
      "headers": {
        "Authorization": "Bearer your_bearer_token"
      }
    }
  }
}

# ── Cursor에서 사용 ──────────────────────────────────
# .cursor/mcp.json
{
  "mcpServers": {
    "dify-tools": {
      "url": "https://dify.yourcompany.com/api/mcp"
    }
  }
}

# 결과: Claude나 Cursor에서 바로 Dify 워크플로우를 도구로 호출!
# "사내 문서에서 보안 정책 찾아줘" → Dify RAG 워크플로우 실행 → 결과 반환
SECTIOND7

플러그인 에코시스템 & 커스텀 Tool 개발

Dify v1.0.0부터 플러그인 아키텍처가 도입됐습니다. 모든 도구·모델 공급자가 플러그인으로 관리되며, Marketplace에서 설치하거나 직접 개발할 수 있습니다.

🛒 Dify Marketplace — 주요 플러그인 카탈로그

카테고리플러그인기능
웹 검색Brave Search, Google, Tavily실시간 웹 검색 결과
생산성Notion, Google Docs, Confluence문서 읽기·쓰기
개발GitHub, GitLab, Jira, Linear이슈·PR·코드 관리
커뮤니케이션Slack, MS Teams, Discord메시지 전송·읽기
이미지DALL-E, Stable Diffusion, Comfy이미지 생성
데이터MySQL, PostgreSQL, MongoDBDB 조회·업데이트
AI 에이전트mcp-server, Claude Max ProxyMCP 연동·모델 확장
분석Wolfram Alpha, Python Sandbox수학 계산·코드 실행

🦙 Ollama 로컬 모델 완전 연동

text — Dify에 Ollama 모델 추가 방법
# ── 방법 1: Dify 내장 Ollama 지원 ────────────────────
# Settings → Model Provider → Ollama

URL: http://host.docker.internal:11434  # Docker 내부에서 호스트 접근
# 또는 홈랩 서버:
URL: http://192.168.1.253:11434

# 모델 목록이 자동으로 불러와집니다
# qwen2.5:14b, llama3.3:70b, gemma3:12b 등 선택 사용

# ── 용도별 모델 전략 ──────────────────────────────────
# 비용 최적화를 위한 모델 라우팅:

고품질 추론 (복잡한 분석):  Claude claude-sonnet-4-5 또는 GPT-4o
빠른 분류/추출:              Groq/llama-4-scout-17b (초고속)
대용량 문서 처리:            Gemini 2.0 Flash (1M 컨텍스트)
로컬 프라이버시 요청:        Ollama/qwen2.5:14b (API 비용 0)
임베딩:                      BAAI/bge-m3 via Ollama (무료)
리랭킹:                      BAAI/bge-reranker-v2-m3 via Ollama

# ── Ollama 임베딩 모델 설정 ───────────────────────────
# Settings → Model Provider → Ollama → Embedding Models
# nomic-embed-text: 경량 (768차원)
# BAAI/bge-m3:      한국어 강력 (1024차원) ← 권장

🔧 커스텀 Tool 플러그인 개발

yaml+python — 커스텀 도구 플러그인 구조 (사내 CRM 연동)
# tools/crm_search.yaml
identity:
  name: crm_search
  author: your-company
  label: 사내 CRM 고객 검색

description:
  human: 사내 CRM에서 고객 정보를 검색합니다
  llm: Search customer information from internal CRM system

parameters:
  - name: customer_name
    type: string
    required: true
    label: 고객명
    human_description: 검색할 고객의 이름 또는 회사명
    llm_description: Customer name or company name to search

  - name: search_type
    type: select
    required: false
    default: "all"
    options:
      - value: "name"
        label: 이름 검색
      - value: "phone"
        label: 전화번호 검색
      - value: "all"
        label: 전체 검색

---
# tools/crm_search.py

import requests
from dify_plugin import Tool
from dify_plugin.entities.tool import ToolInvokeMessage


class CRMSearchTool(Tool):

    def _invoke(self, parameters: dict) -> ToolInvokeMessage:
        customer_name = parameters.get("customer_name", "")
        search_type = parameters.get("search_type", "all")

        # 사내 CRM API 호출
        api_url = self.runtime.credentials.get("crm_api_url")
        api_key = self.runtime.credentials.get("crm_api_key")

        response = requests.get(
            f"{api_url}/api/customers/search",
            params={"q": customer_name, "type": search_type},
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=10
        )

        if not response.ok:
            return self.create_text_message(f"CRM 검색 오류: {response.status_code}")

        customers = response.json().get("customers", [])
        if not customers:
            return self.create_text_message(f"'{customer_name}'에 해당하는 고객을 찾을 수 없습니다.")

        # 결과 포맷팅
        result = f"🔍 **CRM 검색 결과: {len(customers)}건**\n\n"
        for c in customers[:5]:
            result += f"**{c['name']}** ({c['company']})\n"
            result += f"  📞 {c['phone']} | 📧 {c['email']}\n"
            result += f"  마지막 연락: {c['last_contact']}\n\n"

        return self.create_text_message(result)
SECTIOND8

API 배포 & 외부 시스템 통합 — n8n · Webhook

🚀 Dify 앱을 API로 배포하기

python — Dify REST API 호출 완전 가이드
import requests DIFY_BASE_URL = “https://dify.yourcompany.com/v1” API_KEY = “app-xxxxxxxxxxxxxxxxxxxx” # 앱 → API Access → API Key # ── Chatbot (대화형) ──────────────────────────────── response = requests.post( f”{DIFY_BASE_URL}/chat-messages”, headers={“Authorization”: f”Bearer {API_KEY}”}, json={ “query”: “안녕하세요! 반품 정책이 어떻게 되나요?”, “conversation_id”: “”, # 새 대화: “” / 이어서: “conv-xxx” “user”: “user-001”, # 사용자 식별자 “response_mode”: “streaming”, # streaming | blocking “inputs”: { # 앱 정의 입력 변수 “user_type”: “premium” } }, stream=True ) # 스트리밍 응답 처리 for line in response.iter_lines(): if line: decoded = line.decode(‘utf-8’) if decoded.startswith(“data: “): import json data = json.loads(decoded[6:]) if data.get(“event”) == “message”: print(data.get(“answer”, “”), end=””, flush=True) # ── Workflow 실행 ──────────────────────────────────── response = requests.post( f”{DIFY_BASE_URL}/workflows/run”, headers={“Authorization”: f”Bearer {API_KEY}”}, json={ “inputs”: { “document_url”: “https://example.com/report.pdf”, “output_language”: “ko”, “summary_length”: “short” }, “response_mode”: “blocking”, # 완료까지 대기 “user”: “user-001” } ) result = response.json() print(result[“data”][“outputs”][“summary”]) # 워크플로우 출력 # ── File Upload → 워크플로우 실행 ─────────────────── # 1단계: 파일 업로드 with open(“report.pdf”, “rb”) as f: upload = requests.post( f”{DIFY_BASE_URL}/files/upload”, headers={“Authorization”: f”Bearer {API_KEY}”}, files={“file”: (“report.pdf”, f, “application/pdf”)}, data={“user”: “user-001”} ) file_id = upload.json()[“id”] # 2단계: 파일 ID로 워크플로우 실행 response = requests.post( f”{DIFY_BASE_URL}/workflows/run”, headers={“Authorization”: f”Bearer {API_KEY}”}, json={ “inputs”: { “document”: { “transfer_method”: “local_file”, “upload_file_id”: file_id, “type”: “document” } }, “response_mode”: “blocking”, “user”: “user-001” } )

⚡ n8n ↔ Dify 완전 양방향 연동

text — n8n + Dify 통합 시나리오 3가지
# ══ 시나리오 1: n8n → Dify (n8n이 Dify 워크플로우 실행) ══
# n8n HTTP Request 노드 설정:
# URL: https://dify.yourcompany.com/v1/workflows/run
# Method: POST
# Headers: Authorization: Bearer app-xxxxx
# Body (JSON):
{
  "inputs": {
    "email_content": "{{ $json.email.body }}",
    "sender": "{{ $json.email.from }}"
  },
  "response_mode": "blocking",
  "user": "n8n-worker"
}
# 응답에서 {{ $json.data.outputs.summary }} 로 결과 사용

# ══ 시나리오 2: Dify → n8n (Dify 워크플로우에서 n8n 웹훅 호출) ══
# Dify Workflow의 HTTP Request 노드:
# URL: http://n8n:5678/webhook/dify-complete
# Method: POST
# Body:
{
  "result": "{{llm_1.text}}",
  "workflow_id": "{{sys.workflow_run_id}}"
}

# ══ 시나리오 3: 양방향 파이프라인 ═══════════════════
# 1. Gmail에 새 이메일 도착 (n8n Gmail Trigger)
# 2. n8n → Dify: 이메일 분류 워크플로우 실행
#    → 결과: {"type": "complaint", "priority": "high", "summary": "..."}
# 3. n8n: 분류 결과에 따라 라우팅
#    → complaint + high: Slack #긴급 채널 알림
#    → general: Dify 자동 답변 워크플로우 실행
#    → spam: Gmail 스팸 처리
# 4. Dify 자동 답변: 사내 KB 검색 → 맞춤 답변 초안 생성
# 5. n8n: 답변 초안을 Google Docs에 저장 + 담당자에게 검토 요청

🌐 Embed 위젯 — 웹사이트에 챗봇 삽입

html — 웹사이트에 Dify 챗봇 위젯 삽입
<!-- Dify 앱 → Embed → 코드 복사 -->
<script>
  window.difyChatbotConfig = {
    token: 'your-app-token',
    baseUrl: 'https://dify.yourcompany.com',
    systemVariables: {
      user_id: getCurrentUserId(),        // 로그인 사용자 ID
      user_name: getCurrentUserName()     // 사용자 이름
    }
  }
</script>
<script
  src="https://dify.yourcompany.com/embed.min.js"
  id="your-app-token"
  defer>
</script>

<!-- 커스터마이징 옵션 -->
<style>
  #dify-chatbot-bubble-button {
    background-color: #1a56db !important;  /* 버튼 색상 */
  }
</style>
SECTIOND9

LLMOps — 관측 가능성 · 평가 · 최적화

📊 내장 LLMOps 대시보드

기능위치활용 방법
Logs & Monitor앱 → Logs모든 대화·워크플로우 실행 기록. 사용자 쿼리·응답·토큰·지연시간 확인
Conversation VariablesLogs → 대화 클릭각 노드의 입출력, 사용 토큰, 실행 시간 상세 추적
Annotations앱 → AnnotationsAI 응답에 올바른 답변을 직접 주석으로 달기 → Few-shot 예시로 활용
Overview앱 → Overview일별 메시지 수, 활성 사용자, 평균 세션 길이, 오류율 통계
Token UsageSettings → Billing모델별·앱별 토큰 소비량 및 비용 추정

🔬 Langfuse 통합 — 고급 관측 가능성

env — Langfuse 연동 설정 (.env)
# Langfuse 자체 호스팅 또는 클라우드
# Settings → Monitoring → Langfuse 연결

# Langfuse 클라우드 (cloud.langfuse.com)
LANGFUSE_PUBLIC_KEY=pk-lf-xxxxx
LANGFUSE_SECRET_KEY=sk-lf-xxxxx
LANGFUSE_HOST=https://cloud.langfuse.com

# Langfuse 자체 호스팅 (Docker)
LANGFUSE_HOST=http://langfuse:3000

# 연동 후 Langfuse 대시보드에서:
# - 모든 LLM 호출의 완전한 트레이스
# - 프롬프트 버전 관리
# - 모델 비용 분석
# - 품질 평가 데이터셋 구축
# - A/B 테스트 결과 비교

📝 Annotations — AI 응답 품질 개선

text — Annotations 활용 전략
# Annotations 동작 방식:
# 1. AI가 잘못된 답변을 한 경우 Logs에서 해당 대화 열기
# 2. 올바른 답변을 직접 입력 (주석 추가)
# 3. 이후 동일/유사한 질문이 오면:
#    a) 유사도 기반으로 Annotation 매칭
#    b) AI 대신 Annotation 답변을 직접 반환 (빠르고 정확)
#    c) 또는 Annotation을 Few-shot 예시로 프롬프트에 주입

# 설정:
# 앱 → Annotations → Score Threshold: 0.8 (유사도 80% 이상 매칭)
# 앱 → Annotations → Embedding Model: BAAI/bge-m3 (한국어)

# Annotation 활용 전략:
# - 반복적으로 틀리는 질문 유형부터 주석 달기
# - 회사 고유 용어·정책은 반드시 주석으로 정확한 답변 등록
# - 100~200개 Annotation으로 응답 품질 크게 향상 가능
SECTIOND10

실전 완전 구현 레시피 12선

🏢 레시피 1 — 사내 멀티 소스 RAG 검색 시스템

text — 워크플로우 설계
# 워크플로우: 사내 멀티 소스 RAG

Start (query: 사용자 질문, user_dept: 부서)
  │
  ├─→ [Parameter Extractor] — 의도·카테고리 분류
  │     출력: category (HR/기술/재무/일반)
  │
  ├─→ If category = HR
  │     └─→ [Knowledge Retrieval: HR Policy KB]
  │           Metadata Filter: department = "HR"
  │
  ├─→ If category = 기술
  │     └─→ [Knowledge Retrieval: Technical Docs KB]
  │
  ├─→ If category = 재무
  │     └─→ [Knowledge Retrieval: Finance KB]
  │           Metadata Filter: access_level = manager (부서장만)
  │
  └─→ Default: 전체 KB 검색
  │
[Variable Aggregator] — 검색 결과 통합
  │
[Template Transform] — 컨텍스트 조합
  │     시스템: 아래 문서를 참고하여 {{query}}에 답변하세요
  │     컨텍스트: {{aggregator.result}}
  │
[LLM Node: Claude Sonnet] — 최종 답변 생성
  │     temperature: 0.1 (일관성)
  │
End — answer 반환

📄 레시피 2 — 대용량 PDF 자동 분석 파이프라인

text — 워크플로우: PDF → 요약 → 인사이트 → 리포트
Start
  input: document (file), analysis_type (요약/위험분석/경쟁사분석)
  │
[Document Extractor] — PDF 텍스트 추출
  │
[Code Node: 텍스트 청크 분할]
  # 매우 긴 문서를 4000토큰 단위로 분할
  def main(full_text: str) -> dict:
      chunks = []
      words = full_text.split()
      for i in range(0, len(words), 3000):
          chunks.append(' '.join(words[i:i+3000]))
      return {"chunks": chunks}
  │
[Iteration 노드] — 청크별 병렬 처리
  │  └─→ [LLM: 청크 요약] — 각 청크의 핵심 포인트 3개
  │
[Variable Aggregator] — 모든 청크 요약 통합
  │
[LLM: Gemini 2.0 Flash] — 전체 문서 종합 분석
  │  (긴 컨텍스트 모델 활용. 1M 토큰 지원)
  │  프롬프트: analysis_type에 따른 분기 지시
  │
[LLM: 리포트 포맷팅] — 마크다운 리포트 생성
  │
End — report 반환

🤖 레시피 3 — 자율 경쟁사 모니터링 에이전트

text — Chatflow: 경쟁사 자율 조사 에이전트
Start (Chatbot 형태) │ [Agent Node — 경쟁사 조사 전문가] 에이전트 전략: ReAct (다단계 추론) 최대 반복: 15회 사용 도구: – web_search (Brave API) – http_request (회사 내부 API) – knowledge_search (기존 경쟁사 리포트 KB) – calculator (수치 계산) 지시문: “”” 당신은 경쟁사 분석 전문가입니다. 사용자가 지정한 경쟁사에 대해: 1. 최근 30일 뉴스·공식 발표 검색 2. 주요 제품 변화·가격 정책 조사 3. 기존 KB의 이전 분석과 비교 4. 변화가 우리 회사에 미치는 영향 분석 각 단계마다 출처를 명시하고 수치 비교 시 계산기 도구 활용. “”” │ [HTTP Request: Slack 전송] 분석 완료 시 #경쟁사-모니터링 채널에 자동 전송 │ End

📞 레시피 4 — AI 고객 지원 봇 (에스컬레이션 포함)

text — Chatflow: 고객 지원 봇 완전 설계
Start (Chatflow — 대화형)
  사용자 입력 → sys.query
  │
[Parameter Extractor] — 의도 분류
  출력:
    - intent: 배송조회 | 환불 | 기술문제 | 불만 | 기타
    - sentiment: positive | neutral | negative | angry
    - urgency: low | medium | high
  │
[If/Else: sentiment = angry 또는 urgency = high]
  │
  ├─→ True: [HTTP Request → CRM 에스컬레이션]
  │          담당자 배정 + Slack 긴급 알림
  │          [LLM: 공감 메시지] → 사람이 곧 연락할 것임을 안내
  │
  └─→ False: [If intent = 배송조회]
                  └─→ [HTTP Request: 물류 API 조회]
                       주문번호로 배송 상태 조회
                  [LLM: 배송 현황 안내]
             [If intent = 환불]
                  └─→ [Knowledge: 환불 정책 KB]
                  [LLM: 정책 기반 안내]
             [Default]
                  └─→ [Knowledge: 전체 FAQ KB]
                  [LLM: 답변 생성]
  │
[If/Else: 해결 여부 확인]
  LLM이 "해결됐습니다" 판단 시 → Annotation 저장
  미해결 시 → 다음 라운드 대화 계속

End (Chatflow는 대화 지속)

📊 레시피 5 — 자동 BI 리포트 생성기

text — 워크플로우: 데이터 분석 → 자연어 리포트
Start input: report_type (주간/월간), date_range, department │ [HTTP Request: 데이터 웨어하우스 API] GET /api/metrics?type={{report_type}}&dept={{department}} → JSON 데이터: 매출, 사용자, 전환율, 비용 등 │ [Code Node: 데이터 전처리 & 통계 계산] # Python으로 증감률, 이상치, 트렌드 계산 def main(raw_data: dict) -> dict: import statistics metrics = raw_data[‘metrics’] analysis = { ‘revenue_growth’: …, ‘top_products’: …, ‘anomalies’: […], ‘trend_direction’: … } return {“analysis”: analysis} │ [병렬 처리] ├─→ [LLM: 트렌드 분석] (GPT-4o — 정확한 분석) ├─→ [LLM: 위험 요소] (Claude — 세밀한 리스크) └─→ [LLM: 추천 액션] (Gemini — 전략적 제안) │ [Variable Aggregator] — 분석 통합 │ [LLM: 최종 리포트 작성] (GPT-4o) 프롬프트: 마크다운 형식, 임원용 요약, 팀별 액션 아이템 │ [HTTP Request: Notion에 페이지 생성] [HTTP Request: 이메일 발송 (n8n 웹훅 트리거)] End — report_url 반환
🎯 Dify 전문가 심화편 핵심 요약
  • 4가지 앱 유형 — Chatbot·Text Generator·Agent·Workflow를 상황에 맞게 선택
  • 15종 워크플로우 노드 — LLM·Knowledge·If/Else·Code·HTTP·Iterator·Agent 완전 활용
  • RAG 최적화 — 인덱싱 전략·청킹·하이브리드 검색·리랭킹·Metadata 필터
  • MCP 양방향 — 외부 MCP 서버를 도구로·Dify 워크플로우를 MCP 서버로 노출
  • 플러그인 생태계 — Marketplace 50+ 플러그인·커스텀 Tool 개발·Ollama 로컬 연동
  • n8n 통합 — 양방향 API 연동으로 AI(Dify) + 자동화(n8n) 최강 조합
  • LLMOps — Logs·Annotations·Langfuse로 프로덕션 품질 지속 개선

🎉 Dify 전문가 심화편 완독 완료! 비주얼 워크플로우로 시작해 프로덕션 수준의 AI 앱을 빠르게 구축하고, MCP로 AI 생태계와 연결하며, LLMOps로 지속적으로 개선합니다. Dify + n8n + Ollama 조합으로 완전한 자체 AI 인프라를 완성하세요.

Leave a reply

Please enter your comment!
Please enter your name here