# Elixir의 Job 처리 프레임워크 Oban이 파이썬으로 이식되다

> Clean Markdown view of GeekNews topic #26238. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=26238](https://news.hada.io/topic?id=26238)
- GeekNews Markdown: [https://news.hada.io/topic/26238.md](https://news.hada.io/topic/26238.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-01-30T08:33:40+09:00
- Updated: 2026-01-30T08:33:40+09:00
- Original source: [dimamik.com](https://www.dimamik.com/posts/oban_py/)
- Points: 3
- Comments: 1

## Topic Body

- **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)로 리더를 결정  
  - 별도 합의 프로토콜 없이 단일 리더가 **잡 정리·복구**를 담당  
- **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만으로 완전한 잡 큐를 구현한 **깔끔하고 구조적인 파이썬 포트**로, 엘릭서 사용자나 외부 인프라 없는 잡 시스템을 원하는 개발자에게 적합

## Comments



### Comment 50234

- Author: neo
- Created: 2026-01-30T08:33:40+09:00
- Points: 1

###### [Hacker News 의견들](https://news.ycombinator.com/item?id=46797594) 
- 나는 **Sidekiq**를 만든 사람으로, 이번에 Shannon과 Parker가 출시한 것을 축하함  
  예전에 나도 같은 고민을 했음 — Ruby에 집중할지, 아니면 Sidekiq를 다른 언어로 확장할지. 모든 언어의 전문가가 될 수 없다는 걸 깨닫고, 대신 **[Faktory](https://github.com/contribsys/faktory)** 를 만들었음. 이건 중앙 서버가 큐의 생명주기를 관리하고, 각 언어별 클라이언트는 단순하게 유지되는 구조임. 예를 들어 [faktory-rs](https://github.com/jonhoo/faktory-rs) 같은 클라이언트가 있음. 단점은 특정 언어 커뮤니티에 집중하지 않아서, 그 언어에 맞는 예시를 제공하기 어렵다는 점임.  
  한 커뮤니티에 집중하는 접근이 더 좋은 결과를 낼 수도 있을 것 같음. 시간이 말해줄 것임
  - 고마움, Mike! 당신은 진짜 **영감의 원천**임. Parker와 나는 서로 다른 강점을 가지고 있고, Python과 Elixir 간의 상호운용성에서 나오는 시너지를 믿고 있음
  - **Faktory**는 내가 만든 언어 비종속적 작업 큐 시스템 **[Ocypod](https://github.com/davechallis/ocypod)** 에 큰 영감을 줬음. 오픈소스로 공개해줘서 감사함
  - 사실 둘 다 **Resque** 기반이라고 하는 게 더 정확하지 않음?
  - 의도는 아니었겠지만, 네 댓글이 네 프로젝트를 홍보하려는 것처럼 보임. 이런 건 여기서 별로 좋게 안 봄
  - “based on”이라는 표현은 좀 과장된 것 같음. Sidekiq는 Oban이 지원하는 워크플로, 크론, 파티셔닝, 의존 작업, 실패 처리 등과 비교하면 훨씬 단순함

- **Oban**의 핵심은 데이터베이스만으로 작업을 삽입하고 처리할 수 있다는 점임. 사용자 생성 트랜잭션 안에서 이메일 전송 작업을 함께 넣고, 실패 시 전체가 롤백되는 구조임.  
  많은 사람들이 관계형 DB를 작업 큐로 쓰지 말라고 하지만, 트랜잭션의 중요성을 간과함. Brandur Leach의 글 [Job Drain](https://brandur.org/job-drain)에서도 이 개념을 잘 설명함
  - 이 말에 깊이 공감함. 예전에 **Dual Write Problem** 때문에 이벤트가 사라지는 걸 수년간 봤음. 결국 SQL 기반 접근으로 돌아오자 문제가 하루 만에 해결됨.  
    하지만 이제는 아무도 그 불편을 기억하지 못함. “트랜잭셔널 아웃박스 패턴”은 필수적이며, 나는 내 데이터와 같은 **ACID 보장**을 받는 방식을 선호함.  
    DB 내부를 몰라도, 격리 수준과 커밋 순서를 배우는 데 일주일 투자하면 분산 시스템 디버깅 1년을 절약할 수 있음
  - 이건 바로 **트랜잭셔널 아웃박스 패턴**이라고 부름
  - 나도 이 기능이 정말 멋지다고 생각함. 대신 나는 [pg_timetable](https://cybertec-postgresql.github.io/pg_timetable/v6.x/)을 사용 중임
  - 우리는 **AI 기반 앱 빌더**를 만들고 있고, Elixir, Phoenix, 그리고 당연히 OBAN을 사용함.  
    긴 AI 프로세스가 많은 시대에 이런 **내구성**은 필수임. 다른 언어 생태계에서는 이런 기능을 위해 돈을 내지만, Oban에서는 기본 제공임
  - 트랜잭션을 이런 식으로 생각해본 적이 없었는데, 정말 인상적임

- Oban 팀은 Elixir 생태계에서 **정교한 엔지니어링**으로 유명함. 하지만 프로 버전에서 프로세스 풀을 잠근 건 혼란스러움.  
  예를 들어 $135/월 요금제에는 멀티프로세스 실행, 워크플로, 글로벌 제한, 유니크 잡, 벌크 작업, 암호화 소스, 전용 지원 등이 포함됨.  
  내 프로젝트 [Chancy](https://github.com/tktech/chancy)는 완전 무료인데, asyncio, 프로세스, 스레드, 서브 인터프리터를 자유롭게 섞을 수 있음.  
  이런 기능을 OSS로 옮기고, 유료는 **엔터프라이즈 지원** 중심으로 가는 게 낫지 않을까 생각함. Python 생태계에는 경쟁자가 훨씬 많음
  - 관심과 사용량에 따라 일부 기능을 OSS로 옮길 수도 있음. Elixir에서도 그렇게 한 적이 있음.  
    단순히 지원만 판매하는 모델은 잘 안 맞았지만, Python에서는 다를 수도 있음.  
    Python 생태계에는 정말 **모든 게 많음**
  - 참고로 Django 6.0에는 **Django Tasks API**가 추가되어 백엔드 교체가 가능하지만, 실제 프로덕션용 백엔드는 아직 없음.  
    Chancy에 Django Tasks 지원을 추가하거나 `django-chancy` 패키지를 만들면 빠르게 채택될 것 같음
  - Chancy를 공유해줘서 고마움. 흥미로워 보임. API 변경 외에는 지금 프로덕션에서도 **안정적**으로 쓸 수 있을까?

- OSS Oban은 **단일 스레드 asyncio 실행**만 지원해서 CPU 바운드 작업이 이벤트 루프를 막음.  
  그래서 시도할 가치가 없다고 느꼈음. Celery 인터페이스는 별로지만 익숙하고, 수직·수평 확장이 무한히 가능함.  
  다만 여러 워커 노드를 띄울 수 있다는 걸 알고 나니 생각이 조금 바뀜

- OSS/Pro 기능 구분은 괜찮지만, “Pro 버전은 더 똑똑한 하트비트로 프로듀서 생존을 추적한다”는 건 아쉬움.  
  **신뢰성 관련 기능**이 유료라는 건 OSS 프로젝트에서 채택하기 어렵게 만듦
  - 나도 같은 느낌임. Oban은 멋지지만, “같은 기능의 더 나은 버전”이 유료인 건 아쉬움.  
    기본 버전이 최고여야 하고, 추가 기능이 유료여야 함. 경계가 좀 **이상한 위치**에 있는 듯함
  - Redis나 RabbitMQ 기반 큐는 예기치 않은 종료 후 작업을 잃을 수도 있음.  
    인용된 문장은 약간 부정확함 — 프로듀서 생존 추적은 동일하고, 차이는 **고아 작업 복구 방식**뿐임

- Python에서 BI/ML/DS 워크플로가 Elixir로 넘어왔으면 좋겠음.  
  **함수형·내결함성·동시성**이 높은 Elixir가 이런 작업에 훨씬 자연스러운 기반이라고 생각함
  - 동의함. **Claude Code**도 Elixir에서 잘 작동함.  
    [이 영상](https://youtu.be/iV1EcfZSdCM?si=KAJW26GVaBqZjR3M)과 [Elixir Genius 가이드](https://skills.sh/agoodway/.claude/elixir-genius)가 좋은 참고 자료임

- 우리 회사도 Celery를 쓰고 있는데, 그리 좋지는 않음. Temporal은 너무 무겁고, Oban은 가볍고 마음에 듦.  
  두 가지 모두 써본 사람의 비교가 궁금함
  - 두 도구는 **철학이 완전히 다름**.  
    Temporal은 워크플로 보장과 복잡성을 감수할 수 있는 조직(예: 은행)에 적합함.  
    Oban은 DB 기반 큐로, 신뢰성은 직접 강화해야 함.  
    나는 두 가지 모두 시스템에 함께 있으면 좋겠다고 생각함
  - 우리는 Celery에서 **Prefect**로 옮겼고 만족함. 수천 단위 작업 처리에는 완벽함.  
    단순한 ProcessWorker와 ECS 워커를 조합해 사용 중임
  - 나는 오랜만에 Python 웹 개발로 돌아왔는데, Celery에 대한 **불만**이 많아 놀랐음.  
    최근 Celery가 덜 안정적이거나 다루기 어려워졌는지 궁금함

- 흥미로운 프로젝트임. 다만 핵심 기능 일부가 Pro에만 있는 게 눈에 띔.  
  Postgres 기반 내구성 워크플로를 OSS로 구현한 선행 프로젝트로는 **[DBOS](https://news.ycombinator.com/item?id=44840693)** 와 **[Absurd](https://news.ycombinator.com/item?id=45797228)** 가 있음.  
  데이터베이스 중심 접근이 늘어나는 건 반가운 일임
  - Elixir에서도 비슷한 OSS 프로젝트가 있었고, Oban의 내구성 워크플로 구현은 DBOS보다 몇 년 앞섰음.  
    완전한 오픈소스 모델과 지원 판매만으로 운영하는 게 **꿈 같은 모델**임. 언젠가 가능하길 바람

- Postgres로 수억 개 작업을 처리할 만큼 **성능이 충분한가** 궁금함. 예전에 Redis + Sidekiq로 옮기며 큰 성능 향상을 봤음
  - 기간이 어느 정도인지 궁금함. 나는 Rails/Solid Queue + Postgres로 하루 2천만 작업을 $45 VM에서 처리 중이며 여유가 많음

- OSS 버전은 긴 작업이 있으면 프로듀서가 살아 있어도 잘못 복구될 수 있다고 함.  
  그럼 짧은 작업만 써야 하는 건가?
  - 작업 길이에 제한은 없음. 차이는 **충돌 후 복구 속도**뿐임.  
    정상 종료를 기다리지 못한 경우에만 복구 타이밍이 달라짐
