<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>class LifeArchive { }</title>
        <description>//MARK: I love making INSANELY great service!</description>
        <link>https://pilgwon.github.io/</link>
        <atom:link href="https://pilgwon.github.io/feed.xml" rel="self" type="application/rss+xml"/>
        <pubDate>Wed, 30 Mar 2022 17:18:19 +0000</pubDate>
        <lastBuildDate>Wed, 30 Mar 2022 17:18:19 +0000</lastBuildDate>
        <generator>Jekyll v3.9.0</generator>
        
        <item>
            <title>[수위프트UI/번역] SwiftUI에서 에러를 표시하는 가장 간결한 방법</title>
            <description>&lt;p&gt;에러 메세지는 사용자에게 실패 상황을 알려줄 때 꼭 필요한 요소 중 하나입니다. 보통 앱을 만들면 예상한대로만 흘러가는 행복한 흐름에 집중하는 경우가 있는데요, 하지만 예상하지 못 한 상황이 생겼을 때를 대비하는 것도 정말 중요합니다. 그렇다고 모든 에러 메세지를 하나씩 띄우는 것을 하자니 이것도 쉽지 않은 일입니다.&lt;/p&gt;

&lt;p&gt;글쓴이가 앱을 만들 때는 미래의 프로젝트에서도 쓸 수 있는 지속 가능한 방법을 꾸준히 고민했고, 이런 고민의 결과로 만든 익스텐션들은 역시나 미래의 나를 더 생산적이고 쉽게 개발할 수 있게 만들었다고 합니다. 오늘은 그 중 Localized Error를 유저에게 쉽게 보여줄 수 있는 방법을 소개하려고 합니다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This article was originally written by Antoine van der Lee.&lt;br /&gt;
이 글은 Antoine van der Lee가 작성한 글의 번역본입니다. &lt;a href=&quot;https://www.avanderlee.com/swiftui/error-alert-presenting&quot;&gt;원문 링크&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;localized-error란-무엇인가요&quot;&gt;Localized Error란 무엇인가요?&lt;/h2&gt;

&lt;p&gt;얼럿을 띄우는 것에 대해 알아보기 전에, 먼저 보통의 에러와 Localized Error의 차이가 무엇인지 알고 가는 것이 좋겠습니다. Localized Error는 에러가 발생한 이유와 함께 현지화된 메세지를 제공합니다. 이 메세지를 사용해서 유저가 읽을 수 있는 에러 메세지를 제공하려고 합니다.&lt;/p&gt;

&lt;p&gt;Swift의 에러 핸들링에 대해 궁금하시다면 글쓴이의 다른 글인 &lt;a href=&quot;https://www.avanderlee.com/swift/try-catch-throw-error-handling/&quot;&gt;Try Catch Throw: Error Handling in Swift with Code Examples&lt;/a&gt;를 참고하시기 바랍니다.&lt;/p&gt;

&lt;h2 id=&quot;제네릭한-메소드-생성하기&quot;&gt;제네릭한 메소드 생성하기&lt;/h2&gt;

&lt;p&gt;에러 메세지를 띄우는 데에 들이는 노력이 줄어들수록 이상적인 해결책에 가까워질 것입니다. 메소드가 에러를 보여줄지 결정할테니 우리가 할 일은 뷰와 잠재적인 에러의 바인딩을 만들어 두는 것입니다.&lt;/p&gt;

&lt;p&gt;아래의 예시의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArticleView&lt;/code&gt;는 기사를 발행(publish)할 수 있게 해주는 뷰입니다. 이 과정에서 에러가 발생할 수 있으니 적절한 에러 메세지를 띄우면 되겠네요.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;@StateObject&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;some&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;VStack&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;TextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prompt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Article title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;kt&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;Button&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;kt&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Publish&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;errorAlert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;에러 메세지를 보여주기 위해 옵셔널 에러 바인딩을 인자로 받는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;errorAlert(error: Error?)&lt;/code&gt; 뷰 모디파이어를 사용했습니다. 에러는 뷰 모델에 아래와 같이 정의되어 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ObservableObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LocalizedError&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;titleEmpty&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;errorDescription&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;titleEmpty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Missing title&quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;recoverySuggestion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;titleEmpty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Article publishing failed due to missing title&quot;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;@Published&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@Published&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Swift&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;titleEmpty&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 코드에선 에러 바인딩을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error.titleEmpty&lt;/code&gt;로 업데이트 했습니다. 이 에러는 desription과 recoverySuggestion을 제공하고 있으니 Localized Error 프로토콜에도 맞겠네요. 그러면 이제 이 메타데이터를 이용해서 얼럿을 띄우는 제네릭한 뷰 익스텐션을 만들어봅시다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;errorAlert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Binding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;buttonTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;OK&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;some&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;localizedAlertError&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LocalizedAlertError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrappedValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;isPresented&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;constant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;localizedAlertError&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localizedAlertError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;Button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttonTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wrappedValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recoverySuggestion&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;메소드가 인자로 받은 옵셔널 에러 바인딩을 통해 에러를 보여준 뒤, 얼럿이 닫힐 땐 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;로 만들어줍니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LocalizedAlertError&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LocalizedError&lt;/code&gt; 프로토콜에 맞게 만들지 않는다면 다음과 같은 에러가 발생합니다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Protocol ‘LocalizedError’ as a type cannot conform to the protocol itself&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;다음과 같은 구조를 만들면 문제없이 잘 작동합니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LocalizedAlertError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LocalizedError&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;underlyingError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LocalizedError&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;errorDescription&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;underlyingError&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;errorDescription&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;recoverySuggestion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;underlyingError&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;recoverySuggestion&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nf&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;localizedError&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;LocalizedError&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;underlyingError&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;localizedError&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LocalizedAlertError&lt;/code&gt;를 초기화할 때 LocalizedError가 아니면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;을 반환하기 때문에 현지화된 에러가 아니면 에러 메세지를 보여주지 않습니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;constant&lt;/code&gt; 바인딩 조건 덕분에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;일 경우 에러 메세지를 안보여줄 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;constant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;localizedAlertError&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;앞의 코드를 다 합치니 아래와 같은 간단한 구현이 에러 얼럿을 보여줄 수 있게 되었네요.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;@StateObject&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;some&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;VStack&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;TextField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prompt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Article title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;kt&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;Button&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;publish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;kt&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Publish&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;errorAlert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;어떤 Localized Error를 넣어도 아래와 같은 결과가 나오는 것을 확인하실 수 있습니다.&lt;/p&gt;

&lt;figure style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/assets/images/error-alert-presenting-in-swiftui-simplified/1.png&quot; /&gt;
  &lt;figcaption&gt;Localized Error를 표시하는 얼럿&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;h2 id=&quot;결론&quot;&gt;결론&lt;/h2&gt;

&lt;p&gt;최종 사용자에게 에러를 보여주는 것은 예상하지 못 한 상황이 발생했을 때 꼭 필요합니다. 범용적인 해결책을 사용하면 이러한 종류의 구현을 간결화할 수 있습니다. 그리고 이 해결책은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LocalizedError&lt;/code&gt; 프로토콜을 사용했기 때문에 써드파티 프레임워크에서 발생하는 에러에 대해서도 처리할 수 있습니다!&lt;/p&gt;

&lt;p&gt;글 내용이 마음에 드시고 SwiftUI 지식을 더 키우고 싶으시다면 원본 블로그의 &lt;a href=&quot;https://www.avanderlee.com/category/swiftui/&quot;&gt;SwiftUI 카테고리 페이지&lt;/a&gt;를 참고해보세요. (물론 저의 &lt;a href=&quot;https://pilgwon.github.io&quot;&gt;수위프트UI&lt;/a&gt;도 있습니다.)&lt;/p&gt;

&lt;p&gt;감사합니다!&lt;/p&gt;
</description>
            <pubDate>Mon, 28 Mar 2022 00:00:00 +0000</pubDate>
            <link>https://pilgwon.github.io/post/error-alert-presenting-in-swiftui-simplified</link>
            <guid isPermaLink="true">https://pilgwon.github.io/post/error-alert-presenting-in-swiftui-simplified</guid>
            
            
            <category>Posts</category>
            
        </item>
        
        <item>
            <title>[수위프트UI/번역] 코드로 알아보는 @Published의 사용법과 위험성</title>
            <description>&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt;는 SwiftUI의 프로퍼티 래퍼 중 하나로, 변화가 발생하면 뷰를 다시 그릴 수 있게 트리거해주는 역할을 합니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ObservableObject 프로토콜&lt;/code&gt;(&lt;a href=&quot;https://www.avanderlee.com/swiftui/stateobject-observedobject-differences/&quot;&gt;원문&lt;/a&gt;, &lt;a href=&quot;https://pilgwon.github.io/post/state-object-vs-observed-object&quot;&gt;번역&lt;/a&gt;)과 함께 사용하는 경우도 있지만 보통의 클래스에도 사용하기도 합니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티 래퍼는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt; 트리거에 반응하기 때문에 제대로 이해한 후 사용하지 않으면 잘못된 결과로 이어지기 십상입니다. 오늘은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티 래퍼의 작동 방식에 대해 깊이 알아보는 시간을 가져봅시다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This article was originally written by Antoine van der Lee.&lt;br /&gt;
이 글은 Antoine van der Lee가 작성한 글의 번역본입니다. &lt;a href=&quot;https://www.avanderlee.com/swiftui/published-property-wrapper/&quot;&gt;원문 링크&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;published-프로퍼티-래퍼가-뭐죠&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티 래퍼가 뭐죠?&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티 래퍼는 다음과 같이 보통의 프로퍼티 래퍼처럼 사용하면 됩니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleViewModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;@Published&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;An example title&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt;는 Class-constrained 한데, 이는 클래스의 인스턴스에서만 사용할 수 있다는 것을 의미합니다. 구조체에서 사용하면 아래와 같이 에러가 발생합니다.&lt;/p&gt;

&lt;figure style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/assets/images/published-risks-and-usage-explained/published_property_wrapper.png&quot; /&gt;
  &lt;figcaption&gt;`@Published`는 클래스의 프로퍼티에만 사용할 수 있습니다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티 래퍼의 wrapped value는 해당 프로퍼티의 실제 값을 나타냅니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// 출력값: An example title (이전 설명 코드 참조)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;퍼블리셔의 projected value는 아래와 같이 변화를 관찰하는데 사용됩니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cancellable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;receiveValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newTitle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Title changed to &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newTitle&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@Published explained&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 출력값&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Title changed to An example title&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Title changed to @Published explained&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;여기서 projected value에 접근하기 위해 달러 기호($)를 사용했습니다. 혹시 이 문법이 익숙하지 않으시다면 글쓴이의 다른 글인 &lt;a href=&quot;https://www.avanderlee.com/swift/property-wrappers/&quot;&gt;Property Wrappers in Swift explained with code examples&lt;/a&gt;를 참고하시기 바랍니다. (아직 번역하지 못했습니다.)&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;receivedValue&lt;/code&gt; 클로저는 구독했을 때와 값이 바뀔 때 값을 보냅니다. 이 변화를 캐치하기 위해선 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sink&lt;/code&gt; 연산자를 사용하면 됩니다. 간단한 예시로는 특정 레이블의 초기값과 미래의 업데이트를 모두 표시하고 싶을 때 사용할 수 있겠네요.&lt;/p&gt;

&lt;h2 id=&quot;willset-트리거를-이해하는-것이-중요합니다&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt; 트리거를 이해하는 것이 중요합니다&lt;/h2&gt;

&lt;p&gt;여기까지 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티 래퍼의 기본을 알아보았습니다. 하지만 변화를 일으킬 트리거가 언제 발생하는지에 대해 이해하는 것도 필수입니다. 프로퍼티의 변화는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt; 블록에서 발생하기 때문에 이 프로퍼티를 구독하고 있는 곳은 모두 값이 변하기 전에 변할거라는 사실을 알 수 있습니다.&lt;/p&gt;

&lt;p&gt;이해를 위해 다음과 같은 코드 예시를 준비했습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cancellable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;receiveValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newTitle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Title changed to: '&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;newTitle&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ViewModel title is: '&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@Published explained&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 출력값&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Title changed to: '@Published explained'&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ViewModel title is: 'An example title'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 예시에서 보셨듯이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sink&lt;/code&gt;에선 새로운 타이틀을 정확히 불러온 반면, 뷰모델의 프로퍼티의 값은 여전히 바뀌기 이전 값인 것을 확인하실 수 있습니다.&lt;/p&gt;

&lt;p&gt;이러한 차이점으로 인해 실제 서비스에서 예상하지 못한 버그로 이어지기 쉽습니다. 이런 버그는 레이블의 텍스트를 변경할 때도 발생할 수 있을 정도로 흔합니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;cancellable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;receiveValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;weak&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newTitle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// 변화가 발생했으니 레이블의 값을 변경합니다.&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;updateTitleLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;// 레이블의 초기값을 넣어줍니다.&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;updateTitleLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;updateTitleLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;titleLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Title label text is now: '&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;titleLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;empty&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;updateTitleLabel()&lt;/code&gt;은 레이블의 텍스트를 업데이트하는 코드를 담고 있습니다. 그런데 우리는 이 메소드를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sink&lt;/code&gt; 연산자 내부에서 호출하기 때문에, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt; 단계에서 호출됩니다. 위에서 설명드린 것처럼 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt; 단게의 값은 새로운 값이 아니라 바뀌기 전의 값이라 원하는 결과가 나오지 않습니다.&lt;/p&gt;

&lt;p&gt;위의 예시 코드의 버그는 아래와 같이 수정하면 해결할 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;viewDidLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;cancellable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;sink&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;receiveValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;weak&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newTitle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;titleLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newTitle&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Title label text is now: '&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;titleLabel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;??&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;empty&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;publish되는 타이틀 값을 사용하기 때문에, 우리는 가장 최근에 publish된 값을 지속적으로 표시할 수 있게 되었습니다. 게다가 값을 처음 넣을 때도 publish되기 때문에 레이블의 초기값도 걱정하지 않아도 됩니다.&lt;/p&gt;

&lt;h3 id=&quot;왜-didset이-아니고-willset일까요&quot;&gt;왜 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;didSet&lt;/code&gt;이 아니고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt;일까요?&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt;대신 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;didSet&lt;/code&gt;을 사용하지 않는지 궁금해 하시는 분도 계실겁니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt;을 사용하는 이유는 SwiftUI가 새로운 뷰를 그리려면 과거의 상태(State)와 새로운 상태 사이에서 변경이 있는지 알아야 하기 때문입니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt;을 사용하면 과거의 상태에도 접근할 수 있기 때문에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt;을 사용한다고 생각하시면 되겠습니다.&lt;/p&gt;

&lt;h2 id=&quot;publihsed와-observableobject의-관계&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Publihsed&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservableObject&lt;/code&gt;의 관계&lt;/h2&gt;

&lt;p&gt;앞에서는 보통의 클래스에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티 래퍼를 사용하는 것에 대한 예시였다면, 이젠 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ObservedObject&lt;/code&gt;에서 사용하는 경우를 설명드리겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ObservableObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;@Published&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;An example title&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ObservedObject&lt;/code&gt;는 자신이 가지고 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티가 변화하면 방출하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;objectWillChange&lt;/code&gt; 퍼블리셔를 기본으로 가지고 있는 특별한 종류의 프로토콜입니다.&lt;/p&gt;

&lt;p&gt;이 특징은 다음과 같은 코드로 대표할 수 있겠네요.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ArticleViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objectWillChange&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sink&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Articles view model changed!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;@Published explained&quot;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// 출력값&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Articles view model changed!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;SwiftUI는 어떠한 변화가 생겼을 때 이를 뷰에 적용하기 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;objectWillChange&lt;/code&gt; 퍼블리셔를 사용합니다. 이 문법에 관해 궁금하시다면 글쓴이의 지난 글인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject vs. @ObservedObject: The differences explained&lt;/code&gt;(&lt;a href=&quot;https://www.avanderlee.com/swiftui/stateobject-observedobject-differences/&quot;&gt;원문&lt;/a&gt;, &lt;a href=&quot;https://pilgwon.github.io/post/state-object-vs-observed-object&quot;&gt;번역&lt;/a&gt;)을 참고해주세요.&lt;/p&gt;

&lt;h3 id=&quot;결론&quot;&gt;결론&lt;/h3&gt;

&lt;p&gt;클래스 내부에서 프로퍼티의 변화를 감지하려면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티 래퍼를 사용하면 됩니다. 어떠한 새로운 값이라도 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt; 메소드를 통해 보내질겁니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;willSet&lt;/code&gt;이라서 직접 접근했을 때는 최신값을 받을 수 없다는 점을 기억하시구요. 그리고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ObservableObject&lt;/code&gt; 프로토콜은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티 래퍼와 찰떡이라 SwiftUI의 뷰에 어떠한 변화를 일으키기에도 좋습니다.&lt;/p&gt;

&lt;p&gt;번역한 글 외에도 원문을 찾아보거나 더 많은 SwiftUI 지식을 아고 싶다면 &lt;a href=&quot;https://www.avanderlee.com/category/swiftui/&quot;&gt;SwiftUI 카테고리&lt;/a&gt;를 참고해주시길 바랍니다. (&lt;a href=&quot;https://pilgwon.github.io&quot;&gt;물론 제가 번역한 글도 있습니다.&lt;/a&gt;) 혹시 글쓴이에게 추가적인 팁이나 피드백을 전달하고 싶다면 &lt;a href=&quot;https://www.twitter.com/twannl&quot;&gt;트위터&lt;/a&gt;를 통해 연락달라고 하네요.&lt;/p&gt;

&lt;p&gt;오늘도 읽어주셔서 감사합니다.&lt;/p&gt;
</description>
            <pubDate>Mon, 21 Mar 2022 00:00:00 +0000</pubDate>
            <link>https://pilgwon.github.io/post/published-risks-and-usage-explained</link>
            <guid isPermaLink="true">https://pilgwon.github.io/post/published-risks-and-usage-explained</guid>
            
            
            <category>Posts</category>
            
        </item>
        
        <item>
            <title>[수위프트UI/번역] @StateObject와 @ObservedObject, 무엇이 다를까요?</title>
            <description>&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;는 관찰중인 객체의 변경에 반응해서 화면을 업데이트할 수 있게 해주는 SwiftUI의 프로퍼티 래퍼입니다. 둘은 겉보기엔 비슷해 보이지만, SwiftUI 어플리케이션을 만들 때 꼭 알아야하는 뚜렷한 차이를 가지고 있습니다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This article was originally written by Antoine van der Lee.&lt;br /&gt;
이 글은 Antoine van der Lee가 작성한 글의 번역본입니다. &lt;a href=&quot;https://www.avanderlee.com/swiftui/stateobject-observedobject-differences/&quot;&gt;원문 링크&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;글쓴이는 처음엔 항상 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;를 쓰면 되는게 아닌가 생각할 정도로 닮아서 혼란스러웠지만, SwiftUI에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;의 용도를 알고난 이후엔 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;가 얼마나 중요한 존재인지 알게되었다고 합니다.&lt;/p&gt;

&lt;h2 id=&quot;observedobject는-무엇일까요&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;는 무엇일까요?&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;의 차이에 대해 깊이 알아보기 전에, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;가 무엇인지 이해하는 것이 좋겠습니다. 두 프로퍼티 래퍼 모두 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ObservableObject&lt;/code&gt; 프로토콜을 따르는 객체를 필요로 합니다. 이 프로토콜은 객체의 값이 바뀌기 전에 알려주는 퍼블리셔를 의미하며, SwiftUI가 화면을 다시 그리는 것을 가능하게 합니다.&lt;/p&gt;

&lt;p&gt;그러니 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ObservableObject&lt;/code&gt;를 따른다면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt; 프로퍼티 래퍼와 함께 SwiftUI 화면에 연결되어 데이터가 변경되었을 때 화면을 다시 그릴 수 있게 됩니다.&lt;/p&gt;

&lt;p&gt;대표적인 예시는 카운터가 있겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CounterViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ObservableObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@Published&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;incrementCounter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CounterView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@ObservedObject&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CounterViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;some&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;VStack&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Count is: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;Button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Increment Counter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;incrementCounter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 코드에선 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CounterViewModel&lt;/code&gt;이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ObservableObject&lt;/code&gt; 프로토콜을 따르기 때문에 뷰모델을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;로 정의할 수 있었습니다. 뷰모델 내부의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;count&lt;/code&gt; 값은 버튼을 누를 때마다 증가하게 되고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt;가 변화했다는 신호를 쏴서 다른 부분에서 변화를 알게 합니다.&lt;/p&gt;

&lt;p&gt;값이 변화하는 것을 좀 더 직관적으로 이해하기 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Published&lt;/code&gt; 프로퍼티 래퍼 대신 값을 바꾼 후 신호를 직접 쏴보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CounterViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ObservableObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private(set)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;incrementCounter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;objectWillChange&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 코드를 실행해보셨다면 여전히 값이 변경되면 화면이 업데이트되는 것을 확인하셨을 것입니다. 실제로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;objectWillChange.send()&lt;/code&gt; 메소드를 수동으로 쏘는 경우는 거의 없지만, 여러 값을 변경 후 수동으로 신호를 쏘는 것이 어떨 때는 더 나은 해결책이 될 수도 있습니다.&lt;/p&gt;

&lt;p&gt;위의 예시 코드는 SwiftUI가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt; 내부에서 일어나는 변화를 기반으로 어떻게 화면을 다시 그리는지 보여줍니다. 다음으로는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;에 대해서 알아봅시다.&lt;/p&gt;

&lt;h2 id=&quot;stateobject는-무엇인가요&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;는 무엇인가요?&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt; 프로퍼티 래퍼는 겉보기엔 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;와 비슷하게 작동합니다. 앞에 나온 예시의 코드의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;로 바꿨지만 큰 차이가 없어보입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CounterView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;/// `@ObservedObject` 대신 `@StateObject`를 사용한 모습&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@StateObject&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;viewModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CounterViewModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;some&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;VStack&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Count is: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;Button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Increment Counter&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;viewModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;incrementCounter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;여기까지 봤을 땐 글쓴이가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;를 주로 사용하려고 했던 것에 공감이 되실겁니다. 하지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt; 대신 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;를 사용하는 것에는 명확한 차이점이 존재합니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;를 통해서 관찰되고 있는 객체는 그들을 가지고 있는 화면 구조가 재생성되어도 파괴되지 않습니다. 이 차이점은 화면이 다른 화면을 포함하고 있는 경우를 생각하면 이해하기 쉽습니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;가 작동하는 방식을 알기 위해 기존의 카운터 코드를 다른 코드 안에 넣어보겠습니다&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;RandomNumberView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;@State&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;randomNumber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;some&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;View&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;VStack&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;Text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Random number is: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randomNumber&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;Button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Randomize number&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;randomNumber&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;randomElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;padding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;kt&quot;&gt;CounterView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;무작위 숫자 화면은 Randomize 버튼을 통해 새로운 무작위 숫자를 생성합니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;randomNumber&lt;/code&gt;에는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@State&lt;/code&gt; 프로퍼티 래퍼가 붙어있기 때문에 바뀔 때마다 카운터 화면이 새로 그려질 것입니다.&lt;/p&gt;

&lt;p&gt;아래 자료를 보시면 새로운 무작위 숫자가 생성될 때 카운터 숫자가 초기화되는 것을 확인하실 수 있습니다.&lt;/p&gt;

&lt;figure style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/assets/images/state-object-vs-observed-object/observedobject_counter_demo.gif&quot; /&gt;
  &lt;figcaption&gt;`@StateObject`가 아닌 `@ObservedObject`를 썼기 때문에 카운터가 초기화 되는 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;이를 해결하는 가장 쉬운 방법은 뷰 모델을 감싸고 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt; 대신에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;를 사용하는 것입니다. 앞서 설명드렸듯이, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;로 감싼 뷰모델은 화면이 새로 그려져도 카운터 숫자가 그대로 남아있습니다.&lt;/p&gt;

&lt;h2 id=&quot;그래서-stateobject는-언제-써야하나요&quot;&gt;그래서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;는 언제 써야하나요?&lt;/h2&gt;

&lt;p&gt;여기까지 두 프로퍼티 래퍼가 어떻게 작동하는지 알았으니, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;를 쓰면 더 좋은 경우가 어떤 게 있을지 알아보겠습니다.&lt;/p&gt;

&lt;p&gt;SwiftUI가 화면을 만들거나 다시 그릴 수 있는 가능성이 있는 경우엔 내부에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;를 쓰는 것은 안전하지 않습니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt; 객체를 외부에서 주입하는 것이 아니라면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;를 사용하는 것이 화면이 다시 그려져도 항상 같은 결과를 얻을 수 있을 것입니다.&lt;/p&gt;

&lt;h2 id=&quot;그렇다면-동일한-객체를-가져다-쓰는-모든-뷰에선-stateobject를-쓰는게-맞을까요&quot;&gt;그렇다면 동일한 객체를 가져다 쓰는 모든 뷰에선 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;를 쓰는게 맞을까요?&lt;/h2&gt;

&lt;p&gt;동일한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt; 인스턴스를 관찰하고 있는 자식들은 객체를 프로퍼티 래퍼로 표시할 필요가 없는데요. 그렇게 되면 여러군데에서 객체의 라이프사이클을 관리하게 돼서 그러지 않는 것이 좋습니다. 앞 섹션에서 말씀드렸듯이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ObservedObject&lt;/code&gt;를 주입하는 경우엔 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;를 사용하는 것이 좋습니다.&lt;/p&gt;

&lt;h3 id=&quot;결론&quot;&gt;결론&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;는 비슷한 특징을 가졌지만 SwiftUI가 그들의 라이프사이클을 관리하는 방식엔 확실한 차이점이 존재합니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@StateObject&lt;/code&gt;를 사용하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ObservedObject&lt;/code&gt;를 생성하는 화면에서도 일관된 결과를 보장할 수 있습니다. 의존 관계로 주입하는거라면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ObservedObject&lt;/code&gt;를 사용할 수 있겠습니다.&lt;/p&gt;

&lt;p&gt;감사합니다!&lt;/p&gt;
</description>
            <pubDate>Tue, 15 Mar 2022 00:00:00 +0000</pubDate>
            <link>https://pilgwon.github.io/post/state-object-vs-observed-object</link>
            <guid isPermaLink="true">https://pilgwon.github.io/post/state-object-vs-observed-object</guid>
            
            
            <category>Posts</category>
            
        </item>
        
        <item>
            <title>iOS 14.5 NavigationLink의 Unable to present 오류 해결하기</title>
            <description>&lt;p&gt;안녕하세요. 오늘은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftUI&lt;/code&gt;의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NavigationLink&lt;/code&gt;를 사용할 때 생기는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unable to present. Please file a bug&lt;/code&gt; 오류를 해결한 과정을 글로 작성했습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/navigation-link-trouble-shooting/bg.jpg&quot; alt=&quot;bg&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;문제-상황&quot;&gt;문제 상황&lt;/h2&gt;

&lt;p&gt;요즘 저는 SwiftUI로 아이패드 전용 어플리케이션을 만들고 있는데요, 얼마 전부터 메인 화면의 사이드 메뉴가 눌러지지 않는다는 리뷰가 들어오기 시작했고, 시뮬레이터에서 돌려본 결과 정말 그런 문제가 재현되었습니다.&lt;/p&gt;

&lt;p&gt;잘되던 메뉴가 갑자기 안되다니 이게 무슨 귀신이 곡할 노릇일까요?&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;안되는 경우&lt;/th&gt;
      &lt;th&gt;잘되는 경우&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;img src=&quot;/assets/images/navigation-link-trouble-shooting/not_working_five_menu.gif&quot; alt=&quot;image&quot; /&gt;&lt;/td&gt;
      &lt;td&gt;&lt;img src=&quot;/assets/images/navigation-link-trouble-shooting/working_five_menu.gif&quot; alt=&quot;image&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;문제-정의하기&quot;&gt;문제 정의하기&lt;/h2&gt;

&lt;p&gt;메인 화면엔 주요 메뉴와 보조 메뉴가 총 9개 있고, 프로필 및 로그인 관련 코드도 여기 다 붙어있기 때문에, 먼저 무슨 문제 때문에 이런 현상이 일어나는 것인지 알아내는 것이 우선이었습니다.&lt;/p&gt;

&lt;p&gt;야속하게도 콘솔엔 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unable to present. Please file a bug.&lt;/code&gt;라는 에러 로그만 찍히고 다른 힌트는 없었습니다.&lt;/p&gt;

&lt;p&gt;주요 메뉴를 제외한 나머지 코드를 모두 제거해도 오류는 계속 발생했기 때문에, 문제는 주요 메뉴에 있을 거라 생각했습니다.&lt;/p&gt;

&lt;p&gt;그렇다면 최근에 추가한 메뉴들 때문에 생기는 오류는 아닐까요? 그래서 메뉴를 줄여봤지만, 문제는 그대로 발생했습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/navigation-link-trouble-shooting/not_working_three_menu.gif&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;메뉴를 더 줄여봤더니 다행히도 2개에선 잘 되는 것을 확인했습니다!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/navigation-link-trouble-shooting/working_two_menu.gif&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;여전히 이유는 모르겠지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;메뉴(NavigationLink)가 3개 이상일 때 메뉴 이동이 되지 않는다&lt;/code&gt; 라는 문제를 알았습니다.&lt;/p&gt;

&lt;h2 id=&quot;문제-해결하기&quot;&gt;문제 해결하기&lt;/h2&gt;

&lt;p&gt;메뉴는 추가가 되어도 틀이 바뀐 적은 없었는데 갑자기 이런 일이 생겼습니다. 무슨 일이 생긴 걸까요?&lt;/p&gt;

&lt;p&gt;관련 로직에만 집중할 수 있게 간소화한 코드를 준비했습니다.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/pilgwon/319ff93386cd659b26e358f5025409f7.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;지금 와서 생각하면 2개일 때 잘 되는데 3개부턴 안된다는 건 공유해서 사용하고 있는 상태를 의심했어야 하는데 멍청한 저는 하루를 꼬박 구글링했습니다..&lt;/p&gt;

&lt;p&gt;그렇게 이틀째가 돼서야 깨달은 저는 각 메뉴의 상태를 분리해줬습니다.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/pilgwon/21d40a955e290a35cb3f95a999bb0a55.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;그럼 한 번 돌려볼까요?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/navigation-link-trouble-shooting/working_five_menu.gif&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;

&lt;p&gt;제대로 작동하네요!&lt;/p&gt;

&lt;p&gt;글로 적은 과정은 짧았지만, 이틀 동안 정말 눈감고 벽을 짚으며 미로를 빠져나가는 기분이었습니다…&lt;/p&gt;

&lt;h2 id=&quot;문제-원인-찾기&quot;&gt;문제 원인 찾기&lt;/h2&gt;

&lt;p&gt;왜 이런 문제가 발생했을까요?&lt;/p&gt;

&lt;p&gt;구글링하면서 찾은 내용이 몇 가지 있습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://forums.swift.org/t/14-5-beta3-navigationlink-unexpected-pop/45279&quot;&gt;Swift Forum&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.apple.com/forums/thread/678840&quot;&gt;Apple Developer Forum&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/67276205/swiftui-navigationlink-for-ios-14-5-not-working&quot;&gt;Stack Overflow&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.hackingwithswift.com/forums/swiftui/unable-to-present-please-file-a-bug/7901&quot;&gt;Hacking with Swift Forum&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;iOS 14.5가 되면서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NavigationLink&lt;/code&gt; 문제가 꽤 있었나 봅니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NavigationLink unable to present&lt;/code&gt; 라고만 쳐도 정말 많은 결과가 나왔습니다.&lt;/p&gt;

&lt;p&gt;대표적인 해결책으론 NavigationLink 하나당 빈 NavigationLink를 추가하는 방법이 있었습니다. &lt;a href=&quot;https://stackoverflow.com/a/67312740&quot;&gt;링크&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;하지만 이 방식은 제 상황엔 통하지 않았고 코드만 훑어보면서 해결해보려고 했지만 실패해서 하나씩 다 읽어보기로 했습니다.&lt;/p&gt;

&lt;p&gt;제 상황을 해결할 수 있는 가장 큰 실마리가 된 내용은 이 스레드입니다.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://forums.swift.org/t/14-5-beta3-navigationlink-unexpected-pop/45279/26&quot;&gt;jojost1님이 말한 내용&lt;/a&gt;은 저와 동일한 증상이었고, &lt;a href=&quot;https://forums.swift.org/t/14-5-beta3-navigationlink-unexpected-pop/45279/27&quot;&gt;Jon_Shier님의 답변&lt;/a&gt;은 저에게 힌트를 주었습니다. 저도 완벽하게 이해한 것은 아니고 동일한 로컬 상태를 공유하는 네비게이션 링크 간 이동이 공유된 상태를 초기화시켜버린다는 것 같습니다.&lt;/p&gt;

&lt;p&gt;이 부분에서 힌트를 얻어서 위에서 해결했던 방식대로 수정해봤고 결국엔 해결했습니다.&lt;/p&gt;

&lt;p&gt;이 버그는 iOS 14.5에서 시작해서 14.6에서도 계속되고 있는 것 같습니다.&lt;/p&gt;

&lt;p&gt;그리고 단순히 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SideMenu?&lt;/code&gt;을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bool&lt;/code&gt; 다섯 개로 바꾼다고 문제가 해결되지도 않습니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ViewModel&lt;/code&gt; 같은 거로 바깥으로 빼줘야 메뉴 이동이 잘됩니다. 근본적인 이유는 아직도 잘 모르겠습니다..&lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;아직 SwiftUI와 친해지고 있는 단계라 이게 SwiftUI 버그인지 저의 잘못된 사용으로 인해 생긴 문제인지 모르겠지만, 앞으로는 SwiftUI가 더 많이 발전해서 어떻게 만들지 보단 무엇을 만들지에 집중하는, 말 그대로 선언적인 개발을 하고 싶습니다.&lt;/p&gt;

&lt;p&gt;해결하는 방식도 스마트하지 못하고 이유도 명확하게 밝혀낸 것은 아니지만 제 글을 통해 누군가는 저처럼 고통받지 마시고 사용자에게 더 좋은 경험을 제공할 수 있는 시간을 더 가질 수 있었으면 좋겠습니다.&lt;/p&gt;

&lt;p&gt;읽어주셔서 감사합니다. 다음엔 더 유익한 내용으로 찾아뵙겠습니다.&lt;/p&gt;
</description>
            <pubDate>Mon, 31 May 2021 00:00:00 +0000</pubDate>
            <link>https://pilgwon.github.io/post/navigation-link-trouble-shooting</link>
            <guid isPermaLink="true">https://pilgwon.github.io/post/navigation-link-trouble-shooting</guid>
            
            
            <category>Posts</category>
            
        </item>
        
        <item>
            <title>SwiftGen으로 알아보는 선언형 프로그래밍</title>
            <description>&lt;p&gt;안녕하세요! 오늘은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;을 통해 선언형 프로그래밍에 대해 알아보도록 하겠습니다!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/swiftgen-declarative/bg.jpg&quot; alt=&quot;bg&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;문제-발생&quot;&gt;문제 발생&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt;의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Image Literal&lt;/code&gt;이나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Color Literal&lt;/code&gt;에 대해 아시나요?&lt;/p&gt;

&lt;p&gt;지금 다니고 있는 회사는 리소스(이미지, 컬러)를 에셋 카탈로그(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xcasset&lt;/code&gt;)로 관리하고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Image Literal&lt;/code&gt;나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Color Literal&lt;/code&gt;을 통해 리소스를 간접적으로 접근해서 사용하고 있습니다.&lt;/p&gt;

&lt;p&gt;그런데 얼마 전부터 알 수 없는 이유로 리터럴이 제대로 작동하지 않는 것을 발견했습니다.&lt;/p&gt;

&lt;figure style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/assets/images/swiftgen-declarative/1.png&quot; /&gt;
  &lt;figcaption&gt;제대로 작동하는 코드&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/assets/images/swiftgen-declarative/2.png&quot; /&gt;
  &lt;figcaption&gt;제대로 작동하지 않는 코드&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;원인을 찾을 수 없어서 결국 대안을 찾기로 했고, 이전에 적용해본 경험이 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;을 써보기로 했습니다.&lt;/p&gt;

&lt;h3 id=&quot;써드-파티-도구까지-써야-하나요&quot;&gt;써드 파티 도구까지 써야 하나요?&lt;/h3&gt;

&lt;p&gt;물론 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Image Literal&lt;/code&gt;은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UIImage(named:)&lt;/code&gt;로, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Color Literal&lt;/code&gt;은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UIColor&lt;/code&gt;로 대체할 수 있습니다.&lt;/p&gt;

&lt;p&gt;하지만 후자의 방식은 리터럴 방식보다 단점이 있습니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;에셋 카탈로그(이미지, 컬러)가 바뀌거나 삭제되어도 알 방법이 없습니다.&lt;/li&gt;
  &lt;li&gt;선언적이지 않습니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;이러한 이유로 기존의 장점을 유지하면서 안정적인 기술을 찾게 되었고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;이 제격이라 판단했습니다.&lt;/p&gt;

&lt;p&gt;다른 대안으로는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;R.Swift&lt;/code&gt;도 있는 것 같은데 사용해본 적이 없지만, 사용 방식은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;과 비슷할 것으로 예상됩니다.&lt;/p&gt;

&lt;h2 id=&quot;swiftgen을-소개합니다&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;을 소개합니다&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;은 프로젝트에 있는 리소스를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Swift&lt;/code&gt; 코드로 자동 생성해서 타입 안정성을 부여하는 도구입니다.&lt;/p&gt;

&lt;h3 id=&quot;장점&quot;&gt;장점&lt;/h3&gt;

&lt;p&gt;다음은 제가 생각하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;의 장점입니다.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;OS, 프레임워크에 상관없이 리소스를 선언적으로 사용할 수 있습니다.&lt;/li&gt;
  &lt;li&gt;에셋 카탈로그(이미지, 컬러)를 포함해서 폰트, 스트링 파일 등 다양한 리소스를 타입 안정성을 가지고 관리할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;사용법&quot;&gt;사용법&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;을 사용하는 방법을 알아볼까요?&lt;/p&gt;

&lt;p&gt;첫째, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftgen.yml&lt;/code&gt; 파일을 생성하고 관리하려는 리소스 정보를 입력합니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;xcassets:
  inputs:
    - PROJECT_NAME/Resources/Assets.xcassets
  outputs:
    - templateName: swift4
      output: PROJECT_NAME/Generated/Assets.swift
      params:
        forceProvidesNamespaces: true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;둘째, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;을 실행합니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;swiftgen
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;결과물(예: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Asset.swift&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L10n.swift&lt;/code&gt; 등)을 프로젝트에 추가하고 다음과 같이 사용하면 됩니다.&lt;/p&gt;

&lt;figure style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/assets/images/swiftgen-declarative/3.png&quot; /&gt;
&lt;/figure&gt;

&lt;p&gt;여기까지만 해도 리소스에 타입 안정성이 부여돼서 문제는 해결됐지만 다른 문제가 생깁니다.
지금처럼 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;을 사용하면 리소스가 변경될 때마다 터미널을 켜서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swiftgen&lt;/code&gt; 명령어를 입력해야 하는 귀찮은 상황이 발생합니다.&lt;/p&gt;

&lt;p&gt;위와 같은 귀찮은 상황을 제거하기 위해 스크립트를 만들고 프로젝트의 Build Phase에 등록합니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;swiftgen.sh

#!/bin/sh
RESOURCES_DIR_PATH=&quot;../PROJECT_NAME/Resources&quot;
HASH_FILE_PATH=&quot;$RESOURCES_DIR_PATH/checksum.md5&quot;

current_resources_hash=`find $RESOURCES_DIR_PATH -type f ! -path &quot;$HASH_FILE_PATH&quot; -print0 | sort -z | xargs -0 md5 | md5`

resources_hash_changed() {
  touch $HASH_FILE_PATH
  old_resources_hash=`cat $HASH_FILE_PATH`
  [ &quot;$old_resources_hash&quot; != &quot;$current_resources_hash&quot; ]
}

if resources_hash_changed
then
  (cd .. &amp;amp;&amp;amp; swiftgen)
  echo $current_resources_hash &amp;gt;| $HASH_FILE_PATH
fi
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;figure style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/assets/images/swiftgen-declarative/4.png&quot; /&gt;
  &lt;figcaption&gt;BuildPhase에 SwiftGen 적용&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;그러면 빌드할 때마다 체크섬 검사 후 리소스에 변경이 있었으면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;을 실행합니다.&lt;/p&gt;

&lt;figure style=&quot;text-align: center;&quot;&gt;
  &lt;img src=&quot;/assets/images/swiftgen-declarative/5.png&quot; /&gt;
  &lt;figcaption&gt;성공!&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;제 개인 프로젝트인 FREEZY의 경우엔 이미지와 컬러의 에셋 카탈로그, 다국어화 스트링 파일을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;을 통해 관리하고 있습니다.&lt;/p&gt;

&lt;p&gt;여기까지 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;에 대해 알아보았습니다. 여기부턴 앞에서 계속 말씀드렸던 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;선언적이다&lt;/code&gt;의 의미를 알아보도록 하겠습니다.&lt;/p&gt;

&lt;h2 id=&quot;선언적이다&quot;&gt;선언적이다&lt;/h2&gt;

&lt;p&gt;‘선언적’이라는 것은 코드가 선언형 프로그래밍을 따르고 있다는 의미로, 명령형 프로그래밍과는 대비되는 개념입니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;프로그램이 어떤 방법으로 해야 하는지를 나타내기보다 무엇과 같은지를 설명하는 경우에 &quot;선언형&quot;이라고 한다. 예를 들어, 웹 페이지는 선언형인데 웹페이지는 제목, 글꼴, 본문, 그림과 같이 &quot;무엇&quot;이 나타나야 하는지를 묘사하는 것이지 &quot;어떤 방법으로&quot; 컴퓨터 화면에 페이지를 나타내야 하는지를 묘사하는 것이 아니기 때문이다.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 내용은 위키피디아에서 인용했습니다. 선언적인 것은 설명 그대로 “어떻게” 보다는 “무엇을”에 집중하는 것입니다.&lt;/p&gt;

&lt;h3 id=&quot;왜-선언적이어야-할까요&quot;&gt;왜 선언적이어야 할까요?&lt;/h3&gt;

&lt;p&gt;이미지를 그리는 방식에 비유해보겠습니다.&lt;/p&gt;

&lt;p&gt;명령형으로 이미지를 그리는 방식이라면 우리는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hello.png&lt;/code&gt;라는 이름을 가진 이미지 파일을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UIKit&lt;/code&gt;인지 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AppKit&lt;/code&gt;인지에 따라 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UIImage&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NSImage&lt;/code&gt;를 사용하는 코드를 모두 작성해야 합니다. 하지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;을 사용하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Asset.hello.image&lt;/code&gt;라고만 작성하면 됩니다.&lt;/p&gt;

&lt;p&gt;이렇게 “어떻게”를 숨기고 실제 사용하는 곳에서는 “무엇을”에만 집중하는 것은 우리에게 타입 안정성, 코드의 간결함 같은 이로운 결과를 많이 제공합니다.&lt;/p&gt;

&lt;h3 id=&quot;실제로-선언적인-기술들&quot;&gt;실제로 선언적인 기술들&lt;/h3&gt;

&lt;p&gt;우리 주변의 선언적인 기술은 뭐가 있을까요?&lt;/p&gt;

&lt;p&gt;iOS 개발자에게 가장 익숙한 선언적인 기술은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftUI&lt;/code&gt;일 것 같습니다.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftUI&lt;/code&gt;는 뷰를 그리기 위한 하나의 코드로 기기별(아이폰, 아이패드, 애플 워치, 아이맥 등) 상황에 맞는 뷰를 그려줍니다.
사용자에게 뷰를 어떻게 그릴지보다는 무슨 뷰를 그릴지에 더 집중할 수 있게 만들기 때문에 선언적이라고 생각합니다.&lt;/p&gt;

&lt;p&gt;코드로 비교해볼까요? 빨갛고 동그란 X 버튼을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UIKit&lt;/code&gt;과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftUI&lt;/code&gt;로 만들어보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;UIKit

import UIKit

let button: UIButton = UIButton(type: .system)
button.setTitle(&quot;X&quot;, for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 20, weight: .bold)
button.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
button.backgroundColor = UIColor.red
button.layer.cornerRadius = 15
button.addTarget(self, action: #selector(), for: .touchUpInside)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;SwiftUI

Button(&quot;X&quot;) { }
	.foregroundColor(Color.white)
	.font(Font.system(size: 20, weight: .bold))
	.frame(width: 30, height: 30)
	.background(Color.red)
	.cornerRadius(15)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;어떤 코드가 더 선언적일까요?&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UIKit&lt;/code&gt;이라고 생각하는 분이 계실 수도 있습니다.&lt;/p&gt;

&lt;p&gt;하지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AppKit&lt;/code&gt;까지 고려했을 때 두 배가 되는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UIKit&lt;/code&gt; 코드와 비교해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftUI&lt;/code&gt;는 그대로일 것으로 예상이 됩니다.&lt;/p&gt;

&lt;p&gt;그런 면에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftUI&lt;/code&gt;가 선언적이라 할 수 있겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftUI&lt;/code&gt;가 어색하신 분들에겐 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Storyboard&lt;/code&gt;를 대입해서 생각해보시는 것도 좋겠네요!&lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;오늘은 iOS 개발 중 만나게 되는 리소스를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SwiftGen&lt;/code&gt;을 통해서 관리하는 방법에 대해 알아보고, 선언형 프로그래밍을 맛보는 시간을 가져보았습니다.&lt;/p&gt;

&lt;p&gt;아마 선언형 프로그래밍을 처음 접하시는 분은 많이 헷갈리실 것 같습니다.
저도 마찬가지로 처음 접했을 때는 무엇이 선언적인가에 대해 고민을 많이 했었습니다.
답은 많겠지만 단순하게 생각하는 것이 가장 쉬운 이해 방법이라고 생각합니다!&lt;/p&gt;

&lt;p&gt;읽어주셔서 감사하고 다음 글에서 뵙겠습니다!&lt;/p&gt;
</description>
            <pubDate>Mon, 01 Mar 2021 00:00:00 +0000</pubDate>
            <link>https://pilgwon.github.io/post/swiftgen-with-declarative</link>
            <guid isPermaLink="true">https://pilgwon.github.io/post/swiftgen-with-declarative</guid>
            
            
            <category>Posts</category>
            
        </item>
        
        <item>
            <title>👋 안녕 XcodeGen</title>
            <description>&lt;p&gt;오늘은 XcodeGen에 대해 공부한 내용과 그 결과로 내린 결론에 대해 얘기하는 시간을 가져보겠습니다!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/hello-xcodegen/bg.jpg&quot; alt=&quot;bg&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;xcodegen이란&quot;&gt;XcodeGen이란?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/yonaskolb/XcodeGen&quot;&gt;XcodeGen&lt;/a&gt;은 폴더 구조와 프로젝트 스펙에 맞춰서 Xcode 프로젝트를 만들어주는 커맨드 라인 도구입니다.&lt;/p&gt;

&lt;p&gt;대표적으로 &lt;a href=&quot;https://engineering.linecorp.com/ko/blog/improving-build-performance-line-ios-bazel/&quot;&gt;라인&lt;/a&gt;에서 XcodeGen을 사용하고 있는 것 같습니다.&lt;/p&gt;

&lt;p&gt;처음에 리드미만 읽고 큰 프로젝트에 적용해보려 하면 막막할 수 있기 때문에 &lt;a href=&quot;https://github.com/yonaskolb/XcodeGen/blob/master/Docs/Usage.md&quot;&gt;사용법&lt;/a&gt;을 차례대로 읽으며 작은 프로젝트에 기능을 단계적으로 적용하는 것을 추천드립니다.&lt;/p&gt;

&lt;h2 id=&quot;xcodegen의-특징&quot;&gt;XcodeGen의 특징&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;프로젝트 파일(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.xcodeproj&lt;/code&gt;)을 코드 저장소에 올리지 않고 명령어를 통해 프로젝트 파일을 만들기 때문에 머지할 때 프로젝트 파일에서 컨플릭트가 생길 일이 없습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;프로젝트 설정을 봐야 할 때 이곳저곳 돌아다닐 필요 없이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project.yml&lt;/code&gt; 파일 하나만 보면 됩니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;새로운 프로젝트를 찍어낼 때 편합니다. 저 같은 경우는 새로운 기술 적용을 위해 간단한 앱 프로젝트를 여러 개 찍어낼 경우가 있는데요, 이럴 때 공통으로 사용할 수 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project.yml&lt;/code&gt; 파일이 있으니 참 편했습니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;SwiftGen, SwiftLint 등 Build Phase에 스크립트를 추가해야 할 때도 간편하게 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project.yml&lt;/code&gt; 파일에 적어두기만 하면 됩니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://github.com/Carthage/Carthage&quot;&gt;Carthage&lt;/a&gt;를 추가적인 설정없이 간편하게 사용할 수 있다고 합니다만, 사용해보진 않았습니다. Carthage는 사용하려면 Xcode 12에선 별도의 스크립트가 필요한데다가, M1칩에선 작동하지 않는다고 합니다. 그래서 당분간 Carthage를 쓸 일은 없을 것 같아 테스트를 안해봤습니다. 자세한 내용은 &lt;a href=&quot;https://github.com/Carthage/Carthage/blob/master/Documentation/Xcode12Workaround.md&quot;&gt;여기&lt;/a&gt;에서 확인해주세요.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;실제-사용-예시&quot;&gt;실제 사용 예시&lt;/h2&gt;

&lt;p&gt;저는 실제로 뜨개질 단수계 겸 뭐든 셀 수 있는 카운터 어플리케이션인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stitch&lt;/code&gt;에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XcodeGen&lt;/code&gt;을 사용하고 있습니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;project.yml&lt;/code&gt; 파일은 다음과 같습니다.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/pilgwon/9ea4ee494f041a9b84661f691b775506.js&quot;&gt;&lt;/script&gt;

&lt;p&gt;프로젝트 껍데기만 기본적으로 만들어주는 내용이라 pod이 없는데도 pod install을 하고, SPM도 몇 개 쓰고 있지 않지만 이것만으로도 개인 작업 능률이 많이 올라갔습니다.&lt;/p&gt;

&lt;h2 id=&quot;힘든-점&quot;&gt;힘든 점&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XcodeGen&lt;/code&gt;을 사용하면 기본적으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.xcodeproj&lt;/code&gt; 파일을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitignore&lt;/code&gt;에 적어둡니다.
이러한 이유로 origin의 바뀐 코드를 pull하거나 main 브랜치에서 rebase나 merge로 땡겨올 때 코드는 바뀌지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.xcodeproj&lt;/code&gt;는 그대로인 상황이 발생합니다.&lt;/p&gt;

&lt;p&gt;그래서 매번 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xcodegen generate&lt;/code&gt; 명령어를 사용해야 하는데, 저는 이 부분이 많이 귀찮았습니다.&lt;/p&gt;

&lt;p&gt;이 귀찮음을 해결하기 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git hooks&lt;/code&gt;를 사용해보려고 했는데 &lt;a href=&quot;https://stackoverflow.com/questions/9038616/git-post-push-hook&quot;&gt;비슷한 것&lt;/a&gt;을 찾았지만 저한테 필요한 기능이 아니었습니다.&lt;/p&gt;

&lt;h2 id=&quot;결론&quot;&gt;결론&lt;/h2&gt;

&lt;p&gt;평소에 git pull이나 merge를 할 때 스크립트를 사용하는 개발팀이 아니라면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XcodeGen&lt;/code&gt;을 사용하는 것이 조금 무리가 있을거란 생각이 듭니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XcodeGen&lt;/code&gt;을 사용하기 위해선 팀원과의 많은 논의가 필요할 것 같습니다.
하지만 협업하는 인원이 많지 않거나 워킹 브랜치가 적은 경우엔 아주 적합한 것 같습니다.&lt;/p&gt;

&lt;p&gt;오늘은 여기까지 입니다!
저는 개인 프로젝트에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;XcodeGen&lt;/code&gt;을 계속 사용해보고 더 깊게 알아봐야겠네요.&lt;/p&gt;

&lt;h2 id=&quot;참고한-글&quot;&gt;참고한 글&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/yonaskolb/XcodeGen/blob/master/Docs/Usage.md#carthage&quot;&gt;XcodeGen Usage&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://medium.com/@ggaa96/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-xcodegen-%EB%8F%84%EC%9E%85%ED%95%98%EA%B8%B0-d0fd54691aad&quot;&gt;프로젝트에 XcodeGen 도입하기&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
            <pubDate>Mon, 30 Nov 2020 00:00:00 +0000</pubDate>
            <link>https://pilgwon.github.io/post/hello-xcodegen</link>
            <guid isPermaLink="true">https://pilgwon.github.io/post/hello-xcodegen</guid>
            
            
            <category>Posts</category>
            
        </item>
        
        <item>
            <title>💥 복잡한 커밋 로그를 정리해줄 구원자, gitmoji</title>
            <description>&lt;p&gt;개발 문화를 만드는 일은 정말 재밌지만, 때론 머리 아픈 경우도 많습니다.
오늘은 가장 인상 깊었던 개발 문화 중 하나인 gitmoji를 소개해 드리겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/gitmoji/bg.jpg&quot; alt=&quot;bg&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;개발에만-집중하기&quot;&gt;개발에만 집중하기&lt;/h2&gt;

&lt;p&gt;제가 가장 관심을 가지고 있는 분야 중 하나는 &lt;strong&gt;개발에만 집중할 수 있는 환경&lt;/strong&gt;을 만드는 것입니다.
간단히 말하면 개발 중 붕 뜨는 시간을 줄이는 것이죠.&lt;/p&gt;

&lt;p&gt;우리를 개발에 집중할 수 없게 만드는 요소는 참 많은데요.&lt;/p&gt;

&lt;p&gt;빌드나 아카이빙할 때 붕 뜨는 시간을 줄여줄 수 있는 해결책은 작년에 작성했던 &lt;a href=&quot;https://pilgwon.github.io/post/better-rome-usage&quot;&gt;Carthage+Rome에 대한 글&lt;/a&gt;에서 설명해 드렸었죠.&lt;/p&gt;

&lt;p&gt;오늘 제가 초점을 맞출 붕 뜨는 시간은 &lt;strong&gt;코드 리뷰할 때 변경된 코드를 이해하는 시간&lt;/strong&gt;입니다.&lt;/p&gt;

&lt;p&gt;코드 리뷰를 자주 하고 PR을 최대한 작은 단위로 작성한다고 하여도, 프로젝트의 모든 코드를 이해하고 있지 않은 이상 무엇이 바뀌었는지 이해하는 것은 쉬운 일은 아닙니다. 새로운 동료가 있다면 그분에겐 또 하나의 과제가 되겠죠.&lt;/p&gt;

&lt;p&gt;저는 깃모지가 이 시간을 효과적으로 줄여줄 수 있다고 생각합니다.&lt;/p&gt;

&lt;p&gt;저에게 깃모지는 커밋과 PR로 소통하는 과정에서 일어나는 머리 아픈 일을 해결해주는 구원자였습니다.&lt;/p&gt;

&lt;h2 id=&quot;gitmoji&quot;&gt;gitmoji&lt;/h2&gt;

&lt;p&gt;깃모지는 git + emoji를 합친 단어로, 모든 커밋 앞에 이모지를 붙이는 행위입니다.
깃모지를 사용하면 커밋의 목적이나 의도를 아주 쉽고 명확하게 알 수 있습니다.
그래서 코드 리뷰할 때를 포함한 커밋을 봐야 하는 경우 모두에게 도움이 됩니다.&lt;/p&gt;

&lt;h3 id=&quot;gitmoji를-쓰면-좋은-점&quot;&gt;gitmoji를 쓰면 좋은 점&lt;/h3&gt;

&lt;h4 id=&quot;시각적인-편안함을-제공합니다&quot;&gt;시각적인 편안함을 제공합니다&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/gitmoji/gitmoji-joa-1.png&quot; alt=&quot;image1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위 사진은 제 앱인 FREEZY의 실제 커밋 로그입니다.
이모지에 익숙해졌다면 글을 읽지 않아도 전체적으로 어떤 일이 있었는지 한눈에 볼 수 있으실 겁니다.&lt;/p&gt;

&lt;p&gt;조금 더 간단한 예시를 볼까요?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/gitmoji/gitmoji-joa-2.png&quot; alt=&quot;image2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;✨이모지는 기능 추가를 의미하는 깃모지인데요, 그러면 위의 이모지만 읽어도 기능 추가 위주의 작업이라는 것을 바로 알 수 있습니다.&lt;/p&gt;

&lt;h4 id=&quot;커밋-단위로-생각이-가능합니다&quot;&gt;커밋 단위로 생각이 가능합니다&lt;/h4&gt;

&lt;p&gt;깃모지를 사용하면 커밋할 때마다 이모지를 붙여야 해서 내가 작업한 내용을 커밋 하나로 대신하기가 어려워진다고 생각합니다.&lt;/p&gt;

&lt;p&gt;예를 들어 물건 편집 화면을 만든다고 해보겠습니다.&lt;/p&gt;

&lt;p&gt;기능 추가에 대한 ✨이모지 하나로 끝낼 수도 있지만, 💄을 사용해서 레이아웃 완성 시 커밋 한 번, API나 다른 기능들을 붙인 후 화면이 완성되면 ✨로 한 번, 테스트 작성 후 ✅까지 쓴다면 커밋이 조금 더 의미 있게 나뉘지 않을까요?&lt;/p&gt;

&lt;p&gt;이렇게 깃모지를 사용하면 커밋 단위로 생각을 할 수 있어서 좋다고 생각합니다.&lt;/p&gt;

&lt;h3 id=&quot;gitmoji의-단점&quot;&gt;gitmoji의 단점&lt;/h3&gt;

&lt;p&gt;깃모지의 단점은 &lt;strong&gt;익숙하지 않은 사람은 어떤 의미인지 알 수 없다&lt;/strong&gt;라고 생각합니다.&lt;/p&gt;

&lt;p&gt;하지만 후술할 gitmoji 사이트나 gitmoji-cli를 보면 이모지마다 설명이 적혀있고, 팀마다 사용하는 이모지를 정하고 간다면 큰 장애물은 아닐 겁니다.&lt;/p&gt;

&lt;h2 id=&quot;gitmoji를-사용하고-있는-곳&quot;&gt;gitmoji를 사용하고 있는 곳&lt;/h2&gt;

&lt;p&gt;다음은 깃모지를 실제로 사용하고 있는 코드 저장소입니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/atom/atom/blob/master/CONTRIBUTING.md#git-commit-messages&quot;&gt;Atom&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/carloscuesta/gitmoji&quot;&gt;gitmoji&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/OvertheOceanApps/GROOV&quot;&gt;GROOV&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;gitmoji-이렇게-사용하면-좋아요&quot;&gt;gitmoji, 이렇게 사용하면 좋아요&lt;/h2&gt;

&lt;h3 id=&quot;커밋-하나엔-이모지-하나만-쓰기&quot;&gt;커밋 하나엔 이모지 하나만 쓰기&lt;/h3&gt;

&lt;p&gt;커밋에 여러 이모지를 붙이면 그 커밋에서 어떤 일이 일어났는지 알기가 더 어려워집니다.
커밋은 최소 단위로 하고 이모지도 하나만 달도록 합시다.&lt;/p&gt;

&lt;h3 id=&quot;깃모지-가이드-직접-작성하기&quot;&gt;깃모지 가이드 직접 작성하기&lt;/h3&gt;

&lt;p&gt;세상에 이모지는 많고 커밋에 필요 없는 이모지도 많습니다.
깃모지를 팀에 도입하기로 했다면 팀에서 사용할 이모지와 각 용도를 문서로 작성하는 것이 좋습니다.&lt;/p&gt;

&lt;h3 id=&quot;같이-사용하면-좋은-도구들&quot;&gt;같이 사용하면 좋은 도구들&lt;/h3&gt;

&lt;p&gt;저는 깃모지를 써야 하는 경우엔 &lt;a href=&quot;https://gitmoji.carloscuesta.me&quot;&gt;gitmoji.carloscuesta.me&lt;/a&gt;를 항상 열어둡니다.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://matthewpalmer.net/rocket/&quot;&gt;Rocket&lt;/a&gt;이라는 앱을 사용하면 어디서든지 Slack 스타일로 이모지 작성이 가능합니다.&lt;/p&gt;

&lt;p&gt;터미널로 깃 작업을 하시는 분에겐 &lt;a href=&quot;https://github.com/carloscuesta/gitmoji-cli&quot;&gt;gitmoji-cli&lt;/a&gt;를 추천합니다.&lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;오늘은 깃모지에 대해 알아보고 어떻게 쓰면 좋은가에 대해 얘기해봤습니다.&lt;/p&gt;

&lt;p&gt;깃모지는 저에게 강렬한 인상을 남겼지만 그렇다고 모든 팀에서 써야 한다고 생각하지 않습니다. 그냥 언젠가 한 번은 소개하고 싶었습니다.&lt;/p&gt;

&lt;p&gt;깃모지는 기본적으로 커밋에 쓰는 거지만 제가 겪었던 깃모지는 PR에서 개발자들끼리 소통할 때도 사용했었습니다. 이 부분은 다음에 다룰 수 있으면 다루도록 하겠습니다.&lt;/p&gt;

&lt;p&gt;커밋과 PR에 관해서 저와 비슷한 고민을 한 분이 계신다면 깃모지를 추천합니다!&lt;/p&gt;

&lt;h2 id=&quot;참고한-문서--영상&quot;&gt;참고한 문서 / 영상&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=rCrzDaiMP4M&quot;&gt;Level up Your Git Commits with Gitmoji!&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://gitmoji.carloscuesta.me&quot;&gt;gitmoji&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
            <pubDate>Mon, 09 Nov 2020 00:00:00 +0000</pubDate>
            <link>https://pilgwon.github.io/post/gitmoji</link>
            <guid isPermaLink="true">https://pilgwon.github.io/post/gitmoji</guid>
            
            
            <category>Posts</category>
            
        </item>
        
        <item>
            <title>[번역] Point-Free #10 두 flatMap 이야기</title>
            <description>&lt;p&gt;Swift 4.1부터 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;의 기능 중 일부가 deprecate 됐습니다. 왜 그런 일이 일어났을까요? 오늘은 기본적인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;에 대해 알아보고, 없어진 기능에 대해 이해한 후 관련해서 유용한 코드를 작성해보도록 하겠습니다!&lt;/p&gt;

&lt;h2 id=&quot;시작하며&quot;&gt;시작하며&lt;/h2&gt;

&lt;p&gt;Swift 4.1에 제안된 내용은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;에 치중돼있는 기능을 작게 나눠서 새로운 이름을 부여하자는 것이었습니다. 이 제안 자체는 받아들여졌지만 커뮤니티 피드백에 의해 이름은 다르게 바뀌었습니다.&lt;/p&gt;

&lt;p&gt;먼저, 왜 이런 변화가 제안됐는지와 처음 제안된 이름이 바뀌어야 했는지 알아야 합니다. 앞으로 이름 짓는 것이 얼마나 중요한지와 예상하지 못한 방법으로 이전에 익혔던 직관을 활용할 수 있다는 것을 보여드리고자 합니다.&lt;/p&gt;

&lt;h2 id=&quot;두-flatmap-이야기&quot;&gt;두 flatMap 이야기&lt;/h2&gt;

&lt;p&gt;Swift 초기에는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reduce&lt;/code&gt; 그리고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;과 같은 함수를 표준 라이브러리에서 추가하는 등 함수형 프로그래밍 패턴에 대한 지원을 해줬습니다.&lt;/p&gt;

&lt;p&gt;Swift 1.0의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;은 우리에게 친근한 방식인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&lt;/code&gt;에 정의되어 있었습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// extension Array {&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   func flatMap&amp;lt;B&amp;gt;(_ f: @escaping (Element) -&amp;gt; [B]) -&amp;gt; [B] {&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   }&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이런 함수는 배열을 반환하기 때문에 연산자를 연결할 수 있다는 점에서 뛰어납니다.&lt;/p&gt;

&lt;p&gt;예를 들어, 다음과 같이 쉼표와 줄 바꿈으로 이루어진 값의 목록이 있다고 해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;csv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
1,2,3,4
3,5,2
8,9,4
&quot;&quot;&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 문자열의 쉼표 사이에 있는 값을 모두 추출하고 싶다면 어떻게 해야 할까요?&lt;/p&gt;

&lt;p&gt;먼저, 줄 바꿈을 기준으로 자릅니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;separator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [&quot;1,2,3,4&quot;, &quot;3,5,2&quot;, &quot;8,9,4&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이제 배열의 각 원소로 가서 쉼표를 기준으로 나눠보겠습니다.&lt;/p&gt;

&lt;p&gt;배열을 수정할 때는 우리에게 익숙한 map을 사용합니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;separator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;separator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [[&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;], [&quot;3&quot;, &quot;5&quot;, &quot;2&quot;], [&quot;8&quot;, &quot;9&quot;, &quot;4&quot;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 코드는 중첩된 배열을 반환하지만, 우리가 원하는 결과물은 평평한(flat) 배열입니다.&lt;/p&gt;

&lt;p&gt;이것이 정확히 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;이 제공하는 기능입니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;은 주어진 함수를 각 요소에 적용한 결과 배열을 평평하게(flatten) 만들어줍니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;separator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;separator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;3&quot;, &quot;5&quot;, &quot;2&quot;, &quot;8&quot;, &quot;9&quot;, &quot;4&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;배열에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;이 소개된지 얼마 지나지 않아 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&lt;/code&gt;에도 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;이 생기게 되었습니다. 명세는 다음과 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// extension Optional {&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   func flatMap&amp;lt;B&amp;gt;(_ f: @escaping (Element) -&amp;gt; B?) -&amp;gt; B? {&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   }&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&lt;/code&gt;에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;이 추가돼서 좋은 점은 옵셔널을 그냥 반환하는 것이 아니라 연산자를 연결할 수 있게 되었다는 점입니다.&lt;/p&gt;

&lt;p&gt;예를 들어, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;은 다음과 같이 데이터를 받아서 옵셔널 문자열을 반환하는 실패가 가능한 이니셜라이저를 가지고 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utf8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Optional(&quot;&quot;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;배열의 경우, 옵셔널로 감싸인 값을 변환하기 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;을 사용할 수 있습니다. 옵셔널 문자열을 정수로 변환하고 싶은 경우, 코드는 다음과 같을 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utf8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Optional(nil)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;빈 문자열로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt; 이니셜라이저를 호출했기 때문에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;을 반환받을 것입니다. 그런데 약간 이상한 점이 있습니다. 반환된 결과의 타입이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&amp;lt;Int&amp;gt;&lt;/code&gt;일까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utf8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// 옵셔널 타입인 `Int??`의 값이 unwrap되지 않았습니다.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;아닙니다! &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;을 사용한 결과는 이중 옵셔널인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int??&lt;/code&gt;입니다. 우리가 한 일은 옵셔널이 결과로 나올 수 있는 곳에 옵셔널을 반환하는 이니셜라이저를 입력으로 전달한 것입니다. 이 행동은 결국 중첩 옵셔널로 이어졌습니다. 여기서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;을 사용하면 모든 것이 해결됩니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;  &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utf8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// nil&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;드디어 반환값이 잘 처리됐네요. 계속 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;을 반환하고 있으니 다른 데이터를 넣어봅시다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;55&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utf8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Optional(7)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;과 함께라면 옵셔널 문자열을 받아서 껍데기를 벗긴 후 함수를 적용하고 거기서 반환된 옵셔널 결과를 flatten 한 후 단일 옵셔널 정수로 반환할 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&lt;/code&gt;에는 기존 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;의 의도를 모호하게 만드는 세 번째 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;이 있습니다. 이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;은 배열 요소를 받아서 변환 작업을 통해 옵셔널을 반환합니다. 문자열로 이루어진 배열을 예시로 들어보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;buckle&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;my&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shoe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;각 문자열을 정수로 변환하고 싶다면 어떻게 해야 할까요? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;을 사용하면 다음과 같은 결과를 얻게 될 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;buckle&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;my&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shoe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [{some 1}, {some 2}, nil, nil, nil]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;변환이 성공한 경우의 옵셔널로 감싸인 값과 실패했을 경우의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;로 이루어진 배열을 결과로 받을 것입니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt; 대신 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;을 사용하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;을 무시하기 때문에 안전하게 정수의 옵셔널 껍데기를 벗길 수 있게 됩니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;buckle&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;my&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;shoe&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [1, 2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;정말 유용하지 않나요? 하지만 이러한 종류의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;은 옵셔널의 품질에 따라 배열의 품질을 결정하기 때문에 기존과는 다른 느낌을 선사합니다.&lt;/p&gt;

&lt;p&gt;두 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;을 동시에 쓰면 느낌이 더 강해집니다. CSV 예제를 받아서 각 값을 정수로 만든 후 모두 더해보곘습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;separator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;separator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;,&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// 41&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;첫 번째 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;은 쉼표로 각 값을 분리하고 flatten 해서 하나의 배열로 반환합니다. 두 번째 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;은 문자열에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Int&lt;/code&gt;를 생성하려고 시도하고 실패하면 해당 경우를 무시합니다. 이 두 연산은 아주 다르다고 할 수 있는데 이름은 같습니다. 게다가 코드를 한 눈에 봤을 때 바로 알아보기는 힘들 것입니다.&lt;/p&gt;

&lt;p&gt;우리는 타입에 대해 생각하는 것에 시간을 많이 쏟습니다. 특히 함수의 모양에 관해서요. 때로는 이 과정이 메소드의 정의에서 길을 잃게 만듭니다. 컨테이너 타입이 정의에서 없어지기도 하고, 함수와 변수 이름이 흐릿해지기도 합니다. 그럴 땐 좀 더 쉽게 이해할 수 있게 함수 서명을 타입으로만 고정시켜봅시다. 프리 펑션 문법인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(Configuration) -&amp;gt; (Data) -&amp;gt; ReturnValue&lt;/code&gt;를 사용해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// flatMap : ((A) -&amp;gt; [B]) -&amp;gt; ([A]) -&amp;gt; [B]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// flatMap : ((A) -&amp;gt;  B?) -&amp;gt; ( A?) -&amp;gt;  B?&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// flatMap : ((A) -&amp;gt;  B?) -&amp;gt; ([A]) -&amp;gt; [B]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;튀는 형태가 하나 있지 않나요? 위쪽의 두 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&lt;/code&gt;나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&lt;/code&gt; 중 하나의 컨테이너 타입을 가지고 연산합니다. 하지만 세 번째 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt; 연산은 두 컨테이너를 모두 사용합니다.&lt;/p&gt;

&lt;p&gt;편의를 위해 생략했던 내용을 다시 채워보면 다음과 같을 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// flatMap : ((A) -&amp;gt;    Array&amp;lt;B&amp;gt;) -&amp;gt; (   Array&amp;lt;A&amp;gt;) -&amp;gt;    Array&amp;lt;B&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// flatMap : ((A) -&amp;gt; Optional&amp;lt;B&amp;gt;) -&amp;gt; (Optional&amp;lt;A&amp;gt;) -&amp;gt; Optional&amp;lt;B&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// flatMap : ((A) -&amp;gt; Optional&amp;lt;B&amp;gt;) -&amp;gt; (   Array&amp;lt;A&amp;gt;) -&amp;gt;    Array&amp;lt;B&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;각 컨테이너 타입을 제네릭 타입으로 표현하면 어떨까요? 각 타입의 이름을 다음과 같이 바꿔보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// flatMap : ((A) -&amp;gt; M&amp;lt;B&amp;gt;) -&amp;gt; (M&amp;lt;A&amp;gt;) -&amp;gt; M&amp;lt;B&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// flatMap : ((A) -&amp;gt; M&amp;lt;B&amp;gt;) -&amp;gt; (M&amp;lt;A&amp;gt;) -&amp;gt; M&amp;lt;B&amp;gt;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// flatMap : ((A) -&amp;gt; N&amp;lt;B&amp;gt;) -&amp;gt; (M&amp;lt;A&amp;gt;) -&amp;gt; M&amp;lt;B&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;앞의 두 서명은 정확히 동일한 모양을 가지네요! 하지만 세 번째 서명은 두 개의 서로 다른 제네릭 컨테이너 타입을 가지고 의미적으로 더 혼란스럽기도 합니다. 예를 들면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M&lt;/code&gt;을 생성하기 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt;이 정확히 하는 일은 무엇인가? 와 같이요. 입력받는 함수에 대해 변환을 거쳐서 뒤쪽의 결과가 나오는 것처럼 생각할 수도 있지만 그런 경우에도 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;N&lt;/code&gt;에 대해 잘 설명되진 않습니다.&lt;/p&gt;

&lt;p&gt;이해하기 쉽게 만드려면 다음과 같이 구체 타입을 사용하는 방법이 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// flatMap : ((A) -&amp;gt; B?) -&amp;gt; (M&amp;lt;A&amp;gt;) -&amp;gt; M&amp;lt;B&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이는 여전히 혼란스럽습니다. 모든 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M&lt;/code&gt;이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&lt;/code&gt;과 같이 사용할 수 있을까요? 이 세 번째 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;은 다른 것에 비해 상대적으로 덜 제네릭합니다.&lt;/p&gt;

&lt;h2 id=&quot;optional-promotion&quot;&gt;Optional Promotion&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&lt;/code&gt;을 반환하는 연산을 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Array&lt;/code&gt;에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;을 덮어씌우는 것에는 또 다른 이슈가 있는데요, 바로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional Promotion&lt;/code&gt; 입니다. 옵셔널 파라미터를 필수로 하는 경우, Swift는 값을 자동으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&lt;/code&gt;을 감쌉니다. 이는 코드를 더욱 간결하게 만들어주고 엔지니어에게 주어진 보일러플레이트 코드에 대한 부담을 줄여줍니다. 보통 이 결과는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.some&lt;/code&gt;이 명시적으로 감싸져서 나옵니다. 하지만 타입 추론은 양날의 검이라서 옵셔널을 반환하는 클로저의 경우엔 어떻게 해도 같은 결과가 나오는 공평한 상황이 생깁니다.&lt;/p&gt;

&lt;p&gt;다음과 같은 코드가 있다고 해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [2, 3, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 코드는 컴파일, 실행 그리고 결과 생성까지 잘 됩니다. 하지만 의미적으로는 이상합니다. 우리는 클로저에서 옵셔널을 반환하지 않습니다. 그 이유는 다음과 같이 컴파일러가 자동으로 값을 감싸주기 때문입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [2, 3, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;값을 수동으로 감싸는 로직은 약간 불편해 보입니다. 옵셔널은 항상 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.some&lt;/code&gt;을 반환해야 하고 실패할 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;을 반환해야 합니다. 하지만 이 연산은 절대 실패할 수 없기 때문에 그냥 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;을 사용하겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [2, 3, 4]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;옵셔널 프로모션이 존재하기 때문에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;과 작업하는 어떠한 연산자든 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;과도 작동할 수 있습니다. 보통 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;을 사용하는 것을 피하려고 하고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;을 사용하려고 하는 것이 바로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;은 대부분 결과를 반환하는데 성공하지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;은 그렇지 않을 수 있기 때문입니다. 그런데 이렇게 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;을 모든 곳에 쓰게 된다면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;의 의미적인 내용이 많이 모호해집니다. 그래서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;을 사용할 때 실패할 수 있는지 여부를 명확하게 문서화해야 합니다.&lt;/p&gt;

&lt;p&gt;더 최악인 경우는 컴파일 타임 오류가 날거라고 예상하는 타입에 변화를 만들었지만 중첩된 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;과 옵셔널 프로모션으로 인해 컴파일은 성공하고 런타임에 원하지 않는 행동을 하는 경우입니다.
예를 들어, 옵셔널 값인 name을 가지는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User&lt;/code&gt; 구조체가 주어졌고 이를 배열로 관리한다고 해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;users&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Blob&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Math&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;유저의 배열이 주어졌을 경우, 그들의 이름을 뽑아내기 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;map&lt;/code&gt;을 사용할 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [{some &quot;Blob&quot;}, {some &quot;Math&quot;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;하지만 이 배열은 옵셔널 값을 가지는 배열입니다. 우리가 실제로 해야 하는 것은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;을 사용하는 것이죠.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [&quot;Blob&quot;, &quot;Math&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이러한 코드는 실제 상황에도 많이 만나는 경우입니다. 그런데 만약 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;User&lt;/code&gt; 타입이 name 값을 필수로 바꾼다면 어떨까요? 우리의 강력한 타입 시스템 덕분에 우리는 옵셔널 껍데기를 벗길 수 있게 될테니 다음과 같을 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;컴파일은 당연히 될 것입니다. 그러면 결과는 어떨까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;users&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flatMap&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [&quot;B&quot;, &quot;l&quot;, &quot;o&quot;, &quot;b&quot;, &quot;M&quot;, &quot;a&quot;, &quot;t&quot;, &quot;h&quot;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;예상치 못한 결과네요! 이러한 이상한 친구의 이름이 새로 바뀐다니 너무 좋습니다.&lt;/p&gt;

&lt;h2 id=&quot;compactmap과-filtermap&quot;&gt;compactMap과 filterMap&lt;/h2&gt;

&lt;p&gt;앞에서 보셨듯이 몇몇 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;은 다른 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;과는 다른 행동을 하는 것을 보셨을 것입니다. 이게 바로 이름을 바꾸게 된 계기입니다. 배열과 옵셔널에 변환을 적용해서 같은 타입을 반환하게 하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;이 사라진 것이 아닙니다! 이름이 바뀐건 오직 튀는 친구들 뿐입니다.&lt;/p&gt;

&lt;p&gt;처음에 제안된 이름은 배열을 돌면서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt; 값을 무시하고 map한다는 의미의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filterMap&lt;/code&gt;입니다. 정의는 다음과 같았습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filterMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;약간의 바이크쉐딩(덜 중요한 논의)을 통해 이름은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compactMap&lt;/code&gt;으로 결정됐습니다. 이미 Ruby에서도 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compact&lt;/code&gt;라는 메소드가 배열의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt; 값을 걸러주는 의도로 사용돼고 있었기 때문에 선조의 지혜를 따르기로 했습니다. 그럼 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compactMap&lt;/code&gt;을 정의해볼까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;compactMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;none&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;함수 이름 말곤 아무것도 바뀌지 않았으니 비교하지 않으셔도 됩니다.&lt;/p&gt;

&lt;h2 id=&quot;filtermap의-일반성&quot;&gt;filterMap의 일반성&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compactMap&lt;/code&gt;이라는 이름이 가지는 불리한 점 중 하나는 이름이 배열에서 하는 행동과 강하게 엮여 있다는 것입니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compactMap&lt;/code&gt;은 배열의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;을 제거해서 더 작은 배열로 “압축(compacting)”합니다. 이는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compactMap&lt;/code&gt;이 가진 가능성을 오히려 막는 역할을 합니다.&lt;/p&gt;

&lt;p&gt;하지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filterMap&lt;/code&gt;이라는 이름의 좋은 점 중 하나는 꽤 괜찮은 일반성을 가진다는 것입니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A) -&amp;gt; Bool&lt;/code&gt;를 입력으로 받아서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A) -&amp;gt; A?&lt;/code&gt;라는 함수로 유도해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filterSome&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@escaping&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;none&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A) -&amp;gt; Bool&lt;/code&gt;의 값이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;라면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.some&lt;/code&gt;을 씌운 값을 반환할 것이고 그게 아니면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.none&lt;/code&gt;일 것입니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filterSome&lt;/code&gt;이 있으니 배열에 대한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&lt;/code&gt;를 다시 작성할 수 있겠네요.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@escaping&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;filterMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;filterSome&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;정수에 통하는 필터도 만들 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ([Int]) -&amp;gt; [Int]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그리고 이 필터를 배열에 연결하면 다음과 같은 결과가 나올 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;..&amp;lt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [2, 4, 6, 8, 10]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 필터는 좋아보이지만, 실제로 쓸만한 곳은 딱히 찾을 수가 없네요. Swift 표준 라이브러리가 만들어둔 기존의 필터를 사용할 수 있습니다. 그런데도 이런 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&lt;/code&gt;를 이런 방식으로 바라보는 것은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&lt;/code&gt;가 더 나은 일반화를 이끌어낼 수 있다고 생각하기 때문입니다.&lt;/p&gt;

&lt;p&gt;이런 사고 방식은 &lt;a href=&quot;https://www.pointfree.co/episodes/ep4-algebraic-data-types&quot;&gt;이전에도 있었습니다&lt;/a&gt;. 바로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&amp;lt;A&amp;gt;&lt;/code&gt;를 일반화해서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&amp;lt;A, B&amp;gt;&lt;/code&gt;로 표현한 것이죠.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;의 부재를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;로 모델링하는 것 대신, 그 자리에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt; 타입의 다른 값을 넣을 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt;에 대한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filterSome&lt;/code&gt; 같은 함수를 만든다면 다음과 같을 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partitionEither&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@escaping&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 함수는 주어진 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A) -&amp;gt; Bool&lt;/code&gt;에 대해서, 타입 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A)&lt;/code&gt;의 값을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&amp;lt;A, A&amp;gt;&lt;/code&gt;의 두 경우 중 하나로 나눈(partition) 결과를 반환합니다.&lt;/p&gt;

&lt;p&gt;이제 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filterMap&lt;/code&gt;을 partition과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt;에 대한 지식을 바탕으로 일반화해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partitionMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Element&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lefts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lefts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]())&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;switch&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lefts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rights&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filterMap&lt;/code&gt;에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&lt;/code&gt;를 유도한 것처럼 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;partitionMap&lt;/code&gt;에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;partition&lt;/code&gt;을 유도해볼까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partition&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@escaping&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(`&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partitionMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partitionEither&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// error&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 코드는 튜플 이름에 대해 타입 시스템에 문제가 있지만, 약간의 작업이 들어가면 충분히 해결 가능합니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partition&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@escaping&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(`&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;`:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lefts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partitionMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partitionEither&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lefts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;partition&lt;/code&gt;은 표준 라이브러리에 존재하지 않지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filterMap&lt;/code&gt;의 관계와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&lt;/code&gt;를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt;로 일반화하는 과정을 알아보다보니 저절로 밝혀졌습니다.&lt;/p&gt;

&lt;p&gt;여기서 두 개의 평행된 이야기가 나올 수 있겠네요.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A) -&amp;gt; Bool&lt;/code&gt;라는 명세를 optional을 반환하는 함수인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A) -&amp;gt; A?&lt;/code&gt;로 만드는 것은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filterMap&lt;/code&gt; 함수로 이어지고, 여기서 유도할 수 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&lt;/code&gt;는 우리에게 이미 친숙한 존재입니다.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A) -&amp;gt; Bool&lt;/code&gt;라는 명세를 either를 반환하는 함수인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(A) -&amp;gt; Either&amp;lt;A, A&amp;gt;&lt;/code&gt;로 만드는 것은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;partitionMap&lt;/code&gt; 함수로 이어지고, 여기서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;partition&lt;/code&gt; 함수를 유도할 수 있습니다.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;여기에 &lt;a href=&quot;https://www.pointfree.co/episodes/ep6-functional-setters&quot;&gt;functional setters&lt;/a&gt;와 같은 이전 에피소드에서 만든 다른 장치들을 조합할 수도 있습니다. 이 에피소드에서는 아주 작지만 매우 복잡한 방식으로 합쳐져있는 제네릭 세터(generic setters)를 정의했습니다. 게다가 프리 펑션과 잘 맞는 것을 확인했으니 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;partitionMap&lt;/code&gt;의 프리 펑션 버전을 정의해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partitionMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;@escaping&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lefts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rights&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;partitionMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;같이 쓸만한 함수도 하나 정의하겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;evenOdds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// (Int) -&amp;gt; Either&amp;lt;Int, Int&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이제 이 함수를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;partitionMap&lt;/code&gt;과 함께 사용해봅시다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;partitionMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;evenOdds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ([Int]) -&amp;gt; (lefts: [Int], rights: [Int])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;새로운 함수가 만들어졌네요. 이 함수는 정수로 이루어진 배열을 받아서 짝수는 왼쪽, 홀수는 오른쪽으로 나뉜 튜플을 반환합니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;partitionMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;evenOdds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ([2, 4, 6, 8, 10], [1, 3, 5, 7, 9])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;예상한대로 작동하는군요. 게다가 이전 에피소드에서 살펴본 &lt;a href=&quot;https://www.pointfree.co/episodes/ep6-functional-setters&quot;&gt;tuple composable setters&lt;/a&gt;도 사용할 수 있습니다. 짝수만 골라내서 제곱해봅시다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;partitionMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;evenOdds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;|&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;square&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// ([4, 16, 36, 64, 100], [1, 3, 5, 7, 9])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이제 단 몇 줄만으로 우리는 배열을 짝수와 홀수 둘로 나누고 한 쪽을 제곱할 수 있게 되었습니다.&lt;/p&gt;

&lt;h2 id=&quot;그래서-요점이-무엇인가요&quot;&gt;그래서 요점이 무엇인가요?&lt;/h2&gt;

&lt;p&gt;이번 에피소드에선 이름 짓기란 무엇인지와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;의 이름 변경에서 볼 수 있듯이 얼마나 이름 짓기가 빠르게 의미 없는 논쟁이 될 수 있는지에 대해서도 얘기해봤습니다. 그렇다면 이름을 바꾸는 것은 의미가 있었다고 할 수 있을까요? 코드를 deprecate하는 것은 많은 코드 베이스에 흙탕물을 뿌리는 것입니다. 대부분의 사람들은 자신의 코드 베이스가 기존의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;과 잘 작동하도록 만들어뒀을테니 Swift 4.1로 올린 후 이런 의문이 들 것입니다. “왜 이름을 바꾼거지?” 이름을 바꾸는 것이 그만큼의 작업을 감수해야할 정도로 의미있는 일일까요?&lt;/p&gt;

&lt;p&gt;무언가를 볼 때 한 발짝 뒤에서 조금 더 추상적인 방식으로 보고 흥미로운 방식으로 엮을 수 있다는 것은 정말 놀랍습니다. 우리는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;의 모양만 보고 어떤 것이 튀는지와 다른 두 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;이 직관적으로 같은지에 대해 알 수 있었습니다.&lt;/p&gt;

&lt;p&gt;그리고 튀는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filterMap&lt;/code&gt;으로 이름을 바꾸면서 이전에 보지 못했던 방식으로 일반화해볼 수 있는 기회도 있었습니다.&lt;/p&gt;

&lt;p&gt;이름 짓는 것은 정말 논쟁 거리가 되기 쉽습니다! 이름을 통해 관련된 개념 사이의 강력한 유대를 가질 수 있습니다. 이 유대는 우리로 하여금 흥미로운 발견을 할 수 있게 해줍니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filter&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;filterMap&lt;/code&gt;의 관계에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;partition&lt;/code&gt;과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;partitionMap&lt;/code&gt;의 관계를 이끌어 낸 것 처럼요!&lt;/p&gt;

&lt;p&gt;이번에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flatMap&lt;/code&gt;의 튀는 기능의 이름이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;compactMap&lt;/code&gt;으로 바뀌었으니, 나중엔 더 많은 타입에 대해 알아볼 기회도 생길 것 같습니다.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;본문에 연습문제와 참고 자료가 있습니다. &lt;a href=&quot;https://www.pointfree.co/episodes/ep10-a-tale-of-two-flat-maps&quot;&gt;여기&lt;/a&gt;에서 확인해주세요!&lt;/p&gt;
</description>
            <pubDate>Mon, 09 Mar 2020 00:00:00 +0000</pubDate>
            <link>https://pilgwon.github.io/post/episode-10-a-tale-of-two-flat-maps</link>
            <guid isPermaLink="true">https://pilgwon.github.io/post/episode-10-a-tale-of-two-flat-maps</guid>
            
            
            <category>Translations</category>
            
        </item>
        
        <item>
            <title>[번역] Point-Free #4 대수적으로 알아보는 타입 체계</title>
            <description>&lt;p&gt;Swift의 타입 체계와 대수의 연관점이 있을까요? 네, 아주 많이요! 이번 에피소드에선 둘 사이의 공통점을 알아보고 그 공통점을 이용해서 타입 안정성을 가지는 데이터 구조를 만들어보겠습니다.&lt;/p&gt;

&lt;h2 id=&quot;시작하며&quot;&gt;시작하며&lt;/h2&gt;

&lt;p&gt;오늘은 두 세계 사이의 연결점에 대해 알아봅시다. 바로 Swift의 타입과 대수입니다. 우리 모두 두 세계에 익숙하지만, 이들이 아주 깊이 연관돼있고 아름답기까지 하다는 사실을 아시나요? 두 세계의 공통점을 사용하면 데이터 구조가 얼마 만큼의 복잡도를 가지는지 이해할 수 있으며, 일어날 수 없는 상태에 대해 컴파일 시간에 예방하는 더 나은 구조를 생성할 수 있습니다.&lt;/p&gt;

&lt;h2 id=&quot;대수적으로-알아보는-구조체&quot;&gt;대수적으로 알아보는 구조체&lt;/h2&gt;

&lt;p&gt;먼저 간단한 예시인 구조체부터 시작하겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 구조체는 두 개의 제네릭을 받는 구조입니다. 그리고 두 개의 필드가 존재하는데 각 필드가 제네릭 데이터를 하나씩 받습니다. 이 구조체의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;에 타입을 넣고 그에 맞는 경우의 수를 계산해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&amp;lt;Bool, Bool&amp;gt;&lt;/code&gt;는 정확히 4개의 값을 가질 수 있습니다. 다른 값을 넣는다면 Swift의 컴파일러가 허락하지 않을 것입니다. 또 다른 예제를 만들어봅시다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bool&lt;/code&gt;과 짝을 이룰 세 개의 값을 가질 수 있는 열거형을 만들겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;one&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;two&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;three&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bool&lt;/code&gt;과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Three&lt;/code&gt;를 이용하면 가질 수 있는 값의 경우의 수가 어떻게 될까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;two&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;three&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;two&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;three&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;6가지네요! 흥미롭습니다.&lt;/p&gt;

&lt;p&gt;Swift에는 특이한 타입인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;가 존재합니다. 이 타입이 특이한 이유는 두 가지나 있습니다. 하나는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;의 타입과 값을 동일한 방식으로 표현할 수 있다는 점입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;두 번째는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;는 단 하나의 값만 가진다는 점입니다! 그러한 이유로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;에 아무 값을 넣지 않아도 문제가 없습니다. 이는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;의 단 하나의 값을 표현하는 것이지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;()&lt;/code&gt;로 무언가를 할 수는 없습니다. 반환 값이 없는 함수에서 반환값을 명시적으로 지정하지 않아도 비밀리에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;를 반환하는 이유이기도 합니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* -&amp;gt; Void */&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// return ()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Swift 컴파일러가 숨겨진 부분을 채워줍니다.&lt;/p&gt;

&lt;p&gt;그럼 이제 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bool&lt;/code&gt;과 연결해봅시다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;두 가지 값을 가지네요.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;의 쌍은 어떨까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;한 가지 값을 가집니다!&lt;/p&gt;

&lt;p&gt;Swift에는 이상한 타입이 하나 더 있습니다. 바로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;입니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;의 정의는 아주 간단합니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이게 무슨 의미일까요? 열거형인데 케이스가 없습니다. 이런 타입을 보통 “uninhabited type”이라고 부릅니다. 아무런 값도 가지지 않는 타입이라는 뜻입니다. 이런 타입은 다음과 같이 작성할 수 있는 방법이 없습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;???&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위의 물음표에 넣을 수 있는 값도 없는데다가 Swift 컴파일러도 허락하지 않습니다.&lt;/p&gt;

&lt;p&gt;만약 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&lt;/code&gt;를 쌍으로 연결하면 어떻게 될까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;second&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;???)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;앞에서 말한대로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;???&lt;/code&gt; 자리에 넣을 수 있는 값이 없습니다!&lt;/p&gt;

&lt;p&gt;또한 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;는 컴파일러의 특별한 관리를 받습니다. 만약 어떤 함수가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;를 반환하면 아무것도 반환하지 않는 함수라고 이해합니다. 예를 들어, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fatalError&lt;/code&gt; 함수는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;를 반환합니다.&lt;/p&gt;

&lt;p&gt;앞의 예제를 바탕으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;로 이루어진 쌍인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&amp;lt;A, B&amp;gt;&lt;/code&gt;의 경우의 수를 계산해볼까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Bool&amp;gt;  = 4&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Three&amp;gt; = 6&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Void&amp;gt;  = 2&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Void, Void&amp;gt;  = 1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Never&amp;gt; = 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;패턴이 보이네요. 이건 곱셈입니다!&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Bool&amp;gt;  = 4 = 2 * 2&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Three&amp;gt; = 6 = 2 * 3&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Void&amp;gt;  = 2 = 2 * 1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Void, Void&amp;gt;  = 1 = 1 * 1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Never&amp;gt; = 0 = 2 * 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&lt;/code&gt;는 값의 수를 곱한 수만큼의 값을 가질 수 있습니다. 앞에서 본 것 처럼 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&amp;lt;A, B&amp;gt;&lt;/code&gt;가 가질 수 있는 값의 경우의 수는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;가 가질 수 있는 값의 수와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;가 가질 수 있는 값의 수를 곱한 것과 동일합니다.&lt;/p&gt;

&lt;p&gt;이러한 현상을 대수적으로 풀어낸 또 다른 해석이 존재합니다. 바로 논리곱(logical conjunction)입니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&lt;/code&gt; 타입은 두 타입의 “and” 값을 모아놓은 것입니다. 즉, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&amp;lt;A, B&amp;gt;&lt;/code&gt;는 반드시 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;의 어떤 값과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;의 어떤 값을 가집니다.&lt;/p&gt;

&lt;p&gt;그리고 이것은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&lt;/code&gt;에서만 일어나는 일이 아닙니다. 다른 예시도 보시죠.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Theme&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;light&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dark&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;highlighted&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normal&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;selected&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Component&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;enabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;state&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;State&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;theme&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Theme&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Component&lt;/code&gt;를 대수적으로 풀면 어떻게 될까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Bool * Theme * State = 2 * 3 * 2 = 12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Component&lt;/code&gt;가 가질 수 있는 값의 경우의 수는 12네요!&lt;/p&gt;

&lt;p&gt;이제 타입의 이름은 신경쓰지 말고 어떤 데이터가 저장되어 있는지에 집중해봅시다. 지금까지 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&amp;lt;A, B&amp;gt;&lt;/code&gt;라고 쓰던 것이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A * B&lt;/code&gt;로 간결해졌습니다. 이런 모습이 이상해보일 수 있지만, 직관을 키우는데는 이만한 것이 없습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;A, B&amp;gt;        = A * B&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Bool&amp;gt;  = Bool * Bool&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Three&amp;gt; = Bool * Three&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Void&amp;gt;  = Bool * Void&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, Never&amp;gt; = Bool * Never&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;저희는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A * B&lt;/code&gt;를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;의 곱(product)이라고 부릅니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&amp;lt;A, B&amp;gt;&lt;/code&gt;를 풀어서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;가 가질 수 있는 값의 수를 곱하는 직관에 대해 조금 더 추상적으로 생각해봅시다. 타입이 가질 수 있는 값이 한정적일 때는 이런 식의 방식이 참인 반면, 다음과 같은 상황에선 도움이 되지 않습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Pair&amp;lt;Bool, String&amp;gt; = Bool * String&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 예시가 가질 수 있는 값의 경우의 수는 계산하지 않겠습니다. 왜냐하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String&lt;/code&gt;이 가질 수 있는 값의 수는 무한대이기 때문입니다.&lt;/p&gt;

&lt;p&gt;다음과 같이 무한 개의 값을 가질 수 있는 타입끼리 곱하는 경우도 있을 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// String * [Int]&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// [String] * [[Int]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이제는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt; 그리고 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bool&lt;/code&gt;의 이름을 없애고 각 타입이 가질 수 있는 값의 경우의 수를 표현해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Never = 0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Void = 1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Bool = 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이제 우리는 특정 타입에 대해서만 고민하지 않고 추상적이고 대수적인 개체에 대해 생각할 수 있게 되었습니다!&lt;/p&gt;

&lt;h2 id=&quot;대수적으로-알아보는-열거형&quot;&gt;대수적으로 알아보는 열거형&lt;/h2&gt;

&lt;p&gt;지금까지 Swift의 구조체가 타입의 곱셈에 대응한다는 것을 알아보았습니다. 그렇다면 곱셈의 쌍대(dual)인 덧셈에 해당하는 것은 무엇일까요? 이를 Swift의 타입 체계로 본다면 어떤 것일까요?&lt;/p&gt;

&lt;p&gt;Swift에는 정확히 이런 기능을 지원하는데요, 바로 열거형입니다! 일단 아주 일반적인 열거형을 정의해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;구조체에서 봤던 것과 동일하게 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bool&lt;/code&gt;로 예제를 구성해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;구조체와 동일하게 결과는 네 개네요. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Three&lt;/code&gt;의 경우는 어떨까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;two&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;three&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이번엔 다섯 개네요. 흥미롭습니다! 그럼 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;는 어떨까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;세 개입니다!&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;는요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(???)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;마지막 결과는 특히나 흥미롭습니다. 구조체에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;가 들어간 쌍(Pair)으로 예시를 들 때는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&amp;lt;A, Never&amp;gt;&lt;/code&gt;와 같은 모양을 가져서 아무런 쌍도 얻을 수 없었습니다. 하지만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt;의 경우엔 하나의 경우만 불가능한 경우이고 다른 값은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Bool&lt;/code&gt;을 받는 가능한 경우입니다.&lt;/p&gt;

&lt;p&gt;그렇다면 여기에 숨어있는 대수적인 비밀은 무엇일까요? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&amp;lt;A, B&amp;gt;&lt;/code&gt;에서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;의 값 사이의 관계를 알아봅시다!&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위의 예시에서 알 수 있듯이, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&amp;lt;A, B&amp;gt;&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;의 값의 수와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt;의 값의 수를 더한 결과입니다. 이 결과를 통해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt;는 타입의 덧셈에 직접적으로 대응한다는 것을 알 수 있습니다. 그리고 이게 바로 열거형이 “합 타입(sum types)”이라고 불리는 이유이기도 합니다. 또한, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&lt;/code&gt;에 했던 것처럼 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt;를 논리적인 측면에서 해석할 수도 있습니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt; 타입은 두 타입 중 하나를 값으로 가집니다. 즉, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&amp;lt;A, B&amp;gt;&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; 타입이 나타낼 수 있는 값의 수와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;B&lt;/code&gt; 타입이 나타낼 수 있는 값의 수를 합한 수 만큼의 값을 가질 수 있다는 것을 의미합니다.&lt;/p&gt;

&lt;p&gt;Swift 문법에 맞지는 않지만 더욱 직관적으로 이해하기 위해 기존의 코드를 좀 더 풀어서 써보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Three&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;void라는-단어를-조심하세요&quot;&gt;Void라는 단어를 조심하세요!&lt;/h2&gt;

&lt;p&gt;몇몇 언어(Haskell, PureScript, Idris 등)에서 값이 없는 타입을 표현하기 위해 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;(Swift에선 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;입니다)를 사용합니다. 그리고 이는 다른 언어로 갔을 때 혼란을 만들기도 합니다. 생각해보면 “Void”라는 단어의 의미는 아무것도 없는 공허를 뜻하기 때문에 아무것도 없는 타입을 표현하기 위한 이름으로 적절한 것 같기도 합니다.&lt;/p&gt;

&lt;p&gt;Swift의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;처럼 단 하나의 값을 가지고 있는 타입을 표현하는 더 나은 이름은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unit&lt;/code&gt;이 있습니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unit&lt;/code&gt;은 다음과 같이 정의할 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;unit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unit&lt;/code&gt;이 좋은 점은 드디어 타입의 이름(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unit&lt;/code&gt;)과 타입의 값(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt;)을 분리할 수 있게 되었다는 점입니다. 또 다른 좋은 점은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unit&lt;/code&gt;에 대한 실제 구조체 타입이 생겨서 익스텐션을 추가할 수 있게 되었다는 점입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Equatable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lhs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rhs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 코드를 통해 우리는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unit&lt;/code&gt;을 비교가 가능한(Equatable) 값만 입력으로 받는 함수에 넣을 수 있게 되었습니다. Swift의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;는 할 수 없는 일이라 더욱 끝내주네요. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;에 익스텐션을 추가하려고 하면 다음과 같은 에러를 만나게 됩니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Non&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nominal&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cannot&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;be&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extended&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;왜냐하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;는 빈 튜플로 정의되었기 때문입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;typealias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Swift의 튜플은 non-nominal 타입입니다. 다시 말하자면, 이름으로는 접근할 수 없고 구조로만 접근할 수 있다는 의미입니다. 이것은 Swift의 정말 아픈 손가락 중 하나라고 생각됩니다. 꼭 빠른 시일내에 보수되기를 바랍니다.&lt;/p&gt;

&lt;h2 id=&quot;빈-구조체-vs-빈-열거형&quot;&gt;빈 구조체 vs 빈 열거형&lt;/h2&gt;

&lt;p&gt;이제부터는 아주 이상한 일을 해볼 것입니다. 일단 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unit&lt;/code&gt;과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;의 정의를 꼼꼼히 살펴보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unit&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Never&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;아무런 경우가 없는 열거형이라는 점과 아무런 필드가 없는 구조체라는 점에서 비슷한 점이 존재하네요. 그러면 아무런 경우가 없는 열거형은 값이 없는 반면, 아무런 필드가 없는 구조체는 값이 하나 존재할까요? 위 코드만 봐서는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Unit&lt;/code&gt;에도 아무런 값이 존재하지 않는다고 생각하는 것이 충분히 가능해보입니다.&lt;/p&gt;

&lt;p&gt;이러한 이유를 직관적으로 이해할 수 있으신가요?&lt;/p&gt;

&lt;p&gt;이 질문에는 Swift의 타입과 대수 사이의 대응을 사용하면 더욱 쉽게 답변을 낼 수 있습니다. 직관적으로, “빈 열거형과 빈 구조체에는 어떤 값이 존재할까?”라는 질문은 “정수로 이루어진 빈 배열의 합과 곱은 무엇일까?”라는 질문과 동일하다고 생각할 수 있습니다.&lt;/p&gt;

&lt;p&gt;정수로 이루어진 배열이 있다고 해보겠습니다. 다음의 함수에 들어가야 할 내용은 무엇일까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;fatalError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;fatalError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;우리가 할 일은 배열의 모든 원소를 돌면서 합하거나 곱하는 것이겠죠?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;xs&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 코드는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;result&lt;/code&gt;의 기본값이 지정되지 않아서 당장은 컴파일되지 않습니다. 그러면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;result&lt;/code&gt;의 기본값은 무엇이 되어야 할까요? 이 질문에 답변하기 위해선 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum&lt;/code&gt;과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;product&lt;/code&gt;가 어떤 속성을 가져야하는지 이해해야 합니다. 그러면 저절로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;result&lt;/code&gt;가 어떤 값으로 시작해야하는지 정해질 것입니다. 몇 개의 배열을 받았을 때 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum&lt;/code&gt;과 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;product&lt;/code&gt;가 가져야 할 가장 기본적인 속성은 다음과 같을 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그러면 여기에 빈 배열을 넣어볼까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 등식을 만족시키려면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sum([])&lt;/code&gt;은 0이 되어야 하고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;product([])&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;이 되어야 합니다. 다른 선택지는 존재하지 않습니다. 그러니 합의 기본값은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;이고 곱의 기본값은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;이라고 할 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[])&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;product&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이제 이 개념을 타입 세계로 옮겨볼까요? 기본값을 타입으로 옮겨보면 “빈 합 타입”은 값이 없고(불가능하고) “빈 곱 타입”은 하나의 값을 가집니다! 드디어 대수를 이용해서 진퇴양난의 상황을 해결할 수 있게 되었네요! 정말 끝내줍니다!&lt;/p&gt;

&lt;h2 id=&quot;대수적-속성&quot;&gt;대수적 속성&lt;/h2&gt;

&lt;p&gt;여기까지 Swift의 타입과 대수 사이의 대응을 이해하기 위해 몇 가지 개념을 익혔습니다. 그러면 이제 이 지식을 활용해서 타입 구성에 대한 조금 더 높은 단계의 직관을 얻어볼 준비가 되었습니다.&lt;/p&gt;

&lt;p&gt;쉬운 것부터 시작하겠습니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;에 대응한다는 사실은 기억하실 것입니다. 그리고 대수 세계에선 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;로 곱하는 것은 아무일도 일으키지 않는다는 것을 알고 계실 것입니다. 그렇다면 이것을 타입에 적용하면 어떤 일이 일어날까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Void = 1&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// A * Void = A = Void * A&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 내용은 구조체의 필드에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt; 값을 사용하면 본질적으로는 타입이 변하지 않는 순 효과를 일으킨다는 의미입니다.&lt;/p&gt;

&lt;p&gt;반대로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;에 대응하는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;를 곱에 사용하면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;이라는 결과가 나옵니다. 타입 세계에서 보면 다음과 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Never = 0&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// A * Never = Never = Never * A&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그러니 구조체의 필드에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;를 넣는 것은 구조체에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt; 타입 하나만 넣는 것과 같은 결과를 냅니다. 완전히 소멸시켜버리는 것이죠.&lt;/p&gt;

&lt;p&gt;그러나 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;을 더하는 것은 결과값을 바뀌지 않게 해주며, 다음과 같이 표현할 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// A + Never = A = Never + A&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;다음과 같은 타입 표현이 있다고 해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// 1 + A = Void + A&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt;로 표현하면 다음과 같은 모양일 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Either&amp;lt;Void, A&amp;gt; {&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   case left(())&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   case right(A)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 타입은 오른쪽엔 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt;의 모든 값을 가지고 왼쪽엔 단 하나의 특별한 값인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;left(Void())&lt;/code&gt;를 가지게 될 것입니다. Swift에서 이런 모양을 가진 타입이 무엇이 있을까요? 바로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Optional&lt;/code&gt;입니다!&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Optional&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;none&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;some&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;none&lt;/code&gt;의 경우는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;left&lt;/code&gt;에 대응하고, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;some&lt;/code&gt;의 경우는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;right&lt;/code&gt;에 대응합니다. 그러니 다음과 같이 표현할 수 있겠죠.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// 1 + A = Void + A = A?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이제 아래와 같은 표현식을 만나게 되었다고 해보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Either&amp;lt;Pair&amp;lt;A, B&amp;gt;, Pair&amp;lt;A, C&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;지금까지 했던 방식으로 표현해보면 다음과 같겠네요.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// A * B + A * C&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;기본적인 대수를 사용해서 간단한 표현식으로 바꿀 수 있을 것 같습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이를 다시 원래대로 표현하면 열거형을 가진 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&lt;/code&gt;로 표현할 수 있겠네요.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이렇게 대수적인 직관은 데이터 구조를 간단하게 만들 수 있는 능력을 길러줍니다.&lt;/p&gt;

&lt;p&gt;이전 예제의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt;를 뒤집어 봅시다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;C&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;수학 세계의 말로 표현하면 다음과 같을 것입니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// (A + B) * (A + C)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;위 식은 인수분해할 것이 없기 때문에 더 이상 간단하게 만들 수 없습니다.&lt;/p&gt;

&lt;p&gt;물론 확장할 수는 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// A * A + A * C + B * A + B * C&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 결과를 타입 세계의 언어로 표현하면 네 개의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&lt;/code&gt;를 경우로 가지는 열거형이 될 것입니다. 만약 이게 여러분이 원하던 결과라면 대수의 힘을 한 번 더 느끼셨겠군요!&lt;/p&gt;

&lt;h2 id=&quot;그래서-요점이-무엇인가요&quot;&gt;그래서 요점이 무엇인가요?&lt;/h2&gt;

&lt;p&gt;지금까지는 직관에 도움을 주기 위해 Swift에서 작동하지 않는 많은 의사코드를 작성해왔습니다. 도움이 좀 되셨나요?&lt;/p&gt;

&lt;p&gt;이제는 실제 상황인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;URLSession&lt;/code&gt;의 메소드를 살펴보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// URLSession.shared&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   .dataTask(with: url, completionHandler: (data: Data?, response: URLResponse?, error: Error?) -&amp;gt; Void)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 컴플리션 핸들러는 모두 옵셔널인 세 개의 값을 반환합니다. Swift의 튜플은 곱이니 세 개의 필드의 곱 타입이라고 생각할 수 있습니다. 그럼 대수적으로 적어볼까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// (Data + 1) * (URLResponse + 1) * (Error + 1)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이해하기 어려우니 완전히 풀어보겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// (Data + 1) * (URLResponse + 1) * (Error + 1)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   = Data * URLResponse * Error&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     + Data * URLResponse&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     + URLResponse * Error&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     + Data * Error&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     + Data&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     + URLResponse&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     + Error&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//     + 1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;여기엔 일어날 수 없는 상태에 대한 표현도 존재합니다. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;URLResponse&lt;/code&gt;는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error&lt;/code&gt;와 동시에 존재할 수 없기 때문에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;URLResponse * Error&lt;/code&gt;라는 경우는 생길 수 없는 경우입니다. 같은 이유로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Data * Error&lt;/code&gt;도 불가능한 경우입니다. 모든 값이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;인 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Void&lt;/code&gt;라는 뜻이니 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt;은 얻을 수 있는 값입니다. 그리고 절대 일어날 수 없지만 모든 값이 잘 왔을 때는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Data * URLResponse * Error&lt;/code&gt; 모양의 값을 얻을 수 있을 것입니다.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;strong&gt;바로잡기&lt;/strong&gt;
독자 중 한 분인 &lt;a href=&quot;http://twitter.com/olebegemann&quot;&gt;Ole Begemann&lt;/a&gt;에 의하면, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;URLResponse&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Error&lt;/code&gt;가 동시에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;nil&lt;/code&gt;이 아닌 경우는 존재할 수 있다고 합니다. 그 분이 작성하신 &lt;a href=&quot;https://oleb.net/blog/2018/03/making-illegal-states-unrepresentable/&quot;&gt;블로그 포스트&lt;/a&gt;가 있으니 자세한 내용은 여기서 읽어보시면 좋을 것 같습니다.
그리고 이 부분을 바로잡는 내용은 이 시리즈의 다음 에피소드인 &lt;a href=&quot;https://www.pointfree.co/episodes/ep9-algebraic-data-types-exponents&quot;&gt;대수적으로 풀어보는 타입 체계: 지수편&lt;/a&gt;에서 얘기할 예정입니다.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;이 인터페이스를 그대로 사용하면 결과값이 필요한 경우엔 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;if let&lt;/code&gt;을 사용하고, 반대로 결과값이 필요없다고 생각하는 경우엔 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fatalError&lt;/code&gt;를 두고 절대 호출되지 않기를 희망하는 수밖에 없습니다.&lt;/p&gt;

&lt;p&gt;이번 에피소드에서 얻은 새로운 직관을 사용해서 우리에게 필요한 것을 표현해봅시다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Data * URLResponse + Error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;타입을 사용하면 어떤 모양일까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;Either&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;URLResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Error&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;실제로 Swift 커뮤니티에서는 이미 이러한 종류의 타입인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt;를 채택했습니다.&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Result&amp;lt;(Data, URLResponse), Error&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;그리고 이 경우엔 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Pair&lt;/code&gt; 대신 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Data&lt;/code&gt;와 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;URLResponse&lt;/code&gt;로 이루어진 간단한 튜플을 사용하면 됩니다.&lt;/p&gt;

&lt;p&gt;컴플리션 콜백에서 적절한 타입을 사용한다면 컴파일 시간에 허용됐지만 실제로 일어날 수 없는 상태를 제거할 수 있게 되고, 콜백의 로직도 아주 간단해질 것입니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt; 타입에 대해 조금 더 알아보겠습니다. 사용하고 있는 API가 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt; 타입을 반환하지만 이 연산은 절대 실패하지 않는다면 어떨까요? 그런 경우 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt;의 에러 타입을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Never&lt;/code&gt;로 만들 수 있을 것입니다!&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Result&amp;lt;A, Never&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이제 우리는 타입만 보고도 에러가 발생할 수 없는 API라는 것을 알게되었습니다.&lt;/p&gt;

&lt;p&gt;그렇다면 도중에 취소가 가능한 비동기 API를 다룰 때는 어떨까요? 취소에 대한 경우를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Result&lt;/code&gt;에 어떻게 포함할 수 있을까요?&lt;/p&gt;

&lt;div class=&quot;language-swift highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Result&amp;lt;A, Error&amp;gt;?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;옵셔널로 만들어주면 됩니다!&lt;/p&gt;

&lt;p&gt;대수적 직관은 코드의 복잡성을 해결하고 필요한 타입을 적절하게 사용하는 능력을 더 명확하게 만들어줍니다. 지금까지 보여드린 구조체나 열거형에 대한 예시는 우리가 매일 보는 그것들에 비하면 아주 간단한 편입니다.&lt;/p&gt;

&lt;p&gt;튜플은 무서워하지 않는데 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt;는 무서우시다구요? 그 말은 곱셈은 무섭지 않은데 덧셈은 무섭다라는 말과 같고, “or”는 무서운데 “and”는 무섭지 않다와 같습니다. 개발할 때 곱셈(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*&lt;/code&gt;)과 “and”(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;amp;&amp;amp;&lt;/code&gt;)만 사용하는 사람은 아무도 없습니다. 덧셈(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;)과 “or”(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;||&lt;/code&gt;)도 사용해보세요. 그러면 합 타입, 더 나아가서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Either&lt;/code&gt;가 편해질 것입니다!&lt;/p&gt;

&lt;p&gt;오늘 알아본 내용은 대수적으로 타입을 알아보는 여행의 시작점일 뿐입니다. 오늘 알아본 덧셈과 곱셈을 제외하고도 타입 체계가 대수적인 개념을 어떻게 표현하는지 알아볼 내용이 아주 많습니다. 예를 들면 지수가 있겠네요! 타입의 제곱을 표현하는 방법엔 무엇이 있을까요? 더 말씀드리고 싶지만, 아쉽게도 오늘은 여기까지 입니다.&lt;/p&gt;

&lt;p&gt;그럼 다음 에피소드에서 뵙겠습니다!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;본문에 연습문제와 참고 자료가 있습니다. &lt;a href=&quot;https://www.pointfree.co/episodes/ep4-algebraic-data-types&quot;&gt;여기&lt;/a&gt;에서 확인해주세요!&lt;/p&gt;
</description>
            <pubDate>Sun, 16 Feb 2020 00:00:00 +0000</pubDate>
            <link>https://pilgwon.github.io/post/episode-4-algebraic-data-types</link>
            <guid isPermaLink="true">https://pilgwon.github.io/post/episode-4-algebraic-data-types</guid>
            
            
            <category>Translations</category>
            
        </item>
        
        <item>
            <title>프로젝트에 새로운 서브모듈을 추가하는 방법</title>
            <description>&lt;p&gt;&lt;a href=&quot;https://pilgwon.github.io/post/use-submodules&quot;&gt;지난글&lt;/a&gt;에선 서브모듈을 선택하게 된 계기 및 서브모듈을 적용하는 방법에 대해 알아보았습니다. 오늘은 서브모듈이 적용된 프로젝트를 운영할 때 다른 프레임워크를 추가하는 방법에 대해 알아보겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/how-to-import-modules/bg.jpg&quot; alt=&quot;bg&quot; /&gt;&lt;/p&gt;

&lt;p&gt;이번에 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Animation&lt;/code&gt;이라는 내부 프레임워크가 추가되면서 과정을 순서대로 정리할 기회가 생겨서 이런 글을 쓸 수 있게 되었습니다.&lt;/p&gt;

&lt;p&gt;오늘 글엔 총 10개의 항목이 있으며 서브모듈을 적용하지 않고 외부 라이브러리만 추가하는 목적이라면 6번까지만 따라하시면 됩니다.&lt;/p&gt;

&lt;p&gt;오늘 나올 프로젝트와 프레임워크에 대해 설명드리면 다음과 같습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProjectX&lt;/code&gt;: 개발중인 서비스&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Design&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Core&lt;/code&gt;: 기존에 추가돼있던 프레임워크&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Animation&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProjectX&lt;/code&gt;에 추가하고자 하는 새로운 프레임워크&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;그럼 시작하겠습니다!&lt;/p&gt;

&lt;h3 id=&quot;1-프레임워크-추가하기&quot;&gt;1. 프레임워크 추가하기&lt;/h3&gt;

&lt;p&gt;아래와 같이 추가하고자 하는 프레임워크를 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cartfile&lt;/code&gt;에 추가해주세요.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Riiid
git &quot;git@github.com:riiid/Core-iOS.git&quot; ~&amp;gt; 0.1.0
git &quot;git@github.com:riiid/Design-iOS.git&quot; ~&amp;gt; 0.0.1
git &quot;git@github.com:riiid/Animation-iOS.git&quot; ~&amp;gt; 0.0.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-새로-추가한-프레임워크-빌드하기&quot;&gt;2. 새로 추가한 프레임워크 빌드하기&lt;/h3&gt;

&lt;p&gt;새로 추가한 프레임워크만 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Carthage&lt;/code&gt;를 통해 빌드합니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Carthage update Animation --platform ios --no-use-binaries --cache-builds&lt;/code&gt;&lt;/p&gt;

&lt;h3 id=&quot;3-프로젝트에-프레임워크-추가하기&quot;&gt;3. 프로젝트에 프레임워크 추가하기&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Carthage &amp;gt; Build &amp;gt; iOS&lt;/code&gt; 에 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Animation&lt;/code&gt;을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProjectX&lt;/code&gt; 워크스페이스의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProjectX&lt;/code&gt; 프로젝트 안에 있는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frameworks&lt;/code&gt; 폴더에 넣어줍니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/how-to-import-modules/1.png&quot; alt=&quot;1&quot; /&gt;&lt;/p&gt;

&lt;p&gt;여기서 중요한 점은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProjectX&lt;/code&gt;의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;General&lt;/code&gt;로 가서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frameworks, Libraries, and Embedded Content&lt;/code&gt;를 확인했을 때 추가하고자 하는 프레임워크인 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Animation&lt;/code&gt;이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Do Not Embed&lt;/code&gt; 상태여야 합니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/how-to-import-modules/2.png&quot; alt=&quot;2&quot; /&gt;&lt;/p&gt;

&lt;p&gt;프레임워크를 추가할 때 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frameworks&lt;/code&gt; 폴더가 아닌 여기에 바로 넣는 방법도 있는데요, 그러면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Embed &amp;amp; Sign&lt;/code&gt; 상태로 추가되기 때문에 상태를 직접 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Do Not Embed&lt;/code&gt;로 바꿔줘야 합니다. 그래서 저는 그냥 번거롭지 않게 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Frameworks&lt;/code&gt; 폴더에 넣는 것을 추천드립니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/how-to-import-modules/3.png&quot; alt=&quot;3&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;4-xcfilelist-업데이트&quot;&gt;4. xcfilelist 업데이트&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Carthage&lt;/code&gt;를 쓴다면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Build Phase&lt;/code&gt;에서 사용하려는 프레임워크를 추가해줘야 하는 것은 알고 계실 것입니다.
저희는 이 목록을 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xcfilelist&lt;/code&gt;의 형식으로 관리하고 있습니다.
수동으로 관리한다면 다음과 같이 한 줄을 추가하면 됩니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$(SRCROOT)/Carthage/Build/iOS/Animation.framework
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;하지만 저희는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Carting&lt;/code&gt;이라는 도구를 사용해서 자동으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xcfilelist&lt;/code&gt;를 생성해서 사용합니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Carting update&lt;/code&gt; 명령어를 실행한 후 다음과 같이 나오면 성공입니다. 새로운 프레임워크를 추가했는데 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xcfilelist&lt;/code&gt;가 업데이트되지 않으면 분명 문제가 있는 것이니 확인해주셔야 합니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/how-to-import-modules/4.png&quot; alt=&quot;4&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;5-romefile-업데이트&quot;&gt;5. Romefile 업데이트&lt;/h3&gt;

&lt;p&gt;지난 글(&lt;a href=&quot;https://pilgwon.github.io/post/cache-carthage-builds-with-rome&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://pilgwon.github.io/post/better-rome-usage&quot;&gt;2&lt;/a&gt;)을 통해서 아실 수도 있지만, 저희는 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Carthage&lt;/code&gt; 의존성을 쉽고 빠르게 관리하기 위해서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Rome&lt;/code&gt;를 사용합니다.&lt;/p&gt;

&lt;p&gt;수정해야 하는 부분은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Romefile&lt;/code&gt;의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;repositoryMap&lt;/code&gt;인데요, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;repositoryMap&lt;/code&gt;은 코드 저장소 이름과 실제 프레임워크의 이름이 다른 경우 이를 연결해주기 위한 지도라고 생각하시면 됩니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Animation&lt;/code&gt;을 예로 들면 저장소 이름은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Animation-iOS&lt;/code&gt;이고 실제 프레임워크의 이름은 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Animation&lt;/code&gt;이니 다음과 같이 기존 틀에 맞게 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Romefile&lt;/code&gt;에 추가해주겠습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/how-to-import-modules/5.png&quot; alt=&quot;5&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;6-의존성-업로드하기&quot;&gt;6. 의존성 업로드하기&lt;/h3&gt;

&lt;p&gt;여기까지 잘 마무리됐다면 외부 라이브러리를 사용할 준비는 끝났습니다. 마지막으로 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fastlane upload_dependency&lt;/code&gt; 명령어를 사용해서 의존성을 S3에 올립시다!&lt;/p&gt;

&lt;h2 id=&quot;내부-프레임워크를-서브모듈로-추가하는-방법&quot;&gt;내부 프레임워크를 서브모듈로 추가하는 방법&lt;/h2&gt;

&lt;p&gt;시작하면서 말씀드렸듯이 6번까지는 내부 프레임워크와 외부 라이브러리 추가할 때 공통으로 적용되는 부분이었고, 지금부터 말씀드릴 7번부터 10번은 내부 모듈의 서브모듈로 추가하는 방법입니다.&lt;/p&gt;

&lt;h3 id=&quot;7-fastfile-업데이트하기&quot;&gt;7. Fastfile 업데이트하기&lt;/h3&gt;

&lt;p&gt;서브모듈을 추가하기 위해선 이것저것 바꿔야하는 설정이 많은데, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fastfile&lt;/code&gt;에 lane이 생성돼있으니 조금만 건드리면 됩니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fastfile&lt;/code&gt;의 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;update_submodules&lt;/code&gt; lane으로 이동하겠습니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lane :update_submodules do
	carthage(
	  command: &quot;update&quot;,
	  dependencies: [&quot;Core&quot;, &quot;Design&quot;],
	  use_submodules: true,
	  use_binaries: false,
	  platform: &quot;iOS&quot;,
	  no_build: true
	)
end
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;여기에 추가하고자 하는 서브모듈의 이름을 추가하면 됩니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;...
dependencies: [&quot;Animation&quot;, &quot;Core&quot;, &quot;Design&quot;],
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;h3 id=&quot;8-스크립트-업데이트하기&quot;&gt;8. 스크립트 업데이트하기&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fastlane update_submodules&lt;/code&gt; 명령어는 우리가 직접 호출하는 것은 아니고 보통은 다른 스크립트에서 알아서 실행시킵니다.&lt;/p&gt;

&lt;p&gt;저희는 새로운 프로젝트가 생기면 항상 두 개의 스크립트를 기본적으로 만듭니다. 하나는 iOS 프로젝트를 아예 처음부터 설정해야하는 사람을 위한 스크립트이고, 나머지 하나는 다른 iOS 프로젝트는 써봐서 기본적인 환경 설정은 끝난 사람을 위한 스크립트입니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;#!/bin/bash

GREEN='\033[0;32m'
WHITE='\033[0m'

echo -e &quot;${GREEN}Upgrade to Submodules${WHITE}&quot;

echo -e &quot;${GREEN}Download Dependency with fastlane${WHITE}&quot;
fastlane download_dependency

echo -e &quot;${GREEN}Update Submodules with fastlane${WHITE}&quot;
fastlane update_submodules

echo -e &quot;${GREEN}Welcome to ProjectX 🎉${WHITE}&quot;
open ProjectX.xcworkspace
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;스크립트에도 적혀있듯이 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fastlane update_submodules&lt;/code&gt; 명령어는 위와 같은 스크립트에서 알아서 돌려주기 때문에 저희는 이 통합 스크립트만 실행시키면 됩니다.&lt;/p&gt;

&lt;h3 id=&quot;9-gitmodules-확인하기&quot;&gt;9. gitmodules 확인하기&lt;/h3&gt;

&lt;p&gt;스크립트를 돌려보면 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitmodules&lt;/code&gt; 파일에 변화가 생긴 것을 확인하실 수 있습니다.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[submodule &quot;Carthage/Checkouts/SnapKit&quot;]
	path = Carthage/Checkouts/SnapKit
	url = https://github.com/SnapKit/SnapKit.git
[submodule &quot;Carthage/Checkouts/RxSwift&quot;]
	path = Carthage/Checkouts/RxSwift
	url = https://github.com/ReactiveX/RxSwift.git
[submodule &quot;Carthage/Checkouts/core-ios&quot;]
	path = Carthage/Checkouts/core-ios
	url = https://github.com/riiid/core-ios.git
[submodule &quot;Carthage/Checkouts/design-ios&quot;]
	path = Carthage/Checkouts/design-ios
	url = https://github.com/riiid/design-ios.git
[submodule &quot;Carthage/Checkouts/animation-ios&quot;]
	path = Carthage/Checkouts/animation-ios
	url = https://github.com/riiid/animation-ios.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;이 상황에서 서브모듈이 잘 추가됐는지 확인하는 가장 쉬운 방법은 바로 GUI 도구를 여는 것입니다.&lt;/p&gt;

&lt;p&gt;아래는 GitKraken에서 본 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProjectX&lt;/code&gt;의 서브모듈 목록인데요, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Animation&lt;/code&gt;이 잘 추가된 것을 확인하실 수 있습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/how-to-import-modules/6.png&quot; alt=&quot;6&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;10-기존-워크스페이스에-프로젝트-추가하기&quot;&gt;10. 기존 워크스페이스에 프로젝트 추가하기&lt;/h3&gt;

&lt;p&gt;이제 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProjectX&lt;/code&gt; 워크스페이스에서 자유롭게 서브모듈을 수정할 수 있도록 원하는 서브모듈을 추가해줍니다.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Carthage &amp;gt; Checkouts&lt;/code&gt; 폴더로 가서 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Animation&lt;/code&gt; 프로젝트를 워크스페이스에 추가해줍니다.&lt;/p&gt;

&lt;p&gt;Animation 워크스페이스는 데모 프로젝트가 추가된거라 굳이 워크스페이스까지 추가할 필요가 없습니다.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/how-to-import-modules/add.gif&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;마치며&quot;&gt;마치며&lt;/h2&gt;

&lt;p&gt;오늘은 서브모듈이 적용된 프로젝트에 새로운 프레임워크를 추가하는 방법에 대해서 알아보았습니다.&lt;/p&gt;

&lt;p&gt;서브모듈을 추가하는 것은 그렇게 어려운 일은 아닙니다. 하지만 자주 있는 일이 아니기 때문에 잘 까먹을 수 있기 때문에 이런 글을 쓰게 되었습니다.&lt;/p&gt;

&lt;p&gt;그럼 마지막으로 어떤 파일이 바뀌었는지 확인해볼까요?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/how-to-import-modules/7.png&quot; alt=&quot;7&quot; /&gt;&lt;/p&gt;

&lt;p&gt;위의 내용과 더불어, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xcfilelist&lt;/code&gt;의 변경도 있으니 각자 어떤 의미인지 한 번 정리해보겠습니다.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.gitmodules&lt;/code&gt;: 새로운 프레임워크가 서브모듈로 프로젝트에 추가됐다.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cartfile&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Cartfile.resolved&lt;/code&gt;: 새로운 프레임워크가 잘 빌드됐다.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Carthage/Checkouts/Animation-iOS&lt;/code&gt;: 서브모듈로 추가할 프레임워크가 잘 체크아웃됐다.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Fastfile&lt;/code&gt;: 프레임워크를 서브모듈 용도로 체크아웃해주는 코드가 잘 수정됐다.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Romefile&lt;/code&gt;: 의존성이 S3에 올바른 키로 잘 저장된다.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contents.xcworkspacedata&lt;/code&gt;: 새로운 프레임워크의 프로젝트가 워크스페이스에 잘 추가됐다.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;xcfilelist&lt;/code&gt;: 프로젝트에서 사용할 프레임워크를 어디서 불러올지 정하는 path가 잘 지정됐다.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;오늘 글은 여기까지입니다!&lt;/p&gt;

&lt;p&gt;읽어주셔서 감사합니다. 다음 글로 찾아뵙겠습니다 :)&lt;/p&gt;
</description>
            <pubDate>Wed, 12 Feb 2020 00:00:00 +0000</pubDate>
            <link>https://pilgwon.github.io/post/how-to-import-modules-in-riiid</link>
            <guid isPermaLink="true">https://pilgwon.github.io/post/how-to-import-modules-in-riiid</guid>
            
            
            <category>Posts</category>
            
        </item>
        
    </channel>
</rss>
