Nextcloud Hub의 Windmill App 상세 안내서
1. Nextcloud Hub의 고급 자동화: Windmill 워크플로우 엔진
Nextcloud는 단순한 파일 동기화 및 공유 플랫폼을 넘어, 포괄적인 협업 허브로 발전해왔다. 이러한 발전의 핵심에는 강력한 자동화 기능이 있으며, 이는 ’Nextcloud Flow’라는 이름 아래 두 가지 수준으로 제공된다. 이 가이드는 그중 고급 비즈니스 프로세스 자동화를 담당하는 Windmill 엔진에 대한 심층 기술 안내서이다.
1.1 Nextcloud Flow의 이중적 의미
Nextcloud의 자동화 기능을 처음 접하는 사용자는 ’Flow’라는 용어에서 혼란을 겪을 수 있다. 이는 Nextcloud가 ’Flow’를 두 가지 다른 맥락에서 사용하기 때문이다. 하나는 모든 사용자에게 제공되는 간단하고 코드 없는(no-code) 자동화 도구이며, 다른 하나는 이 가이드의 핵심 주제인 Windmill 기반의 고급 자동화 엔진을 지칭하는 앱의 이름이다.1
-
내장 워크플로우 앱 (Built-in Workflow App): Nextcloud 설정 메뉴의 ‘Flow’ 항목에서 찾을 수 있으며, “사용자가 특정 폴더에 파일을 업로드하면 PDF로 변환하고 팀 채팅방에 알림을 보낸다“와 같은 간단한 규칙 기반 자동화를 그래픽 인터페이스를 통해 설정할 수 있다.1 이는 기술적 지식이 없는 사용자도 쉽게 반복 작업을 자동화할 수 있도록 설계되었다.
-
Windmill 기반 Flow 앱 (Windmill-based Flow App): Nextcloud 앱 스토어에서 ’Flow’라는 이름으로 설치하는 외부 앱(ExApp)으로, 강력한 오픈소스 개발자 플랫폼인 Windmill을 Nextcloud에 통합한다.3 이는 단순한 규칙 기반을 넘어, 복잡한 비즈니스 로직, 외부 서비스 연동, 인간의 승인 단계 등을 포함하는 정교한 워크플로우를 코드로 구현하기 위한 전문가용 도구이다.
이러한 용어의 이중 사용은 단순한 사용자 자동화부터 복잡한 기업 프로세스까지 포괄하는 통합된 자동화 경험을 제공하려는 마케팅 전략의 일환으로 볼 수 있다. 하지만 기술적인 관점에서 이 둘은 완전히 다른 엔진이며, 요구되는 기술 수준과 사용 목적 또한 명확히 구분된다. 이 가이드는 후자인 Windmill 기반의 ‘Flow’ 앱에 초점을 맞춰, 그 잠재력을 최대한 활용하고자 하는 시스템 관리자와 개발자를 위한 것이다.
1.2 Windmill의 역할: 스크립트 기반 자동화 엔진
Windmill은 스크립트를 API 엔드포인트, 백그라운드 작업, 예약된 잡(cron job), 그리고 워크플로우로 전환해주는 오픈소스 개발자 플랫폼이다.5 Nextcloud는 이 강력한 엔진을 통합함으로써, 단순한 협업 도구를 넘어 범용 비즈니스 애플리케이션 플랫폼으로 도약하는 발판을 마련했다.
Windmill의 핵심 개념은 다음과 같다 5:
-
스크립트 (Scripts): 자동화의 가장 작은 단위로, 특정 작업을 수행하는 코드 조각이다. Python, TypeScript, Go, Bash, SQL 등 다양한 언어를 지원하여 개발자가 가장 익숙한 도구를 사용할 수 있게 한다.5
-
플로우 (Flows / Workflows): 여러 스크립트를 유향 비순환 그래프(Directed Acyclic Graph, DAG) 형태로 연결하여 복잡한 프로세스를 모델링한다. 각 스크립트의 출력이 다음 스크립트의 입력으로 전달되며, 조건부 분기, 반복, 병렬 실행 등 정교한 제어가 가능하다.5
-
자동 생성 UI (Auto-generated UI): 모든 스크립트와 플로우는 해당 입력 매개변수를 기반으로 웹 UI를 자동으로 생성한다. 이를 통해 개발자가 아닌 사용자도 웹 양식을 통해 복잡한 백엔드 스크립트를 안전하고 쉽게 실행할 수 있다.5
Nextcloud가 Windmill을 통합한 것은 단순한 기능 추가 이상의 전략적 의미를 지닌다. Nextcloud의 핵심 가치인 ’디지털 주권(Digital Sovereignty)’은 사용자가 자신의 데이터를 완벽하게 통제하는 것을 의미한다.1 기존의 많은 자동화 솔루션이 외부 클라우드 서비스에 의존하여 데이터 주권을 침해할 소지가 있었던 반면, 자체 호스팅이 가능한 오픈소스인 Windmill을 통합함으로써 8, Nextcloud는 기업이 자체 인프라 내에서 완벽하게 통제되는 강력한 자동화 환경을 구축할 수 있는 길을 열었다. 이는 Nextcloud를 단순한 파일 저장소를 넘어, 조직의 핵심 비즈니스 프로세스를 실행하고 자동화하는 중앙 플랫폼으로 격상시키는 중요한 결정이다.
| 기능 | 내장 워크플로우 앱 (Built-in) | Windmill 기반 Flow 앱 (Advanced) |
|---|---|---|
| 대상 사용자 | 일반 사용자, 부서 관리자 | 개발자, 시스템 관리자, 프로세스 분석가 |
| 필요 기술 | 없음 (No-code) | 스크립트 작성 능력 (Low-code / Pro-code) |
| 주요 사용 사례 | 파일 태그 시 자동 변환, 특정 폴더 업로드 시 알림 | 다단계 문서 승인, 외부 API 연동, 데이터 처리 파이프라인 |
| 인터페이스 | 그래픽 기반 규칙 설정 | 그래픽 워크플로우 디자이너, 코드 에디터 |
| 통합 방식 | Nextcloud 내부 이벤트 기반 | Webhook, AppAPI, 외부 서비스 연동 |
2. 아키텍처 및 통합 메커니즘
Nextcloud와 Windmill의 통합은 여러 구성 요소가 유기적으로 상호작용하는 정교한 아키텍처를 기반으로 한다. 이 구조를 이해하는 것은 안정적인 자동화 환경을 구축하고 문제를 해결하는 데 필수적이다.
2.1 Windmill 기술 스택 분석
Windmill은 엔터프라이즈 환경에서의 높은 성능, 확장성, 그리고 보안을 목표로 설계되었으며, 이는 기술 스택 선택에 명확히 드러난다.
-
백엔드 (Rust): Windmill의 핵심 백엔드는 Rust로 작성되었다.8 Rust는 메모리 안전성을 컴파일 시점에 보장하면서 C++에 버금가는 성능을 제공하는 시스템 프로그래밍 언어다. 이 선택은 Windmill이 수많은 워크플로우를 동시에 처리할 때 발생할 수 있는 메모리 누수나 동시성 문제를 원천적으로 방지하고, 안정적이고 예측 가능한 성능을 유지하도록 보장한다.
-
프론트엔드 (Svelte): 웹 인터페이스는 Svelte로 개발되었다.8 Svelte는 가상 DOM을 사용하지 않고 코드를 효율적인 바닐라 자바스크립트로 컴파일하여 빠르고 가벼운 사용자 인터페이스를 제공한다. 이는 복잡한 워크플로우 디자이너나 데이터가 많은 대시보드에서도 부드러운 사용자 경험을 가능하게 한다.
-
데이터베이스 (PostgreSQL): 모든 워크플로우 정의, 실행 기록, 사용자 정보 등은 PostgreSQL에 저장된다.8 PostgreSQL은 안정성과 데이터 무결성으로 정평이 나 있어, 비즈니스 크리티컬한 자동화 데이터를 저장하기에 적합하다.
-
스크립트 실행 환경 (Sandboxing): Windmill의 가장 중요한 보안 기능 중 하나는 스크립트 실행의 샌드박싱이다. 사용자가 제출한 임의의 코드를 실행하는 것은 본질적으로 보안 위협을 내포한다. Windmill은 Google이 개발한
nsjail을 사용하여 각 스크립트 실행을 격리된 환경에서 수행한다.8 이는 파일 시스템 접근, 네트워크 통신, 시스템 호출 등을 엄격하게 제한하여, 악의적인 스크립트가 호스트 시스템이나 다른 워크플로우에 영향을 미치는 것을 방지한다. 이 기술은 fly.io와 같은 클라우드 제공업체에서도 멀티테넌트 환경의 보안을 위해 사용할 만큼 신뢰성이 높다.8 -
작업 처리 (Worker/Queue): Windmill은 비동기 작업 처리를 위해 워커-큐(Worker-Queue) 아키텍처를 채택했다. 실행 요청이 들어오면 작업(Job)으로 변환되어 PostgreSQL의 큐에 저장되고, 여러 워커 프로세스가 이 큐에서 작업을 가져와 독립적으로 처리한다.8 이 구조는 수평적 확장을 용이하게 하여, 작업량이 증가하면 워커 수만 늘려 전체 처리량을 높일 수 있다.
이러한 아키텍처 구성 요소들은 Windmill이 단순한 스크립트 실행기를 넘어, “비즈니스 크리티컬한 자동화“를 안정적으로 처리할 수 있는 엔터프라이즈급 플랫폼임을 증명하는 기술적 근거가 된다.5
2.2 Nextcloud 연동 방식: ExApp, AppAPI, Webhook Listeners
Nextcloud와 Windmill의 통합은 의도적으로 느슨하게 결합된(loosely coupled) 구조로 설계되었다. 이는 각 시스템의 독립적인 업데이트와 유지보수를 용이하게 하지만, 문제 발생 시 전체 통신 흐름을 이해해야만 원인을 파악할 수 있음을 의미한다.
통합의 핵심 요소는 외부 앱(ExApp), AppAPI, 그리고 Webhook Listeners 앱이다.3 전체적인 데이터 흐름은 다음과 같다.
-
이벤트 발생 (Nextcloud): 사용자가 파일을 업로드하거나, Forms를 제출하는 등 Nextcloud 내에서 특정 이벤트가 발생한다.
-
이벤트 감지 및 전송 (Webhook Listeners): 사전에 Windmill 워크플로우에 의해 설정된
webhook_listeners앱이 이 이벤트를 감지한다. 이 앱은 Nextcloud의 백그라운드 잡 시스템을 통해 실행되며, 감지된 이벤트를 지정된 Windmill 웹훅 URL로 POST 요청을 통해 전송한다.10 -
워크플로우 실행 (Windmill): Windmill은 웹훅 요청을 수신하고, 해당 URL에 매핑된 워크플로우를 시작한다. 이벤트 데이터는 워크플로우의 초기 입력값(
flow_input)으로 전달된다.3 -
역방향 통신 (AppAPI): 워크플로우 내의 스크립트들은 Nextcloud에 다시 작업을 요청해야 할 수 있다 (예: 파일 이동, Talk 메시지 전송). 이때
AppAPI를 통해 Nextcloud의 OCS(Open Collaboration Services) API를 호출한다. 이 통신은 사전에 설정된 인증 정보를 통해 안전하게 이루어진다.3
이러한 비동기적이고 분리된 구조는 각 구성 요소의 역할을 명확히 하지만, 문제 해결을 복잡하게 만든다. 예를 들어 워크플로우가 트리거되지 않는 경우, 원인은 Nextcloud의 cron 설정 문제일 수도, webhook_listeners 앱의 오류일 수도, 두 서버 간의 네트워크 방화벽 문제일 수도, 혹은 Windmill의 웹훅 수신부 문제일 수도 있다. 따라서 관리자는 이 전체적인 통신 체인을 이해하고 각 단계별로 문제를 진단할 수 있는 능력을 갖추어야 한다.
2.3 인증 리소스 (exapp_resource)와 통신
두 시스템 간의 신뢰 관계를 설정하고 통신을 원활하게 하는 핵심 요소는 u/admin/exapp_resource라는 이름의 인증 리소스다.3 이 리소스는 Flow 앱이 처음 설치될 때 자동으로 생성되며, Windmill이 Nextcloud에 다시 API를 호출할 때 필요한 정보를 담고 있다.
주요 구성 요소는 다음과 같다:
baseUrl: Windmill 스크립트가 Nextcloud 인스턴스에 도달하기 위해 사용하는 기본 URL이다.3 Nextcloud가 리버스 프록시 뒤에 있거나 복잡한 Docker 네트워크 환경에 배포된 경우, 이
baseUrl이 잘못 설정되어 통신 실패를 유발하는 경우가 많다. 관리자는 Windmill UI의 ‘Resources’ 탭에서 이 리소스를 찾아 baseUrl이 외부에서 접근 가능한 정확한 Nextcloud 주소로 설정되어 있는지 반드시 확인하고 필요시 수정해야 한다.
- 인증 정보: AppAPI를 통한 인증에 필요한 토큰 또는 자격 증명 정보가 이 리소스에 암호화되어 저장된다.
이 exapp_resource는 두 독립적인 시스템을 연결하는 다리 역할을 하므로, 초기 설정 및 문제 해결 과정에서 가장 먼저 확인해야 할 중요한 구성 요소이다.
3. 설치 및 초기 설정 가이드
Windmill 워크플로우 엔진을 Nextcloud에 성공적으로 설치하고 구성하는 것은 고급 자동화를 시작하기 위한 첫걸음이다. 권장되는 자동 설치 방법과 고급 사용자를 위한 수동 배포 방법을 모두 상세히 안내한다.
3.1 사전 요구사항
설치를 시작하기 전에, 시스템이 다음 요구사항을 충족하는지 확인해야 한다.
-
Nextcloud 서버: 안정적인 최신 버전의 Nextcloud가 설치되어 있어야 한다.
-
필수 앱 활성화: Nextcloud 관리자 계정으로 로그인하여 ‘앱’ 관리 페이지에서 다음 두 앱이 설치되고 활성화되어 있는지 확인해야 한다.
-
AppAPI: 외부 애플리케이션이 Nextcloud와 안전하게 통신할 수 있도록 하는 핵심 프레임워크다.4 -
webhook_listeners: Nextcloud 내부 이벤트를 감지하여 외부 URL(웹훅)로 전송하는 역할을 한다.4 -
서버 환경 (수동 배포 시): Docker를 사용하지 않고 수동으로 배포할 경우, Nextcloud 서버에 다음 소프트웨어가 설치되어 있어야 한다.4
-
Python 3.10 이상
-
Git
3.2 설치 방법: Flow 외부 앱 (Recommended Method: Flow External App)
대부분의 사용자에게 권장되는 가장 간단한 설치 방법은 Nextcloud 앱 스토어를 이용하는 것이다. 이 방법은 Windmill 인스턴스의 배포와 Nextcloud와의 연동 과정을 대부분 자동화한다.
-
Nextcloud에 관리자 계정으로 로그인한다.
-
우측 상단의 프로필 아이콘을 클릭하고 ’앱’으로 이동한다.
-
검색창에 “Flow“를 입력한다.
-
‘Flow: Seamless Automation for Nextcloud’ 앱을 찾아 ‘다운로드 및 활성화’ 버튼을 클릭한다.4
-
설치가 완료되면 Nextcloud의 메인 메뉴에 ‘Flow’ 아이콘이 나타난다. 이를 클릭하면 Windmill 인터페이스로 이동한다.
이 과정에서 Nextcloud의 ExApp 시스템은 백그라운드에서 Windmill을 위한 Docker 컨테이너를 배포하고 필요한 설정(예: exapp_resource 생성)을 자동으로 수행한다.
3.3 고급 설치: 수동 배포
개발 환경을 구성하거나, Kubernetes와 같은 컨테이너 오케스트레이션 환경에 배포하거나, 자동 설치 과정에서 문제가 발생했을 때 원인을 파악하고 해결하기 위해 수동 배포 방법을 사용할 수 있다. 수동 배포 과정은 자동 설치의 내부 동작을 이해하는 데 매우 유용하며, 이는 그 자체로 강력한 진단 도구가 된다.
수동 배포의 전체 과정은 nextcloud/flow GitHub 저장소에 상세히 설명되어 있으며, 주요 단계는 다음과 같다 4:
-
Deploy Daemon 등록:
AppAPI설정에서manual-install유형의 Deploy Daemon을 수동으로 등록한다. 이는 Nextcloud가 외부에서 관리되는 ExApp과 통신할 수 있도록 하는 엔드포인트 역할을 한다.4 -
Windmill 독립 설치: Windmill 공식 문서에 따라 Docker Compose 등을 이용하여 Windmill 인스턴스를 별도로 설치한다. 이때 초기 관리자 계정은
admin@windmill.dev/changeme로 유지하는 것이 좋다.4 -
Flow 저장소 복제 및 종속성 설치: Nextcloud 서버에서
nextcloud/flow저장소를 복제하고, Python 가상 환경을 생성한 뒤pip install -r requirements.txt명령으로 필요한 라이브러리를 설치한다.4 -
환경 변수 설정: 복제한
flow코드 내의ex_app/lib/main.py스크립트나 환경 변수를 통해NEXTCLOUD_URL(Nextcloud 주소)과WINDMILL_URL(독립 설치한 Windmill 주소) 등을 정확히 설정한다.4 -
프론트엔드 빌드 및 ExApp 등록:
make init및make static_frontend명령을 실행하여 Windmill의 프론트엔드 자산을 빌드한다. 그 후,python ex_app/lib/main.py로 ExApp 프록시 서버를 실행하고, 별도의 터미널에서make register를 실행하여 이 ExApp을 Nextcloud에 등록한다.4
이 복잡한 과정의 각 단계는 자동 설치 시 발생할 수 있는 잠재적인 실패 지점들이다. 예를 들어, Flow 앱 아이콘을 클릭했을 때 UI가 깨져 보인다면 5단계의 프론트엔드 빌드 과정에 문제가 있었을 가능성이 높다. 워크플로우가 Nextcloud와 통신하지 못한다면 4단계의 환경 변수 설정이 잘못되었을 수 있다. 이처럼 수동 설치 과정을 이해함으로써 관리자는 ’블랙박스’처럼 느껴지는 자동 설치의 문제를 체계적으로 진단하고 해결할 수 있다.
3.4 초기 설정
설치가 완료된 후, Windmill과 Nextcloud가 원활하게 통신하기 위해 몇 가지 중요한 초기 설정이 필요하다.
-
‘nextcloud’ 작업 공간 선택: 처음으로 Flow 앱을 통해 Windmill UI에 접속하면, 작업 공간(workspace)을 선택하는 화면이 나타난다. 여기서 반드시 미리 생성되어 있는 ‘nextcloud’ 작업 공간을 선택해야 한다.3 이 작업 공간만이 Nextcloud의 내부 이벤트 시스템과 자동으로 연동되도록 사전 구성되어 있다. 다른 작업 공간을 생성하여 사용하면 모든 웹훅을 수동으로 설정해야 하는 번거로움이 있다.
-
baseUrl확인 및 수정:II. 아키텍처 및 통합 메커니즘에서 설명했듯이, Windmill이 Nextcloud API를 호출할 때 사용하는baseUrl이 정확한지 확인해야 한다.
-
Windmill UI에서 ‘Resources’ 탭으로 이동한다.
-
u/admin/exapp_resource리소스를 찾아 ‘Edit’ 버튼을 클릭한다.3 -
baseUrl필드의 값이 외부에서 Nextcloud에 접근할 수 있는 완전한 URL(예:https://nextcloud.example.com)인지 확인하고, 다르다면 수정 후 저장한다. -
만약 DockerSocketProxy를 사용 중이라면, URL은
https://<your-nextcloud-base-url>/index.php/apps/app_api/proxy/flow와 같은 특정 형식을 따라야 한다.3
3.5 webhook_listeners 앱 상세 설정
webhook_listeners 앱은 기본적으로 Nextcloud의 cron 기반 백그라운드 잡을 통해 웹훅을 발송한다. 기본 cron 주기가 5분이므로, 이벤트 발생 후 워크플로우가 시작되기까지 최대 5분의 지연이 발생할 수 있다.10 실시간에 가까운 반응이 필요한 자동화(예: 사용자 요청에 대한 즉각적인 응답)를 위해서는 이 지연 시간이 문제가 될 수 있다.
이 문제를 해결하고 웹훅을 거의 즉시 발송하기 위해서는, 전용 백그라운드 작업 워커(worker)를 설정하는 것이 강력히 권장된다. 이는 프로덕션 환경에서는 선택이 아닌 필수적인 튜닝 과정으로 보아야 한다.
가장 안정적인 방법은 systemd 서비스를 이용하는 것이다. 다음은 systemd를 사용하여 4개의 병렬 워커를 실행하는 예시다.10
- 쉘 스크립트 생성:
/opt/nextcloud-webhook-worker/taskprocessing.sh 경로에 다음 내용의 쉘 스크립트를 생성하고 실행 권한을 부여한다 (chmod +x).
#!/bin/sh
echo "Starting Nextcloud Webhook Worker $1"
cd /path/to/nextcloud # 실제 Nextcloud 설치 경로로 변경
sudo -E -u www-data php occ background-job:worker -t 60 'OCA\WebhookListeners\BackgroundJobs\WebhookCall'
- systemd 서비스 파일 생성:
/etc/systemd/system/nextcloud-webhook-worker@.service 경로에 다음 내용의 서비스 파일을 생성한다.
[Unit]
Description=Nextcloud Webhook worker %i
After=network.target
ExecStart=/opt/nextcloud-webhook-worker/taskprocessing.sh %i
Restart=always
StartLimitInterval=60
StartLimitBurst=10
[Install]
WantedBy=multi-user.target
- 서비스 활성화 및 시작:
다음 명령을 실행하여 4개의 워커 서비스를 시스템 부팅 시 자동으로 시작하도록 활성화하고, 즉시 시작한다.
for i in {1..4}; do systemctl enable --now nextcloud-webhook-worker@$i.service; done
이제 webhook_listeners 앱은 전용 워커를 통해 이벤트를 훨씬 빠르게 처리하게 되어, 자동화 워크플로우의 반응성을 크게 향상시킬 수 있다.
4. Windmill 워크플로우 설계 및 실행
Windmill의 핵심은 그래픽 기반의 워크플로우 디자이너다. 이곳에서 스크립트들을 조합하여 복잡한 자동화 로직을 시각적으로 설계하고 실행할 수 있다. 이 섹션에서는 디자이너의 주요 기능과 Nextcloud 이벤트를 연동하는 핵심 메커니즘을 다룬다.
4.1 워크플로우 디자이너 UI
Windmill UI에서 ‘+ Flow’ 버튼을 클릭하면 워크플로우 디자이너가 열린다. 인터페이스는 크게 세 부분으로 구성된다.11
-
캔버스 (Canvas): 화면 중앙의 가장 넓은 영역으로, 워크플로우의 구조를 시각적으로 보여준다. ‘Input’ 노드에서 시작하여 ‘Result’ 노드로 끝나며, 그 사이에 여러 스크립트 노드들을 추가하고 연결하여 데이터의 흐름과 실행 순서를 정의한다.
-
설정 및 도구 패널 (Left Panel): 좌측에는 워크플로우의 전반적인 설정(이름, 설명, 권한 등), 스케줄링, 그리고 실행 중인 워크플로우의 상태와 결과(Outputs)를 확인할 수 있는 패널이 있다.
-
노드 속성 패널 (Right Panel): 캔버스에서 특정 노드(스크립트)를 선택하면 우측에 해당 노드의 상세 속성 패널이 나타난다. 이곳에서 스크립트의 입력 매개변수를 설정하고, 실행 결과를 테스트하며, 재시도 정책이나 승인 단계와 같은 고급 설정을 구성할 수 있다.
4.2 Nextcloud 이벤트 리스닝: CORE:LISTEN_TO_EVENT
Windmill 워크플로우를 Nextcloud의 특정 이벤트에 반응하도록 만드는 방법은 매우 독특하며, CORE:LISTEN_TO_EVENT라는 ’매직 스크립트’를 통해 이루어진다. 이는 일반적인 UI 설정이 아닌, 워크플로우 자체의 구조를 통해 웹훅 등록을 선언하는 방식이다.
Nextcloud 이벤트를 수신하려는 워크플로우는 반드시 다음 규칙을 따라야 한다 3:
-
워크플로우의 첫 번째 실행 노드(Input 블록 바로 다음)는 비어있는 스크립트여야 한다.
-
이 스크립트의 ‘Summary’ 필드에 정확히
CORE:LISTEN_TO_EVENT라는 문자열을 입력해야 한다. -
이 스크립트는 두 개의 정적(static) 매개변수를 가져야 한다:
events와filters.
이 규칙을 따르면, 워크플로우가 배포될 때 Windmill(Flow ExApp)은 이 정보를 읽어 Nextcloud의 webhook_listeners 앱에 해당 이벤트를 수신할 웹훅을 자동으로 등록한다.
| 파라미터 | 타입 | 설명 | 예제 |
|---|---|---|---|
events | 문자열 배열 | 수신하고자 하는 Nextcloud 이벤트의 ID 목록. 여러 이벤트를 동시에 수신할 수 있다. | `` |
filters | JSON 객체 | 이벤트를 더욱 세밀하게 필터링하기 위한 조건. MongoDB 쿼리 구문과 유사한 연산자를 지원한다. 10 | 특정 사용자의 이벤트만 수신: {"user.uid": "alice"} 특정 폴더 내 파일 이벤트만 수신: {"event.node.path": "/^\\/alice\\/files\\/Invoices\\//"} |
이 메커니즘의 강력함은 filters 파라미터에 있다. 이를 통해 불필요한 이벤트로 인해 워크플로우가 실행되는 것을 서버 단에서 방지할 수 있다. 예를 들어, 모든 파일 업로드 이벤트를 수신한 뒤 워크플로우 내에서 특정 폴더인지 확인하는 대신, 필터를 사용하여 애초에 ‘Invoices’ 폴더 내의 업로드 이벤트만 Windmill로 전송하도록 할 수 있다. 이는 시스템 자원을 효율적으로 사용하고 워크플로우 로직을 단순하게 유지하는 데 큰 도움이 된다.
4.3 데이터 흐름 제어
워크플로우의 진정한 힘은 각 단계를 연결하여 데이터를 전달하고 처리하는 데 있다. Windmill은 이를 위한 직관적인 방법을 제공한다.
-
초기 입력 데이터 접근:
CORE:LISTEN_TO_EVENT에 의해 트리거된 워크플로우의 경우, Nextcloud가 전송한 웹훅 페이로드(이벤트 데이터)는flow_input이라는 특수 변수를 통해 접근할 수 있다. 예를 들어, Forms 제출 이벤트에서 제출된 양식의 해시값은flow_input.event.form.hash와 같은 경로로 참조할 수 있다.3 -
이전 단계 결과 참조: 워크플로우의 각 스크립트 노드는 자동으로 ‘a’, ‘b’, ‘c’… 와 같은 알파벳 식별자를 부여받는다. 후속 단계에서는
results변수와 이 식별자를 조합하여 이전 단계의 실행 결과를 참조할 수 있다. 예를 들어, ‘e’ 단계에서 실행된 “Get form submission” 스크립트의 결과 중 답변 부분은results.e.submission.answers와 같이 참조할 수 있다.3
스크립트의 입력 필드 옆에 있는 플러그 모양 아이콘을 클릭하면, 사용 가능한 flow_input 및 results 변수 목록이 시각적으로 표시되어 쉽게 선택하고 연결할 수 있다.
4.4 고급 워크플로우 패턴
Windmill은 단순한 순차 실행을 넘어 복잡한 비즈니스 프로세스를 모델링하기 위한 고급 제어 구조를 지원한다.
-
승인 단계 (Approval Steps): 워크플로우 실행을 일시 중단하고 사람의 개입을 기다리게 할 수 있다. 이는 휴가 신청, 비용 지출, 문서 배포 등 인간의 승인이 반드시 필요한 프로세스를 자동화하는 데 핵심적인 기능이다.3
-
설정 방법: 승인이 필요한 스크립트 노드를 선택하고, 우측 속성 패널의 ‘Advanced’ 탭 > ‘Suspend’ 하위 탭에서 ‘Suspend/Approval/Prompt’ 옵션을 활성화한다.3
-
동작 방식: 이 단계가 실행되면 워크플로우는 ‘suspended’ 상태가 되고, 고유한 ‘resume’ 및 ‘abort’ 웹훅 URL을 생성한다. 승인 담당자가 이 URL 중 하나를 호출(예: 링크 클릭)하면 워크플로우는 해당 분기로 계속 진행된다.
-
사용자 경험: Windmill이 제공하는 기본 승인 UI는 기술적인 정보를 많이 담고 있어 일반 사용자에게는 적합하지 않다. 대신, Nextcloud의
approve_links앱을 사용하면 사용자 정의 메시지와 ‘승인’/‘거부’ 버튼이 있는 깔끔한 임시 승인 페이지를 생성할 수 있다.3 워크플로우에서는
approve_links 앱의 링크를 생성하는 스크립트를 호출하고, 그 링크를 Nextcloud Talk 메시지나 알림을 통해 승인자에게 전달하는 방식으로 구현하는 것이 좋다.
- 루프 및 분기 (Loops and Branches): Windmill은
for루프,while루프, 그리고 조건에 따라 실행 경로를 나누는 분기(branch)를 지원한다.13 이를 통해 배열의 각 항목에 대해 동일한 작업을 반복하거나, 특정 조건이 충족될 때까지 작업을 계속하거나, 이전 단계의 결과값에 따라 다른 후속 조치를 취하는 등 정교한 로직을 구현할 수 있다.
5. Nextcloud 연동 스크립트 개발
Windmill의 진정한 잠재력은 사전 제작된 스크립트를 활용하고, 필요에 따라 직접 스크립트를 개발하여 자동화의 범위를 무한히 확장하는 데 있다. 이 섹션에서는 Windmill Hub의 스크립트를 활용하는 방법과 Nextcloud OCS API를 직접 호출하는 사용자 정의 스크립트를 작성하는 방법을 다룬다.
5.1 Windmill Hub 스크립트 활용
가장 빠르고 효율적으로 워크플로우를 구축하는 방법은 Windmill 커뮤니티와 Nextcloud 팀이 미리 만들어 공유한 스크립트를 활용하는 것이다. Windmill Hub는 이러한 재사용 가능한 스크립트들의 중앙 저장소 역할을 한다.
-
스크립트 검색 및 사용: 워크플로우 디자이너에서 노드를 추가할 때, ‘Hub’ 탭을 선택하고 ’nextcloud’를 검색하면 Nextcloud와 관련된 다양한 스크립트 목록을 찾을 수 있다.3 예를 들어 다음과 같은 스크립트들이 제공된다:
-
Nextcloud Talk: Send a message: 지정된 Talk 대화방에 메시지를 보낸다. -
Nextcloud Tables: Create a row in a table: Tables 앱의 특정 테이블에 새로운 행을 추가한다. -
Nextcloud WebDAV: Upload or update a file: WebDAV를 통해 파일을 업로드하거나 내용을 수정한다. -
Nextcloud Calendar: Create a calendar event: 캘린더에 새로운 일정을 생성한다. -
Get a form submission from Nextcloud Forms: Forms 앱으로 제출된 데이터의 상세 내용을 가져온다. -
인스턴스 동기화: Windmill Hub에 새로운 Nextcloud 스크립트가 추가되거나 업데이트될 수 있다. 로컬 Windmill 인스턴스를 최신 상태로 유지하려면, Windmill의 ‘admin’ 작업 공간에서 “Synchronize Hub Resource types with instance“라는 이름의 플로우를 실행하면 된다.3
5.2 사용자 정의 스크립트 작성
Windmill Hub에 원하는 기능의 스크립트가 없는 경우, Nextcloud의 OCS API를 직접 호출하는 자신만의 스크립트를 작성할 수 있다.3 Windmill은 Python, TypeScript, Go 등 다양한 언어를 지원하지만, 여기서는 Python을 예로 들어 설명한다.
다음은 특정 사용자에게 Nextcloud 알림을 보내는 간단한 사용자 정의 스크립트의 보일러플레이트 코드다.
import wmill
from typing import TypedDict
# AppAPI 인증을 위한 기본 타입을 정의한다.
class NextcloudResource(TypedDict):
baseUrl: str
headers: dict
def main(nextcloud_resource: NextcloudResource, user_id: str, subject: str, message: str):
""" 지정된 사용자에게 Nextcloud 알림을 보낸다. """
# OCS API 엔드포인트 경로
# https://docs.nextcloud.com/server/latest/developer_manual/client_apis/OCS/ocs-api-overview.html
endpoint = f"/ocs/v2.php/apps/notifications/api/v2/notifications"
# POST 요청에 필요한 데이터 본문
payload = {
"userId": user_id,
"subject": subject,
"message": message
}
# wmill.fetch를 사용하여 Nextcloud API를 호출한다.
# nextcloud_resource에 baseUrl과 인증 헤더가 포함되어 있다.
response = wmill.fetch(
url=nextcloud_resource["baseUrl"] + endpoint,
method="POST",
headers=nextcloud_resource["headers"],
json=payload,
raise_for_status=True # HTTP 오류 발생 시 예외를 발생시킨다.
)
return response.json()
이 스크립트를 Windmill에 저장하면, user_id, subject, message를 입력받는 UI가 자동으로 생성된다. nextcloud_resource는 워크플로우에서 u/admin/exapp_resource와 같은 리소스 경로를 연결하여 전달받는다. 이처럼 OCS API 문서를 참조하여 Nextcloud의 거의 모든 기능을 프로그래밍 방식으로 제어하는 스크립트를 만들 수 있다.
5.3 인증 방식 심층 분석
Nextcloud 스크립트를 실행할 때 사용할 수 있는 인증 방식은 두 가지이며, 각각의 보안 모델과 사용 사례가 다르다.3
-
AppAPI 인증 (AppAPI Authentication):
-
동작 방식: 이 방식은 Flow ExApp을 통해 설치된 Windmill에서만 사용할 수 있다. 스크립트는 Nextcloud에 등록된 앱으로서 동작하며, Nextcloud의 모든 사용자를 가장(impersonate)할 수 있는 강력한 권한을 가진다.3 즉, 워크플로우를 시작한 사용자가 일반 사용자일지라도, 스크립트는 관리자(admin) 권한으로 API를 호출할 수 있다.
-
사용 사례: 시스템 전체에 영향을 미치는 관리자급 자동화에 적합하다. 예를 들어, 특정 조건이 충족되면 새로운 사용자를 생성하거나, 모든 사용자의 파일을 스캔하여 규정을 위반하는 파일을 격리하는 등의 작업이 가능하다.
-
보안 함의: 이 방식은 의도된 권한 상승 메커니즘을 포함한다. 따라서 AppAPI 인증을 사용하는 워크플로우는 그 자체로 관리 도구로 취급되어야 한다. 해당 워크플로우를 실행할 수 있는 권한은 Windmill의 권한 관리 시스템을 통해 신뢰할 수 있는 관리자 그룹에게만 엄격하게 제한되어야 한다.
-
일반 인증 (Normal Authentication):
-
동작 방식: 스크립트는 특정 Nextcloud 사용자의 사용자 이름과 암호(또는 앱 암호)를 사용하여 인증한다. 이 자격 증명은 Windmill에 암호화된 리소스로 저장된다. 스크립트는 해당 사용자가 가진 권한의 범위 내에서만 동작한다.3
-
사용 사례: 특정 사용자의 컨텍스트에서 실행되어야 하는 자동화에 적합하다. 예를 들어, 한 사용자가 자신의 폴더에 파일을 업로드했을 때, 해당 파일에 대해 그 사용자만이 가진 권한으로 다른 작업을 수행하는 경우가 이에 해당한다.
-
보안 함의: 권한 상승이 발생하지 않으므로 보안 모델이 단순하고 예측 가능하다. 스크립트의 행동 반경이 명확하게 한 사용자의 권한으로 제한된다.
이 두 가지 인증 방식의 차이점을 이해하는 것은 안전하고 효율적인 자동화 워크플로우를 설계하는 데 매우 중요하다. 워크플로우의 목적에 따라 적절한 인증 방식을 선택하고, 특히 AppAPI 인증을 사용할 때는 엄격한 접근 제어를 적용해야 한다.
6. 고급 기능 활용: 운영 및 관리
Windmill은 단순한 워크플로우 설계를 넘어, 프로덕션 환경에서의 안정적인 운영과 관리를 위한 강력한 고급 기능들을 제공한다. 작업 스케줄링, Git을 통한 버전 제어, 그리고 세분화된 권한 관리는 자동화 시스템을 체계적으로 운영하는 데 필수적인 요소다.
6.1 작업 스케줄링
Windmill은 정기적으로 반복되는 작업을 자동화하기 위해 강력한 스케줄링 기능을 제공한다. 이는 전통적인 Unix의 CRON 시스템과 유사하지만, 사용하기 쉬운 UI와 향상된 기능을 갖추고 있다.5
-
스케줄 설정: 스크립트나 플로우 설정 화면에서 직접 ’기본 스케줄(Primary Schedule)’을 활성화하고 CRON 표현식을 입력하여 간단하게 스케줄을 설정할 수 있다. 또는, 작업 공간의 ‘Schedules’ 메뉴에서 특정 스크립트/플로우와 입력 인수를 지정하는 ’다른 스케줄(Other Schedules)’을 여러 개 생성할 수도 있다.15
-
CRON 표현식: Windmill은 표준 CRON 구문뿐만 아니라, 초 단위 설정, 월의 마지막 주 금요일(
5L)이나 특정 날짜에 가장 가까운 평일(15W)과 같은 복잡한 규칙을 지원하는 확장된 구문을 사용한다.15
| 필드 | 값 | 특수 문자 | 의미 |
|---|---|---|---|
| 초 (선택) | 0-59 | * , - / | 60초 중 언제 실행될지 |
| 분 | 0-59 | * , - / | 60분 중 언제 실행될지 |
| 시간 | 0-23 | * , - / | 24시간 중 언제 실행될지 |
| 일 | 1-31 | * , - / ? L W | 한 달 중 며칠에 실행될지 |
| 월 | 1-12 | * , - / | 12달 중 몇 월에 실행될지 |
| 요일 | 0-7 (0,7=일) | * , - / ? L # | 한 주 중 무슨 요일에 실행될지 |
예제 CRON 표현식 15:
-
0 */15 * * * *: 매 15분마다 실행 -
0 0 12 * * MON-FRI: 주중 매일 정오 12시에 실행 -
0 0 12? * 5#3: 매월 세 번째 금요일 정오 12시에 실행
CRON 표현식이 익숙하지 않은 사용자를 위해, Windmill은 “매일 오후 5시에 실행“과 같은 자연어 입력을 CRON 표현식으로 변환해주는 AI 도우미와 간소화된 빌더도 제공한다.15
6.2 버전 제어: Git 연동
엔터프라이즈 환경에서 자동화 워크플로우는 중요한 비즈니스 로직을 담고 있는 ’코드’와 같다. Windmill의 Git 연동 기능은 이러한 워크플로우를 단순한 스크립트가 아닌, 체계적으로 관리하고 검토하며 배포할 수 있는 소프트웨어 자산으로 취급할 수 있게 해준다. 이는 자동화 로직에 ‘코드형 인프라(Infrastructure as Code)’ 개념을 적용하는 것과 같다.
-
Git Sync 설정: 작업 공간 설정의 ‘Git Sync’ 탭에서
git_repository리소스를 추가하여 Windmill 작업 공간을 특정 Git 저장소의 브랜치와 연결할 수 있다.16 인증은 개인 액세스 토큰(PAT)이나 더 안전한 GitHub 앱을 통해 이루어진다. -
자동 커밋 및 푸시: 설정이 완료되면, Windmill UI에서 스크립트나 플로우를 ’Deploy’할 때마다 변경 사항이 자동으로 연결된 Git 저장소에 커밋되고 푸시된다. 이를 통해 모든 변경 이력을 추적하고, 필요한 경우 이전 버전으로 쉽게 되돌릴 수 있다.
-
GitOps 워크플로우: Git 연동의 진정한 가치는 개발-스테이징-프로덕션으로 이어지는 체계적인 배포 파이프라인을 구축하는 데 있다.17
-
개발(Development): 개발자는 로컬 환경이나 개인 작업 공간에서 새로운 워크플로우를 개발하고 테스트한다.
-
스테이징(Staging): 개발이 완료되면, 변경 사항을 ‘staging’ 브랜치에 푸시한다. ‘staging’ 작업 공간은 이 브랜치와 동기화되어 있으며, 이곳에서 통합 테스트를 수행한다. Windmill의 ’프로모션 모드(Promotion Mode)’를 사용하면, 스테이징 작업 공간에서의 배포가 프로덕션 브랜치로의 풀 리퀘스트(Pull Request)를 자동으로 생성하도록 설정할 수 있다.17
-
프로덕션(Production): 동료 개발자나 관리자가 풀 리퀘스트를 검토(Code Review)하고 승인하면, 변경 사항이 ‘main’ 또는 ‘production’ 브랜치에 병합된다. 프로덕션 Windmill 작업 공간은 이 브랜치와 동기화되어 있어, 검증된 변경 사항만이 실제 운영 환경에 자동으로 배포된다.
이러한 GitOps 접근 방식은 자동화 로직의 안정성과 신뢰성을 크게 향상시키며, 여러 개발자가 협업하는 대규모 환경에서는 필수적인 관리 체계다.
6.3 권한 관리
Windmill은 여러 팀과 사용자가 함께 사용하는 것을 전제로 설계되었으며, 이를 위해 세분화된 접근 제어 목록(ACL) 기반의 권한 관리 시스템을 제공한다.12
-
역할 기반 접근 제어 (RBAC):
-
인스턴스 수준: Windmill 전체 인스턴스를 관리하는
Superadmin역할이 있다.19 -
작업 공간 수준: 각 작업 공간 내에는 세 가지 기본 역할이 있다.
-
Admin: 작업 공간의 모든 항목을 관리하고 사용자 및 권한을 설정할 수 있다. -
Developer(또는Writer): 스크립트, 플로우, 앱 등을 생성하고 수정할 수 있다. -
Operator(또는Viewer): 자신에게 보기 권한이 있는 스크립트나 앱을 실행만 할 수 있으며, 수정은 불가능하다.12 -
폴더와 그룹: 효율적인 권한 관리를 위해 폴더와 그룹을 사용한다.20
-
폴더 (Folders): 관련된 스크립트, 리소스, 변수 등을 하나의 프로젝트 단위로 묶는 컨테이너다. 권한은 주로 이 폴더 단위로 부여된다.
-
그룹 (Groups): 여러 사용자를 하나의 단위로 묶는다. 예를 들어 ‘인사팀’, ’개발팀’과 같은 그룹을 만들 수 있다.
-
권한 설정 예시: ’인사팀’만 접근해야 하는 데이터베이스 자격 증명(Resource)과 이를 사용하는 휴가 처리 워크플로우(Flow)가 있다고 가정하자.
-
’인사(HR)’라는 이름의 폴더를 생성한다.
-
데이터베이스 자격 증명 리소스와 휴가 처리 워크플로우를 ‘HR’ 폴더 안에 생성한다.
-
’인사팀’이라는 그룹을 만들고 해당 팀원들을 그룹에 추가한다.
-
‘HR’ 폴더의 권한 설정에서 ‘인사팀’ 그룹에게 ‘Writer’ 또는 ‘Admin’ 권한을 부여한다.
이제 ‘인사팀’ 그룹에 속한 사용자들만 해당 자원과 워크플로우에 접근하고 수정할 수 있으며, 다른 팀 사용자들에게는 보이지 않게 된다. 이러한 체계적인 권한 관리는 민감한 정보(비밀 변수, API 키 등)를 보호하고, 의도치 않은 수정을 방지하며, 조직의 보안 정책을 준수하는 데 필수적이다.
7. 실제 적용 사례 및 예제
이론적인 개념을 넘어, 실제 비즈니스 문제를 해결하는 구체적인 워크플로우 예제를 통해 Windmill의 강력함을 실제로 확인해 본다. 여기서는 문서 승인, Forms 데이터 처리, 그리고 과학 계산 보고서 생성이라는 세 가지 시나리오를 단계별로 구축한다.
7.1 사례 1: 문서 승인 워크플로우
조직에서 가장 흔한 프로세스 중 하나인 문서 승인 절차를 자동화한다. 사용자가 검토가 필요한 문서를 업로드하면, 관리자에게 알림이 가고, 관리자의 승인 여부에 따라 파일이 자동으로 분류되는 워크플로우다.
- 워크플로우 생성 및 이벤트 리스너 설정:
-
새로운 플로우를 생성한다.
-
첫 번째 스크립트 노드를 추가하고, Summary를
CORE:LISTEN_TO_EVENT로 설정한다. -
events파라미터에["OCP\\Files\\Events\\NodeCreatedEvent"]를 입력한다. -
filters파라미터에{"event.node.path": "/^\\/shared\\/Pending Review\\//"}를 입력하여 ‘Pending Review’ 공유 폴더에 파일이 생성될 때만 워크플로우가 실행되도록 제한한다.
- 승인 링크 생성 및 알림 발송:
-
다음 노드로 Windmill Hub의
Create an approval link with the approve_links app스크립트를 추가한다. 이 스크립트는 승인/거부 URL을 생성한다.14 -
그 다음 노드로
Nextcloud Talk: Send a message스크립트를 추가한다.14 -
메시지 내용에 이전 단계에서 생성된 문서 정보와 승인/거부 링크를 포함하여 관리자의 Talk 대화방으로 전송한다.
- 승인 대기 (일시 중단):
- 새로운 스크립트 노드를 추가하고, ‘Advanced’ 탭에서 ’Suspend/Approval/Prompt’를 활성화하여 승인 단계로 설정한다.3 이 단계는 관리자가 링크를 클릭할 때까지 워크플로우를 일시 중단시킨다.
- 조건부 분기 및 파일 이동:
-
‘Branch’ 노드를 추가하여 승인 결과를 확인한다. 승인 링크가 클릭되었는지, 거부 링크가 클릭되었는지에 따라 실행 경로를 나눈다.
-
‘승인’ 분기에는
Nextcloud WebDAV: Move a file or folder스크립트를 사용하여 파일을 ‘Pending Review’ 폴더에서 ‘Approved’ 폴더로 이동시킨다.14 -
‘거부’ 분기에는 파일을 ‘Rejected’ 폴더로 이동시키고, 최초 업로드 사용자에게 Talk 메시지로 반려 사유를 알린다.
7.2 사례 2: Nextcloud Forms 데이터 처리
웹사이트에 임베드된 Nextcloud Forms를 통해 접수된 신청서(예: 유치원 입학 신청) 데이터를 자동으로 처리하고 저장하는 워크플로우다.1
- Forms 제출 이벤트 수신:
-
CORE:LISTEN_TO_EVENT스크립트의events파라미터에 ``를 설정한다. -
필요하다면
filters를 사용하여 특정 양식 ID의 제출 이벤트만 수신하도록 할 수 있다.
- 제출 데이터 상세 조회:
- 웹훅으로 전달되는 초기 데이터에는 기본적인 정보만 포함되어 있다. 전체 제출 내용을 가져오기 위해, Hub의
Get a form submission from Nextcloud Forms스크립트를 사용한다.14 이 스크립트의 입력으로는
flow_input.event.form.hash를 전달한다.
- 데이터 처리 및 검증 (Python 스크립트):
-
새로운 Python 스크립트 노드를 추가한다.
-
이전 단계(
results.b.submission.answers)에서 받은 데이터를 입력으로 받아, 데이터 형식이 올바른지 검증하거나, 외부 API를 호출하여 데이터를 보강하는 등의 처리를 수행한다.
- Nextcloud Tables에 저장:
- Hub의
Nextcloud Tables: Create a row in a table스크립트를 사용하여, 처리된 데이터를 지정된 테이블에 새로운 행으로 삽입한다.14
- 신청자에게 확인 이메일 발송:
- Hub의
SendGrid또는SMTP관련 스크립트를 사용하여 신청자의 이메일 주소로 접수 완료 확인 메일을 발송한다.22
7.3 사례 3: 과학 계산 및 보고서 생성
이 예제는 Windmill의 Python 실행 환경과 라이브러리 지원을 활용하여, 데이터 분석, 시각화, 그리고 LaTeX 기반의 수식 출력을 포함하는 과학 계산 워크플로우를 구축하는 방법을 보여준다. 풍력 터빈의 출력을 계산하는 간단한 물리 모델을 예로 든다.
- 데이터 파일 업로드 트리거:
CORE:LISTEN_TO_EVENT를 사용하여 특정 폴더(예:/data/wind-speed-csv/)에 CSV 파일이 업로드되는 것을 감지하도록 설정한다.
- 데이터 분석, 시각화 및 계산 (Python 스크립트):
- 다음과 같은 Python 스크립트 노드를 생성한다. 이 스크립트는
pandas,matplotlib,sympy라이브러리를 사용하므로, Windmill이 자동으로 의존성을 설치하도록 한다.
# py: >=3.11
import wmill
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import sympy
import os
# Matplotlib이 LaTeX 렌더링을 사용하도록 설정
plt.rcParams.update({
"text.usetex": True,
"font.family": "serif",
"font.serif":,
})
def main(csv_file_content: bytes):
# 1. Pandas를 사용하여 CSV 데이터 로드
from io import BytesIO
df = pd.read_csv(BytesIO(csv_file_content))
# df는 'timestamp'와 'wind_speed_ms' 컬럼을 가졌다고 가정
# 2. Matplotlib를 사용하여 그래프 생성 및 LaTeX 수식 포함
fig, ax = plt.subplots()
ax.plot(df['timestamp'], df['wind_speed_ms'])
ax.set_title(r'Wind Speed Over Time')
ax.set_xlabel(r'Time')
# Betz's Law 공식을 y축 레이블에 LaTeX으로 표현
ax.set_ylabel(r'Wind Speed ($v$) in m/s')
ax.grid(True)
# 그래프를 이미지 파일로 저장
# Windmill의 임시 파일 시스템(/tmp)에 저장
plot_path = "/tmp/wind_speed_plot.png"
fig.savefig(plot_path)
# 3. Sympy를 사용하여 상징적 계산 및 LaTeX 문자열 생성
# Betz's Law: P = 1/2 * rho * A * v^3 * Cp
rho, A, v, Cp = sympy.symbols('rho A v C_p')
P = sympy.Rational(1, 2) * rho * A * v**3 * Cp
# Sympy 표현식을 LaTeX 문자열로 변환
latex_equation = sympy.latex(P, mode='inline')
# 4. 계산된 평균 출력
# 실제 계산 예시 (상수값 가정)
RHO_AIR = 1.225 # 공기 밀도 (kg/m^3)
TURBINE_AREA = 5000 # 터빈 면적 (m^2)
CP_MAX = 0.593 # Betz's Limit
avg_wind_speed = df['wind_speed_ms'].mean()
avg_power_watts = 0.5 * RHO_AIR * TURBINE_AREA * (avg_wind_speed**3) * CP_MAX
avg_power_kw = avg_power_watts / 1000
# 5. 결과 반환
# 파일은 wmill.File 객체로 반환해야 Windmill이 인식함
return {
"plot_image": wmill.File(path=plot_path, content=None),
"betz_law_latex": f"P = {latex_equation}",
"average_power_kw": avg_power_kw,
"report_summary": f"Average wind speed was {avg_wind_speed:.2f} m/s, resulting in an estimated average power output of {avg_power_kw:.2f} kW."
}
이 스크립트는 CSV 파일 내용을 입력받아, 풍속 데이터를 그래프로 시각화하고, Betz의 법칙(P=21ρAv3Cp)을 LaTeX 수식으로 표현하여 그래프 축과 별도의 문자열로 생성한다. 최종적으로 생성된 그래프 이미지 파일과 LaTeX 수식 문자열, 계산된 평균 출력값을 결과로 반환한다.
- 후속 처리:
- 이 스크립트의 결과(
results.b)는 다른 스크립트의 입력으로 사용될 수 있다. 예를 들어, PDF 생성 라이브러리를 사용하는 또 다른 Python 스크립트로 전달하여, 그래프 이미지와 LaTeX 수식을 포함하는 자동화된 분석 보고서를 생성하고 Nextcloud에 저장하거나 이메일로 전송할 수 있다.
8. 기술 참조
이 섹션은 Nextcloud-Windmill 통합 환경을 운영하고 개발하는 동안 빠르고 쉽게 참조할 수 있는 핵심 정보들을 요약하여 제공한다.
8.1 주요 Nextcloud 이벤트 및 필터
워크플로우를 트리거하기 위해 CORE:LISTEN_TO_EVENT 스크립트에서 자주 사용되는 Nextcloud 이벤트 ID와 필터링 가능한 주요 속성은 다음과 같다.10
| 이벤트 ID | 설명 | 주요 필터 속성 |
|---|---|---|
OCP\Files\Events\NodeCreatedEvent | 파일 또는 폴더가 생성됨 | user.uid, event.node.path |
OCP\Files\Events\NodeUpdatedEvent | 파일 내용이 수정됨 | user.uid, event.node.path |
OCP\Files\Events\NodeDeletedEvent | 파일 또는 폴더가 삭제됨 | user.uid, event.node.path |
OCA\Forms\Events\FormSubmittedEvent | Nextcloud Forms 양식이 제출됨 | user.uid, event.form.id |
OCA\Tables\Event\RowAddedEvent | Nextcloud Tables에 행이 추가됨 | user.uid, event.tableId, event.rowId |
OCA\Tables\Event\RowUpdatedEvent | Nextcloud Tables의 행이 수정됨 | user.uid, event.tableId, event.rowId |
OCP\Calendar\Events\CalendarObjectCreatedEvent | 캘린더에 이벤트가 생성됨 | user.uid, event.calendarId |
8.2 Windmill Hub Nextcloud 스크립트 목록
Windmill Hub에서 제공하는 주요 Nextcloud 연동 스크립트 목록은 다음과 같다. 워크플로우 설계 시 이 스크립트들을 우선적으로 활용하는 것이 효율적이다.14
| 스크립트 이름 | 설명 | 주요 파라미터 |
|---|---|---|
Nextcloud Talk: Send a message | Talk 대화방에 메시지를 전송한다. | conversationToken, message |
Nextcloud Tables: Create a row in a table | Tables 앱의 테이블에 행을 생성한다. | tableId, columns (JSON) |
Nextcloud Tables: Edit a row in a table | Tables 앱의 테이블에서 행을 수정한다. | tableId, rowId, columns (JSON) |
Nextcloud WebDAV: Upload or update a file | WebDAV를 통해 파일을 업로드/수정한다. | path, content |
Nextcloud WebDAV: Get the content of a file | WebDAV를 통해 파일 내용을 가져온다. | path |
Nextcloud WebDAV: Move a file or folder | 파일 또는 폴더를 이동/이름 변경한다. | sourcePath, destinationPath |
Send a notification to a user | 사용자에게 Nextcloud 알림을 보낸다. | userId, subject, message |
Get a form submission from Nextcloud Forms | Forms 제출 데이터의 상세 내용을 가져온다. | hash |
Create an approval link with the approve_links app | approve_links 앱을 위한 승인/거부 링크를 생성한다. | subject |
8.3 문제 해결 가이드
Nextcloud와 Windmill 통합 환경에서 발생할 수 있는 일반적인 문제와 해결 방안은 다음과 같다.
-
문제: 워크플로우가 트리거되지 않거나 5분 정도 지연된다.
-
원인:
webhook_listeners앱이 Nextcloud의 기본 cron 백그라운드 잡에 의존하고 있기 때문이다. -
해결책:
III. 설치 및 초기 설정 가이드의3.5. webhook_listeners 앱 상세 설정섹션을 참조하여,systemd서비스 등을 이용한 전용 백그라운드 작업 워커를 설정한다. 이를 통해 웹훅이 거의 즉시 처리되도록 할 수 있다.10 -
문제: Windmill 스크립트에서 Nextcloud API 호출 시 ‘Connection refused’ 또는 ‘404 Not Found’ 오류가 발생한다.
-
원인: Windmill이 Nextcloud에 접속하기 위한
baseUrl이 잘못 설정되었을 가능성이 높다. 특히 리버스 프록시나 Docker 환경에서 자주 발생한다. -
해결책: Windmill UI의 ‘Resources’ 탭에서
u/admin/exapp_resource를 찾아 편집한다.baseUrl필드가 외부에서 접근 가능한 정확한 Nextcloud URL로 설정되어 있는지 확인하고 수정한다.3 -
문제: 스크립트 실행 시 권한 오류(401 Unauthorized, 403 Forbidden)가 발생한다.
-
원인 1: AppAPI 인증이 아닌 일반 인증을 사용하면서, 스크립트를 실행하는 사용자가 대상 객체(파일, 폴더 등)에 대한 충분한 권한이 없는 경우.
-
원인 2: 인증 리소스(
exapp_resource)의 자격 증명이 만료되거나 잘못된 경우. -
해결책: 워크플로우의 목적에 맞는 인증 방식을 사용하고 있는지 확인한다 (AppAPI 인증 vs. 일반 인증). 스크립트가 수행하려는 작업에 대해 해당 사용자가 Nextcloud UI에서 직접 수행할 수 있는 권한을 가졌는지 확인한다.
-
문제: Flow 앱 설치 후 Nextcloud UI가 불안정해지거나 특정 앱(예: Custom Menu)과 충돌한다.
-
원인: 다른 Nextcloud 앱과의 호환성 문제일 수 있다. 커뮤니티 포럼에서 ‘Custom Menu’ 앱과 충돌이 보고된 사례가 있다.23
-
해결책: 문제가 되는 다른 앱을 일시적으로 비활성화하여 충돌 여부를 확인한다.
nextcloud-aio-nextcloud컨테이너를 수동으로 재시작하는 것이 도움이 될 수 있다.23 GitHub 이슈 트래커에서 유사한 문제가 보고되었는지 확인한다.24 -
문제: 워크플로우의 특정 스크립트 단계에서 실행이 실패한다.
-
원인: 스크립트 코드 자체의 버그, 잘못된 입력값 전달, 외부 API의 일시적인 오류 등 다양한 원인이 있을 수 있다.
-
해결책: Windmill UI의 ‘Runs’ 탭에서 실패한 워크플로우 실행 기록을 찾는다. 실패한 스크립트 단계를 클릭하면 상세한 실행 로그(표준 출력 및 표준 에러)를 확인할 수 있다. 로그를 통해 오류의 원인을 파악하고 스크립트나 입력값을 수정한다.
9. 결론
Nextcloud Hub에 통합된 Windmill 앱은 단순한 자동화 도구를 넘어, 조직이 디지털 주권을 유지하면서 자체 인프라 내에서 정교하고 강력한 비즈니스 프로세스를 구축하고 실행할 수 있도록 하는 완전한 개발자 플랫폼이다. Rust 기반의 고성능 백엔드, nsjail을 통한 안전한 코드 실행 환경, 그리고 Git 연동을 통한 체계적인 버전 관리 및 배포(GitOps) 기능은 Windmill이 엔터프라이즈급 요구사항을 충족할 수 있는 기술적 기반을 제공한다.
이 가이드는 Windmill의 아키텍처적 이해부터 시작하여, 설치, 워크플로우 설계, 스크립트 개발, 그리고 고급 운영 관리에 이르기까지 전 과정을 심도 있게 다루었다. 특히, CORE:LISTEN_TO_EVENT를 통한 이벤트 리스닝 메커니즘, AppAPI 인증의 강력함과 보안적 고려사항, 그리고 전용 워커 설정을 통한 성능 최적화와 같은 핵심 개념들을 상세히 설명하였다.
문서 승인, Forms 데이터 처리, 과학 계산 보고서 생성과 같은 구체적인 적용 사례를 통해, 관리자와 개발자는 Windmill을 활용하여 반복적인 작업을 자동화하고, 데이터 기반의 의사결정을 지원하며, 조직의 생산성을 극대화할 수 있는 실질적인 방법을 습득할 수 있다.
결론적으로, Nextcloud와 Windmill의 결합은 조직의 협업 환경을 한 단계 끌어올리는 강력한 시너지 효과를 창출한다. 이는 단순한 파일과 소통의 공간을 넘어, 조직의 핵심 프로세스가 살아 움직이는 동적인 플랫폼으로 Nextcloud를 재정의하며, 오픈소스 생태계 안에서 비즈니스 자동화의 새로운 가능성을 제시한다.
10. 참고 자료
- How to automate business processes with Nextcloud Flow?, https://nextcloud.com/blog/how-to-automate-business-processes-with-nextcloud-flow-your-workflow-automation-assistant/
- Driving digital transformation with automation - Nextcloud Flow, https://nextcloud.com/flow/
- Windmill Workflows — Nextcloud latest Administration Manual latest documentation, https://docs.nextcloud.com/server/latest/admin_manual/windmill_workflows/index.html
- Nextcloud Flow Engine - GitHub, https://github.com/nextcloud/flow
- Windmill | Open-source developer platform and workflow engine, https://www.windmill.dev/
- Scripts quickstart - Windmill, https://www.windmill.dev/docs/getting_started/scripts_quickstart
- Nextcloud - Open source content collaboration platform, https://nextcloud.com/
- windmill-labs/windmill: Open-source developer platform to power your entire infra and turn scripts into webhooks, workflows and UIs. Fastest workflow engine (13x vs Airflow). Open-source alternative to Retool and Temporal. - GitHub, https://github.com/windmill-labs/windmill
- AppAPI and External Apps — Nextcloud latest Administration Manual latest documentation, https://docs.nextcloud.com/server/latest/admin_manual/exapps_management/AppAPIAndExternalApps.html
- Webhook Listeners — Nextcloud latest Administration Manual latest …, https://docs.nextcloud.com/server/latest/admin_manual/webhook_listeners/index.html
- Windmill Basics: Build your first CRUD - tools.dev, https://blog.boldtech.dev/windmill-basics-crud/
- What is Windmill? - tools.dev - Bold Tech, https://blog.boldtech.dev/what-is-windmill-dev/
- Flows quickstart - Windmill, https://www.windmill.dev/docs/getting_started/flows_quickstart
- nextcloud scripts | Windmill Hub, https://hub.windmill.dev/integrations/nextcloud
- Schedules | Windmill, https://www.windmill.dev/docs/core_concepts/scheduling
- Git integration - Windmill, https://www.windmill.dev/docs/integrations/git_repository
- Git sync | Windmill, https://www.windmill.dev/docs/advanced/git_sync
- How Windmill uses Windmill | Windmill, https://www.windmill.dev/blog/how-windmill-uses-windmill
- Roles and permissions | Windmill, https://www.windmill.dev/docs/core_concepts/roles_and_permissions
- Groups and folders - Windmill, https://www.windmill.dev/docs/core_concepts/groups_and_folders
- README.md · main - Nextcloud Flow - GitLab - openCode, https://gitlab.opencode.de/nextcloud/flow/nextcloud-flow/-/blob/main/README.md?ref_type=heads
- SendGrid integration - Windmill, https://www.windmill.dev/docs/integrations/sendgrid
- Cannot get Flow/Windmill working - how to get it up? · nextcloud all-in-one · Discussion #6037 - GitHub, https://github.com/nextcloud/all-in-one/discussions/6037
- Issues · nextcloud/flow - GitHub, https://github.com/nextcloud/flow/issues