Django Signals

Soobin Kim·2023년 8월 22일

공부

목록 보기
5/15

Django Signals 개요

Signal 기본 매커니즘

  • Django에는 signal dispatcher가 포함되어 있어, 분리된 앱이 특정 이벤트 발생 시 이를 알리고 처리할 수 있도록 한다.
  • Signal은 sender, signal, receiver의 형태로 구성된다.
    • Sender: 이벤트를 발생시키는 객체
    • Signal: 이벤트를 정의하고 전달하는 역할
    • Receiver: Signal을 수신하여 동작을 처리하는 함수 또는 메서드
  • 관찰자 패턴(Observer Pattern) 또는 게시-구독(Publish/Subscribe) 모델이라고도 한다.

공식 문서 내용 번역

Signals

  • Django는 signal dispatcher를 제공하여 프레임워크의 다른 부분에서 작업이 발생했을 때 분리된 앱이 알림을 받을 수 있도록 한다.
  • Signal은 특정 sender가 어떤 동작이 발생했음을 여러 receiver에 알릴 수 있게 한다.
  • Signal은 동일한 이벤트를 처리해야 하는 코드 조각이 많을 때 특히 유용하다.

예를 들어, 앱이 설정 변경에 대한 알림을 받을 수 있도록 등록할 수 있다.

from django.apps import AppConfig
from django.core.signals import setting_changed

def my_callback(sender, **kwargs):
    print("Setting changed!")

class MyAppConfig(AppConfig):
    ...
    def ready(self):
        setting_changed.connect(my_callback)
  • Django는 내장 신호(built-in signals)를 제공하여 특정 동작에 대해 사용자 코드가 알림을 받을 수 있도록 한다.
  • 필요에 따라 사용자 지정 신호를 정의하고 전송할 수도 있다.

신호 연결하기 (Listening to Signals)

신호 수신

  • 신호를 수신하려면 Signal.connect()를 사용하여 receiver 함수를 등록해야 한다.
  • 등록된 수신기 함수는 신호가 전송될 때 호출된다.
  • 신호의 모든 수신기 함수는 등록된 순서대로 호출된다.

Signal.connect() 메서드

Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)
매개변수
  1. receiver

  2. sender

  3. weak

    • 기본값은 True. Django는 기본적으로 신호 핸들러를 약한 참조(weak reference)로 저장한다.
    • 수신기가 로컬 함수라면 가비지 컬렉션에 의해 제거될 수 있다. 이를 방지하려면 weak=False를 전달해야 한다.
  4. dispatch_uid

    • 중복 신호를 방지하기 위한 고유 식별자.
    • 신호 수신기의 고유한 문자열 또는 해시 가능한 객체를 지정한다.

Receiver Functions

  • receiver 함수는 파이썬 함수 또는 메서드일 수 있다.
  • 기본적으로 sender와 키워드 인수(**kwargs)를 받아야 한다.

예제:

def my_callback(sender, **kwargs):
    print("Request finished!")
  • 모든 Signal은 기본적으로 **kwargs를 통해 추가 인수를 전달할 수 있다.
  • Signal 처리기는 항상 이를 고려하여 작성해야 한다.

신호 연결 방법

  1. 수동으로 연결하기

    from django.core.signals import request_finished
    request_finished.connect(my_callback)
  2. 데코레이터를 사용하여 연결하기

    from django.core.signals import request_finished
    from django.dispatch import receiver
    
    @receiver(request_finished)
    def my_callback(sender, **kwargs):
        print("Request finished!")

사용자 지정 신호 정의 및 전송

신호 정의

  • 사용자 지정 신호는 django.dispatch.Signal 클래스의 인스턴스로 정의된다.

    import django.dispatch
    
    pizza_done = django.dispatch.Signal()

신호 전송

  • Signal.send(sender, **kwargs) 또는 Signal.send_robust(sender, **kwargs)를 사용하여 신호를 전송한다.

예제:

class PizzaStore:
    def send_pizza(self, toppings, size):
        pizza_done.send(sender=self.__class__, toppings=toppings, size=size)
  • send()는 예외 발생 시 멈추고 전파하지만, send_robust()는 예외를 처리하여 모든 수신기에게 신호를 보낸다.

신호 연결 끊기

  • Signal.disconnect(receiver=None, sender=None, dispatch_uid=None) 메서드를 사용하여 신호의 수신기 연결을 끊을 수 있다.

예제:

from django.core.signals import request_finished
request_finished.disconnect(my_callback, dispatch_uid="my_unique_identifier")
  • 연결이 끊기면 True, 실패하면 False를 반환한다.

0개의 댓글