<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>땀이 삐질삐질 나는 개발 일기</title>
    <link>https://ppizil.tistory.com/</link>
    <description>안드로이드 개발자로 일 하며  경험을 공유합니다</description>
    <language>ko</language>
    <pubDate>Thu, 18 Jun 2026 16:42:47 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>삐질</managingEditor>
    <item>
      <title>클린아키텍쳐를 사용하면서.. 클린했나?</title>
      <link>https://ppizil.tistory.com/entry/%ED%81%B4%EB%A6%B0%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%A9%B4%EC%84%9C-%ED%81%B4%EB%A6%B0%ED%96%88%EB%82%98</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요. 오랜만에 블로그를 방문해 글을 남겨봅니다. 오늘은 클린 아키텍처(Clean Architecture)에 대한 저의 지극히 주관적인 생각을 나누고자 합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;567&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7qjhI/btsHSe87Q4w/K48C5kEwWy5wuSDxNi1cnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7qjhI/btsHSe87Q4w/K48C5kEwWy5wuSDxNi1cnK/img.png&quot; data-alt=&quot;다이어그램&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7qjhI/btsHSe87Q4w/K48C5kEwWy5wuSDxNi1cnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7qjhI%2FbtsHSe87Q4w%2FK48C5kEwWy5wuSDxNi1cnK%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;772&quot; height=&quot;567&quot; data-origin-width=&quot;772&quot; data-origin-height=&quot;567&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다이어그램&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;472&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkMni8/btsHQfIRaWE/4cYp1voqK2gK1OnsVOOsgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkMni8/btsHQfIRaWE/4cYp1voqK2gK1OnsVOOsgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkMni8/btsHQfIRaWE/4cYp1voqK2gK1OnsVOOsgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkMni8%2FbtsHQfIRaWE%2F4cYp1voqK2gK1OnsVOOsgK%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;1280&quot; height=&quot;472&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;472&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클린 아키텍처를 나름대로 사용하고 고민한 지 어느덧 3년이 넘었습니다. 다른 분들은 어떤 이유로 클린 아키텍처에 입문하셨는지 모르겠지만, 제가 처음 클린 아키텍처의 세계로 들어갔던 과정을 돌아보면 다음과 같습니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Activity에 모든 코드를 작성하던 주니어 시절&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Google을 탐험하며 만들었던 나름대로의 Model 구조&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터 관리를 편하게 하기 위한 Singleton 사용 구조&lt;/b&gt; (뭔가 기술을 쓴 듯 뿌듯)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유지보수의 어려움을 느껴 찾아 헤맸던 시간&lt;/b&gt; (기획자와 대표는 왜 이렇게 변덕이 심한지...)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주변으로부터 추천받은 Effective Java나 OOP&lt;/b&gt; (봐도 봐도 무슨 소린지...)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;우여곡절 끝에 진입한 MVC&lt;/b&gt; (분리하니까 뭔가 좋은 것도 같지만...)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MVC를 잘 사용하고 있는지에 대한 의문&lt;/b&gt; (이상하게 코드가 더 많아지는 것 같기도 하고, 모델이 이게 맞나?)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;등장한 MVP, MVVM과 Kotlin&lt;/b&gt; (솔직히 MVC 쓰면서도 Dependency와 SRP 등 잘 모르겠는데 이게 뭐지?)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MVP와 MVVM의 러닝커브를 보고 기겁한 나&lt;/b&gt; (무슨 소린지 당최 모르겠군)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이직하려고 보니 대부분의 요구사항은 MVVM&lt;/b&gt; (해야겠는데 MVP와 MVVM 중 무엇을?)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;트렌드에 맞춰 시작해본 MVVM&lt;/b&gt; (VM 분리와 Model, Databinding 너무너무 편한데?!)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MVVM도 버거운데 들리는 Clean Architecture&lt;/b&gt; (아키텍처..? 아키텍처가 뭐지?)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;트렌드를 따라가지 못하면 뒤쳐지는 것이 아닌가 하는 불안함에 시작된 Clean Architecture&lt;/b&gt; (일단 해보자)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 더 많은 과정들이 있었지만, 이런 과정을 통해 요즘 유행하는 클린 아키텍처 + MVVM 유형의 기법들을 사용하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기에는 암기 과목을 공부하듯 이해는 안되지만, 단순 무식하게 코드를 작성하고 커뮤니티에서 '이러면 된다.', '저러면 된다.', '클린 아키텍처는 이래야 한다.' 등의 파편적인 정보들과 나름대로 공부한 정보들을 통해 익숙함을 높였습니다. 그러나 필요에 의해 사용하는 것이 아닌 맹목적인 사용이다 보니 이해의 영역과는 멀어지게 되었습니다. 때론 MVVM과 클린 아키텍처는 항상 세트구나, MVVM == 클린 아키텍처구나 하는 시기도 있었던 것 같습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;클린 아키텍처는 정말 클린한가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본론으로 돌아와 클린 아키텍처는 정말 클린한가? 라는 질문을 생각해보면, 여러분들은 어떠신가요? 정말 클린한가요?&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 기능을 만들기 위해 클린 아키텍처의 기조를 따를 때 Presentation / Domain / Data 레이어에 생성되는 무수한 파일들... Clean한가요?&lt;/li&gt;
&lt;li&gt;Layer 간 만들어놓은 Mapper들. 왜 사용하는지에 대한 이해가 Clean한가요?&lt;/li&gt;
&lt;li&gt;Domain Layer의 Usecase와 Entity의 차이의 이해, Clean한가요?&lt;/li&gt;
&lt;li&gt;Usecase의 Input value와 Output value와 Entity의 필요성, Clean한가요?&lt;/li&gt;
&lt;li&gt;Domain이라는 개념, Clean한가요?&lt;/li&gt;
&lt;li&gt;Presentation 로직과 Business Logic의 차이, Clean한가요?&lt;/li&gt;
&lt;li&gt;인터넷에 떠도는 Clean Architecture Diagram의 이해, Clean한가요?&lt;/li&gt;
&lt;li&gt;Usecase는 N개의 Repo를 받아도 되는가에 대한 질문, Clean한가요?&lt;/li&gt;
&lt;li&gt;Usecase는 어느 정도의 단위로 나누어야 할까요, Clean한가요?&lt;/li&gt;
&lt;li&gt;Domain레이어에 플랫폼 프레임웍을 반드시 배제해야한다. 다른 플랫폼에도 삽입할 수 있을만큼.. &amp;rarr; 정말 다른 플랫폼에 삽입을 해본적!? , Clean한가요?&lt;/li&gt;
&lt;li&gt;하다 보니 Presentation, Domain, Data에 동일한 속성의 DataClass들... Clean한가요?&lt;/li&gt;
&lt;li&gt;Repository와 DataSource의 차이, Clean한가요?&lt;/li&gt;
&lt;li&gt;Clean Architecture를 사용해서 정말로 유용한가, Clean한가요?&lt;/li&gt;
&lt;li&gt;DI (Hilt), 무수히 사용하는 Interface, Impl 구조의 구현의 유용성, Clean한가요?&lt;/li&gt;
&lt;/ul&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;또는 스스로 Clean하다고 생각하시나요? 저 중에 몇 가지는 지금까지도 고민하는 문제이기도 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;511&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lFGBE/btsHQHLADC4/GMQKHDgLzKh62mScQWJMpk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lFGBE/btsHQHLADC4/GMQKHDgLzKh62mScQWJMpk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lFGBE/btsHQHLADC4/GMQKHDgLzKh62mScQWJMpk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlFGBE%2FbtsHQHLADC4%2FGMQKHDgLzKh62mScQWJMpk%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;511&quot; height=&quot;340&quot; data-origin-width=&quot;511&quot; data-origin-height=&quot;340&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안드로이드 개발자들과 이야기를 나누다 보면, 조금은 맹목적인 분위기를 많이 느끼곤 합니다. &lt;b&gt;무조건 시작부터 클린 아키텍처를 써야 좋다&lt;/b&gt;는 의견, &lt;b&gt;클린 아키텍처가 아키텍처의 왕&lt;/b&gt;이라는 의견, &lt;b&gt;클린 아키텍처를 쓸 거면 반드시 클린 아키텍처의 정의들대로&lt;/b&gt; 코드를 작성해야 한다는 의견 등 다양한 의견들이 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;340&quot; data-origin-height=&quot;316&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JOnSB/btsHQjRSmP5/5BQf9PJZ261pNFm9gSVzG0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JOnSB/btsHQjRSmP5/5BQf9PJZ261pNFm9gSVzG0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JOnSB/btsHQjRSmP5/5BQf9PJZ261pNFm9gSVzG0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/JOnSB/btsHQjRSmP5/5BQf9PJZ261pNFm9gSVzG0/img.gif&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;340&quot; height=&quot;316&quot; data-origin-width=&quot;340&quot; data-origin-height=&quot;316&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;b&gt;&quot;사용법&quot;에 대한 글이 많습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JdQbx/btsHR8BdDJX/XdqHXIzfDk3fDtM7O1onv1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JdQbx/btsHR8BdDJX/XdqHXIzfDk3fDtM7O1onv1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JdQbx/btsHR8BdDJX/XdqHXIzfDk3fDtM7O1onv1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJdQbx%2FbtsHR8BdDJX%2FXdqHXIzfDk3fDtM7O1onv1%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;612&quot; height=&quot;612&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Domain의 Entity가 하는 역할이 매우 빈약하고, Usecase의 구현법에만 치중함.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 단순히 레이어 간 분리에만 포커스를 맞추어 Presentation / Domain / Data에 동일한 DataClass가 모든 피쳐마다 존재하는 것을 원래 레이어를 분리하려면 이렇다거나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Domain이 가장 안쪽의 영역인데, API의 응답에 따라 어떻게 받을지를 고민하거나 (이러면 Domain이 Data에 의존성이 생기게 됩니다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;위 고민들은 이렇게 짜면 안될것 같은데... 라고 스스로 아이러니 함을 느끼면서도 관성처럼 코드를 짜는 중의 제 고민이기도 했습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;저는 요즘 클린 아키텍처의 핵심은 익히 알고있는대로 Domain과 레이어링이고 이때 도메인이라는 계층을 나누는것 보다 중요한것이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Domain이라는 추상적인 개념이 무엇을 의미하는지 이해하고, 이 Domain의 특성에 따른 Entity를 구체적으로 설계한는 것이 가장 중요하다고 생각하고 있습니다.&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;Domain, DDD, Entity, Event등에 관해 고민을 이어나가고 있습니다.&amp;nbsp; 이러한 고민이 없으면 오히려 Domain계층으로 인해 내 전체 프로젝트의 코드가 지저분해지기만 하는 현상을 겪으실 수 있습니다. 또한 정말 데이터를 담기만 하는 Immutable한 DataClass들이 비슷한 네이밍으로 이것저것 만들어져있는 카오스를 경험하시게 될것입니다.&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;또한 DI까지 도입해가며 레이어링과 인터페이스 분리를 해도 이 과정을 통해 테스트 코드를 작성해 내 코드를 검증하지 않으면 이것은 단순히 코드를 복잡하게 짜는 것일 뿐입니다. TDD를 적용하라는 이야기는 아닙니다. 다만, 우리가 OOP에 입각해 클린 아키텍처를 적용했다면 이 코드들이 잘 작성되었는지 &amp;ldquo;검증&amp;rdquo;까지 하는 것이 진정한 클린 아키텍처를 사용한다고 할 수 있을 것입니다.&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;지금은 제 나름대로 시행착오를 겪어, Domain Entity설계, Event분리,&amp;nbsp; Domain Layer에서의 ErrorHandling등 어느정도 고정된 포맷을 가지고 코드를 작성하고 있습니다. 더불어 모든 상황에 클린아키텍쳐를 사용하진 않으리라는 확신이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 과정들로 꼭 유행중인 클린아키텍쳐의 사용 이라는 고민에서 끝나지 않고 각자의 결론을 낼 수 있도록 끝까지 고민해보시길 바라겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분들은 클린 아키텍처에 대해 어떻게 생각하시나요? 여러분의 경험과 생각을 나누어 주시면 감사하겠습니다.&lt;/p&gt;</description>
      <category>개발자 일기</category>
      <category>MVVM</category>
      <category>안드로이드 아키텍쳐</category>
      <category>클린아키텍쳐</category>
      <author>삐질</author>
      <guid isPermaLink="true">https://ppizil.tistory.com/51</guid>
      <comments>https://ppizil.tistory.com/entry/%ED%81%B4%EB%A6%B0%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%A9%B4%EC%84%9C-%ED%81%B4%EB%A6%B0%ED%96%88%EB%82%98#entry51comment</comments>
      <pubDate>Fri, 7 Jun 2024 15:12:53 +0900</pubDate>
    </item>
    <item>
      <title>[Android] WifiDebug  스크립트로 한 큐에!</title>
      <link>https://ppizil.tistory.com/entry/Android-WifiDebug-%EC%89%98%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9E%90%EB%8F%99%ED%99%94-%EA%B9%8C%EC%A7%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요. 개발자 삐질 입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;굉장히 오랜만에 아주 간단하지만 유용한 포스팅 하나 하려고 페이지를 열었네요.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;기존에 이 기능관련해서 사용하고 계시고 &amp;amp;&amp;amp;&amp;nbsp; 맥 기준이에욥!&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 저희가 ShellScript를 통해 adb tcpip , adb connect 또는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안드로이드 스튜디오에서 자체적으로 안드로이드 SDK 특정 버전 이상에서 제공하는 자체 wifi debugging을 사용하고 계셨을 텐데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 안드로이드 스튜디오가 자체 지원함에도 불구하고, ShellScript를 주로 애용해요!.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중요한 점은, 끊겨도 우리 터미널에서 기존 입력했던 명령어를 불러와서 바로 재실행하면 1초 만에 재연결이 가능하다는 점이죠!&lt;/li&gt;
&lt;/ul&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;Shell 환경변수에 ADB 경로와, JDK 등 외적인 것들은 등록이 되어있다는 것을 가정할게요!&lt;br /&gt;( 안되어 있으신 분들은 타 블로그를 참고해 주세요!. 너무 설명 잘해주심.. )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 원하는 경로에 .sh 파일을 하나 만들 거예요.&lt;br /&gt;&amp;nbsp; &amp;nbsp;sudo nano ${경로}/wdb.sh&lt;br /&gt;처럼 원하는 방법으로 원하는 파일명으로 만들어주세요.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt; #!/bin/bash

function getWireConnectedDevices() {
    device_list=$(adb devices -l | awk 'NR&amp;gt;1 {print $1}')
    device_ips=()
    for device_serial in $device_list; do
        if [[ $device_serial =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+$ ]]; then
            continue
        fi
        device_ip=$(adb -s $device_serial shell ip route | awk '{print $9}')
        device_ips+=(&quot;$device_ip&quot;)
    done
    echo &quot;${device_ips[@]}&quot;
}

function connectAllDevices() {
    device_ips=($(getWireConnectedDevices))
    for device in &quot;${device_ips[@]}&quot;; do
        adb connect &quot;${device}:7989&quot;
    done
    echo
}

function cleanExecute() {
    adb kill-server
    sleep 1
    adb start-server
    sleep 1
    adb_status=$(adb get-state 2&amp;gt;&amp;amp;1)
    if [[ $adb_status == *&quot;offline&quot;* ]]; then
        echo &quot;장치가 연결되지 않았습니다. USB 연결을 확인해주세요.&quot;
        exit 1
    fi
    adb tcpip 7989
    sleep 1
    connectAllDevices
}

function showWireConnectedDevices() {
    device_ips=($(getWireConnectedDevices))
    for index in &quot;${!device_ips[@]}&quot;; do
        echo &quot;$((index+1)). ${device_ips[index]}&quot;
    done
    echo &quot;연결을 원하시는 번호를 선택해 주세요.&quot;
    read -r number
    if [[ $number =~ ^[0-9]+$ ]]; then
        selected_device_ip=&quot;${device_ips[number-1]}&quot;
        adb connect &quot;${selected_device_ip}:7989&quot;
    else
        echo &quot;올바른 번호를 입력하세요.&quot;
    fi
    echo
}

while true; do
    echo &quot;1. 최초 연결 또는 신규 디바이스 추가 시&quot;
    echo &quot;2. 기존에 연결했었던 디바이스 목록 재연결&quot;
    echo &quot;3. 디바이스 목록 보기&quot;
    echo &quot;4. 종료&quot;
    read -rp &quot;원하는 작업 번호를 입력하세요: &quot; choice

    case $choice in
        1)
            cleanExecute
            clear
            ;;
        2)
            connectAllDevices
            clear
            ;;
        3)
            showWireConnectedDevices
            clear
            ;;
        4)
            echo &quot;프로그램을 종료합니다.&quot;
            break
            ;;
        *)
            echo &quot;올바른 작업 번호를 입력하세요.&quot;
            ;;
    esac

done&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;p data-ke-size=&quot;size16&quot;&gt;2. 그리고 위 스크립트 내용을 붙여 넣기 해주세요. (&amp;nbsp; 제 자작인데... 퍼가셔도 됨!!! 선순환되기를 )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 이 파일을 이제 간단히 ifconfig 명령어처럼 단순하게 명령어 만으로 실행할 수 있도록 경로를 등록해 줄 거예요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 터미널에 open ~/.zshrc&amp;nbsp; 또는 가지고 계신 shell의 config파일을 열어주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 아무 위치에 방금 만든 ${path}/${파일명}.sh파일의 경로를 붙여 넣습니다.&lt;br /&gt;alias &lt;span style=&quot;color: #ee2323;&quot;&gt;wdb&lt;/span&gt;='${path}/${파일명}.sh'&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 편집기를 종료하고 다시 터미널에&amp;nbsp; source ~/.zshrc 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 터미널에&amp;nbsp;&lt;span style=&quot;color: #ee2323; text-align: start;&quot;&gt;wdb&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&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-origin-width=&quot;2000&quot; data-origin-height=&quot;777&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SdzlO/btsjJdF2TIa/t2K8tZjHObmOYiHKGKW6bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SdzlO/btsjJdF2TIa/t2K8tZjHObmOYiHKGKW6bk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SdzlO/btsjJdF2TIa/t2K8tZjHObmOYiHKGKW6bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSdzlO%2FbtsjJdF2TIa%2Ft2K8tZjHObmOYiHKGKW6bk%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;2000&quot; height=&quot;777&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;777&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8. 짠~ 이제 원하시는 대로 작업하시면 됩니다. ~&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;a href=&quot;https://open.kakao.com/o/gH0XvThc&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;</description>
      <category>개발 Tip</category>
      <author>삐질</author>
      <guid isPermaLink="true">https://ppizil.tistory.com/50</guid>
      <comments>https://ppizil.tistory.com/entry/Android-WifiDebug-%EC%89%98%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9E%90%EB%8F%99%ED%99%94-%EA%B9%8C%EC%A7%80#entry50comment</comments>
      <pubDate>Tue, 13 Jun 2023 11:48:31 +0900</pubDate>
    </item>
    <item>
      <title>BitBucket Authorization failed  ( passwd invalid)일떄</title>
      <link>https://ppizil.tistory.com/entry/BitBucket-Authorization-failed-passwd-invalid%EC%9D%BC%EB%96%84</link>
      <description>&lt;p&gt;안녕하세요. &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;개발자 삐질입니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;보통 회사에서 또는 팀간의 소스 형상관리를 위해 Github,Bitbucket clode를 많이 사용하고는 하는데,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이때&amp;nbsp; Admin -&amp;gt; invitor(초대자)에게 Repo의 참석을 허가합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그런데 정작 초대가가 해당 레포를 clone한 뒤 , pull 또는 push를 하려 하면 Admin이 모든 권한을 인가해줬어도&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Username or Passwd가 안맞다는 에러를 보고는 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이때, 가장먼저 git의&amp;nbsp; global config파일을 초기화해서 계정을 재설정하는 방법&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;$git config --global credential.helper&lt;/p&gt;
&lt;p&gt;을 통해 진행합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;또한 해당 git 관리 Tool&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;- 소스트리&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;- 크라켄&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;- 안스&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp; &amp;nbsp;- ect&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;등의 계정을 연동해주시고,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;보통 github나 bitbucket이나 sns를 통해 연동한 경우 ( 이&amp;nbsp; 경우가 매우 중요합니다. )&lt;/p&gt;
&lt;p&gt;연동을 한 계정이 타 Admin Repo로 초대되었다면 대부분 계정인증 실패가 뜰겁니다. ( git이 push pull하면서 패스워드를 요청함)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;해결방법으로는 해당 리모트 클라우드에서 비밀번호를 재설정하면 됩니다.&lt;/p&gt;
&lt;p&gt;sns로 연동했기 때문에&amp;nbsp; 자체 리모트 클라우드로 계정을 포팅하면서 비밀번호가 설정되지 않은 상황이기 때문입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 Tip</category>
      <category>빗버킷 #bitbucket #authorization failed #깃</category>
      <author>삐질</author>
      <guid isPermaLink="true">https://ppizil.tistory.com/48</guid>
      <comments>https://ppizil.tistory.com/entry/BitBucket-Authorization-failed-passwd-invalid%EC%9D%BC%EB%96%84#entry48comment</comments>
      <pubDate>Mon, 3 May 2021 10:15:44 +0900</pubDate>
    </item>
    <item>
      <title>[Recyclerview Paing] 기본 리사이클러뷰 페이징 처리 Feat.Rx</title>
      <link>https://ppizil.tistory.com/entry/Recyclerview-Paing-%EA%B8%B0%EB%B3%B8-%EB%A6%AC%EC%82%AC%EC%9D%B4%ED%81%B4%EB%9F%AC%EB%B7%B0-%ED%8E%98%EC%9D%B4%EC%A7%95-%EC%B2%98%EB%A6%AC-FeatRx</link>
      <description>&lt;p&gt;&lt;span&gt;안녕하세요&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;삐질삐질&amp;nbsp;개발하는&amp;nbsp;개발자&amp;nbsp;삐질&lt;/span&gt;&lt;span&gt;입니다&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;굉장히 오랜만에 포스팅 하는 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;바로 본론으로 들어가서, 오늘 소개해드릴 Tip은 우리가 흔히 쓰는 리사이클러뷰를 통해&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Remote(server) API를 요청후 결과값을 리스트에 뿌려주는 과정에서, 너무 많은 데이터를 한번에 불러올 수 없기 때문에&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;- 너무 많이 불러오면 서버 과부하..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;페이징 처리가 된 API와, 그에 맞게 호출하여 결과를 리스트에 추가해주는 방법을 알아보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;사실 다른 부분은 크게 중요치 않습니다. 아래 코드가 전부라고 봐도 무방할 정도입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YvFDK/btq16tfD0TW/av0zKGbSWI8uvnZCCVtCQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YvFDK/btq16tfD0TW/av0zKGbSWI8uvnZCCVtCQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YvFDK/btq16tfD0TW/av0zKGbSWI8uvnZCCVtCQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYvFDK%2Fbtq16tfD0TW%2Fav0zKGbSWI8uvnZCCVtCQ0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;하지만 이렇게 가벼운 설명으로 끝내면 너무 정이 없죠?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;기본적인 흐름은 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1. Page의 속성을 담당할 entity클래스가 있습니다. 이 클래스는 요청할 페이지와, 한번에 요청할 아이템의 갯수를 저장하는 클래스입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2oE2X/btq16tGIqQ9/pGygJC8kVRGOIsBKNfJhJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2oE2X/btq16tGIqQ9/pGygJC8kVRGOIsBKNfJhJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2oE2X/btq16tGIqQ9/pGygJC8kVRGOIsBKNfJhJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2oE2X%2Fbtq16tGIqQ9%2FpGygJC8kVRGOIsBKNfJhJ1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;위 클래스는 각 프로퍼티를 보관하고 있고, plusPage라는 page value를 1씩 증가시키는 펑션을 담고 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2. 페이징 API의 기본적으로 요구하는 params는&amp;nbsp; 위와 같이 page, size가 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3. 해당 value들로 하여금 API를 request하여 List를 받고, adapter item에 add를 해주게 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;4. 그러면 한 페이지 분의 list가 리사이클러뷰에 셋 되겠지요?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;여기부터가 페이징의 시작&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;5. 페이징을 하기 위해서는 , 언제? 다음 페이지를 호출 할 것인가를 알아야하고, 저는 scrollListener를 이용해, 가장 아래에 스크롤이 도달했는지 여부를 검사했습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;236&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3igCf/btq13Al3Qsm/gSFQTJFX5QmJbQqWXY2PU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3igCf/btq13Al3Qsm/gSFQTJFX5QmJbQqWXY2PU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3igCf/btq13Al3Qsm/gSFQTJFX5QmJbQqWXY2PU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3igCf%2Fbtq13Al3Qsm%2FgSFQTJFX5QmJbQqWXY2PU1%2Fimg.png&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;236&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;6. 이렇게 canScrolLVertically(-1) 펑션의 리턴이 true일 때, 최하단에 스크롤이 갔다는 사실을 알고, 다음 동작을 호출하게 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;7. 이때 scrollObserver는 더 아래에서 설명하도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;8. 다음 페이지를 호출하는 내용은 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/deSmLz/btq106F2rZj/3mugZ1IO4GOlkV0PtIXtC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/deSmLz/btq106F2rZj/3mugZ1IO4GOlkV0PtIXtC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/deSmLz/btq106F2rZj/3mugZ1IO4GOlkV0PtIXtC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdeSmLz%2Fbtq106F2rZj%2F3mugZ1IO4GOlkV0PtIXtC0%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;9. pageEntity의 plusPage를 호출함으로써 pageEntity가 가진 page의 속성을 +1 시켜준 뒤,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;10. 다음 API를 호출합니다. 그후 받은 결과값을 다시 adatper item에 addAll시켜주고 notify를 해주면 끝이나게 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;-----------------------------------------&lt;/p&gt;
&lt;p&gt;여기에 사용된 scrollObserver라는 것은, 이 scrollListener는 바닥에 닿을때 마다 해당 리스너가 불리우기 때문에 한 번에 여러개의 Api가 호출되는 불상사가 있을 수 있습니다. 이때 중복이 되는 부분을 걸러주기 위한 observer인데 ,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이때 사용한 기법으로는 Rx쪽의 throttleFirst라는 첫번째 신호가 들어온 뒤 , 지정된 시간동안 들어오는 처음 신호 이후의 신호를 싹 무시해버리는 기법입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이것에 대해서는 Rxjava,RxKotlin의 throttle이라는 부분에 대해 공부하시면 좋습니다.&lt;/p&gt;
&lt;p&gt;(사실 이 부분 없어도....크게 상관은 없습니다 만, 디테일하게 정확하게 처리하고 싶은 분은 추천 드립니다.)&lt;/p&gt;
&lt;p&gt;단지 이 장에서는 기법만을 소개하기 때문에 최선의 방법 보다는, 기본적인 개념을 위한 설명으로 이해해주시면 감사하겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;rx를 사용하지 않고, 난 그냥 어찌됐던 최 하단이면 api를 호출하고 싶다 라고 하신 다면, scrollObserver.onNext(true)를 호출하는 대신,&lt;/p&gt;
&lt;p&gt;바로 그 자리에서 pluspage()와 다음 API를 호출하여 작업하시면 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;또한, PageAdapter , ListAdapter를 활용한 방법들도 있지만, 굳이~나는 이런것들말고 기본 Reyclerview로 만들고 싶다 하시는 분께 추천드립니다. 차후 위의 어댑터들로 구성하는 방법들도 포스팅 하도록 하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;- 이상 -&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;해당 예제 소스&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jaekanglee/BasicCode/tree/master/RecyclerviewPagingSample&quot;&gt;BasicCode/RecyclerviewPagingSample at master &amp;middot; jaekanglee/BasicCode (github.com)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1617800900824&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;object&quot; data-og-title=&quot;jaekanglee/BasicCode&quot; data-og-description=&quot;코드분리 하는 습관을 예시로 들기위한 프로젝트, 기본적으로 MVC를 가져간다 . Contribute to jaekanglee/BasicCode development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/jaekanglee/BasicCode/tree/master/RecyclerviewPagingSample&quot; data-og-url=&quot;https://github.com/jaekanglee/BasicCode&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dUw0WJ/hyJNTWSS5T/MtiTBsus34TG9Z9LTBJV5k/img.png?width=420&amp;amp;height=420&amp;amp;face=0_0_420_420&quot;&gt;&lt;a href=&quot;https://github.com/jaekanglee/BasicCode/tree/master/RecyclerviewPagingSample&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/jaekanglee/BasicCode/tree/master/RecyclerviewPagingSample&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dUw0WJ/hyJNTWSS5T/MtiTBsus34TG9Z9LTBJV5k/img.png?width=420&amp;amp;height=420&amp;amp;face=0_0_420_420');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;jaekanglee/BasicCode&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;코드분리 하는 습관을 예시로 들기위한 프로젝트, 기본적으로 MVC를 가져간다 . Contribute to jaekanglee/BasicCode development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;초보 안드로이드 개발자 단톡 방&lt;br /&gt;&lt;a href=&quot;https://open.kakao.com/o/gn4xqQ6&quot;&gt;https://open.kakao.com/o/gn4xqQ6&lt;/a&gt;&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1617800922862&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;카카오톡 오픈채팅&quot; data-og-description=&quot;&quot; data-og-host=&quot;open.kakao.com&quot; data-og-source-url=&quot;https://open.kakao.com/o/gn4xqQ6&quot; data-og-url=&quot;https://open.kakao.com/o/gn4xqQ6&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ZCsOW/hyJPgpoCIt/4J6wKt6Hj9kSi7StXVFhdK/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628&quot;&gt;&lt;a href=&quot;https://open.kakao.com/o/gn4xqQ6&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://open.kakao.com/o/gn4xqQ6&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ZCsOW/hyJPgpoCIt/4J6wKt6Hj9kSi7StXVFhdK/img.png?width=1200&amp;amp;height=628&amp;amp;face=0_0_1200_628');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;카카오톡 오픈채팅&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;open.kakao.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 Tip</category>
      <author>삐질</author>
      <guid isPermaLink="true">https://ppizil.tistory.com/47</guid>
      <comments>https://ppizil.tistory.com/entry/Recyclerview-Paing-%EA%B8%B0%EB%B3%B8-%EB%A6%AC%EC%82%AC%EC%9D%B4%ED%81%B4%EB%9F%AC%EB%B7%B0-%ED%8E%98%EC%9D%B4%EC%A7%95-%EC%B2%98%EB%A6%AC-FeatRx#entry47comment</comments>
      <pubDate>Wed, 7 Apr 2021 22:09:44 +0900</pubDate>
    </item>
    <item>
      <title>초보 카카오톡 오픈 채팅방 URL이 변경되었습니다.</title>
      <link>https://ppizil.tistory.com/entry/%EC%B4%88%EB%B3%B4-%EC%B9%B4%EC%B9%B4%EC%98%A4%ED%86%A1-%EC%98%A4%ED%94%88-%EC%B1%84%ED%8C%85%EB%B0%A9-URL%EC%9D%B4-%EB%B3%80%EA%B2%BD%EB%90%98%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4</link>
      <description>&lt;p&gt;안녕하세요. 개발자 삐질 입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;모든 게시글에 작성 된 링크를 업데이트 하지 못 하고, 아래와 같이 전달 드립니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;카카오톡의 문제로 기존의 방이 &lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt; 링크로 이전되었습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;즉각 업데이트 못한 점 죄송합니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 Tip</category>
      <author>삐질</author>
      <guid isPermaLink="true">https://ppizil.tistory.com/46</guid>
      <comments>https://ppizil.tistory.com/entry/%EC%B4%88%EB%B3%B4-%EC%B9%B4%EC%B9%B4%EC%98%A4%ED%86%A1-%EC%98%A4%ED%94%88-%EC%B1%84%ED%8C%85%EB%B0%A9-URL%EC%9D%B4-%EB%B3%80%EA%B2%BD%EB%90%98%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4#entry46comment</comments>
      <pubDate>Tue, 6 Apr 2021 13:02:14 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드]요즘 핫한 안드로이드 Mvvm 패턴을 공부하는 것..</title>
      <link>https://ppizil.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C%EC%9A%94%EC%A6%98-%ED%95%AB%ED%95%9C-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-Mvvm-%ED%8C%A8%ED%84%B4%EC%9D%84-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EA%B2%83</link>
      <description>&lt;p style=&quot;line-height: 1.5;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;span style=&quot;font-size: 12pt; color: #ffbb00;&quot;&gt;안녕하세요. 개발자 삐질 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;span style=&quot;font-size: 12pt; color: #ffbb00;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;오늘은 요즘 구인 / 구직에 빠지지 않는 아키텍쳐 패턴 MVVM을 공부하는 것에 대한 개인적인 의견을&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;적어 보고자 합니다. (글 내용은 그렇지 않지만.. 하고싶으면 하시라고 미리 말씀 드립니다)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;먼저 요즘 안드로이드 쪽에서 가장 핫한 MVVM은 Model / View / ViewModel이 합쳐진 용어입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;기존에는 MVC , MVP 등이 있었습니다. 최근엔 MVI 패턴도 또 올라오고 있죠?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그렇기에 요즘 신입의 시기에도 MVVM에 대한 질문을 많이 받곤 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;이 글에서 MVVM의 정의나 MVVM이 뭔지에 대해서는 굳이 나열하지 않겠습니다. 왜냐면 저도 ...ㅎ......잘 사용하지 못 하고 있거든요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그럼 이 글을 왜 쓰고 있냐 ? 라는 질문이 남게 되는데,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;저도 일단은 MVVM패턴을 지향하고, 약 1년 반 정도 사용하고 있으며, 트랜디한 기술들에 관심이 많습니다. 하지만, 저와 같이 초급 개발자 수준에서 간과 하지 않아야 할 부분이 있어 꼭 다른 분들도 한번쯤 생각 해 보셨으면 해 글을 쓰게 됐습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li style=&quot;line-height: 1.8;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;MVVM을 왜 사용하고 공부하게 되었나?&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;A: 남들이 좋다고 해서 ..&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li style=&quot;line-height: 1.8;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;MVVM을 사용하는게 잘 하고 있는 것 같나?&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;A: 초기엔 Yes , 지금은 um.....&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li style=&quot;line-height: 1.8;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;MVVM을 앞으로도 계속 사용 할 것인가?&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;A: Yes, 다만 사용하기만 할게 아니라 계속해서 공부 중&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li style=&quot;line-height: 1.8;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;MVVM을 초급 또는 신입 개발자가 바로 시작하는 것은 어떻게 생각하나?&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;A: 반대합니다. 이유는 밑에서 좀더 자세히 말씀 드릴게요.&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li style=&quot;line-height: 1.8;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;MVVM을 꼭 배워야 하나?&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;A: 네. 배워야 합니다. 언젠가는 다만, 본인이 필요성을 1 to 10 중에 3이라도 '정확히' 느낄 때&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;일단 앞서 말씀드린대로 저는 1년 반 정도 MVVM 패턴으로 안드로이드 코드를 작성 해 왔습니다. 하지만 최근에 들어서야 아..MVVM이 이런 느낌이긴 하구나. 그 동안 너무나 잘못 쓰고 있던 부분이 많구나 를 느낍니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;저는 MVVM을 시작 할 당시 MVC도 사실 몰랐습니다. 말로는&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;i&gt;&lt;span style=&quot;color: #ffffff; background-color: #4673ff;&quot;&gt;&quot;M이 Model이고 V는 View고 C는 컨트롤러고 ..&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;i&gt;&lt;span style=&quot;color: #ffffff; background-color: #4673ff;&quot;&gt;안드로이드는 VC가 같이 있는 형국이고 M만 따로 있다. &quot; 라던지,&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&amp;nbsp;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span style=&quot;color: #ffffff; background-color: #4673ff;&quot;&gt;&quot;비지니스 로직을 잘 만들어야 한다&quot; &lt;/span&gt;&lt;/i&gt;&lt;span style=&quot;font-size: 12pt; color: #ffffff; background-color: #4673ff;&quot;&gt;라던지..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: #ffffff; background-color: #4673ff;&quot;&gt;&quot;테스터블 하게 개발하기 위해 아키텍쳐 패턴으로 잘 설계해야 한다.&quot;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt; color: #ffffff; background-color: #4673ff;&quot;&gt;&amp;nbsp;라던지 등등&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;이런 이야기들이 굉장히 핫 했고 지금도 핫한 주제 이죠. 구직 시 채용 공고를 보면 필수 요건에 MVVM or Rx or TDD 이런 단어는 항상 들어가죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;필수 요건이 아니면 우대 요건 이라도..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;이런 추세 속에 저는 MVVM을 시작했고 나름 Github 이라던지 구글의 샘플 코드를 보면서&lt;span style=&quot;text-decoration: line-through;&quot;&gt; 제가 알고 있는 지식대로 코드를 작성했습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;span style=&quot;text-decoration: line-through;&quot;&gt;TDD까지는 지식이 얕아 도입하지 못한 상태로..&lt;/span&gt; 약 1년 정도 MVVM으로 개발을 하고 있을 때 어느날 문득 회사의 기능을 개발하고 있는 와중, 잦은 기획 변경에 스트레스를 받고 이런 생각이 들었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&quot;아..왜 이렇게 자주 기획이 바뀌는거지? 또 MVVM이런거 쓰면 뭐 기획 자주 바뀌거나 컴포넌트 바뀔 일 있어도 바꾸기 쉽다매?? 근데 난 왜이래? &quot; .. -&amp;gt;회사의 사수가 제 프로젝트를 볼 일이 있었는데&amp;nbsp; mvvm을 쓴다고 쓴것 같은데 게 짜면 디펜던시 줄줄 달고 다니는 거라는 이야기를 듣기도 했죠 ..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;굉장히 어리석은 생각이죠. 늘 다른 MVVM의 소스를 보고 나름대로의 공부를 계속 하면서 &lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&quot;겉핥기&quot;&lt;/span&gt;&lt;/b&gt;를 열심히 하고 있었으므로 제 스스로 잘못 짜고 있단 생각이 한 20% 정도 밖에 없었습니다. Databinding도 쓰고 뭐 Room도 쓰고 착착 신기술 써 가면서 확실히 MVC와 비슷한 형태로 짤때는 일일이 뷰 속성을 코드 하나하나 잡아서 수정할 때와 다르게 MVVM속에서 databinding으로 Livedata 써 가면서 편하게 잘 작성하고 있는 줄만 알았습니다.. 나름의 &quot;편의&quot;가 왕창 증폭이 된 것 이었죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;귀찮은 Callback Interface도 안 쓰고, 알아서 Observe 가능하고 , LifeCycle 안에서 Observer가 보장이 되고 적당하게 프로그램은 돌아가고..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그런데 위 처럼 스트레스를 받는 시기에 문득 또 다르게 &quot;그래.. 아키텍쳐 패턴으로 나눠서 잘 짜면 각 모듈간에 종속성이 약화된다는데 왜 난 아직까지 코드 하나 고치면 다른 거 연달아 고쳐야 하고, 또 이곳 저곳에서 사이드 이팩트가 나고, 수정은 또 왜 이렇게 어려운 거지?? 아... 내가 정말 크게 잘못 공부하고 있었구나 자만 했구나&quot;를 드디어 깨닫게 됐습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;돌이켜 코드를 보니 저는 겉모양만 MVVM인 MVC(이 마저도..)를 짜고 있고, 아키텍쳐 패턴을 차치 하고 나서라도 펑션간의 종속성도 제대로 해결하지 못한 채 M / ViewModel / VIew 클래스만 나눠서 Mvvm이다~!!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그렇게 쓰고 있는 걸 발견하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;기본적인 규칙은 지켰죠 .ViewModel이 View를 몰라도 된다. Context가 viewmodel에 있으면 안된다. 등등&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그러나 이런 제가 지키고 있던 규칙들은 제가 원해서 지킨 규칙이 아니라, 남이 지켜야 한다기에 따라 지킨 규칙입니다. 한 마디로 &quot;왜?&quot;는 모르고, &quot;그렇게 하라니까&quot; 하고 있었던 거죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;또한 Github에 많은 Mvvm 예제 들을 보며, Mvvm이라고 올려놓은 프로젝트들이 각자 개발자 마다도 다른 스타일로써 사용하는 구나. 나도 '대충' 비슷하게 쓰면 내가 Mvvm을 쓰고 있는 거 구나 생각해 왔습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;요즘에야 그나마 각 레이어별로 성격을 지키려고 노력하면서 상호간 의존성을 약화 시키려고 하면서, 필요한 펑션 필요한 부분만 싹 고치면 알아서 돌아가게끔 최대한 신경 쓰면서 작성하는데 이걸 잘 모르고 쓰면 저와 같이 그냥 쓰고는 있는데 엉망인 상태가 됩니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;잘 지키면 Viewmodel 테스트 코드 작성하는데도 수월하고, Model UnitTest코드 작성 하는데도 수월하죠. 다른데 종속성이 약하니까.. 이 유닛을 테스트하는데 이 유닛 외에 다른 어떤 게 필요하지 않은 상태가 되니까..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;물론 테스트 코드를 가끔 작성하긴 하지만 시간적인 여유나, 아직 게으른 부분 떄문에 정말 열심히 쓰진 못하고 있습니다. ( 또 회사에선.. 사실 테스트 코드 작성할 여유는 없습니다.) 해 봐야 증말 간단한 케이스??&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;제가 MVVM을 사용하고 있는 배경에는 이런 내용이 있고, 각설 하고 하고 싶은 말이 무엇이냐면,&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&quot;남들이 해라 해라 , 해야한다~ 필요하다 카더라~~&quot; 라는 말 때문에 근본적으로 해야 할 공부를 놔 두고 엄한 데 시간 쓰는 건 아닌지 곱씹어 보셨으면 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;저도 MVVM을 먼저 시작해 놓고 이제서야 느껴서 이런말을 할 상태가 되는지는 모르겠습니다만, 저와 같은 실수를 하는 분들이 없길 바라며..&lt;b&gt;( 저는 회사의 팀장님께 개발적인 자세나, 이런 가치관들을 많이 배웁니다&lt;span style=&quot;font-size: 18pt;&quot;&gt;- &amp;lt;사수의 중요성&amp;gt;&lt;/span&gt;. 물론 그대로 수용하진 않지만 제가 겪고, 느끼는 바와 조언과 더불어 스스로 판단하는 편 입니다.)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;MVVM을 공부하기 전에 MVC는 제대로 지켜가면 짤수 있나? 한번 보세요. Model이 View가 Controller 가 각자의 역할을 지켜 가며, View의 속성을 Model에 집어넣고 이리저리 거미줄 처럼 엮어가면서 짜고 있진 않은가? 패턴에 구애 받지 않고 , 내 코드 짜는 스타일 자체가 단위별로 펑션이면 그 펑션이 해야할 일만 하는지, 한 펑션안에 이 일도 하고, 저 일도 하고 이 속성 수정하고 저 속성 수정하고 이런 상태로 작성하고 있진 않은지, 클래스는 그 클래스가 가지고 있어야할 속성들만 잘 다루고 있는지.. 결국엔 사실 이게 객체지향과 OOP개념인데 이것 조차 들어보지도 못한 상태로 MVVM을 하는 분들이 많습니다. 내가 각 레이어별로 역할이나 OOP Solid개념만 잘 알아도 사실 MVVM을 공부하는데 이해가 수월 할 거에요. 모르면 증말 외계어 써놓은 프로젝트들이 도사리고 있을 겁니다.&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;MVVM을 왜 쓰는가? 를 생각 해 보세요. 단순히 구직에 이점을 얻기 위해?? ......... 제가 보기엔 구인 구직란에 요강 속 내용중 MVVM필수요건 또는 MVVM 우대요건 써놓은 공고 중 그 팀에 그 패턴 , 그 기술 기깔나게 잘 지키고 있는 조직 보다 , 저와 같은 경우로 프로젝트를 이어가고 있느 케이스가 더 많을 것 같습니다. 왜냐면 옆 회사 MVVM쓰고 Dagger쓰고 하는데 우리 회사 사람들은 레거시 쓸 순 없거든요. 너도 나도 MVVM하거든요. 단, 내가 MVVM을 기가막히게 쓰고 있어야만 그런 요건을 내세울 수 있다는 것은 아닙니다. 아직 기존 단체원도 미숙하지만 비슷하게 아는 사람들을 영입해 같이 배워나가며 성장하고자 할 수도 있으니까요. 다만, 요지는 내가 기본적으로 코딩 클래스 하나 만드는게 어렵고, 안드로이드 컴포넌트가 뭐가 있는지도 모르고, 내 코드가 잘 짜고있는건지 아닌건지 내 코드작성의 스타일은 확고한지, 신념은 있는지 이런 자기 판단도 없는 상태에서 MVVM을 해봤자 그 회사가 정말 MVVM을 잘 쓰거나, 또 쓰고 있지 않다 한들 나를 면접 보는 분이 진성 실력이 좋으신 개발자면 내가 어설픈 MVVM프로젝트를 들이 민다고 해도 밑천이 훤히 드러나 보이기 마련입니다. MVVM을 도입하려고 할땐, 그 근본 목적에 작은 단위의 모듈화 , 테스트의 이점 , 내가 가진 상황에서 MVVM을 마냥 맹목적으로 지향하는게 맞는가. 이런 부분들을 반드시 생각 해 보고 작성을 하셔야합니다. ( 실제로 본인 회사에서 MVVM을 써서 본인도 MVVM을 쓰는데 질문을 들어보면 ...??????싶은 분들이 많이 보입니다)&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그렇다고 내가 아예 못 짠다고 MVVM을 공부하지 말란 소리냐? 는 절대 아닙니다. 해야합니다. 위 말처럼 대세는 MVVM이니까요. 그렇지만 MVVM을 공부 할 거면, 그 이전 MVC MVP 더 이전, 내가 코드 짜는 개념, 신념, 가치관등 부터 내가 개발하고 있는 플랫폼의 근본적인 기초 부터 주목 하셔야 할 부분 입니다.&lt;/span&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt; &lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;이런 질문들을 받습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;a. MVVM하는데 Viewmodel1이 Viewmodel 2를 가지고있고 Adapter에 그 Viewmodel들을 다 집어넣고 하고있는데 뭐가 안돼요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;a. ViewModel에 컨텍스트를 넣어서 쓰고싶은데 어떻게 하나요&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;a. Livedata를 왜 쓰나요?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;a. Viewmodel에서 액티비티를 생성 했어요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;등등 사실 이거는 MVVM을 왜 쓰는 지 조차도 모르는 상태에서 코드만 짜고 있는 상태 거든요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;시간 아까워요 이 상태에서 MVVM을 하는 건. 이런 질문을 하시는 분들은 MVC형태로도 못 짤 확률이 커요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;보통 VC만 있죠. M은 없는 코드..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;MVC로 코드를 짜다 보면, 아.. 좀 특성별로 분리하고, 이거 좀 재사용하고 싶고, 이거 재사용 하려는데 저거랑 연관 있으니까 좀 .. 연관 없게 짜면 좋지 않을까? .. 세분화 해서 , 각 컴포넌트 별로 나누고, View를 조작하는 놈 , 실제 필요한 데이터만 다루는놈 쪼개면 분리가 쉽지 않을까? 뭐 이런 의문점들이 생길 때 그떄 MVVM이나 MVP나 MVI나 다른 것들에 눈돌릴 필요성이 생깁니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;거미줄같은 MVVM 칠해놓은 프로젝트보다 나름의 스타일로 MVC라도 잘 지켜서 제출한 과제, 그런 걸 기반으로 본 면접이 오히려 같이 일할 사람으로 더 반갑습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그리고 가장 중요하게.. 아키텍쳐 패턴을 나누고, 종속성을 약화시키고 하는 주요 원인은 테스트를 원활하게 하기 위해서에요.. 테스트를 하기 쉽게 만들려면 뭐 하나 실행하는데 이것저것 다른게 영향이 있으면 안 되니까 종속성을 약화시키는거고.. 종속성이 약하면 어떤 부분을 고쳐야 했을 때 다른 부분이 영향을 받아서 내가 모르는 또 빈번한 사이드 이팩트를 줄이고자 함 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;물론 아키텍쳐 패턴이라던지 이런 것들이 단점도 있지만 규모가 크거나 프로젝트의 복잡도가 클때 잘 지킨 구조의 프로젝트라면 어디 대충 어떤 부분 보면 뭐가 있겠고, 이런 부분 수정하면 괜찮겠고. 영향도 없겠고 이런 결과들이 나오겠죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;디자인 패턴이라는 것에 대해서 무조건 좋다, 무조건 나쁘다, 적당히 지키자 여러 의견이 있습니다. 개발자 마다도..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그치만 내 상황과 비용이 허락된다면 구조를 잘 지키고 잘 나누고 서로 모듈간의 종속성을 약화시키고.. 이런 부분에 대해서 나쁘다고 하는 개발자는 많지 않을 거라 생각합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt; color: #ff0000;&quot;&gt;&lt;b&gt;&quot;필요한 지도 모르는 데 남들이 좋다 카더라 하는 말만 듣고 정작 중요한 것을 놓치지 말자.&quot;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;초급 안드로이드 개발자를 위한 카카오톡 오픈 채팅방을 운영 중 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;(저는 마냥 친절한 방장은 아닙니다. 다만, 다 같이 성장하고 싶은 방장이며 개발자 입니다)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://open.kakao.com/o/gn4xqQ6&quot;&gt;&lt;span style=&quot;font-size: 12pt; color: #0055ff;&quot;&gt;https:&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;//open.kakao.com/o/gn4xqQ6&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 Tip</category>
      <author>삐질</author>
      <guid isPermaLink="true">https://ppizil.tistory.com/45</guid>
      <comments>https://ppizil.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C%EC%9A%94%EC%A6%98-%ED%95%AB%ED%95%9C-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-Mvvm-%ED%8C%A8%ED%84%B4%EC%9D%84-%EA%B3%B5%EB%B6%80%ED%95%98%EB%8A%94-%EA%B2%83#entry45comment</comments>
      <pubDate>Wed, 26 Aug 2020 20:52:55 +0900</pubDate>
    </item>
    <item>
      <title>DI(Dependency Injection)이란? 맛만 이라도 보자!</title>
      <link>https://ppizil.tistory.com/entry/DIDependency-Injection%EC%9D%B4%EB%9E%80-%EB%A7%9B%EB%A7%8C-%EC%9D%B4%EB%9D%BC%EB%8F%84-%EB%B3%B4%EC%9E%90</link>
      <description>&lt;p style=&quot;line-height: 1.5;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;안녕하세요. 개발자 삐질 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;오늘은 Dependency Injection의 개념에 대해 간략하게 설명하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;(정말 간략함 )&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;안드로이드 개발자기에 DI를 지원해주는 라이브러리로 Dagger / Koin을 사용할 수 있지만&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;오늘은 그런 모듈에 대한 사용보다는 세간에서 하도 DI DI DI DI 하니까 뭔지 맛만 보시라고 ..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;한마디로 , 회사가 있다면 그 회사가 안드로이드 포지션이 있다면,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;제가 그 개발자로 입사하던 , 이 글을 읽고계시는 분이 입사를 하던&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;동일하게 '개발'을 하면 된다 쯤?? 너무 추상적이죠? 코드로 한번 설명 해 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;예를들면 저는 T클래스에서 Sorting 작업을 하고 싶습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그러나 Sorting은 Quick ,Bubble ~~ 여러가지가 있을 수 있고, 수행하던 소팅로직은 언제든지 다른 소팅으로 교체할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;이러한 조건일때 우리가 기본적으로 필요한 곳에서 new를 사용해 수행하려면, 아래와 같이 작성할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;span style=&quot;text-decoration: line-through;&quot;&gt;(코드 간략화기 때문에 정확한 문법은 생략 합니다)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;(사수의 코드를 인용)&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;class T () {
    //소팅 클래스를 이용해
    fun targetFunc(){
        ASort a = new Asort()
        //BSort b = new BSort()
        a.sort()
        //b.sort() 
    }

}

class ASort implement ISort{
    fun sort()
}

class BSort implement ISort{
    fun sort()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;targetFunc가 ASort를 수행해야할땐 Asort 를 만들어서 a.sort()를 수행할 수 있도록 코드를&amp;nbsp;작성해야하고&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;아니다, B로 하자 싶다면 , B를 생성해서 b.sort를 수행할 수 있도록 코드를 재작성 해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그렇지만 이렇게 직접적으로 중요한 부위의 펑션을 자꾸 수정하게 되다 보면 내가 예상치 못한 다른 엮여 있는 곳에 영향을 줄 수도 있습니다. 동적으로 테스트를 해볼 수 가 없죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그렇지만 인젝션을 통해 주입을 하게 된다면 아래와 같이 수정 해 볼수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;
class T (Isort object) {
    //소팅 클래스를 이용해
    fun targetFunc(){
        
        object.sort()
        
    }

}

class ASort implement ISort{
    fun sort()
}

class BSort implement ISort{
    fun sort()
}

class InjectionModule(){
    //외부 객체생성 모듈
    val ASort a = new Asort()
    val BSort b = new Bsort()
            
    T = new T (ASort);
    T = new T(BSort);
    
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;위와 같이 InjectionModule(외부에 객체생성을 담당하는 하나의 모듈공간) 에서 필요한 객체 또는 대체 될 객체들을 생성하고 T에 바꿔 주입하게되면 T는 나에게 주입되는 객체가 ASort , BSort 인지 몰라도 어쩃든 두놈다 Interface로 fun sort()라는 것을 구현하고 있기 떄문에 , T입장에서는 받은 객체로 object.sort()만 호출하게 되면 되죠.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;그렇게 되면 T의 메인 로직은 전혀 수정할 게 없게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;이로써 메인 로직에 의해서 T가 바뀌어야하는 결합도가 낮아지고&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;테스트 코드를 작성할 때 , 내가 원하는 어떤 로직을 쓰던, 최소한의 펑션 인터페이스(ex, ISort)만 구현해준다면&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;구현 내용부는 달라지던 같던 상관없게되니까 어떤 객체던 주입해서 원하는 결과를 테스트 해 볼수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;가장 중요한 포인트는 ,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;font-size: 18pt; color: #ff5e00;&quot;&gt;T클래스의 내용을 절대 변경하고 싶지 않다 !!&lt;/span&gt;&lt;/b&gt;&amp;nbsp; &amp;nbsp;에요. (하다보면 어쩔 수 없이 변경될 수 있겠지만.. 이건 다음번 설명으로..&lt;br /&gt;라이브러리에서 Deprecated시키는 이유 중 하나)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;이떄문에 , 안드로이드 구조로 예를 들자면&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;VC (뷰 컨트롤러 ) &amp;rArr; Model에 디펜던시가 강하게 걸리던 부분이 외부에서 주입해 주기 때문에 VC / M과의 결합도가 낮아지게 되는 것 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;다만, DI의 장점은 강력하게는&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;테스트가 용이함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;재사용성이 우수함&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;등이 있지만,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;단점으로는&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;일단 클래스 복잡도 , 프로젝트 복잡도가 상당하게 증가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;일관되게 이 패턴의 Rule을 지키는 것이 매우어렵고, 이 Rule을 지키기 위해 난잡해 질 가능성이 다분함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;테스트 코드, 재사용을 위해 기초 설계를 매우 탄탄하게 해야 하기 때문에 상대적으로 개발의 비용이 큼&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;등이 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;둘다 스스로에게 허락 된 상황에 맞게 사용하면 장단을 잘 이용할 수 있을거라 생각합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;초급 안드로이드 개발자를 위한 카카오톡 오픈 채팅방을 운영 중 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;(저는 마냥 친절한 방장은 아닙니다. 다만, 다 같이 성장하고 싶은 방장이며 개발자 입니다)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 12pt;&quot;&gt;&lt;/span&gt;&lt;a href=&quot;https://open.kakao.com/o/gn4xqQ6&quot;&gt;https://open.kakao.com/o/gn4xqQ6&lt;/a&gt;&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;&lt;/p&gt;</description>
      <category>개발 Tip</category>
      <author>삐질</author>
      <guid isPermaLink="true">https://ppizil.tistory.com/44</guid>
      <comments>https://ppizil.tistory.com/entry/DIDependency-Injection%EC%9D%B4%EB%9E%80-%EB%A7%9B%EB%A7%8C-%EC%9D%B4%EB%9D%BC%EB%8F%84-%EB%B3%B4%EC%9E%90#entry44comment</comments>
      <pubDate>Wed, 3 Jun 2020 12:08:18 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] 아키텍쳐? 패턴 ?  처음엔 아무것도 모른다면 이것 만이라도..</title>
      <link>https://ppizil.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90-%ED%8C%A8%ED%84%B4-%EC%B2%98%EC%9D%8C%EC%97%94-%EC%95%84%EB%AC%B4%EA%B2%83%EB%8F%84-%EB%AA%A8%EB%A5%B8%EB%8B%A4%EB%A9%B4-%EC%9D%B4%EA%B2%83-%EB%A7%8C%EC%9D%B4%EB%9D%BC%EB%8F%84</link>
      <description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;span style=&quot;color: #5c5c5c; font-family: 'Spoqa Han Sans', sans-serif; font-size: 12pt; --inversion-type-color: simple;&quot;&gt;안녕하세요&lt;/span&gt;&lt;span style=&quot;color: #5c5c5c; font-family: 'Spoqa Han Sans', sans-serif; font-size: 12pt; --inversion-type-color: simple;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #5c5c5c; font-family: 'Spoqa Han Sans', sans-serif; font-size: 12pt;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: 'Spoqa Han Sans', sans-serif; font-size: 12pt; color: #ff5e00;&quot;&gt;삐질삐질&amp;nbsp;개발하는&amp;nbsp;개발자&amp;nbsp;삐질&lt;/span&gt;&lt;span style=&quot;color: #5c5c5c; font-family: 'Spoqa Han Sans', sans-serif; font-size: 12pt;&quot;&gt;입니다.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px;&quot;&gt;오늘은 여러분께 또 한번 저의 개인적인 견해를 강요해보려 합니다.&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px;&quot;&gt;요즘 블로그나, 단톡방, 여러가지 소통창구에서 많이 논의되는 단어 중 하나는&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px;&quot;&gt;아키텍쳐 패턴 , 디자인패턴 , mvvm, mvp, mvc 뭐 컨벤션 이런 용어들 일겁니다.&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px;&quot;&gt;&lt;span style=&quot;text-decoration: line-through;&quot;&gt;중복단어가 있긴 하지만..&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;제가 한 줄로 요약하고 싶은 건 ,&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;위의 용어들이 뭔지 모르겠다면 그냥 MVC만 기억 하세요&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;우리가 개발을 효율적으로 하기 위해서는 역사적으로 많은 컨벤션 ( 규칙, 권고 등등) 같은 것들이 즐비해있어요.&lt;/p&gt;
&lt;p&gt;당연하게 코드분리라던지, 객체지향법이라던지 뭐 여러가지가 있죠&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그 중에서 요즘 가장 핫한건 아키텍쳐 패턴들에 관한 것 인데요&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;MVC/ MVVM/ MVP /MVI / MVW&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;너무나 많죠. 하지만 우리는 애석하게도 이것들을 다 알기란.. 너무 어렵습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그래서 저는 초급 개발자 분들께는 다 잊어버리시고 MVC하나라도 알고계시라고 이것만 알아도 어느정도 개발한다고 말씀드리고 싶어요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;인터넷에 블로깅 또는 구글링을 하다보면 이런 말을 많이 들을거에요&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;안드로이드는 뭘 해도 기본적으로 &quot;MVC&quot;로 짤수 밖에 없어&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;못 들어보셨다면 죄송 !!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이것이 무슨 말이냐면 기본적으로&amp;nbsp; 코드는 분리를 할 수록 재사용성 또는 가독성이 올라갈 확률이 높습니다.&lt;/p&gt;
&lt;p&gt;(무조건은 아녀요 그치만 대부분의 경우에 ..)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그런데 어떤 기준으로 분리를 할 것이냐? 가 문제겠지요??&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: line-through;&quot;&gt;( 개인적으론 위의 MVC/MVVM/MVP 규칙 외에&amp;nbsp; It's My Style -&amp;gt; IMS 패턴도 좋습니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그래서 그 기준에 대한 것을 줄인 용어가 위의 MVC / MVVM / MVP 등 입니다&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;사실 이것들이 다&amp;nbsp;뭐야? 하시는 분들이 이 글을 읽으셨을때, 아래에 장황하게는 써 놓겠지만 의미를 정확히 이해 하시리라 생각하진 않습니다. &lt;span style=&quot;background-color: #8cfccb; color: #000000;&quot;&gt;다만 이런것이 있고, 그렇구나 ~~ ㅇㅇㅇㅇㅇ 알겠어 ~~ 하고 단어들에 대해 익숙해지시기라도 했으면 하는 바람입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;M -&amp;gt; Model ( 실제로 안드로이드 Context라던지, TextView라던지 기타 Android의 어떤 특성을 배제하고 순수 자바로만 데이터 핸들링을 할수 있는 녀석)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;즉 , 많이 들어보셨던 &quot;비지니스 로직&quot;을 다루는 놈이에요 . 비지니스 로직이란, 내가 앱을 사용하는데 실제로 필요한 의미있는 데이터들을 핸들링( 가공 ) 하는 로직이에요.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;V -&amp;gt; View ( 이 녀석은 사용자에게 보이는 페이지나, TextView나 실제로 스크린에 보이는 껍데기를 의미하는 놈 입니다 )&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;C -&amp;gt; Controller ( 이 녀석은 View 즉 사용자가 보고있는 Button이나 , EditText에 어떤 이벤트가 발생 했을때, 그 이벤트를 기반으로 하여금 Model에게 야 필요한 데이터 만들어서 다시 돌려줘 !! 그러면 내가 V에 전달하던지 할게 !! 하는 놈 입니다 )&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;참 어렵죠?&amp;nbsp; 도형으로 관계를 표현하면 이렇습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/99D6F9405C91F8C804&quot; alt=&quot;MVC란? MVC 디자인 패턴&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;(여기서 실선으로 표현 한 놈이 중재자 역할을 하며, Model에서 View에 접근할 수 없기때문에 점선으로 표현합니다. )&amp;nbsp;&lt;/p&gt;
&lt;p&gt;무슨 말이냐면, 각 역할대로 나누면, 내가 접근해도 되는 역할이 있고, 접근하면 안되는 역할이 있습니다. ( 관심사 분리 및 의존성 분리 같은..용어로 표현하기도 해요 )&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;즉 Model에서 Activity로 접근할 수 없는 것을 뜻 해요 .&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;사실 위의 이런 주구장창 하는 말들도 크게 유의미하진 않습니다.&lt;/p&gt;
&lt;p&gt;제일 중요한것은 프로젝트 단위로 보았을때 &lt;b&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;코드&amp;nbsp;작성의 일관성 / 적절한 메서드 분리 ..&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;이 2가지만 잘 지켜져도 웬만큼 괜찮은 프로젝트가 될수 있어요 .&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;무슨 말이냐면, 내가 코드를 작성하는 규칙을 통일하라는 말입니다. 또 메서드 단위로 컨트롤 하라는 것 입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EX) TextView 네이밍 -&amp;gt; text_name , text_title 이런식으로 하다가 다른 xml에서는 TextName, TextTitle 이렇듯 규칙을 기준없이 혼용해서 쓰지 마십시오. 펑션 네이밍 또한 마찬가지 입니다. 네이밍에서 뿐 아니라 메서드들을 Call 하는 방식도 그것이 맞던 틀리 던, 일관성을 유지해야 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;EX) 메서드 단위로 컨트롤이란, 하나의 메서드 안에&amp;nbsp; 클릭처리도 하고 ~ 커스텀뷰도 만들고 ~~ Textview 속성도 변경하고~~&amp;nbsp; 이렇듯 하나의 메서드(펑션)안에 잡다한 기능들은&amp;nbsp; 최대한 공통적인 기능으로 세분화해서 메서드(펑션)을 분리해주세요.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;- 클릭처리&lt;/p&gt;
&lt;p&gt;- 커스텀뷰 리프레시&lt;/p&gt;
&lt;p&gt;- 텍스트뷰 속성 변경&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이렇게 각각의 기능별로 분리해서 원하는 곳에 호출만 할 수 있도록.. 그래야 깔끔하겠죠?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;아무튼 여러분들 너무 복잡할 필요도 없습니다.&amp;nbsp; &quot;기능별 메서드 분리&quot; And&amp;nbsp; &quot;코드 작성의 일관성&quot; 두 가지만 지켜서 개발 해주시면 언제어디서든 나름 편리하게 개발할 수 있습니다. -&amp;gt; 요것을 지키기 위해서는 사실 초반에 귀찮아요. 하지만 잘 지켰을때 나중에 어떤 특정 기능만 샥 변경하려는데 , 여기도 바꿔야하고 저기도 바꿔야하고 이런 불상사가 적게 일어납니다.&amp;nbsp; 사이드 이펙트라고 합니다&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;말로 구구절절 설명하기 보다 코드를 보시는 것이 여러분들이 더 편하실 것 같아 아래에 깃허브 주소를 공유합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;font-size: 36pt;&quot;&gt;GITHUB&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ff0000; font-size: 24pt;&quot;&gt;&lt;a href=&quot;https://github.com/jaekanglee/BasicCode&quot;&gt;https://github.com/jaekanglee/BasicCode&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;깃헙에서는 아래처럼 동작하는 예제 입니다.&lt;/p&gt;
&lt;p&gt;1. 리사이클러뷰로 리스트를 표현한다.&lt;/p&gt;
&lt;p&gt;2. 각 아이템을 클릭하면 값을 변환시킨다&lt;/p&gt;
&lt;p&gt;3. 각 계층 (&amp;nbsp; View, Model, Controller )에 맞게 메서드를 작성 / 분리 한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;안드로이드는 V와 C를 같이 가지고 있습니다.&amp;nbsp; ( 검색 플리즈 )&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;VC-&amp;gt; Adapter / Activity -&amp;gt; 사용자가 눈으로 볼수 있는 영역에 대한 성질이나 특성들을 처리하고 관리함&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;M -&amp;gt; Model / Entity&amp;nbsp; -&amp;gt; 실제로 Activity의 성질이나, 각 View들의 성질에 대한 데이터는 하나도 가지고 있지 않으며 필요한 데이터에대한 가공만을 담당함&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;margin: 0px; padding: 0px; color: #5c5c5c; font-family: 'Spoqa Han Sans', sans-serif; font-size: 14px;&quot;&gt;&lt;span style=&quot;color: #2d4fc9; font-family: '맑은 고딕', sans-serif;&quot;&gt;초급 안드로이드 개발자를 위한 카카오톡 오픈 채팅방을 운영 중 입니다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px; color: #5c5c5c; font-family: 'Spoqa Han Sans', sans-serif; font-size: 14px;&quot;&gt;&lt;span style=&quot;font-family: '맑은 고딕', sans-serif;&quot;&gt;(저는 마냥 친절한 방장은 아닙니다.&amp;nbsp; 다만, 다 같이 성장하고 싶은 방장이며 개발자 입니다)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px; color: #5c5c5c; font-family: 'Spoqa Han Sans', sans-serif; font-size: 14px;&quot;&gt;&lt;a href=&quot;https://open.kakao.com/o/gn4xqQ6&quot;&gt;https://open.kakao.com/o/gn4xqQ6&lt;/a&gt;&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;margin-right: auto; margin-bottom: 28px; margin-left: auto; font-size: 15px; line-height: 28px; color: #555555; padding: 0px !important 0px 0px !important 0px;&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 Tip</category>
      <author>삐질</author>
      <guid isPermaLink="true">https://ppizil.tistory.com/43</guid>
      <comments>https://ppizil.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90-%ED%8C%A8%ED%84%B4-%EC%B2%98%EC%9D%8C%EC%97%94-%EC%95%84%EB%AC%B4%EA%B2%83%EB%8F%84-%EB%AA%A8%EB%A5%B8%EB%8B%A4%EB%A9%B4-%EC%9D%B4%EA%B2%83-%EB%A7%8C%EC%9D%B4%EB%9D%BC%EB%8F%84#entry43comment</comments>
      <pubDate>Thu, 30 Apr 2020 20:30:09 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] 심심해서 찍어본 Retrofit 동기 / 비동기 Feat.Rx</title>
      <link>https://ppizil.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8B%AC%EC%8B%AC%ED%95%B4%EC%84%9C-%EC%B0%8D%EC%96%B4%EB%B3%B8-Retrofit-%EB%8F%99%EA%B8%B0-%EB%B9%84%EB%8F%99%EA%B8%B0-FeatRx</link>
      <description>&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;margin: 0px auto 28px; font-size: 15px; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; -en-clipboard: true; padding: 0px !important 0px 0px !important 0px;&quot;&gt;&lt;span style=&quot;font-size: 10pt; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; color: #000000; font-family: Batang, 바탕; font-variant-caps: normal; font-variant-ligatures: normal; line-height: 1.5; font-weight: bold;&quot;&gt;안녕하세요.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: 14px; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; color: #ff5e00; font-family: 'Spoqa Han Sans', sans-serif; font-variant-caps: normal; font-variant-ligatures: normal; line-height: 1.5;&quot;&gt;삐질삐질 개발하는 개발자 삐질&lt;/span&gt;&lt;span style=&quot;font-size: 10pt; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; color: #000000; font-family: Batang, 바탕; font-variant-caps: normal; font-variant-ligatures: normal; line-height: 1.5; font-weight: bold;&quot;&gt;입니다.&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin: 0px auto 28px; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; padding: 0px !important 0px 0px !important 0px;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;p&gt;오늘은 그냥 제가 심심해서 동기와 비동기의 시간차이 측정을 해봤습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;별 내용은 없습니다 만, 관찰 결과를 포스팅 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;실험 주제: Retrofit 동기 / 비동기 콜에 대한 시간 차이 측정&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1. 단순 mainThread에서 비동기 Retrofit call&lt;/p&gt;
&lt;p&gt;2. Rx에서 비동기 Retrofit call&lt;/p&gt;
&lt;p&gt;3. Rx에서 동기 Retrofit call&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;결과는 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;1. 단순 mainThread에서 비동기 Retrofit call&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9.8pt;&quot;&gt;&lt;code&gt;fun asyncApiTestCall() {
    getCurrentThreadName(Thread.currentThread().stackTrace[2].methodName)
    var nickName = &quot;${Random.nextInt()}&quot;
    var pwd = &quot;1234&quot;
    var call = apiClss.registUserApi(nickName, pwd)
    var start  = System.currentTimeMillis()

    var callBack = object : Callback&amp;lt;ResultObject&amp;gt; {
        override fun onFailure(call: Call&amp;lt;ResultObject&amp;gt;, t: Throwable) {
         //   Log.e(&quot;innerRxAsyncApiTestCall&quot;, &quot;onFailure&quot;)
            getCurrentThreadName(Thread.currentThread().stackTrace[2].methodName)

        }

        override fun onResponse(
            call: Call&amp;lt;ResultObject&amp;gt;,
            response: Response&amp;lt;ResultObject&amp;gt;
        ) {
            getCurrentThreadName(Thread.currentThread().stackTrace[2].methodName)
            var end  = System.currentTimeMillis()

            calcTimeDiff(start,end)
       //     Log.e(&quot;innerRxAsyncApiTestCall&quot;, &quot;onResponse&quot;)
        }
    }
    call.enqueue(callBack)

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;1회차&lt;/p&gt;
&lt;p&gt;2020-04-22 20:38:53.693 31375-31375/com.example.rxretrofit2 E/asyncApiTestCall: main / 1587555533693&lt;/p&gt;
&lt;p&gt;2020-04-22 20:38:53.844 31375-31375/com.example.rxretrofit2 E/onResponse: main / 1587555533844&lt;/p&gt;
&lt;p&gt;2020-04-22 20:38:53.844 31375-31375/com.example.rxretrofit2 E/시간차: 150초&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2회차&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:00.633 31375-31375/com.example.rxretrofit2 E/asyncApiTestCall: main / 1587555540633&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:00.782 31375-31375/com.example.rxretrofit2 E/onResponse: main / 1587555540782&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:00.782 31375-31375/com.example.rxretrofit2 E/시간차: 149초&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2. Rx에서 비동기 Retrofit call&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;kotlin&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9.8pt;&quot;&gt;&lt;code&gt;fun innerRxAsyncApiTestCall() {
    getCurrentThreadName(Thread.currentThread().stackTrace[2].methodName)
    var start  = System.currentTimeMillis()

    compositeDisposable.add(
        Completable.fromAction {
            var nickName = &quot;${Random.nextInt()}&quot;
            var pwd = &quot;1234&quot;
            var call = apiClss.registUserApi(nickName, pwd)

            var callBack = object : Callback&amp;lt;ResultObject&amp;gt; {
                override fun onFailure(call: Call&amp;lt;ResultObject&amp;gt;, t: Throwable) {
                  //  Log.e(&quot;innerRxAsyncApiTestCall&quot;, &quot;onFailure&quot;)
                    getCurrentThreadName(Thread.currentThread().stackTrace[2].methodName)

                }

                override fun onResponse(
                    call: Call&amp;lt;ResultObject&amp;gt;,
                    response: Response&amp;lt;ResultObject&amp;gt;
                ) {
                    getCurrentThreadName(Thread.currentThread().stackTrace[2].methodName)
                    var end  = System.currentTimeMillis()

                    calcTimeDiff(start,end)
                  //  Log.e(&quot;innerRxAsyncApiTestCall&quot;, &quot;onResponse&quot;)
                }
            }

            call.enqueue(callBack)
        }
            .subscribeOn(Schedulers.io())
            .subscribe({
                getCurrentThreadName(&quot;subscribe/&quot;+Thread.currentThread().stackTrace[2].methodName)

            }, {

            })
    )
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;1회차&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;2020-04-22 20:39:02.014 31375-31375/com.example.rxretrofit2 E/innerRxAsyncApiTestCall: main / 1587555542014&lt;/div&gt;
&lt;div&gt;2020-04-22 20:39:02.015 31375-31449/com.example.rxretrofit2 E/subscribe/run: RxCachedThreadScheduler-1 / 1587555542015&lt;/div&gt;
&lt;div&gt;2020-04-22 20:39:02.159 31375-31375/com.example.rxretrofit2 E/onResponse: main / 1587555542159&lt;/div&gt;
&lt;div&gt;2020-04-22 20:39:02.160 31375-31375/com.example.rxretrofit2 E/시간차: 146초&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2회차&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:02.014 31375-31375/com.example.rxretrofit2 E/innerRxAsyncApiTestCall: main / 1587555542014&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:02.015 31375-31449/com.example.rxretrofit2 E/subscribe/run: RxCachedThreadScheduler-1 / 1587555542015&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:02.159 31375-31375/com.example.rxretrofit2 E/onResponse: main / 1587555542159&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:02.160 31375-31375/com.example.rxretrofit2 E/시간차: 146초&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;3. Rx에서 동기 Retrofit call&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9.8pt;&quot;&gt;&lt;code&gt;fun innerSyncApiTestCall() {
    getCurrentThreadName(Thread.currentThread().stackTrace[2].methodName)
    var start  = System.currentTimeMillis()
    compositeDisposable.add(

        Completable.fromAction {
            var nickName = &quot;${Random.nextInt()}&quot;
            var pwd = &quot;1234&quot;
            var call = apiClss.registUserApi(nickName, pwd)
            var response = call.execute().body()
            //Log.e(&quot;innerSyncApiTestCall&quot;, response.toString())
            getCurrentThreadName(&quot;fromAction/&quot;+Thread.currentThread().stackTrace[2].methodName)
            var end  = System.currentTimeMillis()

            calcTimeDiff(start,end)

        }
            .subscribeOn(Schedulers.io())
            .subscribe({
                getCurrentThreadName(&quot;subscribe/&quot;+Thread.currentThread().stackTrace[2].methodName)

            }, {

            })
    )

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;1회차&lt;/p&gt;
&lt;p&gt;2020-04-22 20:38:55.598 31375-31375/com.example.rxretrofit2 E/innerSyncApiTestCall: main / 1587555535598&lt;/p&gt;
&lt;p&gt;2020-04-22 20:38:55.740 31375-31449/com.example.rxretrofit2 E/fromAction/run: RxCachedThreadScheduler-1 / 1587555535740&lt;/p&gt;
&lt;p&gt;2020-04-22 20:38:55.741 31375-31449/com.example.rxretrofit2 E/시간차: 143초&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2회차&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:03.042 31375-31375/com.example.rxretrofit2 E/innerSyncApiTestCall: main / 1587555543042&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:03.187 31375-31449/com.example.rxretrofit2 E/fromAction/run: RxCachedThreadScheduler-1 / 1587555543187&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:03.187 31375-31449/com.example.rxretrofit2 E/시간차: 145초&lt;/p&gt;
&lt;p&gt;2020-04-22 20:39:03.187 31375-31449/com.example.rxretrofit2 E/subscribe/run: RxCachedThreadScheduler-1 / 1587555543187&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;보시면 아시겠지만&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;크게 유의미한 차이는 없습니다. 물론 아주 간단한 API에 대한 테스트였기에 정확도를 논할 수 있을까? 싶기도 하지만&lt;/p&gt;
&lt;p&gt;기본적으로 동기와 비동기의 차이라고 해 봤자, API가 응답하는 시간의 차이이기 때문에&amp;nbsp;&lt;/p&gt;
&lt;p&gt;같은 네트워크 / 같은 서버의 성능으로 봤을때 아아아아아주 미미한 랜덤한 차이가 발생합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;취향에 맞게 사용하시면 될 것 같습니다.&lt;/p&gt;
&lt;p&gt;(그래도 Rx&amp;nbsp; 동기가 제일 빠르기는 하네요 ..)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;위의 결과는&amp;nbsp;MiliSeconds의 차이이며 &quot;초&quot;라고 하였지만, 초는 무시해주시면 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;로깅을 위한 펑션&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9.8pt;&quot;&gt;&lt;code&gt;fun getCurrentThreadName(tag: String?) {
    var name = Thread.currentThread().name
    Log.e(tag, &quot;${name} / ${System.currentTimeMillis()}&quot;)
}

fun calcTimeDiff(start:Long, end:Long){
    var diff = end -start
    val diffSeconds: Long = diff / 1000 % 60
    Log.e(&quot;시간차&quot;,&quot;${diff}초&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;-en-clipboard: true;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px; font-size: 14px; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;&quot;&gt;&lt;span style=&quot;font-size: 14px; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; color: #2d4fc9; font-family: '맑은 고딕', sans-serif; font-variant-caps: normal; font-variant-ligatures: normal;&quot;&gt;초급 안드로이드 개발자를 위한 카카오톡 오픈 채팅방을 운영 중 입니다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px; font-size: 14px; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;&quot;&gt;&lt;span style=&quot;font-size: 14px; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; color: #5c5c5c; font-family: '맑은 고딕', sans-serif; font-variant-caps: normal; font-variant-ligatures: normal;&quot;&gt;(저는 마냥 친절한 방장은 아닙니다.&amp;nbsp; 다만, 다 같이 성장하고 싶은 방장이며 개발자 입니다)&lt;/span&gt;&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://open.kakao.com/o/gn4xqQ6&quot;&gt;https://open.kakao.com/o/gn4xqQ6&lt;/a&gt;&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 Tip</category>
      <author>삐질</author>
      <guid isPermaLink="true">https://ppizil.tistory.com/42</guid>
      <comments>https://ppizil.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%8B%AC%EC%8B%AC%ED%95%B4%EC%84%9C-%EC%B0%8D%EC%96%B4%EB%B3%B8-Retrofit-%EB%8F%99%EA%B8%B0-%EB%B9%84%EB%8F%99%EA%B8%B0-FeatRx#entry42comment</comments>
      <pubDate>Wed, 22 Apr 2020 20:46:50 +0900</pubDate>
    </item>
    <item>
      <title>[안드로이드] 기본적인  Recyclerview ViewType으로 홀더 나누기, 다른 Layout만들기</title>
      <link>https://ppizil.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9D%B8-Recyclerview-ViewType%EC%9C%BC%EB%A1%9C-%ED%99%80%EB%8D%94-%EB%82%98%EB%88%84%EA%B8%B0-%EB%8B%A4%EB%A5%B8-Layout%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-size: 14px; line-height: 28px;&quot;&gt;안녕하세요&lt;/span&gt;&lt;span style=&quot;font-size: 14px; line-height: 28px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: 14px; line-height: 28px; color: #f15f5f;&quot;&gt;개발자 삐질&lt;/span&gt;&lt;span style=&quot;font-size: 14px; line-height: 28px;&quot;&gt;입니다&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14px; line-height: 28px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14px; line-height: 28px;&quot;&gt;&lt;span style=&quot;line-height: 28px;&quot;&gt;오늘 제가 소개하고 싶은 내용은 리사이클러뷰를 다루다 보면, 칸칸이 다른 Row를 표현해야할 때가 옵니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14px; line-height: 28px;&quot;&gt;&lt;span style=&quot;line-height: 28px;&quot;&gt;그때를 위한 ViewType을 사용해 표현하는 방법&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;line-height: 28px;&quot;&gt;입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14px; line-height: 28px;&quot;&gt;&lt;span style=&quot;line-height: 28px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;간략하게 개념을 설명 드리겠습니다.&lt;/p&gt;
&lt;p&gt;리사이클러뷰는 각 칸마다 해당 칸의 ViewType, 즉 해당 칸(Row&quot;이하 칸&quot;)의 특성을 나타내는 ViewType이란 것을&lt;/p&gt;
&lt;p&gt;기반으로 어떤 Layout을 형성할지 onCreateViewHolder에서 판단한 뒤, Holder를 return하게 됩니다.&lt;/p&gt;
&lt;p&gt;기본적으로 이 ViewType의 Value는 개발자가 직접 지정할 수 있으며, 지정하지 않았을때는 내부적으로 Default value로 처리가 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;b&gt;즉&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;b&gt;1.빨 ViewType =1&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;b&gt;2.주 ViewType =2&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;b&gt;3.노 ViewType =3&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;b&gt;4.초 ViewType =4&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;b&gt;5.파 ViewType =5&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;b&gt;6.남 ViewType =6&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;b&gt;7.보 ViewType =7&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;line-height: 1.5;&quot;&gt;&lt;b&gt;과 같이 저는 ArrayList각 아이템에 ViewType을 지정하겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;리사이클러뷰는 각 칸의 데이터를 List형태로 관리하기 때문에 해당 List(샘플 데이터)를 만들기 위해&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Model과 ViewType을 가지는 ItemEntity클래스를 만들어줬습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #5d5d5d;&quot;&gt;&lt;b&gt;ViewHolder 라는 것은 말 그대로 View를 담는 그릇입니다 RecyclerView에서는 칸칸별로 Layout을 핸들링 하기 위한 Holder를 강제하고 있습니다. ViewHolder에 대한 기본 개념은 추가적으로 공부하시기 바랍니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;span style=&quot;font-size: 12pt; color: #ff0000;&quot;&gt;저는 기본적으로 FindViewById를 사용하지 않습니다. DataBinding을 사용해 Id에 접근합니다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&lt;span style=&quot;font-size: 16px;&quot;&gt;&lt;b&gt;Gradle :App 에 아래와 같이 추가해주시면 됩니다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;nix&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9.8pt;&quot;&gt;&lt;code&gt;dataBinding{
    enabled= true
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9.8pt;&quot;&gt;&lt;code&gt;
class Model {

    init {
    }

    //각자 다른 뷰타입을 아이템 7개에 순차적으로  Insert
    fun makeTestEntities(): ArrayList&amp;lt;Item&amp;gt; {
        var items = ArrayList&amp;lt;Item&amp;gt;()
        for (i in 1..7) {
            var item =
                Item(i)
            items.add(item)
        }

        return items
    }


    data class Item(
        var viewType: Int = 0
    ) {

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이후 모델은 Item클래스의 객체를 7개의 List를 만들기 위한 Function을 만들어 주었습니다.&lt;/p&gt;
&lt;p&gt;이 Function은 호출 시, 7개의 Item타입을 가지고있는 ArrayList를 반환하게 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이후 RecyclerView Adatper를 커스텀 해주었습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9.8pt;&quot;&gt;&lt;code&gt;class ItemsAdatper(private var items: ArrayList&amp;lt;Model.Item&amp;gt;?) : RecyclerView.Adapter&amp;lt;RecyclerView.ViewHolder&amp;gt;() {

    //각 뷰타입 별 분기 -&amp;gt; 다른 홀더와 다른 Layout을 Inflate해줌
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        when (viewType) {
            TYPE_RE -&amp;gt; {
                var binding =
                    ItemType01Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                return ItemRedHolder(
                    binding
                )
            }
            TYPE_OR -&amp;gt; {
                var binding =
                    ItemType02Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                return ItemOrangeHolder(
                    binding
                )
            }
            TYPE_YELL -&amp;gt; {
                var binding =
                    ItemType03Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                return ItemYellowHolder(
                    binding
                )
            }
            TYPE_GR -&amp;gt; {
                var binding =
                    ItemType04Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                return ItemGreenHolder(
                    binding
                )
            }
            TYPE_BL -&amp;gt; {
                var binding =
                    ItemType05Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                return ItemBlueHolder(
                    binding
                )
            }
            TYPE_DEPPBL -&amp;gt; {
                var binding =
                    ItemType06Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                return ItemDBlueHolder(
                    binding
                )
            }
            TYPE_PU -&amp;gt; {
                var binding =
                    ItemType07Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                return ItemPupleHolder(
                    binding
                )
            }
            else -&amp;gt; {
                var binding =
                    ItemType01Binding.inflate(LayoutInflater.from(parent.context), parent, false)
                return ItemRedHolder(
                    binding
                )
            }

        }
    }

    // 어댑터가 전달받은 리스트 사이즈 반환 , Null일땐 0
    override fun getItemCount(): Int {
        return items?.size ?: 0
    }

    //홀더 타입에 따라 뷰와 바인딩 해줌
    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        if (holder is ItemRedHolder) {
            holder.bind(items?.get(position))
        } else if (holder is ItemOrangeHolder) {
            holder.bind(items?.get(position))
        } else if (holder is ItemYellowHolder) {
            holder.bind(items?.get(position))
        } else if (holder is ItemGreenHolder) {
            holder.bind(items?.get(position))
        } else if (holder is ItemBlueHolder) {
            holder.bind(items?.get(position))
        } else if (holder is ItemDBlueHolder) {
            holder.bind(items?.get(position))
        } else if (holder is ItemPupleHolder) {
            holder.bind(items?.get(position))
        }
    }

    //각 아이템의 Viewtype을 반환함 여기서 반환 된 VieType-&amp;gt; onCreateViewHolder로 넘어감
    override fun getItemViewType(position: Int): Int {
        items?.let {
            return it[position].viewType
        } ?: kotlin.run {
            return super.getItemViewType(position)
        }
    }


    //뷰타입 종류
    companion object {
        const val TYPE_RE = 1;
        const val TYPE_OR = 2;
        const val TYPE_YELL = 3;
        const val TYPE_GR = 4;
        const val TYPE_BL = 5;
        const val TYPE_DEPPBL = 6;
        const val TYPE_PU = 7;

    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;리사이클러뷰 어댑터에서는 기본적으로 우리가 알고있는 onCreateViewHolder / getItemCount / onBindViewHolder 외 getItemViewType이라는 Override Function을 추가로 재정의 합니다.&lt;/p&gt;
&lt;p&gt;이 Function에는 제가 위에서 만들어 Adapter클래스로 전달해 준 ArrayList의 각 칸의 ViewType을 반환합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이렇게 Model / ItemEntity / Adapter가 정의 되었다면 실제로 Recyclerview에 대한 설정을 위해 Activity에서 아래와 같이 작업 했습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9.8pt;&quot;&gt;&lt;code&gt;
class MainActivity : AppCompatActivity() {
    lateinit var binding: ActivityMainBinding
    var adapter: ItemsAdatper? = null
    var model: Model? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView(
            this,
            R.layout.activity_main
        )
        init()
    }

    fun init() {
        model = Model() // 데이터를 핸들링 하기 위한 Model Init
        setRecyclerView() //리사이클러뷰 Init
    }

    fun setRecyclerView() {
        adapter =
            ItemsAdatper(model?.makeTestEntities())
        var layoutManager = LinearLayoutManager(this)
        layoutManager.orientation = RecyclerView.VERTICAL
        binding.recyclerview.layoutManager = layoutManager
        binding.recyclerview.adapter = adapter
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;참 쉽쥬?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;onCreate가 호출되게 되면, inti -&amp;gt; setRecyclerView()를 거쳐 RecyclerView가 Adatper를 Setted하게 되고 실제 아이템을 그리게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: line-through;&quot;&gt;예제이기 때문에 목적별 라이프사이클에 대한 Function의 위치는 무시해주세요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;그렇게 되면 아래와 같은 View를 그리게 됩니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;374&quot; height=&quot;614&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://t1.daumcdn.net/cfile/tistory/995C834D5E983D880B?original&quot; data-phocus=&quot;https://t1.daumcdn.net/cfile/tistory/995C834D5E983D880B?original&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/995C834D5E983D880B&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F995C834D5E983D880B&quot; width=&quot;374&quot; height=&quot;614&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;figure class=&quot;imageblock alignCenter&quot; width=&quot;377&quot; height=&quot;630&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://t1.daumcdn.net/cfile/tistory/9918F84D5E983D8816?original&quot; data-phocus=&quot;https://t1.daumcdn.net/cfile/tistory/9918F84D5E983D8816?original&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9918F84D5E983D8816&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9918F84D5E983D8816&quot; width=&quot;377&quot; height=&quot;630&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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;figure class=&quot;imageblock alignCenter&quot; width=&quot;377&quot; height=&quot;621&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://t1.daumcdn.net/cfile/tistory/9905E94D5E983D8806?original&quot; data-phocus=&quot;https://t1.daumcdn.net/cfile/tistory/9905E94D5E983D8806?original&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9905E94D5E983D8806&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9905E94D5E983D8806&quot; width=&quot;377&quot; height=&quot;621&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이렇듯 RecyclerView는 칸칸이 다른 레이아웃(뷰홀더)을 관리할 수 있게 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;-----------------------------------샘플 ItemHolder xml -----------------------------&lt;/p&gt;
&lt;p&gt;Item_type01.xml&lt;/p&gt;
&lt;pre class=&quot;xml&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9.8pt;&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;
&amp;lt;layout&amp;gt;

    &amp;lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;200dp&quot;
        android:background=&quot;#FA0909&quot;&amp;gt;

        &amp;lt;TextView
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;match_parent&quot;
            android:text=&quot;빨강색&quot;
            android:gravity=&quot;center&quot;
            android:textColor=&quot;#ffffff&quot;
            android:textSize=&quot;40sp&quot;&amp;gt;&amp;lt;/TextView&amp;gt;
    &amp;lt;/LinearLayout&amp;gt;
&amp;lt;/layout&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Item_type02.xml&lt;/p&gt;
&lt;pre class=&quot;xml&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6; font-family: 'Consolas'; font-size: 9.8pt;&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&amp;gt;
&amp;lt;layout&amp;gt;

    &amp;lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;200dp&quot;
        android:background=&quot;#F46708&quot;&amp;gt;

        &amp;lt;TextView
            android:layout_width=&quot;match_parent&quot;
            android:layout_height=&quot;match_parent&quot;
            android:gravity=&quot;center&quot;
            android:text=&quot;주황색&quot;
            android:textColor=&quot;#ffffff&quot;
            android:textSize=&quot;40sp&quot;&amp;gt;&amp;lt;/TextView&amp;gt;
    &amp;lt;/LinearLayout&amp;gt;
&amp;lt;/layout&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;253&quot; height=&quot;280&quot; style=&quot;text-align: center;&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://t1.daumcdn.net/cfile/tistory/9977213D5E98410A2A?original&quot; data-phocus=&quot;https://t1.daumcdn.net/cfile/tistory/9977213D5E98410A2A?original&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9977213D5E98410A2A&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9977213D5E98410A2A&quot; width=&quot;253&quot; height=&quot;280&quot; style=&quot;text-align: center;&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&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&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;font-size: 14pt;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;해당 샘플의 코드는 아래 git에 가시면 볼수 있습니다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jaekanglee/RecyclerViewType&quot;&gt;&lt;span style=&quot;font-size: 14pt;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;https://github.com/jaekanglee/RecyclerViewType&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;margin: 0px; padding: 0px; color: #5c5c5c; font-family: 'Spoqa Han Sans', sans-serif; font-size: 14px;&quot;&gt;&lt;span style=&quot;color: #2d4fc9; font-family: '맑은 고딕', sans-serif;&quot;&gt;초급 안드로이드 개발자를 위한 카카오톡 오픈 채팅방을 운영 중 입니다.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px; color: #5c5c5c; font-family: 'Spoqa Han Sans', sans-serif; font-size: 14px;&quot;&gt;&lt;span style=&quot;font-family: '맑은 고딕', sans-serif;&quot;&gt;(저는 마냥 친절한 방장은 아닙니다.&amp;nbsp; 다만, 다 같이 성장하고 싶은 방장이며 개발자 입니다)&lt;/span&gt;&lt;/div&gt;
&lt;div style=&quot;margin: 0px; padding: 0px; color: #5c5c5c; font-family: 'Spoqa Han Sans', sans-serif; font-size: 14px;&quot;&gt;&lt;a href=&quot;https://open.kakao.com/o/gn4xqQ6&quot;&gt;https://open.kakao.com/o/gn4xqQ6&lt;/a&gt;&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;&lt;a href=&quot;https://open.kakao.com/o/gH0XvThc&quot;&gt;open.kakao.com/o/gH0XvThc&lt;/a&gt;&lt;br /&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 Tip</category>
      <author>삐질</author>
      <guid isPermaLink="true">https://ppizil.tistory.com/41</guid>
      <comments>https://ppizil.tistory.com/entry/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EA%B8%B0%EB%B3%B8%EC%A0%81%EC%9D%B8-Recyclerview-ViewType%EC%9C%BC%EB%A1%9C-%ED%99%80%EB%8D%94-%EB%82%98%EB%88%84%EA%B8%B0-%EB%8B%A4%EB%A5%B8-Layout%EB%A7%8C%EB%93%A4%EA%B8%B0#entry41comment</comments>
      <pubDate>Thu, 16 Apr 2020 20:22:12 +0900</pubDate>
    </item>
  </channel>
</rss>