<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>csj.iOS</title>
    <link>https://whtjdwo78.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sat, 9 May 2026 17:01:31 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>성재's</managingEditor>
    <image>
      <title>csj.iOS</title>
      <url>https://tistory1.daumcdn.net/tistory/4844103/attach/3adadd820f9c40a3b8cc993b5b876fc2</url>
      <link>https://whtjdwo78.tistory.com</link>
    </image>
    <item>
      <title>WebSocket</title>
      <link>https://whtjdwo78.tistory.com/35</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Notion 정리 링크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/WebSocket-f46c2d9a192d4e4e842f15ded8c89f0b?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://trusting-turnip-6f9.notion.site/WebSocket-f46c2d9a192d4e4e842f15ded8c89f0b?pvs=4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1722324033526&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;WebSocket | Notion&quot; data-og-description=&quot;WebSocket 이란?&quot; data-og-host=&quot;trusting-turnip-6f9.notion.site&quot; data-og-source-url=&quot;https://trusting-turnip-6f9.notion.site/WebSocket-f46c2d9a192d4e4e842f15ded8c89f0b?pvs=4&quot; data-og-url=&quot;https://trusting-turnip-6f9.notion.site/f46c2d9a192d4e4e842f15ded8c89f0b&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/9Jrd5/hyWG0oBqv0/v2q1hBuEDTqGR7EyCuUGK0/img.png?width=2000&amp;amp;height=1050&amp;amp;face=0_0_2000_1050,https://scrap.kakaocdn.net/dn/bjD3pV/hyWG1gLftX/abDFuFyk5BfLZZs6mGKBpk/img.png?width=2000&amp;amp;height=1050&amp;amp;face=0_0_2000_1050&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/WebSocket-f46c2d9a192d4e4e842f15ded8c89f0b?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://trusting-turnip-6f9.notion.site/WebSocket-f46c2d9a192d4e4e842f15ded8c89f0b?pvs=4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/9Jrd5/hyWG0oBqv0/v2q1hBuEDTqGR7EyCuUGK0/img.png?width=2000&amp;amp;height=1050&amp;amp;face=0_0_2000_1050,https://scrap.kakaocdn.net/dn/bjD3pV/hyWG1gLftX/abDFuFyk5BfLZZs6mGKBpk/img.png?width=2000&amp;amp;height=1050&amp;amp;face=0_0_2000_1050');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;WebSocket | Notion&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;WebSocket 이란?&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;trusting-turnip-6f9.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS Develop</category>
      <category>ios</category>
      <category>Swift</category>
      <category>URLSessionWebSocketTask</category>
      <category>websocket</category>
      <author>성재's</author>
      <guid isPermaLink="true">https://whtjdwo78.tistory.com/35</guid>
      <comments>https://whtjdwo78.tistory.com/35#entry35comment</comments>
      <pubDate>Tue, 30 Jul 2024 16:21:09 +0900</pubDate>
    </item>
    <item>
      <title>ReactorKit</title>
      <link>https://whtjdwo78.tistory.com/34</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Notion 정리 링크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/ReactorKit-73e6c6bffcf448e78910676867d49a97?pvs=4&quot;&gt;https://trusting-turnip-6f9.notion.site/ReactorKit-73e6c6bffcf448e78910676867d49a97?pvs=4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1722323962824&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;ReactorKit | Notion&quot; data-og-description=&quot;ReactorKit&quot; data-og-host=&quot;trusting-turnip-6f9.notion.site&quot; data-og-source-url=&quot;https://trusting-turnip-6f9.notion.site/ReactorKit-73e6c6bffcf448e78910676867d49a97?pvs=4&quot; data-og-url=&quot;https://trusting-turnip-6f9.notion.site/73e6c6bffcf448e78910676867d49a97&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xFmG8/hyWGQffZ1K/xfUCWSIBHkFQ8ikIDJii1K/img.png?width=2000&amp;amp;height=958&amp;amp;face=0_0_2000_958,https://scrap.kakaocdn.net/dn/bdmwT1/hyWGQ0C3uF/MV9j8dfGHkvQIyl1v3kLn0/img.png?width=2000&amp;amp;height=958&amp;amp;face=0_0_2000_958&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/ReactorKit-73e6c6bffcf448e78910676867d49a97?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://trusting-turnip-6f9.notion.site/ReactorKit-73e6c6bffcf448e78910676867d49a97?pvs=4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xFmG8/hyWGQffZ1K/xfUCWSIBHkFQ8ikIDJii1K/img.png?width=2000&amp;amp;height=958&amp;amp;face=0_0_2000_958,https://scrap.kakaocdn.net/dn/bdmwT1/hyWGQ0C3uF/MV9j8dfGHkvQIyl1v3kLn0/img.png?width=2000&amp;amp;height=958&amp;amp;face=0_0_2000_958');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;ReactorKit | Notion&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;ReactorKit&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;trusting-turnip-6f9.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS Develop</category>
      <category>ios</category>
      <category>ReactorKit</category>
      <category>rxswift</category>
      <category>Swift</category>
      <author>성재's</author>
      <guid isPermaLink="true">https://whtjdwo78.tistory.com/34</guid>
      <comments>https://whtjdwo78.tistory.com/34#entry34comment</comments>
      <pubDate>Tue, 30 Jul 2024 16:19:27 +0900</pubDate>
    </item>
    <item>
      <title>FlexLayout &amp;amp; PinLayout</title>
      <link>https://whtjdwo78.tistory.com/33</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Notion 정리 링크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/FlexLayout-PinLayout-d06ad6c9957341cdafb85e6a6e3ebfa7?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://trusting-turnip-6f9.notion.site/FlexLayout-PinLayout-d06ad6c9957341cdafb85e6a6e3ebfa7?pvs=4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1722323787419&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;FlexLayout &amp;amp; PinLayout | Notion&quot; data-og-description=&quot;FlexLayout&quot; data-og-host=&quot;trusting-turnip-6f9.notion.site&quot; data-og-source-url=&quot;https://trusting-turnip-6f9.notion.site/FlexLayout-PinLayout-d06ad6c9957341cdafb85e6a6e3ebfa7?pvs=4&quot; data-og-url=&quot;https://trusting-turnip-6f9.notion.site/d06ad6c9957341cdafb85e6a6e3ebfa7&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/tEdWx/hyWG27NRBf/CJljkDmv07ccsMOhSle1jk/img.png?width=2000&amp;amp;height=1050&amp;amp;face=0_0_2000_1050,https://scrap.kakaocdn.net/dn/chLAkL/hyWGXrUWXf/E9miZ9HuKZbl6BxCZ9fakK/img.png?width=2000&amp;amp;height=1050&amp;amp;face=0_0_2000_1050&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/FlexLayout-PinLayout-d06ad6c9957341cdafb85e6a6e3ebfa7?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://trusting-turnip-6f9.notion.site/FlexLayout-PinLayout-d06ad6c9957341cdafb85e6a6e3ebfa7?pvs=4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/tEdWx/hyWG27NRBf/CJljkDmv07ccsMOhSle1jk/img.png?width=2000&amp;amp;height=1050&amp;amp;face=0_0_2000_1050,https://scrap.kakaocdn.net/dn/chLAkL/hyWGXrUWXf/E9miZ9HuKZbl6BxCZ9fakK/img.png?width=2000&amp;amp;height=1050&amp;amp;face=0_0_2000_1050');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;FlexLayout &amp;amp; PinLayout | Notion&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;FlexLayout&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;trusting-turnip-6f9.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS Develop</category>
      <category>FlexLayout</category>
      <category>ios</category>
      <category>pinlayout</category>
      <category>Swift</category>
      <author>성재's</author>
      <guid isPermaLink="true">https://whtjdwo78.tistory.com/33</guid>
      <comments>https://whtjdwo78.tistory.com/33#entry33comment</comments>
      <pubDate>Tue, 30 Jul 2024 16:16:35 +0900</pubDate>
    </item>
    <item>
      <title>WWDC 2024</title>
      <link>https://whtjdwo78.tistory.com/32</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Notion 정리 링크&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/WWDC-2024-1-95b9002531dd438a8b93be8d20a0467b?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://trusting-turnip-6f9.notion.site/WWDC-2024-1-95b9002531dd438a8b93be8d20a0467b?pvs=4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1722323716049&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;WWDC 2024 (1) | Notion&quot; data-og-description=&quot;New Swift 6&quot; data-og-host=&quot;trusting-turnip-6f9.notion.site&quot; data-og-source-url=&quot;https://trusting-turnip-6f9.notion.site/WWDC-2024-1-95b9002531dd438a8b93be8d20a0467b?pvs=4&quot; data-og-url=&quot;https://trusting-turnip-6f9.notion.site/95b9002531dd438a8b93be8d20a0467b&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bGF3JR/hyWGTbYv3B/fn2U2WkrG6rqZG870e7JSk/img.png?width=2000&amp;amp;height=1125&amp;amp;face=0_0_2000_1125,https://scrap.kakaocdn.net/dn/cb48EX/hyWG3lm5rX/ZvK1qS6nYWDL3xcrI5vdcK/img.png?width=2000&amp;amp;height=1125&amp;amp;face=0_0_2000_1125&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/WWDC-2024-1-95b9002531dd438a8b93be8d20a0467b?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://trusting-turnip-6f9.notion.site/WWDC-2024-1-95b9002531dd438a8b93be8d20a0467b?pvs=4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bGF3JR/hyWGTbYv3B/fn2U2WkrG6rqZG870e7JSk/img.png?width=2000&amp;amp;height=1125&amp;amp;face=0_0_2000_1125,https://scrap.kakaocdn.net/dn/cb48EX/hyWG3lm5rX/ZvK1qS6nYWDL3xcrI5vdcK/img.png?width=2000&amp;amp;height=1125&amp;amp;face=0_0_2000_1125');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;WWDC 2024 (1) | Notion&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;New Swift 6&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;trusting-turnip-6f9.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/WWDC-2024-2-7ea025c3b1764cf28580294351ac8095?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://trusting-turnip-6f9.notion.site/WWDC-2024-2-7ea025c3b1764cf28580294351ac8095?pvs=4&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1722323730493&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;WWDC 2024 (2) | Notion&quot; data-og-description=&quot;목차&quot; data-og-host=&quot;trusting-turnip-6f9.notion.site&quot; data-og-source-url=&quot;https://trusting-turnip-6f9.notion.site/WWDC-2024-2-7ea025c3b1764cf28580294351ac8095?pvs=4&quot; data-og-url=&quot;https://trusting-turnip-6f9.notion.site/7ea025c3b1764cf28580294351ac8095&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/X6osz/hyWGYYEwe7/k8Un21aNHeJNKzDq11Yk5k/img.png?width=2000&amp;amp;height=1142&amp;amp;face=0_0_2000_1142,https://scrap.kakaocdn.net/dn/bN53ZE/hyWGPUVuTE/Dsfnf5S3zwgRoqxDeDLAak/img.png?width=2000&amp;amp;height=1142&amp;amp;face=0_0_2000_1142&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/WWDC-2024-2-7ea025c3b1764cf28580294351ac8095?pvs=4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://trusting-turnip-6f9.notion.site/WWDC-2024-2-7ea025c3b1764cf28580294351ac8095?pvs=4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/X6osz/hyWGYYEwe7/k8Un21aNHeJNKzDq11Yk5k/img.png?width=2000&amp;amp;height=1142&amp;amp;face=0_0_2000_1142,https://scrap.kakaocdn.net/dn/bN53ZE/hyWGPUVuTE/Dsfnf5S3zwgRoqxDeDLAak/img.png?width=2000&amp;amp;height=1142&amp;amp;face=0_0_2000_1142');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;WWDC 2024 (2) | Notion&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;trusting-turnip-6f9.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS Develop</category>
      <category>ios</category>
      <category>Swift</category>
      <category>WWDC</category>
      <category>wwdc2024</category>
      <author>성재's</author>
      <guid isPermaLink="true">https://whtjdwo78.tistory.com/32</guid>
      <comments>https://whtjdwo78.tistory.com/32#entry32comment</comments>
      <pubDate>Tue, 30 Jul 2024 16:15:44 +0900</pubDate>
    </item>
    <item>
      <title>Privacy Manifest</title>
      <link>https://whtjdwo78.tistory.com/31</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Notion 정리 링크&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/Privacy-Manifest-1501c11ae30e417999b1cae3f50c6154&quot;&gt;https://trusting-turnip-6f9.notion.site/Privacy-Manifest-1501c11ae30e417999b1cae3f50c6154&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1722323627084&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Privacy Manifest | Notion&quot; data-og-description=&quot;What?&quot; data-og-host=&quot;trusting-turnip-6f9.notion.site&quot; data-og-source-url=&quot;https://trusting-turnip-6f9.notion.site/Privacy-Manifest-1501c11ae30e417999b1cae3f50c6154&quot; data-og-url=&quot;https://trusting-turnip-6f9.notion.site/1501c11ae30e417999b1cae3f50c6154&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bIM2C5/hyWGOV2vhT/Uwh3gk6fMe6r0vzwOai0xk/img.png?width=2000&amp;amp;height=612&amp;amp;face=0_0_2000_612,https://scrap.kakaocdn.net/dn/cf5qt2/hyWGUopaWC/mATwRmlH9Tm1c008meeO60/img.png?width=2000&amp;amp;height=612&amp;amp;face=0_0_2000_612&quot;&gt;&lt;a href=&quot;https://trusting-turnip-6f9.notion.site/Privacy-Manifest-1501c11ae30e417999b1cae3f50c6154&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://trusting-turnip-6f9.notion.site/Privacy-Manifest-1501c11ae30e417999b1cae3f50c6154&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bIM2C5/hyWGOV2vhT/Uwh3gk6fMe6r0vzwOai0xk/img.png?width=2000&amp;amp;height=612&amp;amp;face=0_0_2000_612,https://scrap.kakaocdn.net/dn/cf5qt2/hyWGUopaWC/mATwRmlH9Tm1c008meeO60/img.png?width=2000&amp;amp;height=612&amp;amp;face=0_0_2000_612');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Privacy Manifest | Notion&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What?&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;trusting-turnip-6f9.notion.site&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS Develop</category>
      <category>ios</category>
      <category>privacymanifest</category>
      <category>Swift</category>
      <author>성재's</author>
      <guid isPermaLink="true">https://whtjdwo78.tistory.com/31</guid>
      <comments>https://whtjdwo78.tistory.com/31#entry31comment</comments>
      <pubDate>Tue, 30 Jul 2024 16:14:32 +0900</pubDate>
    </item>
    <item>
      <title>iOS [Swift] - DispatchGroup</title>
      <link>https://whtjdwo78.tistory.com/30</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;DispatchGroup&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DispatchQueue는 Tread를 Safe하게 관리할 수 있는 도구이다.&lt;/li&gt;
&lt;li&gt;특징&lt;br /&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;DispatchQueue들을 Group으로 묶어서 trailing closure를 할 수 있도록 한다.&lt;/li&gt;
&lt;li&gt;서로 다른 성격의 Queue들을 Group으로 묶어서 사용 가능하다.&lt;/li&gt;
&lt;li&gt;enter와 leave의 위치를 작업 단위로 설정하여 개발자가 원하는 작업의 범위를 지정할 수 있다. 아래 예시는 for문 한 사이클을 1작업으로 두고 enter &amp;amp; leave를 했지만, for문 밖에 enter &amp;amp; leave를 한다면 총 1쌍으로 notify를 보낼 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1683521618626&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let dispatchGroup = DispatchGroup()

func queueTask(number: Int,
            completionHandler: @escaping (String) -&amp;gt; Void) {

  // 여기서 시간이 지연되는 작업이 있어도 끝날 때까지 Wait
//  sleep(2)
  completionHandler(&quot;Number \(number) is Entered.&quot;)
}

for i in 0..&amp;lt;10 {
  dispatchGroup.enter()
  print(&quot;&quot;)
  print(&quot;=========== dispatchGroup.enter(\(i)) ===========&quot;)
  print(&quot;&quot;)
  queueTask(number: i) { text in
    print(text)
    
    dispatchGroup.leave()
    print(&quot;&quot;)
    print(&quot;=========== dispatchGroup.leave(\(i)) ===========&quot;)
    print(&quot;&quot;)
    print(&quot;_________________________________________________&quot;)
    print(&quot;&quot;)
  }
}

dispatchGroup.notify(queue: .main) {
  print(&quot;This is Dispatch Group Notify&quot;)
}


// 출력 결과
/**

=========== dispatchGroup.enter(0) ===========

Number 0 is Entered.

=========== dispatchGroup.leave(0) ===========

_________________________________________________


=========== dispatchGroup.enter(1) ===========

Number 1 is Entered.

=========== dispatchGroup.leave(1) ===========

_________________________________________________

...
...
... 

_________________________________________________


=========== dispatchGroup.enter(9) ===========

Number 9 is Entered.

=========== dispatchGroup.leave(9) ===========

_________________________________________________

This is Dispatch Group Notify

 */&lt;/code&gt;&lt;/pre&gt;</description>
      <category>iOS Develop</category>
      <category>Dispatch</category>
      <category>DispatchGroup</category>
      <category>DispatchGroup.enter</category>
      <category>DispatchGroup.leave</category>
      <category>DispatchQueue</category>
      <category>ios</category>
      <category>Swift</category>
      <category>스위프트</category>
      <author>성재's</author>
      <guid isPermaLink="true">https://whtjdwo78.tistory.com/30</guid>
      <comments>https://whtjdwo78.tistory.com/30#entry30comment</comments>
      <pubDate>Mon, 8 May 2023 13:55:08 +0900</pubDate>
    </item>
    <item>
      <title>iOS [Swift] - Keychain 정리</title>
      <link>https://whtjdwo78.tistory.com/29</link>
      <description>&lt;body&gt;&lt;html&gt;&lt;head&gt;&lt;link href=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.2/styles/atom-one-dark.min.css&quot; rel=&quot;stylesheet&quot;/&gt;
&lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.2/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt;&lt;/head&gt;&lt;/html&gt;&lt;link href=&quot;https://rawcdn.githack.com/ppuep94/n2t/5ef4dc01e9d6336341e9ab95bb71672f9d3a3dc9/assets/css/style2.css&quot; rel=&quot;stylesheet&quot;/&gt;&lt;article class=&quot;page mono Notion&quot; id=&quot;e4538687-68fe-4518-8130-98e7b0088329&quot;&gt;&lt;header&gt;&lt;/header&gt;&lt;div class=&quot;page-body Tistory&quot;&gt;&lt;p class=&quot;&quot; id=&quot;2ef6b023-9ec9-43d4-a01d-0185ab42d47f&quot;&gt;
&lt;/p&gt;&lt;figure class=&quot;block-color-gray_background callout&quot; id=&quot;34cc8e01-900a-4326-958a-13027efeeae8&quot; style=&quot;white-space:pre-wrap;display:flex&quot;&gt;&lt;div style=&quot;font-size:1.5em&quot;&gt;&lt;span class=&quot;icon&quot;&gt; &lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;width:100%&quot;&gt;목차&lt;nav class=&quot;block-color-gray table_of_contents&quot; id=&quot;d216f690-bf71-4ec3-afef-37d06458d1a0&quot;&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#b671b18d-ac0d-4782-9a42-2ce7b71b09dc&quot;&gt;Keychain 개념&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#2bca2d7e-3257-4127-b588-4b66c006464b&quot;&gt;Keychain Item&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#15523a4c-471b-413f-88c6-03d97af98e6a&quot;&gt;Keychain 속성(kSecClass)&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#d3e34092-0945-4e70-a452-1fe6b9cbcca5&quot;&gt;Keychain 사용&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#f07be28f-ed09-44f8-ba85-379fa81278bc&quot;&gt;Keychain Error Codes &lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#ae989478-a308-4da6-9a61-629a827d397e&quot;&gt;Keychain OpenSource&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#fc868601-71d7-4ff7-8e4a-f664ec202c38&quot;&gt;번외 및 마무리&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#86e7e6f1-0ac1-4813-9dd9-e3dd714493eb&quot;&gt;References&lt;/a&gt;&lt;/div&gt;&lt;/nav&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h1 class=&quot;&quot; id=&quot;b671b18d-ac0d-4782-9a42-2ce7b71b09dc&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;Keychain 개념&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;7ebec74a-abf1-4085-9c4f-77b7331a5eda&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Apple에서 공식적으로 제공하고 있는 보안 프레임워크&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;29986151-da21-4d08-9ccc-281ee0b71189&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;암호화된 Data Base&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;0a312948-f664-4301-8f04-f305b73ddf51&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;사용자의 민감한 데이터를 저장&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;680bf067-539f-47db-8182-6c1dbc203b8d&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;UserDefaults는 App이 삭제되면 같이 삭제되지만, Keychain은 그와 반대로 App이 삭제돼도 데이터 유지&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;2dfcd080-0837-4411-9633-7960b88d94e1&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Keychain은 중복된 값을 새로운 값이 자동으로 덮어씌우지 못함. 따라서 항상 기존의 값을 삭제 해주어야 함 &lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;h1 class=&quot;&quot; id=&quot;2bca2d7e-3257-4127-b588-4b66c006464b&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;Keychain Item&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;5ad86b1a-df63-490f-8abb-0abda53fa7df&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Keychain에 데이터를 저장할 때, 데이터를 Wrapping해서 Item형태로 저장&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;815ab9c6-458f-4f47-8113-2699d9537b34&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Data &amp;amp; Attribute 형태 → Item &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;2d535c22-ad2b-44eb-a380-17615f287576&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Attribute를 통해 데이터를 검색 및 접근&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;h1 class=&quot;&quot; id=&quot;15523a4c-471b-413f-88c6-03d97af98e6a&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;Keychain 속성(kSecClass)&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;p class=&quot;&quot; id=&quot;20122abd-01ab-47bb-b477-46fe93565e1e&quot;&gt;  &lt;code&gt;kSecClass&lt;/code&gt; : 저장된 Item이 어떤 정보를 가지고 있는지 나타낸다.&lt;/p&gt;&lt;p class=&quot;&quot; id=&quot;12a83c2f-2f67-46fe-934c-59e18ca34bba&quot;&gt;  &lt;strong&gt;각 암호화 데이터 별로 다른 Attribute를 가진다.&lt;/strong&gt;&lt;/p&gt;&lt;p class=&quot;&quot; id=&quot;704daac4-ab1b-4485-be26-4e30a7172f2c&quot;&gt;  k- 접두어는 [konstant = constant] 이므로 붙는다. &lt;/p&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;2d1a4c62-a59e-40c9-a6cc-320163ba2fcb&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSecClass&lt;strong&gt;Generic&lt;/strong&gt;Password : 일반 암호 항목&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;d47cf543-f459-42a9-bd0a-c956ec2c519e&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSecClass&lt;strong&gt;Internet&lt;/strong&gt;Password : 인터넷 비밀 항목&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;a9510131-bc27-4051-b4c6-b8ffe0929b4d&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSecClass&lt;strong&gt;Certificate&lt;/strong&gt; : 인증서 항목&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;39daefd1-399b-4c17-bb45-8d527f9a23a3&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSecClass&lt;strong&gt;Identity&lt;/strong&gt; : 아이디 항목 &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;b5a74751-89fe-4eaa-82c4-41fd8f7303cb&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSecClass&lt;strong&gt;Key&lt;/strong&gt; : 암호화 키 항목&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;1627114b-d911-4495-a04f-393b12d7a63e&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSecClass : 데이터 종류 지정&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;cfb62a61-0b1e-415e-9eeb-331ff6a18e49&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSec&lt;strong&gt;AttrAccount&lt;/strong&gt; : 데이터 저장하기 위한 Key 입력 [개인키]&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;9f731c6b-2a10-44fc-92f0-29ce017c97b5&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSecAttr&lt;strong&gt;Service&lt;/strong&gt;: 데이터 저장하기 위한 Key 입력 [공개키]&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;1f472d09-6b01-465c-92c5-6bce88a16fa9&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSec&lt;strong&gt;ValueData&lt;/strong&gt; : 저장할 데이터를 Data Type으로 캐스팅, 실제 저장할 값&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;73f1d310-55b6-43a1-a677-1b6aa52b6974&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSec&lt;strong&gt;ReturnAttributes&lt;/strong&gt; : 값이 항목 속성을 반환하는 것에 대한 여부&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;46caf529-3d56-41e4-84e9-163dd50ec10a&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSec&lt;strong&gt;ReturnData&lt;/strong&gt; : 값이 항목 데이터를 반환하는 것에 대한 여부&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;4c389956-eba1-496e-b621-40eeeb0ef4ed&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;kSec&lt;strong&gt;ValueData&lt;/strong&gt; : update할 value&lt;/li&gt;&lt;/ul&gt;&lt;p class=&quot;&quot; id=&quot;a8af6c95-781c-46e3-9f9f-66d9bcf5b154&quot;&gt;〰️ 등 등 더 많은 속성은 &lt;code&gt;&lt;a href=&quot;https://developer.apple.com/documentation/security/keychain_services/keychain_items&quot;&gt;공식 문서&lt;/a&gt;&lt;/code&gt;를 통해 확인할 수 있습니다 〰️&lt;/p&gt;&lt;/div&gt;&lt;h1 class=&quot;&quot; id=&quot;d3e34092-0945-4e70-a452-1fe6b9cbcca5&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;Keychain 사용&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;h2 class=&quot;&quot; id=&quot;489559a1-50e8-4b68-ada0-b9a06bbf037a&quot;&gt;SecItemAdd&lt;/h2&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;f3961eee-22b2-4328-9e23-d45ab4bc59fc&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;SecItemAdd 메소드를 호출하고 Keychain에 Dictionary를 &lt;mark class=&quot;highlight-purple&quot;&gt;&lt;strong&gt;추가&lt;/strong&gt;&lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;47a841e0-ea02-4a42-a38e-dead4fc8d56f&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;결과 값으로 &lt;strong&gt;Bool&lt;/strong&gt; Type 반환됨&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;b44da32f-2d99-424b-a938-7152684b76c1&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;중복된 Key 값으로 추가될 경우에는 이 전 값을 삭제하던가 &lt;strong&gt;updateItem&lt;/strong&gt;해서 업데이트 해준다.&lt;/li&gt;&lt;/ul&gt;&lt;pre class=&quot;code Swift&quot; id=&quot;2be80ab4-55b4-4740-8a03-ec6245c2145d&quot;&gt;&lt;code&gt;func addItem(id: Any, password: Any) -&amp;gt; Bool {
    // Keychain Query 정의
    let addQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
                               kSecAttrAccount: id,
                                 kSecValueData: (password as AnyObject).data(using: String.Encoding.utf8.rawValue) as Any]
    
    let result: Bool = {
      let status = SecItemAdd(addQuery as CFDictionary, nil)
      if status == errSecSuccess {
        return true
      } else if status == errSecDuplicateItem {
        return updateItem(value: pwd, key: id)
      }
      
      print(&quot;addItem Error : \(status.description))&quot;)
      return false
    }()
    
    return result
  }&lt;/code&gt;&lt;/pre&gt;&lt;p class=&quot;&quot; id=&quot;262c0934-fbfc-4a30-83cf-f4da7478b5df&quot;&gt;
&lt;/p&gt;&lt;hr id=&quot;74035d05-c6f2-4c75-aa18-d62d88e6e665&quot;/&gt;&lt;h2 class=&quot;&quot; id=&quot;70c37d77-764c-4aec-acbb-ecbc03e67663&quot;&gt;SecItemCopyMatching&lt;/h2&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;ba72fca7-df79-4cb8-81f1-f8e5fee1561e&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;SecItemCopyMatching 메소드 호출하고 Keychain에 Key값을 &lt;mark class=&quot;highlight-purple&quot;&gt;&lt;strong&gt;조회&lt;/strong&gt;&lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;e04c3bf9-d854-40df-ab7b-7b61f9ca2811&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;결과 값으로는 &lt;strong&gt;원하는 형태로 Data를 캐스팅하여 반환&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre class=&quot;code Swift&quot; id=&quot;9dcd8dde-92e5-48ae-bb05-3645efd12382&quot;&gt;&lt;code&gt;func readItems(key: Any) -&amp;gt; String? {
    let query: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
                            kSecAttrAccount: key,
                       kSecReturnAttributes: true,
                             kSecReturnData: true]
    var item: CFTypeRef?
    let result = SecItemCopyMatching(query as CFDictionary, &amp;amp;item)
    
    if result == errSecSuccess {
      if let existingItem = item as? [String: Any],
         let data = existingItem[kSecValueData as String] as? Data,
         let password = String(data: data, encoding: .utf8) {
        return password
      }
    }
    
    print(&quot;readItems Error : \(result.description)&quot;)
    return nil
  }&lt;/code&gt;&lt;/pre&gt;&lt;p class=&quot;&quot; id=&quot;acb788e3-4659-48bc-adb5-adbc6e769b1a&quot;&gt;
&lt;/p&gt;&lt;hr id=&quot;1025f3ec-cd0b-4629-b193-dcca9321a673&quot;/&gt;&lt;h2 class=&quot;&quot; id=&quot;f8c1d1e6-6598-426d-a8d9-a924293c1ca7&quot;&gt;SecItemUpdate&lt;/h2&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;5e395914-b508-469f-8525-916fc2e55a35&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;SecItemUpdate 메소드 호출하고 &lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;update&lt;/mark&gt;&lt;/strong&gt;된 결과 값을 반환&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;a9ef8850-1bd5-4596-b516-a5d97b7538cf&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;update할 상황은 Key값이 동일한 상태에서 Value를 최신화 시켜주는 것&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;affe602e-6c58-4f8f-bbed-d71ea4a39170&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;따라서, &lt;strong&gt;직전의 Keychain Query&lt;/strong&gt; 정보를 Dictionary 형태로 담아주고 &lt;strong&gt;Update할 Query Dictionary&lt;/strong&gt;와 함께 SecItemUpdate에 전달&lt;/li&gt;&lt;/ul&gt;&lt;pre class=&quot;code Swift&quot; id=&quot;b9f90aea-d03d-4b78-ba9a-19ae8350e53f&quot;&gt;&lt;code&gt;func updateItem(value: Any, key: Any) -&amp;gt; Bool {
    let previousQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
                                    kSecAttrAccount: key]
    let updateQuery: [CFString: Any] = [kSecValueData: (value as AnyObject).data(using: String.Encoding.utf8.rawValue) as Any]
    
    let result: Bool = {
      let status = SecItemUpdate(previousQuery as CFDictionary, updateQuery as CFDictionary)
      if status == errSecSuccess { return true }
      
      print(&quot;updateItem Error : \(status.description)&quot;)
      return false
    }()
    
    return result
  }&lt;/code&gt;&lt;/pre&gt;&lt;p class=&quot;&quot; id=&quot;4c9d7bd0-a7e4-4227-9845-8e19e0c2aafc&quot;&gt;
&lt;/p&gt;&lt;hr id=&quot;57e577a1-0e25-4a0c-8460-ef63fc4f4a7f&quot;/&gt;&lt;h2 class=&quot;&quot; id=&quot;74ee5594-03a0-411b-a2fb-99f55dfe15e1&quot;&gt;SecItemDelete&lt;/h2&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;2561dd60-4d42-40db-8772-7f455089f4f8&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Keychain &lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;삭제&lt;/mark&gt;&lt;/strong&gt;를 위한 Query를 작성하고 SecItemDelete 메소드 호출&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;03243829-773b-458e-a120-4fe048d7d10e&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;매칭되는 Key 값의 &lt;strong&gt;Keychain을 Update하여 결과 값을 반환 &lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;pre class=&quot;code Swift&quot; id=&quot;b6816f24-9288-4243-8ebb-2f08a7820bc3&quot;&gt;&lt;code&gt;func deleteItem(key: String) -&amp;gt; Bool {
    let deleteQuery: [CFString: Any] = [kSecClass: kSecClassGenericPassword,
                                  kSecAttrAccount: key]
    let status = SecItemDelete(deleteQuery as CFDictionary)
    if status == errSecSuccess { return true }
    
    print(&quot;deleteItem Error : \(status.description)&quot;)
    return false
  }&lt;/code&gt;&lt;/pre&gt;&lt;p class=&quot;&quot; id=&quot;b62cf292-4bb5-4f9d-b2d1-ca09def29e77&quot;&gt;
&lt;/p&gt;&lt;hr id=&quot;c498ca7c-213e-4fd5-aa3d-ff8ae2f61585&quot;/&gt;&lt;h2 class=&quot;&quot; id=&quot;18d44808-ac3d-4672-8877-c86770fce695&quot;&gt;ViewController.swift&lt;/h2&gt;&lt;pre class=&quot;code Swift&quot; id=&quot;af50a86d-5809-428d-8a92-cbdee0ccf506&quot;&gt;&lt;code&gt;override func viewDidLoad() {
    super.viewDidLoad()
    
    if KeyChain.shared.addItem(id: &quot;honggildong&quot;, pwd: &quot;141433&quot;) {
      valueLabel.text = &quot;addItem Success!!!&quot;
      print(&quot;addItem Success!!!&quot;)
    }
  }

@IBAction func tapOnButton(_ sender: Any) {
    
    if KeyChain.shared.deleteItem(key: &quot;honggildong&quot;) {
      valueLabel.text = &quot;삭제 성공&quot;
    }
  }&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;column-list&quot; id=&quot;1a3d29ff-955b-48a1-a6c1-5c223e78e049&quot;&gt;&lt;div class=&quot;column&quot; id=&quot;f1ecfea5-44c7-4cbb-8b84-e1a8160c822b&quot; style=&quot;width:50.00000000000002%&quot;&gt;&lt;figure class=&quot;image&quot; id=&quot;ac89f1fe-7a3a-4fb5-98f7-dfcd3d47b6c9&quot; style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/4tX7r/btrZg8S1tlr/7QDTgvJv1QYzrtUENF0Kj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4tX7r/btrZg8S1tlr/7QDTgvJv1QYzrtUENF0Kj0/img.png&quot; style=&quot;width:528px&quot;/&gt;&lt;/a&gt;&lt;figcaption&gt;viewDidLoad()에서 addItem하고 성공하면 label Text 변경&lt;/figcaption&gt;&lt;/figure&gt;&lt;p class=&quot;&quot; id=&quot;94e1a233-6c2c-4c76-97c1-99dc43b81c74&quot;&gt;
&lt;/p&gt;&lt;/div&gt;&lt;div class=&quot;column&quot; id=&quot;29a7e9ea-2198-4215-8ca0-3376cf7ba692&quot; style=&quot;width:50%&quot;&gt;&lt;figure class=&quot;image&quot; id=&quot;53552976-a647-423c-9c83-af9d5727a9c1&quot; style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/6mxxf/btrZde0qhA3/A5zNrttwrteeGbGkBnBYbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6mxxf/btrZde0qhA3/A5zNrttwrteeGbGkBnBYbK/img.png&quot; style=&quot;width:864px&quot;/&gt;&lt;/a&gt;&lt;figcaption&gt;버튼 클릭하면 deleteItem을 하여 키체인 정보 삭제 후 label Text 변경&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr id=&quot;32e713d8-f911-463f-8cc7-ce0354e58ba6&quot;/&gt;&lt;h1 class=&quot;&quot; id=&quot;f07be28f-ed09-44f8-ba85-379fa81278bc&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;Keychain Error Codes &lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;table class=&quot;simple-table&quot; id=&quot;d255108b-73ea-4a19-b3fc-0e542231583c&quot;&gt;&lt;thead class=&quot;simple-table-header&quot;&gt;&lt;tr id=&quot;cf2c013c-a1de-4710-8112-9b1c25441039&quot;&gt;&lt;th class=&quot;simple-table-header-color simple-table-header&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;Error Code&lt;/th&gt;&lt;th class=&quot;simple-table-header-color simple-table-header&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;Error Value&lt;/th&gt;&lt;th class=&quot;simple-table-header-color simple-table-header&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;Error Description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr id=&quot;cf45b7b1-26f3-41b9-b7ae-a0cfcb6898a8&quot;&gt;&lt;td class=&quot;&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;errSecSuccess&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;0&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;No error encountered
&lt;mark class=&quot;highlight-purple&quot;&gt;오류가 발생하지 않았습니다.&lt;/mark&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id=&quot;4f499f10-b09d-429f-a21f-a4b00b5dc326&quot;&gt;&lt;td class=&quot;&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;errSecUnimplemented&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;-4&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;Function or operation not implemented
&lt;mark class=&quot;highlight-purple&quot;&gt;구현되지 않은 기능 및 작업이 있습니다.&lt;/mark&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id=&quot;de89b111-257c-4360-82a8-13ef6e50f7b1&quot;&gt;&lt;td class=&quot;&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;errSecParam&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;-50&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;One or more parameters passed to the function were not valid
&lt;mark class=&quot;highlight-purple&quot;&gt;함수에 전달된 하나 이상의 매개변수가 유효하지 않습니다.&lt;/mark&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id=&quot;aa16b4f5-b7e0-4e23-a653-ad722f676c63&quot;&gt;&lt;td class=&quot;&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;errSecAllocate&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;-108&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;Failed to allocate memory
&lt;mark class=&quot;highlight-purple&quot;&gt;메모리 할당에 실패 하였습니다.&lt;/mark&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id=&quot;c9367bab-a415-421b-87e4-f5ef6a571003&quot;&gt;&lt;td class=&quot;&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;errSecNotAvailable&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;-25291&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;No trust results are available
&lt;mark class=&quot;highlight-purple&quot;&gt;신뢰할 수 있는 결과가 없습니다.&lt;/mark&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id=&quot;467a0300-72d6-489b-b6d5-400a5c0c6559&quot;&gt;&lt;td class=&quot;&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;errSecAuthFailed&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;-25293&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;Authorization / authentication Failed
&lt;mark class=&quot;highlight-purple&quot;&gt;승인 / 인증 실패 하였습니다.&lt;/mark&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id=&quot;2d7dea69-400d-4ad5-96c9-d3b0fc426d24&quot;&gt;&lt;td class=&quot;&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;errSecDuplicateItem&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;-25299&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;The item already exists
&lt;mark class=&quot;highlight-purple&quot;&gt;항목이 이미 존재합니다.&lt;/mark&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id=&quot;8544342f-9aa2-4f8e-8f3e-1a642fb2f32e&quot;&gt;&lt;td class=&quot;&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;errSecItemNotFound&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;-25300&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;The item cannot be found
&lt;mark class=&quot;highlight-purple&quot;&gt;항목을 찾을 수 없습니다.&lt;/mark&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id=&quot;6e3b4bce-4bd2-401a-bea8-b71fcc63c599&quot;&gt;&lt;td class=&quot;&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;errSecInteractionNotAllowed&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;-25308&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;Interaction with the Security Server is no allowed
&lt;mark class=&quot;highlight-purple&quot;&gt;보안 서버와의 상호 작용이 허용되지 않습니다.&lt;/mark&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr id=&quot;5ee2a021-7a36-4a74-9cbd-fc8f6c20db09&quot;&gt;&lt;td class=&quot;&quot; id=&quot;GQZK&quot; style=&quot;width:205.65625px&quot;&gt;errSecDecode&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RMdz&quot; style=&quot;width:96.65625px&quot;&gt;-26275&lt;/td&gt;&lt;td class=&quot;&quot; id=&quot;RrdB&quot; style=&quot;width:354.65625px&quot;&gt;Unable to decode the provided data
&lt;mark class=&quot;highlight-purple&quot;&gt;제공된 데이터를 디코딩할 수 없습니다.&lt;/mark&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;h1 class=&quot;&quot; id=&quot;ae989478-a308-4da6-9a61-629a827d397e&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;Keychain OpenSource&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;h2 class=&quot;&quot; id=&quot;6777ca3b-f04a-4e35-88e7-2e277e13a348&quot;&gt;  KeychainSwift&lt;/h2&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;2c58ddde-0b97-46f1-9323-779098a80b07&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;위와 같이 Apple에서 기본적으로 제공해주는 메소드들만으로도 Keychain을 구성할 수 있다.&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;9955f7a9-bbeb-4bcd-9b94-6dcd8116a4e8&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;하지만, 더욱 간편하게 사용할 수 있는 오픈소스가 있다.&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;77474728-d22c-4c7e-bcff-43f7d4831bed&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Podfile에 &lt;strong&gt;KeychainSwift&lt;/strong&gt;를 install 해준다.&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;a2b183bc-a0c3-487e-afa8-6fe586dcdd79&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;프로젝트를 열고 KeychainSwift를 import &amp;amp; 인스턴스 생성을 한다.&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;258403f8-a407-451b-a731-86b227406b46&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;인스턴스를 통해 get, set, delete, clear 등의 메소드를 사용한다. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;a088dc3f-d46d-4461-b138-5ce6abd34863&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;자세한 내용은 &lt;code&gt;&lt;a href=&quot;https://github.com/evgenyneu/keychain-swift&quot;&gt;Github Page&lt;/a&gt;&lt;/code&gt;를 통해 안내하겠습니다.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;h1 class=&quot;&quot; id=&quot;fc868601-71d7-4ff7-8e4a-f664ec202c38&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;번외 및 마무리&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;897d8622-d0bc-46b0-8267-5a8fedb58247&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Keychain라고 해서 &lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;무조건 앱을 삭제해도 데이터가 유지되는 것은 아니다.&lt;/mark&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;3c18928e-d791-4129-b2b2-728bea649066&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;iOS 10.3.3 이상 기기에서 iTunes &amp;amp; iCloud 백업 / 복원을 했을 때, 사라지는 현상이 발생한다고 한다. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;093c227d-8564-4516-bdab-6b2e86501721&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;iTunes 백업 / 복원 상황에서는 &lt;code&gt;kSecAttrAccessible&lt;/code&gt; 설정을 해주면 사라지지 않을 수 있다. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;e64d56a5-154f-4080-aaf1-59e9c7113fa4&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;다만, &lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;iCloud 백업 / 복원&lt;/span&gt; 상황에서 사용자가 &lt;mark class=&quot;highlight-purple&quot;&gt;iCloud 설정 &amp;gt; Keychain 백업 옵션을 OFF&lt;/mark&gt; 해놓았다면, &lt;mark class=&quot;highlight-purple&quot;&gt;삭제될 수 있다.&lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;367eb066-2f5c-43aa-84e3-f3f736a873ff&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;확실한 암호화 &amp;amp; 복호화 방법을 사용하는 솔루션을 사용하거나, 서버를 이용하는 것이 보다 안전할 것이라고 생각한다.&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;0c817f4d-5931-455a-ac19-1d52bdbfa07f&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;위에 작성한 예시들 뿐만 아니라, &lt;mark class=&quot;highlight-purple&quot;&gt;다른 Class Type들은 어떻게 사용할 수 있을지에 대한 고민도 필요하다고 생각한다.&lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;p class=&quot;&quot; id=&quot;a8d6915f-0229-431c-8939-1409739bcc39&quot;&gt;
&lt;/p&gt;&lt;hr id=&quot;8fc513cd-b1f9-425d-98a5-e1dab09778c5&quot;/&gt;&lt;h1 class=&quot;&quot; id=&quot;86e7e6f1-0ac1-4813-9dd9-e3dd714493eb&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;References&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;h3 class=&quot;&quot; id=&quot;4c890239-01bb-44c7-b4f7-f873fe1dd112&quot;&gt;  Apple Document&lt;/h3&gt;&lt;figure id=&quot;778c746b-a62d-4945-a709-1dd832d2ecde&quot;&gt;&lt;a class=&quot;bookmark source&quot; href=&quot;https://developer.apple.com/documentation/security/keychain_services&quot;&gt;&lt;div class=&quot;bookmark-info&quot;&gt;&lt;div class=&quot;bookmark-text&quot;&gt;&lt;div class=&quot;bookmark-title&quot;&gt;Apple Developer Documentation&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;bookmark-href&quot;&gt;&lt;img class=&quot;icon bookmark-icon&quot; src=&quot;https://developer.apple.com/favicon.ico&quot;/&gt;https://developer.apple.com/documentation/security/keychain_services&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;&lt;/figure&gt;&lt;h3 class=&quot;&quot; id=&quot;1e333442-0648-4c18-8854-c72f95085c0f&quot;&gt;⚠️ Error Codes&lt;/h3&gt;&lt;figure id=&quot;495ff7fd-6182-4e64-9559-20c80a20b9d6&quot;&gt;&lt;a class=&quot;bookmark source&quot; href=&quot;https://www.oreilly.com/library/view/ios-components-and/9780133086898/ch18lev2sec7.html&quot;&gt;&lt;div class=&quot;bookmark-info&quot;&gt;&lt;div class=&quot;bookmark-text&quot;&gt;&lt;div class=&quot;bookmark-title&quot;&gt;iOS Components and Frameworks: Understanding the Advanced Features of the iOS SDK&lt;/div&gt;&lt;div class=&quot;bookmark-description&quot;&gt;Keychain Error Codes The Keychain can return several specialized error codes depending on any issues encountered at runtime. These errors are described in Table 18.3. Table 18.3 Keychain Error ... - Selection from iOS Components and Frameworks: Understanding the Advanced Features of the iOS SDK [Book]&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;bookmark-href&quot;&gt;&lt;img class=&quot;icon bookmark-icon&quot; src=&quot;https://www.oreilly.com/favicon.ico&quot;/&gt;https://www.oreilly.com/library/view/ios-components-and/9780133086898/ch18lev2sec7.html&lt;/div&gt;&lt;/div&gt;&lt;img class=&quot;bookmark-image&quot; src=&quot;https://www.oreilly.com/library/cover/9780133086898/&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;&lt;h3 class=&quot;&quot; id=&quot;c0ee9c2d-3377-41e5-87b7-3f300be8bbf1&quot;&gt;  Open Source&lt;/h3&gt;&lt;figure id=&quot;991f938d-7124-4c04-ba55-d841789ed699&quot;&gt;&lt;div class=&quot;source&quot;&gt;https://github.com/evgenyneu/keychain-swift&lt;/div&gt;&lt;/figure&gt;&lt;h3 class=&quot;&quot; id=&quot;d32fa914-94cf-4d96-9733-bf0ccaaf3c51&quot;&gt;  Keychain Example&lt;/h3&gt;&lt;figure id=&quot;ae0b6487-4e95-4237-b2b1-246e36e082c0&quot;&gt;&lt;a class=&quot;bookmark source&quot; href=&quot;https://dvlpr-chan.tistory.com/27&quot;&gt;&lt;div class=&quot;bookmark-info&quot;&gt;&lt;div class=&quot;bookmark-text&quot;&gt;&lt;div class=&quot;bookmark-title&quot;&gt;[iOS] 키체인 (Keychain Service)&lt;/div&gt;&lt;div class=&quot;bookmark-description&quot;&gt;안녕하세요~ 차니에요! 오늘은 키체인에 대해 알아보겠습니다~~! 1. 키체인이란? Apple에서 공식으로 제공하는 보안 프레임워크이며, 사용자의 민감한(개인 정보 등) 데이터들을 저장하는 저장소입니다. 키체인은 사용자가 직접 제거하지 않는 한, 앱을 제거해도 키체인 데이터는 남아있고 디바이스가 lock되면 키체인도 함께 lock되며 디바이스가 unlock되면 키체인도 unlock된다는 특징이 있습니다. 키체인은 하나 이상의 Keychain Item을 갖습니다.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;bookmark-href&quot;&gt;&lt;img class=&quot;icon bookmark-icon&quot; src=&quot;https://dvlpr-chan.tistory.com/favicon.ico&quot;/&gt;https://dvlpr-chan.tistory.com/27&lt;/div&gt;&lt;/div&gt;&lt;img class=&quot;bookmark-image&quot; src=&quot;https://img1.daumcdn.net/thumb/R800x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fofn1t%2FbtrazLGvaFM%2FwNkm7rCYvgN3TR5e2OOIbK%2Fimg.png&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;&lt;p class=&quot;&quot; id=&quot;cb2c642d-9cb6-45d8-8f75-bf17e89e3e10&quot;&gt;
&lt;/p&gt;&lt;/div&gt;&lt;html&gt;&lt;body&gt;&lt;br/&gt;&lt;p class=&quot;&quot;&gt;Uploaded by &lt;mark class=&quot;highlight-orange&quot;&gt;&lt;a href=&quot;https://github.com/jmjeon94/N2T&quot;&gt;N2T&lt;/a&gt;&lt;/mark&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;&lt;/div&gt;&lt;/article&gt;&lt;/body&gt;</description>
      <category>iOS Develop</category>
      <category>ios</category>
      <category>Keychain</category>
      <category>Swift</category>
      <category>스위프트</category>
      <category>키체인</category>
      <author>성재's</author>
      <guid isPermaLink="true">https://whtjdwo78.tistory.com/29</guid>
      <comments>https://whtjdwo78.tistory.com/29#entry29comment</comments>
      <pubDate>Tue, 14 Feb 2023 16:00:29 +0900</pubDate>
    </item>
    <item>
      <title>iOS [Swift] - OAuth 개념 스터디</title>
      <link>https://whtjdwo78.tistory.com/28</link>
      <description>&lt;body&gt;&lt;html&gt;&lt;head&gt;&lt;link href=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.2/styles/atom-one-dark.min.css&quot; rel=&quot;stylesheet&quot;/&gt;
&lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.2/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt;&lt;/head&gt;&lt;/html&gt;&lt;link href=&quot;https://rawcdn.githack.com/ppuep94/n2t/5ef4dc01e9d6336341e9ab95bb71672f9d3a3dc9/assets/css/style2.css&quot; rel=&quot;stylesheet&quot;/&gt;&lt;article class=&quot;page mono Notion&quot; id=&quot;efd6e77c-bd33-4317-923d-34399f66ee55&quot;&gt;&lt;header&gt;&lt;/header&gt;&lt;div class=&quot;page-body Tistory&quot;&gt;&lt;p class=&quot;&quot; id=&quot;f6bd3a57-b104-43e9-99ca-20589a9316bc&quot;&gt;
&lt;/p&gt;&lt;figure class=&quot;block-color-gray_background callout&quot; id=&quot;29ca358b-4bf0-4068-a8a1-a61906d0ebe5&quot; style=&quot;white-space:pre-wrap;display:flex&quot;&gt;&lt;div style=&quot;font-size:1.5em&quot;&gt;&lt;span class=&quot;icon&quot;&gt; &lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;width:100%&quot;&gt;목차&lt;nav class=&quot;block-color-gray table_of_contents&quot; id=&quot;322cfe79-00e6-4b23-a1f6-c09df110477f&quot;&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#26fdc0ce-e59d-42e7-8157-d2ea0718269f&quot;&gt;개념&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#b5dc352c-95a6-4be4-986a-a3d7ab7a0522&quot;&gt;Authentication(인증) / Authorization(허가)&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#5e618837-1956-4ce2-a8c9-010912e4719c&quot;&gt;OAuth Actor&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#7e2620ea-9df8-41ab-b81c-8f9a71589f6d&quot;&gt;OAuth [Client - Server]&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#d6d4cbd3-30fd-415f-a52d-cc6d814ea9e9&quot;&gt;용어 정리&lt;/a&gt;&lt;/div&gt;&lt;/nav&gt;&lt;/div&gt;&lt;/figure&gt;&lt;h1 class=&quot;&quot; id=&quot;26fdc0ce-e59d-42e7-8157-d2ea0718269f&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;개념&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;8e8dcd75-2c11-41a6-9e88-d09e1a1d077f&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;Third Party Application의 인증 권한 부여 및 관리&lt;/mark&gt;를 위해 사용하는 것이다.&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;67b95275-53e7-42e6-a96c-0ec1d5f2907b&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;외부 사이트에 저장된 &lt;mark class=&quot;highlight-purple&quot;&gt;자신의 정보에 대해 접근 권한을 부여&lt;/mark&gt;할 수 있는 공통 수단으로 사용된다. &lt;code&gt;개방형 표준&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;c5213c39-6f79-497b-96cf-ca51d562c8fb&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;OAuth 기반 서버에서 인증이 필요한 API를 호출할 때는 &lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;OAuth 토큰&lt;/mark&gt;&lt;/strong&gt;을 반드시 이용한다.&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;6909d958-e71e-43bb-b375-cbbae4fcf50d&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;외부 SNS 계정을 기반으로 &lt;mark class=&quot;highlight-purple&quot;&gt;간편 회원가입 &amp;amp; 로그인&lt;/mark&gt;을 할 수 있게 해주는 역할을 한다. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;3edea415-5f81-40fa-9e99-5d597160f4d3&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;뿐만 아니라, &lt;mark class=&quot;highlight-purple&quot;&gt;외부 App에서 제공하는 기능들을 사용&lt;/mark&gt;할 수 있다. [기타 Api]&lt;ul class=&quot;bulleted-list&quot; id=&quot;a7382638-68ee-47d6-a600-fd312ef3b08e&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Google 로그인 → API 통신 → 사용자 Google Calendar 정보 열람&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;36ba5ba6-ed86-4c58-b5fd-cb14d8ff1379&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;code&gt;장점&lt;/code&gt; : &lt;mark class=&quot;highlight-purple&quot;&gt;사용자가 다른 애플리케이션에서 사용하고 있는 서비스의 정보를 가공하여 보다 가치 있는 결과물을 제공할 수 있다.&lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p class=&quot;&quot; id=&quot;c7e4ae86-427b-42ae-89f2-c71489380c94&quot;&gt;
&lt;/p&gt;&lt;/div&gt;&lt;h1 class=&quot;&quot; id=&quot;b5dc352c-95a6-4be4-986a-a3d7ab7a0522&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;Authentication(인증) / Authorization(허가)&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;5bd80f53-67b6-411a-ade9-9293ec33a15e&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;code&gt;일반&lt;/code&gt; 로그인 : 아이디 &amp;amp; 비밀번호를 통해 인증을 하는 것&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;5b0848cc-c98e-42d0-afb9-0138383a77cc&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;code&gt;OAuth&lt;/code&gt; 로그인 : &lt;mark class=&quot;highlight-purple&quot;&gt;타 App의 정보에 접근하기 위해 우리의 App이 허락받아 사용자 인증을 하는 것&lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;h1 class=&quot;&quot; id=&quot;5e618837-1956-4ce2-a8c9-010912e4719c&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;OAuth Actor&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;a1e7ea45-0cc1-4e76-b0fc-0d5fa290cb23&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;code&gt;Resource Server&lt;/code&gt; : Client가 제어할 자원(resource)을 보유한 서버&lt;ul class=&quot;bulleted-list&quot; id=&quot;10e82570-77c9-46b9-bf86-25686c4e3851&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Twitter, Google, Facebook 등 &lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;사용자의 Api를 제공하는 타 App&lt;/mark&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;80a53539-fe91-4004-9785-c90ebe272e8d&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;code&gt;Resource Owner&lt;/code&gt; : 자원(resource) 소유자&lt;ul class=&quot;bulleted-list&quot; id=&quot;8df131d7-dd31-4d51-b56f-1b5e1053e58a&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;로그인을 행하는 &lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;실제 사용자&lt;/mark&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;8accff9a-049c-4d4e-af39-355db4365461&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;code&gt;Client&lt;/code&gt; : Resource Server에 접속해서 정보를 가져오는 대상 (&lt;a href=&quot;https://www.notion.so/iOS-Swift-OAuth-efd6e77cbd334317923d34399f66ee55&quot;&gt;Web Application&lt;/a&gt;)&lt;ul class=&quot;bulleted-list&quot; id=&quot;227f4e0a-2dd5-4acf-9d0a-c9ddce0588e4&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;다시 말해, &lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;사용자가 사용하고자 하는 우리가 만든 서비스&lt;/mark&gt;&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p class=&quot;&quot; id=&quot;d6f008cf-2e63-4c0b-9e0f-26c5208655aa&quot;&gt;
&lt;/p&gt;&lt;/div&gt;&lt;h1 class=&quot;&quot; id=&quot;7e2620ea-9df8-41ab-b81c-8f9a71589f6d&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;OAuth [Client - Server]&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;figure class=&quot;image&quot; id=&quot;f5a455be-3a21-4dfb-bf03-0b78c17a2557&quot; style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/ewBIh9/btrZkaaW12P/gpSTzIEzjHEZUZP3Ds6uL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ewBIh9/btrZkaaW12P/gpSTzIEzjHEZUZP3Ds6uL1/img.png&quot; style=&quot;width:664px&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;ad753a1b-e6e6-4f8d-b615-9765cb173d53&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;code&gt;요약&lt;/code&gt; : Client에서 Server의 Token을 받고, 그 Token을 가지고 다시 Server에 요청해서 원하는 자원을 획득할 수 있다.&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;ac642173-8cba-47db-a0ea-ef09369857be&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Token의 종류&lt;ul class=&quot;bulleted-list&quot; id=&quot;a0cc7396-f319-485a-b2e8-588bf9a7247f&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Access Token : 요청 절차를 &lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;정상적으로 종료&lt;/mark&gt;&lt;/strong&gt;한 Client에게 발급 (시간 제한 있음)&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;64f8fe9a-4f8d-4f17-bd70-77d0d27ec7f9&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Refresh Token : &quot;Resource Server&quot;가 아니라 &quot;&lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;Authorization Server&lt;/mark&gt;&lt;/strong&gt;&quot;에서만 사용 가능 (시간 제한 없음)&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;dabc03b4-24d9-431d-82c8-d040996e2dfb&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Token은 Apple의 Keychain 저장소에 저장한다. &lt;code&gt;&lt;a href=&quot;https://www.notion.so/Keychain-5d368c931a8c47e8b9b883bf73d6d233&quot;&gt;자세한 내용은 여기&lt;/a&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;toggle&quot; id=&quot;90f1b02b-f08d-4628-9e2d-b561560dcdb9&quot;&gt;&lt;li&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;&lt;mark class=&quot;highlight-red&quot;&gt;&lt;strong&gt;Flow&lt;/strong&gt;&lt;/mark&gt;&lt;/summary&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;a0d16292-4045-4b2b-9f75-da6824060067&quot; start=&quot;1&quot; type=&quot;1&quot;&gt;&lt;li&gt;MyApp(Client)이 Facebook(Resource Server)에 &lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;API를 사용하겠다고 등록 요청&lt;/mark&gt;&lt;/strong&gt;합니다. &lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;da3d86b5-45d7-40d1-aefc-c29ea2d57cff&quot; start=&quot;2&quot; type=&quot;1&quot;&gt;&lt;li&gt;Facebook(Resource Server)은 &lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;MyApp(Client)를 식별&lt;/span&gt;할 수 있는 &lt;mark class=&quot;highlight-purple&quot;&gt;&lt;strong&gt;Client ID &amp;amp; Secret을 발급&lt;/strong&gt;&lt;/mark&gt;해줍니다. &lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;d6db039b-e7ec-49fa-abed-ace24c9690fc&quot; start=&quot;3&quot; type=&quot;1&quot;&gt;&lt;li&gt;사용자(Resource Owner)는 MyApp(Client)에서 &lt;mark class=&quot;highlight-purple&quot;&gt;&lt;strong&gt;Facebook 로그인을 요청&lt;/strong&gt;&lt;/mark&gt;합니다. &lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;43bb8f97-8253-4787-b487-9d30e4e13825&quot; start=&quot;4&quot; type=&quot;1&quot;&gt;&lt;li&gt;MyApp(Client)은 사용자(Resource Owner)에게 &lt;mark class=&quot;highlight-purple&quot;&gt;&lt;strong&gt;Facebook(Resource Server) 로그인 화면을 띄워줍니다.&lt;/strong&gt;&lt;/mark&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;7fc7f9b5-ae5e-41b6-bf7c-275cae15dd46&quot; start=&quot;5&quot; type=&quot;1&quot;&gt;&lt;li&gt;사용자(Resource Owner)는 &lt;mark class=&quot;highlight-purple&quot;&gt;&lt;strong&gt;MyApp(Client)이 Facebook(Resource Server) 자신의 정보에 접근해도 괜찮은지에 대한 동의&lt;/strong&gt;&lt;/mark&gt;를 받습니다. (&quot;MyApp에서 당신의 Facebook 정보를 사용해도 괜찮겠습니까?&quot;)&lt;ol class=&quot;numbered-list&quot; id=&quot;2abe9a97-10a8-434e-a9a6-75ef6ccafd45&quot; start=&quot;1&quot; type=&quot;a&quot;&gt;&lt;li&gt;사용자가 MyApp에게 Facebook 권한을 &lt;mark class=&quot;highlight-yellow_background&quot;&gt;허용했을 때&lt;/mark&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;411787d6-8030-4ee4-b963-3f6eff505f15&quot; start=&quot;1&quot; type=&quot;i&quot;&gt;&lt;li&gt;Facebook(Resource Server)은 MyApp(Client)에게 &lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;암호화 코드를 제공&lt;/span&gt;합니다.&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;77b09c75-217d-4970-a368-678160e010df&quot; start=&quot;2&quot; type=&quot;i&quot;&gt;&lt;li&gt;MyApp(Client)은 2번에서 발급 받은 &lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;Client ID &amp;amp; Secret을 암호화 코드&lt;/span&gt;와 함께 Facebook(Resource Server)으로 &lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;다시 보냅니다.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;b24000cc-0641-43c0-b5ad-bc266e2682e7&quot; start=&quot;3&quot; type=&quot;i&quot;&gt;&lt;li&gt;Facebook(Resource Server)은 &lt;strong&gt;&lt;code&gt;&lt;mark class=&quot;highlight-teal_background&quot;&gt;암호화 코드, Client ID &amp;amp; Secret이 모두 자신이 제공한 것과 일치한다고 판단&lt;/mark&gt;&lt;/code&gt;&lt;/strong&gt;했을 때, &lt;code&gt;&lt;strong&gt;최종 접근 권한 부여의 의미로 Access Token을 발급해줍니다.&lt;/strong&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;0a4178ec-7a73-406f-a70c-265eda75c404&quot; start=&quot;2&quot; type=&quot;a&quot;&gt;&lt;li&gt;사용자가 MyApp에게 Facebook 권한을 &lt;mark class=&quot;highlight-yellow_background&quot;&gt;거부했을 때&lt;/mark&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;2e180192-8696-4f36-8286-55c7af459252&quot; start=&quot;1&quot; type=&quot;i&quot;&gt;&lt;li&gt;Facebook 로그인 정보에 대한 접근이 없기 때문에 &lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;로그인이 불가&lt;/span&gt;합니다. &lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;h1 class=&quot;&quot; id=&quot;d6d4cbd3-30fd-415f-a52d-cc6d814ea9e9&quot;&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;용어 정리&lt;/summary&gt;&lt;/details&gt;&lt;/h1&gt;&lt;div class=&quot;indented&quot;&gt;&lt;p class=&quot;&quot; id=&quot;6670fdca-0ca6-446f-8cce-f51f44642944&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;  Web Application&lt;/mark&gt;&lt;/p&gt;&lt;div class=&quot;indented&quot;&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;6b23ac48-4876-46e6-894b-03362a353a88&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;웹 브라우저와 웹 기술을 사용하여 사용자와 소통할 수 있도록 만든 컴퓨터 프로그램&lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;p class=&quot;&quot; id=&quot;79113482-3492-419c-82ac-90d766750ecd&quot;&gt;
&lt;/p&gt;&lt;p class=&quot;&quot; id=&quot;980e85db-9641-495d-a75a-2a3b858bf247&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;  Web Container&lt;/mark&gt;&lt;/p&gt;&lt;div class=&quot;indented&quot;&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;9fee9e76-9848-4027-8dd7-fd6748730828&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;동적인 처리를 담당한다. &lt;/mark&gt;&lt;strong&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;Servlet Container&lt;/mark&gt;&lt;/strong&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;라고도 하며 JSP, Servlet을 실행할 수 있는 프로그램이다. &lt;/mark&gt;&lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;JSP, Servlet은 웹 서버로부터 받은 동적인 데이터를 처리하여 &lt;/mark&gt;&lt;/span&gt;&lt;strong&gt;&lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;정적인 페이지&lt;/mark&gt;&lt;/span&gt;&lt;/strong&gt;&lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;를 생성&lt;/mark&gt;&lt;/span&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;한다. 하지만, &lt;/mark&gt;&lt;code&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;Web Container는 웹 서버로부터 받은 정보로 동적 페이지를 생성하여 웹 서버에게 전달&lt;/mark&gt;&lt;/code&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;해줄 수 있다. &lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;p class=&quot;&quot; id=&quot;b5979b41-dff4-4491-8e6f-c9a03483603b&quot;&gt;
&lt;/p&gt;&lt;p class=&quot;&quot; id=&quot;4fedfe5c-f8c8-48c8-bb82-96d0232f543a&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;  Web Application Server &lt;/mark&gt;&lt;code&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;(WAS)&lt;/mark&gt;&lt;/code&gt;&lt;/p&gt;&lt;div class=&quot;indented&quot;&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;28789533-691f-44fb-9d95-5fc07068b5c4&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;Web Server + Web Container, &lt;/mark&gt;&lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;정적인 페이지(HTML)에서 처리할 수 없는&lt;/mark&gt;&lt;/span&gt;&lt;mark class=&quot;highlight-gray&quot;&gt; Business Logic, DB 조회 등 &lt;/mark&gt;&lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;&lt;strong&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;동적인 컨텐츠를 제공&lt;/mark&gt;&lt;/strong&gt;&lt;/span&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;한다.&lt;/mark&gt;&lt;code&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;톰캣&lt;/mark&gt;&lt;/code&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;p class=&quot;&quot; id=&quot;5e5a9eda-7d3d-47f9-8d48-1201dd849c9f&quot;&gt;
&lt;/p&gt;&lt;p class=&quot;&quot; id=&quot;673252f5-514b-4ac4-8a35-97d5ed9356e8&quot;&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;  [웹 서버는 정적 처리, WAS는 동적 처리]를 같이 사용하면, 서버 부하를 막으면서 물리적인 분리를 통해 보안을 강화할 수 있다. &lt;/mark&gt;&lt;/p&gt;&lt;p class=&quot;&quot; id=&quot;388a1261-a768-49bf-9d18-8f3de4054034&quot;&gt;
&lt;/p&gt;&lt;p class=&quot;&quot; id=&quot;66e9b58b-a4b9-48c3-9901-1cd299cccdf4&quot;&gt;
&lt;/p&gt;&lt;/div&gt;&lt;p class=&quot;&quot; id=&quot;b5845675-1173-45df-a123-ae5b4a1c0077&quot;&gt;
&lt;/p&gt;&lt;html&gt;&lt;body&gt;&lt;br/&gt;&lt;p class=&quot;&quot;&gt;Uploaded by &lt;mark class=&quot;highlight-orange&quot;&gt;&lt;a href=&quot;https://github.com/jmjeon94/N2T&quot;&gt;N2T&lt;/a&gt;&lt;/mark&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;&lt;/div&gt;&lt;/article&gt;&lt;/body&gt;</description>
      <category>iOS Develop</category>
      <category>ios</category>
      <category>oauth</category>
      <category>Swift</category>
      <category>스위프트</category>
      <author>성재's</author>
      <guid isPermaLink="true">https://whtjdwo78.tistory.com/28</guid>
      <comments>https://whtjdwo78.tistory.com/28#entry28comment</comments>
      <pubDate>Tue, 14 Feb 2023 15:56:04 +0900</pubDate>
    </item>
    <item>
      <title>iOS [Swift] - Moya를 통한 네트워크 통신</title>
      <link>https://whtjdwo78.tistory.com/27</link>
      <description>&lt;body&gt;&lt;html&gt;&lt;head&gt;&lt;link href=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.2/styles/atom-one-dark.min.css&quot; rel=&quot;stylesheet&quot;/&gt;
&lt;script src=&quot;//cdnjs.cloudflare.com/ajax/libs/highlight.js/10.1.2/highlight.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;hljs.initHighlightingOnLoad();&lt;/script&gt;&lt;/head&gt;&lt;/html&gt;&lt;link href=&quot;https://rawcdn.githack.com/ppuep94/n2t/5ef4dc01e9d6336341e9ab95bb71672f9d3a3dc9/assets/css/style2.css&quot; rel=&quot;stylesheet&quot;/&gt;&lt;article class=&quot;page mono Notion&quot; id=&quot;1ba8f649-bbd2-466d-adae-71e4ebf7bcb5&quot;&gt;&lt;header&gt;&lt;/header&gt;&lt;div class=&quot;page-body Tistory&quot;&gt;&lt;figure class=&quot;block-color-gray_background callout&quot; id=&quot;74a128f6-f17e-4abe-b4ad-1673884b7a56&quot; style=&quot;white-space:pre-wrap;display:flex&quot;&gt;&lt;div style=&quot;font-size:1.5em&quot;&gt;&lt;span class=&quot;icon&quot;&gt; &lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;width:100%&quot;&gt;목차&lt;nav class=&quot;block-color-gray table_of_contents&quot; id=&quot;b7ea8787-e088-40d2-8cab-8b04ded92a5d&quot;&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#96c34b70-c098-4a1b-8bf5-e73a94e587f9&quot;&gt;개념&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#2636cc14-1f93-454f-8759-ba17cd6816d6&quot;&gt;특징&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#1a75ca4f-1f88-4cbb-840c-ec4047093c40&quot;&gt;Flow (정말 간단하게만 사용법 익히기)&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#63b707f7-e959-4fbe-9c61-9e8ec4237029&quot;&gt;마무리&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;table_of_contents-item table_of_contents-indent-0&quot;&gt;&lt;a class=&quot;table_of_contents-link&quot; href=&quot;#933629aa-67be-44b3-bf18-0b8a315ab37d&quot;&gt;References&lt;/a&gt;&lt;/div&gt;&lt;/nav&gt;&lt;/div&gt;&lt;/figure&gt;&lt;p class=&quot;&quot; id=&quot;27b4864c-02c4-46ce-a0c2-05c3fc9cee41&quot;&gt;
&lt;/p&gt;&lt;blockquote class=&quot;&quot; id=&quot;35760105-40fc-4b17-8b36-31f1427f335a&quot;&gt;iOS에서 네트워크 작업이라고 하면 가장 떠오르는 &lt;mark class=&quot;highlight-yellow_background&quot;&gt;URLSession, Alamofire&lt;/mark&gt;가 있을 것이다. &lt;strong&gt;URLSession&lt;/strong&gt;은 프로젝트의 복잡도가 올라가고 가독성이 안좋은 반면, URLSession 기반의 &lt;strong&gt;Alamofire&lt;/strong&gt;는 보다 간결하고 가독성이 좋다. 하지만, &lt;strong&gt;Alamofire&lt;/strong&gt;는 유지보수 &amp;amp; 테스트에 적합하다고 확언할 수 없다. &lt;mark class=&quot;highlight-yellow_background&quot;&gt;그래서 오늘의 주제 &lt;/mark&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;&lt;code&gt;Moya&lt;/code&gt;&lt;/mark&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;를 살펴볼 것이다.&lt;/mark&gt;&lt;/blockquote&gt;&lt;p class=&quot;&quot; id=&quot;1bec3c3b-4696-4c1a-a30f-91376d24075c&quot;&gt;
&lt;/p&gt;&lt;hr id=&quot;62f7a1aa-9f87-4682-ac09-69c3b66f6361&quot;/&gt;&lt;h1 class=&quot;&quot; id=&quot;96c34b70-c098-4a1b-8bf5-e73a94e587f9&quot;&gt;개념&lt;/h1&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;993017e3-eb55-4049-aa3e-f6f94ce9b3f8&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;URLSession을 추상화 시킨 &lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;Alamofire를 한 번 더 추상화시킨 Networking Library&lt;/span&gt;이다. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;1a0ff6c3-bfe2-4335-b46b-0306361bae7f&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;&lt;strong&gt;Enum(열거형)을 사용&lt;/strong&gt;&lt;/mark&gt;해서 네트워크 요청을 &lt;mark class=&quot;highlight-purple&quot;&gt;&lt;strong&gt;type-safe&lt;/strong&gt;&lt;/mark&gt;한 방식으로 캡슐화한다. (안전 &amp;amp; 깔끔)&lt;ul class=&quot;toggle&quot; id=&quot;85cc78f2-8bf9-4a6c-9a3e-b7d301d9b809&quot;&gt;&lt;li&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;&lt;mark class=&quot;highlight-gray&quot;&gt;type-safe&lt;/mark&gt;&lt;/summary&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;6206d035-1d25-4f12-a735-7d837a69399d&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;해당 Type에는 정해진 Type만 저장이 가능하다. 라는 의미 (다른 Type 안돼!! ❌)&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;d0edf08e-89d9-47b9-abc9-f69a4f79729e&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;즉, 변수의 Type이 명확해진다. &lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p class=&quot;&quot; id=&quot;5b4863b4-2ae4-4a2c-ac46-e1508a1b4909&quot;&gt;
&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr id=&quot;af875e1d-9153-42b9-843b-24a8f25fcab8&quot;/&gt;&lt;h1 class=&quot;&quot; id=&quot;2636cc14-1f93-454f-8759-ba17cd6816d6&quot;&gt;특징&lt;/h1&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;20d4576e-3efb-4b9b-968d-8b4813a10a72&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Alamofire에서 네트워크 계층을 구조화하는 방법과는 다른 방법을 제공한다. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;bd3f806c-5ae6-4a8f-bca0-efee6f49c384&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;Alamofire Library를 Enum 타입으로 만들어 더 &lt;strong&gt;&lt;mark class=&quot;highlight-purple&quot;&gt;사용성과 테스트성을 용이&lt;/mark&gt;&lt;/strong&gt;하게 만들었다. &lt;ul class=&quot;bulleted-list&quot; id=&quot;47d58503-b6d1-402a-8132-567d057483ee&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Enum이기 때문에 Type 지정을 해주기 편하다.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;toggle&quot; id=&quot;040fb664-0507-4137-8bf7-4d171ad5e093&quot;&gt;&lt;li&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;&lt;strong&gt;기존 네트워킹 방식 VS Moya&lt;/strong&gt;&lt;/mark&gt;&lt;/summary&gt;&lt;figure class=&quot;image&quot; id=&quot;14a8cfe6-171e-485c-b15a-702b87012c60&quot; style=&quot;text-align: center;&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/rOAnL/btrZc7mCAAh/UlT6c7eufyZVz1cmkf4MQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rOAnL/btrZc7mCAAh/UlT6c7eufyZVz1cmkf4MQk/img.png&quot; style=&quot;width:1206px&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;11ccb3f2-16f5-4179-85e0-6a00ea057580&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;code&gt;기존 네트워킹 사용법&lt;/code&gt;은 왼쪽 그림처럼 Network Layer를 통해 자유롭게 구현되고 있다. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;toggle&quot; id=&quot;1bd696b1-6b06-46fc-a2e8-93c8cdcd5647&quot;&gt;&lt;li&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;따라서, 기존 네트워킹 방식은 다음과 같은 &lt;mark class=&quot;highlight-red_background&quot;&gt;문제점&lt;/mark&gt;들을 가지고 있었다. &lt;/summary&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;b10687b1-3618-4074-b9df-706b3bec02df&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;새 App을 작성하기 어렵다.(어디서부터 시작해야하는가?)&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;cf0a3320-2143-4834-88d7-f128dad35043&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;기존 App을 유지하기 어렵게 만든다.(아놔, 너무 엉망 진창이네..)&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;10789c60-8188-41f6-8c99-12ffbc6006f2&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;단위 테스트를 작성하기 어렵게 만든다.(이 작업을 다시 하려면 어떻게 해야해?)&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;b14e2cf5-6be5-4bd7-a852-e26ef902f8da&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;code&gt;Moya&lt;/code&gt;는 오른쪽 그림처럼 보다 깔끔한 Layer를 통해 &lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;자체적으로 네트워킹을하지 않고&lt;/span&gt; &lt;mark class=&quot;highlight-purple&quot;&gt;&lt;strong&gt;Alamofire를 통해 구현된다.&lt;/strong&gt;&lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;2c63e3bc-8e0c-448c-8638-6cb9199cc1c3&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;뿐만 아니라, Network Layer를 Template화 시켜서 &lt;mark class=&quot;highlight-yellow_background&quot;&gt;재사용&lt;/mark&gt;이 가능하다. &lt;/li&gt;&lt;/ul&gt;&lt;p class=&quot;&quot; id=&quot;d711e919-3943-4e4e-a7a6-ce9eee56573b&quot;&gt;
&lt;/p&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;toggle&quot; id=&quot;94fefe43-69ea-4aeb-8f6c-3ee68ad8109a&quot;&gt;&lt;li&gt;&lt;details open=&quot;&quot;&gt;&lt;summary&gt;&lt;code&gt;Moya&lt;/code&gt;의 장점&lt;/summary&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;a1870f90-1cfe-4939-962f-9c95c29348e5&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;올바른 API 엔드포인트 액세스를 위한 컴파일 시간 검사. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;6985ca7c-1a63-4d53-8816-d2ed275221a4&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;연결된 열거형 값을 사용하여 다양한 엔드포인트의 명확한 사용법을 정의할 수 있습니다. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;1f99a3e1-1c68-4be1-b2bd-70fc54eb572d&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;테스트 스텁을 일급 시민으로 취급하므로 단위 테스트가 매우 쉽습니다.&lt;/li&gt;&lt;/ul&gt;&lt;/details&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p class=&quot;&quot; id=&quot;c9381bf0-79bc-4c20-aa4f-3fec807995f8&quot;&gt;
&lt;/p&gt;&lt;hr id=&quot;06ae0dc2-e404-4d1c-b61b-40e2d8e6989c&quot;/&gt;&lt;h1 class=&quot;&quot; id=&quot;1a75ca4f-1f88-4cbb-840c-ec4047093c40&quot;&gt;Flow (정말 간단하게만 사용법 익히기)&lt;/h1&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;323a3a28-9f9f-4935-80e7-3500f73aef3d&quot; start=&quot;1&quot; type=&quot;1&quot;&gt;&lt;li&gt;&lt;strong&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;Pod 설치 &lt;/mark&gt;&lt;/strong&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;56d3420d-4648-4bf1-b403-8a11c6c9dcfe&quot; start=&quot;1&quot; type=&quot;a&quot;&gt;&lt;li&gt;pod init&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;d9324973-87e0-4e9b-a423-c739e2306942&quot; start=&quot;2&quot; type=&quot;a&quot;&gt;&lt;li&gt;pod install&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;code Swift&quot; id=&quot;ff5d0c03-ecdd-4bf5-a5fe-80a1b6618da5&quot;&gt;&lt;code&gt;pod 'Moya', '~&amp;gt; 15.0'&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;&lt;/ol&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;e33c3b57-fda6-4077-83d6-5e01ad32f78d&quot; start=&quot;2&quot; type=&quot;1&quot;&gt;&lt;li&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;API 통신을 위한 &lt;/mark&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;&lt;strong&gt;Moya &amp;gt; TargetType&lt;/strong&gt;&lt;/mark&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;을 정의&lt;/mark&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;code Swift&quot; id=&quot;11dd5959-3ff1-45e8-b170-f1ff89f50056&quot;&gt;&lt;code&gt;import Foundation
import Moya

enum APIClient {
  case users, todos, comments
}

extension APIClient: TargetType {
  var baseURL: URL {
    switch self {
    case .users, .todos, .comments:
      return URL(string: &quot;https://jsonplaceholder.typicode.com/&quot;)!
    }
  }
  
  var path: String {
    switch self {
    case .users:
      return &quot;users&quot;
    case .todos:
      return &quot;todos&quot;
    case .comments:
      return &quot;comments&quot;
    }
  }
  
  var method: Moya.Method {
    switch self {
    case .users, .todos, .comments:
      return .get
    }
  }
  
  var task: Moya.Task {
    switch self {
    case .users:
      return .requestPlain
    case .todos:
      return .requestPlain
    case .comments:
      return .requestPlain
    }
  }
  
  var headers: [String : String]? {
    return [&quot;Content-type&quot;: &quot;application/json&quot;]
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;8b81ca26-0e86-4943-b55f-f572915336a4&quot; start=&quot;3&quot; type=&quot;1&quot;&gt;&lt;li&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;Json Model Struct 작성&lt;/mark&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;code Swift&quot; id=&quot;31f8d73a-fd37-4f5f-8d09-08ed293a4067&quot;&gt;&lt;code&gt;struct Todos: Codable {
  var userId: Int
  var id: Int
  var title: String
  var completed: Bool
}&lt;/code&gt;&lt;/pre&gt;&lt;ol class=&quot;numbered-list&quot; id=&quot;ad8f07dd-64d2-4768-9b6f-ceb997a52646&quot; start=&quot;4&quot; type=&quot;1&quot;&gt;&lt;li&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;API 통신&lt;/mark&gt;&lt;/li&gt;&lt;/ol&gt;&lt;pre class=&quot;code Swift&quot; id=&quot;9748e19c-09ff-4b16-b326-68c37b48a509&quot;&gt;&lt;code&gt;func getDataFromJsonPlaceHolder() {
    let moyaProvider = MoyaProvider&amp;lt;APIClient&amp;gt;()
    
    moyaProvider.request(.todos) { result in
      switch result {
      case .success(let response):
//        guard let todoTitle = try? response.mapJSON() else { return }
        guard let todo = try? response.map([Todos].self) else { return }
        self.labelText.text = todo[Int.random(in: 1..&amp;lt;10)].title
      case .failure(let moyaError):
        print(moyaError.errorDescription ?? &quot;Moya API Request Error&quot;)
      }
    }
  }&lt;/code&gt;&lt;/pre&gt;&lt;p class=&quot;&quot; id=&quot;3bf540df-69b6-46fd-90fd-5b69ab9db921&quot;&gt;
&lt;/p&gt;&lt;hr id=&quot;3c808faf-f970-4f51-840b-3ba9e6e4343a&quot;/&gt;&lt;h1 class=&quot;&quot; id=&quot;63b707f7-e959-4fbe-9c61-9e8ec4237029&quot;&gt;마무리&lt;/h1&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;40b861cd-befa-4175-8f00-644f8a5004db&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;&lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;URLSession &amp;amp; Alamofire&lt;/span&gt;&lt;/mark&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt; &lt;/mark&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;&lt;strong&gt;VS&lt;/strong&gt;&lt;/mark&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt; &lt;/mark&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;&lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;Moya&lt;/span&gt;&lt;/mark&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt; &lt;/mark&gt;&lt;mark class=&quot;highlight-yellow_background&quot;&gt;&lt;strong&gt;차이점&lt;/strong&gt;&lt;/mark&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;2994d4e5-f169-4349-b80f-a6cd2db5008c&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;기존에 사용해봤던 URLSession과 Alamofire는 request/response를 하면서 동시에 여러가지(url, method 등)를 신경 써야했다. (사용할 때마다 반복 작성)&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;a79ac6ae-65f8-49c1-8b5b-156946312339&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Moya를 공부하고 사용해보면서 하나의 타입을 다 정의 해줘야한다는 작업이 조금(?)은 귀찮을 수 있지만, 같은 API를 많이 사용하게 되는 프로젝트라면 사용하는게 좋다고 생각됐다. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;f2f3f7b0-ac71-4afc-9509-b75f367ed286&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;아무래도 같은 API에 대해서 반복적으로 같은 코드를 작성하는 것은 비효율적일 수 있다. 또한, 데이터 처리하는 과정에서 어쩌면 집중도를 떨어뜨리는 요인이 될 수 있다고 생각한다. &lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;e80bacf4-bbde-4f67-90f2-4c608e0b20e0&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;Moya의 &lt;mark class=&quot;highlight-blue&quot;&gt;&lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;TargetType에서 여러가지 항목들을 &lt;/span&gt;&lt;/mark&gt;&lt;strong&gt;&lt;mark class=&quot;highlight-blue&quot;&gt;&lt;span style=&quot;border-bottom:0.05em solid&quot;&gt;미리 작성&lt;/span&gt;&lt;/mark&gt;&lt;/strong&gt;해놓고, 반복적으로 사용되는 부분을    &lt;code&gt;재사용&lt;/code&gt;한다면 데이터 처리하는 과정에서 보다 &lt;mark class=&quot;highlight-blue&quot;&gt;집중도&lt;/mark&gt; 있고 &lt;mark class=&quot;highlight-blue&quot;&gt;가독성&lt;/mark&gt;이 좋은 코드를 작성할 수 있다고 생각한다. &lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;25c87e81-66d4-4982-b802-3933fdd785f5&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;strong&gt;오히려 내가 지금 반복적으로 말하고 있긴하지만 ㅋㅋ 아무튼간!! Moya는 상황에 따라 맞춰 필요한 프로젝트에 적용하면 좋을 것 같다. &lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;f67f04a0-28b0-4fe7-a3f5-c769e5bbd4ca&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;그리고 Moya를 좀 더 효율적으로 쓰기 위해선 &lt;code&gt;CommonMoyaProvider&lt;/code&gt;를 만들어서 모든 API 코드에 적용하는 것이 좋다고 생각한다.&lt;ul class=&quot;bulleted-list&quot; id=&quot;0e43b0da-490f-4e92-abfc-1c5abdaeb8a8&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;&lt;mark class=&quot;highlight-blue&quot;&gt;ex) 모든 api response에 중복 로그인 에러 처리를 하는 반복적인 코드를 작성하지 않기 위해 Custom 해주는 것.&lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;1c4eeec5-bdb8-4f0d-9aa4-a2e94cd99f6e&quot;&gt;&lt;li style=&quot;list-style-type:circle&quot;&gt;CommonMoyaProvider에는 Moya TargetType을 가진 API들을 모두 담아 사용할 수 있도록 Generic 형태로 사용하는 것이 좋다. &lt;mark class=&quot;highlight-blue&quot;&gt;CommonMoyaProvider&amp;lt;T: TargetType&amp;gt;&lt;/mark&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;15ca210a-8558-41ff-ba37-966adb48f61e&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;&lt;strong&gt;막 네트워크 통신을 위해서 Moya는 쓰는게 진짜 좋아!! 이정도의 메리트는 아닌 느낌이 들었다. 그러나 분명히 쓰임새가 좋고 활용도가 높은건 확실!하다. 코드도 간결해지고..? &lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul class=&quot;bulleted-list&quot; id=&quot;f1fcda66-c766-40a4-bf1a-9647a6d85b43&quot;&gt;&lt;li style=&quot;list-style-type:disc&quot;&gt;이번 포스팅 끝!&lt;/li&gt;&lt;/ul&gt;&lt;p class=&quot;&quot; id=&quot;03aa7515-594d-4243-9892-49a1e98f8255&quot;&gt;
&lt;/p&gt;&lt;p class=&quot;&quot; id=&quot;81aa3c58-5361-488a-8083-b6c4ea3f6946&quot;&gt;
&lt;/p&gt;&lt;h1 class=&quot;&quot; id=&quot;933629aa-67be-44b3-bf18-0b8a315ab37d&quot;&gt;References&lt;/h1&gt;&lt;figure id=&quot;770e7f09-efff-4963-81f0-fb6a5318002d&quot;&gt;&lt;a class=&quot;bookmark source&quot; href=&quot;https://techblog.woowahan.com/2704/&quot;&gt;&lt;div class=&quot;bookmark-info&quot;&gt;&lt;div class=&quot;bookmark-text&quot;&gt;&lt;div class=&quot;bookmark-title&quot;&gt;iOS Networking and Testing | 우아한형제들 기술블로그&lt;/div&gt;&lt;div class=&quot;bookmark-description&quot;&gt;Networking은 요즘 앱에서 거의 필수적인 요소입니다. 설치되어 있는 앱들 중에 네트워킹을 사용하지 않는 앱은 거의 없을 겁니다. API 추가가 쉽고 변경이 용이한 네트워킹 모듈을 개발하는것이 중요한 이유죠. 미드 보셨나요? 쉘든 쿠퍼 라는 주인공은 16살에 박사학위를 취득할 만큼 천재이면서 동시에 대단히 특이한 사람입니다. 주변에서 &quot;Are you crazy?&quot; 라는 말을 자주 듣습니다.&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;bookmark-href&quot;&gt;&lt;img class=&quot;icon bookmark-icon&quot; src=&quot;https://techblog.woowahan.com/wp-content/uploads/2020/08/favicon.ico&quot;/&gt;https://techblog.woowahan.com/2704/&lt;/div&gt;&lt;/div&gt;&lt;img class=&quot;bookmark-image&quot; src=&quot;https://techblog.woowahan.com/wp-content/uploads/2021/06/screenshot.jpg&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;&lt;html&gt;&lt;body&gt;&lt;br/&gt;&lt;p class=&quot;&quot;&gt;Uploaded by &lt;mark class=&quot;highlight-orange&quot;&gt;&lt;a href=&quot;https://github.com/jmjeon94/N2T&quot;&gt;N2T&lt;/a&gt;&lt;/mark&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;&lt;/div&gt;&lt;/article&gt;&lt;/body&gt;</description>
      <category>iOS Develop</category>
      <category>Alamofire</category>
      <category>ios</category>
      <category>Moya</category>
      <category>Network</category>
      <category>Swift</category>
      <category>urlsession</category>
      <category>스위프트</category>
      <author>성재's</author>
      <guid isPermaLink="true">https://whtjdwo78.tistory.com/27</guid>
      <comments>https://whtjdwo78.tistory.com/27#entry27comment</comments>
      <pubDate>Tue, 14 Feb 2023 15:08:28 +0900</pubDate>
    </item>
    <item>
      <title>iOS [Swift] - FileManager를 이용해서 파일 다운로드 후 저장하기</title>
      <link>https://whtjdwo78.tistory.com/25</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;내용을 살펴보기에 앞서 Apple 공식 문서에 정의된 FileManager에 대해 짚고 넘어가보겠습니다 :)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;&lt;b&gt;FileManager&lt;/b&gt;&lt;/u&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FileManager Class는 shared file manager object에 편리한 접근을 제공합니다.&lt;/li&gt;
&lt;li&gt;File manager object는 일반적으로 파일 시스템과 상호 작용하는 것을 기본 모드로 합니다.&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;따라서, 저희는 이를 통해 파일 &amp;amp; 디렉토리를 찾고, 만들고, 복사하고, 이동할 수 있습니다.&lt;/li&gt;
&lt;li&gt;그리고 또 파일 &amp;amp; 디렉토리에 대한 정보를 얻거나 속성의 일부를 변경할 때 사용할 수 있습니다.&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만약에 파일이나 디렉토리를 이동, 복사, 연결, 제거하는 경우 file manager object와 함께 delegate를 사용하여 작업 관리를 할 수 있습니다. delegate의 역할은 작업을 확인하고, 오류가 발생할 때 진행할지 말지에 대한 여부를 결정하는 것입니다.&lt;/li&gt;
&lt;li&gt;iOS 5.0 이상 &amp;amp; macOS 10.7 이상에서 FileManager에는 iCloud에 저장된 항목을 관리하는 메서드가 포함되어 있습니다.&lt;/li&gt;
&lt;li&gt;따라서, cloud 저장소로 태그가 지정된 파일이나 디렉토리는 iCloud에 동기화돼서 사용자의 iOS 장비나 mac에서 사용할 수 있습니다.&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;이제 FileManager에 대한 개념을 살펴 보았으니 다음 단계로 진행해보겠습니다. ㅎㅎ&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;저는 &quot;회사 자산 관리 시스템의 매뉴얼 ppt&quot; 다운로드를 FileManager를 사용해서 아이폰 &amp;gt; 파일 에 저장해보도록 할 것입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;따라서, ppt를 다운로드 하는 과정은 Alamofire를 이용할 것이고, 다운로드 된 파일의 경로 설정은 FileManager를 이용할 것입니다.  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;가장 먼저!! 우리는 FileManager를 통해 내 휴대폰의 경로를 찾아내고 그 곳에 파일을 생성하거나 수정하거나 다운로드 할 것이기 때문에..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;info.plist에 그것의 사용에 대한 permission(?)을 YES로 설정해주어야 합니다.   (Alamofire를 위해 네트워크 설정하는 것은 또 별도이기 때문에 그 것에 대한 설정도 추가해주시길 바랍니다. ㅎㅎ)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;SO!! 다음과 같이 값을 추가해주세용. (mac에서 휴대폰 연결하고 파일에서도 확인하고 싶으시다면, Application supports iTunes file sharing -&amp;gt; YES 처리 해주세용)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1048&quot; data-origin-height=&quot;34&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PHEfh/btrWyMqOHBd/muEJPFwHNAS5cO6Zne226k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PHEfh/btrWyMqOHBd/muEJPFwHNAS5cO6Zne226k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PHEfh/btrWyMqOHBd/muEJPFwHNAS5cO6Zne226k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPHEfh%2FbtrWyMqOHBd%2FmuEJPFwHNAS5cO6Zne226k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1048&quot; height=&quot;34&quot; data-origin-width=&quot;1048&quot; data-origin-height=&quot;34&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;이제 준비는 마쳤고, 코드를 살펴 보겠습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;아래 코드는 &lt;b&gt;download~~(url: URL, fileName: String, completion: @escaping () -&amp;gt; Void)&lt;/b&gt; 형태의 메소드로 감싸져 있는 점 참고 부탁드립니다 :)&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674008578178&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    // FileManager의 인스턴스를 생성합니다.
    let fileManager = FileManager.default
    
    // 사용자 기기의 document 디렉토리의 경로를 가져온다. 
    // 인자의 for 부분을 통해 다양한 디렉토리에 대한 경로를 가져올 수 있으니 SearchPathDirectory 키워드를 참고하시면 좋을 것 같습니다. :)
    let appURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
    
    // 위에서 사용자의 경로를 가져온 후, 맨 뒤에 저장할 파일의 이름을 저장하는 것입니다. 
    let fileURL = appURL.appendingPathComponent(&quot;csj시스템 사용법.pptx&quot;)
    
    // 최종적으로 파일이 저장될 위치에 대한 목적지 정보!!
    let destination: DownloadRequest.Destination = { _, _ in
      return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
    }&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1674008681995&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	// AlamoFire를 이용한 File Download
    AF.download(url,
                method: .get,
                parameters: nil,
                encoding: JSONEncoding.default,
                to: destination).downloadProgress { (progress) in
	  // 설치의 진행도를 알 수 있다. 이를 가지고 시각화하여 사용자에게 제공해도 좋다.                
      print(progress.fractionCompleted)
    }.response{ response in
      if response.error != nil {
        print(&quot;파일다운로드 실패&quot;)
      }else{
        print(&quot;파일다운로드 완료&quot;)
        completionHandler()
      }
    }&lt;/code&gt;&lt;/pre&gt;</description>
      <category>iOS Develop</category>
      <category>FileManager</category>
      <category>ios</category>
      <category>Swift</category>
      <category>스위프트</category>
      <category>아이폰</category>
      <category>파일매니저</category>
      <author>성재's</author>
      <guid isPermaLink="true">https://whtjdwo78.tistory.com/25</guid>
      <comments>https://whtjdwo78.tistory.com/25#entry25comment</comments>
      <pubDate>Wed, 18 Jan 2023 13:21:34 +0900</pubDate>
    </item>
  </channel>
</rss>