<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Elixian</title>
    <link>https://elixian.tistory.com/</link>
    <description>시스템 통합 및 관리업, 컴퓨터 프로그래밍 서비스업 / 
컴퓨터 시스템 통합 자문 및 구축 서비스업 /

이메일 : elixian@elixian.co.kr
홈페이지 : www.elixian.co.kr

대표 : 심윤수
사업자등록번호 : 401-23-28025
</description>
    <language>ko</language>
    <pubDate>Fri, 17 Apr 2026 07:20:49 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>gozalex</managingEditor>
    <item>
      <title>Macro 101</title>
      <link>https://elixian.tistory.com/18</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;Basic&lt;/u&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;terms
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Expression : 표현식,&amp;nbsp;코드&lt;/li&gt;
&lt;li&gt;Represent : 코드를&amp;nbsp;표현하는&amp;nbsp;방식, AST consist of Three element tuples&lt;/li&gt;
&lt;li&gt;Quote : 인용, &lt;span style=&quot;color: #000000;&quot;&gt;특정&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;덩어리의&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Representation&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가져오는&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Unquote : 인용하는 것이 아니라 Evaluation 된 코드 결과&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Elixir는&amp;nbsp;이미&amp;nbsp;데이터&amp;nbsp;구조와&amp;nbsp;함수를&amp;nbsp;사용하여&amp;nbsp;간단하고&amp;nbsp;읽기&amp;nbsp;쉬운&amp;nbsp;방식으로&amp;nbsp;일상적인&amp;nbsp;코드를&amp;nbsp;작성할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;메커니즘을&amp;nbsp;제공합니다.&amp;nbsp;매크로는&amp;nbsp;최후의&amp;nbsp;수단으로만&amp;nbsp;사용해야&amp;nbsp;합니다.&amp;nbsp;명시적(explicit)이&amp;nbsp;암시적(implicit)보다&amp;nbsp;낫다는&amp;nbsp;것을&amp;nbsp;기억하십시오. Concise Code보다&amp;nbsp;Clear Code가&amp;nbsp;좋습니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;middot;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;메타&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;프로그래밍의&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;첫번째&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;단계는&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;표현식이&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;어떻게&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;나타나는지를&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이해하는&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;것입니다&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;. Elixir&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;코드는&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;내부적으로&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;추상&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;문법&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;트리&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;(Abstract Syntax Tree, AST)&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;로&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;표현하는데&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이는&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;함수&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이름과&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;메타&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;데이터&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;,&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;함수의&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;인자를&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;포함하는&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;튜플로&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;이루어져&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;있습니다&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;AST tuple은&amp;nbsp;다음&amp;nbsp;형식에&amp;nbsp;따라&amp;nbsp;구성됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1659933191262&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{atom | tuple, list, list | atom}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;첫&amp;nbsp;번째&amp;nbsp;요소는&amp;nbsp;동일한&amp;nbsp;representation의&amp;nbsp;atom&amp;nbsp;또는&amp;nbsp;tuple입니다.&lt;/li&gt;
&lt;li&gt;두&amp;nbsp;번째&amp;nbsp;요소는&amp;nbsp;숫자&amp;nbsp;및&amp;nbsp;컨텍스트와&amp;nbsp;같은&amp;nbsp;메타데이터를&amp;nbsp;포함하는&amp;nbsp;keyword list입니다.&lt;/li&gt;
&lt;li&gt;세&amp;nbsp;번째&amp;nbsp;요소는&amp;nbsp;함수&amp;nbsp;호출&amp;nbsp;또는&amp;nbsp;atom에&amp;nbsp;대한&amp;nbsp;argument list&amp;nbsp;입니다.&amp;nbsp;이&amp;nbsp;요소가&amp;nbsp;atom이면tuple이&amp;nbsp;variable을&amp;nbsp;represent&amp;nbsp;하는&amp;nbsp;것입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에&amp;nbsp;정의된&amp;nbsp;tuple&amp;nbsp;외에도&amp;nbsp;5개의&amp;nbsp;Elixir Literal Representation이&amp;nbsp;있습니다.&amp;nbsp;이&amp;nbsp;Literal은&amp;nbsp;인용(Quote)될&amp;nbsp;때&amp;nbsp;Tuple이&amp;nbsp;아닌&amp;nbsp;스스로를&amp;nbsp;반환합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1659933251697&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:sum #=&amp;gt; atom
1.0 #=&amp;gt; float, integer
[1, 2] #=&amp;gt; list
&quot;string&quot; #=&amp;gt; 문자열
{key, value} #=&amp;gt; 두 개의 element가 있는 tuple&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;과&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;macro&lt;/span&gt;&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;차이&lt;/span&gt;&lt;/u&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1659933340568&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule Unless do

  def fun_unless(clause, do: expression) do
    if(!clause, do: expression)
  end
 
  defmacro macro_unless(clause, do: expression) do
    quote do
      if(!unquote(clause), do: unquote(expression))
    end
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;671&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;671&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;iex(1)&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;Unless.fun_unless false, do: IO.puts &quot;this should never be printed&quot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;this should never be printed&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;:ok&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;iex(2)&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Unless.fun_unless true, do: IO.puts &quot;this should never be printed&quot;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;this should never be printed&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Fun.unless/2를&amp;nbsp;호출&amp;nbsp;하였을&amp;nbsp;때&amp;nbsp;첫&amp;nbsp;번째&amp;nbsp;파라미터가&amp;nbsp;true던&amp;nbsp;false던&amp;nbsp;상관없이&amp;nbsp;모두&amp;nbsp;&amp;ldquo;this should never be printed&amp;rdquo;가&amp;nbsp;출력&amp;nbsp;됩니다.&lt;/li&gt;
&lt;li&gt;그러나&amp;nbsp;리턴&amp;nbsp;값은&amp;nbsp;:ok와&amp;nbsp;nil&amp;nbsp;로&amp;nbsp;서로&amp;nbsp;다릅니다.&lt;/li&gt;
&lt;li&gt;다른&amp;nbsp;예를&amp;nbsp;한&amp;nbsp;번&amp;nbsp;보겠습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;671&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;671&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;iex(3)&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Unless.fun_unless false, do: 1+3&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;4&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;iex(4)&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Unless.fun_unless true, do: 1+3&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫&amp;nbsp;번째&amp;nbsp;파라미터가&amp;nbsp;false&amp;nbsp;일&amp;nbsp;경우, 4가&amp;nbsp;리턴&amp;nbsp;되었습니다.&amp;nbsp;그러나&amp;nbsp;true일&amp;nbsp;경우, nil&amp;nbsp;이&amp;nbsp;리턴&amp;nbsp;됩니다.&lt;/li&gt;
&lt;li&gt;위의&amp;nbsp;예와&amp;nbsp;차이점이&amp;nbsp;명확하게&amp;nbsp;보입니다. do:&amp;nbsp;절에&amp;nbsp;있는&amp;nbsp;코드의&amp;nbsp;Evaluate여부&amp;nbsp;입니다.&lt;/li&gt;
&lt;li&gt;함수는&amp;nbsp;인수를&amp;nbsp;받아&amp;nbsp;Evaluate하여&amp;nbsp;함수&amp;nbsp;내부로&amp;nbsp;전달합니다.&amp;nbsp;그러나&amp;nbsp;매크로는&amp;nbsp;인용된&amp;nbsp;표현식(quoted expression)을&amp;nbsp;수신하고&amp;nbsp;이를&amp;nbsp;인용부(quote do&amp;nbsp;절)에&amp;nbsp;삽입하고&amp;nbsp;마지막으로&amp;nbsp;다른&amp;nbsp;인용된&amp;nbsp;표현식(quoted expression)을&amp;nbsp;반환합니다.&lt;/li&gt;
&lt;li&gt;IO.puts&amp;nbsp;문장은&amp;nbsp;함수&amp;nbsp;구현에서&amp;nbsp;인쇄되었지만&amp;nbsp;매크로&amp;nbsp;구현에서는&amp;nbsp;인쇄되지&amp;nbsp;않았습니다.&amp;nbsp;이는&amp;nbsp;함수&amp;nbsp;호출에&amp;nbsp;대한&amp;nbsp;인수가&amp;nbsp;함수를&amp;nbsp;호출하기&amp;nbsp;전에&amp;nbsp;Evaluate되기&amp;nbsp;때문입니다.&amp;nbsp;그러나&amp;nbsp;매크로는&amp;nbsp;인수를&amp;nbsp;평가하지&amp;nbsp;않습니다.&amp;nbsp;대신&amp;nbsp;인용된&amp;nbsp;표현으로&amp;nbsp;인수를&amp;nbsp;받은&amp;nbsp;다음&amp;nbsp;다른&amp;nbsp;인용된&amp;nbsp;표현으로&amp;nbsp;변환됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; width=&quot;643&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;643&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;iex(5)&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;Unless.macro_unless false, do: IO.puts &quot;this should never be printed&quot;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;this should never be printed&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;:ok&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;iex(6)&amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;Unless.macro_unless true, do: IO.puts &quot;this should never be printed&quot;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;color: #54585b;&quot;&gt;nil&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Macro의&amp;nbsp;정의에&amp;nbsp;의해&amp;nbsp;위의&amp;nbsp;macro_unless&amp;nbsp;에&amp;nbsp;IO.puts&amp;nbsp;는&amp;nbsp;Evaluate&amp;nbsp;되지&amp;nbsp;않고&amp;nbsp;macro&amp;nbsp;안의quote&amp;nbsp;절에&amp;nbsp;삽입되어&amp;nbsp;새로운&amp;nbsp;quoted expression으로&amp;nbsp;리턴&amp;nbsp;됩니다.&lt;/li&gt;
&lt;li&gt;Quote는&amp;nbsp;특정&amp;nbsp;코드&amp;nbsp;덩어리의&amp;nbsp;Representation을&amp;nbsp;가져오는&amp;nbsp;것입니다.&amp;nbsp;그러나&amp;nbsp;때로는&amp;nbsp;가져오려는&amp;nbsp;Representation&amp;nbsp;내부에&amp;nbsp;다른&amp;nbsp;특정&amp;nbsp;코드&amp;nbsp;덩어리를&amp;nbsp;주입해야&amp;nbsp;할&amp;nbsp;수도&amp;nbsp;있습니다.&lt;/li&gt;
&lt;li&gt;예를&amp;nbsp;들어,&amp;nbsp;인용된&amp;nbsp;표현식&amp;nbsp;안에&amp;nbsp;삽입하려는&amp;nbsp;숫자가&amp;nbsp;포함된&amp;nbsp;변수&amp;nbsp;숫자가&amp;nbsp;있다고&amp;nbsp;가정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1659933530809&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; number = 13
iex&amp;gt; Macro.to_string(do: 11 + number)

&quot;11 + number&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;number&amp;nbsp;변수의&amp;nbsp;값이&amp;nbsp;삽입되지&amp;nbsp;않았고&amp;nbsp;expression에서&amp;nbsp;number가&amp;nbsp;인용되었기&amp;nbsp;때문에&amp;nbsp;우리가&amp;nbsp;원하는&amp;nbsp;것이&amp;nbsp;아닙니다. Number에&amp;nbsp;값을&amp;nbsp;삽입하려면&amp;nbsp;quote do&amp;nbsp;절&amp;nbsp;안에&amp;nbsp;unquote를&amp;nbsp;사용해야&amp;nbsp;합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1659933562475&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; number = 13
iex&amp;gt; Macro.to_string(quote do: 11 + unquote(number))

&quot;11 + 13&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;&lt;span&gt;&lt;span&gt;디버깅&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래는&amp;nbsp;매크로로&amp;nbsp;생성된&amp;nbsp;코드를&amp;nbsp;확인하고&amp;nbsp;싶을&amp;nbsp;때,&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/li&gt;
&lt;li&gt;매크로로&amp;nbsp;생성된&amp;nbsp;코드를&amp;nbsp;확인하고&amp;nbsp;싶다면,&amp;nbsp;코드를&amp;nbsp;Macro.expand/2, Macro.expand_once/2로합칠&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;다음은&amp;nbsp;__ENV__를&amp;nbsp;사용하여&amp;nbsp;IEx와&amp;nbsp;소스를&amp;nbsp;합칩니다.&lt;/li&gt;
&lt;li&gt;Expand&amp;nbsp;함수는&amp;nbsp;주어진&amp;nbsp;감싸진&amp;nbsp;코드로&amp;nbsp;매크로를&amp;nbsp;확장합니다.&amp;nbsp;첫&amp;nbsp;번째는&amp;nbsp;여러&amp;nbsp;번&amp;nbsp;확장됩니다.&amp;nbsp;하지만&amp;nbsp;뒤에&amp;nbsp;것은&amp;nbsp;한번만&amp;nbsp;확장됩니다.&amp;nbsp;예를&amp;nbsp;들어,&amp;nbsp;이&amp;nbsp;전&amp;nbsp;단락의&amp;nbsp;unless&amp;nbsp;예제를&amp;nbsp;수정해&amp;nbsp;봅시다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1659933679781&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule OurMacro do

  defmacro unless(expr, do: block) do
    quote do
      if !unquote(expr), do: unquote(block)
    end
  end
end
 
require OurMacro
 
quoted =
  quote do
    OurMacro.unless(true, do: &quot;Hi&quot;)
  end&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1659933716348&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;quoted |&amp;gt; Macro.expand_once(__ENV__) |&amp;gt; Macro.to_string |&amp;gt; IO.puts

if(!true) do
  &quot;Hi&quot;
end&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은&amp;nbsp;코드를&amp;nbsp;Macro.expand/2로&amp;nbsp;실행하면,&amp;nbsp;흥미로운&amp;nbsp;결과가&amp;nbsp;나옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1659933771651&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;quoted |&amp;gt; Macro.expand(__ENV__) |&amp;gt; Macro.to_string |&amp;gt; IO.puts

case(!true) do
  x when x in [false, nil] -&amp;gt;
    nil
  _ -&amp;gt;
    &quot;Hi&quot;
end&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Elixir에서&amp;nbsp;if는&amp;nbsp;매크로입니다.&amp;nbsp;여기에서&amp;nbsp;기저의&amp;nbsp;case&amp;nbsp;구문으로&amp;nbsp;확장되는&amp;nbsp;것을&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/li&gt;
&lt;li&gt;즉,&amp;nbsp;소스를&amp;nbsp;합치는&amp;nbsp;것을&amp;nbsp;&amp;ldquo;확장한다&amp;rdquo;라고&amp;nbsp;표현하는&amp;nbsp;이유는&amp;nbsp;어디에&amp;nbsp;Expand&amp;nbsp;하는지에&amp;nbsp;따라&amp;nbsp;다른quoted expression이&amp;nbsp;생성될&amp;nbsp;수&amp;nbsp;있기&amp;nbsp;때문입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;Macro Hygiene&lt;/u&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본적으로&amp;nbsp;Elixir&amp;nbsp;매크로는&amp;nbsp;청결하며&amp;nbsp;컨텍스트와&amp;nbsp;충돌하지&amp;nbsp;않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1659933839620&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule Example do

  defmacro hygienic do
    quote do: val = -1
  end
end
 
iex&amp;gt; require Example
nil
iex&amp;gt; val = 42
42
iex&amp;gt; Example.hygienic
-1
iex&amp;gt; val
42&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;val을&amp;nbsp;조작하고&amp;nbsp;싶은&amp;nbsp;경우에는&amp;nbsp;Hygiene하지&amp;nbsp;않은&amp;nbsp;변수를&amp;nbsp;원한다는&amp;nbsp;것을&amp;nbsp;알리기&amp;nbsp;위해서&amp;nbsp;var!/2를사용하면&amp;nbsp;됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1659933859854&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule Example do

  defmacro hygienic do
    quote do: val = -1
  end
 
  defmacro unhygienic do
    quote do: var!(val) = -1
  end
end
 
require Example
nil
iex&amp;gt; val = 42
42
iex&amp;gt; Example.hygienic
-1
iex&amp;gt; val
42
iex&amp;gt; Example.unhygienic
-1
iex&amp;gt; val
-1&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매크로에서&amp;nbsp;var!/2를&amp;nbsp;사용하는&amp;nbsp;것으로&amp;nbsp;매크로에게&amp;nbsp;val&amp;nbsp;값을&amp;nbsp;넘기지&amp;nbsp;않고,&amp;nbsp;이를&amp;nbsp;조작하였습니다.&amp;nbsp;청결하지&amp;nbsp;않은&amp;nbsp;매크로를&amp;nbsp;사용하는&amp;nbsp;것은&amp;nbsp;최소화해야&amp;nbsp;합니다.&amp;nbsp;var!/2를&amp;nbsp;사용하는&amp;nbsp;것은&amp;nbsp;변수&amp;nbsp;해결시에충돌이&amp;nbsp;발생할&amp;nbsp;위험성을&amp;nbsp;증가시키게&amp;nbsp;됩니다.&lt;/li&gt;
&lt;li&gt;이미&amp;nbsp;unquote/1라는&amp;nbsp;편리한&amp;nbsp;매크로를&amp;nbsp;배웠습니다만,&amp;nbsp;이외에도&amp;nbsp;코드에&amp;nbsp;값을&amp;nbsp;주입하는바인딩이라는&amp;nbsp;방법이&amp;nbsp;있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1659933890357&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule Example do

  defmacro double_puts(expr) do
    quote do
      IO.puts(unquote(expr))
      IO.puts(unquote(expr))
    end
  end
end
 
Example.double_puts(:os.system_time)
1450475941851668000
1450475941851733000&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간이&amp;nbsp;다릅니다!&amp;nbsp;무슨&amp;nbsp;일이&amp;nbsp;있었던&amp;nbsp;걸까요?&amp;nbsp;unquote/1를&amp;nbsp;같은&amp;nbsp;표현식에&amp;nbsp;여러&amp;nbsp;번&amp;nbsp;사용하는&amp;nbsp;것은재평가를&amp;nbsp;발생시키며&amp;nbsp;예상치&amp;nbsp;못한&amp;nbsp;결과를&amp;nbsp;가져옵니다.&amp;nbsp;bind_quoted를&amp;nbsp;사용해서&amp;nbsp;예제를&amp;nbsp;변경해봅시다.&lt;/li&gt;
&lt;li&gt;변수&amp;nbsp;바인딩을&amp;nbsp;통해&amp;nbsp;매크로의&amp;nbsp;내부에&amp;nbsp;여러&amp;nbsp;변수를&amp;nbsp;포함하고,&amp;nbsp;한번만&amp;nbsp;quote&amp;nbsp;되도록&amp;nbsp;보장하는&amp;nbsp;것으로예상치&amp;nbsp;못한&amp;nbsp;재평가를&amp;nbsp;회피할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;바인딩된&amp;nbsp;변수를&amp;nbsp;사용하려면&amp;nbsp;quote/2의&amp;nbsp;bind_quoted&amp;nbsp;옵션에&amp;nbsp;키워드&amp;nbsp;리스트를&amp;nbsp;넘겨주면&amp;nbsp;됩니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1659933920561&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule Example do

  defmacro double_puts(expr) do
    quote bind_quoted: [expr: expr] do
      IO.puts(expr)
      IO.puts(expr)
    end
  end
end
 
iex&amp;gt; require Example
nil
iex&amp;gt; Example.double_puts(:os.system_time)
1450476083466500000
1450476083466500000&lt;/code&gt;&lt;/pre&gt;</description>
      <category>기술 동향</category>
      <category>ELIXIR</category>
      <category>macro</category>
      <author>gozalex</author>
      <guid isPermaLink="true">https://elixian.tistory.com/18</guid>
      <comments>https://elixian.tistory.com/18#entry18comment</comments>
      <pubDate>Mon, 8 Aug 2022 13:46:51 +0900</pubDate>
    </item>
    <item>
      <title>Debugging using Livebook</title>
      <link>https://elixian.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Elixir Korea Meetup 에서 Livebook 을 사용한 관련 Topic을 세미나 한다길래 꼭 들으려 했으나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피치 못할 사정으로 노쇼하는 바람에 따로 시간 내어 조사해 봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#노쇼노매너 #노쇼 #엘릭서밋업&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에 설치했던 Livebook을 업그레이드 하고, erlang dbg모듈을 사용해 봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 테스트 화면입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;#훌륭 #OTP #Process #RemoteProcess #Cluster&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Screen Shot 2022-07-21 at 2.53.55 PM.png&quot; data-origin-width=&quot;3584&quot; data-origin-height=&quot;2240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmym1k/btrHQoZ9JyE/EGkkTq0ZGYmVwTp0E0nxt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmym1k/btrHQoZ9JyE/EGkkTq0ZGYmVwTp0E0nxt1/img.png&quot; data-alt=&quot;와.. 이건 뭐 사기캐인가?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmym1k/btrHQoZ9JyE/EGkkTq0ZGYmVwTp0E0nxt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdmym1k%2FbtrHQoZ9JyE%2FEGkkTq0ZGYmVwTp0E0nxt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3584&quot; height=&quot;2240&quot; data-filename=&quot;Screen Shot 2022-07-21 at 2.53.55 PM.png&quot; data-origin-width=&quot;3584&quot; data-origin-height=&quot;2240&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;와.. 이건 뭐 사기캐인가?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Debug Using Livebook&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Install as an Escript&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This is the easiest way to use Livebook locally.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This assumes you are doing Elixir development locally and are setup for Elixir development.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Following the Livebook &lt;a href=&quot;https://github.com/elixir-nx/livebook#escript&quot;&gt;&lt;span style=&quot;color: #dca10d;&quot;&gt;Escript README section&lt;/span&gt;&lt;/a&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;this is how you install Livebook.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;$ mix escript.install hex livebook&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Then locally launching Livebook is:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;$ livebook server&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Upgrading When Using an Escript&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;When upgrading your Livebook version while using &lt;a href=&quot;https://asdf-vm.com/&quot;&gt;&lt;span style=&quot;color: #dca10d;&quot;&gt;asdf&lt;/span&gt;&lt;/a&gt; for managing your Elixir and Erlang installs,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;then here's a helpful tip:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Remove the existing livebook shim: rm ~/.asdf/shims/livebook&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Install the new version:&lt;span&gt;&amp;nbsp;mix escript.install hex livebook&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Re-shim to get the command:&lt;span&gt;&amp;nbsp;asdf reshim elixir&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Verify you have the upgrade:&lt;span&gt;&amp;nbsp;livebook --version&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고자료&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://fly.io/docs/getting-started/elixir/&quot;&gt;https://fly.io/docs/getting-started/elixir/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658392992389&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;The Fly Global Application Platform &amp;middot; Fly Docs&quot; data-og-description=&quot;Documentation and guides from the team at Fly.io.&quot; data-og-host=&quot;fly.io&quot; data-og-source-url=&quot;https://fly.io/docs/getting-started/elixir/&quot; data-og-url=&quot;https://fly.io/docs/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bf9Pnr/hyPaDtIlwL/KykMIiLnYLJeWC8m3MA7tk/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/sFrWk/hyPavWGfxk/kMHldLxMUBCSq9UuCwKwg0/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/ut3d0/hyPaDHe8Q0/ESXX3t7ncylxC3kRZkzICk/img.jpg?width=820&amp;amp;height=370&amp;amp;face=0_0_820_370&quot;&gt;&lt;a href=&quot;https://fly.io/docs/getting-started/elixir/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://fly.io/docs/getting-started/elixir/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bf9Pnr/hyPaDtIlwL/KykMIiLnYLJeWC8m3MA7tk/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/sFrWk/hyPavWGfxk/kMHldLxMUBCSq9UuCwKwg0/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/ut3d0/hyPaDHe8Q0/ESXX3t7ncylxC3kRZkzICk/img.jpg?width=820&amp;amp;height=370&amp;amp;face=0_0_820_370');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;The Fly Global Application Platform &amp;middot; Fly Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Documentation and guides from the team at Fly.io.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;fly.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://fly.io/docs/app-guides/elixir-static-cookie/&quot;&gt;https://fly.io/docs/app-guides/elixir-static-cookie/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658392991746&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;The Fly Global Application Platform &amp;middot; Fly Docs&quot; data-og-description=&quot;Documentation and guides from the team at Fly.io.&quot; data-og-host=&quot;fly.io&quot; data-og-source-url=&quot;https://fly.io/docs/app-guides/elixir-static-cookie/&quot; data-og-url=&quot;https://fly.io/docs/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kos5e/hyPaseAhaz/FFRqMo49IbUUjWI5XY8jM0/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/cRzPn5/hyPax71Y1T/o2oGwRYmGHk4n2Y2W5jveK/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/b3J5sb/hyParzZBMv/oK6W2NaUv9S2sFWFHjirl0/img.jpg?width=820&amp;amp;height=370&amp;amp;face=0_0_820_370&quot;&gt;&lt;a href=&quot;https://fly.io/docs/app-guides/elixir-static-cookie/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://fly.io/docs/app-guides/elixir-static-cookie/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kos5e/hyPaseAhaz/FFRqMo49IbUUjWI5XY8jM0/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/cRzPn5/hyPax71Y1T/o2oGwRYmGHk4n2Y2W5jveK/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/b3J5sb/hyParzZBMv/oK6W2NaUv9S2sFWFHjirl0/img.jpg?width=820&amp;amp;height=370&amp;amp;face=0_0_820_370');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;The Fly Global Application Platform &amp;middot; Fly Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Documentation and guides from the team at Fly.io.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;fly.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://fly.io/docs/elixir/advanced-guides/connect-livebook-to-your-app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://fly.io/docs/elixir/advanced-guides/connect-livebook-to-your-app/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1713842171722&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Connecting Livebook to Your App in Production&quot; data-og-description=&quot;Documentation and guides from the team at Fly.io.&quot; data-og-host=&quot;fly.io&quot; data-og-source-url=&quot;https://fly.io/docs/elixir/advanced-guides/connect-livebook-to-your-app/&quot; data-og-url=&quot;https://fly.io/docs/elixir/advanced-guides/connect-livebook-to-your-app/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ATKPS/hyVS0XFks0/9Svh0Ly2nEEX0rqhPGNbJ1/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/bEKAHV/hyVSYr1vPJ/dJhXTXq5l0DcJEp8E0Ntg0/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200&quot;&gt;&lt;a href=&quot;https://fly.io/docs/elixir/advanced-guides/connect-livebook-to-your-app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://fly.io/docs/elixir/advanced-guides/connect-livebook-to-your-app/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ATKPS/hyVS0XFks0/9Svh0Ly2nEEX0rqhPGNbJ1/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200,https://scrap.kakaocdn.net/dn/bEKAHV/hyVSYr1vPJ/dJhXTXq5l0DcJEp8E0Ntg0/img.jpg?width=1200&amp;amp;height=1200&amp;amp;face=0_0_1200_1200');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Connecting Livebook to Your App in Production&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Documentation and guides from the team at Fly.io.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;fly.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://kaiwern.com/posts/2020/11/02/debugging-with-tracing-in-elixir/&quot;&gt;https://kaiwern.com/posts/2020/11/02/debugging-with-tracing-in-elixir/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658392983447&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Debugging With Tracing in Elixir | kw7oe&quot; data-og-description=&quot;If you are a video person, and have 24 minutes to spend with, just jump over to this ElixirConf 2020 - Debugging Live Systems on the BEAM talk by Jeffery Utter. This article is a downgraded version of the video  . I wrote this before the video is publis&quot; data-og-host=&quot;kaiwern.com&quot; data-og-source-url=&quot;https://kaiwern.com/posts/2020/11/02/debugging-with-tracing-in-elixir/&quot; data-og-url=&quot;https://kaiwern.com/posts/2020/11/02/debugging-with-tracing-in-elixir/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://kaiwern.com/posts/2020/11/02/debugging-with-tracing-in-elixir/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kaiwern.com/posts/2020/11/02/debugging-with-tracing-in-elixir/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Debugging With Tracing in Elixir | kw7oe&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;If you are a video person, and have 24 minutes to spend with, just jump over to this ElixirConf 2020 - Debugging Live Systems on the BEAM talk by Jeffery Utter. This article is a downgraded version of the video  . I wrote this before the video is publis&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kaiwern.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.erlang.org/doc/man/dbg.html#tracer-0&quot;&gt;https://www.erlang.org/doc/man/dbg.html#tracer-0&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1658392979265&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Erlang -- dbg&quot; data-og-description=&quot;When tracing function calls on a group leader process (an IO process), there is risk of causing a deadlock. This will happen if a group leader process generates a trace message and the tracer process, by calling the trace handler function, sends an IO requ&quot; data-og-host=&quot;www.erlang.org&quot; data-og-source-url=&quot;https://www.erlang.org/doc/man/dbg.html#tracer-0&quot; data-og-url=&quot;https://www.erlang.org/doc/man/dbg.html#tracer-0&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.erlang.org/doc/man/dbg.html#tracer-0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.erlang.org/doc/man/dbg.html#tracer-0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Erlang -- dbg&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;When tracing function calls on a group leader process (an IO process), there is risk of causing a deadlock. This will happen if a group leader process generates a trace message and the tracer process, by calling the trace handler function, sends an IO requ&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.erlang.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;들어가기 전에...&lt;/h3&gt;
&lt;pre id=&quot;code_1658395545035&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; iex --sname fit --cookie iQ-VfumnytJJ9omnF8s...oNzwDsRIQlrsTA== -S mix phx.server&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 Trace 할 프로젝트를 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시작:dbg&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추적을&amp;nbsp;시작하기&amp;nbsp;전에&amp;nbsp;다음&amp;nbsp;코드로&amp;nbsp;dbg&amp;nbsp;및&amp;nbsp;tracer&amp;nbsp;프로세스를&amp;nbsp;시작해야&amp;nbsp;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tracer는 단순히 생각해서 receive block 안에서 log를 출력해주는 일을 하는 간단한 모듈이라고 생각하면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658393054463&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.start
:dbg.tracer&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명시적으로&amp;nbsp;추적하려는&amp;nbsp;것을&amp;nbsp;명시할&amp;nbsp;때까지&amp;nbsp;아무&amp;nbsp;작업도&amp;nbsp;수행하지&amp;nbsp;않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;추적할&amp;nbsp;대상&amp;nbsp;지정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템에서&amp;nbsp;호출된&amp;nbsp;Enum.map/2&amp;nbsp;함수를&amp;nbsp;추적한다고&amp;nbsp;가정해&amp;nbsp;보겠습니다.&amp;nbsp;다음을&amp;nbsp;실행하여&amp;nbsp;지정할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658393211367&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.tp(Enum, :map, 2, [])
:dbg.p(:all, :c)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드의&amp;nbsp;일부가&amp;nbsp;Enum.map([1,2,3],&amp;nbsp;&amp;amp;&amp;nbsp;&amp;amp;1&amp;nbsp;+&amp;nbsp;1)을&amp;nbsp;호출하면&amp;nbsp;위의&amp;nbsp;:dbg&amp;nbsp;코드를&amp;nbsp;실행하는&amp;nbsp;위치에&amp;nbsp;따라&amp;nbsp;쉘에서&amp;nbsp;다른&amp;nbsp;출력을&amp;nbsp;얻게&amp;nbsp;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Local Shell&amp;nbsp;(응용&amp;nbsp;프로그램&amp;nbsp;코드&amp;nbsp;실행)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Local Shell에서&amp;nbsp;시스템을&amp;nbsp;실행하는&amp;nbsp;셸에&amp;nbsp;있는&amp;nbsp;경우&amp;nbsp;추적한&amp;nbsp;함수가&amp;nbsp;호출될&amp;nbsp;때마다&amp;nbsp;다음과&amp;nbsp;같은&amp;nbsp;내용이&amp;nbsp;표시됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658393341226&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(&amp;lt;0.106.0&amp;gt;) call 'Elixir.Enum':map([1,2,3],#Fun&amp;lt;erl_eval.44.97283095&amp;gt;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Remote Shell (여기서&amp;nbsp;셸&amp;nbsp;프로세스가&amp;nbsp;애플리케이션을&amp;nbsp;실행하는&amp;nbsp;프로세스에&amp;nbsp;연결되었다고 가정)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Remote Shell 에서는&amp;nbsp;Tracer가 Remote Shell 대신&amp;nbsp;라이브&amp;nbsp;프로세스에서&amp;nbsp;출력을&amp;nbsp;기록하기&amp;nbsp;때문에&amp;nbsp;출력이&amp;nbsp;표시되지&amp;nbsp;않습니다.&amp;nbsp;추적을&amp;nbsp;보려면&amp;nbsp;로그&amp;nbsp;파일(예:&amp;nbsp;erlang.log.1)을&amp;nbsp;살펴봐야&amp;nbsp;합니다.&lt;br /&gt;&lt;br /&gt;Remote Shell에서&amp;nbsp;출력하려면&amp;nbsp;추적&amp;nbsp;프로그램&amp;nbsp;프로세스를&amp;nbsp;다르게&amp;nbsp;시작해야&amp;nbsp;합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658393506410&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.tracer(:process, {fn msg, n -&amp;gt; IO.inspect(msg); n+1 end, 0})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;:dbg.tracer는&amp;nbsp;추적된&amp;nbsp;각&amp;nbsp;이벤트를&amp;nbsp;처리하는&amp;nbsp;방법을&amp;nbsp;사용자&amp;nbsp;정의할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;두&amp;nbsp;번째&amp;nbsp;인수를&amp;nbsp;허용합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서&amp;nbsp;우리는&amp;nbsp;대신 Local Shell에&amp;nbsp;출력을&amp;nbsp;기록하도록 Tracer에게&amp;nbsp;지시합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;추적&amp;nbsp;중지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추적을&amp;nbsp;중지하려면&amp;nbsp;다음과&amp;nbsp;같이&amp;nbsp;간단합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658393583192&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.stop_clear&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한&amp;nbsp;정보를&amp;nbsp;얻은&amp;nbsp;후&amp;nbsp;추적을&amp;nbsp;중지하는&amp;nbsp;것이&amp;nbsp;매우&amp;nbsp;중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추적은&amp;nbsp;시스템에&amp;nbsp;대한&amp;nbsp;추가&amp;nbsp;오버헤드입니다.&lt;/li&gt;
&lt;li&gt;IO/로그에&amp;nbsp;기록합니다.&amp;nbsp;따라서&amp;nbsp;디스크&amp;nbsp;공간을&amp;nbsp;차지합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은&amp;nbsp;특히 High Frequency 또는 High Volume 시스템을&amp;nbsp;추적할&amp;nbsp;때&amp;nbsp;중요합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서&amp;nbsp;실제&amp;nbsp;프로덕션&amp;nbsp;시스템에서&amp;nbsp;추적&amp;nbsp;프로그램을&amp;nbsp;시작할&amp;nbsp;때&amp;nbsp;다음을&amp;nbsp;사용하는&amp;nbsp;것이&amp;nbsp;실제로&amp;nbsp;더&amp;nbsp;좋습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1658393727769&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.tracer(:process, {fn _, 5 -&amp;gt; :dbg.stop_clear()
                        msg, n -&amp;gt; IO.inspect(msg); n+1 end, 0})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;첫&amp;nbsp;번째&amp;nbsp;함수&amp;nbsp;절은&amp;nbsp;추적자에게&amp;nbsp;5개의&amp;nbsp;이벤트가&amp;nbsp;발생한&amp;nbsp;후&amp;nbsp;중지하도록&amp;nbsp;지시합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두&amp;nbsp;번째 절은&amp;nbsp;추적자에게&amp;nbsp;수신&amp;nbsp;이벤트를&amp;nbsp;처리하는&amp;nbsp;방법을&amp;nbsp;알려줍니다.&amp;nbsp;이&amp;nbsp;경우에는&amp;nbsp;인쇄만&amp;nbsp;하고&amp;nbsp;카운터를&amp;nbsp;증가시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;All Together&lt;/h3&gt;
&lt;pre id=&quot;code_1658393823843&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.start
:dbg.tracer(:process, {fn _, 5 -&amp;gt; :dbg.stop_clear()
                        msg, n -&amp;gt; IO.inspect(msg); n+1 end, 0})
:dbg.tpl(Enum, :map, [])
:dbg.p(:all, :c)

# With trace
Enum.map([1,2,3,4], &amp;amp; &amp;amp;1 + 1)
Enum.map([1,2,3,4], &amp;amp; &amp;amp;1 + 1)
Enum.map([1,2,3,4], &amp;amp; &amp;amp;1 + 1)
Enum.map([1,2,3,4], &amp;amp; &amp;amp;1 + 1)
Enum.map([1,2,3,4], &amp;amp; &amp;amp;1 + 1)

# No more trace
Enum.map([1,2,3,4], &amp;amp; &amp;amp;1 + 1)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;때로는&amp;nbsp;함수에&amp;nbsp;전달되는&amp;nbsp;인수보다&amp;nbsp;더&amp;nbsp;많은&amp;nbsp;것을&amp;nbsp;알고&amp;nbsp;싶을&amp;nbsp;수도&amp;nbsp;있고,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Return Value&amp;nbsp;또는&amp;nbsp;함수가&amp;nbsp;실행될&amp;nbsp;때의&amp;nbsp;타임스탬프를&amp;nbsp;알고&amp;nbsp;싶을&amp;nbsp;수도&amp;nbsp;있습니다.&lt;br /&gt;위에서&amp;nbsp;사용한&amp;nbsp;일부&amp;nbsp;함수에&amp;nbsp;더&amp;nbsp;많은&amp;nbsp;인수를&amp;nbsp;제공하여&amp;nbsp;이를&amp;nbsp;달성할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;Return Value 를 Trace하고 싶다면 다음과&amp;nbsp;같이&amp;nbsp;:dbg.tpl에&amp;nbsp;더&amp;nbsp;많은&amp;nbsp;옵션을&amp;nbsp;지정할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658393951667&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.start
:dbg.tracer

:dbg.tpl(Enum, :map, 2, [{:_, [], [{:return_trace}]}])

:dbg.p(:all, :c)

Enum.map([1,2,3], &amp;amp; &amp;amp;1 + 1)
# (&amp;lt;0.106.0&amp;gt;) call 'Elixir.Enum':map([1,2,3],#Fun&amp;lt;erl_eval.44.97283095&amp;gt;)
# (&amp;lt;0.106.0&amp;gt;) returned from 'Elixir.Enum':map/2 -&amp;gt; [2,3,4]
# [2,3,4]

:dbg.stop&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;* 추가&amp;nbsp;옵션 MatchSpec 은 Document 에서 참고하세요&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수&amp;nbsp;호출의&amp;nbsp;타임스탬프를&amp;nbsp;포함하려면&amp;nbsp;:dbg.p를&amp;nbsp;호출할&amp;nbsp;때&amp;nbsp;:timestamp를&amp;nbsp;포함할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658394017469&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.start
:dbg.tracer
:dbg.tpl(Enum, :map, 2, [{:_, [], [{:return_trace}]}])

:dbg.p(:all, [:c, :timestamp])

Enum.map([1,2,3,4], &amp;amp; &amp;amp;1 + 1)
# [2, 3, 4, 5]
# (&amp;lt;0.105.0&amp;gt;) call 'Elixir.Enum':map([1,2,3,4],#Fun&amp;lt;erl_eval.44.40011524&amp;gt;) (Timestamp: {1624, 687361, 187278})
# (&amp;lt;0.105.0&amp;gt;) returned from 'Elixir.Enum':map/2 -&amp;gt; [2,3,4,5] (Timestamp: {1624, 687361, 187303})
# ^ The timestmap is in Erlang Timestamp tuple format.

:dbg.stop&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;보다&amp;nbsp;구체적인&amp;nbsp;함수&amp;nbsp;호출&amp;nbsp;추적&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;특정&amp;nbsp;인수(예:&amp;nbsp;사용자&amp;nbsp;ID&amp;nbsp;또는&amp;nbsp;특정&amp;nbsp;범주)로&amp;nbsp;호출된&amp;nbsp;함수만&amp;nbsp;추적할&amp;nbsp;수도&amp;nbsp;있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;:dbg.tpl에&amp;nbsp;대한&amp;nbsp;MatchSpec을&amp;nbsp;수정하여&amp;nbsp;이를&amp;nbsp;수행할&amp;nbsp;수&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1658394220399&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.tpl(Enum, :map, 2, [{[[1, 2, 3], :_], [], [{:return_trace}]}])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;MatchSpec의&amp;nbsp;첫&amp;nbsp;번째&amp;nbsp;튜플에&amp;nbsp;있는&amp;nbsp;첫&amp;nbsp;번째&amp;nbsp;인수는&amp;nbsp;일치시키려는&amp;nbsp;함수&amp;nbsp;매개변수입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서&amp;nbsp;Enum.map/2를&amp;nbsp;다음과&amp;nbsp;일치시키려고&amp;nbsp;합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;첫&amp;nbsp;번째&amp;nbsp;매개변수&amp;nbsp;일치&amp;nbsp;[1,2,3]&lt;/li&gt;
&lt;li&gt;두&amp;nbsp;번째&amp;nbsp;매개변수&amp;nbsp;일치&amp;nbsp;:_는&amp;nbsp;무엇이든&amp;nbsp;됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;:return_trace를&amp;nbsp;둘러싸는&amp;nbsp;{}에&amp;nbsp;유의하세요. Tracer가 Return Value 도&amp;nbsp;추적할&amp;nbsp;수&amp;nbsp;있도록&amp;nbsp;하는&amp;nbsp;것이&amp;nbsp;중요합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658394409747&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.start
:dbg.tracer

:dbg.tpl(Enum, :map, 2, [{[[1, 2, 3], :_], [], [{:return_trace}]}])

:dbg.p(:all, :c)

Enum.map([1,2,3], &amp;amp; &amp;amp;1 + 1)
# (&amp;lt;0.106.0&amp;gt;) call 'Elixir.Enum':map([1,2,3],#Fun&amp;lt;erl_eval.44.97283095&amp;gt;)
# (&amp;lt;0.106.0&amp;gt;) returned from 'Elixir.Enum':map/2 -&amp;gt; [2,3,4]
# [2, 3, 4]

Enum.map([1,2], &amp;amp; &amp;amp;1 + 1)
# Nothing is logged
# [2, 3]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한&amp;nbsp;시나리오에서는&amp;nbsp;매치&amp;nbsp;스펙을&amp;nbsp;작성하기&amp;nbsp;어려울&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운&amp;nbsp;좋게도&amp;nbsp;:dbg.fun2ms를&amp;nbsp;사용하여&amp;nbsp;함수를&amp;nbsp;일치&amp;nbsp;사양으로&amp;nbsp;변환할&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658394512541&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.fun2ms(fn [[1,2,3], _] -&amp;gt; :return_trace end)
# [{[1, 2, 3], [], [:return_trace]}]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그러나 MatchSpec이&amp;nbsp;완전히&amp;nbsp;정확하지는&amp;nbsp;않습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Return Value 추적이 올바르게&amp;nbsp;작동하려면&amp;nbsp;{}로&amp;nbsp;래핑해야&amp;nbsp;합니다.&amp;nbsp;그래서&amp;nbsp;이것은&amp;nbsp;작동하지&amp;nbsp;않을&amp;nbsp;것입니다:&lt;/p&gt;
&lt;pre id=&quot;code_1658394644257&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.start
:dbg.tracer

match_spec = :dbg.fun2ms(fn [[1,2,3], _] -&amp;gt; :return_trace end)
:dbg.tpl(Enum, :map, match_spec)
:dbg.p(:all, :c)

# With trace of function call but no return value
Enum.map([1,2,3], &amp;amp; &amp;amp;1 + 1)
# (&amp;lt;0.105.0&amp;gt;) call 'Elixir.Enum':map([1,2,3],#Fun&amp;lt;erl_eval.44.40011524&amp;gt;)
# [2, 3, 4]

:dbg.stop&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;따라서&amp;nbsp;일치&amp;nbsp;사양을&amp;nbsp;약간&amp;nbsp;변형해야&amp;nbsp;합니다.&amp;nbsp;방법은&amp;nbsp;다음과&amp;nbsp;같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658394722381&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;:dbg.start
:dbg.tracer

match_spec = :dbg.fun2ms(fn [[1,2,3], _] -&amp;gt; :return_trace end)
match_spec = Enum.map(match_spec, fn {args, guards, [:return_trace]} -&amp;gt;
  {args, guards, [{:return_trace}]}
end)

:dbg.tpl(Enum, :map, match_spec)
:dbg.p(:all, :c)

# With trace of function call and return value.
Enum.map([1,2,3], &amp;amp; &amp;amp;1 + 1)
# (&amp;lt;0.105.0&amp;gt;) call 'Elixir.Enum':map([1,2,3],#Fun&amp;lt;erl_eval.44.40011524&amp;gt;)
# (&amp;lt;0.105.0&amp;gt;) returned from 'Elixir.Enum':map/2 -&amp;gt; [2,3,4]
# [2, 3, 4]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Summary&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;:dbg는 Low Level의 디버깅 툴 입니다. 더&amp;nbsp;간단한&amp;nbsp;인터페이스를&amp;nbsp;선호한다면&amp;nbsp;recon에서&amp;nbsp;recon_trace를&amp;nbsp;사용하는&amp;nbsp;것을&amp;nbsp;고려하십시오.&lt;br /&gt;recon_trace에&amp;nbsp;비해&amp;nbsp;:dbg의&amp;nbsp;이점&amp;nbsp;중&amp;nbsp;하나는&amp;nbsp;내장되어&amp;nbsp;있다는&amp;nbsp;것입니다.&amp;nbsp;코드베이스에&amp;nbsp;추가&amp;nbsp;종속성을&amp;nbsp;추가할&amp;nbsp;필요가&amp;nbsp;없습니다.&amp;nbsp;그러나&amp;nbsp;특히&amp;nbsp;라이브&amp;nbsp;프로덕션&amp;nbsp;시스템에서&amp;nbsp;이&amp;nbsp;작업을&amp;nbsp;많이&amp;nbsp;수행하는&amp;nbsp;경우에는&amp;nbsp;recon을&amp;nbsp;종속&amp;nbsp;항목으로&amp;nbsp;추가하고&amp;nbsp;대신&amp;nbsp;recon_trace를&amp;nbsp;사용하는&amp;nbsp;것이&amp;nbsp;좋습니다.&lt;br /&gt;&lt;br /&gt;Recon은&amp;nbsp;단순한 trace보다&amp;nbsp;훨씬&amp;nbsp;더&amp;nbsp;많은&amp;nbsp;도구를&amp;nbsp;제공합니다.&amp;nbsp;또한&amp;nbsp;시스템을&amp;nbsp;안전하게&amp;nbsp;진단할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;이와&amp;nbsp;같은&amp;nbsp;주제에&amp;nbsp;관심이&amp;nbsp;있다면&amp;nbsp;Recon의&amp;nbsp;저자가&amp;nbsp;recon&amp;nbsp;등으로&amp;nbsp;BEAM&amp;nbsp;응용&amp;nbsp;프로그램을&amp;nbsp;진단하는&amp;nbsp;것에&amp;nbsp;대해&amp;nbsp;쓴&amp;nbsp;Erlang&amp;nbsp;in&amp;nbsp;Anger의&amp;nbsp;무료&amp;nbsp;사본을&amp;nbsp;얻을&amp;nbsp;수도&amp;nbsp;있습니다.&lt;br /&gt;&lt;br /&gt;정찰과&amp;nbsp;함께&amp;nbsp;추적을&amp;nbsp;사용하는&amp;nbsp;방법에&amp;nbsp;대해&amp;nbsp;자세히&amp;nbsp;알아보려면&amp;nbsp;&lt;a href=&quot;https://kaiwern.com/posts/2021/06/27/debugging-with-tracing-in-elixir-with-recon_trace/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;에서도&amp;nbsp;읽을&amp;nbsp;수&amp;nbsp;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 내용은 Livebook 내용에 Kai 블로그를 번역하여 추가하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문은 &lt;a href=&quot;https://kaiwern.com/posts/2020/11/02/debugging-with-tracing-in-elixir/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kaiwern.com/posts/2020/11/02/debugging-with-tracing-in-elixir/ &lt;/a&gt;를 참고하세요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>기술 동향</category>
      <author>gozalex</author>
      <guid isPermaLink="true">https://elixian.tistory.com/17</guid>
      <comments>https://elixian.tistory.com/17#entry17comment</comments>
      <pubDate>Thu, 21 Jul 2022 18:15:57 +0900</pubDate>
    </item>
    <item>
      <title>GenServer를 어떻게 종료할 것인가?</title>
      <link>https://elixian.tistory.com/15</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://alexcastano.com/how-to-stop-a-genserver-in-elixir/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://alexcastano.com/how-to-stop-a-genserver-in-elixir/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원문입니다.&lt;/p&gt;
&lt;figure id=&quot;og_1629882729911&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Why and how a GenServer stops?&quot; data-og-description=&quot;The different possibilities to stop a GenServer and how to handle the termination process.&quot; data-og-host=&quot;alexcastano.com&quot; data-og-source-url=&quot;https://alexcastano.com/how-to-stop-a-genserver-in-elixir/&quot; data-og-url=&quot;https://alexcastano.com/how-to-stop-a-genserver-in-elixir/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ceUyiv/hyLnEbZzya/d95zu3uI9O1EfmVhz6bFVK/img.png?width=110&amp;amp;height=110&amp;amp;face=30_36_74_84,https://scrap.kakaocdn.net/dn/FDZa0/hyLnuHeKa6/zULtJ4QVn8KcnQ7ihSHYWK/img.png?width=110&amp;amp;height=110&amp;amp;face=30_36_74_84&quot;&gt;&lt;a href=&quot;https://alexcastano.com/how-to-stop-a-genserver-in-elixir/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://alexcastano.com/how-to-stop-a-genserver-in-elixir/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ceUyiv/hyLnEbZzya/d95zu3uI9O1EfmVhz6bFVK/img.png?width=110&amp;amp;height=110&amp;amp;face=30_36_74_84,https://scrap.kakaocdn.net/dn/FDZa0/hyLnuHeKa6/zULtJ4QVn8KcnQ7ihSHYWK/img.png?width=110&amp;amp;height=110&amp;amp;face=30_36_74_84');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Why and how a GenServer stops?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The different possibilities to stop a GenServer and how to handle the termination process.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;alexcastano.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;u&gt;terminate/2&amp;nbsp;콜백&lt;/u&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;GenServer&lt;span&gt;가 중지되는 이유를 살펴보기 전에&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;terminate/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;콜백을 살펴보겠습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;필수 사항은 아니며 필요할 때만 구현할 수 있지만 중단하기 전에 무언가를 하고 싶다면 도움이 될 수 있습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;terminate/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;콜백&lt;/span&gt;&lt;span&gt;이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;실행&lt;/span&gt;&lt;span&gt;된&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이후에는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer&lt;span&gt;의 상태를 영원히 잃게 되므로&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;s&lt;/span&gt;&lt;span&gt;tate&lt;/span&gt;&lt;span&gt;를 변경할&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;마지막 기회입니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 함수는 두 개의 인수를 수신합니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;첫 번째 인수는 종료 이유이고 두 번째 인수는 프로세스의 마지막 상태입니다&lt;/span&gt;.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;u&gt;How a GenServer can stop itself&lt;/u&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1634533780392&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule Buggy do
  use GenServer

  @impl true
  def init(state) do
    {:ok, state}
  end

  @impl true
  def handle_info({:div, num}, state) do
    state = state + 1
    IO.inspect(&quot;:div received, updating state to: #{state}&quot;)
    IO.inspect(&quot;Divission = 100 / #{num} = #{100 / num}&quot;)
    {:noreply, state}
  end

  @impl true
  def terminate(reason, state) do
    IO.inspect(&quot;terminate/2 callback&quot;)
    IO.inspect({:reason, reason})
    IO.inspect({:state, state})
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;GenServer&amp;nbsp;프로세스 자체에서 중지하는 방법과 다른 프로세스에서&amp;nbsp;GenServer를 중지하는 두 가지 방법이 있습니다.&amp;nbsp;첫 번째 것부터 시작하겠습니다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629882866473&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid} = GenServer.start(Buggy, 0)
{:ok, #PID&amp;lt;0.139.0&amp;gt;}

iex&amp;gt; send(pid, {:div, 10})
{:div, 10}
&quot;:div received, updating state to: 1&quot;
&quot;Divission = 100 / 10 = 10.0&quot;

iex&amp;gt; send(pid, {:div, 0})
{:div, 0}
&quot;:div received, updating state to: 2&quot;
&quot;terminate/2 callback&quot;
{:reason,
 {:badarith,
  [
    {Buggy, :handle_info, 2, [file: 'buggy.ex', line: 13]},
    {:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 680]},
    {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 756]},
    {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 226]}
  ]}}
{:state, 1}
## Error log
&quot;&quot;&quot;
18:00:28.809 [error] GenServer #PID&amp;lt;0.139.0&amp;gt; terminating
** (ArithmeticError) bad argument in arithmetic expression
    buggy.ex:13: Buggy.handle_info/2
    (stdlib 3.13) gen_server.erl:680: :gen_server.try_dispatch/4
    (stdlib 3.13) gen_server.erl:756: :gen_server.handle_msg/6
    (stdlib 3.13) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:div, 0}
State: 1
&quot;&quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;terminate&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;콜백에 의해 수신된 상태가 마지막&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;handle_call/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;콜백이 호출되기 전의 마지막 상태라는 것을 확인하는 것은 흥미롭습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;업데이트된 상태를 반환할 기회가 없었으므로 이것이&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;동작이 할 수 있는 최선입니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이 패턴을 더 많이 볼 것이므로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;terminate&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;콜백&lt;/span&gt;&lt;/span&gt;&lt;span&gt;을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;개발할 때 염두에 두십시오&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629882901765&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid} = GenServer.start(Raising, 0)
{:ok, #PID&amp;lt;0.150.0&amp;gt;}

iex&amp;gt; send(pid, :raising)
&quot;:raising received, updating state to: 1&quot;
:raising
&quot;terminate/2 callback&quot;
{:reason,
 { %RuntimeError{message: &quot;Raising!&quot;},
  [
    {Raising, :handle_info, 2, [file: 'raising.ex', line: 13]},
    {:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 680]},
    {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 756]},
    {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 226]}
  ]}}
{:state, 0}
## Error log
&quot;&quot;&quot;
18:08:25.685 [error] GenServer #PID&amp;lt;0.150.0&amp;gt; terminating
** (RuntimeError) Raising!
    raising.ex:13: Raising.handle_info/2
    (stdlib 3.13) gen_server.erl:680: :gen_server.try_dispatch/4
    (stdlib 3.13) gen_server.erl:756: :gen_server.handle_msg/6
    (stdlib 3.13) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: :raising
State: 0
&quot;&quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Raise Exception&lt;/span&gt;&lt;span&gt;은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;위와&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;비슷합니다&lt;/span&gt;&lt;span&gt;. Log&lt;/span&gt;&lt;span&gt;를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;남기며&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;죽습니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;u&gt;Return :stop in a callback&lt;/u&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1634533833020&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule Stop do
  use GenServer

  @impl true
  def init(state) do
    {:ok, state}
  end

  @impl true
  def handle_info({:quit, reason}, state) do
    state = state + 1
    IO.inspect(&quot;:quit received, updating state to: #{state}&quot;)
    {:stop, reason, state}
  end
  
  @impl true
  def handle_info({:exit, reason}, _state) do
    IO.inspect(&quot;:exit received&quot;)
    exit(reason)
  end

  @impl true
  def terminate(reason, state) do
    IO.inspect(&quot;terminate/2 callback&quot;)
    IO.inspect({:reason, reason})
    IO.inspect({:state, state})
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Exception&lt;/span&gt;&lt;span&gt;이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;발생하던&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;아니면&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;인위적으로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Exception&lt;/span&gt;&lt;span&gt;을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;발생&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시키던&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;상관&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;없습니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;그러나&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;대부분의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;경우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;GenServer&lt;/span&gt;&lt;span&gt;를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;중지하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가장&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;적절한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;방법은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;거의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;콜백에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;{:stop, reason, state}&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;튜플을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;반환하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;것입니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629882941849&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid} = GenServer.start(Stop, 0)
{:ok, #PID&amp;lt;0.160.0&amp;gt;}

iex&amp;gt; send(pid, {:quit, :normal})
{:quit, :normal}
&quot;:quit received, updating state to: 1&quot;
&quot;terminate/2 callback&quot;
{:reason, :normal}
{:state, 1}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;State&lt;/span&gt;&lt;span&gt;도 업데이트가 되고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Log&lt;/span&gt;&lt;span&gt;도 남기지 않습니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;u&gt;Kernel.exit/1&lt;/u&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;{:stop, reason, state}&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;튜플을 반환하는 것과 매우 유사한 동작을 합니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;이 함수는 현재 프로세스&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;이 경우에는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer)&lt;/span&gt;&lt;span&gt;에 종료 신호를 보냅니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629882980234&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid} = GenServer.start(Exit, 0)
{:ok, #PID&amp;lt;0.192.0&amp;gt;}
iex&amp;gt; send(pid, {:exit, :normal})
{:exit, :normal}
&quot;:exit received&quot;
&quot;terminate/2 callback&quot;
{:reason, :normal}
{:state, 0}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;{:stop, reason, state}&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;튜플을 반환하는 것과 마찬가지로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Log&lt;/span&gt;&lt;span&gt;를 남기지 않고 죽습니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다만&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;handle_info/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;exit/1&lt;/span&gt;&lt;span&gt;로 빠져나와 별도의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;State&lt;/span&gt;&lt;span&gt;를 관리하는 리턴 값이 없으므로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;State&lt;/span&gt;&lt;span&gt;를 변경할 수는 없습니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;Important note about the &amp;ldquo;reason&amp;rdquo;&lt;/span&gt;&lt;/u&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;{:stop, reason, state}&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;튜플을 반환하는 것과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;exit(reason)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 통해 우리는&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 중지하는&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;reason&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 조작할 수 있습니다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 이유는&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;OTP&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 대한 다른 중요한 의미가 있습니다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정상적인&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot; reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;값으로 간주되는 세 가지 값이 있습니다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;:normal&lt;/li&gt;
&lt;li&gt;:shutdown&lt;/li&gt;
&lt;li&gt;{:shutdown, term}&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;만약&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;reason&lt;/span&gt;&lt;span&gt;이 위의 세 값과 다르면 어떻게 될까요&lt;/span&gt;&lt;span&gt;? GenServer Document&lt;/span&gt;&lt;span&gt;에 따르면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;&amp;ldquo;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;정상적인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;reason&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;값이 아닌&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;&amp;rdquo;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;다른 이유로 종료하면 비정상으로 간주되어 충돌로 처리됩니다&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;이는&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;OTP&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;기본&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;Supervisor&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;동작이 시작되고 오류 보고서가 내보내지는 등의 작업을 의미합니다&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;.&amp;rdquo;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 말이죠&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1629883155897&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid} = GenServer.start(Exit, 0)
{:ok, #PID&amp;lt;0.204.0&amp;gt;}
iex&amp;gt; send(pid, {:exit, :my_own_reason})
{:exit, :my_own_reason}
&quot;:exit received&quot;
&quot;terminate/2 callback&quot;
{:reason, :my_own_reason}
{:state, 0}
## Error log
&quot;&quot;&quot;
18:34:29.527 [error] GenServer #PID&amp;lt;0.204.0&amp;gt; terminating
** (stop) :my_own_reason
    exit.ex:12: Exit.handle_info/2
    (stdlib 3.13) gen_server.erl:680: :gen_server.try_dispatch/4
    (stdlib 3.13) gen_server.erl:756: :gen_server.handle_msg/6
    (stdlib 3.13) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:exit, :my_own_reason}
State: 0
&quot;&quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;{:stop, :my_own_reason, state}&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;도&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마찬가지입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;u&gt;How a GenServer can be stopped externally&lt;/u&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;우리는&amp;nbsp;이미&amp;nbsp;GenServer가&amp;nbsp;스스로를&amp;nbsp;멈출&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;방법을&amp;nbsp;보았습니다.&amp;nbsp;이제&amp;nbsp;다른&amp;nbsp;프로세스가&amp;nbsp;동일한&amp;nbsp;작업을&amp;nbsp;수행할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;방법을&amp;nbsp;살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #5f6368;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;u&gt;GenServer.stop/3&lt;/u&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 함수는&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;PID(&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또는&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이름으로 간주될 수 있는 모든 값&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 수신하여 중지&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;reason&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;와&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;timeout&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 수신합니다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;. timeout&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매개변수로 인해 상상할 수 있듯이 이 기능은 동기식이며&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 완전히 중지될 때까지 계속되지 않습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629883217355&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule GenServerStop do
use GenServer

  @impl true
  def init(state) do
    {:ok, state}
end

  @impl true
  def terminate(reason, state) do
    IO.inspect(&quot;terminate/2 callback&quot;)
    IO.inspect({:reason, reason})
    IO.inspect({:state, state})
    IO.inspect(&quot;sleep before terminating&quot;)
    Process.sleep(1_000)
    IO.inspect(&quot;really terminating&quot;)
  end
end

iex&amp;gt; {:ok, pid} = GenServer.start(GenServerStop, 0)
{:ok, #PID&amp;lt;0.127.0&amp;gt;}
iex&amp;gt; GenServer.stop(pid)
&quot;terminate/2 callback&quot;
{:reason, :normal}
{:state, 0}
&quot;sleep before terminating&quot;
&quot;really terminating&quot;
:ok&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;reason&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 대한 기본값은&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:normal&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이고&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;timeout&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에 대한 기본값은&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;5_000&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;입니다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다시 말하지만&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, 종료&lt;span&gt;&amp;nbsp;Reason이&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;사용자 정의라면 다음과 같이 기록됩니다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629883245739&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid} = GenServer.start(GenServerStop, 0)
{:ok, #PID&amp;lt;0.131.0&amp;gt;}
iex&amp;gt; GenServer.stop(pid, :abnormal)
&quot;terminate/2 callback&quot;
{:reason, :abnormal}
{:state, 0}
&quot;sleep before terminating&quot;
&quot;really terminating&quot;
# Error log
&quot;&quot;&quot;
09:35:49.180 [error] GenServer #PID&amp;lt;0.131.0&amp;gt; terminating
** (stop) :abnormal
Last message: []
State: 0
&quot;&quot;&quot;
:ok&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;종료할 시간이 충분하지 않으면&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer.stop/3&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;함수가 반환되지 않고 반환되기 전에 충돌이 발생합니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;그러나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;t&lt;/span&gt;&lt;span&gt;erminate&lt;/span&gt;&lt;span&gt;/2&lt;span&gt;는 완료됩니다&lt;/span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;다음을 확인하세요&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629883281934&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid} = GenServer.start(GenServerStop, 0)
{:ok, #PID&amp;lt;0.135.0&amp;gt;}
iex&amp;gt; GenServer.stop(pid, :small_timeout, 100)
&quot;terminate/2 callback&quot;
{:reason, :small_timeout}
{:state, 0}
&quot;sleep before terminating&quot;
# Our current iex process exit because timeout, Error log:
&quot;&quot;&quot;
** (exit) exited in: GenServer.stop(#PID&amp;lt;0.135.0&amp;gt;, :small_timeout, 100)
    ** (EXIT) time out
    (elixir 1.10.3) lib/gen_server.ex:981: GenServer.stop/3
&quot;&quot;&quot;
# The GenServer process finishes anyway some milliseconds later
&quot;really terminating&quot;
# Error log because is not a normal reason:
&quot;&quot;&quot;
09:38:39.020 [error] GenServer #PID&amp;lt;0.135.0&amp;gt; terminating
** (stop) :small_timeout
Last message: []
State: 0
&quot;&quot;&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;u&gt;Link to another process&lt;/u&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1634534065394&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule Link do
  use GenServer

  @impl true
  def init(state) do
    IO.inspect({:init, self()})
    {:ok, state}
  end

  @impl true
  def handle_info({:link, link}, state) do
    Process.link(link)
    {:noreply, state}
  end

  @impl true
  def terminate(reason, state) do
    IO.inspect(&quot;terminate/2 callback in pid #{inspect(self())}&quot;)
    IO.inspect({:reason, reason})
    IO.inspect({:state, state})
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1629883324256&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid_1} = GenServer.start(Link, 0)
{:init, #PID&amp;lt;0.120.0&amp;gt;}
{:ok, #PID&amp;lt;0.120.0&amp;gt;}
iex&amp;gt; {:ok, pid_2} = GenServer.start(Link, 0)
{:init, #PID&amp;lt;0.122.0&amp;gt;}
{:ok, #PID&amp;lt;0.122.0&amp;gt;}
iex&amp;gt; send(pid_1, {:link, pid_2})
{:link, #PID&amp;lt;0.122.0&amp;gt;}
iex&amp;gt; GenServer.stop(pid_2, :my_own_reason)
terminate/2 callback in pid #PID&amp;lt;0.122.0&amp;gt;
{:reason, :my_own_reason}
{:state, 0}
# Error log from pid 2:
&quot;&quot;&quot;
18:57:10.499 [error] GenServer #PID&amp;lt;0.122.0&amp;gt; terminating
** (stop) :my_own_reason
Last message: []
State: 0
&quot;&quot;&quot;
:ok
iex&amp;gt; Process.alive?(pid_1)
false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;우리는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid_2&lt;span&gt;를 중지했고 그것이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;terminate&lt;/span&gt;&lt;span&gt;/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;콜백을 실행하는 것을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;확인할 수 있&lt;/span&gt;&lt;span&gt;습니다&lt;/span&gt;&lt;span&gt;. pid_1&lt;span&gt;의 경우에도 마찬가지입니다&lt;/span&gt;. pid_1&lt;span&gt;로 실행 중인&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer&lt;span&gt;가&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid_2&lt;span&gt;에 연결되어 종료되었습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;흥미롭게도&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid_1&lt;span&gt;에 대해&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;terminate/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;콜백이 전혀 호출되지 않았습니다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;반면&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;GenServer.stop(pid_2, :normal)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사용하면&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;pid_2&lt;/span&gt;&lt;span&gt;는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;종료되지만&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;pid_1&lt;/span&gt;&lt;span&gt;은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;살아있습니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;경우는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;pid_2&lt;/span&gt;&lt;span&gt;의&lt;/span&gt;&lt;span&gt;Supervisor Strategy&lt;span&gt;에 따라 다르게 동작합니다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;:permanent&amp;nbsp;- the child process is always restarted.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;:temporary&amp;nbsp;- the child process is never restarted, regardless of the supervision strategy: any termination (even abnormal) is considered successful.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;:transient&amp;nbsp;- the child process is restarted only if it terminates abnormally, i.e., with an exit reason other than&amp;nbsp;:normal,&amp;nbsp;:shutdown, or&amp;nbsp;{:shutdown, term}.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;u&gt;Trapping Exit Signal&lt;/u&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 기본 동작을 수정할 수 있는 한 가지 방법은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt;xit Signal&lt;/span&gt;&lt;span&gt;을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Trapping&lt;/span&gt;&lt;span&gt;하는 것입니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;프로세스가 죽으면 연결된 프로세스는 종료 신호를 받습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;두 가지 가능성이 있습니다&lt;/span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스는 종료 신호를 트랩하지 않으므로 동일한 이유로 종료됩니다.&lt;/li&gt;
&lt;li&gt;프로세스는 종료 신호를 트랩하므로 일반 메시지로 변환됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1629883389732&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule TrapLink do
use GenServer

  @impl true
  def init(state) do
    # Trap exits
    Process.flag(:trap_exit, true)
    {:ok, state}
  end

  @impl true
  def handle_info({:link, link}, state) do
    Process.link(link)
    {:noreply, state}
  end

  def handle_info(msg, state) do
    IO.inspect({:handle_info, self(), msg, state})
    {:noreply, state}
  end

  @impl true
  def terminate(reason, state) do
    IO.inspect(&quot;terminate/2 callback in pid #{inspect(self())}&quot;)
    IO.inspect({:reason, reason})
    IO.inspect({:state, state})
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;마지막 경우의 예는 다음과 같습니다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629883407632&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid_1} = GenServer.start(TrapLink, 0)
{:ok, #PID&amp;lt;0.187.0&amp;gt;}
iex&amp;gt; {:ok, pid_2} = GenServer.start(TrapLink, 0)
{:ok, #PID&amp;lt;0.189.0&amp;gt;}
iex&amp;gt; send(pid_1, {:link, pid_2})
{:link, #PID&amp;lt;0.189.0&amp;gt;}
iex&amp;gt; GenServer.stop(pid_2, :normal)
&quot;terminate/2 callback in pid #PID&amp;lt;0.189.0&amp;gt;&quot;
{:reason, :normal}
{:state, 0}
# This message is received by the pid_1
{:handle_info, {:EXIT, #PID&amp;lt;0.189.0&amp;gt;, :normal}, 0}
:ok
iex&amp;gt; Process.alive?(pid_1)
true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이번에는&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid_1&lt;span&gt;에서 실행 중인&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer&lt;span&gt;가 살아남았습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;죽지 않았기 때문에&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;terminate/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;콜백도 호출되지 않았습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;대신&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;handle_info/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;콜백에서&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;{:EXIT, #PID&amp;lt;0.189.0&amp;gt;, :normal}&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;메시지를 받았습니다&lt;/span&gt;. &quot;&lt;span&gt;정상적인&lt;/span&gt;&quot;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이유가 아닌 경우에도 동일한 동작이 발생합니다&lt;/span&gt;.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;위는 정상적인 종료&lt;/span&gt;&lt;span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;아래는 비정상 종료의 예입니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629883438750&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid_1} = GenServer.start(TrapLink, 0)
{:ok, #PID&amp;lt;0.198.0&amp;gt;}
iex&amp;gt; {:ok, pid_2} = GenServer.start(TrapLink, 0)
{:ok, #PID&amp;lt;0.200.0&amp;gt;}
iex&amp;gt; send(pid_1, {:link, pid_2})
{:link, #PID&amp;lt;0.200.0&amp;gt;}
iex&amp;gt; GenServer.stop(pid_2, :abnormal)
&quot;terminate/2 callback in pid #PID&amp;lt;0.200.0&amp;gt;&quot;
{:reason, :abnormal}
{:state, 0}
# Error log from pid_2:
&quot;&quot;&quot;
19:28:14.982 [error] GenServer #PID&amp;lt;0.200.0&amp;gt; terminating
** (stop) :abnormal
Last message: []
State: 0
&quot;&quot;&quot;
# This message is received by the pid_1
{:handle_info, {:EXIT, #PID&amp;lt;0.200.0&amp;gt;, :abnormal}, 0}
:ok&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;물론&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;, handle_info/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;콜백에서 우리는 이전에 본 다른 방법 중 하나를 사용하여&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer&lt;span&gt;를 중지하기로 결정할 수 있었습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;그러나 요점은 연결된 프로세스가 죽을 때 종료 신호를 트랩하면&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer&lt;span&gt;가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Trap&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;한 프로세스는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;죽지 않는다는 것입니다&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이 작업은 수동으로 수행해야 합니다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;u&gt;Process.exit/2&lt;/u&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;우리는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Exit Signal&lt;/span&gt;&lt;span&gt;에 대해 배웠습니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;모든 프로세스는 다른 프로세스에 종료 신호를 보낼 수 있습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이를 위해&lt;/span&gt;Process.exit/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;함수를 사용할 수 있습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이전 예에서와 같이 이 함수를 호출한 결과는 신호가 트랩되었는지 여부에 따라 달라집니다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;GenServer.stop(pid, :normal)&lt;/span&gt;&lt;span&gt;은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;해당&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;pid&lt;/span&gt;&lt;span&gt;를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;죽이지만&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Process.exit(pid, :normal)&lt;/span&gt;&lt;span&gt;은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;해당&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;pid&lt;/span&gt;&lt;span&gt;를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;죽이지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;않습니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;헷갈리지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;마세요&lt;/span&gt;&lt;span&gt;~&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629883480521&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule ExternalExit do
use GenServer

  @impl true
  def init(state) do
    {:ok, state}
end

  @impl true
  def handle_info(:trap, state) do
    Process.flag(:trap_exit, true)
    {:noreply, state}
end

  def handle_info(msg, state) do
    IO.inspect({:info, msg, state})
    {:noreply, state}
end

  @impl true
  def terminate(reason, state) do
    IO.inspect(&quot;terminate/2 callback&quot;)
    IO.inspect({:reason, reason})
    IO.inspect({:state, state})
  end
end

iex&amp;gt; {:ok, pid} = GenServer.start(ExternalExit, 0)
{:ok, #PID&amp;lt;0.156.0&amp;gt;}
iex&amp;gt; Process.exit(pid, :abnormal)
true
iex&amp;gt; Process.alive?(pid)
false
iex&amp;gt; {:ok, pid} = GenServer.start(ExternalExit, 0)
{:ok, #PID&amp;lt;0.160.0&amp;gt;}
iex&amp;gt; Process.exit(pid, :shutdown)
true
iex&amp;gt; Process.alive?(pid)
false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그리고 다시&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;말하지만&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;외부에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Process.exit/2&lt;/span&gt;&lt;span&gt;를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;이용해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;GenServer&lt;span&gt;를 죽이는 경우&lt;/span&gt;, GenServer&lt;span&gt;는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Exit Signal&lt;span&gt;로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;terminate/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;콜백을 실행하지 않습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;신호를 받자마자 죽습니다&lt;/span&gt;.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;위의 다른 경우와는 다르게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;:shutdown reason&lt;/span&gt;&lt;span&gt;으로 프로세스를 죽이면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;normal&lt;/span&gt;&lt;span&gt;과 유사하게 동작하지 않습니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;오히려 비정상&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;처럼 동작합니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;즉&lt;/span&gt;&lt;span&gt;, :normal reason&lt;/span&gt;&lt;span&gt;만이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;ldquo;&lt;/span&gt;&lt;span&gt;정상적인 이유&lt;/span&gt;&lt;span&gt;&amp;rdquo;&lt;/span&gt;&lt;span&gt;로 프로세스를 종료할 수 있습니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;normal&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;의 의미는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;Internal Exit&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;이면 정상적 종료로 해석되고&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;External Exit&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;면 종료되지 않습니다&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;외부에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;&amp;ldquo;&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;정상 종료&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;&amp;rdquo;&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;라는 것을 할 수 없다고 보기 때문입니다&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;.&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;shutdown&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;의 경우&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;Internal Exit&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;면 의도한 정상 종료로 해석되고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;External Exit&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;이면 외부에서 누군가가&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;shutdown&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;한 것이므로 비정상으로 해석합니다&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span style=&quot;color: #404040;&quot;&gt;.&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span&gt;반면 신호가 트랩되면 수동으로 원하지 않는 한 죽지 않습니다&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;span&gt;.&lt;/span&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;u&gt;&lt;/u&gt;&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1629883516780&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid} = GenServer.start(ExternalExit, 0)
{:ok, #PID&amp;lt;0.164.0&amp;gt;}
iex&amp;gt; send(pid, :trap)
:trap
iex&amp;gt; Process.exit(pid, :abnormal)
{:info, {:EXIT, #PID&amp;lt;0.111.0&amp;gt;, :abnormal}, 0}
true
iex&amp;gt; Process.alive?(pid)
true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Process.exit/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;기능을 사용할 때 이전 동작에 대한 두 가지 예외가 있습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;첫째&lt;/span&gt;, normal reason&lt;span&gt;를 사용할 때입니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이 경우 문서에는 다음과 같이 나와 있습니다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width=&quot;601&quot;&gt;&lt;span&gt;&lt;b&gt;&lt;i&gt;&lt;span style=&quot;color: #404040;&quot;&gt;&amp;ldquo;&lt;span&gt;이유가&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;atom :normal&lt;span&gt;이면&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid&lt;span&gt;가 종료되지 않습니다&lt;/span&gt;(pid&lt;span&gt;가 호출 프로세스인 경우가 아니면&lt;/span&gt;:normal&lt;span&gt;로 종료됨&lt;/span&gt;).&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;종료를 트래핑하는 경우 종료 신호는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;{:EXIT, from, :normal}&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;메시지로 변환되어 해당 메시지 대기열로 전달 된다&lt;/span&gt;.&amp;rdquo;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;b&gt;&lt;i&gt;&lt;span&gt;&lt;/span&gt;&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre id=&quot;code_1629883540822&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid} = GenServer.start(ExternalExit, 0)
{:ok, #PID&amp;lt;0.169.0&amp;gt;}
iex&amp;gt; Process.exit(pid, :normal)
true
iex&amp;gt; Process.alive?(pid)
true
iex&amp;gt; send(pid, :trap)
:trap
iex&amp;gt; Process.exit(pid, :normal)
{:info, {:EXIT, #PID&amp;lt;0.111.0&amp;gt;, :normal}, 0}
true
iex&amp;gt; Process.alive?(pid)
true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;종료 신호를 트래핑하지 않은 경우에도 프로세스가 죽지 않았음을 알 수 있습니다&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;다른 예외는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:kill&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이유와 함께 사용할 때입니다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이유가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;atom :kill&lt;span&gt;인 경우&lt;/span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;즉&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Process.exit(pid, :kill)&lt;span&gt;이 호출되면 트래핑할 수 없는 종료 신호가&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid&lt;span&gt;로 전송되어 무조건&lt;/span&gt;reason :killed&lt;span&gt;와 함께 종료됩니다&lt;/span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1629883562457&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex&amp;gt; {:ok, pid} = GenServer.start(ExternalExit, 0)
{:ok, #PID&amp;lt;0.185.0&amp;gt;}
iex&amp;gt; send(pid, :trap)
:trap
iex&amp;gt; Process.exit(pid, :kill)
true
iex&amp;gt; Process.alive?(pid)
false&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #a1bbff;&quot;&gt;&lt;u&gt;결론&lt;/u&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;GenServer&lt;/span&gt;&lt;span&gt;를 종료하는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;가지 다른 방법이 있을 수 있습니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;우리는 그것들 모두를 살펴보지는 않았지만 가장 일반적인 것들을 공부했습니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;상황에 가장 적합한 것을 사용하십시오&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;마지막 권장 사항으로&lt;/span&gt;&lt;span&gt;, terminate/2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;콜백&lt;/span&gt;&lt;span&gt;이 항상 실행되는 것은 아니므로 맹목적으로 신뢰하지 마십시오&lt;/span&gt;&lt;span&gt;. GenServer&lt;/span&gt;&lt;span&gt;가 죽을 때 코드를 실행해야 하는 경우 종료 신호를 캡처하는 다른 연결된 프로세스를 만드는 것이 가장 좋습니다&lt;/span&gt;&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;코드는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;&lt;/span&gt;&lt;span&gt;링크 프로세스&lt;/span&gt;&lt;span&gt;&quot;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;예제와 매우 유사합니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;추가)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;terminate/2 콜백&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1. GenServer 외부에서 Process.exit(:abnormal) 로 죽였을 경우, terminate/2 콜백이 호출되지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;2. Link Process가 abnormal 로 종료되면 Linked Process 는 terminate/2 콜백이 호출되지 않는다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>기술 동향</category>
      <author>gozalex</author>
      <guid isPermaLink="true">https://elixian.tistory.com/15</guid>
      <comments>https://elixian.tistory.com/15#entry15comment</comments>
      <pubDate>Wed, 25 Aug 2021 18:26:43 +0900</pubDate>
    </item>
    <item>
      <title>Elixir Process</title>
      <link>https://elixian.tistory.com/14</link>
      <description>&lt;h1&gt;exit(pid, reason)&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sends an exit signal with the given&lt;span&gt;&amp;nbsp;&lt;/span&gt;reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;to&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The following behaviour applies if&lt;span&gt;&amp;nbsp;&lt;/span&gt;reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;is any term except&lt;span&gt;&amp;nbsp;&lt;/span&gt;:normal&lt;span&gt;&amp;nbsp;&lt;/span&gt;or&lt;span&gt;&amp;nbsp;&lt;/span&gt;:kill:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;If&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid&lt;span&gt;&amp;nbsp;&lt;/span&gt;is not trapping exits,&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid&lt;span&gt;&amp;nbsp;&lt;/span&gt;will exit with the given&lt;span&gt;&amp;nbsp;&lt;/span&gt;reason.&lt;/li&gt;
&lt;li&gt;If&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid&lt;span&gt;&amp;nbsp;&lt;/span&gt;is trapping exits, the exit signal is transformed into a message&lt;span&gt;&amp;nbsp;&lt;/span&gt;{:EXIT, from, reason}&lt;span&gt;&amp;nbsp;&lt;/span&gt;and delivered to the message queue of&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If&lt;span&gt;&amp;nbsp;&lt;/span&gt;reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;is the atom&lt;span&gt;&amp;nbsp;&lt;/span&gt;:normal,&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid&lt;span&gt;&amp;nbsp;&lt;/span&gt;will not exit (unless&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid&lt;span&gt;&amp;nbsp;&lt;/span&gt;is the calling process, in which case it will exit with the reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;:normal). If it is trapping exits, the exit signal is transformed into a message{:EXIT, from, :normal}&lt;span&gt;&amp;nbsp;&lt;/span&gt;and delivered to its message queue.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;If&lt;span&gt;&amp;nbsp;&lt;/span&gt;reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;is the atom&lt;span&gt;&amp;nbsp;&lt;/span&gt;:kill, that is if&lt;span&gt;&amp;nbsp;&lt;/span&gt;Process.exit(pid, :kill)&lt;span&gt;&amp;nbsp;&lt;/span&gt;is called, an untrappable exit signal is sent to&lt;span&gt;&amp;nbsp;&lt;/span&gt;pid&lt;span&gt;&amp;nbsp;&lt;/span&gt;which will unconditionally exit with reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;:killed.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Inlined by the compiler.&lt;/p&gt;
&lt;h2 id=&quot;exit/2-examples&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Examples&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Process.exit(pid, :kill) #=&amp;gt; true&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;a href=&quot;https://crypt.codemancers.com/posts/2016-01-24-understanding-exit-signals-in-erlang-slash-elixir/&quot;&gt;Understanding Exit Signals in Erlang/Elixir&lt;/a&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;Written by&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Emil Soman&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;on February 29, 2016;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #969386;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;Process linking and how processes send and handle exit signals&amp;rdquo; - a very important topic to understand in order to build robust apps in Erlang or Elixir, but also the source of a lot of confusions for beginners. In this post, we&amp;rsquo;ll cover this topic and understand it well, once and for all.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Note: Processes are the same in both Erlang and Elixir, so everything below is equally applicable to both languages.&lt;/p&gt;
&lt;h3 id=&quot;processes&quot; data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://crypt.codemancers.com/posts/2016-01-24-understanding-exit-signals-in-erlang-slash-elixir/#processes&quot;&gt;Processes&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Processes in Erlang are like threads that don&amp;rsquo;t share any data. These processes are VM level, so don&amp;rsquo;t confuse them with OS processes. These VM level processes are scheduled for execution by the Erlang VM, like how the OS schedules the OS level processes for execution. Since these Erlang processes own their own data, they are scheduled freely on all available CPUs and this is how Erlang makes concurrency easy for developers.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;624&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XgMUb/btq8ivF8Lzo/Z3xpGkbC9dSlDaMjyPjlWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XgMUb/btq8ivF8Lzo/Z3xpGkbC9dSlDaMjyPjlWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XgMUb/btq8ivF8Lzo/Z3xpGkbC9dSlDaMjyPjlWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXgMUb%2Fbtq8ivF8Lzo%2FZ3xpGkbC9dSlDaMjyPjlWK%2Fimg.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;624&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;But a bunch of processes that run in isolation are rarely of any use. To build anything useful, processes need to work together by communicating with each other.&lt;/p&gt;
&lt;h3 id=&quot;messages&quot; data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://crypt.codemancers.com/posts/2016-01-24-understanding-exit-signals-in-erlang-slash-elixir/#messages&quot;&gt;Messages&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In Erlang processes communicate among themselves by message passing. Every process has one mailbox. A process can read messages that appear in its mailbox and can also send messages to mailboxes that belong to other processes. This way, processes can communicate with each other without having to share any data. This frees developers from writing locks around data access when writing code that may run concurrently.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;624&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUY2vH/btq8mfINoJT/k8p9bbe9ljufkdFN47fmQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUY2vH/btq8mfINoJT/k8p9bbe9ljufkdFN47fmQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUY2vH/btq8mfINoJT/k8p9bbe9ljufkdFN47fmQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUY2vH%2Fbtq8mfINoJT%2Fk8p9bbe9ljufkdFN47fmQk%2Fimg.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;624&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Apart from these regular messages, processes also communicate using &amp;ldquo;exit signals&amp;rdquo;, a special type of message.&lt;/p&gt;
&lt;h3 id=&quot;exit-signals&quot; data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://crypt.codemancers.com/posts/2016-01-24-understanding-exit-signals-in-erlang-slash-elixir/#exit-signals&quot;&gt;Exit Signals&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Processes have a signalling mechanism by which they can let other processes know that they are exiting. These &amp;ldquo;exit signals&amp;rdquo; also contain an exit reason, which help other processes to decide how to react to the signal.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A process can terminate for 3 reasons:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;A normal exit&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;- This happens when a process is done with its job and ends execution. Since these exits are normal, usually nothing needs to be done when they happen. So these signals are usually ignored, but they are emitted anyway for the sake of interested processes. The exit reason for this kind of exit is the atom&lt;span&gt;&amp;nbsp;&lt;/span&gt;:normal.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Because of unhandled errors&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;- This happens when an exception is raised inside the process and not caught. A pattern matching error is an example - a technique used by Erlang programmers to &amp;ldquo;fail fast&amp;rdquo;. The exit reason for this kind of exit is the exception details - name of the exception and some stack trace.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Forcefully killed&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;- This happens when another process sends an exit signal with the reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;:kill, which forces the receiving process to terminate.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A process can subscribe to another process&amp;rsquo;s exit signal by establishing a &amp;ldquo;link&amp;rdquo; with that process. When a process terminates, all the linked processes receive the exit signal from the terminating process.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;624&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMmeeN/btq8mkXHOb1/4Bdxkq827bSN2FKTKfB5ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMmeeN/btq8mkXHOb1/4Bdxkq827bSN2FKTKfB5ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMmeeN/btq8mkXHOb1/4Bdxkq827bSN2FKTKfB5ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMmeeN%2Fbtq8mkXHOb1%2F4Bdxkq827bSN2FKTKfB5ck%2Fimg.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;624&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;624&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHFuLH/btq8iu1uSWL/S3zHGK3MDwZFNJnbl7VRJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHFuLH/btq8iu1uSWL/S3zHGK3MDwZFNJnbl7VRJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHFuLH/btq8iu1uSWL/S3zHGK3MDwZFNJnbl7VRJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHFuLH%2Fbtq8iu1uSWL%2FS3zHGK3MDwZFNJnbl7VRJK%2Fimg.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;624&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The force-kill signals, the ones with exit reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;:kill, will terminate the receiving process no matter what. But the other kinds of exit signals - those with reasons&lt;span&gt;&amp;nbsp;&lt;/span&gt;:normal&lt;span&gt;&amp;nbsp;&lt;/span&gt;or any other reason - can cause different effects on the receiving process depending on whether the receiving process is trapping exits or not. Let&amp;rsquo;s see how trapping of exit signals works.&lt;/p&gt;
&lt;h3 id=&quot;trapping-exits&quot; data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://crypt.codemancers.com/posts/2016-01-24-understanding-exit-signals-in-erlang-slash-elixir/#trapping-exits&quot;&gt;Trapping exits&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;When a process traps exit signals, the exit signals that are received from the links will be converted into messages which are then put inside the mailbox that belongs to the process. Here&amp;rsquo;s how a process can trap exits in Elixir:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #445588;&quot;&gt;Process&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span&gt;flag&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #990073;&quot;&gt;:trap_exit&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt; &lt;span&gt;receive&lt;/span&gt; &lt;span&gt;do&lt;/span&gt; &lt;span&gt;{&lt;/span&gt;&lt;span style=&quot;color: #990073;&quot;&gt;:EXIT&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;from&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;reason&lt;/span&gt;&lt;span&gt;}&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #999988;&quot;&gt;# Handle exit as needed&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;When this process receives an exit signal other than&lt;span&gt;&amp;nbsp;&lt;/span&gt;:kill&lt;span&gt;&amp;nbsp;&lt;/span&gt;signal, it will be converted into a message that will be received inside the&lt;span&gt;&amp;nbsp;&lt;/span&gt;receive&lt;span&gt;&amp;nbsp;&lt;/span&gt;block. In Erlang/Elixir, this is what makes supervisor trees possible.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A supervisor is a process whose responsibility is to start child processes and keep them alive by restarting them if necessary. Let&amp;rsquo;s see how a supervisor does that. If you look at&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/erlang/otp/blob/97ff595e4e0303f597e671b17045940ba8da0330/lib/stdlib/src/supervisor.erl#L285-L286&quot;&gt;the source code&lt;/a&gt;of supervisor in Erlang, you can see that the first thing that happens in the&lt;span&gt;&amp;nbsp;&lt;/span&gt;init&lt;span&gt;&amp;nbsp;&lt;/span&gt;function is trapping exit signals:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #990000;&quot;&gt;init&lt;/span&gt;&lt;span&gt;(...)&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #0086b3;&quot;&gt;process_flag&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;trap_exit&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;&lt;span&gt;),&lt;/span&gt; &lt;span&gt;...&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;This means that exit signals from child processes will be converted into messages. The supervisor then handles these messages by restarting the child processes, based on the restart strategy of the supervisor. This is how you write fault tolerant apps in Elixir or Erlang - you let your processes fail fast, and the supervisor that spawned these processes will make sure they are restarted.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;So if processes can trap exit signals, how is it possible to kill them? Using the&lt;span&gt;&amp;nbsp;&lt;/span&gt;:kill&lt;span&gt;&amp;nbsp;&lt;/span&gt;exit signal, of course. The exit reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;:kill&lt;span&gt;&amp;nbsp;&lt;/span&gt;is used to forcefully terminate the receiving process even if it&amp;rsquo;s trapping exits.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;In Elixir, this is how you kill a process using its pid:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #445588;&quot;&gt;Process&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span&gt;exit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;pid&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; &lt;span style=&quot;color: #990073;&quot;&gt;:kill&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A process can also send an exit signal to itself using:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #445588;&quot;&gt;Process&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;.&lt;/span&gt;&lt;span&gt;exit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;reason&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;The process responds to this signal from self in a similar manner it would respond to an exit signal it receives from another process, but with one exception. If a process sends itself an exit signal with the reason&lt;span&gt;&amp;nbsp;&lt;/span&gt;:normal, the process terminates and when it does, it sends a&lt;span&gt;&amp;nbsp;&lt;/span&gt;:normal&lt;span&gt;&amp;nbsp;&lt;/span&gt;exit signal to all linked processes.&lt;/p&gt;
&lt;h3 id=&quot;recap&quot; data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://crypt.codemancers.com/posts/2016-01-24-understanding-exit-signals-in-erlang-slash-elixir/#recap&quot;&gt;Recap&lt;/a&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;:normal&lt;span&gt;&amp;nbsp;&lt;/span&gt;exit signals are harmless. These are ignored by the receiving process unless trapping exits, in which case, these will be received as messages. If it&amp;rsquo;s sent by self, it will cause the process to terminate with a&lt;span&gt;&amp;nbsp;&lt;/span&gt;:normal&lt;span&gt;&amp;nbsp;&lt;/span&gt;exit reason.&lt;/li&gt;
&lt;li&gt;:kill&lt;span&gt;&amp;nbsp;&lt;/span&gt;exit signals always result in the termination of the receiving process.&lt;/li&gt;
&lt;li&gt;Exit signals with other reasons will terminate the receiving process unless trapping exits, in which case, these will be received as messages.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>기술 동향</category>
      <author>gozalex</author>
      <guid isPermaLink="true">https://elixian.tistory.com/14</guid>
      <comments>https://elixian.tistory.com/14#entry14comment</comments>
      <pubDate>Mon, 28 Jun 2021 19:57:51 +0900</pubDate>
    </item>
    <item>
      <title>Process Register</title>
      <link>https://elixian.tistory.com/13</link>
      <description>&lt;pre id=&quot;code_1617548152457&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule Segway.Context.Registry do
  use GenServer

  # API
  @doc &quot;&quot;&quot;
    ## start_link

    ## Examples
      iex&amp;gt; {:ok, pid} = GenServer.start_link(__MODULE__, &quot;room1&quot;)
      {:ok, #PID&amp;lt;0.107.0&amp;gt;}
  &quot;&quot;&quot;
  def start_link do
    # We register our registry (yeah, I know), with a simple name,
    # just so we can reference it in the other functions.
    GenServer.start_link(__MODULE__, nil, name: :registry)
  end

  @doc &quot;&quot;&quot;
    ## Examples
      iex&amp;gt; Segway.Context.Registry.whereis_name(&quot;room1&quot;)
      :undefined
  &quot;&quot;&quot;
  def whereis_name(room_name) do
    GenServer.call(:registry, {:whereis_name, room_name})
  end

  @doc &quot;&quot;&quot;
    ## Examples
      iex&amp;gt; Segway.Context.Registry.register_name(&quot;room1&quot;, pid)
      :yes

      iex&amp;gt; Segway.Context.Registry.register_name(&quot;room1&quot;, pid)
      :no

      iex&amp;gt; Segway.Context.Registry.whereis_name(&quot;room1&quot;)
      #PID&amp;lt;0.107.0&amp;gt;
  &quot;&quot;&quot;
  def register_name(room_name, pid) do
    GenServer.call(:registry, {:register_name, room_name, pid})
  end

  @doc &quot;&quot;&quot;
    ## Examples
      iex&amp;gt; Segway.Context.Registry.unregister_name(&quot;room1&quot;)
      :ok

      iex&amp;gt; Segway.Context.Registry.whereis_name(&quot;room1&quot;)
      :undefined
  &quot;&quot;&quot;
  def unregister_name(room_name) do
    GenServer.cast(:registry, {:unregister_name, room_name})
  end

  def send(room_name, message) do
    # If we try to send a message to a process
    # that is not registered, we return a tuple in the format
    # {:badarg, {process_name, error_message}}.
    # Otherwise, we just forward the message to the pid of this room.
    case whereis_name(room_name) do
      :undefined -&amp;gt;
        {:badarg, {room_name, message}}

      pid -&amp;gt;
        Kernel.send(pid, message)
        pid
    end
  end
  
  defp via_tuple(room_name) do
    # And the tuple always follow the same format:
    # {:via, module_name, term}
    {:via, Chat.Registry, {:chat_room, room_name}}
  end

  # SERVER
  def init(_) do
    {:ok, Map.new}
  end

  def handle_call({:whereis_name, room_name}, _from, state) do
    {:reply, Map.get(state, room_name, :undefined), state}
  end

  def handle_call({:register_name, room_name, pid}, _from, state) do
    # Registering a name is just a matter of putting it in our Map.
    # Our response tuple include a `:no` or `:yes` indicating if
    # the process was included or if it was already present.
    case Map.get(state, room_name) do
      nil -&amp;gt;
        {:reply, :yes, Map.put(state, room_name, pid)}

      _ -&amp;gt;
        {:reply, :no, state}
    end
  end

  def handle_cast({:unregister_name, room_name}, state) do
    # And unregistering is as simple as deleting an entry from our Map
    {:noreply, Map.delete(state, room_name)}
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;an atom - the GenServer is registered locally with the given name using Process.register/2.&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;{:global, term} - the GenServer is registered globally with the given term using the functions in the :global module.&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;{:via, module, term} - the GenServer is registered with the given mechanism and name.&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;(&lt;i&gt;The :via option expects a module that exports register_name/2, unregister_name/1, whereis_name/1 and send/2.)&lt;/i&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;via tuple (w/ Module that I want to use in order to register processes) 을 사용하여 다음과 같이 name option에 사용할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Process.register/2 는 locally 사용하는 경우 --&amp;gt; &amp;nbsp;:atom만 name(key for pids)으로 사용할 수 있지만&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;:via or :global 은 remote node에서도 사용할 수 있다. --&amp;gt; any type&lt;b&gt;(key for pids)으로 사용할 수 있다.&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1617548295962&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;defmodule Chat.Server do
  use GenServer

  # API

  def start_link(name) do
    # Instead of passing an atom to the `name` option, we send 
    # a tuple. Here we extract this tuple to a private method
    # called `via_tuple` that can be reused for every function
    GenServer.start_link(__MODULE__, [], name: via_tuple(name))
  end

  def add_message(room_name, message) do
    # And the `GenServer` callbacks will accept this tuple the same way it
    # accepts a `pid` or an atom.
    GenServer.cast(via_tuple(room_name), {:add_message, message})
  end

  def get_messages(room_name) do
    GenServer.call(via_tuple(room_name), :get_messages)
  end

  defp via_tuple(room_name) do
    # And the tuple always follow the same format:
    # {:via, module_name, term}
    {:via, Segway.Context.Registry, {:chat_room, room_name}}
  end

  # SERVER (no changes required here)
  # ...
end
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>기술 동향</category>
      <author>gozalex</author>
      <guid isPermaLink="true">https://elixian.tistory.com/13</guid>
      <comments>https://elixian.tistory.com/13#entry13comment</comments>
      <pubDate>Mon, 5 Apr 2021 00:04:04 +0900</pubDate>
    </item>
    <item>
      <title>Ecto Composable Query</title>
      <link>https://elixian.tistory.com/12</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/flatiron-labs/how-to-compose-queries-in-ecto-b71311729dac&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;medium.com/flatiron-labs/how-to-compose-queries-in-ecto-b71311729dac&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1605515160385&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;How to Compose Queries in Ecto&quot; data-og-description=&quot;Composable queries in Ecto including how to safely join through tables.&quot; data-og-host=&quot;medium.com&quot; data-og-source-url=&quot;https://medium.com/flatiron-labs/how-to-compose-queries-in-ecto-b71311729dac&quot; data-og-url=&quot;https://medium.com/flatiron-labs/how-to-compose-queries-in-ecto-b71311729dac&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/IrDA3/hyIfhd2Mr8/38mKf4UMicSvQX0Cfsh5sK/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675,https://scrap.kakaocdn.net/dn/bv8XG7/hyIgQFT5pF/Ekodc4aPILrSV77CuI06Y0/img.png?width=60&amp;amp;height=33&amp;amp;face=0_0_60_33,https://scrap.kakaocdn.net/dn/qwUMw/hyIfo5kNro/Z2FHxCSE4CZp9Q8DKXb71K/img.jpg?width=60&amp;amp;height=45&amp;amp;face=0_0_60_45&quot;&gt;&lt;a href=&quot;https://medium.com/flatiron-labs/how-to-compose-queries-in-ecto-b71311729dac&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/flatiron-labs/how-to-compose-queries-in-ecto-b71311729dac&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/IrDA3/hyIfhd2Mr8/38mKf4UMicSvQX0Cfsh5sK/img.png?width=1200&amp;amp;height=675&amp;amp;face=0_0_1200_675,https://scrap.kakaocdn.net/dn/bv8XG7/hyIgQFT5pF/Ekodc4aPILrSV77CuI06Y0/img.png?width=60&amp;amp;height=33&amp;amp;face=0_0_60_33,https://scrap.kakaocdn.net/dn/qwUMw/hyIfo5kNro/Z2FHxCSE4CZp9Q8DKXb71K/img.jpg?width=60&amp;amp;height=45&amp;amp;face=0_0_60_45');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;How to Compose Queries in Ecto&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Composable queries in Ecto including how to safely join through tables.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;medium.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ecto.Query가 얼마나 Composable한가에 대한 짧은 토픽입니다.(구글 번역)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;간단한&lt;span&gt; &lt;/span&gt;쿼리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋습니다&lt;span&gt;. &lt;/span&gt;간단한&lt;span&gt; &lt;/span&gt;쿼리로&lt;span&gt; &lt;/span&gt;시작하겠습니다&lt;span&gt;. &lt;/span&gt;파란&lt;span&gt; &lt;/span&gt;차를&lt;span&gt; &lt;/span&gt;모두&lt;span&gt; &lt;/span&gt;찾아&lt;span&gt; &lt;/span&gt;봅시다&lt;span&gt;. &lt;/span&gt;이를&lt;span&gt; &lt;/span&gt;위해서는&lt;span&gt; Ecto.Query.where/3 &lt;/span&gt;만&lt;span&gt; &lt;/span&gt;있으면됩니다&lt;span&gt;. &lt;/span&gt;좋은&lt;span&gt; &lt;/span&gt;파이프&lt;span&gt; &lt;/span&gt;기능을&lt;span&gt; &lt;/span&gt;위해&lt;span&gt; &lt;/span&gt;키워드&lt;span&gt; &lt;/span&gt;구문과&lt;span&gt; &lt;/span&gt;달리&lt;span&gt; &lt;/span&gt;표현식&lt;span&gt; &lt;/span&gt;구문을&lt;span&gt; &lt;/span&gt;사용하는&lt;span&gt; &lt;/span&gt;것을&lt;span&gt; &lt;/span&gt;좋아하므로&lt;span&gt; &lt;/span&gt;앞으로&lt;span&gt; &lt;/span&gt;이러한&lt;span&gt; &lt;/span&gt;예를&lt;span&gt; &lt;/span&gt;살펴&lt;span&gt; &lt;/span&gt;보겠습니다&lt;span&gt;. &lt;/span&gt;이제&lt;span&gt; &lt;/span&gt;모든&lt;span&gt; &lt;/span&gt;파란색&lt;span&gt; &lt;/span&gt;자동차를&lt;span&gt; &lt;/span&gt;찾고&lt;span&gt; &lt;/span&gt;싶다고&lt;span&gt; &lt;/span&gt;말했지만이&lt;span&gt; &lt;/span&gt;기능을&lt;span&gt; &lt;/span&gt;좀&lt;span&gt; &lt;/span&gt;더&lt;span&gt; &lt;/span&gt;재사용&lt;span&gt; &lt;/span&gt;가능하게&lt;span&gt; &lt;/span&gt;만들어&lt;span&gt; &lt;/span&gt;모든&lt;span&gt; &lt;/span&gt;색상을&lt;span&gt; &lt;/span&gt;사용할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있도록하겠습니다&lt;span&gt;. &lt;/span&gt;이를&lt;span&gt; &lt;/span&gt;위해&lt;span&gt; &lt;/span&gt;다음과&lt;span&gt; &lt;/span&gt;같이&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이제이를&lt;/span&gt; &lt;span&gt;시도해보기&lt;/span&gt; &lt;span&gt;위해&lt;/span&gt; IEX &lt;span&gt;세션으로&lt;/span&gt; &lt;span&gt;이동하여&lt;/span&gt; EctoCars.Car.with_color (&amp;ldquo;blue&amp;rdquo;) |&amp;gt; EctoCars.Repo.all ()&lt;span&gt;을&lt;/span&gt; &lt;span&gt;실행하여이&lt;/span&gt; &lt;span&gt;쿼리를&lt;/span&gt; &lt;span&gt;시도해&lt;/span&gt; &lt;span&gt;보겠습니다&lt;/span&gt;.&lt;/p&gt;
&lt;pre id=&quot;code_1605515905224&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def with_color(color) do
  Car
  |&amp;gt; where([c], c.color == ^color)
end&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;조인으로&lt;span&gt; &lt;/span&gt;쿼리&lt;/h4&gt;
&lt;pre id=&quot;code_1605515886704&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def with_transmission(type) do
  Car
  |&amp;gt; join(:left, [c], s in Specification, on: c.specification_id == s.id)
  |&amp;gt; join(:left, [c, s], t in Transmission, on: s.transmission_id == t.id)
  |&amp;gt; where([c, s, t], t.type == ^type)
end&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&lt;span&gt; &lt;/span&gt;작업을&lt;span&gt; &lt;/span&gt;수행하려면&lt;span&gt; &lt;/span&gt;실제로&lt;span&gt; &lt;/span&gt;두&lt;span&gt; &lt;/span&gt;번&lt;span&gt;&amp;nbsp;query&lt;/span&gt;해야했습니다&lt;span&gt;. specification&lt;/span&gt;을&lt;span&gt; &lt;/span&gt;통과&lt;span&gt; &lt;/span&gt;한&lt;span&gt; &lt;/span&gt;다음&lt;span&gt; &lt;/span&gt;다시&lt;span&gt; &lt;/span&gt;전송합니다&lt;span&gt;. &lt;/span&gt;우리는&lt;span&gt;&amp;nbsp;Transmission type&lt;/span&gt;을&lt;span&gt; &lt;/span&gt;인수로&lt;span&gt; &lt;/span&gt;받아들이고&lt;span&gt; &lt;/span&gt;마지막에&lt;span&gt; where &lt;/span&gt;절에서 이를&lt;span&gt; &lt;/span&gt;사용하여이&lt;span&gt; &lt;/span&gt;쿼리&lt;span&gt; &lt;/span&gt;함수를&lt;span&gt; &lt;/span&gt;다시&lt;span&gt; &lt;/span&gt;사용할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있도록했습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의해야&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;한&lt;span&gt; &lt;/span&gt;가지는&lt;span&gt; &lt;/span&gt;결합에&lt;span&gt; &lt;/span&gt;대한&lt;span&gt; &lt;/span&gt;세&lt;span&gt; &lt;/span&gt;번째&lt;span&gt; &lt;/span&gt;인수로&lt;span&gt; &lt;/span&gt;사용하는&lt;span&gt; &lt;/span&gt;문자&lt;span&gt; &lt;/span&gt;목록이&lt;span&gt; &lt;/span&gt;바인딩&lt;span&gt; &lt;/span&gt;된&lt;span&gt; &lt;/span&gt;변수&lt;span&gt; &lt;/span&gt;일&lt;span&gt; &lt;/span&gt;뿐이라는&lt;span&gt; &lt;/span&gt;것입니다&lt;span&gt;. &lt;/span&gt;예를&lt;span&gt; &lt;/span&gt;들어&lt;span&gt; &lt;/span&gt;두&lt;span&gt; &lt;/span&gt;번째&lt;span&gt; &lt;/span&gt;조인에서는&lt;span&gt; [c, s] &lt;/span&gt;사용에&lt;span&gt; &lt;/span&gt;특별한&lt;span&gt; &lt;/span&gt;것이&lt;span&gt; &lt;/span&gt;없습니다&lt;span&gt;. &lt;/span&gt;이러한&lt;span&gt; &lt;/span&gt;문자는&lt;span&gt; &lt;/span&gt;이전&lt;span&gt; &lt;/span&gt;함수&lt;span&gt; &lt;/span&gt;호출에서&lt;span&gt; &lt;/span&gt;사용&lt;span&gt; &lt;/span&gt;된&lt;span&gt; &lt;/span&gt;것과&lt;span&gt; &lt;/span&gt;동일한&lt;span&gt; &lt;/span&gt;문자&lt;span&gt; &lt;/span&gt;였기&lt;span&gt; &lt;/span&gt;때문에&lt;span&gt; &lt;/span&gt;우리에게&lt;span&gt; &lt;/span&gt;의미가&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;. &lt;/span&gt;두&lt;span&gt; &lt;/span&gt;번째&lt;span&gt; &lt;/span&gt;조인의&lt;span&gt; s&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;다른&lt;span&gt; &lt;/span&gt;문자로&lt;span&gt; &lt;/span&gt;변경하면&lt;span&gt; &lt;/span&gt;쿼리가&lt;span&gt; &lt;/span&gt;전혀&lt;span&gt; &lt;/span&gt;변경되지&lt;span&gt; &lt;/span&gt;않습니다&lt;span&gt;. &lt;i&gt;&lt;u&gt;&lt;b&gt;(역자주1: 단, 순서는 중요합니다.!! [c, s] -&amp;gt; [a, b] 로 해도 상관 없습니다만 첫 번째가 Car이고 두 번째가 Spec. 이라는 것은 기억해야 합니다.&lt;/b&gt;&lt;/u&gt;&lt;/i&gt;&lt;/span&gt;&lt;i&gt;&lt;u&gt;&lt;b&gt;&lt;span&gt;)&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔에서&lt;span&gt; &lt;/span&gt;이것을&lt;span&gt; &lt;/span&gt;시도하면&lt;span&gt; &lt;/span&gt;다음을&lt;span&gt; &lt;/span&gt;볼&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Composable 하게&lt;span&gt; &lt;/span&gt;만들기&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제&lt;span&gt; &lt;/span&gt;자동&lt;span&gt; &lt;/span&gt;변속기가있는&lt;span&gt; &lt;/span&gt;파란색의&lt;span&gt; &lt;/span&gt;모든&lt;span&gt; &lt;/span&gt;차를&lt;span&gt; &lt;/span&gt;정말로&lt;span&gt; &lt;/span&gt;찾고&lt;span&gt; &lt;/span&gt;있다면&lt;span&gt; &lt;/span&gt;어떨까요&lt;span&gt;? &lt;/span&gt;음&lt;span&gt;, &lt;/span&gt;완전히&lt;span&gt; &lt;/span&gt;새로운&lt;span&gt; &lt;/span&gt;쿼리를&lt;span&gt; &lt;/span&gt;작성하는&lt;span&gt; &lt;/span&gt;대신&lt;span&gt; &lt;/span&gt;기존의&lt;span&gt; &lt;/span&gt;두&lt;span&gt; &lt;/span&gt;쿼리&lt;span&gt; &lt;/span&gt;만&lt;span&gt; &lt;/span&gt;재사용&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있다면&lt;span&gt; &lt;/span&gt;좋을&lt;span&gt; &lt;/span&gt;것입니다&lt;span&gt;.&amp;nbsp;&lt;/span&gt;이렇게 하려면&lt;span&gt; &lt;/span&gt;유형&lt;span&gt; / &lt;/span&gt;색상&lt;span&gt; &lt;/span&gt;인수뿐만&lt;span&gt; &lt;/span&gt;아니라&lt;span&gt; &lt;/span&gt;추가&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;기존&lt;span&gt; &lt;/span&gt;쿼리를&lt;span&gt; &lt;/span&gt;가져&lt;span&gt; &lt;/span&gt;오기&lt;span&gt; &lt;/span&gt;위해&lt;span&gt; &lt;/span&gt;함수를&lt;span&gt; &lt;/span&gt;약간&lt;span&gt; &lt;/span&gt;리팩터링해야 합니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;첫&lt;/span&gt; &lt;span&gt;번째&lt;/span&gt; &lt;span&gt;인수를&lt;/span&gt; &lt;span&gt;선택&lt;/span&gt; &lt;span&gt;사항으로&lt;/span&gt; &lt;span&gt;설정하여&lt;/span&gt; &lt;span&gt;빌드중인&lt;/span&gt; &lt;span&gt;쿼리를&lt;/span&gt; &lt;span&gt;전달하도록&lt;/span&gt; &lt;span&gt;선택하거나&lt;/span&gt; cars &lt;span&gt;테이블에서&lt;/span&gt; &lt;span&gt;쿼리를&lt;/span&gt; &lt;span&gt;기본적으로&lt;/span&gt; &lt;span&gt;수행하도록&lt;/span&gt; &lt;span&gt;선택할&lt;/span&gt; &lt;span&gt;수&lt;/span&gt; &lt;span&gt;있습니다&lt;/span&gt;. &lt;span&gt;이제&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1605515852449&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;EctoCars.Car 
|&amp;gt; EctoCars.Car.with_color(&quot;blue&quot;) 
|&amp;gt; EctoCars.Car.with_transmission(&quot;automatic&quot;) 
|&amp;gt; EctoCars.Repo.all&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하나의&lt;/span&gt; &lt;span&gt;긴&lt;/span&gt; Ecto &lt;span&gt;쿼리를&lt;/span&gt; &lt;span&gt;작성하는&lt;/span&gt; &lt;span&gt;것처럼이를&lt;/span&gt; &lt;span&gt;연결할&lt;/span&gt; &lt;span&gt;수&lt;/span&gt; &lt;span&gt;있습니다&lt;/span&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;여러 조인으로 작성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이전에했던 작업과 함께 엔진에 대한 쿼리 함수를 만들어 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1605516002289&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def with_engine_horse_power(query \\ Car, horse_power) do
  query
  |&amp;gt; join(:left, [c], s in Specification, on: c.specification_id == s.id)
  |&amp;gt; join(:left, [c, s], e in Engine, on: s.engine_id == e.id)
  |&amp;gt; where([c, s, e], e.horse_power &amp;gt; ^horse_power)
end&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1605516020075&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex(10)&amp;gt; EctoCars.Car |&amp;gt; EctoCars.Car.with_color(&quot;blue&quot;) |&amp;gt; EctoCars.Car.with_transmission(&quot;automatic&quot;) |&amp;gt; EctoCars.Car.with_engine_horse_power(200) |&amp;gt; EctoCars.Repo.all()
** (Ecto.QueryError) lib/ecto_cars/cars/car.ex:37: field `horse_power` in `where` does not exist in schema EctoCars.Transmission in query:
from c0 in EctoCars.Car,
  left_join: s1 in EctoCars.Specification,
  on: c0.specification_id == s1.id,
  left_join: t2 in EctoCars.Transmission,
  on: s1.transmission_id == t2.id,
  left_join: s3 in EctoCars.Specification,
  on: c0.specification_id == s3.id,
  left_join: e4 in EctoCars.Engine,
  on: s1.engine_id == e4.id,
  where: c0.color == ^&quot;blue&quot;,
  where: t2.type == ^&quot;automatic&quot;,
  where: t2.horse_power &amp;gt; ^200,
  select: c0
(elixir) lib/enum.ex:1925: Enum.&quot;-reduce/3-lists^foldl/2-0-&quot;/3
    (elixir) lib/enum.ex:1418: Enum.&quot;-map_reduce/3-lists^mapfoldl/2-0-&quot;/3
    (elixir) lib/enum.ex:1418: Enum.&quot;-map_reduce/3-lists^mapfoldl/2-0-&quot;/3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 일어난 일을 분석 할 수 있는지 보겠습니다. 오류를 살펴보면 Transmission 스키마에 horse_power가 존재하지 않는다는 의미입니다.&amp;nbsp;이를 좀 더 잘 이해하기 위해 이러한 모든 쿼리 조각을 풀고 함수 외부에서 함께 작성해 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1605516087654&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Car
|&amp;gt; where([c], c.color == ^color)
|&amp;gt; join(:left, [c], s in Specification, on: c.specification_id == s.id)
|&amp;gt; join(:left, [c, s], t in Transmission, on: s.transmission_id == t.id)
|&amp;gt; where([c, s, t], t.type == ^type)
|&amp;gt; join(:left, [c], s in Specification, on: c.specification_id == s.id)
|&amp;gt; join(:left, [c, s], e in Engine, on: s.engine_id == e.id)
|&amp;gt; where([c, s, e], e.horse_power &amp;gt; ^horse_power)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 좀 더 쉽게 볼 수 있습니다. 결합이 join과 함께 작동하는 기본 방식으로 인해 참조하는 테이블은 해당 목록에서의 위치와 전적으로 관련됩니다. 따라서 8 행에서 engines 테이블에 대해 쿼리 할 때 실제로이 쿼리의 세 번째 테이블에 대해 쿼리합니다. [Trasnmission!!!] 이것을있는 그대로 작동 시키려면 다음을 수행해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1605516266865&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Car
|&amp;gt; where([c], c.color == ^color)
|&amp;gt; join(:left, [c], s in Specification, on: c.specification_id == s.id)
|&amp;gt; join(:left, [c, s], t in Transmission, on: s.transmission_id == t.id)
|&amp;gt; where([c, s, t], t.type == ^type)
|&amp;gt; join(:left, [c, s, t], e in Engine, on: s.engine_id == e.id)
|&amp;gt; where([c, s, t, e], e.horse_power &amp;gt; ^horse_power)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 사양에 대한 이중 조인을 제거했습니다. 실제로 누가 그것을 필요로하기 때문입니다. 또한 바인딩 목록이 Transmission에 대한 기존 바인딩을 인식하도록 엔진에 대한 조인 및 쿼리를 업데이트했습니다. 현재이 쿼리는 이전에 수행 된 쿼리 (사양에 따라)와이 쿼리를 호출하기 전에 동일한 수의 테이블이 쿼리에 조인되었는지에 따라 달라집니다. 동작은 하겠지만 만족스럽지 않습니다. 여기에 더 나은 방법이 있어야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Named Binding&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Named Binding을 사용하려면 join을 호출 할 때 as 옵션을 전달합니다. join (query, : left, [c], s in Specification, as : : specifications, on : c.specification_id == s.id). 그런 다음 다음 키 사양을 사용하여 쿼리에서 사양 변수를 바인딩 할 수 있습니다. : join (query, : left, [c, specification : s], t in Transmission, as : : transmissions, on : s.transmission_id == t.id). 이제 명&lt;span style=&quot;color: #333333;&quot;&gt;Named Binding&lt;/span&gt;을 사용하도록 함수를 다시 작성해 보겠습니다. &lt;u&gt;&lt;i&gt;&lt;b&gt;(역자주2: as 옵션은 딱 2 군데서 사용합니다. join &amp;amp; from)&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1605516561929&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def with_transmission(query \\ Car, type) do
    query
    |&amp;gt; join(:left, [c], s in Specification, as: :specifications, on: c.specification_id == s.id)
    |&amp;gt; join(:left, [c, specifications: s], t in Transmission, as: :transmissions, on: s.transmission_id == t.id)
    |&amp;gt; where([c, transmissions: t], t.type == ^type)
  end

  def with_engine_horse_power(query \\ Car, horse_power) do
    query
    |&amp;gt; join(:left, [c], s in Specification, as: :specifications, on: c.specification_id == s.id)
    |&amp;gt; join(:left, [c, specifications: s], e in Engine, as: :engines, on: s.engine_id == e.id)
    |&amp;gt; where([c, engines: e], e.horse_power &amp;gt; ^horse_power)
  end&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 다시 연결하려고하면 흥미로운 일이 발생합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1605516719130&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex(16)&amp;gt; EctoCars.Car |&amp;gt; EctoCars.Car.with_color(&quot;blue&quot;) |&amp;gt; EctoCars.Car.with_transmission(&quot;automatic&quot;) |&amp;gt; EctoCars.Car.with_engine_horse_power(200) |&amp;gt; EctoCars.Repo.all()
** (Ecto.Query.CompileError) alias `:specifications` already exists
    (ecto_cars) lib/ecto_cars/cars/car.ex:35: EctoCars.Car.with_engine_horse_power/2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동일한 키를 다시 바인딩 할 수 없습니다. 간단한 해결책은 with_engine_horse_power 함수에서 사양에 대한 조인을 제거하는 것이지만, 사양에 조인하는 함수가 호출 된 후에 만이 함수를 호출해야하는 위치에 다시 갇혀 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에서 가장 좋은 방법은 쿼리가 이미 특정 테이블에 조인되었는지 확인하고 확인하지 않은 경우에만 다시 조인하는 것입니다. &lt;b&gt;has_named_binding?&lt;/b&gt;으로 깔끔하게이 작업을 수행 할 수 있습니다. 이 함수를 사용하면 쿼리에 이미 해당 바인딩이 있는지 확인하고 확인할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1605516808232&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def with_transmission(query \\ Car, type) do
    query
    |&amp;gt; join_specifications()
    |&amp;gt; join(:left, [c, specifications: s], t in Transmission, as: :transmissions, on: s.transmission_id == t.id)
    |&amp;gt; where([c, transmissions: t], t.type == ^type)
  end

def with_engine_horse_power(query \\ Car, horse_power) do
    query
    |&amp;gt; join_specifications()
    |&amp;gt; join(:left, [c, specifications: s], e in Engine, as: :engines, on: s.engine_id == e.id)
    |&amp;gt; where([c, engines: e], e.horse_power &amp;gt; ^horse_power)
end

defp join_specifications(query) do
    if has_named_binding?(query, :specifications) do
      query
    else
      query
      |&amp;gt; join(:left, [c], s in Specification, as: :specifications, on: c.specification_id == s.id)
    end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;join_specifications 도우미 함수는 조인을 확인하고 필요한 경우 쿼리에 추가하는 작업을 담당합니다. 이제 마지막으로 특정 순서에 의존하지 않거나 두 번째를 호출하기 전에 항상 호출해야하는 하나의 함수에 의존하는 구성 가능한 쿼리를 작성할 수 있습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1605516928138&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;iex(17)&amp;gt; EctoCars.Car |&amp;gt; EctoCars.Car.with_color(&quot;blue&quot;) |&amp;gt; EctoCars.Car.with_transmission(&quot;automatic&quot;) |&amp;gt; EctoCars.Car.with_engine_horse_power(200) |&amp;gt; EctoCars.Repo.all()
17:31:25.303 [debug] QUERY OK source=&quot;cars&quot; db=2.6ms queue=3.8ms
SELECT c0.&quot;id&quot;, c0.&quot;color&quot;, c0.&quot;vin_number&quot;, c0.&quot;specification_id&quot; FROM &quot;cars&quot; AS c0 LEFT OUTER JOIN &quot;specifications&quot; AS s1 ON c0.&quot;specification_id&quot; = s1.&quot;id&quot; LEFT OUTER JOIN &quot;transmissions&quot; AS t2 ON s1.&quot;transmission_id&quot; = t2.&quot;id&quot; LEFT OUTER JOIN &quot;engines&quot; AS e3 ON s1.&quot;engine_id&quot; = e3.&quot;id&quot; WHERE (c0.&quot;color&quot; = $1) AND (t2.&quot;type&quot; = $2) AND (e3.&quot;horse_power&quot; &amp;gt; $3) [&quot;blue&quot;, &quot;automatic&quot;, 200]
[
  %EctoCars.Car{
    __meta__: #Ecto.Schema.Metadata&amp;lt;:loaded, &quot;cars&quot;&amp;gt;,
    color: &quot;blue&quot;,
    id: 3,
    specification: #Ecto.Association.NotLoaded&amp;lt;association :specification is not loaded&amp;gt;,
    specification_id: 1,
    vin_number: &quot;my_dream_car&quot;
  }
]&lt;/code&gt;&lt;/pre&gt;</description>
      <category>기술 동향</category>
      <author>gozalex</author>
      <guid isPermaLink="true">https://elixian.tistory.com/12</guid>
      <comments>https://elixian.tistory.com/12#entry12comment</comments>
      <pubDate>Mon, 16 Nov 2020 17:55:42 +0900</pubDate>
    </item>
    <item>
      <title>Ecto.Multi</title>
      <link>https://elixian.tistory.com/11</link>
      <description>&lt;p&gt;Ecto.Multi는 여러 Repo 작업을 그룹화하기위한 데이터 구조입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ecto.Multi은 가능한 하나의 데이터베이스 트랜잭션에서 수행하고 각 insert/update/delete등의 각 작업은 호출 시, 실행되지 않은 채로 MapSet에서 관리 되어야 합니다. 각 작업은 고유한 key를 가지며 성공 또는 실패의 경우에 그 결과를 식별하는 이름이 지정됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;i&gt;모든 작업은 추가 된 순서대로 실행됩니다.&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;%Ecto.Multi{}를 사용하여 유형 일치를 패턴화할 수 있지만 필드에 액세스하거나 직접 수정하는 것은 권장되지 않습니다.&lt;/p&gt;
&lt;p&gt;Ecto.Multi.to_list / 1&lt;span&gt;은&lt;/span&gt; &lt;span&gt;내부&lt;/span&gt; &lt;span&gt;검사에&lt;/span&gt; &lt;span&gt;사용할&lt;/span&gt; &lt;span&gt;수있는&lt;/span&gt; &lt;span&gt;구조의&lt;/span&gt; &lt;span&gt;표준&lt;/span&gt; &lt;span&gt;표현을&lt;/span&gt; &lt;span&gt;반환합니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1601960970130&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;      pills_attrs
      |&amp;gt; Stream.map(fn pill -&amp;gt;
        change_pill(prescription, pill)
      end)
      |&amp;gt; Stream.map(fn pill_changeset -&amp;gt;
        key = &quot;pill:#{pill_changeset.changes.name}&quot;
        Ecto.Multi.insert(Ecto.Multi.new(), key, pill_changeset)
      end)
      |&amp;gt; Enum.reduce(Ecto.Multi.new(), &amp;amp;Ecto.Multi.append/2)
      |&amp;gt; Repo.transaction()
      |&amp;gt; case do
        {:ok, _pill} -&amp;gt; {:ok, prescription}
        {:error, _failed_operation, failed_value, _changes_so_far} -&amp;gt; {:error, failed_value}
      end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ecto.Multi 는 MapSet&amp;lt;&amp;gt;의 구현체입니다.&lt;/p&gt;
&lt;p&gt;여러 개의 Multi를 만들어서 append 또는 prepend 하여 Repo.transaction/1 으로 한 번에 처리할 때 사용합니다.&lt;/p&gt;
&lt;p&gt;Stream.map/3 등을 사용하여 Ecto.Multi를 manipulate하여 사용합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;혹시 이전 쿼리의 리턴 값이 다음 쿼리에 필요한 경우에는 다음과 같이 처리합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1601961152585&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Ecto.Multi.new()
    |&amp;gt; Ecto.Multi.insert(:insert_prescription, changes_prescription(user, doctor, prescription_attrs))
    |&amp;gt; Ecto.Multi.run(:insert_pills, fn _repo, %{insert_prescription: prescription} -&amp;gt;

		......

    |&amp;gt; Repo.transaction()
    |&amp;gt; case do
      {:ok, prescription} -&amp;gt; {:ok, prescription.insert_prescription}
      {:error, _failed_operation, failed_value, _changes_so_far} -&amp;gt; {:error, failed_value}
    end
    
    # prescription.insert_prescription로 빼낸 것을 주목하세요 ^^&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ecto.Multi.run/3 함수를 사용하면 이전 쿼리의 결과 값을 name key로 받아올 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Ecto.Multi는 transaction이므로 한 번에 많은 데이터를 여러 쿼리를 사용해서 관리할 때 편합니다.&lt;/p&gt;
&lt;p&gt;명시적으로 rollback함수를 호출할 수도 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;insert_all을 사용할 수도 있지만 이 경우에는 timestampt() 로 생성한 updated_at / created_at을 처리해 주지 않습니다.&lt;/p&gt;</description>
      <category>기술 동향</category>
      <author>gozalex</author>
      <guid isPermaLink="true">https://elixian.tistory.com/11</guid>
      <comments>https://elixian.tistory.com/11#entry11comment</comments>
      <pubDate>Tue, 6 Oct 2020 14:21:01 +0900</pubDate>
    </item>
    <item>
      <title>History of Erlang</title>
      <link>https://elixian.tistory.com/10</link>
      <description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpinBY/btqE8yDFoKQ/FAptK44oJF4YDTKtIcyqtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpinBY/btqE8yDFoKQ/FAptK44oJF4YDTKtIcyqtk/img.png&quot; data-alt=&quot;Erlang&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpinBY/btqE8yDFoKQ/FAptK44oJF4YDTKtIcyqtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpinBY%2FbtqE8yDFoKQ%2FFAptK44oJF4YDTKtIcyqtk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Erlang&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Wikipedia (2017a)&lt;span&gt;에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;따르면&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Erlang&lt;span&gt;은&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;&lt;span&gt;영원히&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;실행되는&lt;/span&gt;&quot;&lt;span&gt;동시&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;작성하도록&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;설계된&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기능적&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그래밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어입니다&lt;/span&gt;. Erlang&lt;span&gt;은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;현재&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사용하여&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;구성합니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이러한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;공유&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;없고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;비동기&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메시지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;전달을&lt;/span&gt;&lt;span&gt;통해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;통신하며&lt;/span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;운영&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;체제가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;아닌&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가벼운&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;속합니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Erlang&lt;span&gt;은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;또한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;코드를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;변경하고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;패치를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;ldquo;&lt;span&gt;즉시&lt;/span&gt;&amp;rdquo;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;추가하므로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;런타임&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;중에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;업데이트&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있으므로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다시&lt;/span&gt;&lt;span&gt;시작할&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;필요가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;없습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이러한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메커니즘은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;논스톱&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;구현하기위한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소프트웨어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;구성을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;단순화합니다&lt;/span&gt;. (Joe Armstrong. Erlang&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;역사&lt;/span&gt;, Ericsson AB)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Erlang&lt;span&gt;은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;함수형&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그래밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제품군에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;속하므로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;일상적인&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;개발&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;접근&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;방식과&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;방법에는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;몇&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;근본적인&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;차이점이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있습니다&lt;/span&gt;. Erlang&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;변수는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;ldquo;&lt;span&gt;Single-assign&lt;/span&gt;&amp;rdquo;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;입니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;즉&lt;/span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;변수가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;특정&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;값에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할당되면&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;값으로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다시&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할당&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;없습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;비슷한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기능을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가진&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그래밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가장&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가까운&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;예는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Java&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;f&lt;span&gt;inal&lt;/span&gt;&quot;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;키워드입니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;변수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;재&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할당이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;없으면&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;루프&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;구성은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;연속적인&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;반복에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;변수를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;변경할&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;방법이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;없기&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;때문에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;의미가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;없습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;언어에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;루핑&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메커니즘을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모방&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할&lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제어는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;재귀&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;호출에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;의해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수행됩니다&lt;/span&gt;. Erlang&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;구문&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;및&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;내부&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기능&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;외에도&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;HTTP&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;및&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;SSH&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;클라이언트&lt;/span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;서버&lt;/span&gt;, SNMP&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;기능&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;및&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;내장&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;NoSQL&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;데이터베이스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;서버를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;포함하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;거대한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;표준&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;라이브러리가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있습니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;실제&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Erlang&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;개발은&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;1986&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;년&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Ericsson Computer Science&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;연구소에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;이루어졌습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;팀은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;차세대&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;통신&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제품을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그래밍하기에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;적합한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그래밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;조사하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;임무를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;부여&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;받았으며&lt;/span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이들은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;보다&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;나은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;전화&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;통신&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그래밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;방법을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제공해야했습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;당시&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;전화&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;응용&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;현재&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사용중인&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;응용&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램과&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;매우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다릅니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;그것들은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;평범한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그래밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어들이&lt;/span&gt;&lt;span&gt;해결하도록&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;고안된&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;많은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;문제들을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가지고있었습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이러한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;응용&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;본질적으로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;단일&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;동시성이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;뛰어납니다&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;switch&lt;span&gt;는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수만&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;또는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수십만&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;건의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;트랜잭션을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;처리해야합니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;트랜잭션이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;분산되고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소프트웨어는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;내결함성이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;높을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;것으로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;예상됩니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Joe Armstrong (Ericsson AB&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Erlang&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;역사&lt;/span&gt;)&lt;span&gt;은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다음과&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;같이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;말합니다&lt;/span&gt;. &amp;ldquo;&lt;span&gt;전화를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제어하는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;​​&lt;span&gt;소프트웨어에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;장애가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;발생하면&lt;/span&gt;&lt;span&gt;신문에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기사가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;납니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;반면에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;일반적인&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;데스크톱&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;응용&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;장애가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;발생해도&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;신문에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기사가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;나는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;일은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;발생하지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;않습니다&lt;/span&gt;.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;전화&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;통신&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;응용&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;발생하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;서비스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;손실없이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;실행되는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;동안&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소프트웨어가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;업데이트되는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;것이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;매우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;중요합니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;또한&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;S&lt;span&gt;oft real time&lt;/span&gt;&quot;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;도메인에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;작동해야&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하며&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;일부&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;작업에는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;엄격한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;타이밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요구&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사항이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있지만&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;클래스의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;작업에는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;타이밍이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;더&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;간단해야&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;합니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Erlang&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;또&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요구&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사항은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가동&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;중지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시간이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;거의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;없어야&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;것이었습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;당시&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;인터넷의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;인기가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;높아지고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;중단&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;없는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;서비스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가용성이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;필요해지면서&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Erlang&lt;span&gt;이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;해결할&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;문제가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;확대되었습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;예를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;들어&lt;/span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;동적&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;코드&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;업그레이드를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사용하여&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하루에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수백만&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;건의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요청을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;처리하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;논스톱&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;웹&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;서버를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;구축하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;것은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소프트웨어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;교환을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제어하기&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;위해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소프트웨어를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;구축하는&lt;/span&gt;&lt;span&gt;것과&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;매우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;유사합니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;일반적으로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;통화&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제어용&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소프트웨어는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로토콜&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메시지에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;대한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;응답으로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;상태&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;전이를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수행하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제한된&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;상태&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기기를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사용하여&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모델링&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;됩니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;소프트웨어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;관점에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;볼&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;때&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;매우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;큰&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;병렬&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모음으로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;작동합니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;어느&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시점에서든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;대부분의&lt;/span&gt;&lt;span&gt;프로세스는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메시지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수신&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;또는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;타이머&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;트리거로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;인한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;이벤트를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기다리고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이벤트가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;발생하면&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;어느&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;정도의&lt;/span&gt;&lt;span&gt;계산을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수행하고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;상태를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;변경하며&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메시지를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;보낸&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;후&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다음&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;이벤트를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기다립니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;계산에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소요되는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시간은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;매우&lt;/span&gt;&lt;span&gt;적습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;반면&lt;/span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;스위칭&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수십만&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;개의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;매우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가벼운&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;처리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;​​&lt;span&gt;있어야하는데&lt;/span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;각&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;거의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;계산을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수행하지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;않습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;또한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소프트웨어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;오류로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;인해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;충돌하거나&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;손상되지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;않아야&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;합니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;문제는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;너무&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;많은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;손상&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;문제로부터&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;보호해야한다는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;점이었습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;포인터가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어에서는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하한을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할당하여&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;관리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하드웨어를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사용하여&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;서로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;보호합니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;또한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;개별&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;대한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;권장&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요구&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사항은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;매우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;작을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있으며&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;보호&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하드웨어없이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스에&lt;/span&gt;&lt;span&gt;대한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;동일한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;주소&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;공간에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있습니다&lt;/span&gt;. Erlang&lt;span&gt;에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;실제로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기본&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;운영&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;체제가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;아닌&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;자체의&lt;/span&gt;&lt;span&gt;일부입니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;언어는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;관리와&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;병렬&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;간&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;보호를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모두&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제공하기&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;때문에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;운영&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;체제의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;대부분의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;서비스가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;필요하지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;않습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;하드웨어에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;액세스하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;데&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;필요한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;리소스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할당&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;및&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;장치&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;드라이버와&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;같은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;운영&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;체제&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;서비스는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;C&lt;span&gt;로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;작성되며&lt;/span&gt;Erlang&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;런타임에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;동적으로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;연결됩니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;프로그래밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;세&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;속성은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;동시&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;또는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;운영&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;체제의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;효율적인&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;운영을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;위한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;핵심&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요소였습니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;프로세스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;생성&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시간&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;두&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스간에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;컨텍스트&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;전환&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시간&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;두&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사이의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메시지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;복사&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시간&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Joe Armstrong (Ericsson AB Erlang&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;역사&lt;/span&gt;)&lt;span&gt;은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다음과&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;같이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;말합니다&lt;/span&gt;.&lt;span&gt;&amp;ldquo;&lt;/span&gt;Erlang&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가장&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;초기&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모티브는&amp;ldquo;&lt;/span&gt;PLEX&lt;span&gt;와&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;같은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;것을&lt;/span&gt;&lt;span&gt;만들어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;일반&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하드웨어에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;더&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;잘&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;실행하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;것&amp;rdquo;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;이었습니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Erlang&lt;span&gt;에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;대한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;아이디어는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;PLEX&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;및&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;AX&lt;span&gt;E&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;디자인에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;크게&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;상속되었습니다&lt;/span&gt;. PLEX&lt;span&gt;는&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;AX&lt;span&gt;E&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;전화&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;교환&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;전용의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;특수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;목적의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;이벤트&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;중심&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;실시간&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그래밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어입니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;그러한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;아이디어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;중&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하나는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;코드를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;ldquo;즉석에서&amp;rdquo;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;변경할&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가능성이었습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;따라서&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;AX&lt;span&gt;E&lt;/span&gt;&lt;span&gt;는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수많은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;전화&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;통화의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;병렬&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;조작과&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;같은&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;&lt;span&gt;포인터&lt;/span&gt;&quot;&lt;span&gt;문제가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있었습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;각&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;호출에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;대한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요구&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사항은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가변적이며&lt;/span&gt;&lt;span&gt;링크&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;된&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;목록과&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;포인터&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;조작을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사용하여&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할당되었습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;인해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;많은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;오류가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;발생했습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이것은&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Erlang&lt;span&gt;에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사용&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;된&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;및&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가비지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수집&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;전략에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;영감을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;얻은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;것입니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;AXE / PLEX&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;문화에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;비롯된&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;최종&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;핵심&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;아이디어는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;나&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하드웨어의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;장애가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;처리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;중인&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;트랜잭션에만&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;영향을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;미치고&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;작업은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;그대로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;유지되고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;실행되어야&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;한다는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;것입니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;이로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;인해&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Erlang&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;디자인이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;단순화되고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;간&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;교수형&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;포인터가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제거되었습니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;메시지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;전달은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메모리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;공간&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사이에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;메시지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;버퍼를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;복사하여&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;구현되었습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;내결함성을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;달성하기&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;위해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;팀은&lt;/span&gt;&lt;span&gt;오류&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;처리가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;어려운&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;문제로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;인해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스간에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;리소스를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;공유한다는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;아이디어를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;거부했으며&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;부분에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;문제가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;발생하면&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;계속&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;실행하기에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;충분한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;로컬&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;정보가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;있어야한다고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;결정했습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;따라서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;안정적으로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;유지하기&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;위해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스간에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;데이터를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;복사하여&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다른&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;충돌하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;경우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로세스가&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;자체적으로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;계속&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;실행하기에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;충분한&lt;/span&gt;&lt;span&gt;데이터를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;갖도록&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;했습니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;AXE / PLEX&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;히스토리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;및&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;내부&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;아키텍처로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;인해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;새로운&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그래밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어마다&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;필요한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요구&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사항&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;목록이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;제공되었습니다&lt;/span&gt;. (Joe Armstrong. Erlang&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;역사&lt;/span&gt;, Ericsson AB.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;목록에는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;다음이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;포함됩니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;1.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;매우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;많은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;동시&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;활동&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;처리&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;2.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;특정&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시간&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;내에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;특정&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시점에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;수행&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;할&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;작업&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;3.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;여러&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;컴퓨터에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;분산&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;된&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;4.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하드웨어와의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;상호&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;작용&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;5.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;매우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;큰&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소프트웨어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;6.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기능&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;통합과&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;같은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;복잡한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기능&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;7.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;중지하지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;않고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소프트웨어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;유지&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;관리&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(&lt;span&gt;재구성&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;등&lt;/span&gt;)&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;8.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;엄격한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;품질&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;및&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;신뢰성&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요구&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사항&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;9.&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;하드웨어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;오류&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;및&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;소프트웨어&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;오류에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;대한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;내결함성&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;이러한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요구&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사항은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;매우&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;간단&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;했으며&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;기존&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;시스템은&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;이미&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;운영&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;체제&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;및&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;응용&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;라이브러리에서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;이미&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;일부를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;해결했습니다&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;그럼에도&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;불구하고&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;요구&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사항을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;충족시키기&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;위해&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;당시&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;사용&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;가능한&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;모든&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그래밍&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;언어로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;통신&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;응용&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;프로그램을&lt;/span&gt;&lt;span&gt;Proto-typing&lt;/span&gt;&lt;span&gt;하는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;실험을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;계속하기로&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;결정했습니다&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;본&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;문서는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Building Analytics Plugin for Erlang MQTT Broker by Damir Mustafin&lt;/span&gt;&lt;span&gt;의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;문서&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;중&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;일부를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;번역하였습니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다음은 CentOS 8에 Erlang을 설치하기 위한 repo 설정입니다.&lt;/p&gt;
&lt;p&gt;erlang.org에서 repo를 찾을 수 없어 rabbitmq의 repo를 사용한 모습입니다.&lt;/p&gt;
&lt;p&gt;기존 방식으로 install 하면 많은 dependancy가 우선 해결되어야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1594602380083&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# In /etc/yum.repos.d/rabbitmq-erlang.repo

[rabbitmq-erlang]
name=rabbitmq-erlang
baseurl=https://dl.bintray.com/rabbitmq-erlang/rpm/erlang/23/el/8
gpgcheck=1
gpgkey=https://dl.bintray.com/rabbitmq/Keys/rabbitmq-release-signing-key.asc
repo_gpgcheck=0
enabled=1&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Elixir를 소스로 인스톨 합니다&lt;/p&gt;
&lt;pre id=&quot;code_1594603348112&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git clone https://github.com/elixir-lang/elixir.git

make clean test&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Precompiled 버전으로 인스톨 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1594618386163&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wget https://github.com/elixir-lang/elixir/releases/download/v1.10.4/Precompiled.zip

# vi /etc/profile
export PATH=&quot;$PATH:/usr/bin/elixir/bin
source /etc/profile

elixir -v&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>기술 동향</category>
      <author>gozalex</author>
      <guid isPermaLink="true">https://elixian.tistory.com/10</guid>
      <comments>https://elixian.tistory.com/10#entry10comment</comments>
      <pubDate>Thu, 25 Jun 2020 13:53:35 +0900</pubDate>
    </item>
    <item>
      <title>Raft Consensus Algorithm</title>
      <link>https://elixian.tistory.com/9</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;What is Raft?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Raft는&amp;nbsp;이해하기&amp;nbsp;쉽게&amp;nbsp;설계된&amp;nbsp;합의&amp;nbsp;알고리즘입니다.&amp;nbsp;내결함성과&amp;nbsp;성능면에서&amp;nbsp;Paxos와&amp;nbsp;같습니다. Raft가&amp;nbsp;더&amp;nbsp;많은&amp;nbsp;사람들에게&amp;nbsp;합의를&amp;nbsp;제공&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있기를&amp;nbsp;희망하며이&amp;nbsp;더&amp;nbsp;많은&amp;nbsp;사람들이&amp;nbsp;오늘날&amp;nbsp;이용&amp;nbsp;가능한&amp;nbsp;것보다&amp;nbsp;다양한&amp;nbsp;고품질의&amp;nbsp;합의&amp;nbsp;기반&amp;nbsp;시스템을&amp;nbsp;개발할&amp;nbsp;수&amp;nbsp;있기를&amp;nbsp;바랍니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Hold on&amp;mdash;what is consensus?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;합의는&amp;nbsp;내결함성&amp;nbsp;분산&amp;nbsp;시스템에서&amp;nbsp;근본적인&amp;nbsp;문제입니다.&amp;nbsp;합의는 &quot;값&quot;을 공유하는&amp;nbsp;여러&amp;nbsp;서버를&amp;nbsp;포함합니다.&amp;nbsp;일단 값에&amp;nbsp;대한&amp;nbsp;결정에&amp;nbsp;도달하면,&amp;nbsp;그&amp;nbsp;결정이&amp;nbsp;최종입니다.&amp;nbsp;일반적인&amp;nbsp;합의&amp;nbsp;알고리즘은&amp;nbsp;대부분의&amp;nbsp;서버를&amp;nbsp;사용할&amp;nbsp;수있을&amp;nbsp;때&amp;nbsp;진행됩니다.&amp;nbsp;예를&amp;nbsp;들어,&amp;nbsp;2&amp;nbsp;대의&amp;nbsp;서버에&amp;nbsp;장애가&amp;nbsp;발생하더라도&amp;nbsp;5&amp;nbsp;대의&amp;nbsp;서버&amp;nbsp;클러스터가&amp;nbsp;계속&amp;nbsp;작동&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;더&amp;nbsp;많은&amp;nbsp;서버가&amp;nbsp;실패하면&amp;nbsp;진행이&amp;nbsp;중지되지만&amp;nbsp;잘못된&amp;nbsp;결과는&amp;nbsp;반환되지&amp;nbsp;않습니다.&lt;br /&gt;&lt;br /&gt;일반적으로&amp;nbsp;내결함성&amp;nbsp;시스템을&amp;nbsp;구축하기위한&amp;nbsp;일반적인&amp;nbsp;접근&amp;nbsp;방식인 Replicated Machine과 합의가&amp;nbsp;이루어집니다.&amp;nbsp;각&amp;nbsp;서버에는&amp;nbsp;상태&amp;nbsp;시스템과&amp;nbsp;로그가&amp;nbsp;있습니다.&amp;nbsp;상태&amp;nbsp;머신은&amp;nbsp;해시&amp;nbsp;테이블과&amp;nbsp;같이&amp;nbsp;내결함성을&amp;nbsp;만들려는&amp;nbsp;구성&amp;nbsp;요소입니다.&amp;nbsp;클러스터의&amp;nbsp;소수의&amp;nbsp;서버에&amp;nbsp;장애가&amp;nbsp;발생하더라도&amp;nbsp;클라이언트가&amp;nbsp;신뢰할&amp;nbsp;수있는&amp;nbsp;단일&amp;nbsp;상태&amp;nbsp;시스템과&amp;nbsp;상호&amp;nbsp;작용하는&amp;nbsp;것으로&amp;nbsp;나타납니다.&amp;nbsp;각&amp;nbsp;상태&amp;nbsp;머신은&amp;nbsp;로그에서&amp;nbsp;입력&amp;nbsp;명령으로&amp;nbsp;사용됩니다.&amp;nbsp;해시&amp;nbsp;테이블&amp;nbsp;예에서&amp;nbsp;로그에는&amp;nbsp;set X to&amp;nbsp;3과&amp;nbsp;같은&amp;nbsp;명령이&amp;nbsp;포함됩니다.&amp;nbsp;합의&amp;nbsp;알고리즘은&amp;nbsp;서버&amp;nbsp;로그의&amp;nbsp;명령에&amp;nbsp;동의하는&amp;nbsp;데&amp;nbsp;사용됩니다.&amp;nbsp;합의&amp;nbsp;알고리즘은&amp;nbsp;상태&amp;nbsp;머신이 X에&amp;nbsp;3을&amp;nbsp;n&amp;nbsp;번째&amp;nbsp;명령으로&amp;nbsp;적용&amp;nbsp;할&amp;nbsp;경우&amp;nbsp;다른&amp;nbsp;상태&amp;nbsp;머신이&amp;nbsp;다른&amp;nbsp;n&amp;nbsp;번째&amp;nbsp;명령을&amp;nbsp;적용하지&amp;nbsp;않도록해야합니다.&amp;nbsp;결과적으로,&amp;nbsp;각&amp;nbsp;상태&amp;nbsp;머신은&amp;nbsp;동일한&amp;nbsp;일련의&amp;nbsp;명령을&amp;nbsp;처리하므로&amp;nbsp;동일한&amp;nbsp;일련의&amp;nbsp;결과를&amp;nbsp;생성하고&amp;nbsp;동일한&amp;nbsp;일련의&amp;nbsp;상태에&amp;nbsp;도달합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Raft Visualization&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;브라우저에서&amp;nbsp;실행중인&amp;nbsp;Raft&amp;nbsp;클러스터는&amp;nbsp;다음과&amp;nbsp;같습니다.&amp;nbsp;Raft가&amp;nbsp;작동하는&amp;nbsp;것을 보기&amp;nbsp;위해&amp;nbsp;상호&amp;nbsp;작용할&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;왼쪽에는&amp;nbsp;5&amp;nbsp;개의&amp;nbsp;서버가&amp;nbsp;표시되고&amp;nbsp;오른쪽에는&amp;nbsp;로그가&amp;nbsp;표시됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKIsme/btqE749WSvs/ipCKfrb5ce1K8nZNdiYplK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKIsme/btqE749WSvs/ipCKfrb5ce1K8nZNdiYplK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKIsme/btqE749WSvs/ipCKfrb5ce1K8nZNdiYplK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKIsme%2FbtqE749WSvs%2FipCKfrb5ce1K8nZNdiYplK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2&gt;A node can be in 1 of 3 states:&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;100&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HamYj/btqE7A2Aawi/DQlgqRJpoeWD9JtPkWJeek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HamYj/btqE7A2Aawi/DQlgqRJpoeWD9JtPkWJeek/img.png&quot; data-alt=&quot;Follower State&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HamYj/btqE7A2Aawi/DQlgqRJpoeWD9JtPkWJeek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHamYj%2FbtqE7A2Aawi%2FDQlgqRJpoeWD9JtPkWJeek%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;100&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Follower State&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;100&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOhoRi/btqE5P7R84Y/vQkvfKSq9segXxk0LezB6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOhoRi/btqE5P7R84Y/vQkvfKSq9segXxk0LezB6k/img.png&quot; data-alt=&quot;Candidate State&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOhoRi/btqE5P7R84Y/vQkvfKSq9segXxk0LezB6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOhoRi%2FbtqE5P7R84Y%2FvQkvfKSq9segXxk0LezB6k%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;100&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Candidate State&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;100&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LzXY9/btqE56awG6H/sWa1B5369qIWWSVoV2kxW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LzXY9/btqE56awG6H/sWa1B5369qIWWSVoV2kxW1/img.png&quot; data-alt=&quot;Leader State&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LzXY9/btqE56awG6H/sWa1B5369qIWWSVoV2kxW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLzXY9%2FbtqE56awG6H%2FsWa1B5369qIWWSVoV2kxW1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; width=&quot;100&quot; height=&quot;NaN&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Leader State&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FRP3I/btqE74WqKiO/kKdsaXyzjh1WHUXLhGZEo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FRP3I/btqE74WqKiO/kKdsaXyzjh1WHUXLhGZEo1/img.png&quot; data-alt=&quot;Become a candidate&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FRP3I/btqE74WqKiO/kKdsaXyzjh1WHUXLhGZEo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFRP3I%2FbtqE74WqKiO%2FkKdsaXyzjh1WHUXLhGZEo1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Become a candidate&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ycw5P/btqE6wGCGD0/n3WWOuugHr3bUNHt1Ys0r0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ycw5P/btqE6wGCGD0/n3WWOuugHr3bUNHt1Ys0r0/img.png&quot; data-alt=&quot;Become a leader&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ycw5P/btqE6wGCGD0/n3WWOuugHr3bUNHt1Ys0r0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fycw5P%2FbtqE6wGCGD0%2Fn3WWOuugHr3bUNHt1Ys0r0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Become a leader&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XXk2O/btqE56VRiea/R2KRDnolPk2aUy0FTLa7E0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XXk2O/btqE56VRiea/R2KRDnolPk2aUy0FTLa7E0/img.png&quot; data-alt=&quot;&amp;amp;amp;nbsp;Append Entry Message within a hearbeat&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XXk2O/btqE56VRiea/R2KRDnolPk2aUy0FTLa7E0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXXk2O%2FbtqE56VRiea%2FR2KRDnolPk2aUy0FTLa7E0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;nbsp;Append Entry Message within a hearbeat&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvadGT/btqE75VmAL3/6sH9deoTeKLeyrjVbaPVCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvadGT/btqE75VmAL3/6sH9deoTeKLeyrjVbaPVCk/img.png&quot; data-alt=&quot;Commit&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvadGT/btqE75VmAL3/6sH9deoTeKLeyrjVbaPVCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdvadGT%2FbtqE75VmAL3%2F6sH9deoTeKLeyrjVbaPVCk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Commit&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U87Xo/btqE7BmTgfY/BLAY9mySmyAHLzwVC6KxS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U87Xo/btqE7BmTgfY/BLAY9mySmyAHLzwVC6KxS1/img.png&quot; data-alt=&quot;Consensus - Log replication&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U87Xo/btqE7BmTgfY/BLAY9mySmyAHLzwVC6KxS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU87Xo%2FbtqE7BmTgfY%2FBLAY9mySmyAHLzwVC6KxS1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Consensus - Log replication&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZOVRj/btqE75OzPrd/nn9Yjj5plikQOAqb7iTbKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZOVRj/btqE75OzPrd/nn9Yjj5plikQOAqb7iTbKK/img.png&quot; data-alt=&quot;Election Timeout -&amp;amp;amp;nbsp;The election timeout is the amount of time a follower waits until becoming a candidate.The election timeout is randomized to be between 150ms and 300ms.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZOVRj/btqE75OzPrd/nn9Yjj5plikQOAqb7iTbKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZOVRj%2FbtqE75OzPrd%2Fnn9Yjj5plikQOAqb7iTbKK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Election Timeout -&amp;nbsp;The election timeout is the amount of time a follower waits until becoming a candidate.The election timeout is randomized to be between 150ms and 300ms.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bByeAq/btqE76mpaZu/xijdmunaFdDLrg2gwhGq9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bByeAq/btqE76mpaZu/xijdmunaFdDLrg2gwhGq9k/img.png&quot; data-alt=&quot;Send &amp;amp;quot;Request Vote Message&amp;amp;quot; to all nodes and waits...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bByeAq/btqE76mpaZu/xijdmunaFdDLrg2gwhGq9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbByeAq%2FbtqE76mpaZu%2FxijdmunaFdDLrg2gwhGq9k%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Send &quot;Request Vote Message&quot; to all nodes and waits...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yCEfV/btqE6LQ3fdJ/sanShM0fB2LWp3M2dJK141/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yCEfV/btqE6LQ3fdJ/sanShM0fB2LWp3M2dJK141/img.png&quot; data-alt=&quot;Append Entries messages&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yCEfV/btqE6LQ3fdJ/sanShM0fB2LWp3M2dJK141/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyCEfV%2FbtqE6LQ3fdJ%2FsanShM0fB2LWp3M2dJK141%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Append Entries messages&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkHNmh/btqE57AvHjq/bOQeYxDM7DRryUlA2Mlku0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkHNmh/btqE57AvHjq/bOQeYxDM7DRryUlA2Mlku0/img.png&quot; data-alt=&quot;Heartbeat timeout&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkHNmh/btqE57AvHjq/bOQeYxDM7DRryUlA2Mlku0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkHNmh%2FbtqE57AvHjq%2FbOQeYxDM7DRryUlA2Mlku0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Heartbeat timeout&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTboBy/btqE6MoWPnq/99kTYW1Y2YDQ9zT4unx8Qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTboBy/btqE6MoWPnq/99kTYW1Y2YDQ9zT4unx8Qk/img.png&quot; data-alt=&quot;Split Vote - Wait another term and re-vote&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTboBy/btqE6MoWPnq/99kTYW1Y2YDQ9zT4unx8Qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTboBy%2FbtqE6MoWPnq%2F99kTYW1Y2YDQ9zT4unx8Qk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Split Vote - Wait another term and re-vote&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XaM96/btqE6yj7ndI/OBi0J1WucakvuzyklKCqSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XaM96/btqE6yj7ndI/OBi0J1WucakvuzyklKCqSk/img.png&quot; data-alt=&quot;Log Replication with the exactly same as heartbeat flow&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XaM96/btqE6yj7ndI/OBi0J1WucakvuzyklKCqSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXaM96%2FbtqE6yj7ndI%2FOBi0J1WucakvuzyklKCqSk%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Log Replication with the exactly same as heartbeat flow&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F4abP/btqE6NaivwG/C55z5CK5KzSuSh4yyLNSwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F4abP/btqE6NaivwG/C55z5CK5KzSuSh4yyLNSwK/img.png&quot; data-alt=&quot;Commit -&amp;amp;amp;gt; Reply to the client&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F4abP/btqE6NaivwG/C55z5CK5KzSuSh4yyLNSwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF4abP%2FbtqE6NaivwG%2FC55z5CK5KzSuSh4yyLNSwK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Commit -&amp;gt; Reply to the client&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NnrIx/btqE7ABv4SD/0jUmpoPJpah5KDcxxYMkX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NnrIx/btqE7ABv4SD/0jUmpoPJpah5KDcxxYMkX1/img.png&quot; data-alt=&quot;Partitioned Network&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NnrIx/btqE7ABv4SD/0jUmpoPJpah5KDcxxYMkX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNnrIx%2FbtqE7ABv4SD%2F0jUmpoPJpah5KDcxxYMkX1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Partitioned Network&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d1He9n/btqE7QKTHjO/a9cnPZVq855XflvUbKi5D1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d1He9n/btqE7QKTHjO/a9cnPZVq855XflvUbKi5D1/img.png&quot; data-alt=&quot;Can&amp;amp;#39;t replicate&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d1He9n/btqE7QKTHjO/a9cnPZVq855XflvUbKi5D1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd1He9n%2FbtqE7QKTHjO%2Fa9cnPZVq855XflvUbKi5D1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Can't replicate&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cssBhi/btqE8xRDPbj/41tFnKkGKbPiARaEDLPBtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cssBhi/btqE8xRDPbj/41tFnKkGKbPiARaEDLPBtK/img.png&quot; data-alt=&quot;Become a new leader due to &amp;amp;quot;HIGHER TERM&amp;amp;quot; and roll back&amp;amp;amp;nbsp;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cssBhi/btqE8xRDPbj/41tFnKkGKbPiARaEDLPBtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcssBhi%2FbtqE8xRDPbj%2F41tFnKkGKbPiARaEDLPBtK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Become a new leader due to &quot;HIGHER TERM&quot; and roll back&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;본 문서는 &lt;a href=&quot;https://raft.github.io&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;raft.github.io&lt;/a&gt;&amp;nbsp;를 번역하였습니다. &lt;a href=&quot;https://raft.github.io&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;raft.github.io&lt;/a&gt;&amp;nbsp; 에 접속하면 시각화 도구를 이용하여 어떻게 Leader Election이 일어나는지 쉽게 이해할 수 있습니다.&lt;/p&gt;</description>
      <category>기술 동향</category>
      <author>gozalex</author>
      <guid isPermaLink="true">https://elixian.tistory.com/9</guid>
      <comments>https://elixian.tistory.com/9#entry9comment</comments>
      <pubDate>Thu, 25 Jun 2020 10:31:04 +0900</pubDate>
    </item>
    <item>
      <title>RabbitMQ Clustering</title>
      <link>https://elixian.tistory.com/8</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;RabbitMQ.sh-600x600.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bif27g/btqEXJ6skmk/DNFzeVNUcmfy4R8n3WRfFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bif27g/btqEXJ6skmk/DNFzeVNUcmfy4R8n3WRfFK/img.png&quot; data-alt=&quot;토끼&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bif27g/btqEXJ6skmk/DNFzeVNUcmfy4R8n3WRfFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbif27g%2FbtqEXJ6skmk%2FDNFzeVNUcmfy4R8n3WRfFK%2Fimg.png&quot; data-filename=&quot;RabbitMQ.sh-600x600.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;600&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;토끼&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;RabbitMQ는 Erlang으로 만든 Message Queuing Framework 이라고 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;공식 홈에 따르면 RabbitMQ는 다음과 같은 프로토콜을 지원합니다.&lt;/p&gt;
&lt;h1&gt;Which protocols does RabbitMQ support?&lt;/h1&gt;
&lt;p&gt;RabbitMQ supports several messaging protocols, directly and through the use of plugins. This page describes the supported protocols and helps differentiate between them.&lt;/p&gt;
&lt;h2&gt;&lt;a id=&quot;amqp-091&quot; href=&quot;https://www.rabbitmq.com/protocols.html#amqp-091&quot;&gt;AMQP 0-9-1 and extensions&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;RabbitMQ was originally developed to&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/protocol.html&quot;&gt;support AMQP 0-9-1&lt;/a&gt;. As such this protocol is the &quot;core&quot; protocol supported by the broker. All of these variants are fairly similar to each other, with later versions tidying up unclear or unhelpful parts of earlier versions. We have&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/extensions.html&quot;&gt;extended&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;AMQP 0-9-1 in various ways.&lt;/p&gt;
&lt;p&gt;AMQP 0-9-1 is a binary protocol, and defines quite strong messaging semantics. For clients it's a reasonably easy protocol to implement, and as such there are&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/devtools.html&quot;&gt;a large number of client libraries&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;available for many different programming languages and environments.&lt;/p&gt;
&lt;p&gt;AMQP 0-9-1 is the protocol used by&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/getstarted.html&quot;&gt;RabbitMQ tutorials&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a id=&quot;stomp&quot; href=&quot;https://www.rabbitmq.com/protocols.html#stomp&quot;&gt;STOMP&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://stomp.github.io/&quot;&gt;STOMP&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;is a text-based messaging protocol emphasising (protocol) simplicity. It defines little in the way of messaging semantics, but is easy to implement and very easy to implement partially (it's the only protocol that can be used by hand over telnet).&lt;/p&gt;
&lt;p&gt;RabbitMQ supports STOMP (all current versions) via a&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/stomp.html&quot;&gt;plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a id=&quot;mqtt&quot; href=&quot;https://www.rabbitmq.com/protocols.html#mqtt&quot;&gt;MQTT&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://mqtt.org/&quot;&gt;MQTT&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;is a binary protocol emphasising lightweight publish / subscribe messaging, targetted towards clients in constrained devices. It has well defined messaging semantics for publish / subscribe, but not for other messaging idioms.&lt;/p&gt;
&lt;p&gt;RabbitMQ supports MQTT 3.1 via a&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/mqtt.html&quot;&gt;plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a id=&quot;amqp-10&quot; href=&quot;https://www.rabbitmq.com/protocols.html#amqp-10&quot;&gt;AMQP 1.0&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Despite the name, AMQP 1.0 is a radically different protocol from AMQP 0-9-1 / 0-9 / 0-8, sharing essentially nothing at the wire level. AMQP 1.0 imposes far fewer semantic requirements; it is therefore easier to add support for AMQP 1.0 to existing brokers. The protocol is substantially more complex than AMQP 0-9-1, and there are fewer client implementations.&lt;/p&gt;
&lt;p&gt;RabbitMQ supports AMQP 1.0 via a&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/plugins.html&quot;&gt;plugin&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;&lt;a id=&quot;http-and-websockets&quot; href=&quot;https://www.rabbitmq.com/protocols.html#http-and-websockets&quot;&gt;HTTP and WebSockets&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;While HTTP is not really a messaging protocol. However, RabbitMQ can transmit messages over HTTP in three ways:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/web-stomp.html&quot;&gt;Web STOMP plugin&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;supports STOMP messaging to the browser using WebSockets.&lt;/li&gt;
&lt;li&gt;The&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/web-mqtt.html&quot;&gt;Web MQTT plugin&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;supports MQTT messaging to the browser using WebSockets.&lt;/li&gt;
&lt;li&gt;The&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/management.html&quot;&gt;management plugin&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;supports a simple HTTP API to send and receive messages. This is primarily intended for diagnostic purposes but can be used for low volume messaging without&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.rabbitmq.com/reliability.html&quot;&gt;reliable delivery&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;엄청나군요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;RabbitMQ는 Erlang 기반이므로 기본적으로 멀티 호스트에서의 분산 처리를 지원합니다.&lt;/p&gt;
&lt;p&gt;바로 이 점이 &lt;u&gt;&lt;i&gt;&lt;b&gt;&quot;Development Philosophy of Elixian&quot; &amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;/u&gt;이며 제가 Elixir를 선택한 이유이기도 합니다.&lt;/p&gt;
&lt;p&gt;나중에 다시 언급하겠지만 Elixir / Erlang은 분산 처리 환경과 Fast Fail 이라는 두 가지 컨셉은 정말 다른 어느 언어보다도 훌륭하다고 생각합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다시 본론으로 돌아와서...&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;RabbitMQ는 elixir에서 했던 것과 동일하게&lt;/p&gt;
&lt;p&gt;Node.connect :&quot;rabbit@host1&quot; 처럼 간단한 함수 호출 하나로 호스트간의 연결을 유지시켜 줍니다.&lt;/p&gt;
&lt;p&gt;(예: elixir&amp;nbsp;&lt;span style=&quot;color: #333333;&quot;&gt;에서 Node Connect 할 때에 iex --name api@hole1 과 같이 접속하면 해당 노드와 connection이 이루어 집니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Erlang은 이 기능에 대한 보안을 위해 &lt;span style=&quot;color: #333333;&quot;&gt;RABBITMQ_ERLANG_COOKIE 를 설정하게 하는데요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이게 docker-compose로 up 하다가 어이 없는 상황을 경험하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;아래와 같이 RabbitMQ 공식 이미지를 사용하였을 경우,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #333333;&quot;&gt;Host1에서는 Cookie가 설정한 값대로 잘 들어있지만 Host2와 Host3에서는 엉뚱한 값이 들어 있는 경우가 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;background-color: #409d00; color: #dddddd;&quot;&gt;docker-compose exec rabbitmq01 cat ~/.erlang.cookie&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;background-color: #409d00; color: #dddddd;&quot;&gt;&quot;TLSD23932LKDX&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;rabbitmqctl join_cluster 시에 아무리 시도를 해도 노드를 찾지 못해 애 먹었는데요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;실제로 docker-compose.yml 에서 cookie를 설정했기 때문에 아무런 의심 없이 모든 노드가 동일한 cookie를 가지고 있을거라 예상했지만 결과는 사뭇 달랐습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;결국엔 echo \&quot;이것은 cookie 입니다.\&quot; &amp;nbsp;&amp;gt; ~/.erlang.cookie 로 업데이트 후, clustering 성공했습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;p&gt;&lt;span&gt;version: '3.8'&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;services:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;rabbitmq01:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;image: rabbitmq:3-management&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;container_name: rabbitmq01&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;hostname: hole1&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;environment:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- RABBITMQ_ERLANG_COOKIE=&quot;이것은 cookie 입니다.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- RABBITMQ_DEFAULT_USER=&quot;rabbit&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- RABBITMQ_DEFAULT_PASS=&quot;hole&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- RABBITMQ_NODE_NAME=&quot;rabbit@hole1&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- RABBITMQ_NODE_TYPE=&quot;queue-ram&quot;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ulimits:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;memlock:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;soft: -1&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;hard: -1&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;volumes:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- ./config/rabbitmq.config:/etc/rabbitmq/rabbitmq.config&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- ./config/definitions.json:/etc/rabbitmq/definitions.json&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- ./data:/var/lib/rabbitmq&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- logs:/var/log/rabbitmq&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;ports:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- 4369:4369&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- 5671:5671&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- 5672:5672&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- 15672:15672&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- 25672:25672&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;- 35197:35197&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;network_mode: host&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;restart: always&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;volumes:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;logs:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;driver: local&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;클러스터링이 성공하면 다음과 같은 로그가 나옵니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;Screen Shot 2020-06-18 at 8.41.18 PM.png&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;760&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ez0T5/btqEWCGL7J3/MlEGfwgIeERrXirvEj5jk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ez0T5/btqEWCGL7J3/MlEGfwgIeERrXirvEj5jk1/img.png&quot; data-alt=&quot;클러스터링 성공!!!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ez0T5/btqEWCGL7J3/MlEGfwgIeERrXirvEj5jk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEz0T5%2FbtqEWCGL7J3%2FMlEGfwgIeERrXirvEj5jk1%2Fimg.png&quot; data-filename=&quot;Screen Shot 2020-06-18 at 8.41.18 PM.png&quot; data-origin-width=&quot;1268&quot; data-origin-height=&quot;760&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;클러스터링 성공!!!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;# 추가 1&lt;/p&gt;
&lt;p&gt;기본적으로 네트워크는 모두 host를 사용하였으며&lt;/p&gt;
&lt;p&gt;각각의 docker host 에서 /etc/hosts 파일을 다음과 같이 수정하였습니다.&lt;/p&gt;
&lt;p&gt;(보안을 위해 ip / domain / alias는 실제와 다르게 변경하였습니다. 위의 로그와 다를 수 있음을 참고해주세요.)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;
&lt;p&gt;&lt;span&gt;10.10.120.11&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;api1.elixian.co.kr&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt; &lt;span style=&quot;color: #333333;&quot;&gt;hole1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;10.10.120.12&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;api2.&lt;span style=&quot;color: #333333;&quot;&gt;elixian.co.kr&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt; &lt;span style=&quot;color: #333333;&quot;&gt;hole2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;10.10.120.13&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;api3.&lt;span style=&quot;color: #333333;&quot;&gt;elixian.co.kr&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&lt;span&gt; &lt;span style=&quot;color: #333333;&quot;&gt;hole3&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;설정을 변경한 뒤, 꼭 네트워크 호스트 데몬을 재시작 해줍니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;br /&gt;systemctl restart systemd-hostnamed&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;# 추가 2&lt;/p&gt;
&lt;p&gt;네트워크를 Host 로 사용하여 /etc/hosts 를 수정하면 container에서도 동일하게 적용됩니다.&lt;/p&gt;
&lt;p&gt;만약 Bridge였다면 어땠을까요? ^^;;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;테스트 해보지는 않았습니다만 link를 잡는다던가 network을 connect 한다던가하는 작업이 필요하지 않았을가 생각해 봅니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;# 추가 3&lt;/p&gt;
&lt;p&gt;인터넷을 뒤지다가 재미난 것을 발견했습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;Screen Shot 2020-06-18 at 8.43.36 PM.png&quot; data-origin-width=&quot;2456&quot; data-origin-height=&quot;1478&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUJqBK/btqEWCNy6DJ/RnGka3YOIQSj31495wU1E0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUJqBK/btqEWCNy6DJ/RnGka3YOIQSj31495wU1E0/img.png&quot; data-alt=&quot;http://tryrabbitmq.com&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUJqBK/btqEWCNy6DJ/RnGka3YOIQSj31495wU1E0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUJqBK%2FbtqEWCNy6DJ%2FRnGka3YOIQSj31495wU1E0%2Fimg.png&quot; data-filename=&quot;Screen Shot 2020-06-18 at 8.43.36 PM.png&quot; data-origin-width=&quot;2456&quot; data-origin-height=&quot;1478&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;http://tryrabbitmq.com&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;Try RabbitMQ 라는 사이트인데요.&lt;/p&gt;
&lt;p&gt;다양한 Exchange Type과 Producer / Consumer / Queue를 배치해 보면서 어떻게 데이터가 흘러가는지 시각적으로 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;잘 만들었네요 ^^;;&lt;/p&gt;</description>
      <category>Elixian의 Referenece</category>
      <category>ELIXIR</category>
      <category>erlang</category>
      <category>Queue</category>
      <category>rabbitmq</category>
      <category>메시지</category>
      <category>분산 처리</category>
      <category>토끼</category>
      <author>gozalex</author>
      <guid isPermaLink="true">https://elixian.tistory.com/8</guid>
      <comments>https://elixian.tistory.com/8#entry8comment</comments>
      <pubDate>Thu, 18 Jun 2020 20:45:27 +0900</pubDate>
    </item>
  </channel>
</rss>