로컬 소스 코드로 Dify 시작하기

로컬 소스 코드로 Dify 시작하기

플랫폼을 수정하거나 디버깅해야 할 때는 소스 코드에서 서비스를 직접 띄우는 방법을 써요. Docker 이미지로 올리는 것과 달리, 백엔드·워커·웹 서비스를 각각 개발 서버로 실행하니까 코드 변경이 바로 반영돼요. 단계별로 살펴볼게요.

사전 준비

Docker와 Docker Compose 설정

Dify를 설치하기 전에 머신이 다음 최소 시스템 요구사항을 충족하는지 확인하세요.

  • CPU >= 2 Core
  • RAM >= 4 GiB
운영체제 소프트웨어 설명
macOS 10.14 이상 Docker Desktop Docker 가상 머신(VM)에 최소 2개의 가상 CPU(vCPU)와 8 GB 초기 메모리를 설정하세요. 그렇지 않으면 설치가 실패할 수 있어요. 자세한 내용은 Mac용 Docker Desktop 설치 가이드 참고.
Linux 플랫폼 Docker 19.03 이상, Docker Compose 1.25.1 이상 Docker와 Docker Compose 설치 방법은 각각 Docker 설치 가이드Docker Compose 설치 가이드 참고.
WSL 2를 활성화한 Windows Docker Desktop Linux 컨테이너에 묶이는 소스 코드와 데이터는 Windows 파일 시스템보다 Linux 파일 시스템에 두는 걸 권장해요. 자세한 내용은 WSL 2 백엔드 사용에 관한 Docker Desktop 설치 가이드 참고.

OpenAI TTS를 사용하려면 시스템에 FFmpeg가 설치돼 있어야 정상 동작해요. 자세한 내용은 이 링크를 참고하세요.

Dify 저장소 클론

git 명령으로 Dify 저장소를 클론합니다.

git clone https://github.com/langgenius/dify.git

미들웨어를 Docker Compose로 시작

Dify 백엔드 서비스에는 스토리지용 미들웨어(예: PostgreSQL / Redis / Weaviate, 로컬에 없다면)와 확장 기능(예: Dify의 sandboxplugin-daemon 서비스)이 필요해요. Docker Compose로 미들웨어를 시작하는 명령은 이렇습니다.

cd docker

cp envs/middleware.env.example middleware.env

# PostgreSQL과 Weaviate를 쓰지 않는다면 middleware.env에서 DB_TYPE 이나 COMPOSE_PROFILES 를 바꾸세요.
docker compose --env-file middleware.env -f docker-compose.middleware.yaml -p dify up -d

백엔드 서비스 설정

백엔드 서비스는 두 가지로 나뉘어요.

  1. API Service: 프론트엔드 서비스와 API 접근의 요청을 처리
  2. Worker Service: 데이터셋 처리, 워크스페이스, 청소 등 비동기 태스크를 처리

API 서비스 시작

  1. api 디렉터리로 이동합니다.
cd api
  1. 환경 변수 설정 파일을 준비합니다.
cp .env.example .env

프론트엔드와 백엔드가 서로 다른 서브도메인에서 실행될 때는 .env 파일의 COOKIE_DOMAIN을 사이트의 최상위 도메인(예: example.com)으로 설정하세요. 인증 쿠키를 공유하려면 프론트엔드와 백엔드가 같은 최상위 도메인 아래 있어야 해요.

  1. 랜덤 시크릿 키를 생성해 .env 파일의 SECRET_KEY 값을 교체합니다.
awk -v key="$(openssl rand -base64 42)" '/^SECRET_KEY=/ {sub(/=.*/, "=" key)} 1' .env > temp_env && mv temp_env .env
  1. 의존성을 설치합니다. 의존성 관리는 uv를 써요. uv로 필요한 의존성을 설치하는 명령은 다음과 같아요.
uv sync --dev

macOS라면 brew install libmagic로 libmagic을 설치하세요.

  1. 데이터베이스 마이그레이션을 최신 버전으로 수행합니다.
uv run flask db upgrade
  1. API 서비스를 시작합니다.
uv run flask run --host 0.0.0.0 --port=5001 --debug

예상 출력:

* Debug mode: on
INFO:werkzeug:WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:5001
INFO:werkzeug:Press CTRL+C to quit
INFO:werkzeug: * Restarting with stat
WARNING:werkzeug: * Debugger is active!
INFO:werkzeug: * Debugger PIN: 695-801-919

워커(Worker) 서비스 시작

데이터셋 파일 임포트나 데이터셋 문서 업데이트 같은 비동기 태스크를 큐에서 소비하려면 워커 서비스를 시작해야 해요.

  • macOS 또는 Linux
uv run celery -A app.celery worker -P gevent -c 1 --loglevel INFO -Q dataset,dataset_summary,priority_dataset,priority_pipeline,pipeline,mail,ops_trace,app_deletion,plugin,workflow_storage,conversation,workflow,schedule_poller,schedule_executor,triggered_workflow_dispatcher,trigger_refresh_executor,retention,workflow_based_app_execution

Windows 시스템이라면 대신 다음 명령을 사용하세요.

  • Windows
uv run celery -A app.celery worker -P solo --without-gossip --without-mingle --loglevel INFO -Q dataset,dataset_summary,priority_dataset,priority_pipeline,pipeline,mail,ops_trace,app_deletion,plugin,workflow_storage,conversation,workflow,schedule_poller,schedule_executor,triggered_workflow_dispatcher,trigger_refresh_executor,retention,workflow_based_app_execution

예상 출력:

-------------- [email protected] v5.4.0 (opalescent)
--- ***** -----
-- ******* ---- macOS-15.4.1-arm64-arm-64bit 2025-04-28 17:07:14
- *** --- * ---
- ** ---------- [config]
- ** ---------- .> app:         app_factory:0x1439e8590
- ** ---------- .> transport:   redis://:**@localhost:6379/1
- ** ---------- .> results:     postgresql://postgres:**@localhost:5432/dify
- *** --- * --- .> concurrency: 1 (gevent)
  -- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
  --- ***** -----
  -------------- [queues]
  .> dataset          exchange=dataset(direct) key=dataset
  .> generation       exchange=generation(direct) key=generation
  .> mail             exchange=mail(direct) key=mail
  .> ops_trace        exchange=ops_trace(direct) key=ops_trace

[tasks]
. schedule.clean_embedding_cache_task.clean_embedding_cache_task
. schedule.clean_messages.clean_messages
. schedule.clean_unused_datasets_task.clean_unused_datasets_task
. schedule.create_tidb_serverless_task.create_tidb_serverless_task
. schedule.mail_clean_document_notify_task.mail_clean_document_notify_task
. schedule.update_tidb_serverless_status_task.update_tidb_serverless_status_task
. tasks.add_document_to_index_task.add_document_to_index_task
. tasks.annotation.add_annotation_to_index_task.add_annotation_to_index_task
. tasks.annotation.batch_import_annotations_task.batch_import_annotations_task
. tasks.annotation.delete_annotation_index_task.delete_annotation_index_task
. tasks.annotation.disable_annotation_reply_task.disable_annotation_reply_task
. tasks.annotation.enable_annotation_reply_task.enable_annotation_reply_task
. tasks.annotation.update_annotation_to_index_task.update_annotation_to_index_task
. tasks.batch_clean_document_task.batch_clean_document_task
. tasks.batch_create_segment_to_index_task.batch_create_segment_to_index_task
. tasks.clean_dataset_task.clean_dataset_task
. tasks.clean_document_task.clean_document_task
. tasks.clean_notion_document_task.clean_notion_document_task
. tasks.deal_dataset_vector_index_task.deal_dataset_vector_index_task
. tasks.delete_account_task.delete_account_task
. tasks.delete_segment_from_index_task.delete_segment_from_index_task
. tasks.disable_segment_from_index_task.disable_segment_from_index_task
. tasks.disable_segments_from_index_task.disable_segments_from_index_task
. tasks.document_indexing_sync_task.document_indexing_sync_task
. tasks.document_indexing_task.document_indexing_task
. tasks.document_indexing_update_task.document_indexing_update_task
. tasks.duplicate_document_indexing_task.duplicate_document_indexing_task
. tasks.enable_segments_to_index_task.enable_segments_to_index_task
. tasks.mail_account_deletion_task.send_account_deletion_verification_code
. tasks.mail_account_deletion_task.send_account_deletion_success_task
. tasks.mail_email_code_login.send_email_code_login_mail_task
. tasks.mail_invite_member_task.send_invite_member_mail_task
. tasks.mail_reset_password_task.send_reset_password_mail_task
. tasks.ops_trace_task.process_trace_tasks
. tasks.recover_document_indexing_task.recover_document_indexing_task
. tasks.remove_app_and_related_data_task.remove_app_and_related_data_task
. tasks.remove_document_from_index_task.remove_document_from_index_task
. tasks.retry_document_indexing_task.retry_document_indexing_task
. tasks.sync_website_document_indexing_task.sync_website_document_indexing_task

2025-04-28 17:07:14,681 INFO [connection.py:22]  Connected to redis://:**@localhost:6379/1
2025-04-28 17:07:14,684 INFO [mingle.py:40]  mingle: searching for neighbors
2025-04-28 17:07:15,704 INFO [mingle.py:49]  mingle: all alone
2025-04-28 17:07:15,733 INFO [worker.py:175]  [email protected] ready.
2025-04-28 17:07:15,742 INFO [pidbox.py:111]  pidbox: Connected to redis://:**@localhost:6379/1.

Beat 서비스 시작

celery 예약 태스크를 디버깅하거나 Schedule Trigger 노드를 실행하고 싶다면, 다른 터미널에서 beat 서비스를 시작할 수 있어요.

uv run celery -A app.celery beat

웹 서비스 설정

웹 서비스는 프론트엔드 페이지를 위해 빌드되는 서비스예요.

환경 준비

웹 프론트엔드 서비스를 시작하려면 Node.js v22 (LTS)PNPM v10이 필요해요.

  • NodeJS 설치: https://nodejs.org/en/download에서 운영체제에 맞는 v18.x 이상 설치 패키지를 고르세요. 일반적인 사용에는 LTS 버전을 권장해요.
  • PNPM 설치: 설치 가이드를 따라 PNPM을 설치하거나, npm으로 pnpm을 설치하는 다음 명령을 실행해도 돼요.
npm i -g pnpm

웹 서비스 시작

  1. web 디렉터리로 이동합니다.
cd web
  1. 의존성을 설치합니다.
pnpm install --frozen-lockfile
  1. 환경 변수 설정 파일을 준비합니다. 현재 디렉터리에 .env.local 파일을 만들고 .env.example의 내용을 복사하세요. 요구사항에 맞게 환경 변수 값을 수정합니다.
# 프로덕션 릴리스에서는 PRODUCTION 으로 바꾸세요
NEXT_PUBLIC_DEPLOY_ENV=DEVELOPMENT

# 배포 에디션: SELF_HOSTED 또는 CLOUD
NEXT_PUBLIC_EDITION=SELF_HOSTED

# 콘솔 애플리케이션의 base URL. 콘솔 도메인이 api나 웹앱 도메인과 다르면 콘솔 base URL을 가리킵니다.
# example: http://cloud.dify.ai/console/api
NEXT_PUBLIC_API_PREFIX=http://localhost:5001/console/api

# 웹앱의 URL. 웹앱 도메인이 콘솔이나 api 도메인과 다르면 웹앱 base URL을 가리킵니다.
# example: http://udify.app/api
NEXT_PUBLIC_PUBLIC_API_PREFIX=http://localhost:5001/api

# 프론트엔드와 백엔드가 서로 다른 서브도메인에서 실행될 때 NEXT_PUBLIC_COOKIE_DOMAIN=1 로 설정하세요.
NEXT_PUBLIC_COOKIE_DOMAIN=

# SENTRY
NEXT_PUBLIC_SENTRY_DSN=
NEXT_PUBLIC_SENTRY_ORG=
NEXT_PUBLIC_SENTRY_PROJECT=
  1. 웹 서비스를 빌드합니다.
pnpm build
  1. 웹 서비스를 시작합니다.
pnpm start

예상 출력:

   ▲ Next.js 15
   - Local:        http://localhost:3000
   - Network:      http://0.0.0.0:3000

 ✓ Starting...
 ✓ Ready in 73ms

Dify 접속

브라우저로 http://localhost:3000에 접속하면 Dify의 모든 기능을 즐길 수 있어요. 건배! 🍻