<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>멋있게걷는방법</title>
    <link>https://dohyeon-dev.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sat, 1 Aug 2026 18:47:12 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>도현D</managingEditor>
    <item>
      <title>[Flutter] 출시 시 firebase 로그인 안 될 때</title>
      <link>https://dohyeon-dev.tistory.com/16</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;출시는 성공했지만 firebase 로그인이 되지 않을 때!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많이들 sha키를 제대로 확인하라고 하지만, 만약 처음 앱을 올리는 게 아니라 이미 앱이 배포되어 있고 두 번째 시도일 때는 이유가 다릅니다.&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;안드로이드는 한 번 출시하면 두 번째부터는 추가해줘야하는 sha 키가 있는데 이걸 firebase에 추가해 줘야 로그인이 가능합니다.&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;1. 먼저 google play console에 가셔서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 설정 -&amp;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;앱 서명 키 인증서 섹션에 보시면 SHA-1 인증서 지문과 SHA-256 지문이 있을 거예요.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 firebase -&amp;gt; 프로젝트 설정 -&amp;gt; 내 앱 -&amp;gt; android -&amp;gt; 디지털 지문 추가에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가해 주시고 google-services.json을 다시 다운로드한 후 프로젝트에 적용시키면 로그인이 성공하는 걸 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>도현D</author>
      <guid isPermaLink="true">https://dohyeon-dev.tistory.com/16</guid>
      <comments>https://dohyeon-dev.tistory.com/16#entry16comment</comments>
      <pubDate>Wed, 24 Jul 2024 19:28:45 +0900</pubDate>
    </item>
    <item>
      <title>[Swift] GC vs ARC (with. Retain Cycle)</title>
      <link>https://dohyeon-dev.tistory.com/15</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #f3c000;&quot;&gt;가장 큰 차이는 참조 카운팅 시점.&lt;/span&gt;&lt;/h2&gt;
&lt;h1 style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;b&gt;GC&lt;/b&gt;&lt;/h1&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;런타임&lt;/b&gt; 중에 메모리 해제 시점을 결정함.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이미 할당된 메모리에서 더 이상 사용하지 않는 메모리를 해제하는 기술.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;런타임에 동작.&lt;/li&gt;
&lt;li&gt;백그라운드에서 실행.&lt;/li&gt;
&lt;li&gt;불확실한 간격으로 발생하기 때문에, 객체가 더 이상 사용되지 않는 정확한 순간에 무조건 해제되는 건 아님.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;발생시점&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;각 영역에 할당된 크기의 메모리가 허용치를 넘을 때&lt;/b&gt; 수행됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;rArr; 개발자가 컨트롤할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;왜?&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;rArr; &lt;b&gt;강제로 GC를 수행시키면 GC를 실행하는 동안 해당 스레드를 제외하고 모든 스레드가 멈춰서 성능에 영향을 줄 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;성능 저하가 발생할 수 있음.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;런타임에 계속해서 메모리를 감시하다가 해제하기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;순환참조 발생 X&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;계속해서 메모리를 감시하기 때문에 인스턴스가 해제될 가능성이 더 높다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;retain cycle 관리 가능.&lt;/li&gt;
&lt;li&gt;백그라운드에서 발생하므로 일반 애플리케이션 흐름의 일부로 수행되는 메모리 작업이 줄어든다. (메모리 성능상 이점)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체의 정확한 release 시점을 알 수 없다.&lt;/li&gt;
&lt;li&gt;런타임에서 인스턴스를 추적하기 때문에 추적, 해제하는 과정에서 오버헤드가 발생.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h1&gt;&lt;b&gt;ARC&lt;/b&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(automatic reference count)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;컴파일 시점&lt;/b&gt;에 인스턴스 해제 시점이 결정되어 있다.&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;성능 저하가 발생하지 않음.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴파일 시점에서 인스턴스 해제 시점이 결정되어 있기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;순환참조&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;순환참조가 발생하면 인스턴스가 메모리에서 영원히 해제되지 않아, 쌓이게 되면 앱이 터질 수 있음. 개발자의 명시적인 설계가 필요함. 이를 위해 (strong, weak, unowned 같은 걸 도입함.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참조 횟수를 추적해 더 이상 참조되지 않는 인스턴스를 메모리에서 해제한다.&lt;br /&gt;(retain, release를 해 retain count(reference count)가 0이 되면 해제)&lt;/li&gt;
&lt;li&gt;런타임 시점에 추가 리소스가 발생하지 않음. (컴파일 시점에 인스턴스 해제 시점을 결정하기 때문)&lt;/li&gt;
&lt;li&gt;백그라운드 처리가 없기 때문에 모바일 장치와 같은 저전력 시스템에 더 효율적이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;순환참조 문제&lt;/li&gt;
&lt;li&gt;Retain cycle 자동 처리 불가능. (개발자가 명시적으로 설계해야 함.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Retain Cycle 자동 처리 불가?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #953b34;&quot;&gt;GC&lt;/span&gt;는 계속 메모리를 감시한다. 객체에 &lt;b&gt;외부 참조가 존재하지 않는 것을 감지하면, 서로를 참조하는 객체 그래프 전체를 버린다.&lt;/b&gt; 때문에 순환참조가 발생하지 않음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데, &lt;span style=&quot;color: #ee2323;&quot;&gt;ARC&lt;/span&gt;는. &lt;b&gt;참조 수를 기반으로 생명 주기를 관리한다. 때문에 retain cycle을 자동으로 처리할 수 없고, 결과적으로 순환참조가 발생할 수 있음.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;외부 참조가 없다?&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;retainCycle_example.png&quot; data-origin-width=&quot;1184&quot; data-origin-height=&quot;846&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DQcD0/btsy44VCnaQ/7qgs8TTq8qSFVaRA7FXmlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DQcD0/btsy44VCnaQ/7qgs8TTq8qSFVaRA7FXmlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DQcD0/btsy44VCnaQ/7qgs8TTq8qSFVaRA7FXmlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDQcD0%2Fbtsy44VCnaQ%2F7qgs8TTq8qSFVaRA7FXmlK%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;443&quot; height=&quot;317&quot; data-filename=&quot;retainCycle_example.png&quot; data-origin-width=&quot;1184&quot; data-origin-height=&quot;846&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 이런 상황일 때,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 인스턴스가 해제(nil) 된다면? (외부 참조가 없어진다면)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;RetainCycle_example2.png&quot; data-origin-width=&quot;1662&quot; data-origin-height=&quot;1488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qdVoq/btsy8roKlG9/fmx0jpGzEV15vfQjJB5QT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qdVoq/btsy8roKlG9/fmx0jpGzEV15vfQjJB5QT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qdVoq/btsy8roKlG9/fmx0jpGzEV15vfQjJB5QT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqdVoq%2Fbtsy8roKlG9%2Ffmx0jpGzEV15vfQjJB5QT0%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;453&quot; height=&quot;406&quot; data-filename=&quot;RetainCycle_example2.png&quot; data-origin-width=&quot;1662&quot; data-origin-height=&quot;1488&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;프로퍼티인 child만 남게 되는데 이 둘은 해제되지 않고 영원히 해제되지 않고 남아있게 된다.&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;ARC의 경우에는&lt;/p&gt;
&lt;pre id=&quot;code_1698129945544&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var a = A()
var b = B()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 생성할 때 retain(+1) 되면서 Retain Count(reference count)가 +1 되고, (현재 1)&lt;/p&gt;
&lt;pre id=&quot;code_1698129995702&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;a.child = b
b.child = a&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 인스턴스를 대입할 때 또 +1 되면서 Retain Count(reference count)가 +1 된다. (현재 2)&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;인스턴스를 nil로 바꾸면서 release(-1) 되면서 Retain Count(reference count)가 1이 된다. (현재 1)&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;Retain Count(reference count)가 0이 될 때 메모리가 전부 해제되니까. &lt;b&gt;순환참조 발생.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;중요!!!&lt;/span&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그니까 GC는 이런 상황일 때 참조 객체 그래프 전체를 버려버리니까 순환참조가 발생하지 않고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ARC는 참조수로 생명 주기를 관리하기 때문에 순환참조가 발생하는 것. &amp;rarr; 때문에 weak, unkowned로 관리하는 것.&lt;/p&gt;</description>
      <category>iOS</category>
      <category>arc</category>
      <category>Automatic Reference Count</category>
      <category>garbage collection</category>
      <category>gc</category>
      <category>rc</category>
      <category>retain cycle</category>
      <category>Swift</category>
      <category>Xcode</category>
      <author>도현D</author>
      <guid isPermaLink="true">https://dohyeon-dev.tistory.com/15</guid>
      <comments>https://dohyeon-dev.tistory.com/15#entry15comment</comments>
      <pubDate>Tue, 24 Oct 2023 15:54:48 +0900</pubDate>
    </item>
    <item>
      <title>[Tuist] Firebase 에러 해결(with. _OBJC_CLASS_$_JSContext)</title>
      <link>https://dohyeon-dev.tistory.com/14</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제는 Tuist를 이용해 SPM을 사용하면서, Firebase SDK Library를 추가하면서 생긴 에러입니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;해결법&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일단 가장 간단한 방법은&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Targets -&amp;gt; Build Phases -&amp;gt; Link Binary With Libraries에&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;JavaScriptCore.framework&lt;/span&gt;를 추가하면 해결됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일단 저의 경우는 Tuist를 쓰고 있기 추가했더라도 generate를 하게 되면JavaScriptCore.framework가&amp;nbsp;다시 사라져 근본적으로 해결할 순 없습니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Tuist에 추가하기&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;현재 Library를 추가하려는 모듈에서, dependency에 추가해야 합니다.&amp;nbsp;&lt;br /&gt;아래와 같이 TargetDepency의 sdk를 사용해 추가하면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-09-21 오전 9.55.13.png&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IyPou/btsuG7KaecI/Wr1guUjx2DLiKo0fpzM050/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IyPou/btsuG7KaecI/Wr1guUjx2DLiKo0fpzM050/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IyPou/btsuG7KaecI/Wr1guUjx2DLiKo0fpzM050/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIyPou%2FbtsuG7KaecI%2FWr1guUjx2DLiKo0fpzM050%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;435&quot; height=&quot;283&quot; data-filename=&quot;스크린샷 2023-09-21 오전 9.55.13.png&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;776&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;주의&lt;/h4&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;type을 framework로 지정해 주면 자동으로 name 뒤에. framework가 붙기 때문에&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;JavaScriptCore.framework로 쓰면 에러가 발생합니다. (생성 시 JavaScriptCore.framework.framework로 생기게 됨)&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;- 따라서 name엔 &lt;b&gt;JavaScriptCore&lt;/b&gt;만 써주면 됩니다.&lt;/p&gt;</description>
      <category>Tuist</category>
      <author>도현D</author>
      <guid isPermaLink="true">https://dohyeon-dev.tistory.com/14</guid>
      <comments>https://dohyeon-dev.tistory.com/14#entry14comment</comments>
      <pubDate>Thu, 21 Sep 2023 09:57:42 +0900</pubDate>
    </item>
    <item>
      <title>[Swift] Override함수에서 Super는 필수일까? (with. layoutSubViews)</title>
      <link>https://dohyeon-dev.tistory.com/13</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기본적으로 super 키워드는 상위 뷰를 호출합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어볼게요.&lt;/p&gt;
&lt;pre id=&quot;code_1688230458801&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class A: UITableViewCell {
    override func layoutSubviews() {
        super.layoutSubviews()
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 제가 UITableViewCell을 상속하고 있는 &lt;span style=&quot;color: #f3c000;&quot;&gt;A&lt;/span&gt;라는 클래스에 있는 layoutSubview override 함수에서 super를 통해 &lt;span style=&quot;color: #ee2323;&quot;&gt;super.layoutSubviews()를&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;super는 상위 뷰를 호출한다고 했죠?&lt;br /&gt;현재 상속 중인 클래스는 UITableViewCell입니다. &lt;br /&gt;그럼 호출되는 건 &lt;b&gt;UITableView의 상위 뷰인 UIView의 layoutSubviews가 호출되겠죠!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;super 가 뭘 하는 녀석인 줄은 알고 있었지만 이렇게 자세히 파본건 처음입니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;여기서부턴 제 경험에 대한 얘기입니다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 글을 쓰게 된 이유는 프로젝트를 하면서 contentView의 inset을 변경해야 하는 일이 있었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-02 오전 1.59.11.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wld80/btsl2nUqpoI/IKg5Jpsxlgul2YkHQlnXj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wld80/btsl2nUqpoI/IKg5Jpsxlgul2YkHQlnXj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wld80/btsl2nUqpoI/IKg5Jpsxlgul2YkHQlnXj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwld80%2Fbtsl2nUqpoI%2FIKg5Jpsxlgul2YkHQlnXj0%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;433&quot; height=&quot;135&quot; data-filename=&quot;스크린샷 2023-07-02 오전 1.59.11.png&quot; data-origin-width=&quot;1672&quot; data-origin-height=&quot;522&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;/p&gt;
&lt;pre id=&quot;code_1688230791514&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    override func layoutSubviews() {
        super.layoutSubviews()
        contentView.frame = contentView.frame.inset(by: UIEdgeInsets(top: 0, left: 15, bottom: 16, right: 15))
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는.. super.layoutSubviews()를 적지 않아서 며칠 동안 고생했습니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 오히려 문제를  분석해 볼 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 문제는 TableViewCell을 만질 때마다 cell 이 움직이는 문제가 있었습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignLeft&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/bsRB0v/btsl0kdoH6r/xN3VDO73yBZLsAoxA5FGh0/Simulator_Screen_Recording_-_iPhone_14_Pro_-_2023-06-30_at_12.19.22%20%281%29.mp4?attach=1&amp;amp;knm=tfile.mp4&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;Simulator_Screen_Recording_-_iPhone_14_Pro_-_2023-06-30_at_12.19.22 (1).mp4&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;3.49MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1688230984187&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    override func layoutSubviews() {
        contentView.frame = contentView.frame.inset(by: UIEdgeInsets(top: 0, left: 15, bottom: 16, right: 15))
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 코드는 super를 통해 상위 뷰를 호출하지 않은 위와 같은 코드였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;원인은 이러했습니다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;layoutSubviews&lt;/b&gt;는 layout이 변경될 때마다 호출되는데 &lt;br /&gt;제가 아까 `cell을 만질 때마다`라고 했던 말은&amp;nbsp; cell을  스와이프 하거나 등의 동작을 얘기합니다.&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;즉. contentView에 inset을 계속해서 더해준 거죠.. 아래는 &lt;b&gt;contentView.frame입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-02 오전 1.46.55.png&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QMjaN/btsl1yWseXr/44VgdZ8YK9QJki2z3YWiY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QMjaN/btsl1yWseXr/44VgdZ8YK9QJki2z3YWiY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QMjaN/btsl1yWseXr/44VgdZ8YK9QJki2z3YWiY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQMjaN%2Fbtsl1yWseXr%2F44VgdZ8YK9QJki2z3YWiY1%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;593&quot; height=&quot;231&quot; data-filename=&quot;스크린샷 2023-07-02 오전 1.46.55.png&quot; data-origin-width=&quot;593&quot; data-origin-height=&quot;231&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;이렇게 해결했습니다.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 super의 개념을 적용시켰습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 &lt;b&gt;layoutSubviews는&lt;/b&gt; 공식 문서에 의하면 이러한 일을 합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;the default implementation uses any constraints you have set to determine the size and position of any subviews.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;- &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;기본 구현에서는 사용자가 설정한 제약 조건을 사용하여 하위 보기의 크기와 위치를 결정합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;그니까. super.layoutSubviews()를 호출하고 -&amp;gt; content inset을 변경해 주면,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;기본적으로 설정했던 layout으로 초기화되고 -&amp;gt; content inset 이 변경된다!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;라고 이해했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;아래는 문제를 해결한 후 &lt;b&gt;contentView.frame입니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-02 오전 1.47.27.png&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nExlQ/btsl9MlkGIU/d8eWMH5fnCAMK6dvOC9vAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nExlQ/btsl9MlkGIU/d8eWMH5fnCAMK6dvOC9vAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nExlQ/btsl9MlkGIU/d8eWMH5fnCAMK6dvOC9vAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnExlQ%2Fbtsl9MlkGIU%2Fd8eWMH5fnCAMK6dvOC9vAK%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;583&quot; height=&quot;194&quot; data-filename=&quot;스크린샷 2023-07-02 오전 1.47.27.png&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;194&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323; background-color: #dddddd;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;혹시나 틀린 부분이 있다면 알려주세요!! 제발  &lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;마무리.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;많은 삽질을 했지만, 결국은 기본적인 실수였고, 하지만 그 과정에서 오늘도 &lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;배운 점이 있었습니다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;발생한 이슈를 근본적 원인을 찾고 분석하면서 해결해 나가는 과정은 늘 새롭고 재밌는 것 같습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;이런 과정들이 쌓인다면 분명 좋은 개발자가 될 수 있지 않을까 기대해 봅니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd;&quot;&gt;&lt;span style=&quot;background-color: #fdfdfd; color: #000000; text-align: start;&quot;&gt;읽어주셔서 감사합니다. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>iOS</category>
      <category>layoutSubviews</category>
      <category>Override</category>
      <category>super</category>
      <category>Swift</category>
      <category>개발자</category>
      <author>도현D</author>
      <guid isPermaLink="true">https://dohyeon-dev.tistory.com/13</guid>
      <comments>https://dohyeon-dev.tistory.com/13#entry13comment</comments>
      <pubDate>Sun, 2 Jul 2023 02:28:54 +0900</pubDate>
    </item>
    <item>
      <title>App Store 배포 리젝 사유 회고 2.1 , 1.2</title>
      <link>https://dohyeon-dev.tistory.com/12</link>
      <description>&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #111111; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Guideline 2.1 - Information Needed&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;In addition to the demo account you provided, we still need a demo phone number and authentication code to verify the registration process in your app.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;해당 리젝 사유는 한 마디로&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;'&lt;b&gt;나 회원가입 테스트할 건데 테스트용 전화번호랑 인증코드 줘'라는&lt;/b&gt; 의미입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;따라서 서버에서 테스트용 전화번호와 해당 전화번호일 때 성공할 수 있는 인증번호를 임의로 설정해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;ex) 전화번호가 01011110000 일 때 인증번호가 0000 이면 성공. 와 같은 로직을 작성해야 한다.&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;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #111111; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Guideline 1.2 - Safety - User Generated Content&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;We found that your app includes user-generated content but does not have all the required precautions. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Next Steps&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;To resolve this issue, please revise your app to implement the following precautions:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;- Require that users agree to terms (EULA) and these terms must make it clear that there is no tolerance for objectionable content or abusive users&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 리젝 사유는 마지막 줄&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;'&lt;b&gt;사용자가 약관(EULA)에 동의하도록 요구하고 이러한 약관은 불쾌한 콘텐츠나 악의적인 사용자를 용납하지 않는다는 점을 명확히 해야 합니다.' &lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;즉 약관을 동의할 수 있도록 기능을 구현하고, 약관 동의를 작성한 페이지에&lt;b&gt; '불쾌한 콘텐츠나 악의적인 사용자는 제재를 받을 수 있다.&lt;/b&gt; '와 같은 내용을 포함시켜 주면 해결할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-27 오후 4.16.29.png&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xWaZB/btslw7ZfNhp/hIoQL11VEyRvExvEXXacV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xWaZB/btslw7ZfNhp/hIoQL11VEyRvExvEXXacV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xWaZB/btslw7ZfNhp/hIoQL11VEyRvExvEXXacV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxWaZB%2Fbtslw7ZfNhp%2FhIoQL11VEyRvExvEXXacV0%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;1472&quot; height=&quot;184&quot; data-filename=&quot;스크린샷 2023-06-27 오후 4.16.29.png&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;184&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;</description>
      <category>iOS</category>
      <category>App Connect</category>
      <category>AppStore</category>
      <category>HIG</category>
      <category>human interface guidelines</category>
      <category>Swift</category>
      <category>Xcode</category>
      <author>도현D</author>
      <guid isPermaLink="true">https://dohyeon-dev.tistory.com/12</guid>
      <comments>https://dohyeon-dev.tistory.com/12#entry12comment</comments>
      <pubDate>Tue, 27 Jun 2023 16:18:34 +0900</pubDate>
    </item>
    <item>
      <title>App Store 배포 회고(with. 개발 &amp;amp; 책임)</title>
      <link>https://dohyeon-dev.tistory.com/11</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저의 두 번째 프로젝트를 개발, 출시하며 들었던 생각과 고민들에 대해 적어보려고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로젝트는 원래는 한 달짜리 프로젝트였지만, TestFlight를 통해 팀원끼리 테스트도 하며 피드백을 통해 요구사항을 추가됐고, 디자인도 변경되면서 기간이 길어졌습니다.&lt;br /&gt;팀원들은 '&lt;b&gt;일단 배포하고 v2에서 고치자~'라는&lt;/b&gt; 말을 자주 했는데요. 사실 이 말이 어쩌면 맞을지도 모릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빠른 앱 출시를 시도한다면, 앱스토어 배포 과정에서도 reject 사유를 알 수 있고, 또 만약 reject 없이 바로 앱이 출시된다 하더라도&lt;br /&gt;사용자들로부터 얻는 피드백을 통해 앱의 퀄리티를 높일 수도 있겠죠. &lt;br /&gt;(reject 사유를 알 수 있다는 건 큰 이점이란 걸 이번에 reject을 4번 당하면서 깨달았습니다. ㅎㅎ)&lt;br /&gt;&lt;br /&gt;그러나 제 생각은 달랐습니다.&lt;b&gt; '낮은 퀄리티의 앱을 굳이 배포해서 사용자들에게 보여줄 필요가 있는가?'였습니다.&lt;/b&gt; 물론 많은 사용자가 저희의 프로젝트를 사용하지 않을 수도 있죠. 또 그 과정에서 얻는 피드백 등으로 성장할 수 있습니다. &lt;br /&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;마지막으로..&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 프로젝트에선 유저 리텐션 같은 개발 외적인 부분은 고민해보지 않고 프로젝트를 진행했던 게 아쉬움이 남습니다. 하지만, 앞으로의 프로젝트에선 나의 책무가 무엇인지 더 고민해 보고 프로젝트 전반에 대해 깊게 고민해 볼 수 있을 것 같습니다. 개발을 하는 것도 중요하지만 너무 나무만 보고 있던 게 아니었나 싶습니다.. 고려해야 할 부분들이 많더라고요(유저 리텐션 늘리기, 피드백 유도...) 이제는 숲을 보는 넓은 시선으로 개발뿐만 아니라 다른 곳에도 신경 써서 더 높은 퀄리티의 제품을 만들어내고 싶습니다. 너무 뿌듯했고, 기대됩니다. 다른 분들도 이런 부분에서 고민해 보면 좋을 것 같아요.  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각나는 대로 적은 거라 이 글은 언제든 추가/수정이 있을 수 있습니다!&lt;/p&gt;</description>
      <category>iOS</category>
      <category>App Connect</category>
      <category>app store</category>
      <category>ios</category>
      <category>Swift</category>
      <category>회고</category>
      <author>도현D</author>
      <guid isPermaLink="true">https://dohyeon-dev.tistory.com/11</guid>
      <comments>https://dohyeon-dev.tistory.com/11#entry11comment</comments>
      <pubDate>Sun, 25 Jun 2023 22:39:34 +0900</pubDate>
    </item>
    <item>
      <title>[Swift] 지금 바로 Pagination 을 적용해야 하는 이유</title>
      <link>https://dohyeon-dev.tistory.com/10</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에 단순 데이터를 불러오는 게 아닌, page 단위로 불러오면 메모리 효율을 아낄 수 있는데요,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 바로 &lt;code&gt;Pagination&lt;/code&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;Pagination 은 메모리 효율을 아낄 수 있다고 했는데, 그 이유는 뭘까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;들어가기 전에,&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tableView의 delegate, datasource로 tableView를 구성했다면 대부분&lt;br /&gt;&lt;code&gt;dequeueReusableCell를&lt;/code&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;만약 Rx를 쓴다면?&lt;/p&gt;
&lt;pre id=&quot;code_1686152823954&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.drive(postTableView.rx.items(cellIdentifier: PostCell.identifier,
                              cellType: PostCell.self)) { (row, data, cell) in&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 쉽게 구현할 수 있었을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 본론으로 들어가서,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Pagination을 사용하면 얻는 장점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(대부분 일정 범위까지의 데이터만 로드하기 때문에 얻는 장점입니다.)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 효율적인 데이터 로딩&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존엔 모든 데이터를 불러왔다면 Pagination 을 적용하면 현재 보이는, 또는 일정 범위까지의 데이터만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로드하기 때문에 로딩 시간을 크게 줄일 수 있습니다. 예를 들어 &lt;b&gt;인터넷이 느리거나 규모가 큰 대량의 데이터를 다룰 때 유용합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 메모리 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tableView를 띄운다면 내가 볼 수 없는 곳까지의 데이터를 굳이 불러오는 건 메모리 낭비겠죠? Pagination을 사용하면 &lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;필요한 페이지만 로드하여 &lt;b&gt;메모리 사용을 최적화&lt;/b&gt;할 수 있습니다. &lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;또한 필요하지 않은 데이터를 메모리에 유지하지 않아도 되므로 &lt;b&gt;앱의 메모리 사용량을 줄일 수 있습니다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;3. 캐싱 &amp;amp; 재사용&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;pagination 은 페이지 단위로 데이터를 처리하기 때문에 각 페이지를 &lt;b&gt;캐싱하고 재사용&lt;/b&gt;할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt;예를 들어 첫 번째 페이지를 로딩을 완료했는데 네트워크 연결이 끊어졌다면,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: left;&quot;&gt; 첫 번째 페이지의 데이터는 캐싱된 메모리를 통해 보일 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 제가 직접 프로젝트에 Pagination을 적용시키면서 확인한 메모리 사용량 비교입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(response는 title, content, image1, image 2, voteCount, commentCount 이렇게 구성되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;image의 종류에 따라 메모리가 크게 변할 수 있음.)&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;(Before, After는 서로 비슷한 환경에서 테스트함.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Before&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqpH95/btsi5B1CyKF/4DeGCsFp5hD4cP3sw9QTz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqpH95/btsi5B1CyKF/4DeGCsFp5hD4cP3sw9QTz0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;552&quot; data-origin-height=&quot;686&quot; data-filename=&quot;스크린샷 2023-04-20 오후 3.56.55.png&quot; width=&quot;275&quot; data-widthpercent=&quot;47.8&quot; height=&quot;342&quot; style=&quot;width: 47.2452%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqpH95/btsi5B1CyKF/4DeGCsFp5hD4cP3sw9QTz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqpH95%2Fbtsi5B1CyKF%2F4DeGCsFp5hD4cP3sw9QTz0%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;552&quot; height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0bWtH/btsi2Hvi2rY/YkCJWUARyPrEo9uWXQuWOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0bWtH/btsi2Hvi2rY/YkCJWUARyPrEo9uWXQuWOk/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;594&quot; data-origin-height=&quot;676&quot; data-filename=&quot;스크린샷 2023-04-20 오후 3.56.34.png&quot; width=&quot;275&quot; height=&quot;313&quot; data-widthpercent=&quot;52.2&quot; style=&quot;width: 51.592%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0bWtH/btsi2Hvi2rY/YkCJWUARyPrEo9uWXQuWOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0bWtH%2Fbtsi2Hvi2rY%2FYkCJWUARyPrEo9uWXQuWOk%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;594&quot; height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;After&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnIeFb/btsi2Scf6X4/7oyqsIE9g4dsQxPBn4iMPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnIeFb/btsi2Scf6X4/7oyqsIE9g4dsQxPBn4iMPK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;648&quot; data-filename=&quot;스크린샷 2023-04-20 오후 3.54.29.png&quot; width=&quot;275&quot; height=&quot;294&quot; style=&quot;width: 55.6167%; margin-right: 10px;&quot; data-widthpercent=&quot;56.27&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnIeFb/btsi2Scf6X4/7oyqsIE9g4dsQxPBn4iMPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnIeFb%2Fbtsi2Scf6X4%2F7oyqsIE9g4dsQxPBn4iMPK%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;606&quot; height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhj64K/btsi3bbOCtw/H9j96umKkBffWd4GLYLl4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhj64K/btsi3bbOCtw/H9j96umKkBffWd4GLYLl4k/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;688&quot; data-filename=&quot;스크린샷 2023-04-20 오후 3.55.12.png&quot; width=&quot;275&quot; height=&quot;378&quot; style=&quot;width: 43.2205%;&quot; data-widthpercent=&quot;43.73&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhj64K/btsi3bbOCtw/H9j96umKkBffWd4GLYLl4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbhj64K%2Fbtsi3bbOCtw%2FH9j96umKkBffWd4GLYLl4k%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;500&quot; height=&quot;688&quot;/&gt;&lt;/span&gt;&lt;/div&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(테스트 당시에 데이터 개수가 많지는 않았습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좀 더 많은 데이터를 갖고 체크해 봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Before, After와 다른 환경입니다. (데이터 크기, 내용..))&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-06-08 오전 1.19.09.png&quot; data-origin-width=&quot;548&quot; data-origin-height=&quot;698&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crIGOO/btsi4MWFQAA/6eB74Xj22EAdkbKHTFEnaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crIGOO/btsi4MWFQAA/6eB74Xj22EAdkbKHTFEnaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crIGOO/btsi4MWFQAA/6eB74Xj22EAdkbKHTFEnaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrIGOO%2Fbtsi4MWFQAA%2F6eB74Xj22EAdkbKHTFEnaK%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;275&quot; height=&quot;350&quot; data-filename=&quot;스크린샷 2023-06-08 오전 1.19.09.png&quot; data-origin-width=&quot;548&quot; data-origin-height=&quot;698&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 많아도 한 번에 모든 데이터를 로드하지 않고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt; 정해진 범위 내의 데이터만 로드하기 때문에 효율적으로 메모리를 관리할 수 있는 것 같습니다!&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;추가로&amp;nbsp; 참고하면 좋은 것&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 애플 기본 갤러리에 있는 이미지는 생각보다 많은 메모리를 차지한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 스크롤 속도에 따라 그래프 모양은 달라질 수 있으니 참고하시길..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS</category>
      <category>Instruments</category>
      <category>pagination</category>
      <category>Swift</category>
      <category>Xcode</category>
      <author>도현D</author>
      <guid isPermaLink="true">https://dohyeon-dev.tistory.com/10</guid>
      <comments>https://dohyeon-dev.tistory.com/10#entry10comment</comments>
      <pubDate>Thu, 8 Jun 2023 01:28:21 +0900</pubDate>
    </item>
    <item>
      <title>[Tuist] Tuist Action 사용하기 [with. fetch Error]</title>
      <link>https://dohyeon-dev.tistory.com/9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 Github Action으로 CI를 구축할 땐 아래처럼 yml을 작성했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1682898753459&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;name: Swift

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:

    runs-on: macos-latest

    steps:
    - uses: actions/checkout@v3
      with:
        xcode-version: latest
    - name: install tuist
      run: curl -Ls https://install.tuist.io | bash
    - name: project Generate
      run: |
        rm -rf .package.resolved
        tuist generate
    - name: Build
      run: |
        xcodebuild -project Choice.xcodeproj -scheme Choice -destination 'platform=iOS Simulator,name=iPhone 11 Pro,OS=latest'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Tuist 에선 Tuist Action 이라는 것을 지원하는데요,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tuist Action 을 사용하면 더욱 간결한 코드를 아래와 같이 작성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1682898938501&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;name: Swift

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

jobs:
  build:
    name: Build
    runs-on: macos-latest
    steps:
        - uses: actions/checkout@v3
        - uses: tuist/tuist-action@0.13.0
          with:
            command: 'fetch'
            arguments: ''
        - uses: tuist/tuist-action@0.13.0
          with:
            command: 'build'
            arguments: ''&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;actions/checkout@v3&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;checkout 은 Github 에 올라가 있는 코드를 CI 서버로 내려받는 것이라고 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 Github Action 을 쓸 때 이 checkout 명령어는 필수적이다라고 생각하면 될 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뒤에 @v3 는 버전이므로 되도록 최신버전에 맞추는 것을 추천드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Tuist 는 버전이 자주 바뀌어서 팀원들과 맞추는 게 좋다고 하네요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;tuist/tuist-action@0.13.0&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 액션을 사용하면 프로젝트를 빌드, 배포하기 위해 필요한 구성을 직접 할 필요가 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 yml처럼 tuist 를 설치하고 generate 하고 어떻게 run 할 건지 직접 할 필요가 없는 것입니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- fetch&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외부 Dependency 를 불러오는 작업입니다.&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;- build&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 빌드합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-05-01 오전 9.18.38.png&quot; data-origin-width=&quot;2422&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnFStj/btsddHIp2cm/WZTkbiImgTmmF9NCbYXEW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnFStj/btsddHIp2cm/WZTkbiImgTmmF9NCbYXEW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnFStj/btsddHIp2cm/WZTkbiImgTmmF9NCbYXEW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnFStj%2FbtsddHIp2cm%2FWZTkbiImgTmmF9NCbYXEW0%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;2422&quot; height=&quot;166&quot; data-filename=&quot;스크린샷 2023-05-01 오전 9.18.38.png&quot; data-origin-width=&quot;2422&quot; data-origin-height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;build 과정에선 코드의 warning과 Error에 대한 설명을 해주는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 따라해도&amp;nbsp; 몇몇 분들은 에러가 나실 텐데..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약,&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1682900525943&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Error: command failed: /Users/runner/work/Project_name/tuistexec fetch&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와 같은 &lt;b&gt;fetch 과정에서 에러가 난다면&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 tuist version을 확인해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. tuist local&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-05-01 오전 9.23.25.png&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pYMiU/btsdemcGGbW/5zWRGlfquK5wVeFawe9yi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pYMiU/btsdemcGGbW/5zWRGlfquK5wVeFawe9yi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pYMiU/btsdemcGGbW/5zWRGlfquK5wVeFawe9yi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpYMiU%2FbtsdemcGGbW%2F5zWRGlfquK5wVeFawe9yi0%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;576&quot; height=&quot;372&quot; data-filename=&quot;스크린샷 2023-05-01 오전 9.23.25.png&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;372&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어를 통해 로컬 환경 버전을 찾습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. tuist local 최신버전&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-05-01 오전 9.24.19.png&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JTt6o/btsdlrKSS8u/yPiVxyHMHCiQ90VOLgi7o1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JTt6o/btsdlrKSS8u/yPiVxyHMHCiQ90VOLgi7o1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JTt6o/btsdlrKSS8u/yPiVxyHMHCiQ90VOLgi7o1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJTt6o%2FbtsdlrKSS8u%2FyPiVxyHMHCiQ90VOLgi7o1%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;771&quot; height=&quot;69&quot; data-filename=&quot;스크린샷 2023-05-01 오전 9.24.19.png&quot; data-origin-width=&quot;1274&quot; data-origin-height=&quot;114&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어를 통해 local version을. tuist-version에 생성해 줍니다.&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;이렇게 해주면. tuist-version 파일이 생기고 내부에는 위에서 설정해 준 local version 이 쓰여있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-05-01 오전 9.25.42.png&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;364&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btdqwp/btsdtFaDV6d/fRCDsWyRrZtelQTfZBsEb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btdqwp/btsdtFaDV6d/fRCDsWyRrZtelQTfZBsEb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btdqwp/btsdtFaDV6d/fRCDsWyRrZtelQTfZBsEb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbtdqwp%2FbtsdtFaDV6d%2FfRCDsWyRrZtelQTfZBsEb1%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;348&quot; height=&quot;237&quot; data-filename=&quot;스크린샷 2023-05-01 오전 9.25.42.png&quot; data-origin-width=&quot;534&quot; data-origin-height=&quot;364&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이걸 commit -&amp;gt; push 해주면 CI 가 다시 실행되면서 에러가 해결됩니다!  &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;ref.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/tuist/tuist-action/issues/6&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/tuist/tuist-action/issues/6&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.tuist.io/guides/continuous-integration/#github-actions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.tuist.io/guides/continuous-integration/#github-actions&lt;/a&gt;&lt;/p&gt;</description>
      <category>Tuist</category>
      <category>Github-Action</category>
      <category>SPM</category>
      <category>Swift</category>
      <category>Tuist</category>
      <category>Tuist-Action</category>
      <author>도현D</author>
      <guid isPermaLink="true">https://dohyeon-dev.tistory.com/9</guid>
      <comments>https://dohyeon-dev.tistory.com/9#entry9comment</comments>
      <pubDate>Mon, 1 May 2023 09:30:47 +0900</pubDate>
    </item>
    <item>
      <title>[Swift] firebase - 이메일 중복 검사</title>
      <link>https://dohyeon-dev.tistory.com/8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;firebase에서 이메일 중복을 검사하는 메서는 따로 없는 것 같더라고요..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서,&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이렇게 해봤습니다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 FirebaseAuth를 import 해야겠죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그다음 아래와 같은 코드를 작성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;forEmail에 검사하고 싶은 email(String type)을 넣습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1681268228674&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Auth.auth().fetchSignInMethods(forEmail: &quot;test_email&quot;) { arg, error in
    if let arg = arg {
        print(&quot;등록됨&quot;)
    } else {
        print(&quot;등록 안 됨&quot;)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Authentication에 등록된 이메일이라면 if, 등록되지 않았다면 (사용가능) else가 실행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;arg를 출력해 보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 등록된 이메일이 아니다? = nil&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 등록된 이메일이다? = Optional([&quot;password&quot;])&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가 출력됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS</category>
      <category>authentication</category>
      <category>fetchSignInMethods</category>
      <category>Firebase</category>
      <category>ios</category>
      <category>Swift</category>
      <category>Xcode</category>
      <author>도현D</author>
      <guid isPermaLink="true">https://dohyeon-dev.tistory.com/8</guid>
      <comments>https://dohyeon-dev.tistory.com/8#entry8comment</comments>
      <pubDate>Wed, 12 Apr 2023 12:04:58 +0900</pubDate>
    </item>
    <item>
      <title>[UITest] password textFiled 에 tap 이 안 될 때?</title>
      <link>https://dohyeon-dev.tistory.com/7</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이걸로 하루의 절반을 날렸습니다..&lt;/p&gt;
&lt;pre id=&quot;code_1680598165510&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    private let inputPasswordTextField = UITextField().then {
        $0.accessibilityIdentifier = &quot;inputPasswordTextField&quot;
        $0.placeholder = &quot;비밀번호&quot;
        $0.layer.borderColor = UIColor.clear.cgColor
        $0.layer.borderWidth = 1
        $0.setPlaceholder(color: UIColor.gray)
        $0.layer.cornerRadius = 8
        $0.isSecureTextEntry = true
        $0.backgroundColor = .blue
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 제 passwordTextField 는 이렇습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 바탕으로 UITest 를 시도했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1680598230690&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    override func setUpWithError() throws {
        // Put setup code here. This method is called before the invocation of each test method in the class.

        // In UI tests it is usually best to stop immediately when a failure occurs.
        continueAfterFailure = false
        
        app = XCUIApplication()
        app.launch()

        skipButton = app.buttons[&quot;Skip&quot;]
        emailTF = app.textFields[&quot;inputEmailTextField&quot;]
        passwordTF = app.textFields[&quot;inputPasswordTextField&quot;]
        signInButton = app.buttons[&quot;signInButton&quot;]
    }

    func testSignInViewController_notRegistedUser_isVisibleWarningLabel() {
        skipButton.tap()
        emailTF.tap()
        emailTF.typeText(&quot;asdf123@naver.com&quot;)
        app.tap()
        
        passwordTF.tap()
        passwordTF.typeText(&quot;12345678&quot;)

        XCTAssertEqual(signInButton.isEnabled, true)
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이러한 에러를 마주했습니다ㅠㅠ..&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-04-04 오후 5.51.53.png&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;624&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m7kU1/btr7UJLnaoD/BTyYa07QTJacJnROB94yvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m7kU1/btr7UJLnaoD/BTyYa07QTJacJnROB94yvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m7kU1/btr7UJLnaoD/BTyYa07QTJacJnROB94yvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm7kU1%2Fbtr7UJLnaoD%2FBTyYa07QTJacJnROB94yvK%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;1312&quot; height=&quot;624&quot; data-filename=&quot;스크린샷 2023-04-04 오후 5.51.53.png&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;624&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는..&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;inputPasswordTextField 의 isSecureTextEntry 가 True 이기 때문입니다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결 방법은&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;passwordTF&lt;/span&gt;&lt;span&gt; = &lt;/span&gt;&lt;span&gt;app&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;secureTextFields&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&quot;inputPasswordTextField&quot;&lt;span&gt;]&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 isSecureTextEntry 가 True 라면 secureTextFields 로 설정해주면 에러를 해결할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이런걸로 삽질했다는게 너무 허무하네요..&lt;/span&gt;&lt;/p&gt;</description>
      <category>iOS</category>
      <category>Swift</category>
      <category>UITest</category>
      <author>도현D</author>
      <guid isPermaLink="true">https://dohyeon-dev.tistory.com/7</guid>
      <comments>https://dohyeon-dev.tistory.com/7#entry7comment</comments>
      <pubDate>Tue, 4 Apr 2023 17:57:13 +0900</pubDate>
    </item>
  </channel>
</rss>