개요

Oban은 데이터베이스 기반 Job 큐/백그라운드 작업 처리 프레임워크입니다. 원래 Elixir용으로 개발되었으며, 2025년 Python 포팅(Oban.py)도 출시되었습니다. Redis 같은 외부 브로커 없이 PostgreSQL만으로 작업 큐잉, 스케줄링, 리더 선출까지 처리하는 것이 핵심 설계입니다.

핵심 설계

데이터베이스가 곧 브로커

기존 방식                     Oban 방식
─────────                     ──────────
App → Redis/RabbitMQ → Worker  App → PostgreSQL → Worker
      (외부 브로커 필요)              (DB가 브로커 역할)
  • 트랜잭션 무결성: Job 삽입과 비즈니스 로직이 같은 DB 트랜잭션 → 실패 시 전체 롤백
  • 외부 의존성 제로: Redis, RabbitMQ, SQS 불필요
  • PostgreSQL 기능 활용: FOR UPDATE SKIP LOCKED (동시 충돌 방지), LISTEN/NOTIFY (실시간 알림)

내부 워크플로우

Insert → Notify → Fetch → Execute → Ack
  │        │        │        │        │
  │   LISTEN/    FOR UPDATE  워커가   완료/실패
  │   NOTIFY     SKIP LOCKED 실행    상태 기록
  └── DB 트랜잭션 내 삽입

주요 기능

기능설명
큐 관리명명된 큐, 우선순위, 동시성 제한
Cron 스케줄링주기적 작업 (crontab 문법)
재시도자동 재시도, 백오프 전략, 최대 시도 횟수
결과 저장Job 실행 결과를 DB에 저장
고유성 보장중복 Job 방지 (기간/상태/키 기반)
리더 선출PostgreSQL INSERT ... ON CONFLICT + TTL 리스
Lifeline타임아웃 후 방치된 Job 자동 복구
Pruner오래된 완료/취소 Job 자동 삭제

Oban (Elixir)

# 워커 정의
defmodule MyApp.Workers.EmailWorker do
  use Oban.Worker, queue: :mailers, max_attempts: 3
 
  @impl Oban.Worker
  def perform(%Oban.Job{args: %{"email" => email}}) do
    MyApp.Mailer.send(email)
    :ok
  end
end
 
# Job 삽입 (트랜잭션 내)
Ecto.Multi.new()
|> Ecto.Multi.insert(:user, user_changeset)
|> Oban.insert(:email, EmailWorker.new(%{email: user.email}))
|> Repo.transaction()
 
# config.exs
config :my_app, Oban,
  repo: MyApp.Repo,
  queues: [default: 10, mailers: 5, events: 25],
  plugins: [
    {Oban.Plugins.Pruner, max_age: 60 * 60 * 24 * 7},
    {Oban.Plugins.Cron, crontab: [
      {"0 * * * *", MyApp.Workers.HourlyWorker},
      {"0 0 * * *", MyApp.Workers.DailyWorker}
    ]}
  ]

Oban.py (Python)

from oban import Oban, Worker, job, cron
 
# 워커 정의
@job(queue="mailers", max_attempts=3)
async def send_email(email: str):
    await mailer.send(email)
    return {"status": "sent"}
 
# Job 삽입
await send_email.insert(email="user@example.com")
 
# Cron 스케줄링
@cron("0 * * * *")
async def hourly_cleanup():
    await db.cleanup_old_records()

OSS vs Pro:

항목OSS (무료)Pro (유료)
실행 모드단일 스레드 asyncio병렬 처리
큐 관리기본고급 (동적 큐, 속도 제한)
워크플로우XO (Job 체이닝/팬아웃)
배치 처리XO
모니터링기본Oban Web (대시보드)

Oban vs 경쟁 도구

항목ObanCelerySidekiqBullMQTemporal
언어Elixir, PythonPythonRubyNode.js다국어
브로커PostgreSQLRedis/RabbitMQRedisRedisPostgreSQL/Cassandra
외부 의존성없음Redis 필수Redis 필수Redis 필수서버 필수
트랜잭션 무결성OXXXO
스케줄링Cron 내장Celery Beatsidekiq-cron내장내장
워크플로우Pro 버전Canvas제한적제한적최강
대시보드Web (Pro)FlowerWeb UIBull BoardWeb UI
적합 규모소~대중~대중~대소~중대규모

왜 Oban인가

  • 이미 PostgreSQL 쓰고 있다면: 인프라 추가 없이 바로 Job 큐 사용
  • 트랜잭션 무결성: “사용자 생성 + 이메일 발송”이 하나의 트랜잭션 → 실패 시 둘 다 롤백
  • 운영 단순: Redis 클러스터 관리, 브로커 모니터링 불필요
  • Elixir/BEAM: OTP Supervisor와 자연스러운 통합

주의점

  • PostgreSQL에 부하 집중 (대규모 시 DB 병목 가능)
  • OSS 버전의 단일 스레드 제한 (CPU-bound 작업 시 Pro 필요)
  • Pro 버전에 핵심 안정성 기능 일부 포함 (커뮤니티 논란)

사용 사례

용도예시
이메일/알림회원가입 후 환영 이메일, 비밀번호 재설정
데이터 처리CSV 임포트, 리포트 생성, ETL
외부 API 호출결제 처리, 웹훅 전송
정기 작업데이터 정리, 통계 집계, 구독 갱신
미디어 처리이미지 리사이즈, 동영상 트랜스코딩

관련 항목