Celery는 비동기 작업 처리를 지원하는 강력한 프레임워크입니다. @shared_task
데코레이터는 작업(Task)을 정의하는 데 사용되며, 특히 옵션인 bind
, autoretry_for
, retry_backoff
, max_retries
를 활용하면 작업의 안정성과 자동화된 오류 처리를 크게 향상시킬 수 있습니다.
이번 글에서는 각 옵션의 동작 방식과 활용법을 살펴보며, 자주 발생하는 혼동과 함께 이를 해결하는 최선의 방법을 소개합니다.
1. bind=True
정의
bind=True
는 현재 작업(Task)을 첫 번째 매개변수로 전달하여 작업 내부에서 self
를 사용할 수 있도록 합니다. 이를 통해 작업의 상태, 메서드, 속성 등에 접근할 수 있습니다.
주요 기능
- 작업 상태에 접근 가능: 작업 ID, 요청 정보 등에 접근하여 상태를 확인하거나 로깅할 수 있습니다.
- 명시적 재시도 로직:
self.retry()
메서드를 통해 재시도 로직을 수동으로 구현할 수 있습니다.
예시
@shared_task(bind=True)
def my_task(self, some_arg):
print(f"Task ID: {self.request.id}") # 작업 ID 출력
self.retry() # 작업 재시도
2. autoretry_for=(ExceptionType, ...)
정의
지정된 예외 유형이 발생했을 때, Celery가 작업을 자동으로 재시도(retry)하도록 설정합니다. 개발자가 self.retry()
를 명시적으로 호출하지 않아도 예외를 처리하고 재시도를 자동화합니다.
주의점
autoretry_for
를 사용하는 경우: 재시도가 자동으로 이루어지므로self.retry()
와 중복되지 않도록 사용해야 합니다.- 혼용 시 문제점:
autoretry_for
와self.retry()
를 동시에 사용하면 동일한 예외에 대해 중복 재시도가 발생할 수 있습니다.
예시
권장 방식: autoretry_for
만 사용하는 경우
import requests
@shared_task(bind=True, autoretry_for=(requests.RequestException,), retry_backoff=True)
def my_task(self, url):
response = requests.get(url)
response.raise_for_status() # 상태 코드가 200이 아니면 예외 발생
특정 조건에서만 명시적으로 재시도 (self.retry()
)를 사용하는 경우
import requests
@shared_task(bind=True, retry_backoff=True, max_retries=5)
def my_task(self, url):
try:
response = requests.get(url)
response.raise_for_status()
except requests.RequestException as e:
print(f"Retrying due to error: {e}")
self.retry(exc=e) # 명시적 재시도
3. retry_backoff=True
정의
작업 재시도 간격을 점진적으로 증가시키는 지수 백오프(Exponential Backoff)를 활성화합니다. 첫 번째 재시도는 즉시, 이후 재시도는 1초, 2초, 4초...와 같이 간격이 증가합니다.
주요 기능
- 서버 부하를 줄이고 네트워크 장애를 효율적으로 처리.
- 백오프 시간은 Celery의 기본 설정을 통해 커스터마이징 가능.
예시
@shared_task(bind=True, autoretry_for=(requests.RequestException,), retry_backoff=True)
def my_task(self):
# 첫 번째 재시도는 1초 후, 두 번째 재시도는 2초 후...
raise requests.RequestException("Simulated failure")
4. max_retries
정의
작업의 최대 재시도 횟수를 제한합니다. 작업이 지정된 횟수만큼 재시도한 후에도 성공하지 못하면, 작업은 실패로 기록됩니다.
주요 기능
- 무한 재시도를 방지하여 서버 자원 소모를 제한.
- 실패 조건에 따라 작업을 기록하거나 다른 로직을 실행 가능.
예시
@shared_task(bind=True, autoretry_for=(requests.RequestException,), retry_backoff=True, max_retries=5)
def my_task(self):
raise requests.RequestException("Simulated failure")
5. 혼용 시 주의사항: autoretry_for
vs self.retry()
올바른 사용 가이드
autoretry_for
사용 시: 자동 재시도가 설정되므로,self.retry()
를 명시적으로 호출하지 않아도 됩니다. 단순히 특정 예외에 대해 작업을 재시도할 때 간결한 코드를 작성할 수 있습니다.self.retry()
사용 시: 재시도 전 추가 작업(예: 로그 작성, 특정 조건 검사)이 필요할 때 사용합니다.autoretry_for
와 중복되지 않도록 주의하세요.
6. 옵션 요약
옵션 | 설명 |
---|---|
bind=True |
작업에서 self 를 통해 작업 상태와 메서드에 접근 가능. |
autoretry_for |
특정 예외가 발생했을 때 작업을 자동으로 재시도. |
retry_backoff |
재시도 간격을 점진적으로 증가시키는 지수 백오프(Exponential Backoff) 활성화. |
max_retries |
최대 재시도 횟수를 제한하여 작업 실패 조건 정의. |

7. 결론
Celery의 @shared_task
옵션은 작업 실패를 효과적으로 처리하고 안정성을 높이는 데 유용합니다.
autoretry_for
를 사용하는 경우: 재시도 로직이 자동화되므로,self.retry()
와 중복되지 않도록 주의하세요.- 조건부 로직이나 추가 작업이 필요하다면
self.retry()
를 활용할 수 있습니다.
Celery를 활용한 작업을 안정적으로 구현하려면 이러한 옵션을 조합하여 상황에 맞게 최적화된 코드를 작성해보세요! 😊
Add a New Comment