Elixir의 Job 처리 프레임워크 Oban이 파이썬으로 이식되다
(dimamik.com)- Oban.py는 엘릭서의 잡 처리 프레임워크 Oban을 PostgreSQL 기반으로 파이썬에 이식한 버전으로, 데이터베이스만으로 잡을 삽입하고 처리할 수 있음
- 잡은 데이터베이스 트랜잭션 내에서 생성·롤백되며, 큐 관리·결과 저장·크론 스케줄링 등 다양한 기능을 지원
- 오픈소스 버전은 단일 스레드 asyncio 실행과 개별 삽입·확인 처리 등 제약이 있으나, Pro 버전은 병렬 처리·워크플로·스마트 동시성을 제공
- 내부 동작은
Insert → Notify → Fetch → Execute → Ack의 다섯 단계로 구성되며, PostgreSQL의 FOR UPDATE SKIP LOCKED를 활용해 동시성 충돌을 방지 - 리더 선출, 고아 잡 복구, 백오프 재시도 등도 데이터베이스 기반으로 수행되어 외부 브로커 없이 안정적 분산 처리를 가능하게 함
Oban.py 개요
-
Oban.py는 엘릭서의 Oban을 파이썬으로 포팅한 데이터베이스 기반 잡 처리 프레임워크
- 잡을 데이터베이스 트랜잭션 내에서 삽입·처리하며, 실패 시 전체 트랜잭션이 롤백됨
- 큐 제한, 완료 잡 저장, 결과 유지, 크론 스케줄링 등 다양한 제어 기능을 포함
- 두 가지 버전 제공
- 오픈소스(OSS) : 단일 스레드 asyncio 실행, 개별 삽입·확인, 단순 복구
- Pro 버전: 프로세스 풀 기반 병렬 처리, 워크플로·릴레이·유니크 잡·스마트 동시성 지원
- OSS는 개인 프로젝트나 평가용으로 적합하며, 대규모 환경에는 Pro 버전 권장
잡 처리 경로
- 잡 삽입 후
oban_jobs테이블에state='available'로 저장되고, PostgreSQL의 NOTIFY로 각 노드에 알림 전송 - 각 노드의 Stager가 해당 큐를 감지해 Producer를 깨우고, Producer는 잡을 가져와 실행
- 잡 선택 시 SQL의
FOR UPDATE SKIP LOCKED를 사용해 중복 실행 없이 병렬 처리 가능- 이미 잠긴 행은 건너뛰어 다른 프로듀서가 다른 잡을 즉시 가져올 수 있음
- 잡은 async task로 디스패치되며, 완료 시 콜백으로 acknowledgement 처리
- Pro 버전은 asyncio 대신 프로세스 풀 디스패처를 사용해 다중 코어 병렬 실행 지원
백그라운드 프로세스
-
리더 선출(Leader Election)
- PostgreSQL의
INSERT ... ON CONFLICT와 TTL 기반 임대(lease)로 리더를 결정 - 별도 합의 프로토콜 없이 단일 리더가 잡 정리·복구를 담당
- PostgreSQL의
-
Lifeline(고아 잡 복구)
- 실행 중인 잡이 일정 시간(
rescue_after, 기본 5분) 이상 지속되면 available 상태로 복구 - Pro 버전은 프로듀서 생존 여부를 확인하지만, OSS는 시간 기반으로만 판단
- 실행 중인 잡이 일정 시간(
-
Pruner(잡 정리)
- 완료·취소·폐기된 잡 중
max_age(기본 1일) 이상 지난 항목을 삭제 -
LIMIT으로 삭제 범위를 제한해 데이터베이스 부하 방지
- 완료·취소·폐기된 잡 중
재시도 및 백오프
- 잡이 예외를 발생시키면 Executor가 재시도 여부를 결정
- 최대 시도 횟수(
max_attempts) 미만이면 재시도, 초과 시 폐기
- 최대 시도 횟수(
- 기본 백오프는 지터(jitter) 가 포함된 지수형 증가
- 대량 실패 시 동시 재시도를 방지해 부하 급증(Thundering Herd) 완화
- 예: 1회차 약 17초, 5회차 약 47초, 10회차 약 17분 대기
- 워커 클래스는
backoff()메서드로 사용자 정의 백오프 로직 구현 가능
주요 특징 및 평가
-
PostgreSQL이 핵심 역할 수행
-
FOR UPDATE SKIP LOCKED,LISTEN/NOTIFY,ON CONFLICT를 통해 동시성 제어·신호 전달·리더 선출을 모두 처리 - Redis나 외부 브로커 없이 단일 데이터베이스로 조정 계층 구성
-
-
비병렬적이지만 동시성 지원
- asyncio 기반으로 I/O 바운드 작업에 적합, CPU 바운드 작업은 Pro 버전 권장
-
코드 구조 명확성
- 일관된 네이밍과 분리된 책임 구조로 읽기 쉬운 코드베이스
-
OSS와 Pro의 역할 분리 명확
- OSS는 실험·소규모용, Pro는 대규모·고성능 환경용
- 결론: PostgreSQL만으로 완전한 잡 큐를 구현한 깔끔하고 구조적인 파이썬 포트로, 엘릭서 사용자나 외부 인프라 없는 잡 시스템을 원하는 개발자에게 적합
Hacker News 의견들
-
나는 Sidekiq를 만든 사람으로, 이번에 Shannon과 Parker가 출시한 것을 축하함
예전에 나도 같은 고민을 했음 — Ruby에 집중할지, 아니면 Sidekiq를 다른 언어로 확장할지. 모든 언어의 전문가가 될 수 없다는 걸 깨닫고, 대신 Faktory 를 만들었음. 이건 중앙 서버가 큐의 생명주기를 관리하고, 각 언어별 클라이언트는 단순하게 유지되는 구조임. 예를 들어 faktory-rs 같은 클라이언트가 있음. 단점은 특정 언어 커뮤니티에 집중하지 않아서, 그 언어에 맞는 예시를 제공하기 어렵다는 점임.
한 커뮤니티에 집중하는 접근이 더 좋은 결과를 낼 수도 있을 것 같음. 시간이 말해줄 것임- 고마움, Mike! 당신은 진짜 영감의 원천임. Parker와 나는 서로 다른 강점을 가지고 있고, Python과 Elixir 간의 상호운용성에서 나오는 시너지를 믿고 있음
- Faktory는 내가 만든 언어 비종속적 작업 큐 시스템 Ocypod 에 큰 영감을 줬음. 오픈소스로 공개해줘서 감사함
- 사실 둘 다 Resque 기반이라고 하는 게 더 정확하지 않음?
- 의도는 아니었겠지만, 네 댓글이 네 프로젝트를 홍보하려는 것처럼 보임. 이런 건 여기서 별로 좋게 안 봄
- “based on”이라는 표현은 좀 과장된 것 같음. Sidekiq는 Oban이 지원하는 워크플로, 크론, 파티셔닝, 의존 작업, 실패 처리 등과 비교하면 훨씬 단순함
-
Oban의 핵심은 데이터베이스만으로 작업을 삽입하고 처리할 수 있다는 점임. 사용자 생성 트랜잭션 안에서 이메일 전송 작업을 함께 넣고, 실패 시 전체가 롤백되는 구조임.
많은 사람들이 관계형 DB를 작업 큐로 쓰지 말라고 하지만, 트랜잭션의 중요성을 간과함. Brandur Leach의 글 Job Drain에서도 이 개념을 잘 설명함- 이 말에 깊이 공감함. 예전에 Dual Write Problem 때문에 이벤트가 사라지는 걸 수년간 봤음. 결국 SQL 기반 접근으로 돌아오자 문제가 하루 만에 해결됨.
하지만 이제는 아무도 그 불편을 기억하지 못함. “트랜잭셔널 아웃박스 패턴”은 필수적이며, 나는 내 데이터와 같은 ACID 보장을 받는 방식을 선호함.
DB 내부를 몰라도, 격리 수준과 커밋 순서를 배우는 데 일주일 투자하면 분산 시스템 디버깅 1년을 절약할 수 있음 - 이건 바로 트랜잭셔널 아웃박스 패턴이라고 부름
- 나도 이 기능이 정말 멋지다고 생각함. 대신 나는 pg_timetable을 사용 중임
- 우리는 AI 기반 앱 빌더를 만들고 있고, Elixir, Phoenix, 그리고 당연히 OBAN을 사용함.
긴 AI 프로세스가 많은 시대에 이런 내구성은 필수임. 다른 언어 생태계에서는 이런 기능을 위해 돈을 내지만, Oban에서는 기본 제공임 - 트랜잭션을 이런 식으로 생각해본 적이 없었는데, 정말 인상적임
- 이 말에 깊이 공감함. 예전에 Dual Write Problem 때문에 이벤트가 사라지는 걸 수년간 봤음. 결국 SQL 기반 접근으로 돌아오자 문제가 하루 만에 해결됨.
-
Oban 팀은 Elixir 생태계에서 정교한 엔지니어링으로 유명함. 하지만 프로 버전에서 프로세스 풀을 잠근 건 혼란스러움.
예를 들어 $135/월 요금제에는 멀티프로세스 실행, 워크플로, 글로벌 제한, 유니크 잡, 벌크 작업, 암호화 소스, 전용 지원 등이 포함됨.
내 프로젝트 Chancy는 완전 무료인데, asyncio, 프로세스, 스레드, 서브 인터프리터를 자유롭게 섞을 수 있음.
이런 기능을 OSS로 옮기고, 유료는 엔터프라이즈 지원 중심으로 가는 게 낫지 않을까 생각함. Python 생태계에는 경쟁자가 훨씬 많음- 관심과 사용량에 따라 일부 기능을 OSS로 옮길 수도 있음. Elixir에서도 그렇게 한 적이 있음.
단순히 지원만 판매하는 모델은 잘 안 맞았지만, Python에서는 다를 수도 있음.
Python 생태계에는 정말 모든 게 많음 - 참고로 Django 6.0에는 Django Tasks API가 추가되어 백엔드 교체가 가능하지만, 실제 프로덕션용 백엔드는 아직 없음.
Chancy에 Django Tasks 지원을 추가하거나django-chancy패키지를 만들면 빠르게 채택될 것 같음 - Chancy를 공유해줘서 고마움. 흥미로워 보임. API 변경 외에는 지금 프로덕션에서도 안정적으로 쓸 수 있을까?
- 관심과 사용량에 따라 일부 기능을 OSS로 옮길 수도 있음. Elixir에서도 그렇게 한 적이 있음.
-
OSS Oban은 단일 스레드 asyncio 실행만 지원해서 CPU 바운드 작업이 이벤트 루프를 막음.
그래서 시도할 가치가 없다고 느꼈음. Celery 인터페이스는 별로지만 익숙하고, 수직·수평 확장이 무한히 가능함.
다만 여러 워커 노드를 띄울 수 있다는 걸 알고 나니 생각이 조금 바뀜 -
OSS/Pro 기능 구분은 괜찮지만, “Pro 버전은 더 똑똑한 하트비트로 프로듀서 생존을 추적한다”는 건 아쉬움.
신뢰성 관련 기능이 유료라는 건 OSS 프로젝트에서 채택하기 어렵게 만듦- 나도 같은 느낌임. Oban은 멋지지만, “같은 기능의 더 나은 버전”이 유료인 건 아쉬움.
기본 버전이 최고여야 하고, 추가 기능이 유료여야 함. 경계가 좀 이상한 위치에 있는 듯함 - Redis나 RabbitMQ 기반 큐는 예기치 않은 종료 후 작업을 잃을 수도 있음.
인용된 문장은 약간 부정확함 — 프로듀서 생존 추적은 동일하고, 차이는 고아 작업 복구 방식뿐임
- 나도 같은 느낌임. Oban은 멋지지만, “같은 기능의 더 나은 버전”이 유료인 건 아쉬움.
-
Python에서 BI/ML/DS 워크플로가 Elixir로 넘어왔으면 좋겠음.
함수형·내결함성·동시성이 높은 Elixir가 이런 작업에 훨씬 자연스러운 기반이라고 생각함- 동의함. Claude Code도 Elixir에서 잘 작동함.
이 영상과 Elixir Genius 가이드가 좋은 참고 자료임
- 동의함. Claude Code도 Elixir에서 잘 작동함.
-
우리 회사도 Celery를 쓰고 있는데, 그리 좋지는 않음. Temporal은 너무 무겁고, Oban은 가볍고 마음에 듦.
두 가지 모두 써본 사람의 비교가 궁금함- 두 도구는 철학이 완전히 다름.
Temporal은 워크플로 보장과 복잡성을 감수할 수 있는 조직(예: 은행)에 적합함.
Oban은 DB 기반 큐로, 신뢰성은 직접 강화해야 함.
나는 두 가지 모두 시스템에 함께 있으면 좋겠다고 생각함 - 우리는 Celery에서 Prefect로 옮겼고 만족함. 수천 단위 작업 처리에는 완벽함.
단순한 ProcessWorker와 ECS 워커를 조합해 사용 중임 - 나는 오랜만에 Python 웹 개발로 돌아왔는데, Celery에 대한 불만이 많아 놀랐음.
최근 Celery가 덜 안정적이거나 다루기 어려워졌는지 궁금함
- 두 도구는 철학이 완전히 다름.
-
흥미로운 프로젝트임. 다만 핵심 기능 일부가 Pro에만 있는 게 눈에 띔.
Postgres 기반 내구성 워크플로를 OSS로 구현한 선행 프로젝트로는 DBOS 와 Absurd 가 있음.
데이터베이스 중심 접근이 늘어나는 건 반가운 일임- Elixir에서도 비슷한 OSS 프로젝트가 있었고, Oban의 내구성 워크플로 구현은 DBOS보다 몇 년 앞섰음.
완전한 오픈소스 모델과 지원 판매만으로 운영하는 게 꿈 같은 모델임. 언젠가 가능하길 바람
- Elixir에서도 비슷한 OSS 프로젝트가 있었고, Oban의 내구성 워크플로 구현은 DBOS보다 몇 년 앞섰음.
-
Postgres로 수억 개 작업을 처리할 만큼 성능이 충분한가 궁금함. 예전에 Redis + Sidekiq로 옮기며 큰 성능 향상을 봤음
- 기간이 어느 정도인지 궁금함. 나는 Rails/Solid Queue + Postgres로 하루 2천만 작업을 $45 VM에서 처리 중이며 여유가 많음
-
OSS 버전은 긴 작업이 있으면 프로듀서가 살아 있어도 잘못 복구될 수 있다고 함.
그럼 짧은 작업만 써야 하는 건가?- 작업 길이에 제한은 없음. 차이는 충돌 후 복구 속도뿐임.
정상 종료를 기다리지 못한 경우에만 복구 타이밍이 달라짐
- 작업 길이에 제한은 없음. 차이는 충돌 후 복구 속도뿐임.