무거운 작업은 비동기로! Celery와 Redis 연동하기

웹 애플리케이션에서 이메일 발송, 데이터 분석, 파일 처리 등 시간이 오래 걸리는 작업을 비동기로 처리하여 사용자 경험과 서버 성능을 향상시키는 방법

왜 비동기 처리가 필요한가

동기 처리의 문제점

  • 작업이 끝날 때까지 사용자 대기 시간 증가

  • 여러 사용자가 동시에 무거운 요청을 보낼 때 서버 병목 발생

  • 타임아웃으로 인한 요청 실패 가능성

비동기 처리의 장점

  • 즉각적인 응답으로 향상된 사용자 경험

  • 웹 서버 자원의 효율적 사용

  • 작업 실패가 전체 서비스에 미치는 영향 최소화

Celery와 Redis 아키텍처

핵심 구성 요소

  • Task Queue: 처리할 작업들의 대기열

  • Message Broker (Redis): 작업 메시지를 전달하는 중간 관리자

  • Celery Worker: 작업을 실행하는 백그라운드 프로세스

Django 프로젝트 연동 설정

라이브러리 설치

pip install "celery[redis]"

Celery 설정 파일 생성 (myproject/celery.py)

import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
app = Celery('myproject')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

프로젝트 초기화 (myproject/init.py)

from .celery import app as celery_app
__all__ = ('celery_app',)

Django 설정 (settings.py)

CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
CELERY_TASK_SERIALIZER = 'json'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Seoul'

비동기 작업 생성 및 실행

작업 정의 (users/tasks.py)

from celery import shared_task
from django.core.mail import send_mail

@shared_task
def send_welcome_email(user_pk):
    user = User.objects.get(pk=user_pk)
    send_mail(
        subject=f"환영합니다, {user.username}님!",
        message="가입해 주셔서 감사합니다",
        from_email="[email protected]",
        recipient_list=[user.email]
    )

View에서 작업 호출

def post(self, request):
    user = serializer.save()
    send_welcome_email.delay(user.pk)  # 비동기 실행
    return Response({"message": "회원가입 완료"})

Celery 실행 및 모니터링

워커 실행

celery -A myproject worker -l info

Flower 모니터링 도구

pip install flower
celery -A myproject flower --broker=redis://localhost:6379/0

실무 팁

멱등성 유지

  • 작업이 여러 번 실행되어도 같은 결과가 나오도록 설계

작업 분리

  • 하나의 작업은 작고 빠르게, 큰 작업은 여러 개로 분리

우선순위 큐 활용

  • 긴급한 작업과 배치 작업을 별도 큐로 분리

에러 처리

  • 재시도 로직과 Dead Letter Queue 구성으로 안정성 확보

Last updated