Django 신호(Signal)는 특정 이벤트가 발생했을 때 추가적인 로직을 실행할 수 있게 해주는 강력한 메커니즘이다. 신호를 제대로 사용하기 위해서는 설정 방법과 각 신호의 용도를 정확히 이해해야 한다.
신호 처리기가 동작하지 않을 때의 해결 방법
신호 처리기를 구현했는데 아무런 출력이 없다면, 다음 사항들을 점검해야 한다.
1. apps.py 설정 확인
# myapp/apps.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
name = 'myapp'
verbose_name = '고객 관리 시스템'
def ready(self):
import myapp.signals # 신호 모듈 임포트 필수
2. __init__.py 설정
# myapp/__init__.py
default_app_config = 'myapp.apps.MyAppConfig'
3. 신호 처리기 코드 작성
# myapp/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from myapp.models import Order
@receiver(post_save, sender=Order)
def order_post_save(sender, instance, created, **kwargs):
print('주문 모델 신호 수신')
print(f'인스턴스: {instance}')
print(f'생성 여부: {created}')
print(f'추가 파라미터: {kwargs}')
4. 모델 저장 로직 확인
# myapp/views.py
from myapp.models import Order
def create_order(request):
order = Order(customer_name='홍길동', product='노트북', quantity=1)
order.save() # 실제 저장 실행 확인
5. settings.py 앱 등록
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
# ...
'myapp', # 앱 이름 정확히 기입
]
6. 서버 재시작
설정 변경 후에는 반드시 Django 개발 서버를 재시작해야 한다.
7. 디버깅을 위한 로깅 추가
@receiver(post_save, sender=Order)
def order_post_save(sender, instance, created, **kwargs):
import logging
logger = logging.getLogger(__name__)
logger.info(f'주문 생성: {instance.id}')
logger.debug(f'생성 여부: {created}')
# 파일로도 기록
try:
with open('signal_debug.log', 'a') as f:
f.write(f'주문 신호 실행: {instance}\n')
except Exception as e:
print(f'로그 작성 오류: {e}')
8. 에러 로그 확인
서버 터미널과 Django 에러 로그를 확인하여 예외 사항이 있는지 점검한다.
9. 신호 모듈 로드 확인
# myapp/signals.py
print('신호 모듈 로드 완료') # 시작 시 출력 확인
from django.db.models.signals import post_save
from django.dispatch import receiver
from myapp.models import Order
10. 저장 전후 상태 확인
def save_order():
order = Order(customer_name='홍길동', product='노트북')
print('저장 전:', order.id)
order.save()
print('저장 후:', order.id)
Django 신호의 종류
1. 모델 신호 (Model Signals)
- pre_save: 모델 인스턴스 저장 직전에 발생
- post_save: 모델 인스턴스 저장 직후에 발생
- pre_delete: 모델 인스턴스 삭제 직전에 발생
- post_delete: 모델 인스턴스 삭제 직후에 발생
- m2m_changed: ManyToMany 관계 변경 시 발생
- pre_init: 모델 인스턴스 초기화 전에 발생
- post_init: 모델 인스턴스 초기화 후에 발생
2. 데이터베이스 신호 (Database Signals)
- pre_migrate: 마이그레이션 실행 전에 발생
- post_migrate: 마이그레이션 실행 후에 발생
3. 요청/응답 신호 (Request/Response Signals)
- request_started: HTTP 요청 처리 시작 시 발생
- request_finished: HTTP 요청 처리 완료 시 발생
- got_request_exception: 요청 처리 중 예외 발생 시 발생
4. 관리 명령 신호 (Management Signals)
- pre_migrate: migrate 명령어 실행 전
- post_migrate: migrate 명령어 실행 후
5. 사용자 인증 신호 (User Authentication Signals)
- user_logged_in: 사용자 로그인 성공 시
- user_logged_out: 사용자 로그아웃 시
- user_login_failed: 사용자 로그인 실패 시
6. 기타 신호
- connection_created: 데이터베이스 연결 생성 후
신호 사용 예제
모델 신호 활용
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
from myapp.models import Product, Inventory
@receiver(post_save, sender=Product)
def product_saved(sender, instance, created, **kwargs):
if created:
Inventory.objects.create(product=instance, stock=0)
print(f'새 제품 재고 생성: {instance.name}')
else:
print(f'제품 정보 업데이트: {instance.name}')
@receiver(pre_delete, sender=Product)
def product_deleting(sender, instance, **kwargs):
print(f'제품 삭제 진행: {instance.name}')
요청 신호 활용
from django.core.signals import request_started, request_finished
from django.dispatch import receiver
@receiver(request_started)
def request_started_handler(sender, **kwargs):
print('새 요청 시작')
@receiver(request_finished)
def request_finished_handler(sender, **kwargs):
print('요청 처리 완료')
사용자 인증 신호 활용
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver
@receiver(user_logged_in)
def login_success(sender, request, user, **kwargs):
print(f'로그인 성공: {user.username}')
@receiver(user_logged_out)
def logout_success(sender, request, user, **kwargs):
print(f'로그아웃: {user.username}')
Django 신호를 잘 활용하면 모델 상태 변경 추적, 로그 기록, 캐시 무효화, 데이터 동기화 등 다양한 기능을 구현할 수 있다. 신호 설정 시에는 apps.py의 ready() 메서드에서 신호 모듈을 반드시 임포트해야 하며, 서버 재시작을忘رات 않아야 한다.