내구성 워크플로우는 Postgres만 쓰면 된다

발행: (2026년 5월 29일 AM 03:41 GMT+9)
13 분 소요

내구성 워크플로우: 데이터베이스를 오케스트레이터로 활용하는 간단한 접근법

내구성 워크플로우는 신뢰할 수 있는 프로그램을 만들기 위한 간단하지만 강력한 도구입니다.
아이디어는 프로그램이 실행되는 동안 진행 상황을 정기적으로 데이터베이스에 체크포인트로 저장한다는 것입니다.
이렇게 하면 프로그램이 충돌하거나 실패했을 때 마지막 체크포인트부터 다시 로드하여 마지막으로 완료된 단계부터 복구할 수 있습니다.
비디오 게임의 저장 기능과 비슷하게, 프로그램 진행 상황을 정기적으로 **“저장”**하고, 충돌 시 **“로드”**할 수 있습니다.

외부 오케스트레이션 – 기존 모델

대부분의 경우, 내구성 워크플로우는 외부 오케스트레이션을 통해 구현됩니다.
이 패턴은 Temporal, Airflow, AWS Step Functions 같은 시스템에서 사용됩니다.
이 모델에서는 내구성 프로그램이 단계들의 워크플로우 형태로 작성되고, 실행은 중앙 오케스트레이터가 조정합니다.

  1. 클라이언트가 워크플로우를 제출합니다.
  2. 오케스트레이터가 데이터 스토어에 해당 워크플로우 레코드를 생성하고, 작업자에게 실행을 전달합니다.
  3. 작업자가 단계 실행을 마칠 때마다 결과를 오케스트레이터에 보냅니다.
  4. 오케스트레이터는 결과를 데이터 스토어에 체크포인트하고, 다음 단계를 전달합니다.
  5. 작업자가 충돌하거나 실패하면, 오케스트레이터는 해당 워크플로우를 다른 작업자에게 전달하여 마지막 체크포인트 단계부터 다시 시작합니다.

외부 오케스트레이션 다이어그램

외부 오케스트레이션이 근본적으로 과도하게 복잡한 이유

이 블로그 포스트에서는 외부 오케스트레이션이 근본적으로 과도하게 복잡하다고 주장합니다.
내구성 워크플로우의 핵심 아이디어는 프로그램 상태를 데이터베이스에 체크포인트하는 것입니다.
내구성 워크플로우가 데이터베이스와 관련된 것이라면, 별도의 오케스트레이터 서버를 둘 필요가 없습니다.
대신 데이터베이스 자체를 오케스트레이터로 활용하는 것이 더 간단하고 효율적입니다.

구체적인 예시로, 우리는 PostgreSQL을 기반으로 내구성 워크플로우를 구축하는 데 초점을 맞춥니다. 이유는 다음과 같습니다.

데이터베이스 기반 설계

Postgres 기반 내구성 워크플로우 시스템에서는 애플리케이션 서버가 중앙 오케스트레이터를 거치지 않고 직접 Postgres와 통신해 워크플로우를 실행합니다.

  1. 클라이언트가 workflows 테이블에 엔트리를 생성하여 워크플로우를 제출합니다.
  2. 애플리케이션 서버가 테이블을 폴링하고, 워크플로우를 dequeue한 뒤 실행합니다.
  3. 서버가 워크플로우를 실행하면서 각 단계의 결과를 Postgres에 체크포인트합니다.
  4. 서버가 충돌하면, 다른 서버가 체크포인트를 기반으로 워크플로우를 복구합니다.

데이터베이스 기반 워크플로우 다이어그램

이 설계는 중앙 오케스트레이터가 필요 없게 합니다. 이유는 다음과 같습니다.

  • 디스패치: 작업자는 SELECT … FOR UPDATE SKIP LOCKED와 같은 락 절을 사용해 Postgres 테이블에서 워크플로우를 dequeue하므로, 각 워크플로우가 정확히 하나의 작업자에 의해 처리됩니다.
  • 체크포인트: 작업자는 단계 결과를 직접 Postgres에 기록합니다.
  • 중복 작업 감지: 고유 인덱스와 같은 무결성 제약조건을 활용해 다른 작업자가 이미 같은 단계를 체크포인트했는지 감지하고 작업을 중단할 수 있습니다.

중앙 오케스트레이터를 Postgres(또는 다른 데이터베이스)로 대체하면 내구성 워크플로우가 근본적으로 단순해집니다. 확장성, 가용성, 가시성, 보안 같은 어려운 문제들도 잘 알려진 Postgres 고유의 솔루션으로 해결할 수 있습니다.

확장성 및 가용성

데이터베이스 기반 내구성 워크플로우 시스템의 확장성과 가용성은 기본 데이터베이스에 의해 결정됩니다.

  • 확장성: 워커 서버를 더 추가함으로써 수평적으로 확장할 수 있으며, 병목은 데이터베이스가 워크플로우 레코드를 얼마나 빠르게 처리하느냐가 됩니다.
  • 가용성: 워커는 서로 교체 가능하고 자유롭게 상태를 복구할 수 있기 때문에, 데이터베이스가 정상인 한 시스템은 계속 가용합니다.

Postgres‑특화 장점

  • 수직 확장: 단일 Postgres 인스턴스가 초당 수만 개의 워크플로우를 처리할 수 있습니다 (벤치마크).
  • 수평 확장: CockroachDB와 같은 분산 솔루션이나 샤딩된 Postgres 클러스터를 이용하면 용량을 더욱 늘릴 수 있습니다.
  • 고가용성: Postgres는 스트리밍 복제와 자동 페일오버를 지원하며, 관리형 서비스는 멀티 AZ 배포와 고가용성 SLA를 기본 제공합니다.

수십 년에 걸친 Postgres 확장성·가용성 엔지니어링을 그대로 내구성 워크플로우에 활용할 수 있습니다.

가시성

Postgres 기반 내구 실행을 사용할 경우, 워크플로우와 단계들은 테이블에 체크포인트됩니다.
따라서 가시성이 내재되어 있어, 해당 테이블을 쿼리하면 실시간으로 워크플로우를 모니터링하고 실행 흐름을 시각화할 수 있습니다.

SQL만으로 거의 모든 가시성 쿼리를 표현할 수 있기 때문에, 강력하고 선언적인 분석 기능을 별도 비용 없이 얻을 수 있습니다. 예를 들어, 지난 한 달 동안 오류가 발생한 모든 워크플로우를 찾는 쿼리는 다음과 같습니다.

SELECT
    workflow_id,
    step_name,
    error_message,
    completed_at
FROM
    workflow_steps
WHERE
    status = 'error'
    AND completed_at >= now() - interval '1 month'
ORDER BY
    completed_at DESC;

이와 같은 쿼리는 직관적이지만, 그 힘을 과소평가하기 어렵습니다.
Postgres의 관계형 모델 덕분에 복잡한 필터링·분석 작업을 선언적으로 표현할 수 있으며, 수십 년간 축적된 쿼리 최적화 연구 결과를 그대로 활용합니다.
많은 외부 오케스트레이터는 표현력이 제한된 키‑밸류 스토어에 의존하는 반면, Postgres 테이블에 워크플로우·단계 데이터를 저장하고 보조 인덱스를 추가하면 “무료”로 효율적인 가시성을 얻을 수 있습니다.


이 포스트의 나머지 부분에서는 보안, 내결함성, PostgreSQL 기반 내구성 워크플로우 구현 패턴을 더 깊이 살펴볼 예정입니다.

신뢰성 및 보안

외부 오케스트레이터를 사용해 내구 실행을 할 경우, 오케스트레이터와 그 데이터 스토어가 모두 단일 장애 지점이 됩니다. 워크플로우 실행을 직접 조정하기 때문에, 어느 하나가 다운되면 전체 애플리케이션이 사용 불가능해집니다. 또한 워크플로우와 단계 체크포인트를 처리·저장하므로 민감한 애플리케이션 데이터에 접근할 가능성이 높아, 다른 중요한 인프라와 마찬가지로 강화·접근 제어·감사가 필요합니다.

반면 Postgres 기반 내구 실행에서는 실패 가능성이 있는 유일한 지점은 Postgres 자체이며, 모든 워크플로우 데이터는 직접 Postgres에 저장되고 다른 시스템을 거치지 않습니다. 애플리케이션이 이미 Postgres에 의존하고 있다면, 내구 실행을 도입해도 새로운 장애 지점이 추가되지 않으며 보안 표면도 확대되지 않습니다. 데이터베이스는 이미 핵심 인프라이므로, 별도의 핵심 인프라를 추가해 오케스트레이션을 구현하기보다 기존 인프라를 재활용하는 것이 더 합리적입니다.

더 알아보기

스케일러블하고 신뢰성 높은 시스템 구축에 관심이 있다면 언제든지 연락 주세요. DBOS에서는 Postgres 기반 내구 실행을 최대한 간단하고 성능 좋게 만들고자 합니다. 확인해 보세요:

  • 빠른 시작:
  • GitHub:
  • Discord 커뮤니티:
0 조회
Back to Blog

관련 글

더 보기 »

PostgreSQL 01008 오류 원인과 해결 방법 완벽 가이드

PostgreSQL 오류 코드 01008은 “WARNING: implicit zero bit padding” 경고이며, 비트 문자열(BIT/BIT VARYING) 데이터를 다룰 때 지정된 길이보다 짧은 값이 입력되면 PostgreSQL이 자동으로 오른쪽에 0 비트를 채워 넣는 상황에서 발생합니다.

첫 포스트: 짧은 전기

Introduction Hello, my name is Jay. Growing up, I wanted to follow in my dad's footsteps and become an engineer—and I did, just not in the way I originally exp...