<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>wyt_cpri.log</title>
        <link>https://velog.io/</link>
        <description>항상 새로움을 추구하는 안드로이드 개발자입니다! 🏆</description>
        <lastBuildDate>Mon, 08 Jan 2024 13:53:40 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>wyt_cpri.log</title>
            <url>https://velog.velcdn.com/images/wyt_cpri/profile/191c4be5-9a58-4a38-b35e-896b2f23fccc/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. wyt_cpri.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/wyt_cpri" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[2024 Prography IT DAY]]></title>
            <link>https://velog.io/@wyt_cpri/2024-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9D%BC%ED%94%BC-IT-DAY</link>
            <guid>https://velog.io/@wyt_cpri/2024-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9D%BC%ED%94%BC-IT-DAY</guid>
            <pubDate>Mon, 08 Jan 2024 13:53:40 GMT</pubDate>
            <description><![CDATA[<p>2024년 1월 6일, 토요일에 프로그라피 IT DAY 세미나가 있었습니다.
제가 처음으로 프로그라피에서 회장직인 <strong>디렉터를</strong> 맡고, 처음으로 프로그라피 내부의 사람들이 아닌, 그 외부의 사람들에게 저와 프로그라피를 알리는 자리를 만들게 되었습니다. 
저 역시 수많은 사이드 프로젝트를 경험했던 사람으로써, &quot;내 사이드 프로젝트가 망하는 이유&quot; 에 대해서 세미나를 하기도 했습니다.
저는 그래서 저희의 처음을 시작하였던 IT DAY 에 대해서 이야기해보려 합니다.</p>
<blockquote>
<p>Prography에서 1월13일부터 9기 모집이 시작됩니다.
    글을 읽으며 조금이라도 재밌겠다는 생각이 들거나, 같이 참여하고 싶다는 생각이 조금이라도 생긴다면 적극적인 지원 부탁드립니다.
    또한 앞으로도 네트워킹 세미나와 같은 행사를 꾸준히 개최하기 위해 노력하고 있으니, 많은 관심 부탁드립니다!
    Prography 🏡 : <a href="https://prography.org/">https://prography.org/</a>
    Prography 플러스채널 : <a href="http://pf.kakao.com/_tusXG">http://pf.kakao.com/_tusXG</a></p>
</blockquote>
<h1 id="세미나의-시작">세미나의 시작</h1>
<p>이번에 프로그라피에서는 정말 많은 새로운 시도를 하려 합니다. 그중에 첫번째였던 것이 바로 IT DAY, 네트워킹 세미나입니다. 
처음은 하나의 단순한 요청에서 시작했습니다.<img src="https://velog.velcdn.com/images/wyt_cpri/post/9be713c4-2e50-4ac5-a04a-6f902c8c9772/image.png" alt="">
하지만 다른 매니저들 전부 이 의견에 대해서 굉장히 관심을 가지게 되었고, 진행하고자 하는 열망이 생겨 사전적으로 우리가 이걸 진행해도 괜찮은지에 대해서 조사를 받기 시작했습니다.
<img src="https://velog.velcdn.com/images/wyt_cpri/post/d086f9ba-001e-4ff2-85ab-23ae0612daef/image.png" alt="무려 100명이 넘는 분들께서 참여의 의사를 보여주셨습니다!">
이 결과는 <strong>단 3일</strong> 만에 이렇게나 많은 분들이 저희의 행사에 관심을 가져주셨고, 저희도 이 결과를 보고 진행해야 한다라는 판단이 들어 이때부터 계획을 시작했습니다.
행사의 유형은 어떤게 좋은지, 세미나 형식이 될 것인지 커피챗 형식이 될 것인지, 혹은 그 둘 다 될 것인지 이러한 방법에서부터, 이걸로 어떠한 목적이 달성되는지까지 굉장히 많은 이야기가 오고 갔습니다.
하지만 확실했던건, 많은 사람들이 우리의 행사를 기다리고 있고, 저희는 그 기대에 걸맞는 양질의 행사를 만들어야 한다는 것이였습니다.
무려 한달 전부터 시작되어 준비된 세미나는 서서히 가까워 졌고, 1월 6일, 세미나가 시작되었습니다.</p>
<h1 id="prography-it-day">Prography IT DAY</h1>
<p><img src="https://velog.velcdn.com/images/wyt_cpri/post/4dfe165c-2dae-4c99-a2e4-f5af97bfd232/image.JPG" alt="">
처음 이 장소에 들어갔을 때는 기대보다는 걱정이 앞섰습니다. 
<em>처음 진행하는 이 행사를 잘 끝마칠 수 있을까? 사람들에게 좋은 영향을 끼칠까?</em>
이러한 걱정을 가지고 첫번째 세미나가 시작되었습니다.</p>
<h2 id="marketing--po--designer">Marketing / P.O / Designer</h2>
<p><img src="https://velog.velcdn.com/images/wyt_cpri/post/c59ddd38-33c9-497a-8731-b39b6f8a31a2/image.JPG" alt="">
오전 시간에는 <strong>마케팅 세션</strong>과 더불어 <strong>P.O 세션</strong>과 <strong>디자이너 세션</strong>이 진행되었습니다.
생각보다 이른 아침임에도 불구하고 더욱 많은 분들의 세션에 참여해주셨고, 여기서 걱정을 한시름 덜 수 있었습니다. (이 자리를 빌어서 이른 아침에도 저희의 행사를 참석해주신 분들께 다시 한 번 큰 감사드립니다.🙇)
&#39; 아 , 생각보다 우리의 세션들을 사람들이 더 많이 듣고 싶어했고, 더 궁금해했던 세션들이였구나 &#39; 라고 생각하게 되었습니다. 
어떻게보면 첫 단추가 가장 중요한 부분인데, 너무 잘 끼워지기도 해서, 이제는 잘 마무리만 해보자 하는 생각으로 세미나에 임했습니다.</p>
<p><img src="https://velog.velcdn.com/images/wyt_cpri/post/b6467070-de65-42d5-9697-d259c3cc8d9b/image.JPG" alt="">
또한 되게 많은 사람들이 세션과 함께 커피챗도 함께 신청해주셨고, 되게 다양한 사람들이 좋은 정보들과 좋은 인맥을 쌓아갔다는 생각이 들어 어떻게 보면 세션보다 더욱 유익한 시간이지 않았나? 라는 생각이 들었습니다. 
하나 아쉬운게 있었다면, 다른 세션들도 있고, 커피챗에 대해서 많은 준비를 못한 까닭일 수도 있지만, 그 정보를 줄 수 있는 양에 비해서 저희가 제공해드렸던 절대적인 시간이 너무 한정되지 않았나..? 라는 아쉬움이 좀 짙게 남았던 것 같습니다.
혹시 다음에 또 이러한 세션들이 더 생기게 된다면, 커피챗 시간을 더 많이, 더 자주 진행하면 어떨까 하게 만드는 시간이였습니다.</p>
<h2 id="프로그라피-소개-세션">프로그라피 소개 세션</h2>
<p>다음은 <em><strong>프로그라피 소개 세션</strong></em> 을 진행했습니다. 여태까지의 프로그라피는 어때왔고, 앞으로의 프로그라피는 어떻게 될 것인지를 설명하는 자리로 마련하려 했습니다. <img src="https://velog.velcdn.com/images/wyt_cpri/post/32ee20f9-2123-4b62-a744-4125228a389a/image.JPG" alt="">
세상에 필요한 IT 서비스를 만들어가는 동아리에서, 열정을 가진 개발자/디자이너들의 모임으로. 열정을 가진 개발자/디자이너들의 모임에서 성장하고 싶은 사람들의 IT 커뮤니티로 변화하는 과정을 담으려 했고, 또한 저희의 앞으로의 방향성에 대해서 깊게 얘기를 꺼내려 했습니다. 또한 <strong>Communication, High Quality, Synergy, Improvement</strong> 이 4개의 철학을 가지고 프로그라피를 이끌어나갈 것이라는 것을 많은 사람들 앞에서 공표하는 자리이기도 했습니다. 
앞으로 더욱 재밌고, 더욱 유익한 커뮤니티를 만들기 위해서 디렉터로써 더욱 노력하도록 하겠습니다. 더욱 성장하는 프로그라피, 지켜봐주세요!</p>
<h2 id="be--fe--mobile">BE / FE / Mobile</h2>
<p>오후에는 개발 세션 4개를 진행하게 되었습니다 그 중에서는 제가 진행하는 &quot;내 사이드 프로젝트가 망하는 이유&quot; 세션도 포함되어 있었고 발표를 진행하게 되었습니다. <img src="https://velog.velcdn.com/images/wyt_cpri/post/5577dd84-a050-4879-8f95-5ca1ef5120bf/image.jpeg" alt="">
정말 다행스럽게도, 많은 분들이 제 세션을 들어주셨고, 저 역시 이분들의 노고가 헛되지 않게 제가 경험했던 모든 일들과 사이드 프로젝트 관련 방법들을 다 전달해드리려 노력했습니다.
개발세션에서 개발세션답지 않은 세션을 진행했는데, 이렇게 많은 분들이 찾아와주셔서 여기서도 또 한번 굉장히 감사드립니다! </p>
<p><img src="https://velog.velcdn.com/images/wyt_cpri/post/e1fc07be-7e79-488e-905f-cb350afa40fc/image.JPG" alt="">
또한 저는 프로그라피 디렉터이기 전에, 한명에 안드로이드 개발자로써, 고현석 매니저님의 <em><strong>프로그라피 8기 프로젝트 멀티모듈 도입에 관하여</strong></em> 를 인상깊게 듣기도 했습니다. 저도 개발자인 입장에서, 멀티모듈을 사용하는 것에 대한 욕심들을 많이 가지고 있고, 그러한 고민의 흔적들을 고현석 매니저님께서 재밌게 풀어서 보여주셨다고 생각합니다!</p>
<blockquote>
<p>혹시라도 위 서비스가 궁금하시다면 <a href="https://apps.apple.com/kr/app/lovebird-%EC%BB%A4%ED%94%8C-%EA%B3%B5%EC%9C%A0-%EC%9D%BC%EA%B8%B0-%EC%95%B1/id6462698149">https://apps.apple.com/kr/app/lovebird-%EC%BB%A4%ED%94%8C-%EA%B3%B5%EC%9C%A0-%EC%9D%BC%EA%B8%B0-%EC%95%B1/id6462698149</a> 에서 확인해주세요!</p>
</blockquote>
<h1 id="아쉬웠던-점">아쉬웠던 점</h1>
<p>일단 제 개인적으로, 세션의 준비를  많이 못한 것에 대해서 큰 아쉬움이 있었습니다. 독감에 걸리기도 했고, 일이 바쁘다는 핑계로 많이 준비를 못했던 것 같다라는 아쉬움이 많이 남는 시간이였습니다. 
역시 제가 준비를 많이 못했다는 것이 보였던 건지, 너무 일반론적인 이야기만 반복한다는 피드백을 듣기도 했었습니다. 나중에는 더욱 열심히 준비해서 참여하셨던 모든 분들께서 만족하실 수 있는 주제와 내용으로 보여드릴 수 있는 시간이 되면 좋겠습니다.
또한 더욱 체계적인 준비가 필요하다는 것도 느끼게 되었습니다. 마이크를 전달하는 것부터, 세션이 혹시라도 빨라지거나 느려지는것을 대비하는것까지, 아직 처음이여서 미흡한 부분들이 굉장히 많았다고 생각합니다. 하지만 제가 저의 세션에서 말했던 <strong>&quot;아무 것도 하지 않았던 것보다 한발짝 앞에 가있는 것이다&quot;</strong> 라고 생각하면서 다음 IT DAY 를 더욱 체계적이고, 깔끔하게 진행할 수 있도록 노력하겠습니다.</p>
<h1 id="얘기를-마치며">얘기를 마치며</h1>
<p><img src="https://velog.velcdn.com/images/wyt_cpri/post/8a32344f-cca0-4b2f-94ba-4739604bc606/image.jpeg" alt="">
저는 욕심이 굉장히 많은 사람입니다. 앞으로 더욱 많은 사람들에게 프로그라피를 알리고 싶고, 더욱 많은 사람들이 프로그라피를 함께했으면 좋겠다는 생각이 항상 머리속에 자리잡아 있습니다. 
*<em>저는 앞으로 프로그라피를 IT 커뮤니티하면 모든 사람들의 생각속에 가장 먼저 떠오르는 곳으로 만들 것이고, 그렇게 될 것 입니다. *</em>
그 길에 굉장히 많은 시련들이 있을 것이고, 저 또한 굉장히 힘들겠지만, 재밌는 프로그라피를 만들기 위해 더 노력하고 계속 끊임없이 노력하겠습니다.
긴 글 읽어주셔서 감사드리고, 모두 평탄하고 행복한 2024년 되시길 희망합니다! ☀️</p>
<blockquote>
<p>Prography에서 1월13일부터 9기 모집이 시작됩니다.
    글을 읽으며 조금이라도 재밌겠다는 생각이 들거나, 같이 참여하고 싶다는 생각이 조금이라도 생긴다면 적극적인 지원 부탁드립니다.
    또한 앞으로도 네트워킹 세미나와 같은 행사를 꾸준히 개최하기 위해 노력하고 있으니, 많은 관심 부탁드립니다!
    Prography 🏡 : <a href="https://prography.org/">https://prography.org/</a>
    Prography 플러스채널 : <a href="http://pf.kakao.com/_tusXG">http://pf.kakao.com/_tusXG</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Android LaunchMode 알아보기]]></title>
            <link>https://velog.io/@wyt_cpri/Android-LaunchMode-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@wyt_cpri/Android-LaunchMode-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Tue, 01 Nov 2022 15:28:05 GMT</pubDate>
            <description><![CDATA[<p>이번에는 많은 개발자들이 처음에는 어려워하는 주제를 들고 와봤다. ( 사실, 내가 제일 어려워했다. )
그리고 이 주제는 되게 많은 회사에서 하나의 면접질문으로 나오기도 한다. 나도 이 질문을 면접에서 정말 많이 들었고, 그 때마다 정확하게 말했는지는 알 수 없다.
그래서 확실하게 알아보고, 이제는 면접에서도 정확하게 말할 수 있도록 확실하게 알아보려고 한다.</p>
<h2 id="androidlaunchmode">android:launchMode</h2>
<p>Android Manifest 에는 필요한 activity를 설정할 수 있고, 그 activity 가 실행되는 방법을 정의한다.
manifest에서 activity 태그 내에서 android:launchMode 를 정의하고 그 정의된 값에 맞는 값을 사용하게 된다.
<img src="https://velog.velcdn.com/images/wyt_cpri/post/3703aedf-83ce-49fe-bbe0-fb250f69b858/image.png" alt=""></p>
<p>이와 같이 Manifest 에서는 launchMode를 5가지로 분류할 수 있다. 
이제는 이 launchMode가 각자 어떤 것을 하는지를 차근차근 알아보도록 하자.
편의를 위해 launchMode.{VALUE} 형식으로 작성하도록 하겠다.</p>
<h3 id="launchmodestandard">launchMode.Standard</h3>
<p>가장 기본적으로 사용되는 기본값이다. 
시스템에서 활동이 시작된 작업에 새로운 인스턴스를 만들고, 인텐트를 인스턴스로 라우팅시킨다.
액티비티는 여러번 인스턴스로 만들어질 수 있으며, 각각의 액티비티 인스턴스는 다른 작업에 포함되어 있을수도 있다. 또한 하나의 작업에 여러개의 액티비티 인스턴스가 있을 수 있다.</p>
<p>만약 A -&gt; B -&gt; A -&gt; A 이렇게 액티비티가 변화된다고 가정해보자.
launchMode가 standard 일 때는 내 현재 인텐트가 무엇이던 간에, 항상 필요한 액티비티 인스턴스를 만들고, 그 인스턴스로 변화되게 된다. 물론 백 스택에도 남아있다.</p>
<h3 id="launchmodesingletop">launchMode.SingleTop</h3>
<p>현재 만들고 싶은 인스턴스가 최상단에 있다면, 시스템이 새로운 액티비티 인스턴스를 만들지 않고, <code>onNewIntent()</code> 를 호출하여 현재 인스턴스의 인텐트를 바꿔주게 된다.
이런 상황을 제외하고는, standard 와 동일한 역할을 하게 된다</p>
<p>standard와 같은 예시를 들어보겠다.
만약 A -&gt; B -&gt; A -&gt; A 와 같이 액티비티 인스턴스가 생성된다고 가정해보자.
그러면 standard에서는 어떤 상황에서도 새로운 액티비티 인스턴스를 만들고 라우팅을 진행하게 된다.
하지만 SingleTop 에서는 그렇지 않다.
A -&gt; B -&gt; A 까지는 동일하게 진행이 되지만,  A 액티비티에서 A 인텐트가 왔을 때, 새로운 인스턴스를 만들지 않고, <code>onNewIntent()</code> 함수를 호출하여 새 액티비티 인스턴스를 만들지 않고, 인텐트를 현재 액티비티 인스턴스로 라우팅해주게 된다.</p>
<h3 id="launchmodesingletask">launchMode.SingleTask</h3>
<p>SingleTask 로 설정되어 있는 Activity 가 불리게 되면, 시스템이 그 액티비티로 진행되는 새 작업을 만들고, 그 작업에 루트로 현재 액티비티 인스턴스를 라우팅 해주게 된다. 그러나, 이 SingleTask 로 설정되어 있는 액티비티가 어느 한 프로세스에서라도 동작중이면, 그 액티비티의 <code>onNewIntent</code>가 불리면서 인텐트를 현재 존재하고 있는 인스턴스로 라우팅하게 된다. 그 말은 현재 액티비티의 인스턴스는 한 번에 하나만 존재할 수 있다는 것이다.</p>
<p>예를 들어보겠다.
A -&gt; B -&gt; C 인 상황에서 C 가 SingleTask 라고 가정해보자.
A -&gt; B 까지는 하나의 프로세스에서 동작할 것이다. 그러나 B 액티비티에서 C 인스턴스를 만드려고 한다면, C 인스턴스는 새로운 프로세스에서 동작을 하게 될 것이다. 다시 뒤로 가게 되면 C 프로세스는 사라지고, A -&gt; B 액티피티가 존재하는 프로세스로 돌아오게 된다.
A -&gt; B -&gt; A 의 과정에서는, A -&gt; B 과정까지는 그대로 인텐트 형식으로 액티비티가 생성되지만, A 는 이미 하나의 프로세스에서 동작 중에 있기 때문에, 새로운 작업을 만들지 않고, 존재하고 있는 A 액티비티에 <code>onNewIntent()</code> 함수가 불리게 되면서 선택된 인텐트가 존재하고 있는 A 액티비티로 라우팅되게 된다.  </p>
<h3 id="launchmodesingleinstance">launchMode.SingleInstance</h3>
<p>SingleTask와 동일한 동작을 제공하지만, 시스템이 SingleInstance로 설정되어 있는 액티비티의 프로세스는 이 액티비티 인스턴스 외에는 어떠한 다른 활동도 실행하지 않는다는 것이 차이점이다.
이 활동으로 시작된 모든 인스턴스 활동들은 별도의 프로세스를 가지고 실행하게 된다.</p>
<p>여기 A -&gt; B -&gt; A -&gt; A를 가진 함수가 있다.
여기서 A가 SingleInstance라고 가정해보자. 
그렇게 되면 A -&gt; B 로 인텐트를 움직일 프로세스를 만들 것이며, B -&gt; A 로 갈 때에도 새로운 프로세스를 생성하게 될 것이다. 그리고 A -&gt; A 로 갈 때에도 역시나 SingleInstance 형식을 가지고 있기 때문에, 새로운 프로세스로 시작이 될 것이다. 그래서 결국에는 A 인스턴스를 가진 프로세스 태스크는 3개가 존재할 것이다.</p>
<h3 id="launchmodesingleinstancepertask">launchMode.SingleInstancePerTask</h3>
<p>이 launchMode를 설정한 Instance 는 프로세스의 첫 번째 작업으로만 실행이 될 수 있다고 한다.</p>
<p>A -&gt; B -&gt; A 이 상황에서는 
A -&gt; B 는 하나의 작업에서 실행이 되지만, B에서 A 에 대한 인스턴스로 활동은 만들 수 있어도, A의 인텐트를 가진 새로운 프로세스를 만들지 않는 한, A의 인텐트를 가진 새로운 인스턴스를 만들 수는 없다.</p>
<h2 id="그래서-어떤걸-써야-해">그래서... 어떤걸 써야 해???</h2>
<p><img src="https://velog.velcdn.com/images/wyt_cpri/post/fe2e0943-d27b-4eb2-993a-4462d877572e/image.png" alt="">
어떻게 사용되는지를 나열해 봤다.
그리고 구글에서 이렇게 말하기도 했다.
<em><strong>다른 모드인 <code>singleTask</code>, <code>singleInstance</code>, <code>singleInstancePerTask</code>는 대부분의 애플리케이션에 적합하지 않습니다.</strong></em>
보통 사용자들이 사용하기에는 standard 나 singleTop 을 추천한다고 한다.
하지만, 특정 상황에서 singleInstance나 SingleTask 도 사용성에 맞게 사용한다면, 충분히 사용할 수 있는 옵션이니 참고 바란다.</p>
<blockquote>
<p>참조: <a href="https://developer.android.com/guide/topics/manifest/activity-element#lmode">Android Developers</a></p>
</blockquote>
<p>그리고 마지막으로, 제가 아는 것이 이론적으로 확실하지 않을 수 있습니다. 
혹시라도 의문점이 있거나, 틀렸다라고 생각되는 부분이 있으면 댓글에다가 편하게 작성부탁드립니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[StateFlow vs SharedFlow]]></title>
            <link>https://velog.io/@wyt_cpri/StateFlow-vs-SharedFlow</link>
            <guid>https://velog.io/@wyt_cpri/StateFlow-vs-SharedFlow</guid>
            <pubDate>Fri, 28 Oct 2022 23:33:30 GMT</pubDate>
            <description><![CDATA[<p>어느 한 곳에 면접을 보게 되었다.
과제를 완료해서 과제에 대한 이야기를 하는 도중에 &quot;왜 StateFlow를 사용하셨나요??&quot; 라는 말을 듣게 되었다.
난 여기서 StateFlow를 통해서 collect를 받아오면서 사용할 수 있기 위해서 사용했다라고 답했다.
여기서 이제 내가 실수했던 문제가 나오게 됐는데, SharedFlow 와 StateFlow 의 차이를 물으셨다.
난 여기서 <del>StateFlow는 콜드 흐름이고, SharedFlow 는 핫 흐름이라고 답했다.</del> (그냥 그랬다구요.)
그러자 면접관님께서는 StateFlow도 핫 흐름이다. 들어가서 확인해보면 SharedFlow를 상속받고 있다.라고 하셨다.
나는 여기서 내가 내가 잘못 알고 있구나라고 느꼈고, 어떤게 다른지 궁금해졌다.</p>
<p>그래서 찾아봤을 때 가장 큰 건 두개가 있는것 같다.</p>
<h2 id="value-의-존재">Value 의 존재</h2>
<p>한번 StateFlow를 들어가봤다.</p>
<pre><code>public interface StateFlow&lt;out T&gt; : SharedFlow&lt;T&gt; {
    /**
     * The current value of this state flow.
     */
    public val value: T
}</code></pre><p>이렇게 되어있다. SharedFlow의 값을 그대로 상속받는데, 여기서 value 가 더해지는 거였다.
SharedFlow 에서는 value가 없고, StateFlow 만 가지고 있는 이유가 이거였다고 생각이 든다.
근데 StateFlow에서 value는 어떻게 동작하는지 알고싶었다.</p>
<pre><code>// StateFlow,kt ( StateFlowImpl )
 @Suppress(&quot;UNCHECKED_CAST&quot;)
    public override var value: T
        get() = NULL.unbox(_state.value)
        set(value) { updateState(null, value ?: NULL) }</code></pre><p>여기서 가지고 올때 NULL.unbox 라는 함수를 통하여 현재 <code>_state</code>를 통해 관리가 되고 있다. ( <code>_state</code>는 atomic 으로 <code>set()</code> 내의 <code>updateState()</code>에서 계속 변화되고 있다.
이렇게 때문에, StateFlow에서는 우리가 원하는 타입으로 value 를 가지고 올 수 있는 것이다.</p>
<h2 id="equality-check">Equality Check</h2>
<p>아마 이게 가장 중요한 부분이 아닐까 싶다. 
SharedFlow 는 이전의 값과 현재의 값이 같아도 collect 하는 과정에서 정상적으로 collect 가 진행되는 느낌인데, StateFlow 는 그런 느낌을 받지 못했다.
그래서 한번 찾아보려고 한다.</p>
<pre><code>// StateFlow.kt
// Conflate value emissions using equality
    if (oldState == null || oldState != newState) {
        collector.emit(NULL.unbox(newState))
        oldState = newState
    }</code></pre><p>위 코드는 StateFlowImpl에 collect함수에 들어있는 코드이다. oldState가 null이거나, oldState랑 newState의 값이 다를 때만 emit 을 진행하도록 설정되어 있다.
그렇다면 SharedFlow는 어떨까??</p>
<pre><code>// SharedFlow.kt
 var newValue: Any?
    while (true) {
        newValue = tryTakeValue(slot) // attempt no-suspend fast path first
            if (newValue !== NO_VALUE) break
            awaitValue(slot) // await signal that the new value is available
        }
    collectorJob?.ensureActive()
    collector.emit(newValue as T)</code></pre><p>위 코드는 SharedFlow 에 collect함수에 들어있는 코드이다. oldState 이런 것 없이 일단 emit하고 본다.
Equality Check 가 들어가지 않는다는 뜻이다.</p>
<h2 id="안드로이드에서-사용방법">안드로이드에서 사용방법</h2>
<p>그래도 만들어서 우리 손으로 변경이 가능한 MutableSharedFlow 랑 MutableStateFlow로 비교를 해보도록 하겠다.</p>
<pre><code>// SharedFlow.kt
public fun &lt;T&gt; MutableSharedFlow(
    replay: Int = 0,
    extraBufferCapacity: Int = 0,
    onBufferOverflow: BufferOverflow = BufferOverflow.SUSPEND
): MutableSharedFlow&lt;T&gt; {
    require(replay &gt;= 0) { &quot;replay cannot be negative, but was $replay&quot; }
    require(extraBufferCapacity &gt;= 0) { &quot;extraBufferCapacity cannot be negative, but was $extraBufferCapacity&quot; }
    require(replay &gt; 0 || extraBufferCapacity &gt; 0 || onBufferOverflow == BufferOverflow.SUSPEND) {
        &quot;replay or extraBufferCapacity must be positive with non-default onBufferOverflow strategy $onBufferOverflow&quot;
    }
    val bufferCapacity0 = replay + extraBufferCapacity
    val bufferCapacity = if (bufferCapacity0 &lt; 0) Int.MAX_VALUE else bufferCapacity0 // coerce to MAX_VALUE on overflow
    return SharedFlowImpl(replay, bufferCapacity, onBufferOverflow)
}</code></pre><p>보통 우리가 MutableSharedFlow 를 만들때, 이 함수를 통해서 만들게 된다. StateFlow는 어떻게 만들까? </p>
<pre><code>// StateFlow.kt
public fun &lt;T&gt; MutableStateFlow(value: T): MutableStateFlow&lt;T&gt; = StateFlowImpl(value ?: NULL)</code></pre><p>굉장히 간결하다. 근데 여기서 한가지 의문점이 생겼다.
StateFlow도 SharedFlow인데, 만드는 방식에서 왜 SharedFlow 를 만들때 필요한 프로퍼티였던 <code>replay</code>, <code>extrabufferCapacity</code>, <code>onBufferOverflow</code>가 왜 없어졌을까?
먼저 buffer 관련해서는 tryEmit 쪽에서 이유를 찾았다.
SharedFlowImpl에서는 emit 을 할 때 replay, bufferCapacity, BufferOverflow등을 다 확인하면서 그에 맞게 변경이 진행되고 있는데,
SharedFlowImpl에서는 그냥 <code>_state</code>의 value만 바꿔주면 되니, 굳이 SharedFlow에서 받아올 필요가 없기 때문에 사용하지 않았다고 생각하면 될 것 같다.</p>
<h2 id="결론">결론</h2>
<ul>
<li>StateFlow는 SharedFlow 의 상속 클래스이므로, 핫 흐름이다.</li>
<li>StateFlow는 SharedFlow에서 value 와 Equality Check 가 들어간 클래스이다.(물론 더 있을 수 있다. 있으면 말씀 부탁드려요..)</li>
<li>만들때 Default 값이 있어야 하고, Equality Check가 필요하고, value에 대한 접근이 필요할 때 StateFlow가 굉장히 좋은 수단이 될 수 있다.</li>
<li><del>~ 면접을 볼 때는 안정을 취하고, 아는 척 하지 말자.</del></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Architecture - Data Layer]]></title>
            <link>https://velog.io/@wyt_cpri/Architecture-Data-Layer</link>
            <guid>https://velog.io/@wyt_cpri/Architecture-Data-Layer</guid>
            <pubDate>Thu, 22 Sep 2022 04:43:52 GMT</pubDate>
            <description><![CDATA[<p>먼저 얘기를 나눌 것은 설계를 하는 과정에서 어떻게 보면 가장 중요한 역할을 지니고 있는 데이터 레이어를 보려고 한다.</p>
<h2 id="what-is-data-layer">What is Data Layer?</h2>
<p>데이터 레이어란, 애플리케이션의 데이터를 가지고 있거나, 비즈니스 로직을 처리하는 부분들을 담당하는 레이어로 이루어져 있다. </p>
<blockquote>
<p><strong>여기서 비즈니스 로직이란</strong> ?? 애플리케이션의 데이터들이 생성되고, 저장되는 로직들 중 변경되지 않을 부분들을 결정하는 것이다.</p>
</blockquote>
<h2 id="data-layer-구성-요소">Data Layer 구성 요소</h2>
<p>Repository : 0개, 1개, 혹은 그 이상의 데이터 소스들과 결합하여 상호작용하는 클래스
애플리케이션의 모든 레이어에서 데이터 레이어와 연결시켜주는 역할을 진행한다.
데이터를 보여주고, 데이터의 변화들을 한곳으로 모아주는 작업을 하며, 여러개의 Data Source 에서 발생되는 충돌을 해결하고, 그 충돌을 해결하면서 중요한 비즈니스 로직들은 지속시킨다.
Data Source : 이름과 같이 네트워크, 로컬 데이터베이스, 혹은 메모리에서 직접적으로 데이터를 사용하는 클래스
Data Source 에서는, 클래스 하나당 단 하나의 데이터와만 일을 진행해야 한다. ex. ( RemoteArticleDataSource, LocalUsersDataSource .. etc )
Repository 작성 방법</p>
<pre><code>class MovleRepsitory(...) { }

class PaymentsRepository(...) { }</code></pre><p>이렇게 하나의 아이템 별로 하나의 리포지토리를 생성하여, 리포지토리가 하나의 아이템에 대해서만 관장할 수 있게끔 진행한다. </p>
<p>리포지토리들은 여려개의 다른 DataSource 들을 합칠 수 있고, 그 합치는 것에 대한 충돌 자체도 이 리포지토리에서 해결을 진행해야 한다.</p>
<p>만약 로컬 DB 와 서버에서 내려오는 값들과의 충돌이 있다고 가정해보자. 그렇게 되면, 리포지토리에서 그 두개의 충돌을 막는것을 지원해주면 된다.</p>
<p>애플리케이션의 모든 레이어에서는 직접적으로 Data Source 와 연결될 수 없다. → 그 뜻은 DataSource 와 연결하려면 무조건 리포지토리를 거쳐야만 가능하다는 것이다.</p>
<p>리포지토리의 가장 보편적인 패턴은, One-shot call 로, CRUD 와 같은 데이터와 연결되는 것을 단 한번만 부르는 패턴을 말한다.</p>
<blockquote>
<p>CRUD: Create, Read, Update, Delete 의 약자로, 컴퓨터의 소프트웨어가 가지는 기본인 데이터 처리 과정을 일컫는 말이다.</p>
</blockquote>
<h2 id="source-of-truth">Source Of Truth</h2>
<p>하나의 리포지토리에서 여러개의 데이터 소스를 관리하는 것은 약간 까다로울 수 있다. 그것을 방지하기 위하여 리포지토리를 사용하게 되면, 다른 레이어에서 필요한 것이 무엇인지 알 수 있고, 일관된 상태를 제공할 수 있게 된다.</p>
<pre><code>
// LocalDataSource
LocalNewsDataSource(news: Dao) {
    suspend fun fetch(): List&lt;Article&gt; { ... }
    suspend fun update(article: List&lt;Article&gt;) { ... }
}

// RemoteDataSource
RemoteNewsDataSource(api: API) {
    suspend fun fetch(): List&lt;Article&gt; { ... }
}</code></pre><p>예를 들어, 위와 같이 두개의 DataSource 가 있고, 로컬에서는 Room DB 를 이용하여, Fetch 와 Update 를 진행하고 있고, Remote 에서는 ApiClient 를 이용하여 Fetch 만 진행을 하고 있다.</p>
<p>// Repository</p>
<pre><code>class NewsRepository(
    val localNewsDataSource: LocalNewsDataSource,
    val remoteNewsDataSource: RemoteNewsDataSource
) {
    suspend fun fetchNews() : List&lt;Article&gt; {
        try {
            val news = remoteNewsDataSource.fetchNews()
            localNewsDataSource.updateNews(news)
        } catch (exception: RemoteDataSourceNotAvailableException) {
            Log.d(&quot;NewsRepository&quot;, &quot;Connection failed, using local data source&quot;)
        }
        return localNewsDataSource.fetchNews()
    }
}
</code></pre><blockquote>
<p>참조 : <a href="https://www.youtube.com/watch?v=r5AseKQh2ZE">https://www.youtube.com/watch?v=r5AseKQh2ZE</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Kotlin-DSL로 build.gradle 변경하기]]></title>
            <link>https://velog.io/@wyt_cpri/Kotlin-DSL%EB%A1%9C-build.gradle-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@wyt_cpri/Kotlin-DSL%EB%A1%9C-build.gradle-%EB%B3%80%EA%B2%BD%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 22 Sep 2022 04:27:14 GMT</pubDate>
            <description><![CDATA[<h2 id="dsl-이란">DSL 이란?</h2>
<p>DSL 이란 도메인 특화 언어의 약어로, 특정한 도메인에서만 사용 가능한 언어를 이야기 한다. 이는 자바와 같은 범용 언어(GPL)가 여러 도메인에 광범위하게 적용되거나 사용되는 것과는 대조적이다.</p>
<p>DSL 은 선언형 코드를 작성하는데 도움을 주어, 보일러플레이트 코드를 줄이는데 도움을 준다. 그래서 DSL 로 코드를 작성하게 되면 읽기가 쉬워진다.</p>
<h3 id="dsl-예제">DSL 예제</h3>
<p>Web Development 를 위한 HTML
build tools 작성을 위한 Gradle
데이터 관리를 위한 SQL
마크업 관련 언어 관리를 위한 XML
등이 있다.</p>
<h2 id="gradle">Gradle</h2>
<p>Gradle 은 굉장히 강한 빌드용 도구이다. Gradle 은 빌드 Script 를 설명하기 위해 DSL을 제공한다. ( Groovy 와 Kotlin DSL ) .</p>
<p>여기서 만약 Kotlin 을 사용하여 개발하는 사람이라면, Groovy 를 사용하는 것보다 Kotlin DSL 을 사용하는게 더 쉽고 유연하게 빌드 스크립트를 작성할 수 있을 것이다.</p>
<h2 id="kotlin-dsl">Kotlin DSL</h2>
<p>Kotlin DSL 은 Kotlin 언어를 사용하도록 설정되어 있다. 그래서 문법같은 경우도 Kotlin 을 개발할 때 사용하는것과 동일하게 사용할 수 있다. 또한 Android Studio 와 전체적으로 호환된다.</p>
<p>만약 Groovy 대신 Kotlin DSL을 사용하게 된다면, 다음과 같은 장점들이 있다.</p>
<h4 id="읽기-편하다">읽기 편하다</h4>
<p>Kotlin 문법과 비슷해서 쉽게 적응할 수 있다.&#39;</p>
<h4 id="자동완성과-코드-추천이-된다">자동완성과 코드 추천이 된다</h4>
<p>Compile-time time error
Dependency, Artifact configuration, sourceSets 등등의 접근자들의 Type-Safe 모델을 제공한다.
그러나, 코드 클린, buildSrc Directory related Change 같은 경우는 Groovy 보다는 느릴 수 있다.</p>
<h2 id="groovy-vs-kotlin-dsl">Groovy vs Kotlin DSL</h2>
<h3 id="coding-parameter">Coding Parameter</h3>
<p>Kotlin 과 Groovy 중 Coding Parameter 관련 퍼포먼스로 선택을 해야 한다면, 둘다 우열을 가릴 수 없을 정도로 좋은 Coding Parameter 를 가지고 있다.</p>
<p>Kotlin = Groovy</p>
<h3 id="salient-features">Salient Features</h3>
<p>Kotlin 과 Groovy 모두 안드로이드 애플리케이션을 제작하는데 많이 사용되고 있다. Kotlin 과 Groovy 모두 JVM 을 지원하고 있고, JVM 은 안드로이드 생태계에서 가장 많은 기능들을 제공한다.</p>
<p>Java 에서 NPE 관련해서 지원이 가능하다는 것은, Kotlin 쪽에서 점수를 가져갈 수 있다. 그러나, Groovy 는 생산성을 높이는 광범위한 프레임워크를 지원하게 된다.</p>
<p>멀티메소드나, 메타프로그래밍을 통해 강력한 시스템을 활용할 수 있다. 메타프로그래밍 요소는 Kotlin 대 Groovy 요소에 영항을 끼치므로, 특정 도메인의 컨텍스트에서 서로 다른 코드를 사용할 수 있게 된다.</p>
<p>NPE → Kotlin</p>
<p>Framework → Groovy</p>
<h3 id="learning-curve">Learning Curve</h3>
<p>Kotlin 과 Groovy 모두 굉장히 낮은 러닝커브를 가지고 있다. Kotlin 이 16년도에 소개되었을 때, 표준 Java 컴파일러의 대안으로 명칭되었지만, 현재는 Google 에서 지정한 Official Language 가 되었다.</p>
<p>짧게 얘기하자면, 자바를 사용해본적이 있다면 Kotlin 를 사용해도, Groovy 를 사용해도 아무런 문제가 되지 않는다.</p>
<p>Kotlin = Groovy</p>
<h3 id="ecosystem">Ecosystem</h3>
<p>Software Ecosystem 은 소프트웨어 프로젝트를 실행할 수 있게 만들고, 언어, 구문, 스크립팅 및 오픈소스 커뮤니티를 포함하는 생산에서 동기화하는 모든 것을 나타낸다.</p>
<p>Kotlin 이라는 언어가 가지고 있는 라이브러리와, 개발 로직들은 개발자들에게 큰 영향을 남깁니다. 그러나, Groovy는 데이터 클래스와, 정적 코드 소모를 갖추고 있어, 정말 좋은 동적 언어가 될 수 있다.</p>
<p>Groovy 는 비동기 코드, 동시성, 병렬성을 특징으로 가지고 있지만, 코틀린은 라이브러리와 테스트 프레임워크를 통해 풍부핱 Ecosystem 을 제공할 수 있다.</p>
<p>코드 기능 : <strong>Groovy</strong></p>
<p>코드의 범용성 : <strong>Kotlin</strong></p>
<h3 id="performance-time">Performance Time</h3>
<p>Kotlin 과 Groovy 모두 Java 기반 코드이다. 그러나, Kotlin 쪽으로 제공하는 코드 설정은 자바에 비해 많이 제한적일 수밖에 없다. 반대로, 두 프로그래밍의 기술적인 반응은 굉장히 시의적절하다.</p>
<p>Groovy 는 Java 와 같은 문법을 제공하지만, Kotlin 의 코드 수는 훨씬 줄어들게 된다. Kotlin을 선택하는 이유이다 ( 빠르고, 호환성 좋고, 현대적이고, 안전하다 ).</p>
<p>문제는 Kotlin 의 성능은 Java 와 비슷하지만, groovy 는 Kotlin 뿐만 아니라 Java보다도 다소 느릴 수 있다.</p>
<p><strong>Kotlin &gt; Groovy</strong></p>
<p>그래서 다음 세션에서는 Groovy 로 되어 있던 Build.gradle 을 Kotlin 으로 바꾸는 방법을 말해보려고 한다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[consumer-rule.pro VS proguard-rule.pro]]></title>
            <link>https://velog.io/@wyt_cpri/Consumer-rule-VS-Proguard-Rule</link>
            <guid>https://velog.io/@wyt_cpri/Consumer-rule-VS-Proguard-Rule</guid>
            <pubDate>Thu, 22 Sep 2022 03:58:09 GMT</pubDate>
            <description><![CDATA[<p>빌드 스크립트를 보는데 갑자기 문득 이러한 궁금증이 생겼다. 왜 처음 모듈을 만들게 되면, consumer-rules.pro 파일과 proguard-rules.pro 파일이 왜 생기는가?</p>
<p>과연 이 두개는 어디서 쓰이고, 어떻게 쓰이는가? 그래서 한번 찾아보기로 했다.</p>
<p>이 <a href="https://stackoverflow.com/questions/60861929/what-is-the-difference-between-consumer-rules-pro-and-proguard-rules-pro-in-andr">링크</a>를 보면 Consumer-rules.pro 파일과 proguard-rules.pro 파일들이 언제 어디서 쓰이는지를 알 수 있을 것 같다.</p>
<p>여기서 제공하는 질문들을 일단 먼저 찾아보자</p>
<p>Will all the modules code be obfuscated by the rules of the main modules pro-guard rules even if the module does not specify any rules?
What is the difference between consumer-rules.pro and proguard-rules.pro in Android?
Should I enable minifyEnabled in my module?
I notices that I can add proguard rules for my module in the main module, so does that mean proguard-rules in the module are overriden in the main module?
1번 질문부터 살펴보자.</p>
<h3 id="1모듈이-규칙들을-명시하지-않았더라도-모든-모듈-코드는-메인-모듈-프로가드의-규칙에-의해-난독화가-진행되나요">1.모듈이 규칙들을 명시하지 않았더라도, 모든 모듈 코드는 메인 모듈 프로가드의 규칙에 의해 난독화가 진행되나요?</h3>
<p>답은 이렇다.</p>
<p><strong>난독화는 그렇게 진행되지 않는다.</strong> App 모듈에서 Property Minify 를 활성화하게 되면, 앱 모듈에서 사용가능한 코드들 뿐만 아니라, 서드파티 로 Dependency 가 걸려있는 라이브러리들도 난독화를 진행하려고 하며, 다른 라이브러리 모듈 역시 서드파티로 간주하게 된다. 그러나 서드파티가 종속하고 있는 라이브러리에 대해서는 건드리지 않는다.</p>
<h3 id="2-그러면-consumer-rulespro-와-proguard-rulespro-의-차이점은-무엇인가요">2. 그러면 consumer-rules.pro 와 proguard-rules.pro 의 차이점은 무엇인가요?</h3>
<p>답은 다음과 같다.</p>
<p>proguard-rules.pro 는 모듈과 그 모듈의 종속되어 있는 라이브러리의 proguard 와 연관되어 있는 규칙을 선언하는 파일이다.</p>
<p>잠깐! 그러면 proguard 는 무엇이냐?? → 코드를 난독화해주고, 최적화를 해주는 오픈소스 툴이다.</p>
<p>그말은 프로가드라는 오픈소스를 사용할 수 있게 해주는 규칙들을 선언해주는 파일이 proguard-rules.pro 라는 것이다.</p>
<p>consumer-rules.pro 는 고객 ( 혹은 소비자 ) 가 모듈에 적용할 수 있는 규칙을 선언하는 파일이다. </p>
<blockquote>
<p>여기서 말하는 고객이란 → 이 모듈을 사용하는 곳, 혹은 종속성 자체로 선언한 라이브러리이며, 보통 라이브러리 선언자들이 많이 사용하게 된다 )</p>
</blockquote>
<h3 id="3-모듈에서-minifyenabled-를-설정해도-되나요">3. 모듈에서 minifyEnabled 를 설정해도 되나요?</h3>
<p><strong>추천한다.</strong> 그러나 모든 아이템들이 설정이 잘 되어있는지 확인해봐야 할 것이다. ( classes.dex 파일에 압축되어있는 코드가 있을것 )</p>
<p>그래서 생각하건데, 프로젝트를 생성할 때에는 내가 library를 만들어서 사용할 것이냐, 혹은 Application Module 만 사용할 것이냐에 따라서 이 두개의 사용성을 정의해보면 좋을 것 같다. ( 애플리케이션만 있으면 굳이 consumer-rules.pro 파일은 필요 없어보인다.) </p>
<blockquote>
<p>참조 : <a href="https://stackoverflow.com/questions/60861929/what-is-the-difference-between-consumer-rules-pro-and-proguard-rules-pro-in-andr">https://stackoverflow.com/questions/60861929/what-is-the-difference-between-consumer-rules-pro-and-proguard-rules-pro-in-andr</a></p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>