{"title":"시그널","version":"4.2","locale":"ko","docname":"topics/signals","url":"/ko/4.2/topics/signals/","canonical":"https://djangodocs.dev/ko/4.2/topics/signals/","summary":"Django includes a “signal dispatcher” which helps decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow…","html":"<span id=\"signals\"></span><h1>시그널<a class=\"heading-anchor\" href=\"#module-django.dispatch\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>Django includes a “signal dispatcher” which helps decoupled applications get\nnotified when actions occur elsewhere in the framework. In a nutshell, signals\nallow certain <em>senders</em> to notify a set of <em>receivers</em> that some action has\ntaken place. They’re especially useful when many pieces of code may be\ninterested in the same events.</p>\n<p>For example, a third-party app can register to be notified of settings\nchanges:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.apps</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">AppConfig</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">setting_changed</span>\n\n\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_callback</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;Setting changed!&quot;</span><span class=\"p\">)</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyAppConfig</span><span class=\"p\">(</span><span class=\"n\">AppConfig</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">ready</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"n\">setting_changed</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">my_callback</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Django’s <a class=\"reference internal\" href=\"/ko/4.2/ref/signals/\"><span class=\"doc\">built-in signals</span></a> let user code get notified of\ncertain actions.</p>\n<p>You can also define and send your own custom signals. See\n<a class=\"reference internal\" href=\"#defining-and-sending-signals\"><span class=\"std std-ref\">Defining and sending signals</span></a> below.</p>\n<aside class=\"admonition admonition-warning\" role=\"note\">\n<p class=\"admonition-title\">경고</p>\n<p>Signals give the appearance of loose coupling, but they can quickly lead to\ncode that is hard to understand, adjust and debug.</p>\n<p>Where possible you should opt for directly calling the handling code,\nrather than dispatching via a signal.</p>\n</aside>\n<section id=\"listening-to-signals\">\n<h2>Listening to signals<a class=\"heading-anchor\" href=\"#listening-to-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>To receive a signal, register a <em>receiver</em> function using the\n<a class=\"reference internal\" href=\"#django.dispatch.Signal.connect\" title=\"django.dispatch.Signal.connect\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.connect()</span></code></a> method. The receiver function is called when the signal\nis sent. All of the signal’s receiver functions are called one at a time, in\nthe order they were registered.</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.connect\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Signal.</span></span><span class=\"sig-name descname\"><span class=\"pre\">connect</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">receiver</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sender</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">weak</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">True</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">dispatch_uid</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal.connect\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"field-list simple\">\n<dt class=\"field-odd\">매개변수<span class=\"colon\">:</span></dt>\n<dd class=\"field-odd\"><ul class=\"simple\">\n<li><p><strong>receiver</strong> – The callback function which will be connected to this\nsignal. See <a class=\"reference internal\" href=\"#receiver-functions\"><span class=\"std std-ref\">Receiver functions</span></a> for more information.</p></li>\n<li><p><strong>sender</strong> – Specifies a particular sender to receive signals from. See\n<a class=\"reference internal\" href=\"#connecting-to-specific-signals\"><span class=\"std std-ref\">Connecting to signals sent by specific senders</span></a> for more information.</p></li>\n<li><p><strong>weak</strong> – Django stores signal handlers as weak references by\ndefault. Thus, if your receiver is a local function, it may be\ngarbage collected. To prevent this, pass <code class=\"docutils literal notranslate\"><span class=\"pre\">weak=False</span></code> when you call\nthe signal’s <code class=\"docutils literal notranslate\"><span class=\"pre\">connect()</span></code> method.</p></li>\n<li><p><strong>dispatch_uid</strong> – A unique identifier for a signal receiver in cases\nwhere duplicate signals may be sent. See\n<a class=\"reference internal\" href=\"#preventing-duplicate-signals\"><span class=\"std std-ref\">Preventing duplicate signals</span></a> for more information.</p></li>\n</ul>\n</dd>\n</dl>\n</dd></dl>\n\n<p>Let’s see how this works by registering a signal that\ngets called after each HTTP request is finished. We’ll be connecting to the\n<a class=\"reference internal\" href=\"/ko/4.2/ref/signals/#django.core.signals.request_finished\" title=\"django.core.signals.request_finished\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">request_finished</span></code></a> signal.</p>\n<section id=\"receiver-functions\">\n<span id=\"id1\"></span><h3>Receiver functions<a class=\"heading-anchor\" href=\"#receiver-functions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>First, we need to define a receiver function. A receiver can be any Python\nfunction or method:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_callback</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;Request finished!&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Notice that the function takes a <code class=\"docutils literal notranslate\"><span class=\"pre\">sender</span></code> argument, along with wildcard\nkeyword arguments (<code class=\"docutils literal notranslate\"><span class=\"pre\">**kwargs</span></code>); all signal handlers must take these arguments.</p>\n<p>We’ll look at senders <a class=\"reference internal\" href=\"#connecting-to-specific-signals\"><span class=\"std std-ref\">a bit later</span></a>, but\nright now look at the <code class=\"docutils literal notranslate\"><span class=\"pre\">**kwargs</span></code> argument. All signals send keyword\narguments, and may change those keyword arguments at any time. In the case of\n<a class=\"reference internal\" href=\"/ko/4.2/ref/signals/#django.core.signals.request_finished\" title=\"django.core.signals.request_finished\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">request_finished</span></code></a>, it’s documented as sending no\narguments, which means we might be tempted to write our signal handling as\n<code class=\"docutils literal notranslate\"><span class=\"pre\">my_callback(sender)</span></code>.</p>\n<p>This would be wrong – in fact, Django will throw an error if you do so. That’s\nbecause at any point arguments could get added to the signal and your receiver\nmust be able to handle those new arguments.</p>\n</section>\n<section id=\"connecting-receiver-functions\">\n<span id=\"id2\"></span><h3>Connecting receiver functions<a class=\"heading-anchor\" href=\"#connecting-receiver-functions\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>There are two ways you can connect a receiver to a signal. You can take the\nmanual connect route:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">request_finished</span>\n\n<span class=\"n\">request_finished</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">my_callback</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Alternatively, you can use a <a class=\"reference internal\" href=\"#django.dispatch.receiver\" title=\"django.dispatch.receiver\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">receiver()</span></code></a> decorator:</p>\n<dl class=\"py function\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.receiver\">\n<span class=\"sig-name descname\"><span class=\"pre\">receiver</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">signal</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.receiver\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd><dl class=\"field-list simple\">\n<dt class=\"field-odd\">매개변수<span class=\"colon\">:</span></dt>\n<dd class=\"field-odd\"><ul class=\"simple\">\n<li><p><strong>signal</strong> – A signal or a list of signals to connect a function to.</p></li>\n<li><p><strong>kwargs</strong> – Wildcard keyword arguments to pass to a\n<a class=\"reference internal\" href=\"#receiver-functions\"><span class=\"std std-ref\">function</span></a>.</p></li>\n</ul>\n</dd>\n</dl>\n</dd></dl>\n\n<p>Here’s how you connect with the decorator:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">request_finished</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.dispatch</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">receiver</span>\n\n\n<span class=\"nd\">@receiver</span><span class=\"p\">(</span><span class=\"n\">request_finished</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_callback</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s2\">&quot;Request finished!&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n<p>Now, our <code class=\"docutils literal notranslate\"><span class=\"pre\">my_callback</span></code> function will be called each time a request finishes.</p>\n<aside class=\"admonition-where-should-this-code-live admonition\">\n<p class=\"admonition-title\">코드가 어디에서 서비스 되어야 할까요?</p>\n<p>Strictly speaking, signal handling and registration code can live anywhere\nyou like, although it’s recommended to avoid the application’s root module\nand its <code class=\"docutils literal notranslate\"><span class=\"pre\">models</span></code> module to minimize side-effects of importing code.</p>\n<p>In practice, signal handlers are usually defined in a <code class=\"docutils literal notranslate\"><span class=\"pre\">signals</span></code>\nsubmodule of the application they relate to. Signal receivers are\nconnected in the <a class=\"reference internal\" href=\"/ko/4.2/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">ready()</span></code></a> method of your\napplication <a class=\"reference internal\" href=\"/ko/4.2/ref/applications/#configuring-applications-ref\"><span class=\"std std-ref\">configuration class</span></a>. If\nyou’re using the <a class=\"reference internal\" href=\"#django.dispatch.receiver\" title=\"django.dispatch.receiver\"><code class=\"xref py py-func docutils literal notranslate\"><span class=\"pre\">receiver()</span></code></a> decorator, import the <code class=\"docutils literal notranslate\"><span class=\"pre\">signals</span></code>\nsubmodule inside <a class=\"reference internal\" href=\"/ko/4.2/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">ready()</span></code></a>, this will implicitly\nconnect signal handlers:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.apps</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">AppConfig</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">request_finished</span>\n\n\n<span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">MyAppConfig</span><span class=\"p\">(</span><span class=\"n\">AppConfig</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">ready</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">):</span>\n        <span class=\"c1\"># Implicitly connect signal handlers decorated with @receiver.</span>\n        <span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">.</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">signals</span>\n\n        <span class=\"c1\"># Explicitly connect a signal handler.</span>\n        <span class=\"n\">request_finished</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">signals</span><span class=\"o\">.</span><span class=\"n\">my_callback</span><span class=\"p\">)</span>\n</code></pre></div>\n</aside>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">참고</p>\n<p>The <a class=\"reference internal\" href=\"/ko/4.2/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">ready()</span></code></a> method may be executed more than\nonce during testing, so you may want to <a class=\"reference internal\" href=\"#preventing-duplicate-signals\"><span class=\"std std-ref\">guard your signals from\nduplication</span></a>, especially if you’re planning\nto send them within tests.</p>\n</aside>\n</section>\n<section id=\"connecting-to-signals-sent-by-specific-senders\">\n<span id=\"connecting-to-specific-signals\"></span><h3>Connecting to signals sent by specific senders<a class=\"heading-anchor\" href=\"#connecting-to-signals-sent-by-specific-senders\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>Some signals get sent many times, but you’ll only be interested in receiving a\ncertain subset of those signals. For example, consider the\n<a class=\"reference internal\" href=\"/ko/4.2/ref/signals/#django.db.models.signals.pre_save\" title=\"django.db.models.signals.pre_save\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">django.db.models.signals.pre_save</span></code></a> signal sent before a model gets saved.\nMost of the time, you don’t need to know when <em>any</em> model gets saved – just\nwhen one <em>specific</em> model is saved.</p>\n<p>In these cases, you can register to receive signals sent only by particular\nsenders. In the case of <a class=\"reference internal\" href=\"/ko/4.2/ref/signals/#django.db.models.signals.pre_save\" title=\"django.db.models.signals.pre_save\"><code class=\"xref py py-data docutils literal notranslate\"><span class=\"pre\">django.db.models.signals.pre_save</span></code></a>, the sender\nwill be the model class being saved, so you can indicate that you only want\nsignals sent by some model:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.db.models.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">pre_save</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.dispatch</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">receiver</span>\n<span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">myapp.models</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">MyModel</span>\n\n\n<span class=\"nd\">@receiver</span><span class=\"p\">(</span><span class=\"n\">pre_save</span><span class=\"p\">,</span> <span class=\"n\">sender</span><span class=\"o\">=</span><span class=\"n\">MyModel</span><span class=\"p\">)</span>\n<span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">my_handler</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"p\">,</span> <span class=\"o\">**</span><span class=\"n\">kwargs</span><span class=\"p\">):</span>\n    <span class=\"o\">...</span>\n</code></pre></div>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">my_handler</span></code> function will only be called when an instance of <code class=\"docutils literal notranslate\"><span class=\"pre\">MyModel</span></code>\nis saved.</p>\n<p>Different signals use different objects as their senders; you’ll need to consult\nthe <a class=\"reference internal\" href=\"/ko/4.2/ref/signals/\"><span class=\"doc\">built-in signal documentation</span></a> for details of each\nparticular signal.</p>\n</section>\n<section id=\"preventing-duplicate-signals\">\n<span id=\"id3\"></span><h3>Preventing duplicate signals<a class=\"heading-anchor\" href=\"#preventing-duplicate-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>In some circumstances, the code connecting receivers to signals may run\nmultiple times. This can cause your receiver function to be registered more\nthan once, and thus called as many times for a signal event. For example, the\n<a class=\"reference internal\" href=\"/ko/4.2/ref/applications/#django.apps.AppConfig.ready\" title=\"django.apps.AppConfig.ready\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">ready()</span></code></a> method may be executed more than once\nduring testing. More generally, this occurs everywhere your project imports the\nmodule where you define the signals, because signal registration runs as many\ntimes as it is imported.</p>\n<p>If this behavior is problematic (such as when using signals to\nsend an email whenever a model is saved), pass a unique identifier as\nthe <code class=\"docutils literal notranslate\"><span class=\"pre\">dispatch_uid</span></code> argument to identify your receiver function. This\nidentifier will usually be a string, although any hashable object will\nsuffice. The end result is that your receiver function will only be\nbound to the signal once for each unique <code class=\"docutils literal notranslate\"><span class=\"pre\">dispatch_uid</span></code> value:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">from</span><span class=\"w\"> </span><span class=\"nn\">django.core.signals</span><span class=\"w\"> </span><span class=\"kn\">import</span> <span class=\"n\">request_finished</span>\n\n<span class=\"n\">request_finished</span><span class=\"o\">.</span><span class=\"n\">connect</span><span class=\"p\">(</span><span class=\"n\">my_callback</span><span class=\"p\">,</span> <span class=\"n\">dispatch_uid</span><span class=\"o\">=</span><span class=\"s2\">&quot;my_unique_identifier&quot;</span><span class=\"p\">)</span>\n</code></pre></div>\n</section>\n</section>\n<section id=\"defining-and-sending-signals\">\n<span id=\"id4\"></span><h2>Defining and sending signals<a class=\"heading-anchor\" href=\"#defining-and-sending-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>Your applications can take advantage of the signal infrastructure and provide\nits own signals.</p>\n<aside class=\"admonition-when-to-use-custom-signals admonition\">\n<p class=\"admonition-title\">When to use custom signals</p>\n<p>Signals are implicit function calls which make debugging harder. If the\nsender and receiver of your custom signal are both within your project,\nyou’re better off using an explicit function call.</p>\n</aside>\n<section id=\"defining-signals\">\n<h3>Defining signals<a class=\"heading-anchor\" href=\"#defining-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<dl class=\"py class\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal\">\n<em class=\"property\"><span class=\"k\"><span class=\"pre\">class</span></span><span class=\"w\"> </span></em><span class=\"sig-name descname\"><span class=\"pre\">Signal</span></span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>All signals are <a class=\"reference internal\" href=\"#django.dispatch.Signal\" title=\"django.dispatch.Signal\"><code class=\"xref py py-class docutils literal notranslate\"><span class=\"pre\">django.dispatch.Signal</span></code></a> instances.</p>\n<p>예시:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"kn\">import</span><span class=\"w\"> </span><span class=\"nn\">django.dispatch</span>\n\n<span class=\"n\">pizza_done</span> <span class=\"o\">=</span> <span class=\"n\">django</span><span class=\"o\">.</span><span class=\"n\">dispatch</span><span class=\"o\">.</span><span class=\"n\">Signal</span><span class=\"p\">()</span>\n</code></pre></div>\n<p>This declares a <code class=\"docutils literal notranslate\"><span class=\"pre\">pizza_done</span></code> signal.</p>\n</section>\n<section id=\"sending-signals\">\n<h3>Sending signals<a class=\"heading-anchor\" href=\"#sending-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h3>\n<p>There are two ways to send signals in Django.</p>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.send\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Signal.</span></span><span class=\"sig-name descname\"><span class=\"pre\">send</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sender</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal.send\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.send_robust\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Signal.</span></span><span class=\"sig-name descname\"><span class=\"pre\">send_robust</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sender</span></span></em>, <em class=\"sig-param\"><span class=\"o\"><span class=\"pre\">**</span></span><span class=\"n\"><span class=\"pre\">kwargs</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal.send_robust\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>To send a signal, call either <a class=\"reference internal\" href=\"#django.dispatch.Signal.send\" title=\"django.dispatch.Signal.send\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.send()</span></code></a> (all built-in signals use\nthis) or <a class=\"reference internal\" href=\"#django.dispatch.Signal.send_robust\" title=\"django.dispatch.Signal.send_robust\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.send_robust()</span></code></a>. You must provide the <code class=\"docutils literal notranslate\"><span class=\"pre\">sender</span></code> argument\n(which is a class most of the time) and may provide as many other keyword\narguments as you like.</p>\n<p>For example, here’s how sending our <code class=\"docutils literal notranslate\"><span class=\"pre\">pizza_done</span></code> signal might look:</p>\n<div class=\"code-block\" data-language=\"default\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Code</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Code code\"><code><span class=\"k\">class</span><span class=\"w\"> </span><span class=\"nc\">PizzaStore</span><span class=\"p\">:</span>\n    <span class=\"o\">...</span>\n\n    <span class=\"k\">def</span><span class=\"w\"> </span><span class=\"nf\">send_pizza</span><span class=\"p\">(</span><span class=\"bp\">self</span><span class=\"p\">,</span> <span class=\"n\">toppings</span><span class=\"p\">,</span> <span class=\"n\">size</span><span class=\"p\">):</span>\n        <span class=\"n\">pizza_done</span><span class=\"o\">.</span><span class=\"n\">send</span><span class=\"p\">(</span><span class=\"n\">sender</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"o\">.</span><span class=\"vm\">__class__</span><span class=\"p\">,</span> <span class=\"n\">toppings</span><span class=\"o\">=</span><span class=\"n\">toppings</span><span class=\"p\">,</span> <span class=\"n\">size</span><span class=\"o\">=</span><span class=\"n\">size</span><span class=\"p\">)</span>\n        <span class=\"o\">...</span>\n</code></pre></div>\n<p>Both <code class=\"docutils literal notranslate\"><span class=\"pre\">send()</span></code> and <code class=\"docutils literal notranslate\"><span class=\"pre\">send_robust()</span></code> return a list of tuple pairs\n<code class=\"docutils literal notranslate\"><span class=\"pre\">[(receiver,</span> <span class=\"pre\">response),</span> <span class=\"pre\">...</span> <span class=\"pre\">]</span></code>, representing the list of called receiver\nfunctions and their response values.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">send()</span></code> differs from <code class=\"docutils literal notranslate\"><span class=\"pre\">send_robust()</span></code> in how exceptions raised by receiver\nfunctions are handled. <code class=\"docutils literal notranslate\"><span class=\"pre\">send()</span></code> does <em>not</em> catch any exceptions raised by\nreceivers; it simply allows errors to propagate. Thus not all receivers may\nbe notified of a signal in the face of an error.</p>\n<p><code class=\"docutils literal notranslate\"><span class=\"pre\">send_robust()</span></code> catches all errors derived from Python’s <code class=\"docutils literal notranslate\"><span class=\"pre\">Exception</span></code> class,\nand ensures all receivers are notified of the signal. If an error occurs, the\nerror instance is returned in the tuple pair for the receiver that raised the error.</p>\n<p>The tracebacks are present on the <code class=\"docutils literal notranslate\"><span class=\"pre\">__traceback__</span></code> attribute of the errors\nreturned when calling <code class=\"docutils literal notranslate\"><span class=\"pre\">send_robust()</span></code>.</p>\n</section>\n</section>\n<section id=\"disconnecting-signals\">\n<h2>Disconnecting signals<a class=\"heading-anchor\" href=\"#disconnecting-signals\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<dl class=\"py method\">\n<dt class=\"sig sig-object py\" id=\"django.dispatch.Signal.disconnect\">\n<span class=\"sig-prename descclassname\"><span class=\"pre\">Signal.</span></span><span class=\"sig-name descname\"><span class=\"pre\">disconnect</span></span><span class=\"sig-paren\">(</span><em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">receiver</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">sender</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em>, <em class=\"sig-param\"><span class=\"n\"><span class=\"pre\">dispatch_uid</span></span><span class=\"o\"><span class=\"pre\">=</span></span><span class=\"default_value\"><span class=\"pre\">None</span></span></em><span class=\"sig-paren\">)</span><a class=\"heading-anchor\" href=\"#django.dispatch.Signal.disconnect\"><span class=\"visually-hidden\">Link to this definition</span><span aria-hidden=\"true\">#</span></a></dt>\n<dd></dd></dl>\n\n<p>To disconnect a receiver from a signal, call <a class=\"reference internal\" href=\"#django.dispatch.Signal.disconnect\" title=\"django.dispatch.Signal.disconnect\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.disconnect()</span></code></a>. The\narguments are as described in <a class=\"reference internal\" href=\"#django.dispatch.Signal.connect\" title=\"django.dispatch.Signal.connect\"><code class=\"xref py py-meth docutils literal notranslate\"><span class=\"pre\">Signal.connect()</span></code></a>. The method returns\n<code class=\"docutils literal notranslate\"><span class=\"pre\">True</span></code> if a receiver was disconnected and <code class=\"docutils literal notranslate\"><span class=\"pre\">False</span></code> if not. When <code class=\"docutils literal notranslate\"><span class=\"pre\">sender</span></code>\nis passed as a lazy reference to <code class=\"docutils literal notranslate\"><span class=\"pre\">&lt;app</span> <span class=\"pre\">label&gt;.&lt;model&gt;</span></code>, this method always\nreturns <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code>.</p>\n<p>The <code class=\"docutils literal notranslate\"><span class=\"pre\">receiver</span></code> argument indicates the registered receiver to disconnect. It\nmay be <code class=\"docutils literal notranslate\"><span class=\"pre\">None</span></code> if <code class=\"docutils literal notranslate\"><span class=\"pre\">dispatch_uid</span></code> is used to identify the receiver.</p>\n</section>","rootId":"module-django.dispatch","toc":[{"title":"Listening to signals","anchor":"listening-to-signals","children":[{"title":"Receiver functions","anchor":"receiver-functions","children":[]},{"title":"Connecting receiver functions","anchor":"connecting-receiver-functions","children":[]},{"title":"Connecting to signals sent by specific senders","anchor":"connecting-to-signals-sent-by-specific-senders","children":[]},{"title":"Preventing duplicate signals","anchor":"preventing-duplicate-signals","children":[]}]},{"title":"Defining and sending signals","anchor":"defining-and-sending-signals","children":[{"title":"Defining signals","anchor":"defining-signals","children":[]},{"title":"Sending signals","anchor":"sending-signals","children":[]}]},{"title":"Disconnecting signals","anchor":"disconnecting-signals","children":[]}],"breadcrumbs":[{"docname":"topics/index","title":"Django 사용하기","url":"/ko/4.2/topics/"}],"prev":{"docname":"topics/settings","title":"Django settings","url":"/ko/4.2/topics/settings/"},"next":{"docname":"topics/checks","title":"시스템 점검 프레임워크","url":"/ko/4.2/topics/checks/"},"formats":{"html":"/ko/4.2/topics/signals/","markdown":"/ko/4.2/topics/signals.md","json":"/ko/4.2/topics/signals.json"},"source":"https://github.com/django/django/blob/stable/4.2.x/docs/topics/signals.txt","official":"https://docs.djangoproject.com/ko/4.2/topics/signals/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0","1.11"],"inLocales":["en","zh-hans","fr","ja","id","it","pt-br","ko","es","el","pl"]}