전 포스트에서는 장고에서 email 전송을 간단하게 하는 법에 대해 작성했습니다.
마지막에 작성한 것 처럼 간단하게 작성된 부분이라 api의 response time이 5초 정도 걸린다는 엄청난 문제점을 가지고 있습니다.
그렇기에 이번 포스트에서는 redis와 celery를 활용하여 이런 문제점을 해결해보겠습니다.
이메일 등과 같이 응답시간이 오래 걸리는 기능을 동기로 처리하는 것은 서비스의 엄청난 결격 사유가 될 수 있습니다. 오래 걸리는 작업을 비동기로 작업할 수 있게 해주는 파이썬 프레임워크입니다.
redis에 대한 설명은 이번 포스트에서 중요한 내용이 아니기 때문에 이번 포스트에서는 설명하지 않겠습니다.
레디스의 특징 중 redis-server를 쓸 수 있는 점이 있습니다. 이번 포스트에서는 그 server를 활용하려고 합니다.
저는 mac에서 작업을 했기 때문에 mac 기준으로 작성하겠습니다.
(추후 시간이 되면 window 버전도 추가하겠습니다...)
$ brew update
$ brew install redis
## redis start
$ brew services start redis
## redis stop
$ brew services stop redis
## redis background service (아래 이미지 처럼 나오면 됩니다.)
$ redis-server /usr/local/etc/redis.conf
## redis-server 확인 법
## pong 이 나오면 제대로 된 것입니다.
$ redis-cli ping
celery 설치 (가상환경을 세팅했으면 실수 하지말고 들어가셔서 설치해주세요.)
pip install celery
## 하는 김에 rediseh 설치하겠습니다.
pip install redis
메인 app 위치에 celery.py 파일을 생성합니다.
touch api_server/celery.py
아래 내용을 celery.py에 작성합니다.
## api_server/celery.py
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'api_server.settings')
app = Celery('api_server',backend='redis://', broker='redis://localhost:6379/0')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print("Request: {0!r}".format(self.request))
settings.py에 아래 내용을 추가합니다.
BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = TIME_ZONE
동일 디렉토리에 있는 __init__.py에 아래 내용을 작성합니다.
from __future__ import absolute_import
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app
__all__ = ('celery_app',)
celery 설정을 끝냈으니 이메일 전송을 celery 작업으로 할 수 있도록 코드를 수정하겠습니다.
task.py 생성
celery로 작업할 내용을 빼놓기 위해 testapi 디렉토리에 task.py 생성 후 아래 코드를 작성하겠습니다.
## testapi/task.py
from __future__ import absolute_import, unicode_literals
from celery import shared_task
from django.core.mail.message import EmailMessage
from api_server import settings
FROM_EMAIL = settings.EMAIL_HOST_USER
@shared_task
def send_email():
subject = "이메일 테스트3"
to = ['lemontech119@gmail.com']
message = "email test가 성공했습니다."
EmailMessage(subject=subject, body=message, to=to, from_email=FROM_EMAIL).send()
return True
views.py 수정
이메일 전송을 task.py로 분리했기 때문에 views.py의 코드도 수정하겠습니다.
## testapi/views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from .task import send_email
@api_view(['GET'])
@permission_classes([AllowAny])
def send_test_email(requset):
send_email.delay()
return Response({"message": "ok"})
api_server 자리에는 메인프로젝트 name을 써주시면 됩니다.
위의 사진처럼 response time이 1초 이내이며 메일이 전송이 되었다면 Test가 정상적으로 된 것입니다.
해당 시리즈에서 작업한 코드는 github에 업로드가 되어 있습니다.
부족한 점이나 잘못된 점이 있으면 댓글에 적어주시면 감사하겠습니다.
안녕하세요, 덕분에 drf에 대해 많이 배우고 있습니다.
오타가 하나 있는데, 정정하시면 좋을 것 같아 남겨봅니다.
하는 김에 rediseh 설치하겠습니다.
->
하는 김에 redis도 설치하겠습니다.