Community코딩 & 개발github.com

SystemTce/dify-skills

Dify 워크플로 및 플러그인 성능 최적화 종합 가이드

dify-skills란 무엇인가요?

이 스킬은 Dify 워크플로와 플러그인의 성능을 최적화하기 위한 포괄적인 가이드를 제공합니다. 그래프 구조 최적화, LLM 비용 제어, Worker 풀 튜닝, 변수 풀 최적화, 병렬 처리 및 성능 모니터링과 같은 핵심 주제를 다룹니다. v0.8.0+의 병렬 브랜치 기능을 활용하여 실행 시간을 40-60% 단축하고, LLM 캐싱을 통해 API 호출을 30-50% 줄이는 등 정량화 가능한 최적화 효과를 제공합니다. 또한 N+1 쿼리 문제, 대규모 노드 렌더링, 로그 삭제, TiDB 통합, Higress 게이트웨이 고가용성 배포 등 5가지 실제 사례를 통해 최적화 전후를 비교합니다. 이 스킬은 Claude Code, Cursor, Codex 등 AI 에이전트 개발 환경에서 사용할 수 있습니다.

지원 대상✓Claude Code~Codex CLI~Cursor✓Gemini CLI
npx skills add https://github.com/SystemTce/dify-skills/tree/main/03-performance

Installed? Explore more 코딩 & 개발 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Dify 성능 최적화 SKILL

개요

본 SKILL은 Dify 워크플로와 플러그인의 포괄적인 성능 최적화 가이드를 제공하며, 그래프 구조 최적화, LLM 비용 제어, Worker 풀 튜닝, 변수 풀 최적화, 병렬 처리 및 성능 모니터링과 같은 핵심 주제를 다룹니다.

적용 시나리오

다음과 같은 상황에서 이 SKILL을 사용해야 합니다:

  • ⏱️ 워크플로 실행 시간이 너무 길어 성능 최적화가 필요할 때
  • 💰 LLM API 비용이 너무 높아 토큰 소모를 줄여야 할 때
  • 🚀 동시 처리 능력이 부족하여 처리량을 늘려야 할 때
  • 📊 시스템 리소스 활용률이 낮아 구성을 최적화해야 할 때
  • 📈 대규모 데이터 처리 성능 병목 현상이 발생할 때
  • 🔍 성능 진단 및 모니터링이 필요할 때

핵심 가치

  • 정량화 가능한 최적화 효과: 병렬 브랜치 실행으로 40-60% 시간 단축, LLM 캐시로 30-50% 호출 감소
  • 실전 사례 기반: 최적화 전후 비교가 포함된 5가지 실제 최적화 사례
  • 포괄적인 최적화 전략: 워크플로, LLM, 플러그인, 모니터링 등 모든 계층을 포괄
  • 신속한 진단 도구: 5가지 차원의 성능 진단 체크리스트

빠른 진단 체크리스트

최적화를 시작하기 전에 다음 체크리스트를 사용하여 성능 문제를 신속히 찾아내십시오:

📊 그래프 구조 진단

  • 직렬 종속성이 너무 많지 않은가요?
  • 병렬 브랜치를 사용할 수 있나요? (v0.8.0+)
  • 불필요한 노드와 연결이 있나요?
  • 노드 수가 50개를 초과하나요?
  • 적절한 디자인 패턴을 사용하고 있나요?

🤖 LLM 사용 진단

  • 모델 선택이 적절한가요? (가벼운 작업에는 가벼운 모델)
  • 프롬프트가 너무 길지 않나요? (간결하게 할 수 있나요?)
  • LLM 응답 캐시를 활성화했나요?
  • 구조화된 출력(JSON Schema)을 사용하고 있나요?
  • 토큰 소모가 예산 내에 있나요?

⚙️ Worker 풀 진단

  • Worker 수 구성이 합리적인가요? (2-8 스레드)
  • 큐 깊이가 너무 크지 않나요?
  • Worker 유휴 상태로 낭비되는 부분이 있나요?
  • 확장/축소 전략이 합리적인가요?

💾 변수 풀 진단

  • 변수 풀에 큰 객체를 저장하고 있나요?
  • 변수를 적시에 정리하고 있나요?
  • 복사 대신 참조를 사용하고 있나요?
  • 변수 범위가 합리적인가요?

🔄 동시 처리 진단

  • 반복자에 parallel_nums를 구성했나요?
  • 스트리밍 응답을 사용하고 있나요?
  • 비동기 작업이 적절히 구성되었나요?
  • 블로킹 작업이 있나요?

제1부: 그래프 구조 최적화

1.1 직렬 종속성 줄이기

문제: 너무 많은 직렬 종속성으로 인해 워크플로 실행 시간이 선형적으로 증가합니다.

최적화 전략:

  1. 병렬화 가능한 노드 식별: 노드 간 종속 관계를 분석하여 병렬로 실행할 수 있는 노드를 찾습니다.
  2. 병렬 브랜치 사용: Dify v0.8.0+는 병렬 브랜치 기능을 지원합니다.
  3. 워크플로 재구성: 직렬 흐름을 병렬 + 집계 패턴으로 재구성합니다.

예시:

# 최적화 전: 직렬 실행 (총 시간 = 3 + 2 + 4 = 9초)
Start → API호출1(3s) → API호출2(2s) → API호출3(4s) → End

# 최적화 후: 병렬 실행 (총 시간 = max(3,2,4) = 4초)
Start → [API호출1(3s), API호출2(2s), API호출3(4s)] → 변수 집계 → End

최적화 효과: 실행 시간 40-60% 감소

1.2 병렬 브랜치 기능 (v0.8.0+)

Dify v0.8.0은 여러 브랜치를 동시에 실행할 수 있는 병렬 브랜치 기능을 도입했습니다.

사용 방법:

  1. 워크플로 편집기에서 여러 브랜치를 생성합니다.
  2. 브랜치 간에 데이터 종속성이 없는지 확인합니다.
  3. 변수 수집기를 사용하여 결과를 수집합니다.

적용 시나리오:

  • 여러 HTTP Request 노드 병렬 호출
  • 여러 Tool 노드 병렬 실행
  • 지식 베이스 검색 + API 호출 병렬 처리
  • 다중 모델 병렬 추론 (모델 비교 시나리오)

구성 예시:

# 병렬 브랜치 구성
parallel_branches:
  - branch_1:
      nodes: [http_request_1, code_1]
  - branch_2:
      nodes: [http_request_2, code_2]
  - branch_3:
      nodes: [tool_1, llm_1]

1.3 불필요한 노드 방지

일반적인 문제:

  • 중복된 데이터 변환 노드
  • 불필요한 중간 변수 노드
  • 과도한 조건 판단 노드

최적화 제안:

  • 유사한 처리 로직을 병합합니다.
  • 여러 단순 노드 대신 코드 노드를 사용합니다.
  • 조건 판단 로직을 단순화합니다.

1.4 그래프 구조 디자인 패턴

작업 유형에 따라 적절한 디자인 패턴을 선택하십시오:

  1. 순차 파이프라인: Start → LLM → End (간단한 작업)
  2. 조건 분기: Start → LLM → If-Else → 다중 경로 (의사 결정 작업)
  3. 반복 처리: Start → Code → Iteration → LLM (배치 작업)
  4. 지식 검색: Start → Knowledge-Retrieval → LLM (RAG 애플리케이션)
  5. 다중 소스 집계: 여러 Tool/HTTP → Variable-Aggregator → LLM (데이터 집계)

상세 문서: workflow-optimization/graph-structure.md 참조


제2부: LLM 최적화 전략

2.1 모델 선택 전략

적절한 모델을 선택하는 것이 비용 최적화의 핵심입니다.

모델 선택 매트릭스:

작업 유형권장 모델토큰 비용적용 시나리오
간단한 분류Qwen-Turbo, Gemini Flash낮음텍스트 분류, 감정 분석
텍스트 생성GPT-3.5-turbo, Qwen-Plus중간콘텐츠 생성, 요약
복잡한 추론GPT-4, Claude Opus높음복잡한 분석, 의사 결정
로컬 배포Ollama (Llama 3, Qwen)API 비용 0개인정보 민감 시나리오

비용 비교:

  • GPT-4: $0.03/1K 토큰 (입력) + $0.06/1K 토큰 (출력)
  • GPT-3.5-turbo: $0.0015/1K 토큰 (입력) + $0.002/1K 토큰 (출력)
  • Qwen-Turbo: ¥0.0008/1K 토큰 (약 20배 비용 차이)

최적화 제안:

  • 가벼운 작업에는 가벼운 모델 사용 (Qwen/Gemini)
  • 복잡한 작업에는 강력한 모델 사용 (GPT-4/Claude)
  • 비용 절감을 위해 로컬 모델(Ollama) 고려

2.2 프롬프트 최적화 팁

프롬프트 간소화:

# 최적화 전 (150 토큰)
"""
당신은 전문 고객 지원 담당자입니다. 다음 고객 질문을 주의 깊게 읽고, 제품 지식 베이스를 기반으로
상세하고 정확하며 친절한 답변을 제공하십시오. 답변 시 다음 사항에 유의하십시오:
1. 전문적이고 예의 바른 어조 유지
2. 구체적인 해결 방안 제공
3. 확실하지 않은 경우 설명
4. 관련 제품 문서 인용

고객 질문: {query}
"""

# 최적화 후 (50 토큰)
"""
고객 지원 담당자로서 지식 베이스를 바탕으로 고객 질문에 답변하되, 전문적이고 예의 바르게 하십시오.

질문: {query}
"""

토큰 절약: 66% (150 → 50 토큰)

기타 최적화 팁:

  • 중복된 설명과 예제 제거
  • 간결한 명령어 사용
  • 반복되는 컨텍스트 방지
  • 구조화된 출력을 사용하여 파싱 비용 절감

2.3 캐시 전략

LLM 응답 캐시:

Redis를 사용하여 LLM 응답을 캐시하고 중복 호출을 방지합니다.

구현 방안:

import hashlib
import redis

# Redis 연결
r = redis.Redis(host='localhost', port=6379, db=0)

def get_llm_response_with_cache(prompt, model="gpt-3.5-turbo"):
    # 캐시 키 생성
    cache_key = f"llm:{model}:{hashlib.md5(prompt.encode()).hexdigest()}"

    # 캐시 확인
    cached = r.get(cache_key)
    if cached:
        return cached.decode('utf-8')

    # LLM 호출
    response = call_llm_api(prompt, model)

    # 캐시 저장 (TTL: 1시간)
    r.setex(cache_key, 3600, response)

    return response

캐시 전략:

  • LLM 응답 캐시: 동일한 프롬프트에 대해 캐시된 결과 반환
  • 지식 베이스 검색 캐시: 동일한 쿼리에 대해 캐시된 벡터 반환
  • 노드 결과 캐시: 동일한 노드의 중복 실행 방지

최적화 효과: API 호출 30-50% 감소

2.4 구조화된 출력

JSON Schema를 사용하여 LLM 출력 안정성을 보장하고 파싱 오류 및 재시도를 줄입니다.

구성 예시:

{
  "type": "object",
  "properties": {
    "category": {
      "type": "string",
      "enum": ["기술", "영업", "사후"]
    },
    "priority": {
      "type": "integer",
      "minimum": 1,
      "maximum": 5
    },
    "summary": {
      "type": "string",
      "maxLength": 100
    }
  },
  "required": ["category", "priority", "summary"]
}

최적화 효과:

  • 출력 토큰 수 감소
  • 파싱 오류 및 재시도 방지
  • 다운스트림 노드 처리 효율성 향상

상세 문서: llm-optimization/ 참조


제3부: Worker 풀 튜닝

3.1 동적 작업자 스레드 풀

Dify는 동적 Worker 풀을 사용하여 노드를 병렬로 실행하며, 기본 구성은 2-8개의 작업 스레드입니다.

Worker 풀 아키텍처:

GraphEngine
├── ReadyQueue (준비된 노드 큐)
├── EventQueue (이벤트 큐)
├── Dispatcher (이벤트 디스패처)
└── WorkerPool (2-8개 작업 스레드)
    ├── Worker 1
    ├── Worker 2
    ├── ...
    └── Worker N

3.2 구성 파라미터

주요 구성:

파라미터기본값설명최적화 제안
min_workers2최소 Worker 수최소 동시 요구 사항에 따라 설정
max_workers8최대 Worker 수CPU 코어 수에 따라 설정
queue_depth_threshold10확장 트리거 임계값평균 큐 깊이에 따라 조정
idle_timeout60sWorker 유휴 시간 초과작업 빈도에 따라 조정

확장/축소 전략:

# 확장 조건
if queue_depth > queue_depth_threshold and workers < max_workers:
    add_worker()

# 축소 조건
if worker_idle_time > idle_timeout and workers > min_workers:
    remove_worker()

3.3 성능 기준

테스트 시나리오: 100개 노드의 워크플로

Worker 수실행 시간처리량CPU 사용률
245초2.2 노드/초40%
425초4.0 노드/초70%
815초6.7 노드/초95%

최적화 효과: Worker 수를 2에서 8로 늘리면 처리량이 3배 향상

3.4 최적화 제안

  1. CPU 코어 수에 따라 max_workers 설정: 일반적으로 CPU 코어 수의 1-2배로 설정합니다.
  2. 큐 깊이 모니터링: 큐 깊이가 지속적으로 높으면 max_workers를 늘립니다.
  3. 과도한 확장 방지: Worker가 너무 많으면 컨텍스트 전환 오버헤드가 발생합니다.
  4. 비동기 I/O 사용: I/O 집약적인 작업의 경우 비동기 처리를 사용하여 효율성을 높입니다.

상세 문서: workflow-optimization/parallel-execution.md 참조


제4부: 변수 풀 최적화

4.1 큰 객체 저장 방지

문제: 변수 풀에 큰 객체(예: 큰 파일, 긴 텍스트)를 저장하면 많은 메모리를 사용합니다.

최적화 전략:

# ❌ 비권장: 큰 객체 저장
variables = {
    "large_file": open("large_file.pdf", "rb").read(),  # 10MB
    "long_text": "..." * 100000  # 1MB
}

# ✅ 권장: 참조 저장
variables = {
    "file_path": "/path/to/large_file.pdf",
    "text_summary": summarize(long_text)  # 요약만 저장
}

4.2 복사 대신 참조 사용

문제: 변수 복사는 메모리 사용량과 처리 시간을 증가시킵니다.

최적화 전략:

# ❌ 비권장: 변수 복사
result = process_data(data.copy())

# ✅ 권장: 참조 사용
result = process_data(data)  # 읽기 전용 작업은 참조 사용

4.3 변수 적시 정리

문제: 더 이상 사용되지 않는 변수가 메모리를 차지합니다.

최적화 전략:

# 코드 노드에서 더 이상 사용하지 않는 변수 정리
def main(args):
    # 데이터 처리
    large_data = process_large_data(args["input"])
    result = extract_result(large_data)

    # 큰 객체 정리
    del large_data

    return {"result": result}

4.4 변수 범위 관리

변수 유형:

  • 시스템 변수: sys.query, sys.files, sys.conversation_id
  • 노드 변수: {{#node_id.output#}}
  • 환경 변수: 구성 및 키 관리
  • 반복 변수: 루프의 현재 항목 및 인덱스

최적화 제안:

  • 최소 범위 사용
  • 전역 변수 오염 방지
  • 임시 변수 적시 해제

상세 문서: workflow-optimization/variable-pool.md 참조


제5부: 병렬 처리 및 스트리밍 응답

5.1 반복자 병렬 처리

반복자의 parallel_nums 매개변수를 사용하여 배열 데이터를 병렬로 처리합니다.

구성 예시:

iteration_node:
  type: iteration
  inputs:
    items: "{{#code_node.output.items#}}"
  config:
    parallel_nums: 5  # 5개 항목 병렬 처리

성능 비교:

데이터 양직렬 처리병렬 처리 (5)향상
10개 항목20초5초4배
50개 항목100초25초4배
100개 항목200초50초4배

5.2 스트리밍 응답

스트리밍 응답을 사용하여 사용자 경험을 개선하고 첫 바이트까지의 시간(TTFB)을 줄입니다.

구현 방식:

# API 호출에서 스트리밍 응답 활성화
response = requests.post(
    "https://api.dify.ai/v1/workflows/run",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"inputs": {...}, "response_mode": "streaming"},
    stream=True
)

for line in response.iter_lines():
    if line:
        event = json.loads(line)
        print(event["data"])

최적화 효과:

  • TTFB 80% 감소
  • 사용자 인지 응답 시간 50% 감소

5.3 비동기 작업 처리

Celery를 사용하여 장기 실행 작업을 비동기적으로 처리합니다.

아키텍처:

API 서버 → Celery 큐 → Worker 풀 → 작업 실행

적용 시나리오:

  • 대용량 파일 처리
  • 일괄 데이터 가져오기
  • 장시간 API 호출
  • 예약된 작업

5.4 이벤트 기반 아키텍처 최적화

Dify는 이벤트 기반 아키텍처를 채택하여 노드 실행 시 이벤트 스트림을 생성합니다.

최적화 전략:

  • 비차단 이벤트 처리 사용
  • 이벤트 큐 일괄 처리
  • 이벤트 디스패치 로직 최적화

상세 문서: workflow-optimization/parallel-execution.md 참조


제6부: 성능 최적화 사례

사례 1: 데이터베이스 쿼리 최적화 (N+1 문제)

적용 시나리오:

  • 워크플로에서 여러 관련 데이터를 쿼리해야 하는 경우
  • 데이터베이스에 대한 반복 쿼리가 있는 경우
  • 실행 시간이 데이터 양에 따라 선형적으로 증가하는 경우

문제 특징:

  • 쿼리 횟수 = 1 + N (N은 데이터 레코드 수)
  • 데이터베이스 연결이 빈번하게 생성 및 종료됨
  • 실행 시간이 너무 김

최적화 전 상태:

# 사용자 목록 조회
users = query("SELECT * FROM users LIMIT 100")

# 각 사용자의 주문 조회 (N+1 문제)
for user in users:
    orders = query(f"SELECT * FROM orders WHERE user_id = {user.id}")
    user.orders = orders
  • 쿼리 횟수: 101회 (1 + 100)
  • 실행 시간: 10.5초
  • 데이터베이스 부하: 높음

최적화 방안:

# 모든 데이터를 한 번에 조회
users = query("SELECT * FROM users LIMIT 100")
user_ids = [user.id for user in users]

# 주문 일괄 조회
orders = query(f"SELECT * FROM orders WHERE user_id IN ({','.join(map(str, user_ids))})")

# 메모리에서 데이터 연결
orders_by_user = {}
for order in orders:
    if order.user_id not in orders_by_user:
        orders_by_user[order.user_id] = []
    orders_by_user[order.user_id].append(order)

for user in users:
    user.orders = orders_by_user.get(user.id, [])

최적화 후 효과:

  • 쿼리 횟수: 2회 (98% 감소)
  • 실행 시간: 2.1초 (80% 감소)
  • 데이터베이스 부하: 낮음

예상 이점:

  • 단기: 실행 시간 80% 감소, 데이터베이스 부하 감소
  • 장기: 더 큰 데이터 규모 지원, 시스템 확장성 향상
  • ROI: 개발 비용 2시간, 월간 서버 비용 30% 절감

사례 2: 대규모 노드 렌더링 최적화 (100+ 노드)

적용 시나리오:

  • 워크플로에 100개 이상의 노드 포함
  • 프론트엔드 렌더링 끊김
  • 편집기 응답 느림

문제 특징:

  • 페이지 로드 시간 > 5초
  • 노드 드래그 지연 현상 현저함
  • 브라우저 메모리 사용량 높음

최적화 전 상태:

  • 노드 수: 150개
  • 페이지 로드 시간: 8.5초
  • 메모리 사용량: 500MB
  • 사용자 경험: 심각한 끊김

최적화 방안:

  1. 가상 스크롤: 보이는 영역의 노드만 렌더링
  2. 노드 지연 로딩: 필요에 따라 노드 세부 정보 로드
  3. Canvas 최적화: DOM 렌더링 대신 Canvas 사용
  4. 상태 관리 최적화: 불필요한 재렌더링 감소

최적화 후 효과:

  • 페이지 로드 시간: 2.1초 (75% 감소)
  • 메모리 사용량: 150MB (70% 감소)
  • 사용자 경험: 원활함

예상 이점:

  • 단기: 사용자 경험 현저히 향상
  • 장기: 더 복잡한 워크플로 설계 지원
  • ROI: 개발 비용 1주, 사용자 만족도 40% 향상

사례 3: 워크플로 로그 삭제 성능 최적화

적용 시나리오:

  • 정기적인 이전 로그 정리 필요
  • 로그 데이터 많음 (수백만 건)
  • 삭제 작업 시간이 오래 걸림

문제 특징:

  • 삭제 작업이 데이터베이스를 차단
  • 정상 업무에 영향
  • 실행 시간 예측 불가

최적화 전 상태:

  • 로그 수: 500만 건
  • 삭제 시간: 45분
  • 데이터베이스 잠금: 장시간 테이블 잠금
  • 업무 영향: 심각

최적화 방안:

# 최적화 전: 일괄 삭제
DELETE FROM workflow_logs WHERE created_at < '2024-01-01';

# 최적화 후: 분할 삭제
batch_size = 10000
while True:
    deleted = DELETE FROM workflow_logs
              WHERE created_at < '2024-01-01'
              LIMIT batch_size;

    if deleted < batch_size:
        break

    # 짧은 대기, 데이터베이스 잠금 해제
    sleep(0.1)

최적화 후 효과:

  • 삭제 시간: 50분 (약간 증가했지만 업무 차단 없음)
  • 데이터베이스 잠금: 짧은 시간 잠금 (0.1초)
  • 업무 영향: 없음

예상 이점:

  • 단기: 업무에 영향 없음
  • 장기: 데이터베이스 안정성 향상
  • ROI: 개발 비용 4시간, 업무 중단 손실 방지

사례 4: TiDB 분산 스토리지 통합

적용 시나리오:

  • 지식 베이스 데이터 큼 (TB 단위)
  • 단일 PostgreSQL 성능 병목
  • 수평 확장 능력 필요

문제 특징:

  • 쿼리 응답 시간 > 5초
  • 데이터베이스 CPU 사용률 > 90%
  • 더 이상 확장 불가

최적화 전 상태:

  • 데이터베이스: PostgreSQL 단일
  • 데이터 양: 2TB
  • 쿼리 응답 시간: 8.5초
  • 확장 능력: 제한적

최적화 방안:

  1. TiDB로 마이그레이션: 분산 SQL 데이터베이스
  2. 벡터 인덱스 최적화: TiDB Vector를 사용하여 검색 가속화
  3. 읽기/쓰기 분리: 읽기 요청을 여러 복제본에 분산
  4. 파티션 테이블: 시간별 파티셔닝으로 쿼리 효율성 향상

최적화 후 효과:

  • 쿼리 응답 시간: 1.2초 (86% 감소)
  • 데이터베이스 CPU: 40% (50% 감소)
  • 확장 능력: 10배 데이터 규모 지원

예상 이점:

  • 단기: 쿼리 성능 현저히 향상
  • 장기: 비즈니스 급속 성장 지원
  • ROI: 마이그레이션 비용 2주, 10배 비즈니스 성장 지원

사례 5: Higress AI Gateway 고가용성 배포

적용 시나리오:

  • 프로덕션 환경에서 고가용성 필요
  • 여러 LLM 모델 부하 분산
  • 장애 조치 능력 필요

문제 특징:

  • 단일 장애점 위험
  • LLM API 호출 불안정
  • 트래픽 급증 대응 불가

최적화 전 상태:

  • 아키텍처: 단일 인스턴스 Dify
  • 가용성: 95%
  • 장애 복구 시간: 10분
  • 트래픽 피크: 대응 불가

최적화 방안:

# Higress AI Gateway 구성
apiVersion: networking.higress.io/v1
kind: McpBridge
metadata:
  name: dify-gateway
spec:
  replicas: 3  # 3개 인스턴스
  loadBalancer:
    algorithm: round-robin
  healthCheck:
    enabled: true
    interval: 10s
  failover:
    enabled: true
    maxRetries: 3

아키텍처:

사용자 요청 → Higress Gateway → [Dify 인스턴스 1, Dify 인스턴스 2, Dify 인스턴스 3]
                ↓
           부하 분산 + 장애 조치

최적화 후 효과:

  • 가용성: 99.9%
  • 장애 복구 시간: < 1초 (자동 전환)
  • 트래픽 피크: 10배 트래픽 지원

예상 이점:

  • 단기: 시스템 안정성 현저히 향상
  • 장기: 비즈니스 핵심 애플리케이션 지원
  • ROI: 배포 비용 3일, 업무 중단 손실 방지

제7부: 성능 테스트 및 모니터링

7.1 성능 지표 체계

워크플로 실행 지표:

지표목표값설명
평균 실행 시간< 2초워크플로 전체 실행 시간
P95 실행 시간< 5초95% 요청의 실행 시간
P99 실행 시간< 10초99% 요청의 실행 시간
노드 성공률> 99%노드 실행 성공 비율
API 호출 성공률> 99.5%외부 API 호출 성공률
동시 처리 능력> 100 QPS초당 처리 요청 수

리소스 사용 지표:

지표목표값설명
CPU 사용률< 70%평균 CPU 사용률
메모리 사용률< 80%평균 메모리 사용률
데이터베이스 연결 수< 80%연결 풀 사용률
Redis 메모리< 70%Redis 메모리 사용률

비용 지표:

지표목표값설명
토큰 사용 비용< 예산LLM API 비용
인프라 비용< 예산서버, 데이터베이스 비용
사용자당 비용지속적 감소단일 사용자 비용

7.2 모니터링 도구

LLMOps 모니터링:

# Dify 내장 모니터링
from dify import Monitor

monitor = Monitor()

# 워크플로 실행 기록
monitor.log_workflow_execution(
    workflow_id="xxx",
    execution_time=2.5,
    node_count=10,
    token_usage=1500,
    cost=0.003
)

# 통계 데이터 조회
stats = monitor.get_workflow_stats(
    workflow_id="xxx",
    time_range="7d"
)

실행 추적:

  • 워크플로 실행 이력
  • 노드 실행 단계 통계
  • LLM 사용 통계
  • 오류 로그 및 재시도 기록

리소스 모니터링:

# Prometheus + Grafana
# CPU, 메모리, 네트워크, 디스크 모니터링

# 예시 쿼리
rate(dify_workflow_execution_total[5m])  # 워크플로 실행 속도
histogram_quantile(0.95, dify_workflow_duration_seconds)  # P95 실행 시간

7.3 성능 테스트 방법

부하 테스트:

# Locust를 사용한 부하 테스트
from locust import HttpUser, task, between

class DifyUser(HttpUser):
    wait_time = between(1, 3)

    @task
    def run_workflow(self):
        self.client.post(
            "/v1/workflows/run",
            headers={"Authorization": f"Bearer {self.api_key}"},
            json={"inputs": {"query": "테스트 질문"}}
        )

# 테스트 실행
# locust -f load_test.py --users 100 --spawn-rate 10

스트레스 테스트:

# Apache Bench 사용
ab -n 1000 -c 50 -H "Authorization: Bearer xxx" \
   -p request.json \
   https://api.dify.ai/v1/workflows/run

벤치마크 테스트:

# 성능 벤치마크 테스트
import time

def benchmark_workflow(workflow_id, iterations=100):
    times = []
    for i in range(iterations):
        start = time.time()
        run_workflow(workflow_id)
        end = time.time()
        times.append(end - start)

    return {
        "avg": sum(times) / len(times),
        "p50": sorted(times)[len(times) // 2],
        "p95": sorted(times)[int(len(times) * 0.95)],
        "p99": sorted(times)[int(len(times) * 0.99)]
    }

7.4 성능 분석 도구

Python Profiler:

import cProfile

...

[번역을 위해 잘렸습니다]

Individual skills in this repo

This repo contains 5 individual skills — each has its own dedicated page.

관련 스킬