Celery Beat & 비동기 스케줄링

HY_1023·2026년 4월 1일

헷갈리는 부분 정리

목록 보기
34/40

Celery Beat & 비동기 스케줄링

Celery Beat는 Celery의 주기적 태스크 스케줄러로, 정해진 간격이나 crontab 스케줄에 따라 태스크를 자동으로 실행합니다.

기본 구조

Celery Beat는 크게 세 가지 요소로 구성됩니다.

Beat Scheduler — 주기적으로 태스크를 큐에 넣는 프로세스입니다. 단일 인스턴스로만 실행해야 중복 실행을 방지할 수 있습니다.

Worker — 큐에서 태스크를 꺼내 비동기로 실행하는 프로세스입니다. 여러 인스턴스를 띄울 수 있습니다.

Broker — Redis나 RabbitMQ 같은 메시지 브로커가 둘 사이를 연결합니다.

스케줄 설정 방법

# celery.py
from celery import Celery
from celery.schedules import crontab

app = Celery('myapp', broker='redis://localhost:6379/0')

# 방법 1: beat_schedule 설정
app.conf.beat_schedule = {
    # 매 30초마다 실행
    'check-every-30s': {
        'task': 'tasks.check_status',
        'schedule': 30.0,  # 초 단위
    },
    # crontab으로 매일 오전 7시 30분 실행
    'morning-report': {
        'task': 'tasks.send_report',
        'schedule': crontab(hour=7, minute=30),
        'args': ('daily',),
    },
    # 매주 월요일 오전 9시
    'weekly-cleanup': {
        'task': 'tasks.cleanup',
        'schedule': crontab(hour=9, minute=0, day_of_week=1),
    },
}

app.conf.timezone = 'Asia/Seoul'

태스크 정의

# tasks.py
from celery import shared_task

@shared_task
def check_status():
    # 비동기로 실행될 로직
    return "checked"

@shared_task(bind=True, max_retries=3)
def send_report(self, report_type):
    try:
        # 실패 시 자동 재시도
        generate_and_send(report_type)
    except Exception as exc:
        raise self.retry(exc=exc, countdown=60)

주요 스케줄 타입

from celery.schedules import crontab, solar
from datetime import timedelta

# 1) 고정 간격 (timedelta)
'schedule': timedelta(minutes=5)

# 2) crontab 표현식
'schedule': crontab(minute='*/15')          # 매 15분
'schedule': crontab(hour='9-17', minute=0)  # 업무 시간 매 정시
'schedule': crontab(0, 0, day_of_month='1') # 매월 1일 자정

# 3) solar (일출/일몰 기반 - 특수 용도)
'schedule': solar('sunset', -37.81, 144.96)

실행 명령어

# Worker 실행
celery -A myapp worker --loglevel=info

# Beat 실행 (별도 프로세스)
celery -A myapp beat --loglevel=info

# Worker + Beat 동시 실행 (개발용, 프로덕션 비권장)
celery -A myapp worker --beat --loglevel=info

Django와 함께 사용할 때

Django를 쓴다면 django-celery-beat 패키지를 활용하면 Admin 페이지에서 스케줄을 동적으로 관리할 수 있습니다.

# settings.py
CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

이렇게 하면 DB에 스케줄이 저장되어 서버 재시작 없이 스케줄을 추가/수정/삭제할 수 있습니다.

주의할 점

  • Beat 프로세스는 반드시 하나만 실행해야 합니다. 여러 개 띄우면 태스크가 중복 실행됩니다.
  • 태스크가 스케줄 간격보다 오래 걸리면 중첩 실행될 수 있으므로, 필요하다면 분산 락(Redis Lock 등)을 사용하세요.
  • timezone 설정을 명시하지 않으면 UTC 기준으로 동작합니다.

더 구체적인 부분(예: 동적 스케줄 관리, 태스크 체이닝, 에러 핸들링 등)에 대해 궁금한 점이 있으면 알려주세요.

profile
개발언어를 배우는 과정 기록

0개의 댓글