pg_durable - PostgreSQL 내부에서 실행되는 지속 실행 워크플로우
요약
PostgreSQL 내부에서 실행되는 지속 실행 워크플로우인 pg_durable와 관련하여, 데이터베이스 내 로직 구현의 장단점을 분석합니다. 큐 로직의 코드 관리, 버전 제어, 테스트 및 확장성 측면에서 저장 프로시저 활용에 대한 기술적 논쟁을 다룹니다.
핵심 포인트
- Postgres 기반 큐(pgQue, DBOS)의 부상과 개발자 경험 문제
- 비즈니스 로직의 데이터베이스 내 위치에 따른 버전 관리 및 테스트 이슈
- 저장 프로시저 활용 시 관측성 및 확장성 확보 방안
- 워크플로우 엔진으로서의 pg_durable와 Temporal 비교 관점
2026년은 Postgres 큐의 해가 될 듯함: DBOS[0], pgQue[1] 같은 흐름이 있고, 커뮤니티가 이런 선택지를 만들어 주는 건 멋짐
다만 전직 애플리케이션 엔지니어 입장에서는 큐 로직이 코드와 Git 안에 있는 편을 선호함. 적절한 도구가 있으면 생각이 바뀔 수도 있음
[0]: https://www.dbos.dev/
[1]: https://github.com/NikolayS/pgque
작업 방식이 더 어렵거나 그냥 다른 것일 수도 있지만, 문서·검색 가능한 글·경험·도구가 부족해 보임
버전 관리, 디버깅, 테스트, 릴리스는 어떻게 하는지 궁금함. 데이터 지역성과 스택 단순화를 위해 전부 한곳에 두는 건 좋아 보이지만, “제대로” 하는 방법에 대한 유용한 지식을 많이 잃는 느낌임
“큐 로직은 코드에 두고 싶다”에 동의함. 데이터 자체보다 그 데이터에 대해 수행해야 하는 동작이 훨씬 자주 바뀌는데, 동작을 바꿀 때마다 마이그레이션을 해야 하는 건 이해가 안 됨
Supabase에서 조금만 복잡한 일을 하려 해도 Postgres 함수를 만들어야 했던 점도 그래서 정말 싫었음. 다만 이전 스타트업에서는 Postgres 위에 간단한 작업 큐를 직접 만들었고, pgQue 같은 것이 있었다면 훨씬 다듬어진 형태가 됐을 것 같음
Postgres 7 시절부터 팬이었고 실험적으로 가능한 한 많은 걸 PostgreSQL 안에 넣어 보려 했지만, 최소한 개발자 경험과 관측성은 아직 부족함
멀티 마스터 확장도 즉시 쓸 수 있고 완전히 안전한 이야기는 아니라서, 데이터베이스 확장 필요성을 앞당기는 쓰기 중심의 복잡한 작업을 넣는 데는 조심스러움
DB 트리거가 있던 프로젝트에서는 SQL 코드도 Git에 넣어 관리했음
로컬 설정 시 트리거가 로컬 데이터베이스에 들어가도록 Django 마이그레이션에 밀어 넣은 경우도 있었음
이건 저장 프로시저 냄새가 남. 단위 테스트도, 버전 관리도 어렵고, 비즈니스 로직이 데이터베이스 안에 숨어 “숨은 두뇌”가 됨
시끄러운 워크로드를 격리하기도 어렵고, 관측성도 없으며, 확장 압력이 전부 Postgres에 몰림. 특히 API 호출 같은 입출력이 부족함. 로컬 데이터베이스 안에서만 도는 작업에는 괜찮지만, 쓰임새가 좁아 보임
저장 프로시저도 제대로 쓰면 훌륭함. 버전 관리는 단조 증가하는 ID를 이름 끝에 붙이면 되고, 깨지는 변경이 필요할 때 ID를 올리며, 예전 버전은 더 이상 쓰지 않을 때까지 남겨 두면 됨
물론 데이터베이스 업그레이드 절차가 제대로 있어야 함. 팀원이 root로 임의 SQL 마이그레이션을 실행하는 식이면 고생하게 됨
단위 테스트도 다른 SQL 테스트와 똑같이 가능하고, 데이터베이스를 띄워야 할 뿐임. 저장 프로시저를 테스트할 수 없다면 SQL 자체를 테스트할 방법이 없다는 뜻이고, 그게 진짜 문제임
저장 프로시저의 대안은 데이터베이스에 비즈니스 로직을 전혀 안 두는 것이 아니라, 코드베이스 곳곳에 SQL이 흩어져 테스트하기 어렵고 버전 관리와 캡슐화가 나쁘며 불필요하게 느린 상태가 되는 경우가 많음
관측성은 일부 맞는 말로, SQL 문제를 들여다보는 일은 대부분의 프로그래밍 언어보다 손이 더 감. 하지만 저장 프로시저가 입출력 문제와 확장 문제를 만든다면 잘못 쓰고 있는 것이고, 제대로 쓰면 오히려 입출력을 크게 줄여 확장성을 개선하는 경우가 많음
사소한 정정이지만, absurd는 Mario Zechner가 earendil에 합류하기 전부터 시작된 earendil의 원래 프로젝트처럼 보이고, 커밋에서도 그를 보지 못했음
물론 세부 사정을 전부 아는 건 아니라 진심으로 궁금함
“쓰지 말아야 할 때”에 “워크플로가 대부분 Postgres 밖에 있고 여러 이기종 시스템에 걸쳐 있을 때”라고 되어 있는데, 그렇다면 이 프로젝트가 Temporal 같은 것과 어떻게 비교될 수 있는지 모르겠음
이 권고가 암시하는 제한을 잘못 이해한 것인지 궁금함
동의함. 예제인 https://github.com/microsoft/pg_durable/blob/main/examples/i...를 보면 프로젝트의 가치가 잘 이해되지 않음
기술적으로는 흥미로운 성취일 수 있지만, 이런 SQL을 읽는 건 꽤 기묘함 SELECT df.start( @> ( ($$SELECT ... FROM demo.invoices WHERE status = 'pending'$$ |=> 'inv') ~> df.if_rows('inv', $$UPDATE ... SET status = 'processing'$$ ~> (df.http(...) |=> 'resp') ~> df.if($$SELECT $r.ok$$, -- classify, branch, wait for signal ... ), df.sleep(5) ) ), 'invoice-approval-pipeline' );
ParadeDB는 AGPL이라 대형 클라우드 사업자들에서 일반적으로 제공되기 어려움. 다만 Azure HorizonDB에서는 https://github.com/timescale/pg_textsearch를 쓸 수 있고, Flex에도 곧 들어갈 가능성이 큼
공개하자면 pg_textsearch 유지관리자이고 지금은 Azure에 있음. 벡터 지원에 대한 말은 정확히 이해하지 못했는데, Azure에서 제공되는 pgvector + diskann을 넘어서는 뭔가를 원하는 것인지 궁금함
벡터 검색에는 Azure Cosmos DB가 더 맞지 않나 싶음
이미 검토했겠지만, 그냥 베어 VM을 만들고 최신 Postgres를 설치하면 안 되는 이유가 궁금함
Azure PG 팀에서 Postgres의 AI 기능을 맡는 PM임. 요청한 기능들은 실제로 제공 중이고, 지난 3~6개월 사이에 많은 진전이 있었음
하이브리드 검색(BM25 + 벡터)의 경우 ParadeDB의 pg_search도 AWS 네이티브 기능은 아니며 EC2에 직접 호스팅해야 함. Azure PostgreSQL에는 같은 BM25 순위 모델을 제공하는 pg_textsearch를 네이티브로 만들었고, 주 기여자가 현재 Azure Postgres 팀에 있음
문서: https://learn.microsoft.com/en-us/azure/horizondb/ai/full-te...
고차원 벡터는 오히려 앞서 있는 영역임. HNSW를 쓰는 pgvector는 2,000차원 제한이 있지만, Azure는 벡터 저장과 검색용 pgvector를 지원하고, 고차원·대규모 워크로드에는 Microsoft의 그래프 기반 벡터 인덱스인 pg_diskann을 제공함. 최대 16,000차원을 지원하고, 그래프 순회 중 WHERE 조건을 평가하는 고급 인덱스 내 필터링도 제공해 선택적 조건에서 재현율을 잃지 않음
pgvector: https://learn.microsoft.com/en-us/azure/horizondb/ai/vector-...
DiskANN 고차원 지원: https://learn.microsoft.com/en-us/azure/horizondb/ai/vector-...
이 기능들은 현재 Azure PostgreSQL, 특히 Azure HorizonDB Preview에서 사용 가능함. 특정 워크로드가 있다면 더 구체적으로 살펴볼 수 있음
이건 Apache Airflow 같은 DAG 스케줄러가 오래전부터 풀어 온 오래된 문제에 대한 잘못된 해법처럼 느껴짐
제어 흐름을 왜 코드가 아니라 데이터베이스에 저장하고 싶은지 이상함. 프로젝트를 깎아내리려는 건 아니고, 아직 잘 이해가 안 됨
Microsoft에는 이런 용도의 Durable Task 프레임워크[1]가 있고, Temporal처럼 자체 호스팅 독립 서비스로도 실행할 수 있으며 Azure Functions에서 서버리스로도 돌릴 수 있음. 기억이 맞다면 Airflow, Temporal보다도 먼저 나왔음
이 프로젝트는 더 데이터베이스 특화 사용 사례로 보임. 장점은 워크플로 로그와 코드베이스를 대조하며 한 줄씩 추적하지 않아도, 작업의 정확한 상태를 데이터베이스 자체에서 추적할 수 있다는 점일 듯함. 부하와 지연도 더 작고, 운영상 띄워야 할 구성요소가 하나 줄어드는 효과도 있을 것 같음
[1] https://learn.microsoft.com/en-us/azure/durable-task/common/...
Airflow 같은 외부 도구는 데이터베이스 부하를 알 수 없음. 개발자가 동시 워커 200개를 데이터베이스에 때려 넣으면 다른 워크로드가 영향을 받을 수 있음
반대로 이 방식은 현재 그렇게 동작하는 것 같지는 않지만, 왕복 지연 비용 없이 거의 실시간 성능 피드백을 받아 스스로 조절할 가능성이 있음
문서와 예제를 읽어도 몇 가지가 명확하지 않음. df.wait_for_schedule()는 어떻게 동작하는지 궁금함
애플리케이션에서 호출하면 멱등적인지, 같은 파라미터로 두 번 실행하면 틱이 두 번 발생하는지, 쿼리 콘솔에서 한 번만 수동으로 호출하는 것인지, 마이그레이션 스크립트 일부로 실행하는 것인지 모르겠음
예제[0]의 timed_out은 시간 초과 시 반환되는 고정 상수인지도 궁금함. 오류나 예외 처리는 어떻게 하는지도 바로 보이지 않음
[0] https://github.com/microsoft/pg_durable/blob/main/examples/i...
df.start()를 호출하면 내구성 함수를 만들고 동시에 실행을 시작함. 이 호출은 해당 실행을 나타내는 인스턴스 ID를 돌려주고, 이후 그 실행을 참조하는 데 쓸 수 있음
이 내구성 함수 안에서 df.wait_for_signal()을 호출하는데, 이 호출은 해당 함수 인스턴스 안에서 정확히 한 번만 실행되므로 중복은 불가능함. df.start() 호출 자체가 시간 초과되어 다시 실행되면 중복될 수 있지만, 그 경우에는 다른 함수 인스턴스가 만들어짐
SQL 실행 중 처리되지 않은 오류가 나면 함수 인스턴스는 실패하고, 상태에는 발생한 정확한 오류가 그대로 올라옴
데이터베이스 밖에 있는 오케스트레이션 도구 대신 이걸 왜 써야 하는지 설명해 줄 수 있을까. README와 예제를 읽어도 아직 이해가 안 됨
데이터베이스의 스냅샷 PITR을 쓰면 특정 시점의 내구성 작업까지 전부 함께 복원됨
같은 데이터 저장소에 속한 다른 구성요소와 백업을 동기화할 필요가 없어서 ETL 파이프라인이나 상태 기계형 작업에 좋음. ETL이 대부분 SQL이라면 실제 작업이 같은 서버에서 실행되는 것도 도움이 됨
기여자 입장에서 보면 Microsoft의 Postgres 고객은 꽤 균등하게 두 부류로 나뉨. 가능한 한 많은 걸 데이터베이스 안에서 하려는 쪽과, 애플리케이션과 연산을 데이터베이스 밖에 두고 싶어 하는 쪽임
아키텍처에서 데이터베이스가 유일한 상태 저장 구성요소라면 때때로 편리함
모든 상태가 한 데이터베이스에 있으면 일관된 백업을 얻을 가능성도 더 높음
애플리케이션 워크플로를 잘 통합할 수 있음. 예를 들어 프런트엔드 앱의 고정 링크에서 진행 상황을 보여 주는 식이 가능하고, 앱 재시작에도 이어서 실행되는 워크플로를 만들 수 있으며, 인프라 구성요소를 하나 더 추가하지 않아도 됨 https://transport.data.gouv.fr에서 Postgres를 그런 용도로 쓰고 있고, 꽤 많은 처리를 하는 Elixir 앱에서 도움이 됨. pg_durable은 아직 잘 모르지만 비슷한 해법을 쓰거나 구현해 본 적이 있어서 공감됨
데이터베이스는 이미 확장하기 가장 어려운 인프라 중 하나 아닌가. 왜 거기에 장시간 실행 작업까지 얹고 싶은지 모르겠음
Postgres에서 장시간 실행 작업을 돌리는 건 전혀 새로운 일이 아님. 예로 pg_cron이 있음
결국 이런 워크로드는 외부 구성요소가 트리거하든 아니든 데이터베이스를 상대로 실행될 작업임. 데이터나 AI 파이프라인에서 추가 구성요소로 인한 왕복과 실패 지점을 피하려고 데이터베이스에서 HTTP 쿼리를 보내는 방식도 더 흔해졌음. 다만 연산을 데이터 쪽으로 가져갈지, 데이터를 연산 쪽으로 가져갈지는 논쟁이 큰 설계 선택임
AI 자동 생성 콘텐츠
본 콘텐츠는 GeekNews의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기