brunch

B. Dify 내부 구조 및 Dify 환경변수

Dify(디파이) 노코드 AI구축 기초부터 실무 가이드

by AI개발자
dify-기초부터-실무가이드-top.jpg

(1) Dify의 내부구조

앞에서 Docker 컨테이너를 실행해 보았습니다. 실행되는 것을 확인했다면 하나의 명령어로 여러개의 컨테이너가 실행되어, 쇼핑센터 안에 상점들이 한껍번에 문을 연듯한 느낌으로 데이터베이스, API, 웹서버등 각각이 제 역할을 하며 동작하기 시작합니다. 이때 사용했던 명령어를 다시한번 기억해봅시다.

dify-0004 (1)-8.png

겉으로 보면 간단해 보이는 명령어이지만 실제로 정교한 설계가 포함되어 있습니다. 그 설계가 바로 "docker-compose.yaml"파일입니다. 이 파일을 설명하다보면, Dify(디파이)라는 시스템 구조를 알게 될 것입니다.


① docker-compose.yaml 파일 확인하기

이 파일은 Dify(디파이)라는 애플리케이션의 설계도이면서 동시에 조립설명서입니다. 처음에는 복잡해 보일 수 있지만 조금씩 살펴보면 쉽게 이해가 됩니다.

이 파일 안의 내용중 'services:'라는 부분 아래에 나열되어 있는 것이 Dify((디파이)를 구성하는 개별 컨테이너입니다.

dify-0006 (1).png /dify/docker/docker-compose.yaml

중요한 것을 설명하기 위해, 최소한의 내용으로 아래와 같이 정리했습니다.

api, worker, web, postgres, redis, ....등을 바로 앞서 실행한 여러가지 컨테이너들의 정체입니다. 각각 Dify(디파이)라는 거대한 기계속의 중요한 톱니바퀴와 같습니다.


예를 들어, api는 외부환경과 Dify(디파이) 내부를 연결하는 통역하는 같은 역할을 합니다. web은 사용자가 직접 접하는 부분 즉, Dify의 얼굴과도 같습니다. postgres는 데이터를 보관하는 창고, redis는 빠르게 동작하는 일시적인 기억장치라고 기억하면 편리합니다.

그리고 각각의 구성안에 image:라는 행은 어떤 Docker이미지를 사용할지 지정하는 것입니다. Docker이미지는 요리에 비유하지면 재료와 같은 것입니다. 예를 들어, 'langgenius/dify-api:latest'라고 적혀 있는데 이는 '최신 Dify API이미지를 사용해라!'라는 의미입니다.

dify-0006 (1)-1.png

이 파일을 읽어보면 'docker compose up -d' 명령어가 무엇을 하는지 조금씩 파악할 수 있을 것입니다. 이 명령어는 'docker-compose.yaml'파일을 읽어서 그 안에 기재된 대로 컨테이너를 실행하는 것입니다. 다음은 각 서비스(컨테이너)의 상세 설정을 살펴봅시다. 환경변수나 포트번호 설정등 약간 복잡한 부분도 있지만 천천히 하나씩 살펴보길 권장합니다.


② 각종 컨테이너의 상세내용

각 서비스의 설정을 자세히 살펴보면 더 재미있는 것들을 알 수 있습니다.


API 서비스

우선 시스템의 중추를 담당하는 API서비스를 살펴봅시다. 이것은 Dify(디파이)의 심장ㅂ부라고 해도 될 정도로 중요한 부분입니다.

dify-0006 (1)-2.png

① image: langgenius/dify-api:1.1.3 : 어떤 Docker이미지를 사용할지 지정합니다. 이미지란, Dockerfile라는 설계도를 기반으로 만들어진 실체로 그대로 Docker상에서 실행됩니다. 사용자는 이를 Docker Hub라는 온라인 저장소에서 다운로드하면 바로 사용할 수 있습니다. 이 경우 dify-api라는 이미지를 지정하고 있습니다.

② restart: always : 이 서비스의 강인함을 나타냅니다. 어떤 문제가 발생하더라도 자동으로 재시작을 시도하는 설정입니다.

③ environment: 이 부분은 약간 특이합니다. '<<: *shared-api-worker-env' 라는 것은 '공통설정을 여기에 삽입해라'라는 의미입니다. 여러 서비스에서 동일한 설정을 사용시 유용한 방법입니다.

④ MODE: api : 'API모드로 동작하라'라고 지시하는 것입니다.

⑤ depends_on: 이 서비스가 실행되기 전에 필요한 다른 서비스를 지정합니다. 여기서는 db와 redis가 지정되어 있습니다. 즉, 데이터베이스와 Redis가 준비된 후에 실행해라'라는 의미입니다.

⑥ volumes: 이 부분은 데이터 저장위치를 지정합니다. 컨테이너 내의 '/app/api/storage'라는 위치와 실제 컴퓨터의 './volume/app/storage'라는 위치를 연결하라는 의미입니다.

⑦ networks: 이 서비스가 어느 네트워크에 연결될지를 지정합니다. 'ssrf_proxy_network'와 'default' 2가지 네트워크 모두에 연결될 수 있습니다. 마치 2개의 서로 다른 도시의 도로에 접근할 수 있는 것과 같습니다.


이렇게 하나씩 살펴보면, docker-compose.yaml파일이 Dify라는 거대한 기계의 설계도이자 동시에 실행절차서임을 다시한번 알 수 있습니다. 'docket compose up -d'명령어는 이 설계도를 읽어 그에 따라 기계를 조립하고 실행시키는 것입니다.


③ 웹서비스 확인하기

다음은 사용자 인터페이스를 담당하는 웹서비스입니다.

dify-0006 (1)-3.png

다음으로 주목할 부분은 environment: 부분입니다. ${CONSOLE_API_URL:-}와 같은 표기는 '환경변수 CONSOLE_API_URL값을 사용합니다. 만약 설정되어 있지 않으면 빈문자열로 처리해라'라는 의미입니다.

이는 고객주문을 받으면서 주문이 없을 경우에 기본메뉴도 준비해놓는 것과 같습니다. CONSOLE_API_URL이나 APP_API_URL은 웹애플리케이션이 API서버와 통싱하기 위한 엔드포인트를 지정합니다. 이들 값을 설정함으로써 웹과 API가 올바르게 연계될 수 있습니다.


worker 서비스의 역할

worker라는 서비스를 살펴봅시다. 자세히 보면 api서비스와 거의 비슷해 보이지않습니까? 실제로 이 worker서비스는 api서비스와 거의 동일한 설정을 사용합니다. 단, 유일하게 다른 점으 MODE: worker라는 부분입니다.

재미있는 매커니즘으로 동일한 Docker이미지를 사용하면서 서로 다른 역할을 부여하고 있는 것입니다. 만약, api서비가 고객주문을 받는 점원이라면 worker서비스는 백그라운드에서 서용히 요리를 만드는 요리사와 같습니다. 그리고 이 두 서비스가 협력하여 작동함으로써 Dify는 고속으로 효율적인 처리를 구현하고 있습니다.


dify-0006 (1)-4.png



④ Dify의 기억장치 이해하기

시스템에는 다양한 종류의 기억이 필요합니다. Dify는 2종류 기억장치를 구분하여 효율적인 데이터관리를 구현하고 있습니다. 중요한 역할을 하는 것은 dbd와 redis입니다.


PostgreSQL 장기기억장치

우선 핵심 데이터베이스 역할을 하는 PostgreSQL의 설정을 살펴봅시다.

dify-0006 (1)-5.png

postgre는 PostgreSQL은 매우 유명한 관계형 데이터베이스 관리 시스템(RDBMS)입니다. 관계형 데이터베이스는 우선 표와 같은 것을 상상해 봅시다. 예를 들어, "사용자"라는 표가 있고, 그 안에 "이름", "니이", 주소"등의 열이 있습니다. Dify(다피아)는 이 PostgreSQL을 사용하여 다양한 정보를 정리합니다. 재미있는 것은

command: 부분입니다. 이는 데이터베이스를 기동하는 명령어 자체이며, 동시에 다양한 파라미터로 성능을 조정합니다. 예를 들어, max_connections는 동시에 몇명의 사용자가 데이테베이스를 사용할 수 있는지, shared_buffers는 데이터베이스가 사용할 수 있는 메모리양, work_mem은 복잡한 작업을 수행할 대 사용할 수 있는 메모리양을 결정합니다. 이것은 도서관을 운영을 조정하는 것과 같습니다. 동시에 몇명까지 입장할 수 있는지, 책장크기는 어느정도인지, 한사람이 사용할 수 있는 열람공간 크기는 얼마인지와 같은 방식입니다.

그리고 volumes: 부분은 데이터가 저장되는 위치를 지정합니다. 즉, Dify의 메모리를 실제로 어디에 저장할지를 결정하는 것입니다. 더 나아가 healthcheck:부분은 정기적으로 데이터베이스가 정상적으로 작동하는지 확인하는 역할을 합니다. 이는 도서관의 책이 올바르게 정렬되어 있는지 주기적으로 점검하는 것과 같습니다.

Dify는 다양한 설정과 여러가지 용도로 PostgreSQL을 사용하고 있습니다. 주의할 점은 데이터베이스 보안을 위해 독자가 설정에 익숙해지면 POSTGRES_PASSWORD등의 기본비밀번호를 변경하는 것을 추천합니다.


redis (단기 기억장치)

그리고 또 한가지 중요한 기억장치가 있습니다. 그것은 redis입니다.

dify-0006 (1)-6.png

Redis는 빠른 키-값 저장소(Key-Value Store)라고 불리는 데이터베이스입니다. 만약, PostgreSQL이 도서관이라면, Redis는 메모리와 같은 역할입니다. 필요한 정보를 순식간에 적어두고, 즉시, 꺼낼 수 있는 형태입니다. Dify(디파이)에서는 실행중인 애플리케이션의 임시 데이터를 유지하거나 백그라운드에서 동작하는 여러 서비스들을 연결하기 위한 ID(세션)등 정보를 저장하는데 사용됩니다.


command: 부분에서느 redis서버를 실행하고 '--requirepass'옵션으로 비밀번호를 설정하고 있습니다. 이는 메모지에 비밀번호를 걸어두고 중요한 정보를 쉽게 볼 수 없도록 보호하는 것과 같습니다. 이렇게 살펴보면, Dify(디파이)의 기억체제가 조금은 이해가 되었을 것입니다. 인간의 기억시스템과 비슷하게 장기기억(PostgreSQL)과 단기기억(Redis)을 구분하여 효율적으로 정보를 관리하고 있습니다.


⑤ weaviate

이제 Dify의 2가지 저장 메커니즘 외에도 약간 특수 저장 메커니즘인 RAG를 다루는 부분을 살펴보겠습니다. 그것이 weaviate입니다.

dify-0006 (1)-7.png

weaviate는 나중에 설명하는 벡터데이터베이스라고 불리는 특수 데이터베이스입니다. 일반 데이터베이스가 "사과", "귤"과 같은 문자열을 저장하는 반면에, 벡터데이터베이스는 "사과답게", "귤처럼"라는 단어의 의미나 특징을 수치 나열(벡터)로 저장합니다.

벡터데이터베이스는 데이터를 고차원 수치 벡터로 저장하고 유사도 검색을 빠르게 수행하기 위한 데이터베이스입니다. 이를 통해 의미적으로 유사한 데이터를 신속하게 검색할 수 있습니다. 단 주의할 점은 Dify는 RAG에서 항상 weaviate를 사용하는 것은 아닙니다. 보통 벡터검색전용 API를 사용하여 벡터검색을 수행합니다. weaviate는 경제적인 검색 옵션을 선택한 경에 사용되는 것입니다.


지금까지 Dify(디파이)의 각 컨테이너와 그 역할에 대해 설명했습니다. docker-compose.yaml파일을 분석하여 Dify가 어떻게 작동하는지를 이해할 수 있게 됩니다. 각 서비스가 서로 연계되어 하나의 거대한 기계처럼 동작한다는 것을 알 수 있습니다. 이로서 'docker compose up -d'라는 명령어의 궁금증도 알게 되었습니다. 이제 실제로 이 설정을 사용자지정을 해봅시다.



(2) 환경변수와 사용자지정

Docker(도커)를 실행시켜 Dify(디파이)를 실행합니다. 그리고 Docker컨테이너에 대해서도 살펴보았습니다. 현재 Dify(디파이)는 원본 그대로이며 아직 독자나 필자의 목적에 맞게 꾸며지지 않은 상태입니다. 이는 새 집으로 이사한 직후의 상태와 비슷합니다. 전기와 수도는 연결되어 있지만, 아직 가구배치도 결정되지 않은 상태이라고 보면 됩니다. 독자만의 라이프스타일을 만들기 위해서는 조금 더 손을 봐야 합니다.


① 설정할 수 있는 사항들

Dify를 커스터마이징할 수 있는 항목은 매우 다양합니다. 몇 가지 예를 들어봅니다.

dify-0006 (1)-8.png

위와 같은 항목들을 환경변수로 쉽게 사용자지정을 할 수있습니다.


② 환경변수

docker-compose.yaml파일을 열면 첫번째 알수없는 코드들이 나옵니다.

dify-0006 (1)-9.png

처음 이런 코드를 보면 정말로 어떤 암호체계를 보는 것과 같을 수 있습니다. 하지만 이것은 매우 단순한 규칙이 있습니다.


③ 환경변수 설명

기본구문은 다음과 같습니다.

dify-0006 (1)-10.png

이 암호같은 코드들을 한국어로 번역하면, "이 설정항목에는 환경변수의 값을 사용합니다. 그런데 환경변수가 설정되어 있지 않으면 기본값을 사용합니다"라는 의미입니다.

구체적인 예를 살펴보면 다음과 같습니다.

dify-0006 (1)-11.png

이것은 다음과 같이 동작합니다.

우선 시스템은 'LOG_LEVEL'이라는 환경변수를 찾습니다.

만약 찾으면 그 값을 사용합니다.

찾지 못하면, 기본값인 'INFO'를 사용합니다.


기본값의 패턴

환경변수에는 여러가지 종류의 기본값을 설정할 수 있습니다.


빈값: ${변수명:-}

dify-0006 (1)-12.png

이는 LOG_FILE환경변수가 없으면 빈문자열을 사용하라는 의미입니다.


문자열: ${변수명: --somevalue}

dify-0006 (1)-13.png


불런값: ${변수명:-false}

dify-0006 (1)-14.png


숫자: ${변수명:-20}

dify-0006 (1)-15.png


URL: $(변수명:-http://example.com}

dify-0006 (1)-16.png

이 메커니즘 덕분에 Dify(디파이)는,

우선 동작합니다. (기본값이 있기 때문에)

필요한 경우에만 사용자지정을 할 수 있습니다. (환경변수로 덮어쓸수 있음)

안전하게 운영할 수 있습니다. (설정오류가 있더라도 기본값으로 보호됨)


라는 균형을 실현하고 있습니다.


④ 환경변수 설정방법

환경변수 설정방법은 3가지가 있습니다. 각각 특징이 있기 때문에 상황에 맞춰 사용하길 권장합니다.


1. docker-compose.yaml 파일 직접 편집

dify-0006 (1)-17.png


장점

설정이 한눈에 파악됩니다.

변경사항이 바로 반영됩니다.

단점

Dify의 업데이트시 설정이 사라집니다.

GitHub에 공개하면 기밀정보도 노출됩니다.


2. .env파일 (추천함!)

dify-0006 (1)-18.png


장점

업데이트에 강합니다.

환경별로 설정을 분리할 수 있습니다.

기밀정보 관리가 용이합니다.

백업이 간단합니다.


3. 호스트머신의 환경변수 (일반적이지 않음)

dify-0006 (1)-19.png


장점

일시적인 변경에 편리합니다.

컨테이너 재시작이 필요없는 경우도 있습니다.

단점

컨테이너를 재시작하면 사라집니다.

시스템 전체에 영향을 미칠 가능성이 있습니다.


⑤ 환경변수의 우선순위 이해

환경변수 설정에는 우선순위가 있습니다. 이는 마치 체스판 말과 비슷합니다. 같은 설정학목에 대해 여러 곳에서 값이 정의가 되어 있는 경우, 더 '강한' 쪽의 값이 채택됩니다.


기본적인 우선순위(강한순서)

1.쉘에서 설정한 환경변수

가장 강력한 설정방법

다른 모든 설정을 덮어쓸 수 있음

예: export LOG_LEVEL=DEBUG

2. .env 파일 설정

중견급 실력

YAML기본값보다 우위임

예: .env파일내의 LOG_LEVEL=INFO

3. docker-compose.yaml 기본값

마지막 방어선

다른 설정의 없을 경우의 대비책

예: LOG_LEVEL: ${LOG_LEVEL:-WARNING}


예시

dify-0006 (1)-20.png

이 경우, 실제로 사용되는 값은 DEBUG가 됩니다. 이 우선순위 메커니즘을 잘 활용하면 유연하고 안전한 설정관리가 가능해집니다. 예를 들어, 이번 환경의 기본설정은 .env파일로 관리하면서 긴급상황에서는 쉘환경변수로 일시적으로 변경을 적용하는 방법으로 사용할 수 있습니다.


⑥ .env파일 활용

여러 환경변수 설정방법 중에서 docker-compose.yaml파일을 직접 편집하는 것이 가장 쉬운 방법일 수 있습니다. 단, 이 방법에는 문제가 있습니다. Dify(디파이)를 업데이트하면 YAML파일이 덮어쓰기가 되거나 수정해둔 내용이 원래대로 돌아가 버립니다.


이런 문제를 피하려면, .env파일을 사용하여 환경변수를 설정하는 것이 현명한 것입니다. .env파일은 보통 Git등의 버전관리 시스템에 추적되지 않기 때문에, Dify(디파이)업데이트시 덮어쓰기가 될 위험이 없습니다. 또한, .env파일은 텍스트파일이기 때문에 백업도 쉽고, 서로 다른 환경에서 설정을 이전할 때도 편리합니다.


그렇다면 중요한 .env파일은 어떻게 만들까요? 만드는 방법은 간단합니다. 설치된 docker(도커) 디렉토리를 확인합니다. .env.example이라는 파일이 있습니다. 이 파일을 .env파일로 이름을 바꿔서 복사해 넣습니다. (처음 설치할 때 cp명령어로 복사해 넣는 명령이 실행되고 있습니다.)


⑦ 커스터마이징 설정 예시

Dify 환경변수는 엄청 많지만, 처음부터 모두 이해할 필요는 없습니다. 우선 간단한 것부터 살펴봅시다.


로그 관련 설정

개발중에는 문제 원인을 조사하기 위해 상세한 로그출력이 필요합니다.

dify-0006 (1)-21.png

위와 같은 설정을 통해,

개발중에는 DEBUG모드로 상세로그를 출력하고,

이번 환경에서는 INFO나 WARNING수준의 필요한 로그만 출력하며,

로그파일이 너무 커지지 않도록 제어할 수 있습니다.


이번환경의 기본설정

이번 환경과 개발환경은 서로 다른 설정이 필요합니다. 특히 중요한 것은 디버그 관련 설정입니다. 이번환경에서는 디버그 모드를 비활성화하여 보안을 강화하고 불필요한 정보가 외부로 노출되는 것을 방지합니다.

dify-0006 (1)-22.png

파일업로드 제한

스토리지 사용량과 보안 균형을 맞추기 위한 설정입니다. 파일크기 제한을 변경할 수 있어 자주 사용됩니다.

dify-0006 (1)-23.png

이런 설정은 .env파일에 기재함으로써 Dify(디파이) 업데이트 시에도 설정이 사라지지 않고 유지됩니다. 또한, 개발환경과 이번 환경에 따라 서로 다른 .env파일을 준비하여 환경에 맞는 최적의 설정을 손쉽게 전환할 수 있습니다. 우선 이런 기본설정으로부터 점차적으로 다른 설정에도 도전해보는 것을 권장합니다.


Docker를 재시작하여 설정을 반영하기

.env파일에서 환경변수 설정을 완료한 후에는 해당 설정을 반영해야 합니다. 우선 컨테이너를 중지합니다.

dify-0006 (1)-24.png

정상적으로 중지되면 재시작합니다.

dify-0006 (1)-25.png

오류가 없이 실행되면 설정이 반영된 것입니다. 오류가 발생할 경우에는 로그파일을 확인하고 대처해야 합니다.


⑧ 트러블슈팅

환경변수와 관련된 일반적인 문제와 그 해경방법에 대한 것들입니다.


1.설정이 반영되지 않는 경우

Docker컨테이너를 재시작하였는지 확인합니다.

.env 파일 위치가 올바른지 확인합니다.

구문오류가 없는지 확인합니다.

2. 기밀정보 유출 발지

.env 파일을 Gitignore에 추가합니다.

정기적으로 보안검사를 실시합니다.


⑨ 정리

환경변수 설정은 Dify(디파이)를 Docker(도커)로 실행하는데 있어서 중요한 지식입니다. 이번에 배운 것을 활용하면,


개발환경과 사용환경을 구분하여 사용할 수 있고,

안정한 설정관리가 가능하며,

성능튜닝을 할 수 있고,

트러블슈팅등과 같은 고급운영이 가능합니다.


물론 독자가 아직 Docker 세부사항을 완벽히 이해하지 못해도 문제는 없습니다. 환경변수 설정을 통해 Docker세계에 첫발을 내디딘 것 자체가 큰 의미가 있습니다. 생각해보면, 지금 Dify(디파이)라는 복잡한 애플리케이션을 Docker(도커)로 실행하고 더나아가 그 동작을 사용자지정할 수 있게 된 것입니다. 지금 이해가 다 안되더라도, 이것을 시작으로 Docker(도커)를 한단계 더 학습한다면 Dify(디파이)의 고급운영도 자유자재로 다룰수 있게 될 것입니다.


관련 URL: https://docs.dify.ai/getting-started/install-self-hosted/environments



©2024-2025 GAEBAL AI, Hand-crafted & made with Damon Jaewoo Kim.

GAEBAL AI 개발사: https://gaebalai.com

AI 강의 및 개발, 컨설팅 문의: https://talk.naver.com/ct/w5umt5

AI 강의 및 개발, 컨설팅 문의: https://talk.naver.com/ct/w5umt5

keyword
작가의 이전글A. Docker 사용해서 설치하기