<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title> </title>
    <link>https://madilyn.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 27 Jul 2026 17:41:41 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Jungbin</managingEditor>
    <image>
      <title> </title>
      <url>https://tistory1.daumcdn.net/tistory/4096925/attach/a9f72b5efdbc419693787cc3583fc9da</url>
      <link>https://madilyn.tistory.com</link>
    </image>
    <item>
      <title>더 나은 판단을 하려면</title>
      <link>https://madilyn.tistory.com/46</link>
      <description>&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;color: #333333; text-align: start;&quot;&gt;호기롭게 시작했지만 1주 밀리고.. ^^; 일요일 저녁에야 컴퓨터를 잡고 앉았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;고백하자면 사실 이번 주 내내 마땅한 글감을 찾지 못해서 차일피일 미뤘다.&lt;/span&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;span&gt;홍보 업무를 하면서 다양한 지표들이 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;올해 광고를 돌린 지 2주 정도 되었는데, 작년에 광고를 돌렸던 것과 비교하면 월등히(!!) 높은 수치들이 나온다. 업계 평균이라는 수치보다 2-3배 더 좋을 때도 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;거의 상상하지도 못했던 지표여서 처음에는 신나기도 했지만, 조금만 떨어져도 (그래도 여전히 작년보단 낫지만) 소재를 바꿔야 하나? 테스트를 멈출까? 하는 고민이 들기도 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;광고 지표를 보며 항상 고민하는 건, 결국 &quot;잘했다&quot;, &quot;못했다&quot;의 판단을 어떻게 내릴 것인가 하는 문제다. CTR이 1.0%~1.5%면 광고할 만하다고 평가하기도 하고, 그런데 메타/네이버/구글 등 매체마다 평균이 다르기도 하고, 업종마다 천차만별이기도 하다. 평균치를 참고할 수는 있지만 우리 교육 홍보에 그대로 판단의 기준으로 삼기에는 여전히 어렵다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이런 고민 속에 이것저것 찾아보다가 눈에 들어온 글이 있었다. &quot;업계 평균에 얽매이지 말고, 본인 조직의 과거 지표를 바탕으로 판단하라&quot;는 내용이었다. 우리 상황에는 이 방법이 제일 적합한 판단 방식이라는 생각이 들었다. (이때 본 글을 첨부하고 싶지만 잃어버렸다 ...)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;작년 처음 홍보 업무를 맡았을 때는 비교할 과거 수치를 찾기가 힘들어 판단이 더 어려웠다. 올해는 작년의 경험과 데이터를 참고할 수 있어서 그나마 다행이긴 하지만, 담당자가 아니면 파악할 수 없는 형태로 남아있다. 작년에 홍보 결과를 전체적으로 정리하지 못한 것이 큰 아쉬움으로 남는다. 담당자의 기억과 경험에 의존하고 있는 업무라니........... 올해는 좀 더 차곡차곡 잘 쌓아 둬서, 내년 홍보 성과를 측정할 때 좀 더 객관적인 근거를 가지고 판단할 수 있도록 정리해야겠다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;한편으로는 CTR, CPC와 같은 효율 지표만 언제까지 중요하게 생각해야 할지도 고민이다. ㅎㅎㅎㅎ 물론 비용 대비 결과가 좋다는 것은 유의미하지만, 클릭률이 중요한지, 노출이 중요한지, 도달이 중요한지는 결국 홍보의 목적에 따라 달라지는 것 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;예를 들어, 지금은 아직 모집 전이고 모집을 위한 알림 신청을 받고 있는 상황이다. 부스트캠프의 교육 기간이 길어서 대학생들에게 미리 교육의 존재를 알리는 게 중요하다. 그런 측면에서는 클릭도 중요하지만 노출과 도달에 더 신경을 써야 하지 않을까! 이후 실제 지원 기간에는 부캠이라는 교육을 알리는 것도 중요하지만 실제 지원으로 이어지는 것이 더 중요하기 때문에 클릭 중심의 전략을 가져가는 게 맞지 않을까 하는 생각도 든다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;지금 바쁜 업무가 조금 정리되면, 기간별로 어느 지표를 더 중요한 판단 기준으로 삼을지 정리해 보는 시간을 가져야겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;실무를 하다 보면 이것도 중요하고, 저것도 중요하고, 결국 다 중요하게 느껴져서 모든 지표를 한꺼번에 보다가 이도저도 안 되는 상황이 벌어지기도 한다. 이건 아마 조급함과 불안함 때문이 아닐까 싶다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;무엇이 가장 중요한지, 결국 우선순위를 잘 세우는 게 가장 중요하다~!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;✅ 두줄요약 by GPT&lt;/span&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;/p&gt;</description>
      <category>essay</category>
      <author>Jungbin</author>
      <guid isPermaLink="true">https://madilyn.tistory.com/46</guid>
      <comments>https://madilyn.tistory.com/46#entry46comment</comments>
      <pubDate>Sun, 13 Apr 2025 23:27:25 +0900</pubDate>
    </item>
    <item>
      <title>홍보는 누구에게 해야 하는 걸까?</title>
      <link>https://madilyn.tistory.com/44</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;다시 부스트캠프 웹&lt;span style=&quot;background-color: #ffffff; color: #474747; text-align: start;&quot;&gt;&amp;middot;모바일의 교육생을 모집하는 시즌이 돌아왔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요새 일을 하는 시간 중 80%는 고뇌의 시간으로 보내는 것 같다..^^ 홍보 업무를 담당하며 했던 이런저런 생각을 작성해 본다.&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;어떤 홍보물에서든 이것이 여러분에게 효과적이라고 말한다. 특히 명확한 아웃풋을 강조하면서. 예를 들어 다이어트 제품 광고는 '일주일 만에 5kg 감량!!!' 이라든가, 어떠한 자기계발서의 광고는 '이 책을 읽으면 당신의 인생이 변합니다' 라든가.. 이런 아웃풋을 보면 자연스럽게 해당 효과가 적용된 내 모습을 상상하게 된다.&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;사람에 따라서는 5kg 감량이 필요하지 않을 수도 있고, 딱히 인생의 변화가 필요하지 않을 수도 있다. 이런 경우는 본인이 뭘 원하는지 명확히 아는 것 같다. 분명 많은 사람들이 쇼핑할 때 검색하는 행위로 시작한다.&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;그러나 많은 경우 본인이 5kg 감량이 필요한 상태인지 아닌지, 인생의 변화가 필요한지 아닌지에 대해서조차 생각해 두지 않았을 것이라고 생각한다. 그런 경우 홍보 문구를 보면 '어 나도 필요한가?' 라고 생각하게 되는 것 같다. 마치 내가 '인생관을 정립하는 것'에 대해 생각해 보지 않았지만, 우연히 &lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000213816361&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[마인드 박스]&lt;/a&gt; 책의 저자 유튜브 영상을 보며 인생관을 생각하고 정리하는 것이 필요하다고 느꼈던 것처럼..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 홍보는 '어라 다들 다이어트를 하네 &amp;gt; 그리고 그렇게 멋진 몸을 가지게 된 모습이 멋있어 보이네 &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;비슷한 예시로 우연히 새롭게 출시된 네이버 플러스 스토어 앱과 관련한 &lt;a href=&quot;https://brunch.co.kr/@trendlite/573&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;글&lt;/a&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;1) 이 상품을 원하는 사람 2) 원하지 않는 사람 3) 원하는지 아닌지 모르는 사람&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 원하지 않는 사람에게 필요하다고 설득하는 건 굉장히 어려운 일인 것 같고... 1) 원하는 사람의 경우 도달하기만 한다면 자연스럽게 고객이 될 것 같고, 3) 원하는지 아닌지 모르는 사람은 잠재적 고객이 될 수 있지 않을까?&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 팀원 분들은 정말 진심으로 세상에 필요한 개발자를 양성하려고 힘쓴다. 겨우 1년 보았지만 외부에서는 절대 상상할 수 없는 영역까지 고민하는 걸 보며 '이런 고민까지 한다는 걸 모두가 알면 좋을 텐데!!!!!' 라는 생각을 많이 했다. 팀원 분의 아이디어에서 시작한 글쓰기 스터디를 통해 정기적으로 각자의 생각을 담은 글을 작성해 보기로 했다. 우리 교육을 만드는 사람들의 진정성이 잘 전달되기를 바란다. 이 진정성이 누적되면 우리 교육에 공감하고 찾는 사람들이 자연스럽게 많아지겠지라는 바람도 있다. ㅎㅎ 이 글은 스터디의 첫 글!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;스터디 이름은 부글부글이다. (부스트캠프 글쓰기라는 뜻)&lt;/i&gt;&lt;/p&gt;</description>
      <category>essay</category>
      <author>Jungbin</author>
      <guid isPermaLink="true">https://madilyn.tistory.com/44</guid>
      <comments>https://madilyn.tistory.com/44#entry44comment</comments>
      <pubDate>Sun, 23 Mar 2025 22:52:14 +0900</pubDate>
    </item>
    <item>
      <title>[iOS] Firebase Cloud Messaging - APN</title>
      <link>https://madilyn.tistory.com/43</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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. firebase project 만들기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://console.firebase.google.com/u/3/?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://console.firebase.google.com/u/3/?hl=ko&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4016&quot; data-origin-height=&quot;1894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RaPpj/btsDWp7YAOF/I7kt5ofM597tN93uZkGut1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RaPpj/btsDWp7YAOF/I7kt5ofM597tN93uZkGut1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RaPpj/btsDWp7YAOF/I7kt5ofM597tN93uZkGut1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRaPpj%2FbtsDWp7YAOF%2FI7kt5ofM597tN93uZkGut1%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;4016&quot; height=&quot;1894&quot; data-origin-width=&quot;4016&quot; data-origin-height=&quot;1894&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;br /&gt;2. iOS 앱 추가하기&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 2.33.18.png&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;814&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Awn20/btsDQWzlxpH/3c9WHYKDFwFtDM2t3aS0ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Awn20/btsDQWzlxpH/3c9WHYKDFwFtDM2t3aS0ek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Awn20/btsDQWzlxpH/3c9WHYKDFwFtDM2t3aS0ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAwn20%2FbtsDQWzlxpH%2F3c9WHYKDFwFtDM2t3aS0ek%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;944&quot; height=&quot;814&quot; data-filename=&quot;스크린샷 2024-01-24 오후 2.33.18.png&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;814&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;iOS를 눌러 앱을 추가합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 앱 등록 화면이 나오는데 이때&lt;b&gt; Apple 번들 ID&lt;/b&gt;를 입력해야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요건 어느 것이냐면 오른쪽 엑스코드 창에서!! &lt;b&gt;Signing &amp;amp; Capabilities&lt;/b&gt; 안에 있는 &lt;b&gt;Bundle Identifier&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;나머지 앱 닉네임, App Store ID는 선택사항이니 패스할게요&lt;/p&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/chYI81/btsDQSjJujY/lRYnSgAN76wksHlcSz0gMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chYI81/btsDQSjJujY/lRYnSgAN76wksHlcSz0gMK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;770&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.02.35.png&quot; style=&quot;width: 39.3444%; margin-right: 10px;&quot; data-widthpercent=&quot;39.81&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chYI81/btsDQSjJujY/lRYnSgAN76wksHlcSz0gMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchYI81%2FbtsDQSjJujY%2FlRYnSgAN76wksHlcSz0gMK%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;854&quot; height=&quot;770&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bECEfd/btsDRHPwa5x/7D2p4yGgTpRsnZytr0VwC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bECEfd/btsDRHPwa5x/7D2p4yGgTpRsnZytr0VwC0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1506&quot; data-origin-height=&quot;898&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.01.33.png&quot; style=&quot;width: 59.4928%;&quot; data-widthpercent=&quot;60.19&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bECEfd/btsDRHPwa5x/7D2p4yGgTpRsnZytr0VwC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbECEfd%2FbtsDRHPwa5x%2F7D2p4yGgTpRsnZytr0VwC0%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;1506&quot; height=&quot;898&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 2번 단계 구성 파일 다운로드가 나오고, &lt;b&gt;GoogleService-Info.plist&lt;/b&gt; 다운로드 받아서 Xcode 프로젝트 안에 추가해 주세요&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.02.48.png&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;968&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkOzMW/btsDTsLjWx2/VQqRaZJzyF93LeUxK6BXM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkOzMW/btsDTsLjWx2/VQqRaZJzyF93LeUxK6BXM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkOzMW/btsDTsLjWx2/VQqRaZJzyF93LeUxK6BXM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkOzMW%2FbtsDTsLjWx2%2FVQqRaZJzyF93LeUxK6BXM1%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;1366&quot; height=&quot;968&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.02.48.png&quot; data-origin-width=&quot;1366&quot; data-origin-height=&quot;968&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.03.34.png&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WnmMt/btsDSsSldjy/CeRQ1YdbSj8WYjcU759tjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WnmMt/btsDSsSldjy/CeRQ1YdbSj8WYjcU759tjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WnmMt/btsDSsSldjy/CeRQ1YdbSj8WYjcU759tjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWnmMt%2FbtsDSsSldjy%2FCeRQ1YdbSj8WYjcU759tjk%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;492&quot; height=&quot;124&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.03.34.png&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;124&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;저는 위 사진처럼 Plists라는 폴더를 따로 만들어 여기에 Info.plist와 함께 넣어 두었습니다&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;참고!!!! GoogleService-Info.plist 안에는 앱에 관련된 정보가 들어있어서 &lt;b&gt;gitignore에 추가하여 따로 로컬에서 관리&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;3. Apple Developer &amp;gt; Identifiers 설정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Firebase Console은 잠시.. 멈춰 두고 Apple Developer로 갑니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.apple.com/account&quot;&gt;https://developer.apple.com/account&lt;/a&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;Identifiers 탭에서, &lt;b&gt;App ID&lt;/b&gt;를 만들었는지 확인합니다 (Push Notifications 말고도 다른 기능 (Sign in with Apple 등..)을 이용하셨다면 이미 만들어져 있을 겁니다 !)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, App ID가 없다면 새로 추가합니다&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.50.27.png&quot; data-origin-width=&quot;2542&quot; data-origin-height=&quot;1544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lU680/btsDRmkuhy8/17D9JV4rUu8BF32FT0P6e1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lU680/btsDRmkuhy8/17D9JV4rUu8BF32FT0P6e1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lU680/btsDRmkuhy8/17D9JV4rUu8BF32FT0P6e1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlU680%2FbtsDRmkuhy8%2F17D9JV4rUu8BF32FT0P6e1%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;2542&quot; height=&quot;1544&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.50.27.png&quot; data-origin-width=&quot;2542&quot; data-origin-height=&quot;1544&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용할 App ID를 클릭해서 들어간 후, &lt;b&gt;Push Notifications를 활성화&lt;/b&gt;시킵니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.50.55.png&quot; data-origin-width=&quot;2418&quot; data-origin-height=&quot;1126&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvzCKO/btsDUSbJJgN/SwkwsLLzBXcO50Fy9NhOA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvzCKO/btsDUSbJJgN/SwkwsLLzBXcO50Fy9NhOA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvzCKO/btsDUSbJJgN/SwkwsLLzBXcO50Fy9NhOA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvzCKO%2FbtsDUSbJJgN%2FSwkwsLLzBXcO50Fy9NhOA0%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;2418&quot; height=&quot;1126&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.50.55.png&quot; data-origin-width=&quot;2418&quot; data-origin-height=&quot;1126&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.50.38.png&quot; data-origin-width=&quot;2034&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbH0ks/btsDUMWRKLF/927fxzkYPDTI1EVxNL5rxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbH0ks/btsDUMWRKLF/927fxzkYPDTI1EVxNL5rxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbH0ks/btsDUMWRKLF/927fxzkYPDTI1EVxNL5rxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbH0ks%2FbtsDUMWRKLF%2F927fxzkYPDTI1EVxNL5rxK%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;2034&quot; height=&quot;192&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.50.38.png&quot; data-origin-width=&quot;2034&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. Apple Developer &amp;gt; Keys 설정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고다음... Keys로 가서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용할 Key가 없으면 새 &lt;b&gt;Key&lt;/b&gt;를 만들어 주세요... 전 이미 있으니 있는 걸 쓰겠습니다 (참고로 Key는 한 계정당 3개인.. 가? 발급받을 수 있는 걸로 알아요. 그냥 개인 프로젝트를 하시는 분들은 있던 Key를 계속 다른 프로젝트에 사용하셔도 괜찮습니다.. 아닐 수 있음)&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.51.07.png&quot; data-origin-width=&quot;1964&quot; data-origin-height=&quot;816&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dU4n88/btsDUcIcm0Y/VT1AvNQdpKJqpMaqyvu401/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dU4n88/btsDUcIcm0Y/VT1AvNQdpKJqpMaqyvu401/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dU4n88/btsDUcIcm0Y/VT1AvNQdpKJqpMaqyvu401/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdU4n88%2FbtsDUcIcm0Y%2FVT1AvNQdpKJqpMaqyvu401%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;1964&quot; height=&quot;816&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.51.07.png&quot; data-origin-width=&quot;1964&quot; data-origin-height=&quot;816&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;Key를 만들 때 주의할 점은 ... 저 &lt;b&gt;Download가 한 번만 가능&lt;/b&gt;하다는 점입니다!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 꼭 Key를 다운로드받고, (.p8 확장자를 가지고 있는 파일입니다) 개인적으로 꼭 따로 저장하여 관리해 주세요~ 잃어버리면 곤란~&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.51.10.png&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;1020&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqqjf2/btsDUVsHVmy/3bAdzfrCb6YZ16lQmx3KW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqqjf2/btsDUVsHVmy/3bAdzfrCb6YZ16lQmx3KW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqqjf2/btsDUVsHVmy/3bAdzfrCb6YZ16lQmx3KW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdqqjf2%2FbtsDUVsHVmy%2F3bAdzfrCb6YZ16lQmx3KW0%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;2490&quot; height=&quot;1020&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.51.10.png&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;1020&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.p8 Key 파일까지 받았다면 Apple Developer에서 해야 할 일은 끝입니다&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;5. Firebase Console 프로젝트 설정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 Firebase Project Console로 돌아와서... &lt;b&gt;설정 &amp;gt; 클라우드 메시징&lt;/b&gt;으로 들어와 주세요&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.52.00.png&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eqvYsf/btsDUT2JcAB/W7wXoqclchaJGISOdLIWG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eqvYsf/btsDUT2JcAB/W7wXoqclchaJGISOdLIWG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eqvYsf/btsDUT2JcAB/W7wXoqclchaJGISOdLIWG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeqvYsf%2FbtsDUT2JcAB%2FW7wXoqclchaJGISOdLIWG0%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;1440&quot; height=&quot;350&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.52.00.png&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;350&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;아래로 좀 내려가 보면 아까 추가했던 iOS 앱이 보입니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;&lt;b&gt;APN 인증 키&lt;/b&gt;&quot; 부분에 좀 전에 받았던 &lt;b&gt;.p8&lt;/b&gt; 파일을 업로드하여 주세요&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.52.04.png&quot; data-origin-width=&quot;1994&quot; data-origin-height=&quot;1350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwyoNs/btsDQSD18bw/bmOvt648im1KlGHXTnrIw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwyoNs/btsDQSD18bw/bmOvt648im1KlGHXTnrIw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwyoNs/btsDQSD18bw/bmOvt648im1KlGHXTnrIw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwyoNs%2FbtsDQSD18bw%2FbmOvt648im1KlGHXTnrIw0%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;1994&quot; height=&quot;1350&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.52.04.png&quot; data-origin-width=&quot;1994&quot; data-origin-height=&quot;1350&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;b&gt;키 ID&lt;/b&gt;와 &lt;b&gt;팀 ID&lt;/b&gt;를 입력하라고 뜰 텐데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;키 ID&lt;/b&gt;는 Apple Developers &amp;gt; Keys에서 저~ 기 Key ID를 쓰시면 됩니다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.51.10.png&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;1020&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqqjf2/btsDUVsHVmy/3bAdzfrCb6YZ16lQmx3KW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqqjf2/btsDUVsHVmy/3bAdzfrCb6YZ16lQmx3KW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqqjf2/btsDUVsHVmy/3bAdzfrCb6YZ16lQmx3KW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdqqjf2%2FbtsDUVsHVmy%2F3bAdzfrCb6YZ16lQmx3KW0%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;2490&quot; height=&quot;1020&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.51.10.png&quot; data-origin-width=&quot;2490&quot; data-origin-height=&quot;1020&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;b&gt;팀 ID&lt;/b&gt;는 Apple Developers &lt;b&gt;우측 상단 계정 정보&lt;/b&gt;에 나와 있는&lt;br /&gt;저 가린 부분!! 저기예요~! 위 사진에서 &lt;b&gt;Key ID 밑에 CONFIGURATION&lt;/b&gt;에도 똑같은 부분이 있을 거예요!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.53.01.png&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn9kuI/btsDUgX9xpG/mX3vDEHxTuzqv4sHdik1uK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn9kuI/btsDUgX9xpG/mX3vDEHxTuzqv4sHdik1uK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn9kuI/btsDUgX9xpG/mX3vDEHxTuzqv4sHdik1uK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn9kuI%2FbtsDUgX9xpG%2FmX3vDEHxTuzqv4sHdik1uK%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;490&quot; height=&quot;134&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.53.01.png&quot; data-origin-width=&quot;490&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 Firebase Console도 진짜 끝났습니다&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;6. Xcode로 가서 프로젝트 Capability 설정&lt;/h4&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;+Capability&lt;/b&gt;를 눌러 &lt;b&gt;Push Notifications와 Background Modes&lt;/b&gt;를 추가합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Background Modes에는 &lt;b&gt;Background fetch와 Remote notifications를 체크&lt;/b&gt;합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.58.25.png&quot; data-origin-width=&quot;1610&quot; data-origin-height=&quot;730&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEjQsT/btsDVmXVgQv/ddKBxKy7kUGPkKHAPlCS30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEjQsT/btsDVmXVgQv/ddKBxKy7kUGPkKHAPlCS30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEjQsT/btsDVmXVgQv/ddKBxKy7kUGPkKHAPlCS30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEjQsT%2FbtsDVmXVgQv%2FddKBxKy7kUGPkKHAPlCS30%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;1610&quot; height=&quot;730&quot; data-filename=&quot;스크린샷 2024-01-24 오후 3.58.25.png&quot; data-origin-width=&quot;1610&quot; data-origin-height=&quot;730&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 4.13.52.png&quot; data-origin-width=&quot;1584&quot; data-origin-height=&quot;644&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Mh7mp/btsDQ9esEMW/G2I6CX3ebu1o2GNhb7KS5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Mh7mp/btsDQ9esEMW/G2I6CX3ebu1o2GNhb7KS5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Mh7mp/btsDQ9esEMW/G2I6CX3ebu1o2GNhb7KS5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMh7mp%2FbtsDQ9esEMW%2FG2I6CX3ebu1o2GNhb7KS5k%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;1584&quot; height=&quot;644&quot; data-filename=&quot;스크린샷 2024-01-24 오후 4.13.52.png&quot; data-origin-width=&quot;1584&quot; data-origin-height=&quot;644&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;그 다음에, Info.plist 파일로 이동하여 &lt;b&gt;FirebaseAppDelegateProxyEnabled&lt;/b&gt; 프로퍼티를 추가합니다. 값은 NO&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 4.15.11.png&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xPlTx/btsDQ8miWDK/i9Gmqg8IKaaF5Snl97JxL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xPlTx/btsDQ8miWDK/i9Gmqg8IKaaF5Snl97JxL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xPlTx/btsDQ8miWDK/i9Gmqg8IKaaF5Snl97JxL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxPlTx%2FbtsDQ8miWDK%2Fi9Gmqg8IKaaF5Snl97JxL1%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;1208&quot; height=&quot;278&quot; data-filename=&quot;스크린샷 2024-01-24 오후 4.15.11.png&quot; data-origin-width=&quot;1208&quot; data-origin-height=&quot;278&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;7.  AppDelegate.swift에서 토큰 관련 코드 작성&lt;/h4&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;코드에 대한 피드백은.. 환영합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1706086464835&quot; class=&quot;swift&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;swift&quot;&gt;&lt;code&gt;import UIKit
import Firebase
import FirebaseCore

@main
class AppDelegate: UIResponder, UIApplicationDelegate, MessagingDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -&amp;gt; Bool {
        
        FirebaseApp.configure()
        PushNotificationHelper.shared.setAuthorization()
        // 앱 실행 시 사용자에게 알림 허용 권한 받기
        UNUserNotificationCenter.current().delegate = self
        
        // 원격 알림 등록
        application.registerForRemoteNotifications()

        /// 메시지 대리자 설정
        Messaging.messaging().delegate = self
        
        /// 자동 초기화 방지
        Messaging.messaging().isAutoInitEnabled = true
        
        /// 현재 등록 토큰 가져오기
        Messaging.messaging().token { token, error in
            if let error = error {
                print(&quot;Error fetching FCM registration token: \(error)&quot;)
            } else if let token = token {
                print(&quot;FCM registration token: \(token)&quot;)
                UserDefaultsManager.fcmDeviceToken = token
                UserInfo.shared.deviceToken = token 
            }
        }
        
        return true
    }
    
    // MARK: UISceneSession Lifecycle
    
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -&amp;gt; UISceneConfiguration {
        // Called when a new scene session is being created.
        // Use this method to select a configuration to create the new scene with.
        return UISceneConfiguration(name: &quot;Default Configuration&quot;, sessionRole: connectingSceneSession.role)
    }
    
    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set&amp;lt;UISceneSession&amp;gt;) {
        // Called when the user discards a scene session.
        // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
        // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
    }
    
    func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -&amp;gt; Bool {
        if (AuthApi.isKakaoTalkLoginUrl(url)) {
            return AuthController.handleOpenUrl(url: url)
        }
        
        return false
    }
    
    /// APN 토큰과 등록 토큰 매핑
    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Messaging.messaging().apnsToken = deviceToken
    }
    
    /// APN 토큰과 등록 토큰 매핑 실패
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        debugPrint(&quot;APN 토큰 등록 실패&quot;, &quot;fail&quot;)
    }
    
    /// 디바이스 세로방향으로 고정
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -&amp;gt; UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.portrait
    }
    
    /// 토큰 갱신 모니터링 메서드
    func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
        print(&quot;Firebase registration token: \(String(describing: fcmToken))&quot;)
        UserDefaultsManager.fcmDeviceToken = fcmToken
        UserInfo.shared.deviceToken = fcmToken ?? &quot;non-token&quot;
        let dataDict: [String: String] = [&quot;token&quot;: fcmToken ?? &quot;&quot;]
        NotificationCenter.default.post(
            name: Notification.Name(&quot;FCMToken&quot;),
            object: nil,
            userInfo: dataDict
        )
    }
}

// MARK: - UNUserNotificationCenterDelegate
extension AppDelegate: UNUserNotificationCenterDelegate {

    /// foreGround에 푸시알림이 올 때 실행되는 메서드
    func userNotificationCenter(_ center: UNUserNotificationCenter,willPresent notification: UNNotification,withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -&amp;gt; Void) {
        completionHandler([.badge, .sound, .list, .banner])
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1706087466783&quot; class=&quot;swift&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;swift&quot;&gt;&lt;code&gt;//
//  PushNotificationHelper.swift
//  GAM
//
//  Created by Jungbin on 1/24/24.
//

import Foundation
import Firebase

class PushNotificationHelper {
    static let shared = PushNotificationHelper()

    private init() { }

    func setAuthorization() {
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound] // 필요한 알림 권한을 설정
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: { _, _ in }
        )
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;8. 테스트하기&lt;/h4&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;b&gt;device token&lt;/b&gt;이 출력될 텐데요, 이 토큰을 복사해 둡니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 6.11.36.png&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F1iRu/btsDQgdTcni/dWKFIf2Jsh5Zh03IJpDUB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F1iRu/btsDQgdTcni/dWKFIf2Jsh5Zh03IJpDUB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F1iRu/btsDQgdTcni/dWKFIf2Jsh5Zh03IJpDUB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF1iRu%2FbtsDQgdTcni%2FdWKFIf2Jsh5Zh03IJpDUB0%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;418&quot; height=&quot;148&quot; data-filename=&quot;스크린샷 2024-01-24 오후 6.11.36.png&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;148&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;Firebase Console &amp;gt; Messaging으로 들어가서, Firebase 알림 메시지 캠페인을 선택합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 4.14.16.png&quot; data-origin-width=&quot;2528&quot; data-origin-height=&quot;1686&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ttuYw/btsDWJFk31x/Hwvuw2Z1a64PyfcywrX4hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ttuYw/btsDWJFk31x/Hwvuw2Z1a64PyfcywrX4hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ttuYw/btsDWJFk31x/Hwvuw2Z1a64PyfcywrX4hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FttuYw%2FbtsDWJFk31x%2FHwvuw2Z1a64PyfcywrX4hk%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;2528&quot; height=&quot;1686&quot; data-filename=&quot;스크린샷 2024-01-24 오후 4.14.16.png&quot; data-origin-width=&quot;2528&quot; data-origin-height=&quot;1686&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;그리고 알림 제목, 알림 내용을 입력하고, 오른쪽에 &quot;&lt;b&gt;테스트 메시지 전송&lt;/b&gt;&quot; 버튼 클릭&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 6.15.06.png&quot; data-origin-width=&quot;1494&quot; data-origin-height=&quot;586&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wJMWa/btsDQQ7gfPW/QdWkCrM06b71qkkYR2Yi50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wJMWa/btsDQQ7gfPW/QdWkCrM06b71qkkYR2Yi50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wJMWa/btsDQQ7gfPW/QdWkCrM06b71qkkYR2Yi50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwJMWa%2FbtsDQQ7gfPW%2FQdWkCrM06b71qkkYR2Yi50%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;1494&quot; height=&quot;586&quot; data-filename=&quot;스크린샷 2024-01-24 오후 6.15.06.png&quot; data-origin-width=&quot;1494&quot; data-origin-height=&quot;586&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;p data-ke-size=&quot;size16&quot;&gt;Xcode 콘솔에서 복사해 뒀던&lt;b&gt; FCM 등록 토큰을 추가&lt;/b&gt;합니다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-01-24 오후 4.14.33.png&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;984&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lQWaU/btsDTuJbNmJ/OTxkCZkogrbiDIpyie9zi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lQWaU/btsDTuJbNmJ/OTxkCZkogrbiDIpyie9zi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lQWaU/btsDTuJbNmJ/OTxkCZkogrbiDIpyie9zi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlQWaU%2FbtsDTuJbNmJ%2FOTxkCZkogrbiDIpyie9zi1%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;1404&quot; height=&quot;984&quot; data-filename=&quot;스크린샷 2024-01-24 오후 4.14.33.png&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;984&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그리고 테스트를 누르면~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;1306&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pAb54/btsDUbJktMU/9iKIiak41PHvAGQV8pVy1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pAb54/btsDUbJktMU/9iKIiak41PHvAGQV8pVy1K/img.png&quot; data-alt=&quot;짜잔&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pAb54/btsDUbJktMU/9iKIiak41PHvAGQV8pVy1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpAb54%2FbtsDUbJktMU%2F9iKIiak41PHvAGQV8pVy1K%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;602&quot; height=&quot;1306&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;1306&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;짜잔&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;p data-ke-size=&quot;size16&quot;&gt;FCM - APN, FCM 토큰 만료 시점 등에 대해서는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://seungwoolog.tistory.com/88&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://seungwoolog.tistory.com/88&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1706087859245&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;[Firebase] FCM을 도입할 때 고려할 것들&quot; data-og-description=&quot;최근 진행하는 프로젝트에 FCM을 앱 푸시 알림 서비스로 사용하게 되었다. 도입할 때 서버 개발자로서 고려할 것들을 정리하였다. Firebase Cloud Messaging (FCM) Firebase 클라우드 메시징(FCM)은 무료로 메&quot; data-og-host=&quot;seungwoolog.tistory.com&quot; data-og-source-url=&quot;https://seungwoolog.tistory.com/88&quot; data-og-url=&quot;https://seungwoolog.tistory.com/88&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ur6Lm/hyVbZXO8YU/SQGrhK7u0A95d1jXZCbJKk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/jAfVj/hyU8Qg91wz/ST6imissbA6krUgKnWwxEK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bR77FT/hyVb2G0Dk3/Nx4PGo7V0MSvpDuk2x2tsK/img.png?width=880&amp;amp;height=586&amp;amp;face=0_0_880_586&quot;&gt;&lt;a href=&quot;https://seungwoolog.tistory.com/88&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://seungwoolog.tistory.com/88&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ur6Lm/hyVbZXO8YU/SQGrhK7u0A95d1jXZCbJKk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/jAfVj/hyU8Qg91wz/ST6imissbA6krUgKnWwxEK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bR77FT/hyVb2G0Dk3/Nx4PGo7V0MSvpDuk2x2tsK/img.png?width=880&amp;amp;height=586&amp;amp;face=0_0_880_586');&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;[Firebase] FCM을 도입할 때 고려할 것들&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;최근 진행하는 프로젝트에 FCM을 앱 푸시 알림 서비스로 사용하게 되었다. 도입할 때 서버 개발자로서 고려할 것들을 정리하였다. Firebase Cloud Messaging (FCM) Firebase 클라우드 메시징(FCM)은 무료로 메&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;seungwoolog.tistory.com&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;/p&gt;</description>
      <category>iOS/Swift</category>
      <category>ios</category>
      <category>swift</category>
      <author>Jungbin</author>
      <guid isPermaLink="true">https://madilyn.tistory.com/43</guid>
      <comments>https://madilyn.tistory.com/43#entry43comment</comments>
      <pubDate>Wed, 24 Jan 2024 18:21:27 +0900</pubDate>
    </item>
    <item>
      <title>[UIKit] UIScrollView &amp;quot;Scrollable content size is ambiguous.&amp;quot; 에러 해결</title>
      <link>https://madilyn.tistory.com/42</link>
      <description>&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;508&quot; data-origin-height=&quot;116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pHtpA/btsp7qGV6mC/TkV7hl5IegXWvSNBMIhv4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pHtpA/btsp7qGV6mC/TkV7hl5IegXWvSNBMIhv4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pHtpA/btsp7qGV6mC/TkV7hl5IegXWvSNBMIhv4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpHtpA%2Fbtsp7qGV6mC%2FTkV7hl5IegXWvSNBMIhv4k%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;508&quot; height=&quot;116&quot; data-origin-width=&quot;508&quot; data-origin-height=&quot;116&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;아래 코드처럼 요상하게 구현했었는데... 조작하는 데나 보여지는 뷰에서는 아무 문제가 없었지만, View Hierarchy를 보면 제약조건 에러가 있는 게 너무너무 거슬려서 결국 해결했다!&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;(평소 scrollView 에러는 터치나 스크롤이 안 되는 등의 문제가 있었지만, 이 경우는 모든 인터랙션이 다 가능하긴 했음.)&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;원래 코드 (SnapKit 사용)&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;swift&quot; data-code-language=&quot;swift&quot; data-ke-language=&quot;swift&quot;&gt;&lt;code&gt;        self.view.addSubviews([scrollView])
        self.scrollView.addSubview(contentView)
        self.contentView.addSubviews([infoTitleLabel, profileInfoView, tagTitleLabel, tagCollectionView, emailTitleLabel, emailButton])
        
        self.scrollView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        
        self.contentView.snp.makeConstraints { make in
            make.width.equalToSuperview()
            make.centerX.top.bottom.equalToSuperview()
        }&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lQSYB/btsp8bWTG6R/re0juUWypwBxcEKs3r9KMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lQSYB/btsp8bWTG6R/re0juUWypwBxcEKs3r9KMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lQSYB/btsp8bWTG6R/re0juUWypwBxcEKs3r9KMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlQSYB%2Fbtsp8bWTG6R%2Fre0juUWypwBxcEKs3r9KMk%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;650&quot; height=&quot;496&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;496&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;여러 블로그를 참고해 본 결과... scrollView를 이용해 레이아웃을 구현할 때의 나의 대전제(?)를 세울 수 있었는데&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1️⃣ scrollView는 top, bottom, leading(left), trailing(right)를 모두 스크롤 될 영역 사이즈에 맞춘다. (보통 equalToSuperView 사용)&lt;/p&gt;
&lt;pre id=&quot;code_1691311228585&quot; class=&quot;stylus&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;self.scrollView.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2️⃣ scrollView 안에 들어가는 contentView는 top, bottom, leading(left), trailing(right)는 모두 equalToSuperView를 사용하여 scrollView 영역과 동일하게 맞추고, 세로 스크롤을 원하면 width를 equalToSuperView, 가로 스크롤을 원하면 height를 equalToSuperView 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1691311298185&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;self.contentView.snp.makeConstraints { make in
    make.edges.width.equalToSuperview() // 세로 스크롤
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4️⃣ contentView의 height는 항상 정해져 있어야 하며, height 값을 직접 넣을 수도 있고, contentView의 하위 UI 컴포넌트들을 통해 height을 설정해도 된다. (하위 UI 컴포넌트를 통해 contentView의 사이즈가 결정되므로,,, (세로 스크롤이면 height가 결정됨) 하위 컴포넌트들의 제약 조건을 잘 넣었는지 확인한다!&lt;/p&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1691311313550&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;self.infoTitleLabel.snp.makeConstraints { make in
    make.top.equalToSuperview().inset(26) // top 설정!
    make.horizontalEdges.equalToSuperview().inset(20)
    make.height.equalTo(27) // height 1
}
self.profileInfoView.snp.makeConstraints { make in
    make.top.equalTo(self.infoTitleLabel.snp.bottom).offset(10)
    make.horizontalEdges.equalToSuperview().inset(20)
    make.height.equalTo(194) // height 2
    make.bottom.equalToSuperView().inset(40) // bottom 설정!
}&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;해결!&lt;/div&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;476&quot; data-origin-height=&quot;172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuvTvh/btsp620zjJ9/uyFM3N2HpYkbiG0rORHB01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuvTvh/btsp620zjJ9/uyFM3N2HpYkbiG0rORHB01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuvTvh/btsp620zjJ9/uyFM3N2HpYkbiG0rORHB01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuvTvh%2Fbtsp620zjJ9%2FuyFM3N2HpYkbiG0rORHB01%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;476&quot; height=&quot;172&quot; data-origin-width=&quot;476&quot; data-origin-height=&quot;172&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;전체 코드&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;reasonml&quot; data-code-language=&quot;swift&quot;&gt;&lt;code&gt;self.view.addSubviews([scrollView])
self.scrollView.addSubview(contentView)
self.contentView.addSubviews([infoTitleLabel, profileInfoView])

self.scrollView.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

self.contentView.snp.makeConstraints { make in
    make.edges.width.equalToSuperview()
}

self.infoTitleLabel.snp.makeConstraints { make in
    make.top.equalToSuperview().inset(26) // top 설정!
    make.horizontalEdges.equalToSuperview().inset(20)
    make.height.equalTo(27) // height 1
}
self.profileInfoView.snp.makeConstraints { make in
    make.top.equalTo(self.infoTitleLabel.snp.bottom).offset(10)
    make.horizontalEdges.equalToSuperview().inset(20)
    make.height.equalTo(194) // height 2
    make.bottom.equalToSuperView().inset(40) // bottom 설정!
}
&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;~ 아닐 수도 있음 ~&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>iOS/UIKit</category>
      <author>Jungbin</author>
      <guid isPermaLink="true">https://madilyn.tistory.com/42</guid>
      <comments>https://madilyn.tistory.com/42#entry42comment</comments>
      <pubDate>Sun, 6 Aug 2023 17:43:17 +0900</pubDate>
    </item>
    <item>
      <title>2021년 회고, 2022년의 다짐</title>
      <link>https://madilyn.tistory.com/41</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;벌써 2021년이 마무리되고 있다. 몇 시간 안 남았지만... 밤새워서 적을 수 있겠지. 작년은 코로나가 이제 막 시작되던 시기라 정신 못 차리고 보냈었다. 꿀 빨면서 학교 다니며... 알바 열심히 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;올해는 '도전의 해'라고 정의할 수 있겠다. 처음 겪는 일들이 너무 많았다. 그리고... 예상치 못한 일들도 많았다. J 중에서도 극성 J라는 ESTJ인 나는... 계획하지 않았던 일을 마주치게 되면 좀 어리바리해진다. 올해를 보내고 나니까 그런 상황에서도 조금이나마 더 유연하게 대처할 수 있는 사람이 된 것 같다.&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;올해의 첫 도전, 복수전공. 복수전공을 신청하기엔 성적이 좀 딸리던 나는 비대면 수업을 발판 삼아 성적을 열심히 올렸다. 간신히 커트라인 맞춰서 복수전공 신청을 해냈다. 단순히 유일한 교내 iOS 전공 수업 듣고 싶어서 신청한 거였는데... 그 교수님 안식년이셨다. 1학기에만 열리는 수업인데 일 년 놓쳐 버렸다. 디미과 갔으니까 디자인 수업이나 열심히 들었다. 3D나 게임 쪽은 왜 이렇게 듣기 싫은 거지.... 본전공 2학점 듣고 나머지는 다 복수전공 학점으로 채웠다. 나름 나쁘지 않았고, 3학년 디자인 과목을 1학년이랑 지식 수준 비슷한 내가 들으려니까 아주 스파르타로 공부당한 기분이었다. 학점 괜찮게 나오긴 했다.... 모바일 UI/UX 디자인 과목이라서 클라 개발 공부 중인 나한테는 너무너무너무너무너무 유익했다. 내년엔 우리 전공 좀 열심히 들어야지.&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;&amp;nbsp;대학교 들어와서 처음으로 동아리에 들어갔다. 일이 학년 때에는 이상하게 동아리는 쳐다도 안 봤다. 작년에  &amp;zwj;♀️아자차 스터디로 iOS 공부 본격적으로 시작했는데, 주변에 iOS 하는 사람이 정~~~~ 말 없다는 걸 알았다. 그때 이후로 iOS 파트가 존재하는 동아리를 많이 찾아보고, 방학 시작하자마자 디앤디에 지원했다. 사실 원래 떨어졌었는데, 어쩌다 iOS 한 자리가 비어서 추가 합격으로 들어가게 되었다. 떨어져서 아쉬워하고 있었는데 갑자기 문자 와서 완전 놀랐음. 본격적으로 사람들이랑 뭔가를 만들어 본다! 라고 하는 경험이 정말 처음이어서 많이 두렵기도 했고, 항상 나 자신이 너무 부족한 것 같았다. 우리 조 사람들은 거의 다... 직장인이었다. 넘 쫄렸다. 얼마 공부 안 하긴 했지만 그래도 해 본 게 UIKit 기반이었는데, 덜컥 SwiftUI로 개발하자는 말에 오케이를 해 버렸다. 뭔가... 탐색하고 싶었나. 그때 공부할 땐 정말 너무 뭐가 뭔지 몰랐고... 어려웠다. 그때 멘토님이 나 붙잡고 거의 일대일 속성 과외를 해 주셨는데 아직도 너무 감사하다. 그래도 디앤디 때 주워듣고 배운 것들이 좀 있었는지, 다른 협업 들어가서는 뭔가 이끌고 진행할 수 있었다. 아무것도 모르는 채로 4기 한 기수 보내고 나니까, 좀 더 공부하고 다시 디앤디에서 서비스를 만들어 보고 싶다. 지금은 그래도 많이 공부했으니까 괜찮지 않을까. 디앤디 7기 딱 기다려요....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;사실 솝트는 28기 때 떨어졌었다. 그 사이에 공부 열심히 했는데, 오히려 지금 29기 하고 있는 게 더 좋은 것 같기도. 내 휴대폰에선 조회가 잘 안 돼서, 혜빈이가 대신 최종 결과 발표를 봐 줬는데 합격이었다. 그때 신촌 길거리에서 뭐 먹고 있었던 것 같은데, 찐행복. 곧 있을 앱잼도 너무 기대된다. 이미 솝텀 계획까지 세워 버렸다.... 내년의 나 파이팅.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;# 창업팀, 직장, 계획에 없던 휴학&lt;/h4&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;Co-founder라는 타이틀은 그때 결정되었지만, 사실 이걸 받아들이기까지에는 많은 시간이 걸렸다. 나는 분명히 개발자로 합류했는데, 정신 차리니까 이것저것 회사의 존망이 달린 일들이 내 손에 맡겨지고 있었다. 인사 업무도 보고, 디자인도 하고, 기획도 하고, 개발팀 관리, 외주 관리까지 맡았다. 진짜 회사에서는 올라운더로 살았는데... 집에만 오면 현타가 너무 왔다. 이게 스스스스스타트업의 현실인가. 애초에 내 아이디어의 사업이 아니어서 그랬나. 나는 창업이나 경영보단 '개발'에 관심이 더 있었고, 그 생각은 지금도 여전하다. 예상하지 못했던 일들을 자의 반 타의 반으로 잔뜩 떠안게 되어서 정식 출근 후 세네 달은 정말로 너무 힘들었다. 스트레스도 진짜 많이 받았고. 웬만하면 스트레스 안 받는 성격인데, 지금 생각해 보니까 그땐 좀 나약했던 것 같기도. 그때 내 한탄 다 들어 주었던 가족들이랑 친구들한테 너무 고마워. 말해야 속이 풀리는 성격은 좀 고쳐야겠다고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;연말이 되어서야 조금 더 개발에 집중할 수 있었다. 솔직히 사수 없이 혼자 개발하는 게 막막했지만, 우리는 완전 최초 MVP 앱을 개발하는 중이었으니까. 내 코딩 스타일이 곧 컨벤션이고 위키였다.... 이런 점이 너무 아쉬워서 솝트에 들어갔던 것도 있다. 역시 다른 사람들 개발하는 걸 보고 많이 배워야 해. 대신 거의 혼자 개발하다 보니 어떤 문제가 생기든 무조건 다 내가 해결해야 했는데, 그 과정에서 스스로 정말 많이 배웠다. 나 아니면 해결할 사람이 없는 극한의 상황.... 어쩔 수 없이 눈에 불을 켜고 방법을 찾아야 했다. 공부하기에는 최적의 상황이었다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2월 말 계약 종료를 앞두고, 나는 조금 더 개발에 집중하고 싶어서 재계약 생각이 없다고 말씀드렸다. 이것도 몇 달 내내 생각하고 생각해서 낸 결론이다. 이렇게 조심스럽고 오래 고민한 일이 별로 없었고, 그런 성격도 아니었고. 회사를 다니면서 내가 하고 싶은 일이 무엇인가에 대해 생각을 많이 했다. 사실 개발자라는 직업을 꿈꾼 건 초등학교 6학년 때부터였고, 이 생각은 중고등학교 때에도 변한 적이 없었다. 고삼 때 희망 전공을 정할 때에도 일말의 고민도 없이 컴공을 적어 냈다. 작년에는 좀... 주변에 하고 싶은 게 굉장히 많았던 사람을 보면서, 내가 너무 어렸을 때 결정했던 일에 나를 가둔 건 아니었나, 하는 약간의 불안도 있었다. 어떻게 됐든 다른 업무에 많이 치이며 회사를 다니다 보니까, 저 그냥 개발하게 해 주세요... 라는 소리가 절로 나왔다. 개발이 내 적성인 것 같아. 역시 뭐든 헷갈릴 땐 경험! 경해 봐야 생각도 정리가 된다는 걸 또 한번 깨달았다.&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;&amp;nbsp;드디어 피아노를 다시 쳤다. 어릴 때 피아노 너무 열심히 치기도 했고, 좋아했고. 중고등학교 때는 합창 대회만 하면 반주를 꼭 맡아서 했다. 이상하게 우리 반에는 항상 음대 가고 싶은 친구가 없었다. 그래서 걍 어릴 때 좀 치던 내가 쳤다. ㅋㅋㅋ 고삼 때부턴 항상 어른이 되면 피아노를 다시 치고 싶다고 생각했다. 근데 우리 집에서 피아노를 버려서... 학원 아니면 칠 곳이 없었다. 한 10년 전에 다니던 피아노 학원이 아직도 집 앞에 있는데, 원장 선생님은 젊은 분으로 바뀌었다. 나랑 나이 차이가 별로 안 났음. 상담하러 갔다가 그날 바로 결제하고 두 달 동안 열심히 다녔다. 6월 말부터 출근했어서 어쩔 수 없었는데... 피아노를 이제 못 치는 게 너무 아쉬워서 결국 디지털 피아노를 지르고 말았다. 당근 짱. 내 돈으로 하고 싶은 악기 사는 어른이 되었다! 내년에는 우쿨렐레 사서 유튜브로 독학할 거다. 음악은 나의 힘.   특히 올해엔 재즈에 빠졌다. 뭘 하든 확실한 걸 좋아하는 편인데, 재즈의 불규칙함은 뭔가... 들을 때 일탈하는 기분. 라라랜드 짱.&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;IMG_24C5672AA7D8-1.jpeg&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;721&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZhgsV/btrpq8Alitn/ecOr2XUjT2Hs4yElfGbgx0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZhgsV/btrpq8Alitn/ecOr2XUjT2Hs4yElfGbgx0/img.jpg&quot; data-alt=&quot;올해의 정빈플릭스 영화 상. 킬 빌 드립니ㄷㅏ.... 짱짱.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZhgsV/btrpq8Alitn/ecOr2XUjT2Hs4yElfGbgx0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZhgsV%2Fbtrpq8Alitn%2FecOr2XUjT2Hs4yElfGbgx0%2Fimg.jpg&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;330&quot; height=&quot;321&quot; data-filename=&quot;IMG_24C5672AA7D8-1.jpeg&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;721&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;올해의 정빈플릭스 영화 상. 킬 빌 드립니ㄷㅏ.... 짱짱.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;# 2022&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;작성하다 보니까 벌써 날짜가 넘어갔다. 나가서 GF 연례 행사 카운트다운 세고 왔다. ㅎㅎ 작년의 나 수고 많았다. 회고 작성하면서 1월부터의 캘린더를 쭉 봤는데... 진짜 뭐가 엄청 많다. 1월이랑 5월엔 어떻게 살았지 싶다. ;;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_2580.jpg&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;1179&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b02oQt/btrpu7goI3D/2tLa3IjSKPf4Zk8KjG0nCk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b02oQt/btrpu7goI3D/2tLa3IjSKPf4Zk8KjG0nCk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b02oQt/btrpu7goI3D/2tLa3IjSKPf4Zk8KjG0nCk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb02oQt%2Fbtrpu7goI3D%2F2tLa3IjSKPf4Zk8KjG0nCk%2Fimg.jpg&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;452&quot; height=&quot;455&quot; data-filename=&quot;IMG_2580.jpg&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;1179&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;스물셋에도 다 이루길 부탁해. 내년 상반기에는 면허도 따고, 알바도 하고, 운동도 하고, 책도 읽고, 공부도 열심히 해야지. 회사 다니는 지금보다 더 바쁠 것 같긴 하지만... 할 수 있다. 그리고 기록의 중요함을 아는 사람이 되고 싶다. 올해 처음으로 회고를 작성해 본다. 내년 이맘때쯤 보면 기분이 어떨지 너무 궁금하다. 연초에 일 년 만다라트 계획표를 작성했었는데, 최근에 다시 봤더니 한 40% 정도 달성했다. 작성해 놓고 거의 잊고 살았는데. ㅋㅋㅋㅋ 뭔가 생각을 하고 한번 정리를 한다는 게 나에게 각인이라도 되는 건가 싶었다. 올해에는 좀 더 구체적으로, 현실적으로 작성하는 중이다. 얘도 올해 끝날 때 보면 감회가 새롭겠지. 2022년 12월에 이 글을 보고 있는 나에게.... 맥북은 새로 샀니? 여전히 최선을 다하고 있을 거야. 수고했단다.  &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Group 4.png&quot; data-origin-width=&quot;3510&quot; data-origin-height=&quot;2532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNpY5A/btrptgx6L0Q/8mcg07iXGM6Efhem7QPkkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNpY5A/btrptgx6L0Q/8mcg07iXGM6Efhem7QPkkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNpY5A/btrptgx6L0Q/8mcg07iXGM6Efhem7QPkkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNpY5A%2Fbtrptgx6L0Q%2F8mcg07iXGM6Efhem7QPkkk%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;782&quot; height=&quot;564&quot; data-filename=&quot;Group 4.png&quot; data-origin-width=&quot;3510&quot; data-origin-height=&quot;2532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>essay</category>
      <category>일기</category>
      <category>회고</category>
      <author>Jungbin</author>
      <guid isPermaLink="true">https://madilyn.tistory.com/41</guid>
      <comments>https://madilyn.tistory.com/41#entry41comment</comments>
      <pubDate>Sat, 1 Jan 2022 01:56:36 +0900</pubDate>
    </item>
    <item>
      <title>[RxSwift] ARC, 강한 참조 strong, 약한 참조 weak, 강한 참조 순환 문제</title>
      <link>https://madilyn.tistory.com/30</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Struct vs Class&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Struct 타입과 Class 타입을 비교할 때 가장 많이 하는 말 &amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Struct는 값 타입,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Class는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;참조&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;타입!&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;값 타입: 전달할 때마다 값을 복사해서 전달&lt;/li&gt;
&lt;li&gt;참조 타입: 하나의 인스턴스가 참조를 통해 여러 곳에서 접근
&lt;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;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;rarr; 스위프트에서 메모리 사용을 관리하기 위해 ARC를 사용!&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;ARC의 작동 규칙을 모르고 사용하면 인스턴스가 메모리에서 영원히 해제되지 않을 가능성이 있기 때문에... ARC에 대해 알아야 한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ARC&lt;/h3&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;* 자동 참조 카운팅, Automatic Reference Counting =&amp;gt;&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;자동으로 메모리를 관리해 주는 방식&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;* 더 이상 필요하지 않은 클래스의 인스턴스를 메모리에서 해제시킴&lt;/span&gt;&lt;/span&gt;&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;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;0&quot; data-reactroot=&quot;&quot;&gt;&amp;nbsp;-&amp;gt; 더 이상 필요하지 않은 클래스&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 판단하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;2&quot; data-reactroot=&quot;&quot;&gt;참조 횟수를 카운트&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;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;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;* RC(Reference Counting)가 0이 되는 순간 인스턴스는 메모리에서 해제됨&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;* 인스턴스가 계속 메모리에 남아 있어야 할 무언가 명분이 필요하다! &amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;1&quot; data-reactroot=&quot;&quot;&gt;강한&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;3&quot; data-reactroot=&quot;&quot;&gt;Strong&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;5&quot; data-reactroot=&quot;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;참조&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 사용하여 RC를 1 증가시킴&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;강한 참조&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&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&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;1&quot; data-reactroot=&quot;&quot;&gt;기본&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;으로 강한 참조&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1636286246723&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 이 코드에서 말하는 RC(Reference Counting)는 Person 클래스의 인스턴스 RC!!!
class Person {
	let name: String
		
	init(name: String) {
		self.name = name
	}
}

var reference1: Person?
var reference2: Person?
var reference3: Person?

reference1 = Person(name: &quot;JUNGBIN&quot;) // RC = 1
reference2 = reference1 // RC = 2
reference3 = reference1 // RC = 3

reference3 = nil // RC = 2
reference2 = nil // RC = 1
reference1 = nil // RC = 0 -&amp;gt; 메모리에서 해제됨!!!!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;강한 참조 순환 문제&lt;/span&gt;&lt;/span&gt;&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 style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;* &lt;span style=&quot;color: #000000;&quot;&gt;두 인스턴스가 서로를 참조하는 상황에서 강한 참조 순환 문제가 발생할 수 있음&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1636286341712&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
	let name: String
		
	init(name: String) {
		self.name = name
    }
		
	var car: Car?
}

class Car {
	let name: String

	init(name: String) {
		self.name = name
	}

	var owner: Person?
}

var jungbin: Person? = Person(name: &quot;JUNGBIN&quot;) // Person RC = 1
var myCar: Car? = Car(name: &quot;BoongBoong&quot;) // Car RC = 1

myCar?.owner = jungbin // Person RC = 2
jungbin?.car = myCar // Car RC = 2

jungbin = nil // Person RC = 1
myCar = nil // Car RC = 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;* &lt;span style=&quot;color: #000000;&quot;&gt;위 코드에서,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;1&quot; data-reactroot=&quot;&quot;&gt;jungbin&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;3&quot; data-reactroot=&quot;&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 할당했을 때 Person RC = 1이 됨.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;5&quot; data-reactroot=&quot;&quot;&gt;jungbin&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;은 이제&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;7&quot; data-reactroot=&quot;&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;9&quot; data-reactroot=&quot;&quot;&gt;myCar.owner&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 통해 아직&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;11&quot; data-reactroot=&quot;&quot;&gt;Person&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;인스턴스에 참조할 수 있음.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #fbf3db; color: #eb5757;&quot; data-token-index=&quot;13&quot; data-reactroot=&quot;&quot;&gt;Person&lt;/span&gt;&lt;span style=&quot;background-color: #fbf3db; color: #000000;&quot; data-token-index=&quot;14&quot; data-reactroot=&quot;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;인스턴스가 메모리에 살아 있고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #fbf3db; color: #eb5757;&quot; data-token-index=&quot;15&quot; data-reactroot=&quot;&quot;&gt;Person&lt;/span&gt;&lt;span style=&quot;background-color: #fbf3db; color: #000000;&quot; data-token-index=&quot;16&quot; data-reactroot=&quot;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;인스턴스에 참조할 방법도 남아 있는 상황&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;! 하지만 다음에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;18&quot; data-reactroot=&quot;&quot;&gt;myCar&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;20&quot; data-reactroot=&quot;&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;을 할당했을 때,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;22&quot; data-reactroot=&quot;&quot;&gt;myCar&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 참조하던 인스턴스의 RC는 하나 감소하여 1이 되었음. 근데 이제&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;24&quot; data-reactroot=&quot;&quot;&gt;myCar.owner&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;26&quot; data-reactroot=&quot;&quot;&gt;Person&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;인스턴스에 접근하지 못하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;28&quot; data-reactroot=&quot;&quot;&gt;myCar&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;도&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;30&quot; data-reactroot=&quot;&quot;&gt;nil&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이라서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;32&quot; data-reactroot=&quot;&quot;&gt;Car&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;인스턴스에 접근하지 못함.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #fbf3db; color: #000000;&quot; data-token-index=&quot;34&quot; data-reactroot=&quot;&quot;&gt;인스턴스에 접근할 방법은 사라졌는데, 정작 인스턴스들은 메모리에 남아 있기 때문에(RC = 1) 메모리 누수 발생!&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;span style=&quot;color: #000000;&quot;&gt;아래 그림에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;1&quot; data-reactroot=&quot;&quot;&gt;ViewController&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;가 화면에서 pop 되고 이제 사용하지 않는데도 불구하고 3번의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;3&quot; data-reactroot=&quot;&quot;&gt;self.어쩌고저쩌고&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;코드에 의해 RC 카운트가 한 번 증가되었기 때문에 4번에서 RC = 1이 됨.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;5&quot; data-reactroot=&quot;&quot;&gt;ViewController&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;의 인스턴스가 메모리에서 해제되지 않음!!!! &amp;rarr; 메모리 누수(Memory Leak)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2684&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;IMG_EDFD2A81DE62-1.jpeg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEno0H/btrkhpmPDDI/ZmbuQLmHqRdRtKBHLcxug1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEno0H/btrkhpmPDDI/ZmbuQLmHqRdRtKBHLcxug1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEno0H/btrkhpmPDDI/ZmbuQLmHqRdRtKBHLcxug1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEno0H%2FbtrkhpmPDDI%2FZmbuQLmHqRdRtKBHLcxug1%2Fimg.jpg&quot; data-origin-width=&quot;2684&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;IMG_EDFD2A81DE62-1.jpeg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;약한 참조&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h3&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&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;span style=&quot;color: #000000;&quot;&gt;참조하는 타입의 프로퍼티를 선언하는 문장 앞에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd; color: #eb5757;&quot; data-token-index=&quot;1&quot; data-reactroot=&quot;&quot;&gt;weak&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;를 써 주면 그 프로퍼티는 인스턴스를 약한 참조!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;span style=&quot;color: #000000;&quot;&gt;아래 코드는 약한 참조를 통해 강한 참조 순환 문제를 해결하는 코드&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1636379724210&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
	let name: String
		
	init(name: String) {
		self.name = name
	}
	
	var car: Car?
}

class Car {
	let name: String

	init(name: String) {
		self.name = name
	}

	weak var owner: Person?
}

var jungbin: Person? = Person(name: &quot;JUNGBIN&quot;) // Person RC = 1
var myCar: Car? = Car(name: &quot;BoongBoong&quot;) // Car RC = 1

myCar?.owner = jungbin // Person RC = 1 약한 참조!
jungbin?.car = myCar // Car RC = 2 강한 참조!

jungbin = nil // Person RC = 0, Car RC = 1
print(myCar?.owner) // Person의 인스턴스가 메모리에 없기 때문에 nil(약한 참조 해서 그럼)

myCar = nil // Car RC = 0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;span style=&quot;color: #000000;&quot;&gt;아래에서 세 번째 라인을 보면... 인스턴스가 메모리에서 해제될 때, 자신의 프로퍼티(car)가 강한 참조를 하던 인스턴스(Car 인스턴스)의 RC를 1 감소시킨다는 것을 알 수 있음&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&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>iOS/Swift</category>
      <category>arc</category>
      <category>swift</category>
      <category>weak</category>
      <category>강한참조</category>
      <category>약한참조</category>
      <author>Jungbin</author>
      <guid isPermaLink="true">https://madilyn.tistory.com/30</guid>
      <comments>https://madilyn.tistory.com/30#entry30comment</comments>
      <pubDate>Mon, 8 Nov 2021 22:57:21 +0900</pubDate>
    </item>
    <item>
      <title>[RxSwift] Subject, .scan, RxCocoa, .bind 개념</title>
      <link>https://madilyn.tistory.com/29</link>
      <description>&lt;aside&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/aside&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #777777;&quot;&gt;곰튀김 님의 RxSwift 4시간에 끝내기 (종합편) 영상을 보고 작성한 글입니다 ^~^&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #777777;&quot;&gt;&lt;a href=&quot;https://youtu.be/w5Qmie-GbiA&quot;&gt;https://youtu.be/w5Qmie-GbiA&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;정말 생초보,, 아무것도 모르는 입장에서 강의 영상을 보고 의식의 흐름대로 작성한 글이니 비판의 눈으로 글을 읽어 주시면 감사하겠습니다~~ 오류 지적 대환영!&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;Subject&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Observable 밖에서 값을 받아 와서 컨트롤할 수 있음&lt;/li&gt;
&lt;li&gt;종류 4개(docs 참고)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AsyncSubject&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ceOS9S/btrj3hiXhvw/flKQYqAxcHlrYxdKFwSTRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ceOS9S/btrj3hiXhvw/flKQYqAxcHlrYxdKFwSTRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ceOS9S/btrj3hiXhvw/flKQYqAxcHlrYxdKFwSTRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FceOS9S%2Fbtrj3hiXhvw%2FflKQYqAxcHlrYxdKFwSTRk%2Fimg.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Subcribe가 아무리 많이 들어와도 Complete 시점에 가장 마지막 데이터만 모두에게 내려 줌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;BehaviorSubject&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;830&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B5dxc/btrj4VMXHXo/YQm31nyjLb5jVULPxaPtW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B5dxc/btrj4VMXHXo/YQm31nyjLb5jVULPxaPtW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B5dxc/btrj4VMXHXo/YQm31nyjLb5jVULPxaPtW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB5dxc%2Fbtrj4VMXHXo%2FYQm31nyjLb5jVULPxaPtW1%2Fimg.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;830&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본값 하나 가지고 시작, 누군가가 Subscribe하면 기본값을 내려 줌&lt;/li&gt;
&lt;li&gt;중간에 새롭게 Subscirbe가 들어오면 기본값으로 가장 최근의 값을 내려 줌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PublishSubject&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6N94p/btrkaPdVDxL/23Wlb7Oqi06gv505MLN3O1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6N94p/btrkaPdVDxL/23Wlb7Oqi06gv505MLN3O1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6N94p/btrkaPdVDxL/23Wlb7Oqi06gv505MLN3O1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6N94p%2FbtrkaPdVDxL%2F23Wlb7Oqi06gv505MLN3O1%2Fimg.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Subscribe가 들어오면 그대로 데이터를 내려 줌&lt;/li&gt;
&lt;li&gt;중간에 새롭게 Subscribe가 들어와도 그 중간부터 그대로 내려 줌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ReplaySubject&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rVLrz/btrj876XBYt/d165uLjHCXXznhVDiKjq6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rVLrz/btrj876XBYt/d165uLjHCXXznhVDiKjq6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rVLrz/btrj876XBYt/d165uLjHCXXznhVDiKjq6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrVLrz%2Fbtrj876XBYt%2Fd165uLjHCXXznhVDiKjq6K%2Fimg.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;810&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음부터 Subscribe하면 PublishSubject와 똑같이 데이터 내려 줌&lt;/li&gt;
&lt;li&gt;중간에 Subscribe가 들어오면 그동안의 데이터들을 한번에 Replay하여 내려 줌&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Sugar API&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;.scan&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;256&quot; data-filename=&quot;스크린샷 2021-11-07 오후 3.57.12.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/esWNsY/btrj2T92hn8/JnSBVfaw0ehxAh9Kl7wqp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/esWNsY/btrj2T92hn8/JnSBVfaw0ehxAh9Kl7wqp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/esWNsY/btrj2T92hn8/JnSBVfaw0ehxAh9Kl7wqp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FesWNsY%2Fbtrj2T92hn8%2FJnSBVfaw0ehxAh9Kl7wqp0%2Fimg.png&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;256&quot; data-filename=&quot;스크린샷 2021-11-07 오후 3.57.12.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;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;b&gt;&lt;code&gt;[Scan]&lt;/code&gt;&lt;/b&gt;&amp;nbsp;&amp;mdash; Observable이 배출한 항목에 연속적으로 함수를 적용하고 실행한 후 성공적으로 실행된 함수의 리턴 값을 발행한다&lt;/li&gt;
&lt;li&gt;&lt;code&gt;초기값&lt;/code&gt;-&lt;code&gt;1번&lt;/code&gt; 연산하여 리턴(&lt;code&gt;A&lt;/code&gt;), &lt;code&gt;A&lt;/code&gt;-&lt;code&gt;2번&lt;/code&gt; 연산하여 리턴(&lt;code&gt;B&lt;/code&gt;), &lt;code&gt;B&lt;/code&gt;-&lt;code&gt;3번&lt;/code&gt; 연산하여 리턴(&lt;code&gt;C&lt;/code&gt;), &lt;code&gt;C&lt;/code&gt;-&lt;code&gt;4번&lt;/code&gt; 연산하여 리턴(&lt;code&gt;D&lt;/code&gt;) ...&lt;/li&gt;
&lt;li&gt;초기값과 연산
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;.scan&lt;/code&gt;에 들어올 첫 번째 값은 초기값과 연산됨!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Observable.of(1, 2, 3) // 만약 1, 2, 3이 연속으로 들어온다면
   .scan(0) { (prevValue, newValue) in // 초기값을 0으로!
      return prevValue + newValue
   }
   .subscribe(onNext: { print($0) })&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;// 결과
1 // (초기값 0 + 1)
3 // (기존값 1 + 2)
6 // (기존값 3 + 3)&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;RxCocoa&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Rx를 활용한 UIKit의 Extension 제공&lt;/li&gt;
&lt;li&gt;Sugar API
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;.bind&lt;/code&gt; 순환 참조 없이 사용 가능( .subscribe와 동일)&lt;/li&gt;
&lt;li&gt;.bind (2:25:25~)&lt;/li&gt;
&lt;li&gt;UIKit요소.rx.~ 했을 때 나오는 값이 &lt;code&gt;Binder&lt;/code&gt;면 바인드를 시킬 수 있음&lt;/li&gt;
&lt;li&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-filename=&quot;스크린샷_2021-11-01_오후_9.40.40.png&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;106&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEGyzC/btrkcqZfA7S/IedCq8k4eQ7iQWrv0efsv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEGyzC/btrkcqZfA7S/IedCq8k4eQ7iQWrv0efsv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEGyzC/btrkcqZfA7S/IedCq8k4eQ7iQWrv0efsv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEGyzC%2FbtrkcqZfA7S%2FIedCq8k4eQ7iQWrv0efsv0%2Fimg.png&quot; data-filename=&quot;스크린샷_2021-11-01_오후_9.40.40.png&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;106&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;li&gt;Subscirbe를 하지 않고 bind해서 사용&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1636268330674&quot; class=&quot;swift&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.map { &quot;\($0)&quot; }
.bind(to: itemCountLabel.rx.text)
.disposed(by: disposeBag)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1636268414239&quot; class=&quot;swift&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background-color: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.subscribe(onNext: [weak self] {
	self.itemCountLabel.text = $0
})
.disposed(by: disposeBag)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;위의 두 코드가 같은 동작!&lt;/li&gt;
&lt;li&gt;장점: &lt;code&gt;[weak self]&lt;/code&gt; 같은 순환 참조 방지를 안 해도 됨&lt;/li&gt;
&lt;li&gt;위 코드처럼 UI를 바꾸는 작업을 진행하려면 메인 스케줄러에서 동작시켜야 함!&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1636268444516&quot; class=&quot;swift&quot; style=&quot;display: block; overflow: auto; padding: 20px; color: #383a42; background-color: #f8f8f8; font-size: 14px; font-family: 'SF Mono', Menlo, Consolas, Monaco, monospace; border: 1px solid #ebebeb; line-height: 1.71; margin: 20px auto 0px; cursor: default; z-index: 1; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none;&quot; data-ke-language=&quot;swift&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.map { &quot;\($0)&quot; }
.observeOn(MainScheduler.instance)
.bind(to: itemCountLabel.rx.text)
.disposed(by: disposeBag)&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>iOS/Swift</category>
      <author>Jungbin</author>
      <guid isPermaLink="true">https://madilyn.tistory.com/29</guid>
      <comments>https://madilyn.tistory.com/29#entry29comment</comments>
      <pubDate>Sun, 7 Nov 2021 16:01:25 +0900</pubDate>
    </item>
    <item>
      <title>[RxSwift] Observable의 생명 주기, 순환 참조와 메모리 관리, subscribeOn, observeOn</title>
      <link>https://madilyn.tistory.com/28</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정말 생초보,, 아무것도 모르는 입장에서 강의 영상을 보고 의식의 흐름대로 작성한 글이니 비판의 눈으로 글을 읽어 주시면 감사하겠습니다~~ 오류 지적 대환영!&lt;/b&gt;&lt;/p&gt;
&lt;h1&gt;Observable Life-Cycle&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Create&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;Observable&lt;/code&gt; 생성&lt;/li&gt;
&lt;li&gt;데이터가 생성되거나, 어떤 명령이 동작하지 않음 &amp;rarr; 2. &lt;code&gt;Subscribe&lt;/code&gt;에서 동작!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Subscribe&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떠한 &lt;code&gt;Observable&lt;/code&gt;이 동작함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Next&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;4. Completed&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;4-1. Error&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;5. Disposed&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;Dispose&lt;/code&gt;되면 그 &lt;code&gt;Observable&lt;/code&gt;은 더 이상 재사용 불가&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;.debug()&lt;/code&gt; 로 Observable 상태 확인 가능&lt;/p&gt;
&lt;h1&gt;순환 참조와 메모리 관리&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;.subscribe(onNext: { i in
    self.countLabel.text = &quot;\(i)&quot;
})
.disposed(by: disposeBag)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드에서 &lt;code&gt;subscribe&lt;/code&gt; 내에서 UI 작업을 하느라 &lt;code&gt;self&lt;/code&gt;(ViewController)를 참조. 이미 VC 인스턴스를 생성하면서 한 번 참조된 것임. VC가 pop 되더라도 위 클로저에서 한 번 참조된 게 남아 있음! (4번의 RC=1) 이 VC 인스턴스는 더 이상 안 쓰는데...&amp;rarr; 순환 참조에 의한 메모리 누수(Memory Leak)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2684&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;IMG_EDFD2A81DE62-1.jpeg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FcD1w/btrjsq7jjGO/OmhqkjSDDiwkhvhZCukZ3k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FcD1w/btrjsq7jjGO/OmhqkjSDDiwkhvhZCukZ3k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FcD1w/btrjsq7jjGO/OmhqkjSDDiwkhvhZCukZ3k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFcD1w%2Fbtrjsq7jjGO%2FOmhqkjSDDiwkhvhZCukZ3k%2Fimg.jpg&quot; data-origin-width=&quot;2684&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;IMG_EDFD2A81DE62-1.jpeg&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 누수를 해결하려면 약한 참조(&lt;code&gt;weak self&lt;/code&gt;)를 사용하거나, &lt;code&gt;onCompleted()&lt;/code&gt;를 통해 &lt;code&gt;Subscribe&lt;/code&gt; 클로저 자체를 종료시킨다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;약한 참조(weak self)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;.subscribe(onNext: { [weak self] i in
    self.countLabel.text = &quot;\(i)&quot;
})
.disposed(by: disposeBag)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;weak self&lt;/code&gt;를 안 썼을 때는 자동으로 강한 참조(strong)로 사용됨. &lt;code&gt;weak self&lt;/code&gt;는 위의 코드와 같이 사용하며, 참조될 때 RC를 증가시키지 않는다! 상위 인스턴스가 해제되면(RC- -) 얘는 바로 메모리에서 날아감(RC=0).&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;subscribe&lt;/code&gt;의 클로저를 종료시키는 또 다른 방법: &lt;code&gt;Observable&lt;/code&gt;을 만들 때 &lt;code&gt;onCompleted()&lt;/code&gt; 명시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;emitter.onNext(image)
emitter.onCompleted()
return Disposables.create()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐 이런 식으로... &lt;code&gt;onCompleted&lt;/code&gt;가 꼭 실행되도록 명시하면 &lt;code&gt;Observable&lt;/code&gt; 동작 자체가 종료되면서 메모리가 해제됨.&lt;/p&gt;
&lt;h1&gt;스레드 분기&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;DispatchQueue&lt;/code&gt;, &lt;code&gt;OperationQueue&lt;/code&gt;를 사용하는 대신 &lt;code&gt;observeOn&lt;/code&gt;, &lt;code&gt;subscribeOn&lt;/code&gt;을 사용함! (&lt;code&gt;DispatchQueue&lt;/code&gt;, &lt;code&gt;OperationQueue&lt;/code&gt;를 &lt;code&gt;observeOn&lt;/code&gt;, &lt;code&gt;subscribeOn&lt;/code&gt;가 감싼(wrapping) 개념)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;441&quot; data-origin-height=&quot;504&quot; data-filename=&quot;스크린샷_2021-10-25_오후_11.51.35.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sgd2l/btrjnGJA4UD/3pBcUEdBIOegJxJXhGXKS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sgd2l/btrjnGJA4UD/3pBcUEdBIOegJxJXhGXKS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sgd2l/btrjnGJA4UD/3pBcUEdBIOegJxJXhGXKS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsgd2l%2FbtrjnGJA4UD%2F3pBcUEdBIOegJxJXhGXKS1%2Fimg.png&quot; data-origin-width=&quot;441&quot; data-origin-height=&quot;504&quot; data-filename=&quot;스크린샷_2021-10-25_오후_11.51.35.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;subscribeOn&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 번만 사용 가능, &lt;b&gt;구독&lt;/b&gt; 시 시작할 스레드 지정&lt;/li&gt;
&lt;li&gt;subscribeOn이 지정된 위치에 상관없이 첫 스레드를 지정함!&lt;/li&gt;
&lt;li&gt;위에 있는 Stream에 영향을 줌 &amp;rarr; &lt;b&gt;업스트림(Up Stream)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;observeOn&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 번 사용 가능, observeOn에서 스레드를 지정한 후 그 아래부터의 Stream에 작동 &amp;rarr; &lt;b&gt;다운스트림(Down Stream)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Stream의 분리 및 병합&lt;/h1&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;merge&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Observable 2개를 1개로 merge&lt;/li&gt;
&lt;li&gt;하나로 합쳐야 하기 때문에 데이터 타입을 통일해야 함!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;zip&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쌍으로 만들어 전달 &amp;rarr; 데이터 타입 달라도 상관 X&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;1----2--------3---------4----&amp;gt;
B----------C---A-------------&amp;gt;
########### zip ############
1B---------2C--3A------------&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터의 개수는 가장 작은 스트림의 데이터 개수와 동일!&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;combineLatest&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;zip과의 차이점: 가장 최근의 데이터와 쌍을 이뤄 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;1----2--------3---------4----&amp;gt;
B----------C---A-------------&amp;gt;
######### combineLatest #########
1B---2B----C2-3C--A3----4A---&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://its-blog.tistory.com/m/92?category=779968&quot;&gt;https://its-blog.tistory.com/m/92?category=779968&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://m.blog.naver.com/mym0404/221596834186&quot;&gt;https://m.blog.naver.com/mym0404/221596834186&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>iOS/Swift</category>
      <author>Jungbin</author>
      <guid isPermaLink="true">https://madilyn.tistory.com/28</guid>
      <comments>https://madilyn.tistory.com/28#entry28comment</comments>
      <pubDate>Sun, 31 Oct 2021 20:51:32 +0900</pubDate>
    </item>
    <item>
      <title>기획자 없이 서비스 만들기 - 버그/업데이트 리포트 편</title>
      <link>https://madilyn.tistory.com/27</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;현재 근무하고 있는 회사에 서비스 기획자가 없는 관계로 개발자들이 자급자족하며 개발하고 있는데, 어쩌다 보니 나름의 PM도 담당해 기획도 찍먹(?) 중이다. 사실 학부 수업으로 서비스 기획 관련해서 수업을 듣긴 했지만 실전 경험은 전무해서 우왕좌왕 비효율적인 프로세스로 개발을 해왔던 것 같은데(개발하느라바빴음), 나름 체계를 잡고자 했던 것과 느낀 점이 들어간 글을 써 보려고 한다.&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;오늘은! 요 시리즈 첫 글이지만! 출시 후 업데이트 및 유지보수를 진행하면서 생각했던 것들을 정리해 보려고 한다. 여차저차해서 어떻게 어떻게 서비스를 개발해 릴리즈까지는 성공했다고 치고, (일정에 쫓겨) 개발자로서 효율적으로 구현하지 못한 부분들은 생각날 때마다 github issue에 뿌려 놓은 상황.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Group 1.png&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpiwA7/btriitS8kVL/wlpAKkyOZ1XzNK17zkOn70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpiwA7/btriitS8kVL/wlpAKkyOZ1XzNK17zkOn70/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpiwA7/btriitS8kVL/wlpAKkyOZ1XzNK17zkOn70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpiwA7%2FbtriitS8kVL%2FwlpAKkyOZ1XzNK17zkOn70%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;399&quot; height=&quot;456&quot; data-filename=&quot;Group 1.png&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;대충 요런 식...? 근데 뭐 이건 저 혼자 볼 거라 상관없고. 문제는 QA 때&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;'이거 안 되는데요?' '이거 멈춰요.' '이거 튕겨요.' '이거(~~~~) 추가해 주세요.'&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 같은 방법으로 다시 작동시켰을 때 동일한 증상이 나타나나요?&lt;br /&gt;2. 로그인 상태인가요? 비로그인 상태인가요?&lt;br /&gt;3. iOS 버전과 기종 알려 주실래요?&lt;br /&gt;4. TestFlight 충돌 공유 보내셨나요?&lt;br /&gt;4-1. 안 보내셨으면 다시 시도하셔서 충돌 리포트 넘겨 주세요.&lt;br /&gt;5. 전후 상황 포함해 재현 과정 말씀해 주세요.&lt;br /&gt;6. 동영상으로 녹화해 주세요.&amp;nbsp;&lt;br /&gt;7. 등등...&lt;/blockquote&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;color: #000000;&quot;&gt;&amp;nbsp;그래서 오늘 노션으로 &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;버그 수정 요청 문서&lt;/span&gt;, &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;기능 추&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;가 요청 문서&lt;/span&gt; 작성 양식을 만들었다!&lt;/span&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;스크린샷 2021-10-20 오후 8.29.50.png&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;391&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lUSEH/btrijsfqos4/BmWlnbmls5UIUoDkZkoJQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lUSEH/btrijsfqos4/BmWlnbmls5UIUoDkZkoJQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lUSEH/btrijsfqos4/BmWlnbmls5UIUoDkZkoJQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlUSEH%2Fbtrijsfqos4%2FBmWlnbmls5UIUoDkZkoJQK%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;904&quot; height=&quot;391&quot; data-filename=&quot;스크린샷 2021-10-20 오후 8.29.50.png&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;391&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2021-10-20 오후 8.30.59.png&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lrhkZ/btrim6WVp1L/27yn7DeUxS8mydAjGLfMsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lrhkZ/btrim6WVp1L/27yn7DeUxS8mydAjGLfMsK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lrhkZ/btrim6WVp1L/27yn7DeUxS8mydAjGLfMsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlrhkZ%2Fbtrim6WVp1L%2F27yn7DeUxS8mydAjGLfMsK%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;1114&quot; height=&quot;362&quot; data-filename=&quot;스크린샷 2021-10-20 오후 8.30.59.png&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;안에 템플릿도 넣어 둠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style16&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2021-10-20 오후 8.31.57.png&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;1942&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8WPei/btrioobwRFr/N4rZ72hwP3A7ktSY9ZrAW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8WPei/btrioobwRFr/N4rZ72hwP3A7ktSY9ZrAW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8WPei/btrioobwRFr/N4rZ72hwP3A7ktSY9ZrAW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8WPei%2FbtrioobwRFr%2FN4rZ72hwP3A7ktSY9ZrAW0%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;1252&quot; height=&quot;1942&quot; data-filename=&quot;스크린샷 2021-10-20 오후 8.31.57.png&quot; data-origin-width=&quot;1252&quot; data-origin-height=&quot;1942&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;905&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QVDrh/btripFX9TdT/eaqW38ksTCCCRkqTohUmk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QVDrh/btripFX9TdT/eaqW38ksTCCCRkqTohUmk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QVDrh/btripFX9TdT/eaqW38ksTCCCRkqTohUmk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQVDrh%2FbtripFX9TdT%2FeaqW38ksTCCCRkqTohUmk1%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;399&quot; height=&quot;657&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;905&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식이다!!!!!&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;요구사항png.png&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;1216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eCedP5/btrikMkrWzZ/ubXg9e2RZIqsQ6eu25ON0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eCedP5/btrikMkrWzZ/ubXg9e2RZIqsQ6eu25ON0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eCedP5/btrikMkrWzZ/ubXg9e2RZIqsQ6eu25ON0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeCedP5%2FbtrikMkrWzZ%2FubXg9e2RZIqsQ6eu25ON0K%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;1205&quot; height=&quot;1216&quot; data-filename=&quot;요구사항png.png&quot; data-origin-width=&quot;1205&quot; data-origin-height=&quot;1216&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;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://madilyn.notion.site/085d2d3402fe40f58f57ec80a5d3a110?v=e59c64c5ba714cb7b8ec352b88bbdf67&quot;&gt;https://madilyn.notion.site/085d2d3402fe40f58f57ec80a5d3a110?v=e59c64c5ba714cb7b8ec352b88bbdf67&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1634730133369&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;Update plan&quot; data-og-description=&quot;효율적이고 빠른 개선을 위해 양식에 맞게 요구사항을 작성해 주세요. new feature  은 개발팀에게 새로운 기능 추가를 요청할 때 사용합니다. bug  는 개발팀에게 버그 수정을 요청할 때 사용합&quot; data-og-host=&quot;madilyn.notion.site&quot; data-og-source-url=&quot;https://madilyn.notion.site/085d2d3402fe40f58f57ec80a5d3a110?v=e59c64c5ba714cb7b8ec352b88bbdf67&quot; data-og-url=&quot;https://madilyn.notion.site/085d2d3402fe40f58f57ec80a5d3a110&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://madilyn.notion.site/085d2d3402fe40f58f57ec80a5d3a110?v=e59c64c5ba714cb7b8ec352b88bbdf67&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://madilyn.notion.site/085d2d3402fe40f58f57ec80a5d3a110?v=e59c64c5ba714cb7b8ec352b88bbdf67&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Update plan&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;효율적이고 빠른 개선을 위해 양식에 맞게 요구사항을 작성해 주세요. new feature  은 개발팀에게 새로운 기능 추가를 요청할 때 사용합니다. bug  는 개발팀에게 버그 수정을 요청할 때 사용합&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;madilyn.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>essay</category>
      <author>Jungbin</author>
      <guid isPermaLink="true">https://madilyn.tistory.com/27</guid>
      <comments>https://madilyn.tistory.com/27#entry27comment</comments>
      <pubDate>Wed, 20 Oct 2021 20:44:09 +0900</pubDate>
    </item>
    <item>
      <title>[RxSwift] 이게 맞나? 싶은 RxSwift 개념 정리</title>
      <link>https://madilyn.tistory.com/26</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #777777;&quot;&gt;곰튀김 님의 RxSwift 4시간에 끝내기 (종합편) 영상을 보고 작성한 글입니다 ^~^&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #777777;&quot;&gt;&lt;a href=&quot;https://youtu.be/w5Qmie-GbiA&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://youtu.be/w5Qmie-GbiA&lt;/a&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: #8a3db6;&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;b&gt;[1교시] 개념잡기 - RxSwift를 사용한 비동기 프로그래밍&lt;/b&gt;&lt;/p&gt;
&lt;h1&gt;✈️ Rx의 목적&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기적으로 만들어지는 데이터(언제 만들어질지 모름)를 &lt;code&gt;completion&lt;/code&gt;으로 전달하는 게 아니라 리턴 값으로 전달하여 좀 더 간결하게 사용하도록 만들어진 유틸리티&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간이 걸리는 작업 도중 취소 시 유용&lt;/li&gt;
&lt;li&gt;동기/비동기 처리 쉽고 간단하게&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;create, subscribe, disposable&lt;/h2&gt;
&lt;pre class=&quot;swift&quot;&gt;&lt;code&gt;// MARK: RxSwift 원형 사용
    func showImageRx(_ url: String) -&amp;gt; Observable&amp;lt;UIImage?&amp;gt;{
        return Observable.create { seal in
            asyncLoadImage(from: url) { image in
                **seal.onNext(image) // 2
                seal.onCompleted() // 4**
            }
            return Disposables.create()
        }
    }

@IBAction func tapDownloadRxBtn(_ sender: Any) {
        disposable = showImageRx(imageURLStr)
            .observe(on: MainScheduler.instance) // 1 5
            **.subscribe**({ result in
                switch result {
                case let .next(image): // 3
                    print(&quot;called .next&quot;)
                    self.imageView.image = image
                case let .error(err):
                    print(err.localizedDescription)
                case .completed: // 6
                    print(&quot;called .completed&quot;)
                    break
                }
            })
    }
@IBAction func tapDisposeBtn(_ sender: Any) {
        disposable?.dispose()
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요런 함수를 만들어서 &lt;code&gt;tapDownloadRxBtn&lt;/code&gt;을 실행시켰을 때! 로그에 이렇게 찍히는 걸 볼 수 있음&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;151&quot; data-origin-height=&quot;36&quot; data-filename=&quot;스크린샷_2021-10-12_오후_7.33.02.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2djhQ/btrhFRMVYsq/hAJ8G7B2ReQCeQRt77cgok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2djhQ/btrhFRMVYsq/hAJ8G7B2ReQCeQRt77cgok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2djhQ/btrhFRMVYsq/hAJ8G7B2ReQCeQRt77cgok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2djhQ%2FbtrhFRMVYsq%2FhAJ8G7B2ReQCeQRt77cgok%2Fimg.png&quot; data-origin-width=&quot;151&quot; data-origin-height=&quot;36&quot; data-filename=&quot;스크린샷_2021-10-12_오후_7.33.02.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 생각엔.. 주석 달아 놓은 순서대로 처리되는 것 같슴다..&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;Main 스레드에서 돌아가는(UI 작업을 처리해야 하기 때문), &lt;code&gt;Observable&lt;/code&gt; 객체를 리턴하는 &lt;code&gt;showImageRx()&lt;/code&gt; 를 만들어 두고, &lt;code&gt;asyncLoadImage()&lt;/code&gt;를 통해 만들어진 image를 &lt;code&gt;onNext&lt;/code&gt; &amp;rarr; &lt;code&gt;onCompleted&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;&lt;code&gt;onNext&lt;/code&gt; &amp;rarr; &lt;code&gt;switch-case&lt;/code&gt; 문의 &lt;code&gt;.next&lt;/code&gt;로 빠져 구문을 실행하고, 완료되면 다음 작업인 &lt;code&gt;onCompleted&lt;/code&gt; &amp;rarr; &lt;code&gt;.completed&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;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;  Subscribe&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;&lt;code&gt;.subscribe&lt;/code&gt;의 &lt;code&gt;result&lt;/code&gt;의 경우의 수는 &lt;code&gt;switch-case&lt;/code&gt; 문처럼 있으며, 다른 경우를 추가할 수도 있겠음. 이들은 구독과알림설정처럼... &lt;code&gt;result&lt;/code&gt;로 들어오는 친구들에 대해 작업을 수행하려고 항상 구독ON 상태인 게 아닐까...??????&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;  Dispose &amp;rarr; 취소&lt;/h1&gt;
&lt;pre class=&quot;swift&quot;&gt;&lt;code&gt;// 선언
var disposable: Disposable?

// dispose
disposable?.dispose()&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DisposeBag(가방): Dispose들을 담는 곳, 여러개의 Dispose들을 담아서 한번에 처리 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;// 선언
var disposeBag = DisposeBag()

// dispose
Observable.just(&quot;Hello World&quot;)
            .subscribe(onNext: { str in
                print(str)
            })
            **.disposed(by: disposeBag)**

// 모든 Observable 초기화
disposeBag = DisposeBag()&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Dispose를 해야 하는 이유 - 야곰닷넷 게시글에서 발췌&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;1025&quot; data-origin-height=&quot;86&quot; data-filename=&quot;스크린샷_2021-10-12_오후_8.54.06.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dynLc6/btrhAMscJUm/30lYuKWk0Vz5WW7kzzI7Ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dynLc6/btrhAMscJUm/30lYuKWk0Vz5WW7kzzI7Ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dynLc6/btrhAMscJUm/30lYuKWk0Vz5WW7kzzI7Ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdynLc6%2FbtrhAMscJUm%2F30lYuKWk0Vz5WW7kzzI7Ck%2Fimg.png&quot; data-origin-width=&quot;1025&quot; data-origin-height=&quot;86&quot; data-filename=&quot;스크린샷_2021-10-12_오후_8.54.06.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;  Observable 다양하게 사용하기&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정의를 뭐라고 내리면 좋을까...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;xquery&quot;&gt;&lt;code&gt;Observable.just(&quot;800x600&quot;)
            .map { $0.replacingOccurrences(of: &quot;x&quot;, with: &quot;/&quot;) }
            .map { &quot;https://picsum.photos/\($0)/?random&quot; }
            .map { URL(string: $0) }
            .filter { $0 != nil }
            .map { $0! }
            .map { try Data(contentsOf: $0) }
            .map { UIImage(data: $0) }
            .subscribe(onNext: { image in
                self.imageView.image = image
            })
            .disposed(by: disposeBag)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;.just (생성)&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;.from (생성)&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;li&gt;&lt;code&gt;.from([&quot;RxSwift&quot;, &quot;In&quot;, 4, &quot;Hours&quot;])&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;.map (변형)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무언가 받은 값이 있을 때! 걔를 &lt;code&gt;{ 어떻게 처리함 }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.map { str in &quot;\(str) RxSwift&quot; }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;from 등 생성하는 친구들과 같이 쓸 수 있음!
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이렇게 줄 세워서 &lt;code&gt;from&lt;/code&gt; 거쳤다가 &lt;code&gt;map&lt;/code&gt; 거쳤다가 &lt;code&gt;subscribe&lt;/code&gt;까지... 주르륵 이어지는 것을 &lt;b&gt;Stream&lt;/b&gt;이라고 함!&lt;/li&gt;
&lt;li&gt;Observable의 나열들(Stream)으로 비동기 프로그래밍 하는 것이 Rx..~~!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-swift&quot;&gt;  Observable.from([&quot;with&quot;, &quot;곰튀김&quot;])
              .map { $0.count }
              .subscribe(onNext: { str in
                  print(str)
              })
  // 4 3&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;.filter (필터)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;if&lt;/code&gt;문처럼 &lt;code&gt;true&lt;/code&gt;일 때만 밑으로 내려가도록(통과하도록) 사용!&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;➕ 추가로 정리하면 좋을 내용(개개개개개개개개ㅐ인적)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$0, $1... 이란? - 항상 정확한 의미를 모르는 채로 사용해 왔는데 다음 스터디에서 이걸 정리해 주시는 분이 계셔서 신난다!&lt;/p&gt;</description>
      <category>iOS/Swift</category>
      <category>RxSwift</category>
      <category>swift</category>
      <category> &amp;zwj; </category>
      <author>Jungbin</author>
      <guid isPermaLink="true">https://madilyn.tistory.com/26</guid>
      <comments>https://madilyn.tistory.com/26#entry26comment</comments>
      <pubDate>Thu, 14 Oct 2021 01:39:24 +0900</pubDate>
    </item>
  </channel>
</rss>