<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>saebyuck_choom</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Thu, 28 Jul 2022 11:59:03 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>saebyuck_choom</title>
            <url>https://images.velog.io/images/dawn_dancer/profile/0f1fb3e0-eb1c-403e-b1f9-3c50000fad49/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. saebyuck_choom. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dawn_dancer" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[iOS]Coordinator Pattern?]]></title>
            <link>https://velog.io/@dawn_dancer/Coordinator-Pattern</link>
            <guid>https://velog.io/@dawn_dancer/Coordinator-Pattern</guid>
            <pubDate>Thu, 28 Jul 2022 11:59:03 GMT</pubDate>
            <description><![CDATA[<h2 id="코디네이터-패턴의-필요성">코디네이터 패턴의 필요성</h2>
<p>MVC든 MVVM이든, 비즈니스 로직과 flow logic이 혼재되어있는 문제가 있다. </p>
<p><strong>flow logic이 특정 뷰(혹은 뷰컨)에 속하면 안되는 이유는 무엇일까?</strong></p>
<ul>
<li>View가 알 필요 없는 다음 flow를 인식하게 되며</li>
<li>자신과 관계없는 View의 타입을 알아야 하며 초기화 책임까지 갖게 된다.</li>
<li>또한, 자신의 논리적 부모인 navigationController에게 메세지를 보내게 된다.</li>
<li>이러한 flow 로직들이 여러 뷰컨트롤러에 산재되어 있다.</li>
</ul>
<p>위와 같은 문제를 해결하려면 flow 로직이 뷰/뷰컨 객체로부터 분리되어야 한다. </p>
<p>이러한 필요성에 따라 모든 ViewController를 모아 관리하는 높은 수준의 객체(Coordinator)를 두어 flow logic을 담당하도록 하는 것이 Coordinator Pattern이다.</p>
<blockquote>
<p>Coordinator 패턴은 KHANLOU의 <a href="https://khanlou.com/2015/01/the-coordinator/">The Coordinator</a> 포스팅에서 처음 제안되었다고 한다.</p>
</blockquote>
<p>AppDelegate 혹은 SceneDelegate와 같은 엔트리포인트는 앱의 flow를 관장하는 App(Scene)Coordinator를 유지하며, 모든 Coordinator는 하위 Coordinator(들)를 소유한다.</p>
<p>childCoordinator(들)를 부모 coordinator가 소유하는 이유는, childCoordinator들의 사용이 완전히 끝나기 전까지 메모리에서 할당 해제되지 않도록 보장하기 위함이다.</p>
<h2 id="코디네이터의-사용이-가져오는-효과들">코디네이터의 사용이 가져오는 효과들</h2>
<h3 id="1-각-뷰-컨트롤러의-격리">1. 각 뷰 컨트롤러의 격리</h3>
<p>뷰 컨트롤러는 데이터를 표시하는 방법 외에는 아무것도 모릅니다. 어떤 일이 발생할 때마다 대리인에게 알리지만 물론 대리인이 누구인지는 모릅니다.
한 번에 두 개의 흐름이 필요한 경우 뷰 컨트롤러 전체에 많은 조건문을 붙이는 대신 전체 코디네이터 개체를 교체할 수 있습니다.
흐름이 작동하는 방식을 이해하고 싶다면 모든 코드가 한 곳에 있기 때문에 매우 쉽습니다.</p>
<h3 id="2-이제-뷰-컨트롤러를-재사용할-수-있습니다">2. 이제 뷰 컨트롤러를 재사용할 수 있습니다.</h3>
<p>그들은 어떤 컨텍스트에서 표시될 것인지 또는 버튼이 무엇을 위해 사용될 것인지에 대해 아무 것도 가정하지 않습니다. 논리를 끌어들이지 않고도 보기 좋게 사용하고 재사용할 수 있습니다.
앱의 iPad 버전을 작성하는 경우 교체해야 하는 유일한 것은 코디네이터이며 모든  컨트롤러를 재사용할 수 있습니다.</p>
<h3 id="3-이제-앱의-모든-작업과-하위-작업에-전용-캡슐화-방법이-있습니다">3. 이제 앱의 모든 작업과 하위 작업에 전용 캡슐화 방법이 있습니다.</h3>
<p>작업이 여러 뷰 컨트롤러에서 작동하더라도 캡슐화됩니다. iPad 버전에서 이러한 하위 작업 중 일부는 재사용하지만 나머지는 재사용하지 않는 경우 해당 하위 작업만 사용하기가 정말 쉽습니다.</p>
<h3 id="4-코디네이터는-뷰-바인딩을-사이드-이펙트와-분리합니다">4. 코디네이터는 뷰 바인딩을 사이드-이펙트와 분리합니다.</h3>
<p>뷰 컨트롤러를 present할 때 뷰 컨트롤러가 데이터를 엉망으로 만들지 다시 걱정할 필요가 없습니다. 읽기 및 표시만 할 수 있으며 데이터를 쓰거나 손상시키지 않습니다. </p>
<h3 id="5-코디네이터는-완전히-제어할-수-있는-개체입니다">5. 코디네이터는 완전히 제어할 수 있는 개체입니다.</h3>
<p>당신은 작업을 위해 -viewDidLoad의 호출을 기다리지 않고도 뷰를 완전히 통제할 수 있습니다. UIViewController당신이 이해할 수 없는 마법을 부리는 슈퍼클래스의 보이지 않는 코드 가 없습니다. 이 모델을 뒤집으면 무슨 일이 일어나고 있는지 훨씬 더 쉽게 이해할 수 있습니다. 앱의 동작은 완전히 투명하며 UIKit이제는 사용하고 싶을 때 호출하는 라이브러리일 뿐입니다.</p>
<p>자료 출처: KHANLOU - <a href="https://khanlou.com/2015/01/the-coordinator/">The Coordinator</a>, <a href="https://khanlou.com/2015/10/coordinators-redux/">Coordinators Redux</a></p>
<p>참고: <a href="https://zeddios.medium.com/coordinator-pattern-bf4a1bc46930">Coordinator Pattern. Coordinator의 시작부터 간단한 사용까지 | by Zedd | Medium</a></p>
<h2 id="생각">생각</h2>
<p>Coordinator Pattern으로 앱의 flow를 관리하면 앱의 흐름을 follow하기 위해서 우리는 더이상 뷰컨트롤러나 뷰모델을 구석구석 찾을 필요가 없다. Flow에 관한 모든 코드는 부모-자식coordinator 객체 트리에서 찾을 수 있을 것이며, ViewController들은 뼈대를 이루는 Coordinator 트리의 부수적인 요소가 될 뿐, flow에 영향을 미치지 않게 된다. Zedd님이 포스팅 말미에 언급하신 것처럼, Ribs로 이행하기 이전의 중간단계처럼 느껴지기도 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] SwiftUI - @State 언제 사용할까?]]></title>
            <link>https://velog.io/@dawn_dancer/TIL-SwiftUI-State-%EC%96%B8%EC%A0%9C-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@dawn_dancer/TIL-SwiftUI-State-%EC%96%B8%EC%A0%9C-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Thu, 21 Jul 2022 00:59:14 GMT</pubDate>
            <description><![CDATA[<h3 id="언제-사용할까">언제 사용할까?</h3>
<p>상태값이 있어야 할 곳은 뷰가 아닌 모델이다.
하지만, 기획에 따라 뷰에 일시적으로 상태값이 머무를 수밖에 없는 경우가 있다.</p>
<p>예컨데, 텍스트를 입력한 후 완료 버튼을 눌러야 진행되는 기능이라면, 완료 버튼을 누르기 전까지의 텍스트값은 뷰가 갖고있을 수밖에 없다.</p>
<p>이러한 경우에만 한정적으로 사용하는 것이 @State 이다.</p>
<h3 id="state">@State</h3>
<p>@State 프로퍼티는 항상 private하게 선언해야 하고, (어차피 해당 뷰에서만 접근 가능하며, 해당 뷰에만 관련된 프로퍼티이다)
이는 Heap 영역에 할당된다.
struct인 View가 갈아끼워진다고 해도, 새롭게 대체된 View가 해당 Heap영역의 @State 인스턴스를 가리키게(point) 된다. (해제 후 재할당되는 것이 아니라는 뜻이다)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Swift] ARC - saebyuck_choom]]></title>
            <link>https://velog.io/@dawn_dancer/Swift-ARC-saebyuckchoom</link>
            <guid>https://velog.io/@dawn_dancer/Swift-ARC-saebyuckchoom</guid>
            <pubDate>Sun, 19 Jun 2022 10:50:29 GMT</pubDate>
            <description><![CDATA[<p><a href="https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html">Automatic Reference Counting</a></p>
<p>ARC로 인해 스위프트에서는 메모리에 대한 특별한 관리 없이도 &quot;그냥 작동하는&quot; 경우가 대부분이다. ARC는 인스턴스들이 더이상 사용되지 않을 때 자동으로 메모리를 비워준다.</p>
<p>하지만, 몇몇 경우에 ARC는 메모리를 관리하기 위해서 코드에 대한 어떤 정보를 필요로 한다.</p>
<p>*레퍼런스 카운팅은 클래스의 인스턴스에만 적용되는 개념이다 - 열거형 및 구조체는 값 타입이므로.</p>
<pre><code class="language-swift">class Person {
    let name: String
    init(name: String) {
        self.name = name
        print(&quot;\(name) is being initialized&quot;)
    }
    deinit {
        print(&quot;\(name) is being deinitialized&quot;)
    }
}</code></pre>
<pre><code class="language-swift">var reference1: Person?
var reference2: Person?
var reference3: Person?</code></pre>
<p><code>var reference: Person?</code> 와 같이 옵셔널로 어떤 인스턴스를 만들면 초깃값은 nil이며, <code>Person</code>클래스를 참조하지 않는다. 이 상태에서, 아직 인스턴스는 initialize되지 않음.</p>
<pre><code class="language-swift">reference1 = Person(name: &quot;John Appleseed&quot;)
// Prints &quot;John Appleseed is being initialized&quot;</code></pre>
<p>이 상태일 때,  <code>reference1</code> → <code>Person</code> 인스턴스  이렇게 <code>강한 참조</code> 가 생긴다.</p>
<p>최소 하나의 <code>강한 참조</code> 가 있으므로, ARC가 이제 메모리상에 Person이 유지되며 해제되지 않음을 보장해준다.</p>
<pre><code class="language-swift">reference2 = reference1
reference3 = reference1</code></pre>
<p>이러면 <code>Person</code> 인스턴스에 대한 총 3개의 <code>강한 참조</code>가 있는 상태이다.</p>
<pre><code class="language-swift">reference1 = nil
reference2 = nil</code></pre>
<p>이렇게 셋 중 두개의 강한 참조를 없애도, 아직 하나가 남았기에 <code>Person</code> 인스턴스는 아직 메모리에서 해제되지 않는다.</p>
<pre><code class="language-swift">reference3 = nil
// Prints &quot;John Appleseed is being deinitialized&quot;</code></pre>
<p>이렇게 마지막 <code>강한 참조</code> 관계까지 없애주면 더이상 <code>Person</code> 인스턴스가 사용되지 않는 상태이기에 ARC가 <code>Person</code> 인스턴스를 메모리에서 해제한 것을 확인할 수 있다.</p>
<hr>
<p>Swift에서 사용되는 메모리 관리 방식인 ARC는 흔히 Garbage Collector 와 비교되는 개념이다.</p>
<p>ARC는 컴파일시 컴파일러가 코드의 요소요소에 적절히 메모리 해제 코드를 끼워넣어 주는 것이고,</p>
<p>GC는 런타임시 사용되지 않는 인스턴스가 있는지 탐색하여 해제해준다.</p>
<p>ARC는 메모리가 언제 해제될지에 대한 <code>규칙</code> 이다. 그 규칙에 따라 컴파일시 메모리 해제 시점이 정해지는 것.</p>
<p>그렇기에 <strong>규칙을 이해하고 코드를 작성</strong>할 필요가 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[iOS] Rx-MVVM의 올바른 사용법 - saebyuck_choom]]></title>
            <link>https://velog.io/@dawn_dancer/iOS-Rx-MVVM%EC%9D%98-%EC%98%AC%EB%B0%94%EB%A5%B8-%EC%82%AC%EC%9A%A9%EB%B2%95-saebyuckchoom</link>
            <guid>https://velog.io/@dawn_dancer/iOS-Rx-MVVM%EC%9D%98-%EC%98%AC%EB%B0%94%EB%A5%B8-%EC%82%AC%EC%9A%A9%EB%B2%95-saebyuckchoom</guid>
            <pubDate>Sun, 19 Jun 2022 10:35:23 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>&quot;MVVM이 좋은 것도 알겠고, Observable과 Operator들이 어떤 기능을 하는지는 알겠는데, 그래서 ViewController와 ViewModel을 어떻게 작성해야 하는거지?&quot;</strong></p>
</blockquote>
<p>MVC에서 이제 막 MVVM으로 넘어와 RxSwift를 사용해 보시는 많은 분들이 어려워하시는 부분일 거에요. 사실 이 부분은 <strong>MVVM의 단점</strong>이기도 한데요, 정형화된 패턴이 없기에 개발자들 간에도 모두 스타일이 다르다는 것이죠. 그만큼 정답이 없는 문제이기도 합니다.</p>
<p>저도 공부를 하는 과정에서 많은 혼란을 겪었고, 처음에 참고했던 코드가 나중에는 그리 좋지 않은 예시였다는 것을 알게 되는 등, 시행착오를 많이 겪었어요. </p>
<p>그 과정에서 깨달았던 포인트를 몇 가지 말씀드리겠습니다.</p>
<h2 id="1-viewmodel-viewcontroller에-있어야-하는-코드는">1. ViewModel, ViewController에 있어야 하는 코드는?</h2>
<h3 id="--viewcontroller">- ViewController</h3>
<ul>
<li>프로퍼티로 viewModel을 소유</li>
<li><strong>binding 함수</strong>: <code>self.viewModel.transform(_:)</code>메서드를 사용하여 뷰의 input 스트림을 매개변수로 넘기고, 반환값인 Output 스트림을 뷰에 적절히 binding</li>
<li>뷰 레이아웃 관련 코드</li>
</ul>
<h3 id="--viewmodel">- ViewModel</h3>
<ul>
<li>프로퍼티로 비즈니스 로직을 담당하는 Model 객체(Usecase)를 소유</li>
<li><strong>transform 함수</strong>: Input 스트림을 받아서 Model을 통해 비즈니스 로직을 처리한 후, Operator를 통해 적절히 가공하여 반환</li>
<li>(필요시) 각종 뷰의 State를 저장하는 Subject 프로퍼티</li>
</ul>
<h2 id="2-input---output-모델링-transform_">2. Input - Output 모델링, transform(_:)</h2>
<p>MVVM에 정형화된 문법은 없지만, 최소한 <code>Input - Output 모델링</code>을 구현한 코드가 개인적으로 읽기 좋았고, 제가 작성할 때에도 머릿속으로 흐름을 이해하기 좋았어요.</p>
<pre><code class="language-swift">class MovieDetailViewModel {

    private let movieSearchService: MovieSearchService // 비즈니스 로직을 담당하는 객체(API Call)

    init(movieSearchService: MovieSearchService) {
        self.movieSearchService = movieSearchService
    }

    struct Input { // View에서 발생할 Input 이벤트(Stream)들
        let trigger: Observable&lt;Void&gt; // viewWillAppear와 같은 trigger event
    }
    struct Output { // NView에 반영시킬 Output Stream들
        let resultTitleText: Observable&lt;String&gt; // UILabel 등에 바인딩할 데이터 Stream
    }

    func transform(input: Input) -&gt; Output { // 뷰의 Input을 받아 Output으로 변형하는 메서드
        let resultTitleText = input.trigger
            .flatMap { _ in
                self.movieSearchService.fetchMovieDetail()
            }
            .map { $0.title }

        return Output(resultTitleText: resultTitleText)
    }
}
</code></pre>
<p>간단한 예시 코드를 작성해 보았어요. 지금은 Input과 Output이 하나씩이지만, 여러 이벤트가 들어와 가공하고, 비즈니스 로직을 사용하고, 스트림 간의 합성 및 분리를 거치는 등 복잡한 작업을 한다면, 이렇게 Input과 Output을 정리해 놓는 것이 쓰는 사람도 읽는 사람도 명확하게 의도를 알 수 있게 됩니다.</p>
<h2 id="3-하나의-stream---구독은-한-번-만">3. 하나의 Stream -&gt; 구독은 한 번 만!!</h2>
<p><img src="https://velog.velcdn.com/images/dawn_dancer/post/735112c7-38dd-44f4-b318-937a71a68e3e/image.jpeg" alt=""></p>
<p>이 내용을 설명하기 위해 만들어본 개념도인데요, 
뷰에서 시작된 <strong>Stream</strong>(사람 손 모양의 User Input)<strong>이 <code>subscribe</code>되는 곳이 어디</strong>인지 보이시나요? 실선을 쭉쭉 따라가다 보면, <strong>다시 뷰로 돌아와서야 <code>subscribe</code></strong>되는 것을 확인할 수 있습니다!</p>
<p>처음 Rx-MVVM을 구현한 코드에서 가장 많이 보이는 실수가 &quot;모든 곳에서 subscribe&quot;하는 것이었어요. 뷰에서 뷰모델로 이벤트 전달할 때 subscribe, 뷰모델에서 비즈니스 로직을 사용할 때 또 subscribe...
그렇게 하나의 스트림이 중간에 뚝 뚝 끊어지는 모습을 많이 보았는데요. 이는 전혀 Rx답지 못한 방식이고, MVVM의 개념에도 맞지 않아요.</p>
<p><strong><em><code>subscribe</code>는 Stream의 종착점인 <code>ViewController</code>에서, 한 번만 이루어지는 것이 좋습니다!</em></strong></p>
<p>모든 스트림은 최종적으로 뷰의 변경을 일으키게 되지요. 그 종착점까지 가는 과정에서는 subscribe하지 않고도, Operator를 통해 충분히 데이터를 가공하거나 Stream을 합성 및 분리, 비즈니스 로직을 사용한 사이드이펙트를 반영할 수도 있습니다.</p>
<h2 id="추천하고-싶은-예시-repo">추천하고 싶은 예시 Repo</h2>
<blockquote>
<p><a href="https://github.com/sergdort/CleanArchitectureRxSwift">github.com/sergdort/CleanArchitectureRxSwift</a></p>
</blockquote>
<p>저는 위 코드를 보고 Rx-MVVM과 Clean Architecture를 이해하는데 큰 도움을 받았습니다! 보면 볼 수록 모범적으로 잘 작성된 것 같아서 교과서로 삼고 있는데, 여러분께도 도움이 많이 되었으면 좋겠어요!</p>
<h2 id="마치며">마치며</h2>
<p>아직 공부하는 입장이기에, 오류나 다른 의견이 있다면 댓글을 통해 알려주시면 정말 감사하겠습니다.
읽어주셔서 고맙습니다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[iOS] MVC에 대한 오해, 그리고 MVP - saebyuck_choom]]></title>
            <link>https://velog.io/@dawn_dancer/iOS-MVC%EC%97%90-%EB%8C%80%ED%95%9C-%EC%98%A4%ED%95%B4-%EA%B7%B8%EB%A6%AC%EA%B3%A0-MVP-saebyuckchoom</link>
            <guid>https://velog.io/@dawn_dancer/iOS-MVC%EC%97%90-%EB%8C%80%ED%95%9C-%EC%98%A4%ED%95%B4-%EA%B7%B8%EB%A6%AC%EA%B3%A0-MVP-saebyuckchoom</guid>
            <pubDate>Tue, 14 Jun 2022 04:19:14 GMT</pubDate>
            <description><![CDATA[<p><br>iOS로 개발 공부를 시작한 많은 사람들은 <strong>MVC 패턴</strong>에 가장 익숙할 것입니다. 
<br></p>
<p>UIKit은 MVC 패턴을 염두하여 만들어졌으며, 우리가 Xcode에서 생성하는 프로젝트 템플릿에는 <code>ViewController</code>가 만들어져 있지요.</p>
<p>이 <code>ViewController</code>에 거의 모든 로직이 담겨있어 몇백 줄이 넘어가는 상황도 자주 겪어 보셨을거에요. </p>
<p>그래서 다른 패턴에 관심을 갖게 되고, MVVM을 사용하기 위해 RxSwift를 공부하게 됩니다.
<br>
<strong>하지만 다른 디자인 패턴으로 넘어가기 이전에, 우리는 MVC에 대해서는 확실히 알고 있을까요?</strong>
<br></p>
<h2 id="cocoa-mvc">Cocoa MVC</h2>
<p>.
<img width="640" alt="title" src="https://velog.velcdn.com/images/dawn_dancer/post/4e20c3bf-a4bf-4cbe-8edb-5e4d6b3cac14/image.png"><a href="https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html">Apple 공식문서</a>의 MVC에 대한 모식도입니다.</p>
<p>이 Cocoa MVC는 사실 <strong>최초의 MVC</strong>와는 다른 패턴입니다. 
전통적인 MVC 패턴은 최초의 객체지향 언어 중 하나인 Smalltalk에서 제시된 디자인 패턴으로, Cocoa MVC와는 달리 Model이 Controller를 거치지 않고 View와 직접 소통합니다.<br><img width="640" alt="title" src="https://velog.velcdn.com/images/dawn_dancer/post/ab450fbe-79d7-4772-9fd6-7cf6fe7d8afe/image.png">1. View에서 User action을 Controller로 전달하면, 
2. 그에 따라 Controller는 (View와) Model을 변경하고, 
3. Model은 자신의 변경을 <strong>View에 알립니다.</strong>
4. View는 Model과 직접 소통하여 Model의 변경을 반영하게 됩니다.
<br>
여기에서 <strong>모델과 뷰의 의존성을 끊고, 분산되었던 뷰의 변경 책임을 Controller에 집중시킨 패턴이 Cocoa MVC</strong>인 것이죠.</p>
<p>Cocoa MVC에서는,</p>
<ol>
<li>뷰에서 User action을 Controller로 전달하면, </li>
<li>그에 따라 Controller는 Model을 변경하고,</li>
<li>Model은 자신의 변경을 <strong>Controller에 알립니다.</strong></li>
<li>Controller는 Model의 변경에 따라 View에 적절한 변경을 적용합니다.<br>
MVC의 문제점을 극복하여 발전시켰다고 볼 수 있지만, 문제는 이 용어가 현재 여러 진영에서 각기 다른 방식으로 쓰이고 있다는 것입니다. 

</li>
</ol>
<p>서로 다른 도메인의 개발자끼리 <strong>&quot;MVC 패턴&quot;</strong> 에 대해 말하면, 모두가 조금씩 다른 그림을 머리속에 그리고 있을지도 모릅니다. 
전통적인 MVC와 iOS, Android, 백엔드에서 사용하는 MVC가 각기 크고작은 차이가 있기 때문이죠.
<br>
역사적으로 MVC 패턴이 대세를 이루었지만, 그 이후에 MVC의 문제점을 해결하기 위해 각 진영에서 수정을 거친 결과 이런 용어의 난립이 일어났다고 해요.
<br><br></p>
<h2 id="cocoa-mvc---mvp">Cocoa MVC? -&gt; MVP!</h2>
<p>.
<img width="300" alt="title" src="https://velog.velcdn.com/images/dawn_dancer/post/78be03ee-fe31-443b-9971-e95d74d6a273/image.png"></p>
<p>익숙하게 들어 본 또 하나의 디자인 패턴, 바로 MVP입니다.
Cocoa MVC의 모식도와 몇몇 용어를 제외하고는 일치하는 모습을 볼 수 있습니다.</p>
<p>사실 그 동안 우리가 MVC라고 부르던 패턴(Cocoa MVC)는 <strong>MVP 패턴</strong>이었다고 봐도 무방할 것입니다.</p>
<p><br><br></p>
<h2 id="맺으며">맺으며</h2>
<p>디자인 패턴 및 아키텍쳐는 더 이해하기 쉽고, 테스터블 하며, 유지보수가 용이한 코드를 작성하기 위해 필수적으로 고민해야 하는 주제인 것 같습니다. iOS 개발 공부를 하더라도, 디자인 패턴과 아키텍쳐는 하나의 프로그래밍 언어에 한정되지 않는 소프트웨어 엔지니어링의 문제이기에, 다른 진영에서 이루어지는 논의도 눈여겨보는 것이 좋을 것 같아요.</p>
<p>이를 위해 MVC에 대한 기본적인 오해를 해소하는데 도움이 되는 글이었으면 좋겠네요 :)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SPM(Swift Package Manager) 사용하기 / RxSwift 설치하기]]></title>
            <link>https://velog.io/@dawn_dancer/SPMSwift-Package-Manager-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-RxSwift-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@dawn_dancer/SPMSwift-Package-Manager-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EC%97%90-RxSwift-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 24 Apr 2022 10:44:09 GMT</pubDate>
            <description><![CDATA[<p>Xcode에서 제공하는 의존성 관리 도구인 Swift Package Manager를 사용하는 방법을 간단히 알아볼게요!</p>
<h3 id="의존성-관리-도구란">의존성 관리 도구란?</h3>
<p>외부 라이브러리를 설치, 삭제, 관리하도록 도와주는 도구입니다.
공개된 유용한 라이브러리 코드를 활용하고 싶은데, 많은 라이브러리들은 지속적으로 유지/보수가 이루어지고 있어요.
그렇다면 내 코드도 수정하고, 오픈소스 코드도 업데이트마다 다시 복붙해야 하는 번거로움이 있을 거에요.
그런 수고를 덜어주고자 사용하는 도구가 의존성 관리 도구입니다.</p>
<p>저희 iOS 개발자가 주로 사용하는 의존성 관리 도구는 <a href="https://cocoapods.org/">CocoaPods</a>, <a href="https://github.com/Carthage/Carthage">Carthage</a>, 그리고 SPM(Swift Package Manager)이 있어요. 
이들 중, 코코아팟과 SPM을 주로 사용하는 추세인데요, 오늘은 사용법이 정말 간단한 SPM 사용 방법을 알아볼게요.</p>
<hr>
<p>이번 포스트에서는, 가장 유명하고 널리 쓰이는 라이브러리 중 하나인 RxSwift를 설치해 볼 거에요!</p>
<h3 id="먼저">먼저,</h3>
<p>Xcode를 켜고 라이브러리를 설치하기 원하는 프로젝트를 열어요. 
<img width="740" src="https://velog.velcdn.com/images/dawn_dancer/post/ff234f28-d8fe-4a67-beab-459b99e438ff/image.png">
상단 탭에서 Add Packages를 선택합니다.
<img width="840" src="https://velog.velcdn.com/images/dawn_dancer/post/27e6f91f-be35-4bba-9c18-6d577197cc5b/image.png">
이런 창이 보이실거에요. 우상단 검색창에 원하는 라이브러리의 이름을 검색하거나, 해당 라이브러리의 url을 붙여 넣으면 자동으로 설치 가능한 패키지를 찾아 줍니다!<code>Add Package</code>를 클릭해 진행해 보면, 
<img width="840" src="https://velog.velcdn.com/images/dawn_dancer/post/fd9d890d-5920-44d4-b96a-f7ee648d8090/image.png">
설치할 수 있는 세부 패키지 목록이 보여요. 필요한 것만 체크 후, <code>Add Package</code> 로 진행해 봅시다.
<img width="340" src="https://velog.velcdn.com/images/dawn_dancer/post/1832a357-cc6d-45f8-b995-286840704fb6/image.png">
전에는 보이지 않던 Package Dependencies라는 항목이 생겼어요. 우리가 설치한 라이브러리의 이름도 보이네요!</p>
<p>벌써 끝난걸까요? 정상적으로 설치되었는지 테스트 해 볼게요!
<img width="340" src="https://velog.velcdn.com/images/dawn_dancer/post/77f94724-db2a-43d3-a164-878b73466a9d/image.png">
<code>RxSwift</code>를 import할 수 있게 되었어요!</p>
]]></description>
        </item>
    </channel>
</rss>