<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코딩스토리</title>
    <link>https://lakue.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 5 Apr 2026 18:47:23 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>라크라꾸</managingEditor>
    <image>
      <title>코딩스토리</title>
      <url>https://tistory1.daumcdn.net/tistory/3076769/attach/ab06bff01ec44d95a5bcb05935270f25</url>
      <link>https://lakue.tistory.com</link>
    </image>
    <item>
      <title>[Android/안드로이드] 애드몹과 안드로이드 연동하기- 안드로이드 코드 연결하기 (2/2)</title>
      <link>https://lakue.tistory.com/87</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드.jpeg&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;293&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k1xb5/btsl0UrrL2y/TwVKfEdvHzE0PRffblqd10/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k1xb5/btsl0UrrL2y/TwVKfEdvHzE0PRffblqd10/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k1xb5/btsl0UrrL2y/TwVKfEdvHzE0PRffblqd10/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk1xb5%2Fbtsl0UrrL2y%2FTwVKfEdvHzE0PRffblqd10%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;401&quot; height=&quot;293&quot; data-filename=&quot;다운로드.jpeg&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;293&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 포스팅에서는 애드몹 세팅하는 방법에 대해서 포스팅을 해, 애드몹ID와 광고ID를 가져올 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가져온 ID를 가지고 안드로이드 앱에 적용하는 방법에 대해 알아보겠습니다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Step 1: 안드로이드 스튜디오에서 앱을 설정&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 프로젝트의 build.gradle(Module:app) 파일을 열고 dependencies에 Google Mobile Ads SDK를 추가합니다. 아래는 예시입니다:&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688145865870&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dependencies {
    implementation 'com.google.android.gms:play-services-ads:20.0.0'
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;버전 정보는 Google Mobile Ads SDK의 &lt;a href=&quot;https://developers.google.com/admob/android/rel-notes&quot;&gt;&lt;span&gt;릴리즈 노트&lt;/span&gt;&lt;/a&gt;에서 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;b&gt;2. 이제 AndroidManifest.xml에 광고 앱 ID를 추가해야 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688145934441&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;application&amp;gt;
    &amp;lt;!-- Sample AdMob App ID: ca-app-pub-3940256099942544~3347511713 --&amp;gt;
    &amp;lt;meta-data
        android:name=&quot;com.google.android.gms.ads.APPLICATION_ID&quot;
        android:value=&quot;ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy&quot;/&amp;gt;
    ...
&amp;lt;/application&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;여기서 android:value는 AdMob에서 받은 앱 ID로 대체해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Step 2: 광고를 앱에 연동하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로는 실제로 광고를 앱에 연동하는 작업을 진행해보겠습니다. 여기에서는 배너 광고를 예로 들어 설명하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;b&gt;1. 먼저 광고를 표시하려는 Activity의 레이아웃 XML 파일에 AdView를 추가합니다. 예를 들어, activity_main.xml 파일을 수정하면 다음과 같을 것입니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688146031245&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;com.google.android.gms.ads.AdView
    xmlns:ads=&quot;http://schemas.android.com/apk/res-auto&quot;
    android:id=&quot;@+id/adView&quot;
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_centerHorizontal=&quot;true&quot;
    android:layout_alignParentBottom=&quot;true&quot;
    ads:adSize=&quot;BANNER&quot;
    ads:adUnitId=&quot;ca-app-pub-xxxxxxxxxxxxxxxx/yyyyyyyyyy&quot;&amp;gt;
&amp;lt;/com.google.android.gms.ads.AdView&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;여기서 ads:adUnitId는 AdMob에서 생성한 광고 단위 ID로 대체해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;b&gt;2. 다음으로 Activity 파일에서 AdView를 초기화하고 광고를 로드해야 합니다. 예를 들어, MainActivity.java를 다음과 같이 수정하면 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688146065134&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.MobileAds;

public class MainActivity extends AppCompatActivity {
    private AdView mAdView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MobileAds.initialize(this);

        mAdView = findViewById(R.id.adView);
        AdRequest adRequest = new AdRequest.Builder().build();
        mAdView.loadAd(adRequest);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 앱을 실행시키면, 설정한 위치에 광고가 표시되는 것을 확인할 수 있을 것입니다. 다만, 실제 기기에서 테스트를 하는 경우에는 실제 광고가 노출되기 때문에 테스트 광고 단위를 사용하는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Step 3: 배포 전 최종 확인&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱을 배포하기 전에는 다음과 같은 사항을 다시 한 번 확인하는 것이 중요합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;테스트 광고 단위를 사용하였다면, 실제 광고 단위 ID로 변경하였는지 확인하세요.&lt;/li&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;광고의 위치, 크기, 형태 등이 사용자 경험을 방해하지 않는지 확인하세요.&lt;/li&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;앱의 동작에 광고가 영향을 미치지 않는지 (예: 메모리 누수, 프레임 드랍 등) 확인하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Step 4: 앱 배포&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 설정이 완료되었다면, 이제 앱을 Google Play 스토어에 배포하실 수 있습니다. 앱이 사용자들에게 배포되고 광고가 정상적으로 노출되면, 이제부터 광고 수익이 발생하기 시작합니다.&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;Google AdMob은 모바일 앱에서 광고 수익을 창출하는 효과적인 방법 중 하나입니다. 이 포스트를 통해 Android 앱에 AdMob을 연동하는 방법을 알아보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱&lt;span&gt; &lt;/span&gt;개발에&lt;span&gt; &lt;/span&gt;성공하시길&lt;span&gt; &lt;/span&gt;바라며&lt;span&gt;, &lt;/span&gt;애드몹을&lt;span&gt; &lt;/span&gt;통해&lt;span&gt; &lt;/span&gt;원하는&lt;span&gt; &lt;/span&gt;수익을&lt;span&gt; &lt;/span&gt;얻으시길&lt;span&gt; &lt;/span&gt;바랍니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Android/유용한 기술</category>
      <category>Android AdMob</category>
      <category>Android 애드몹</category>
      <category>광고배너</category>
      <category>광고설정</category>
      <category>안드로이드 Admob</category>
      <category>안드로이드 애드몹</category>
      <category>안드로이드광고</category>
      <category>애드몹</category>
      <category>애드몹광고</category>
      <category>애드몹배너</category>
      <author>라크라꾸</author>
      <guid isPermaLink="true">https://lakue.tistory.com/87</guid>
      <comments>https://lakue.tistory.com/87#entry87comment</comments>
      <pubDate>Sun, 2 Jul 2023 13:42:41 +0900</pubDate>
    </item>
    <item>
      <title>[Android/안드로이드] 애드몹과 안드로이드 연동하기- 애드몹 세팅하기 (1/2)</title>
      <link>https://lakue.tistory.com/86</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Google AdMob은 모바일 앱의 광고 수익을 극대화하는 데 도움이 되는 무료 도구입니다. 이 포스트에서는 Android 앱에 AdMob을 연동하는 방법을 단계별로 설명해보겠습니다.&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://apps.admob.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://apps.admob.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1688142935032&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;AdMob&quot; data-og-description=&quot;이메일 또는 휴대전화&quot; data-og-host=&quot;accounts.google.com&quot; data-og-source-url=&quot;https://apps.admob.com/&quot; data-og-url=&quot;https://accounts.google.com/v3/signin/identifier?dsh=S2013818609%3A1688142933732651&amp;amp;continue=https%3A%2F%2Fapps.admob.com%2Fv2%2Fhome&amp;amp;followup=https%3A%2F%2Fapps.admob.com%2Fv2%2Fhome&amp;amp;ifkv=AeDOFXhjPFL1z76q04eaSoHGjQX2iMveIeLnQjxPoISiL2O6eSEusvWPH98ze84zMfBpHchT819KQw&amp;amp;osid=1&amp;amp;passive=1209600&amp;amp;service=admob&amp;amp;flowName=WebLiteSignIn&amp;amp;flowEntry=ServiceLogin&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://apps.admob.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://apps.admob.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;AdMob&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이메일 또는 휴대전화&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;accounts.google.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Step 1: Google AdMob 계정 만들기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 AdMob 계정이 없다면, 다음과 같이 만들어 봅시다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;a href=&quot;https://apps.admob.com/&quot;&gt;&lt;span&gt;Google AdMob 사이트&lt;/span&gt;&lt;/a&gt;에 접속해서 '시작하기'를 클릭합니다.&lt;/li&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;Google 계정 정보를 입력한 후 로그인합니다.&lt;/li&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;AdMob의 이용약관을 확인하고 '수락'을 눌러 계정을 생성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Step 2: 애드몹에 앱 등록&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AdMob 대시보드에서 '앱 추가'를 선택합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.36.06.png&quot; data-origin-width=&quot;508&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wp6Um/btslZ2RgRUW/Vg9BdXtLA19GL6Lq0VuE5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wp6Um/btslZ2RgRUW/Vg9BdXtLA19GL6Lq0VuE5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wp6Um/btslZ2RgRUW/Vg9BdXtLA19GL6Lq0VuE5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwp6Um%2FbtslZ2RgRUW%2FVg9BdXtLA19GL6Lq0VuE5K%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;344&quot; height=&quot;284&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.36.06.png&quot; data-origin-width=&quot;508&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2023-07-01 오전 1.36.13.png&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;1158&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fx06H/btsl1WoInt3/iK26LaCI6UutMDGKHZ4IKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fx06H/btsl1WoInt3/iK26LaCI6UutMDGKHZ4IKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fx06H/btsl1WoInt3/iK26LaCI6UutMDGKHZ4IKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFx06H%2Fbtsl1WoInt3%2FiK26LaCI6UutMDGKHZ4IKk%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;358&quot; height=&quot;362&quot; data-filename=&quot;edited_스크린샷 2023-07-01 오전 1.36.13.png&quot; data-origin-width=&quot;1144&quot; data-origin-height=&quot;1158&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;앱이 Google Play 스토어에 존재하면 '예', 그렇지 않으면 '아니오'를 선택합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.40.51.png&quot; data-origin-width=&quot;1968&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kQusU/btsl1fvwA9x/z7O4uondZSkaIEMMme9KVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kQusU/btsl1fvwA9x/z7O4uondZSkaIEMMme9KVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kQusU/btsl1fvwA9x/z7O4uondZSkaIEMMme9KVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkQusU%2Fbtsl1fvwA9x%2Fz7O4uondZSkaIEMMme9KVK%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;546&quot; height=&quot;219&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.40.51.png&quot; data-origin-width=&quot;1968&quot; data-origin-height=&quot;790&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;앱 이름과 플랫폼(Android)을 입력하고 '추가'를 클릭합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.41.52.png&quot; data-origin-width=&quot;2016&quot; data-origin-height=&quot;818&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5KeVG/btslZGnqyFk/S1V4BOWE1bxbMJ1NVG0AW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5KeVG/btslZGnqyFk/S1V4BOWE1bxbMJ1NVG0AW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5KeVG/btslZGnqyFk/S1V4BOWE1bxbMJ1NVG0AW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5KeVG%2FbtslZGnqyFk%2FS1V4BOWE1bxbMJ1NVG0AW1%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;596&quot; height=&quot;242&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.41.52.png&quot; data-origin-width=&quot;2016&quot; data-origin-height=&quot;818&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;앱을&lt;span&gt; &lt;/span&gt;추가가 완료되면 앱 설정에서 앱 ID를 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2023-07-01 오전 1.43.04.png&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1113&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekGkg5/btsl1g82Gsj/AAlFfhsQAMkikobWD4Cab1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekGkg5/btsl1g82Gsj/AAlFfhsQAMkikobWD4Cab1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekGkg5/btsl1g82Gsj/AAlFfhsQAMkikobWD4Cab1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FekGkg5%2Fbtsl1g82Gsj%2FAAlFfhsQAMkikobWD4Cab1%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;574&quot; height=&quot;213&quot; data-filename=&quot;edited_스크린샷 2023-07-01 오전 1.43.04.png&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1113&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Step 3: 광고 단위 만들기&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;AdMob 대시보드에서 '광고 단위 만들기'를 선택합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.44.23.png&quot; data-origin-width=&quot;2698&quot; data-origin-height=&quot;976&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oRjjR/btsl2KhcUl7/Ua3d8wyy7hvbS7YwMIkFWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oRjjR/btsl2KhcUl7/Ua3d8wyy7hvbS7YwMIkFWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oRjjR/btsl2KhcUl7/Ua3d8wyy7hvbS7YwMIkFWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoRjjR%2Fbtsl2KhcUl7%2FUa3d8wyy7hvbS7YwMIkFWk%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;545&quot; height=&quot;197&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.44.23.png&quot; data-origin-width=&quot;2698&quot; data-origin-height=&quot;976&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;광고 형식을 선택하고 '선택'을 클릭합니다. (예: 배너, 보상형)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.44.39.png&quot; data-origin-width=&quot;2776&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NGew4/btsl4mGYRvm/tWuGrrkucyhJzri7e5taF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NGew4/btsl4mGYRvm/tWuGrrkucyhJzri7e5taF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NGew4/btsl4mGYRvm/tWuGrrkucyhJzri7e5taF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNGew4%2Fbtsl4mGYRvm%2FtWuGrrkucyhJzri7e5taF0%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;513&quot; height=&quot;284&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.44.39.png&quot; data-origin-width=&quot;2776&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;광고 단위 이름을 지정하고 '만들기'를 클릭합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.45.09.png&quot; data-origin-width=&quot;992&quot; data-origin-height=&quot;1212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HIGxw/btslZGubZ1g/XoWHYxNG1kpM1ie0BQkxx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HIGxw/btslZGubZ1g/XoWHYxNG1kpM1ie0BQkxx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HIGxw/btslZGubZ1g/XoWHYxNG1kpM1ie0BQkxx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHIGxw%2FbtslZGubZ1g%2FXoWHYxNG1kpM1ie0BQkxx0%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;506&quot; height=&quot;618&quot; data-filename=&quot;스크린샷 2023-07-01 오전 1.45.09.png&quot; data-origin-width=&quot;992&quot; data-origin-height=&quot;1212&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;광고 단위 ID가 생성됩니다. 이 ID는 광고를 로드할 때 사용하므로 복사해 둡니다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2023-07-01 오전 1.45.34.png&quot; data-origin-width=&quot;1482&quot; data-origin-height=&quot;1194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bU0wyK/btslZ60dqe3/JEe8mNwK6SkBpfz6zUmX0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bU0wyK/btslZ60dqe3/JEe8mNwK6SkBpfz6zUmX0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bU0wyK/btslZ60dqe3/JEe8mNwK6SkBpfz6zUmX0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbU0wyK%2FbtslZ60dqe3%2FJEe8mNwK6SkBpfz6zUmX0k%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;549&quot; height=&quot;442&quot; data-filename=&quot;edited_스크린샷 2023-07-01 오전 1.45.34.png&quot; data-origin-width=&quot;1482&quot; data-origin-height=&quot;1194&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Step 4: 테스트 광고 단위 사용하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 중인 앱에 실제 광고를 로드하는 것은 AdMob 정책 위반으로 간주될 수 있습니다. 따라서 개발 중이거나 테스트하는 동안에는 테스트 광고 단위를 사용해야 합니다. Google AdMob은 몇 가지 테스트 광고 단위 ID를 제공하고 있으며, 이들은 아래와 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배너 광고: ca-app-pub-3940256099942544/6300978111&lt;/li&gt;
&lt;li&gt;전면 광고: ca-app-pub-3940256099942544/1033173712&lt;/li&gt;
&lt;li&gt;보상형 광고: ca-app-pub-3940256099942544/5224354917&lt;/li&gt;
&lt;li&gt;네이티브 광고: ca-app-pub-3940256099942544/2247696110&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트를&lt;span&gt; &lt;/span&gt;위한&lt;span&gt; &lt;/span&gt;이러한&lt;span&gt; &lt;/span&gt;광고&lt;span&gt; &lt;/span&gt;단위&lt;span&gt; ID&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;사용하여&lt;span&gt; &lt;/span&gt;앱을&lt;span&gt; &lt;/span&gt;테스트하면&lt;span&gt;, &lt;/span&gt;실제&lt;span&gt; &lt;/span&gt;광고가&lt;span&gt; &lt;/span&gt;표시되는&lt;span&gt; &lt;/span&gt;대신&lt;span&gt; &lt;/span&gt;테스트&lt;span&gt; &lt;/span&gt;광고가&lt;span&gt; &lt;/span&gt;표시됩니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Android/유용한 기술</category>
      <category>AdMob</category>
      <category>Android AdMob</category>
      <category>Android 애드몹</category>
      <category>안드로이드광고</category>
      <category>안드로이드배너광고</category>
      <category>안드로이드애드몹</category>
      <category>애드몹</category>
      <category>애드몹광고</category>
      <category>애드몹배너</category>
      <category>애드몹배너광고</category>
      <author>라크라꾸</author>
      <guid isPermaLink="true">https://lakue.tistory.com/86</guid>
      <comments>https://lakue.tistory.com/86#entry86comment</comments>
      <pubDate>Sat, 1 Jul 2023 02:20:29 +0900</pubDate>
    </item>
    <item>
      <title>[Android/안드로이드] 안드로이드 컴포즈 기본 구성요소</title>
      <link>https://lakue.tistory.com/85</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요, 여러분! 이번 포스트에서는 안드로이드의 선언형 UI 툴킷인 Jetpack Compose의 기본적인 구성요소에 대해 알아보겠습니다. 이를 통해 Compose를 이용한 UI 작성에 대한 기본적인 이해를 높일 수 있습니다.&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;Jetpack Compose는 선언형 UI를 구성하기 위한 다양한 구성요소를 제공합니다. 이들 구성요소는 각각 특정 UI 요소를 표현하며, 이들을 조합하여 복잡한 UI를 만들 수 있습니다. 가장 기본적인 구성요소로는 Text, Button, Image 등이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저&lt;span&gt;, Text &lt;/span&gt;구성요소는&lt;span&gt; &lt;/span&gt;화면에&lt;span&gt; &lt;/span&gt;텍스트를&lt;span&gt; &lt;/span&gt;표시하는데&lt;span&gt; &lt;/span&gt;사용됩니다&lt;span&gt;. &lt;/span&gt;이는&lt;span&gt; &lt;/span&gt;다음과&lt;span&gt; &lt;/span&gt;같이&lt;span&gt; &lt;/span&gt;사용할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다.&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1687540097060&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Composable
fun SimpleText() {
    Text(&quot;Hello, World!&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드는 &quot;Hello, World!&quot;라는 텍스트를 화면에 표시합니다. Text 함수는 @Composable 함수로, Compose에서 제공하는 UI 구성요소를 선언하는 데 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로&lt;span&gt;, Button &lt;/span&gt;구성요소는&lt;span&gt; &lt;/span&gt;사용자가&lt;span&gt; &lt;/span&gt;클릭할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있는&lt;span&gt; &lt;/span&gt;버튼을&lt;span&gt; &lt;/span&gt;화면에&lt;span&gt; &lt;/span&gt;표시하는데&lt;span&gt; &lt;/span&gt;사용됩니다&lt;span&gt;. &lt;/span&gt;이는&lt;span&gt; &lt;/span&gt;다음과&lt;span&gt; &lt;/span&gt;같이&lt;span&gt; &lt;/span&gt;사용할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1687540133394&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Composable
fun SimpleButton() {
    Button(onClick = { /* handle click */ }) {
        Text(&quot;Click Me&quot;)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드는 &quot;Click Me&quot;라는 텍스트가 쓰여진 버튼을 화면에 표시합니다. Button 함수는 클릭 이벤트를 처리하기 위한 onClick 콜백을 받습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로&lt;span&gt;, Image &lt;/span&gt;구성요소는&lt;span&gt; &lt;/span&gt;이미지를&lt;span&gt; &lt;/span&gt;화면에&lt;span&gt; &lt;/span&gt;표시하는데&lt;span&gt; &lt;/span&gt;사용됩니다&lt;span&gt;. &lt;/span&gt;이는&lt;span&gt; &lt;/span&gt;다음과&lt;span&gt; &lt;/span&gt;같이&lt;span&gt; &lt;/span&gt;사용할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1687540173410&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Composable
fun SimpleImage() {
    Image(painter = painterResource(id = R.drawable.my_image), contentDescription = &quot;My Image&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이외에도, Jetpack Compose는 Row, Column, Box, Surface 등과 같은 레이아웃 구성요소를 제공하여, 여러 UI 구성요소를 조직하고 배치하는 데 도움을 줍니다. 이런 레이아웃 구성요소들은 화면에 UI 요소들을 어떻게 배치할지 결정하는 역할을 합니다. 예를 들어, Row와 Column은 각각 가로 방향과 세로 방향으로 UI 요소들을 배치합니다.&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;또한, Jetpack Compose는 State와 같은 상태 관리 도구를 제공하여, UI의 상태를 관리하고 업데이트하는 데 도움을 줍니다. State는 UI의 특정 상태를 저장하고, 이 상태가 변경될 때 UI를 자동으로 업데이트합니다. 이를 통해 UI가 동적인 데이터에 반응하도록 만들 수 있습니다.&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;예를 들어, 사용자의 입력을 받아서 화면에 표시하는 텍스트 필드의 경우, 이 텍스트 필드의 현재 값은 State에 저장될 수 있습니다. 사용자가 텍스트 필드에 새로운 값을 입력하면, 이 State는 새로운 값으로 업데이트되고, 이에 따라 화면에 표시되는 텍스트도 자동으로 업데이트됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은&lt;span&gt; State&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;사용하여&lt;span&gt; &lt;/span&gt;텍스트&lt;span&gt; &lt;/span&gt;필드의&lt;span&gt; &lt;/span&gt;값을&lt;span&gt; &lt;/span&gt;관리하는&lt;span&gt; &lt;/span&gt;예제입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1687540357963&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Composable
fun TextFieldWithState() {
    var text by remember { mutableStateOf(&quot;&quot;) }

    TextField(
        value = text,
        onValueChange = { newText -&amp;gt; text = newText },
        label = { Text(&quot;Enter text&quot;) }
    )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드에서 remember { mutableStateOf(&quot;&quot;) }는 State를 생성하고 초기화하는 코드입니다. TextField의 value는 이 State의 현재 값을 가져오고, onValueChange는 사용자의 입력에 따라 State를 업데이트합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이상으로&lt;span&gt; '&lt;/span&gt;안드로이드&lt;span&gt; &lt;/span&gt;컴포즈&lt;span&gt; &lt;/span&gt;기본&lt;span&gt; &lt;/span&gt;구성요소&lt;span&gt;'&lt;/span&gt;에&lt;span&gt; &lt;/span&gt;대한&lt;span&gt; &lt;/span&gt;글을&lt;span&gt; &lt;/span&gt;마치겠습니다&lt;span&gt;. &lt;/span&gt;이&lt;span&gt; &lt;/span&gt;글을&lt;span&gt; &lt;/span&gt;통해&lt;span&gt; Compose&lt;/span&gt;의&lt;span&gt; &lt;/span&gt;기본&lt;span&gt; &lt;/span&gt;구성요소에&lt;span&gt; &lt;/span&gt;대한&lt;span&gt; &lt;/span&gt;이해를&lt;span&gt; &lt;/span&gt;높이는&lt;span&gt; &lt;/span&gt;데&lt;span&gt; &lt;/span&gt;도움이&lt;span&gt; &lt;/span&gt;되었기를&lt;span&gt; &lt;/span&gt;바랍니다&lt;span&gt;. &lt;/span&gt;앞으로도&lt;span&gt; &lt;/span&gt;여러분의&lt;span&gt; &lt;/span&gt;안드로이드&lt;span&gt; &lt;/span&gt;개발&lt;span&gt; &lt;/span&gt;여행에&lt;span&gt; &lt;/span&gt;도움이&lt;span&gt; &lt;/span&gt;될&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있는&lt;span&gt; &lt;/span&gt;유용한&lt;span&gt; &lt;/span&gt;정보와&lt;span&gt; &lt;/span&gt;팁을&lt;span&gt; &lt;/span&gt;계속&lt;span&gt; &lt;/span&gt;제공하겠습니다&lt;span&gt;. &lt;/span&gt;다음&lt;span&gt; &lt;/span&gt;번에&lt;span&gt; &lt;/span&gt;뵙겠습니다&lt;span&gt;!&lt;/span&gt;&lt;/p&gt;</description>
      <category>Android/유용한 기술</category>
      <category>AndroidCompose</category>
      <category>Android컴포즈</category>
      <category>JetpackCompose</category>
      <category>UI구성요소</category>
      <category>선언형UI</category>
      <category>안드로이드개발</category>
      <category>안드로이드컴포즈</category>
      <category>젯팩컴포즈</category>
      <category>컴포즈개발</category>
      <category>컴포즈구성요소</category>
      <author>라크라꾸</author>
      <guid isPermaLink="true">https://lakue.tistory.com/85</guid>
      <comments>https://lakue.tistory.com/85#entry85comment</comments>
      <pubDate>Sat, 24 Jun 2023 02:17:35 +0900</pubDate>
    </item>
    <item>
      <title>[Android/안드로이드] 안드로이드 컴포즈 소개</title>
      <link>https://lakue.tistory.com/84</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;안녕하세요, 여러분! 오늘은 앱 개발의 새로운 패러다임인 안드로이드의 &quot;Jetpack Compose&quot;에 대해 알아보겠습니다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.android.com/jetpack/compose/documentation?hl=ko&quot;&gt;https://developer.android.com/jetpack/compose/documentation?hl=ko&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1686157917880&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Jetpack Compose 시작하기 &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;Jetpack Compose 시작하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Jetpack Compose는 네이티브 Android UI를 빌드하기 위한 최신 도구 키트입니다. 여기에서 Compo&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/jetpack/compose/documentation?hl=ko&quot; data-og-url=&quot;https://developer.android.com/jetpack/compose/documentation?hl=ko&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://developer.android.com/jetpack/compose/documentation?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/jetpack/compose/documentation?hl=ko&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Jetpack Compose 시작하기 &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Jetpack Compose 시작하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Jetpack Compose는 네이티브 Android UI를 빌드하기 위한 최신 도구 키트입니다. 여기에서 Compo&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Jetpack Compose&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;안드로이드의&lt;span&gt; &lt;/span&gt;모던&lt;span&gt; UI &lt;/span&gt;툴킷으로&lt;span&gt;, &lt;/span&gt;선언형&lt;span&gt; UI&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;구현할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있게&lt;span&gt; &lt;/span&gt;해주는&lt;span&gt; &lt;/span&gt;라이브러리입니다&lt;span&gt;. &lt;/span&gt;기존에는&lt;span&gt; XML&lt;/span&gt;을&lt;span&gt; &lt;/span&gt;통해&lt;span&gt; UI&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;작성하였지만&lt;span&gt;, Compose&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;이를&lt;span&gt; &lt;/span&gt;대체할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;. &lt;/span&gt;그럼&lt;span&gt; XML&lt;/span&gt;과&lt;span&gt; Compose&lt;/span&gt;의&lt;span&gt; &lt;/span&gt;차이점에&lt;span&gt; &lt;/span&gt;대해&lt;span&gt; &lt;/span&gt;살펴보겠습니다&lt;span&gt;.&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1686157565430&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// XML 기반 UI 구성 예제
&amp;lt;TextView
    android:layout_width=&quot;wrap_content&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:text=&quot;Hello, XML!&quot; /&amp;gt;

// Jetpack Compose 기반 UI 구성 예제
@Composable
fun Greeting() {
    Text(&quot;Hello, Compose!&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;상기된 예제에서 볼 수 있듯이, Compose는 UI를 코틀린으로 직접 작성합니다. 이는 UI와 데이터를 보다 직접적으로 연결하며, 더욱 반응형의 UI를 쉽게 만들 수 있게 해줍니다. 그렇다면, 왜 이러한 변화가 필요했을까요?&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;XML은 구조적인 언어로서 UI를 묘사하는데 충분하지만, UI가 복잡해질수록 그에 따른 코드도 복잡해지는 문제가 있었습니다. 그리고 그로 인해 발생하는 중복 코드, 유지보수의 어려움 등의 문제점이 있었습니다. 반면, Compose는 이러한 문제점을 해결해주며, 보다 효율적인 UI 개발을 가능하게 합니다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Compose의 장점&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 선언형 UI&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;선언형 프로그래밍은 UI의 상태를 선언하고, 상태가 변경될 때 UI를 자동으로 업데이트하는 방식입니다. 이를 통해 UI와 데이터를 동기화하며, UI의 상태 관리에 대한 부담을 줄일 수 있습니다.&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 코틀린 기반&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Compose는 순수 코틀린으로 작성되었습니다. 이는 개발자들이 이미 익숙한 언어를 활용할 수 있게 해주며, 코틀린의 강력한 기능들을 활용하여 보다 간결하고 읽기 쉬운 코드를 작성할수 있습니다.&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 반응형 프로그래밍&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Compose는 UI의 상태가 변경되었을 때 자동으로 UI를 업데이트합니다. 이는 데이터와 UI가 동기화를 유지하며, 이를 통해 개발자는 UI의 상태 관리에 대해 걱정할 필요가 없게 됩니다.&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. 모듈화와 재사용성&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Compose 함수는 재사용 가능한 구성요소를 만드는데 용이합니다. 이는 UI 구성요소를 작은 단위로 나누고 재사용함으로써 코드의 재사용성을 높이고, 유지보수를 용이하게 합니다.&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 동적 UI&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Compose는 앱의 상태가 변화할 때마다 UI를 동적으로 갱신합니다. 이는 UI가 최신 상태를 항상 반영하도록 하며, 사용자 경험을 향상시킵니다.&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. 테스트 용이성&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Compose는 UI 테스트를 쉽게 만들어줍니다. 각 UI 구성요소는 독립적으로 테스트할 수 있으며, 이는 테스트의 복잡성을 줄이고 코드의 안정성을 높입니다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이러한 장점들을 통해, Compose는 안드로이드 앱 개발의 새로운 시대를 열게 됩니다. 더 이상 복잡한 XML 코드를 작성하거나, 상태 관리에 대해 고민하지 않아도 됩니다. 대신, 간결하고 직관적인 코틀린 코드를 작성하면, Compose가 나머지를 처리해줍니다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;하지만, 이 모든 것이 의미가 있으려면, 우리가 Compose를 어떻게 사용하는지를 알아야 합니다. 그래서 이  시리즈에서는 Compose의 기본부터 고급 기능까지,&amp;nbsp; 실제 코드 예제를 통해 알아보도록 하겠습니다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이렇게 하면, 우리는 보다 간결하고 이해하기 쉬운 코드를 작성하면서도, 보다 강력한 UI를 구현할 수 있게 될 것입니다. 이를 통해 개발 시간을 단축시키고, 앱의 품질을 향상시킬 수 있습니다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음&lt;span&gt; &lt;/span&gt;포스트에서는&lt;span&gt; Compose&lt;/span&gt;의&lt;span&gt; &lt;/span&gt;설치&lt;span&gt; &lt;/span&gt;및&lt;span&gt; &lt;/span&gt;설정&lt;span&gt; &lt;/span&gt;방법에&lt;span&gt; &lt;/span&gt;대해&lt;span&gt; &lt;/span&gt;알아보겠습니다&lt;span&gt;. &lt;/span&gt;그럼&lt;span&gt;, &lt;/span&gt;행복한&lt;span&gt; &lt;/span&gt;코딩&lt;span&gt; &lt;/span&gt;시간&lt;span&gt; &lt;/span&gt;되세요&lt;span&gt;!&lt;/span&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;</description>
      <category>Android/Jetpack Compose</category>
      <category>JetpackCompose</category>
      <category>모던안뜨로이드</category>
      <category>선언형UI</category>
      <category>안드로이드개발</category>
      <category>안드로이드스튜디오</category>
      <category>안드로이드컴포즈</category>
      <category>젯팩컴포즈</category>
      <category>컴포즈</category>
      <category>컴포즈장점</category>
      <category>코틀린</category>
      <author>라크라꾸</author>
      <guid isPermaLink="true">https://lakue.tistory.com/84</guid>
      <comments>https://lakue.tistory.com/84#entry84comment</comments>
      <pubDate>Thu, 8 Jun 2023 02:14:05 +0900</pubDate>
    </item>
    <item>
      <title>[Android/토이프로젝트] 실시간 뉴스 - 실시간 뉴스 받아보기</title>
      <link>https://lakue.tistory.com/83</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;어플을 사용하시면서 문의하실 내용이나, 버그를 발견하셔서 의견 제공은 댓글을 남겨주시면 신속하게 처리할 수 있도록 노력하겠습니다. 많은 댓글 부탁드립니다 &lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;사용하시면서 이런 기능 및 기술은 어떻게 구현했는지에 대해 궁금증을 가지고 계신 분들도 댓글을 통해 문의주시면 제가 한 방식에 대한 설명으로 도와드리겠습니다.&lt;/p&gt;</description>
      <category>Android/토이프로젝트</category>
      <author>라크라꾸</author>
      <guid isPermaLink="true">https://lakue.tistory.com/83</guid>
      <comments>https://lakue.tistory.com/83#entry83comment</comments>
      <pubDate>Thu, 11 May 2023 15:01:06 +0900</pubDate>
    </item>
    <item>
      <title>[Android/안드로이드] Context, 뭐하는 녀석인지 알고 사용하자!</title>
      <link>https://lakue.tistory.com/82</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Context란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #464646;&quot;&gt;현재 사용되고 있는 애플리케이션(또는 액티비티)에 대한 포괄적인 정보를 지니고 있는 객체입니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Application의 현재 상태를 나타냅니다.&lt;/li&gt;
&lt;li&gt;Activity와 Application의 정보를 얻기 위해 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;Resource, Database, SharedPreference 등에 접근하기 위해 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;Activity와 Application 클래스는 Context 클래스를 확장한 클래스입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Context의 잘못된 사용법&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Context는 안드로이드 앱 개발을 할 때 모든 곳에서 쉽게 접근할 수 있습니다. 하지만 잘못 사용하게 되면 메모리 누수를 발생시킬 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;b674&quot; data-selectable-paragraph=&quot;&quot;&gt;ViewModel 등에서 Activity를 멤버 변수로 참조하는 경우.&lt;/li&gt;
&lt;li id=&quot;3d20&quot; data-selectable-paragraph=&quot;&quot;&gt;non-static inner class로 선언된 Handler를 Activity에서 사용하는 경우.&lt;/li&gt;
&lt;li id=&quot;c534&quot; data-selectable-paragraph=&quot;&quot;&gt;(Text) View를 static 변수로 선언하고 Activity가 이를 참조하는 경우&lt;/li&gt;
&lt;li id=&quot;1588&quot; data-selectable-paragraph=&quot;&quot;&gt;Singleton에서 Activity를 참조하는 경우&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;h4 data-ke-size=&quot;size20&quot;&gt;1. Application Context&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #464646;&quot;&gt;ApplicationContext는 Application LifeCycle을 따르며 애플리케이션이 실행되어 종료될 때까지 동일한 객체를 참조합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. Activity Context&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #464646;&quot;&gt;ActivityContext는 Activity LifeCycle을 따르며 Activity가 onDestroy() 될 때 context는 사라지게 됩니다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #464646;&quot;&gt;Application Context와 Activity Context 간 계층은 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;이미지 2.png&quot; data-origin-width=&quot;2444&quot; data-origin-height=&quot;1672&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WXZTH/btrvbeIOstX/CK7tZn72HBQjx6O44KJDtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WXZTH/btrvbeIOstX/CK7tZn72HBQjx6O44KJDtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WXZTH/btrvbeIOstX/CK7tZn72HBQjx6O44KJDtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWXZTH%2FbtrvbeIOstX%2FCK7tZn72HBQjx6O44KJDtK%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;653&quot; height=&quot;447&quot; data-filename=&quot;이미지 2.png&quot; data-origin-width=&quot;2444&quot; data-origin-height=&quot;1672&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;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Context는 어떻게 사용해야 할까?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 말한대로 Context를 잘못 사용하면 메모리 누수를 발생할 수 있습니다. 하지만 잘만 사용한다면 편리하게 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 ViewModel에서 ActivityContext를 주입해 사용할 경우 문제가 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;이미지 3.png&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;1114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kBqoz/btrvoBpwB7X/QoMSE7zTNTWq5KCgwCKsRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kBqoz/btrvoBpwB7X/QoMSE7zTNTWq5KCgwCKsRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kBqoz/btrvoBpwB7X/QoMSE7zTNTWq5KCgwCKsRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkBqoz%2FbtrvoBpwB7X%2FQoMSE7zTNTWq5KCgwCKsRk%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;410&quot; height=&quot;297&quot; data-filename=&quot;이미지 3.png&quot; data-origin-width=&quot;1540&quot; data-origin-height=&quot;1114&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;위와 같은 방법대로 ActivityContext를 ViewModel이 주입을 받았다고 가정을 한다면, 굉장히 안 좋은 상황이 발생하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순서대로 작업을 실행해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;이미지 4.png&quot; data-origin-width=&quot;2050&quot; data-origin-height=&quot;880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clXZjg/btrvhoqCgRV/0r0LFUruQO5M4B1nkSRWU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clXZjg/btrvhoqCgRV/0r0LFUruQO5M4B1nkSRWU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clXZjg/btrvhoqCgRV/0r0LFUruQO5M4B1nkSRWU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclXZjg%2FbtrvhoqCgRV%2F0r0LFUruQO5M4B1nkSRWU1%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;648&quot; height=&quot;278&quot; data-filename=&quot;이미지 4.png&quot; data-origin-width=&quot;2050&quot; data-origin-height=&quot;880&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;액티비티에서 ViewModel에 ActivityContext 주입&lt;/li&gt;
&lt;li&gt;ViewModel에서 데이터베이스 접근하는 코드를 작성&lt;/li&gt;
&lt;li&gt;여기서 가정이 필요합니다. 호출을 했을 때 데이터를 불러오는 시간을 3초라고 가정을 해봅니다.&lt;/li&gt;
&lt;li&gt;데이터를 불러오는 시간보다 먼저 Activity를 종료합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이렇게되면 무슨 상황이 발생할까요??&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Room에 접근하기 위해서는 Context객체가 필요한데 보시다시피 ViewModel에서 참조하고 있는 ActivityContext가 Activity가 종료가 되면서 메모리 누수 현상이 발생하게 됩니다. 이러면서 앱은 강제 종료가 되며 사용자는 불편을 겪게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 ViewModel에서는 Context를 참조하면 안되나? 라는 의문점을 가질 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ApplicationContext를 사용하게되면 해결됩니다. 안드로이드에서 제공하는 AndroidViewModel에서도 ApplicationContext를 참조하게 되는데, 이와 같이 ApplicationContext를 참조하게 되면 Activity의 생명주기와는 관계없이 끝까지 살아남게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그럼 모든 Context를 ApplicationContext를 사용하면 되나?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정답은 No입니다. ApplicationContext는 ActivityContext가 지원하는 모든 것을 지원하지 않기 때문에, GUI와 관련된 모든 것에 대해서는 ApplicationContext가 정상적으로 작동하지 않을 수 있습니다. 그렇기 때문에 무조건 ApplicationContext를 사용하는 것은 잘못된 방법입니다. Dialog, Toast 등, 화면 관련된 Context는 ActivityContext를 사용해줍니다.&lt;/p&gt;</description>
      <category>Android/유용한 기술</category>
      <category>activity</category>
      <category>ActivityContext</category>
      <category>Application</category>
      <category>ApplicationContext</category>
      <category>context</category>
      <category>Memory Leak</category>
      <category>가비지 콜렉터</category>
      <category>메모리 누수</category>
      <author>라크라꾸</author>
      <guid isPermaLink="true">https://lakue.tistory.com/82</guid>
      <comments>https://lakue.tistory.com/82#entry82comment</comments>
      <pubDate>Tue, 8 Mar 2022 01:31:35 +0900</pubDate>
    </item>
    <item>
      <title>Clean Architecture 스터디[16장] 독립성</title>
      <link>https://lakue.tistory.com/81</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 아키텍처는 다음을 지원해야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템의 유스케이스&lt;/li&gt;
&lt;li&gt;시스템의 운영&lt;/li&gt;
&lt;li&gt;시스템의 개발&lt;/li&gt;
&lt;li&gt;시스템의 배포&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;유스케이스&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템의 아키텍처는 시스템의 의도를 지원해야 한다는 뜻이다.&lt;/li&gt;
&lt;li&gt;좋은 아키텍처가 행위를 지원하기 위해 할 수 있는 일 중에서 가장 중요한 사항은 행위를 명확히 하고 외부로 드러내며, 이를 통해 시스템이 지닌 의도를 아키텍처 수준에서 알아볼 수 있게 만드는 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;운영&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템의 운영 지원 관점에서 볼 때 아키텍처는 더 실질적이며 덜 피상적인 역할을 맡는다.&lt;/li&gt;
&lt;li&gt;각 컴포넌트를 적절히 격리하여 유지하고 컴포넌트 간 통신 방식을 특정 형태로 제한하지 않는다면, 시간이 지나 운영에 필요한 요구사항이 바뀌더라도 스레드, 프로세스, 서비스로 구성된 기술 스펙트럼 사이를 전환하는 일이 훨씬 쉬어질 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;개발&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아키텍처는 개발환경을 지원하는 데 있어 핵심적인 역할을 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;콘웨이의-법칙&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;콘웨이의 법칙&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;시스템을 설계하는 조직이라면 어디든지 그 조직의 의사소통 구조와 동일한 구조의 설계를 만들어 낼 것이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;많은 팀으로 구성되며 관심사가 다양한 조직에서 어떤 시스템을 개발해야 한다면, 각 팀이 독립적으로 행동하기 편한 아키텍처를 반드시 확보하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;개발하는 동안 팀들이 서로를 방해하지 않도록 해야 한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;이러한 아키텍처를 만들려면&lt;span&gt;&amp;nbsp;&lt;/span&gt;잘 격리되어 독립적으로 개발 가능한 컴포넌트 단위로 시스템을 분할할 수 있어야 한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;그래야만 이들 컴포넌트를 독립적으로 작업할 수 있는 팀에 할당할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;배포&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #343a40;&quot;&gt;좋은 아키텍처는 수십 개의 작은 설정 스크립트나 속성 파일을 약간씩 수정하는 방식을 사용하지 않는다. 좋은 아키텍처는 꼭 필요한 디렉터리나 파일을 수작업으로 생성하게 내버려 두지 않는다. 좋은 아키텍처는 시스템이 빌드된 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;즉각 배포&lt;span style=&quot;background-color: #ffffff; color: #343a40;&quot;&gt;할 수 있도록 지원해야한다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;선택사항 열어놓기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;좋은 아키텍처는 선택사항을 열어 둠으로써, 향후 시스템에 변경이 필요할 때 어떤 방향으로든 쉽게 변경할 수 있도록 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;계층 결합 분리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;아키텍트는 단일 책임 원칙과 공통 폐쇄 원칙을 적용하여, 그 의도의 맥락에 따라서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;다른 이유로 변경되는 것들을 분리&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;동일한 이유로 변경되는 것들을 묶는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;유스케이스 결합 분리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유스케이스 또한 서로 다른 이유로 변경될 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유스케이스는 시스템을 분할하는 매우 자연스러운 방법이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유스케이스는 시스템의 수평적인 계층을 가로지르도록 자른, 수직으로 좁다란 조각이기도 하다. 각 유스케이스는 UI의 일부, 애플리케이션 특화 업무 규칙이 일부, 애플리케이션 독립적 업무 규칙의 일부, 그리고 데이터베이스 기능의 일부를 사용한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;따라서 우리는 시스템을 수평적 계층으로 분할하면서 동시에 해당 계층을 가로지르는 얇은 수직적인 유스케이스로 시스템을 분할할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결합 분리 모드&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유스케이스를 위해 수행하는 그 작업들(결합 분리)은 운영에도 도움이 된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;운영 측면에서 이러한 장점을 살리기 위해선 결합을 분리할 때 적절한 모드를 선택해야 한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) 분리된 컴포넌트를 서로 다른 서버에서 실행해야 하는 상황이라면, 이들 컴포넌트가 단일 프로세서의 동일한 주소 공간에 함께 상주하는 형태로 만들어져서는 안 된다. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;분리된 컴포넌트는 반드시 독립된 서비스가 되어야 하고, 일종의 네트워크를 통해 서로 통신해야 한다.&lt;/li&gt;
&lt;li&gt;실제로 서비스에 기반한 아키텍처를 흔히 서비스 지향 아키텍처(serice-oriented-architecture, SOA)라고 부른다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;개발 독립성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #343a40;&quot;&gt;컴포넌트가 완전히 분리되면 팀 사이 간섭은 줄어든다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #343a40;&quot;&gt;기능 팀, 컴포넌트 팀, 계층 팀, 혹은 또 다른 형태의 팀이라도, 계층과 유스케이스의 결합이 분리되는 한 시스템의 아키텍처는 그 팀의 구조를 뒷받침해 줄 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;배포 독립성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포 측면에서 유연성이 생긴다. 결합이 제대로 분리가 되었다면 시스템에서 계층과 유스케이스를 교체할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 유스케이스를 추가하는 일은 시스템의 나머지는 그대로 둔 채 새로운 jar파일이나 서비스 몇 개를 추가하면 끝나는 정도로 단순한 일이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;중복&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중복은 두가지 종류가 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;진짜 중복
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중복으로 보이는 두 코드 영역이 한 곳 변경 시 다른 곳도 변경해주어야 하는 경우&lt;/li&gt;
&lt;li&gt;하나의 코드로 합치는 것이 관리에 용이하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;우발적 중복
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중복으로 보이는 두 코드 영역이 각자의 경로로 발전하는 경우&lt;/li&gt;
&lt;li&gt;시간이 지나면서 두 코드는 서로 다른 방향으로 변경될 가능성이 높다.&lt;/li&gt;
&lt;li&gt;우발적 중복은 코드를 통합하지 않도록 유의해야 한다. 그렇지 않으면 나중에 다시 코드를 분리하느라 큰 수고를 감수해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결합 분리 모드(다시)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계층과 유스케이스의 결합을 분리하는 방법 3가지&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;소스 수준 분리 모드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소스 코드 모듈 사이의 의존성 제어할 수 있다.&lt;/li&gt;
&lt;li&gt;모든 컴포넌트가 같은 주소 공간에서 실행된다.&lt;/li&gt;
&lt;li&gt;통신할 때는 간단함 함수 호출을 사용한다.&lt;/li&gt;
&lt;li&gt;컴퓨터 메모리에는 하나의 실행 파일만이 로드된다. (모노리틱 구조)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;배포 수준 분리 모드&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배포 가능한 단위들(jar 파일 / DLL / 공유 라이브러리) 사이의 의존성 제어할 수 있다.&lt;/li&gt;
&lt;li&gt;많은 컴포넌트가 여전히 같은 주소 공간에서 실행된다.&lt;/li&gt;
&lt;li&gt;통신할 때는 간단함 함수 호출을 사용한다.&lt;/li&gt;
&lt;li&gt;어떤 컴폰너트는 동일한 프로세서의 다른 프로세스에 상주하고, 프로세스간 통신/소켓/공유메모리 를 통해 통신할 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서비스 수준 분리 모드&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;순전히 네트워크 패킷을 통해서만 통신한다.&lt;/li&gt;
&lt;li&gt;모든 실행 가능한 단위는 소스와 바이너리 변경에 대해 서로 완전히 독립적이게 된다. (마이크로서비스 구조)&lt;/li&gt;
&lt;/ul&gt;
&lt;/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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현 시점 가장 인기 있어보이는 해결책은 단순히 서비스 수준에서의 분리를 기본 정책으로 삼는 것이다..&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 아키텍처는 결합 분리 모드를&lt;span&gt;&amp;nbsp;&lt;/span&gt;선택사항으로 남겨두어 배포 규모에 따라 가장 적합한 모드를 선택해 사용할 수 있게 만들어 준다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;좋은 아키텍처는 모노리틱 구조로 시작해 마이크로서비스 수준까지 성장해도 원래 형태로 돌아갈 수 있어햐 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;시스템의 결합 분리 모드는 시간이 지나면서 바뀌기 쉬우며, 뛰어난 아키텍트라면 이러한 변경을 예측하여 큰 무리 없이 반영할 수 있도록 만들어야 한다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Clean Architecture</category>
      <category>Clean Architecture</category>
      <category>UseCase</category>
      <category>개발</category>
      <category>독립성</category>
      <category>배포</category>
      <category>운영</category>
      <category>유스케이스</category>
      <category>클린 아키텍처</category>
      <author>라크라꾸</author>
      <guid isPermaLink="true">https://lakue.tistory.com/81</guid>
      <comments>https://lakue.tistory.com/81#entry81comment</comments>
      <pubDate>Mon, 7 Feb 2022 22:38:46 +0900</pubDate>
    </item>
    <item>
      <title>Clean Architecture 스터디[15장] 아키텍처란?</title>
      <link>https://lakue.tistory.com/80</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;아키텍처의 주 목적&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템의 생명주기를 지원&lt;/li&gt;
&lt;li&gt;좋은 아키텍처는 시스템을 쉽게 이해하고, 쉽게 개발하며, 쉽게 유지보수하고, 쉽게 배포하게 해준다.&lt;/li&gt;
&lt;li&gt;시스템의 수명과 관련된 비용은 최소화 하고, 프로그래머의 생산성은 최대화 하는 데 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;개발&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;개발하기 힘든 시스템이라면 수명이 길지도 않고 건강하지도 않을 것이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 아키텍처는 개발팀이 시스템을 쉽게 개발할 수 있는 구조여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;배포&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;소프트웨어 시스템이 사용될 수 있으려면 반드시 배포할 수 있어야 한다. 배포 비용이 높을수록 시스템의 유용성은 떨어진다.&lt;/blockquote&gt;
&lt;p id=&quot;운영&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;소프트웨어 아키텍처는 시스템을&amp;nbsp;단 한 번에 쉽게&amp;nbsp;배포할 수 있도록 만드는 데 목표를 두어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;운영&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;아키텍처가 시스템 운영에 미치는 영향은 개발, 배포, 유지보수에 미치는 영향보다는 덜 극적이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 소프트웨어 아키텍처는 시스템을 운영하는데 필요한 요구도 알려준다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템 아키텍처는&lt;span&gt;&amp;nbsp;&lt;/span&gt;유스케이스, 기능, 시스템의 필수 행위를 일급(first-class) 엔티티로 격상시키고, 이들 요소가 개발자에게 주요 목표로 인식되도록 해야 한다.&lt;/li&gt;
&lt;li&gt;이를 통해 시스템을 이해하기 쉬워지며, 따라서 개발과 유지보수에 큰 도움이 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;유지보수&lt;/b&gt;&lt;/h2&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;가장 큰 비용은 탐사(spelunking)와 이로 인한 위험부담에 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;탐사: 기존 소프트웨어에 새로운 기능을 추가하거나 결함을 수정할 때, 소프트웨어를 파헤쳐서 어디를 고치는게 최선인지, 그리고 어떤 전략을 쓰는게 최적일지를 결정할 때 드는 비용이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아키텍처를 신중하게 만들면 이 비용을 크게 줄일 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템을 컴포넌트로 분리하고, 안정된 인터페이스를 두어 서로 격리한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;선택사항 열어두기&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어를 부드럽게 유지하는 방법은&amp;nbsp;선택사항을 가능한 한 많이, 그리고 가능한 한 오랫동안 열어 두는 것이다.&lt;/li&gt;
&lt;li&gt;열어둬야 할 선택사항 - 중요치 않은 세부사항&lt;/li&gt;
&lt;li&gt;모든 소프트웨어 시스템은 주요한 두 가지 구성요소로 분해할 수 있다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;정책 - 시스템의 진정한 가치가 살아있는 곳(모든 업무 규칙과 업무 절차를 구체화)&lt;/li&gt;
&lt;li&gt;세부사항 - 사람, 외부 시스템, 프로그래머가 정책과 소통할 때 필요한 요소지만, 정책이 가진 행위에는 조금도 영향을 미치지 않음(입출력장치, 데이터베이스, 웹 시스템, 서버 프레임워크, 통신 프로토콜 등)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;아키텍트의 목표&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템 정책을 가장 핵심적인 요소로 식별&lt;/li&gt;
&lt;li&gt;세부사항은 정책에 무관하게 만들 수 있는 형태의 시스템을 구축&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;장치 독립성&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1960년대에 프로그래머는 많은 실수를 저릴렀는데, 대표적인 실수 중 하나는&lt;span&gt;&amp;nbsp;&lt;/span&gt;코드를 입출력 장치와 결합해버린 일이다. 프린터로 인쇄할 일이 생기면, 해당 프린터를 제어하는 입출력 명렁어를 직접 사용해서 코드를 작성했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이러한 코드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;장치 종속적(device dependent)이다.&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;카드 판독기에서 카드를 읽어야 할 경우에도 카드 판독기와 직접 상호작용하도록 코드를 작성했다.&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;큰 규모의 천공카드 뭉치기는 관리하기가 어려웠다.&lt;/li&gt;
&lt;li&gt;잃어버리거나 찢어지거나 구멍이 뚫리고 서로 섞이거나 떨ㅇ어뜨릴 수 있었다.&lt;/li&gt;
&lt;li&gt;개별 카드를 잃어버릴 수도 있었고, 다른 카드가 추가되기도 했다.&lt;/li&gt;
&lt;li&gt;결국 데이터 무결성이 중요한 문제로 대두되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결책&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해결책은 자기테이프였다&lt;/li&gt;
&lt;li&gt;자기테이프는 떨어뜨리더라도 레코드가 섞이지 않았다. 단순히 테이프를 전달ㄹ하는 과정에서 레코드가 우연히 사라지거나, 또는 비어 있는 레코드가 추가되지 않았다.&lt;/li&gt;
&lt;li&gt;이처럼 테이프는 훨씬 안전하고, 더 빨리 읽고 쓸 수 있고, 맥업용 복사본도 매우 쉽게 만들 수 있었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;문제점&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우리가 만든 모든 소프트웨어는 오직 카드 판독기와 카드 천공기를 조작하도록 작성되었다.&lt;/li&gt;
&lt;li&gt;자기 테이프를 사용하려면 이들 프로그램을 다시 작성해야 하는데, 너무 큰 작업이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;장치 독립성을 생각&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 장치를 소프트웨어 함수로 추상화했고, 해당 함수는 천공카드와 같은 단위 레코드를 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램은 운영체제의 서비스를 호출하고, 해당 서비스가 추상화된 단위 레코드 장치를 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오퍼레이터가 해당 추상 서비스를 카드 판독기, 자기 테이프, 아니면 또 다른 단위 레코드 장치 중 어디에 연결해야 하는지를 운영체제에 알려줌&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동일한 프로그램을 아무런 변경 없이도 카드에서 읽고 쓰거나 테이프에서 읽고 쓸 수 있게 되면서 개방 폐쇄 원칙이 탄생하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;광고 우편&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;장치 독립성을 이용해 어떤 장치를 사용할지 전혀 모른채, 그리고 고려하지 않고도 프로그램을 작성할 수 있엇다고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이러한 프로그램에는 형태가 있었는데, 이 형태는&amp;nbsp;정책을 세부사항으로부터 분리했다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;어떤 장치를 사용할지에 대한 결정을 연기시켰다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;물리적 주소 할당&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;시스템에서 고수준의 정책을 물리적 구조로부터 독립시킴으로써 애플리케이션과 하드웨어를 분리할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Clean Architecture</category>
      <category>architecture</category>
      <category>Clean Architecture</category>
      <category>아키텍처</category>
      <category>클린 아키텍처</category>
      <author>라크라꾸</author>
      <guid isPermaLink="true">https://lakue.tistory.com/80</guid>
      <comments>https://lakue.tistory.com/80#entry80comment</comments>
      <pubDate>Sun, 6 Feb 2022 20:26:51 +0900</pubDate>
    </item>
    <item>
      <title>Clean Architecture 스터디[14장] 컴포넌트 결합</title>
      <link>https://lakue.tistory.com/79</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;컴포넌트 결합&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 결합은 컴포넌트 사이의 관계를 설명한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;ADP: 의존성 비순환 원칙&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;컴포넌트 의존성 그래프에 순환이 있어서는 안 된다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;숙취 증후군&lt;/b&gt;&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;해결법&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주 단위 빌드&lt;/li&gt;
&lt;li&gt;의존선 비순환 원칙&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주 단위 빌드(Weekly Build)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중간규모 프로젝트에서 흔하게 사용한다.&lt;/li&gt;
&lt;li&gt;정해진 기간동안 각자 신경쓰지 않고 개발을 하다가, 날 잡고 통합하여 시스템 빌드하는 방법이다.&lt;/li&gt;
&lt;li&gt;프로젝트가 커지며 통합하는 시간이 길어지며, 개발하는 시간을 침범하게 되어 효율성이 점점 떨어지게됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;순환 의존성 제거&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;그룹 49.png&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;77&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uwQks/btrsxgWgrQx/KiYj5NYRkwLgAnbOmRKzP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uwQks/btrsxgWgrQx/KiYj5NYRkwLgAnbOmRKzP1/img.png&quot; data-alt=&quot;개발자가 개발 -&amp;amp;gt; 릴리스 -&amp;amp;gt; 다른 개발자가 사용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uwQks/btrsxgWgrQx/KiYj5NYRkwLgAnbOmRKzP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuwQks%2FbtrsxgWgrQx%2FKiYj5NYRkwLgAnbOmRKzP1%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;610&quot; height=&quot;77&quot; data-filename=&quot;그룹 49.png&quot; data-origin-width=&quot;610&quot; data-origin-height=&quot;77&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;개발자가 개발 -&amp;gt; 릴리스 -&amp;gt; 다른 개발자가 사용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 문제의 해결책은 개발 환경을 릴리스 가능한 컴포넌트 단위로 분리하는 것이다.&lt;/li&gt;
&lt;li&gt;이렇게 되면 컴포넌트는 개별 개발자 또는 단일 개발팀이 책일을 질 수 있는 닥업 단위가 된다.&lt;/li&gt;
&lt;li&gt;컴포넌트가 변경되어도 다른 팀에 영향을 주지 않음&lt;/li&gt;
&lt;li&gt;이 방법은 단순하고 합리적이어서 널리 사용되지만 성공적으로 동작하려면 컴포넌트 사이의 의존성구조를 반드시 관리해야 한다. 의존성 구조에 순환이 생기면 '숙취 증후군'을 피해 갈 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드 (1).png&quot; data-origin-width=&quot;535&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cu6XkG/btrszlI7FZy/J4cf8bmUZdHHr8d2O6fpO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cu6XkG/btrszlI7FZy/J4cf8bmUZdHHr8d2O6fpO0/img.png&quot; data-alt=&quot;전형적인 컴포넌트 다이어그램&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cu6XkG/btrszlI7FZy/J4cf8bmUZdHHr8d2O6fpO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcu6XkG%2FbtrszlI7FZy%2FJ4cf8bmUZdHHr8d2O6fpO0%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;535&quot; height=&quot;308&quot; data-filename=&quot;다운로드 (1).png&quot; data-origin-width=&quot;535&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;전형적인 컴포넌트 다이어그램&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 컴포넌트들을 가각의 팀이라고 생각하고, Presenters를 담당하는 팀이 새로 릴리즈를 하게 됬다고 가정을 해보면, Presenters를 의존하는 컴포넌트는 View와 Main이 해당하게 됩니다. View와 Main팀의 작업중인 개발자라면, Presenters의 새로운 릴리스와 자신의 작업물을 언제 통합할지만 결정하면 된다. 또, Main이 새로 릴리스가 되더라도, 이를 의존하는 컴포넌트가 없기 때문에 영향을 받는 컴포넌트가 없다. 시스템 전체를 릴리스 해야 할 시기에는 Entities -&amp;gt; Database,Interactors -&amp;gt; Presenter, View, Controllers, Authorizer -&amp;gt;Main 순서로 절차는 상향식으로 진행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;순환이 컴포넌트 의존성 그래프에 미치는 영향&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드 (1).png&quot; data-origin-width=&quot;535&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vCpR9/btrstJEJ3gB/BkUow4LnHHcEhlMsSptkSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vCpR9/btrstJEJ3gB/BkUow4LnHHcEhlMsSptkSk/img.png&quot; data-alt=&quot;순환 의존성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vCpR9/btrstJEJ3gB/BkUow4LnHHcEhlMsSptkSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvCpR9%2FbtrstJEJ3gB%2FBkUow4LnHHcEhlMsSptkSk%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;535&quot; height=&quot;308&quot; data-filename=&quot;다운로드 (1).png&quot; data-origin-width=&quot;535&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;순환 의존성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 순환은 즉각적인 문제를 일으킨다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;그룹 50.png&quot; data-origin-width=&quot;785&quot; data-origin-height=&quot;205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qOrLd/btrsvdlt8kV/RknpYgClyD2L0io0y0GYl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qOrLd/btrsvdlt8kV/RknpYgClyD2L0io0y0GYl0/img.png&quot; data-alt=&quot;Database 컴포넌트 릴리스 -&amp;amp;gt; Entities 의존 -&amp;amp;gt; Authorizer의존 -&amp;amp;gt; Interactors 의존 -&amp;amp;gt; Entities 의존 -&amp;amp;gt; 순환...&amp;amp;nbsp;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qOrLd/btrsvdlt8kV/RknpYgClyD2L0io0y0GYl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqOrLd%2Fbtrsvdlt8kV%2FRknpYgClyD2L0io0y0GYl0%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;785&quot; height=&quot;205&quot; data-filename=&quot;그룹 50.png&quot; data-origin-width=&quot;785&quot; data-origin-height=&quot;205&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Database 컴포넌트 릴리스 -&amp;gt; Entities 의존 -&amp;gt; Authorizer의존 -&amp;gt; Interactors 의존 -&amp;gt; Entities 의존 -&amp;gt; 순환...&amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 Database를 릴리스 했을 뿐인데, Entities에 호환되어야하고, Authorizer에 호환되어야하고, Interactors에도 호환되어야하는게 계속 순환되기 때문에 Database는 릴리스 하기가 어려워진다. 이렇게 되면 거대한 Entities, Authorizer, Interactors는 거대한 컴포넌트가 되버린다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;순환 끊기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순환 끊기의 방법&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;의존성 역전 활용&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드 (2).png&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;318&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eFY5MA/btrswVEHeZO/ranSQaIMei0R881InAGV6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eFY5MA/btrswVEHeZO/ranSQaIMei0R881InAGV6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eFY5MA/btrswVEHeZO/ranSQaIMei0R881InAGV6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeFY5MA%2FbtrswVEHeZO%2FranSQaIMei0R881InAGV6k%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;580&quot; height=&quot;318&quot; data-filename=&quot;다운로드 (2).png&quot; data-origin-width=&quot;580&quot; data-origin-height=&quot;318&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;위와 같이 User가 필요하는 메서드를 제공하는 인터페이스를 생성한다. 이 인텊페이스는 Entities에 위치시키고, Authorizer에서는 이 인터페이스를 상속받는다. 이렇게 하면 Entities와 Authorizer 사이의 의존성을 역전시킬 수 있고, 이를 통해 순환을 끊을 수 있다.&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;두 컴포넌트가 의존하는 새로운 컴포넌트를 만든다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-14.4.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCrWcL/btrswVLrTaT/MbtxEMk1uZjMKl7Ve4cVr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCrWcL/btrswVLrTaT/MbtxEMk1uZjMKl7Ve4cVr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCrWcL/btrswVLrTaT/MbtxEMk1uZjMKl7Ve4cVr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCrWcL%2FbtrswVLrTaT%2FMbtxEMk1uZjMKl7Ve4cVr1%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;600&quot; height=&quot;274&quot; data-filename=&quot;image-14.4.png&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Entities와 Authorizer가 모두 의존하는 새로운 컴포넌트를 만든다. 그리고 두 컴포넌트가 모두 의존하는 클래스들을 새로운 컴포넌트로 이동시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;흐트러짐&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;요구사항이 변경되면 컴포넌트 구조도 변경될 수 있다. 애플리케이션이 성장함에 따라 컴포넌트 의존성 구조는 서서히 흐트러지며 또 성장한다. 따라서 의존성 구조에 순환이 발생하는지를 항상 관찰해야 한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;하향식(top-down) 설계&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;구조는 하향식으로 설계될 수 없다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;는 시스템에서 가장 먼저 설계할 수 있는 대상이 아니며, 오히려 시스템이 성장하고 변경될 때 함께 진행한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컴포넌트 의존성 다이어그램은 애플리케이션의 빌드 가능성과 요주보수성을 보여주는 지도와 같다. 컴포넌트 구조는 프로젝트 초기에 설계할 수 없다. 구현과 설계가 이뤄지는 프로젝트 초기에 모듈들이 점차 쌓이기 시작하면, &amp;lsquo;숙취 증후군&amp;rsquo;을 겪지 않고 프로젝트를 개발하기 위해서 의존성 관리에 대한 요구가 점차 늘어나게 된다. 뿐만 아니라 변경되는 범위가 시스템의 가능한 한 작은 일부로 한정되기를 원한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;의존성 구조와 관련된 최우선 관심사는 변동성을 격리하는 일이다. 우리는 변덕스러운 이유로 자주 변경되는 컴포넌트로 인해, 그렇지 않았다면 안정적이었을 컴포넌트가 영향받는 일을 원치 않는다. 결국 컴포넌트 의존성 그래프는 자주변경되는 컴포넌트로부터 안정적이며 가치가 높은 컴포넌트를 보호하려는 아키텍트가 만들고 가다듬게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;애플리케이션이 계속 성장함에 따라 우리는 재사용 가능한 요소를 만드는 일에 관심을 기울이기 시작한다. 이 시점이 되면 컴포넌트를 조합하는 과정에 공통 재사용 원칙(CRP)이 영향을 미치기 시작한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;SDP:안정된 의존성 원칙&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;안정성의 방향으로(더 안정된 쪽에) 의존하라.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;설계를 유지하다 보면 변경은 불가피하다. CCP(공통 폐쇄 원칙)을 준수함으로써,&amp;nbsp;컴포넌트가 다른 유형의 변경에는 영향을 받지 않으면서도 특정 유형의 변경에만 민감하게 만들 수 있다. 이처럼 컴포넌트 중 일부는 변동성을 지니도록 설계된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;변경이 쉽지 않은&amp;nbsp;컴포넌트가 변동성이 큰&amp;nbsp;컴포넌트를 의존하게 만들어서는 절대로 안된다. 한번 의존하게 되면 변동성이 큰&amp;nbsp;컴포넌트도 결국 변경하기 어려워지기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;SDP(안정된 의존성 원칙)을 준수하면 변경하기 어려운 모듈이 변경하기 쉽게 만들어진 모듈에 의존하지 않도록 만들 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안정성&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;소프트웨어 컴포넌트를 변경하기 어렵게 만드는 확실한 방법 하나는 수많은 다른 컴포넌트가 해당 컴포넌트에 의존하게 만드는 것이다. 컴포넌트 안쪽으로 들어오는 의존성이 많아지면 상당히 안정적으로 볼 수 있는데, 사소한 변경이라도 의존하는 모든 컴포넌트를 만족시키면서 변경하려면 상당한 노력이 들기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-14.5.png&quot; data-origin-width=&quot;729&quot; data-origin-height=&quot;287&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpotnU/btrssC61Pae/EjZerhuvbUcBxBp8Hqn851/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpotnU/btrssC61Pae/EjZerhuvbUcBxBp8Hqn851/img.png&quot; data-alt=&quot;X는 안정된 컴포넌트다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpotnU/btrssC61Pae/EjZerhuvbUcBxBp8Hqn851/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpotnU%2FbtrssC61Pae%2FEjZerhuvbUcBxBp8Hqn851%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;729&quot; height=&quot;287&quot; data-filename=&quot;image-14.5.png&quot; data-origin-width=&quot;729&quot; data-origin-height=&quot;287&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;X는 안정된 컴포넌트다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 그림은 안정된 컴포넌트다.&lt;/li&gt;
&lt;li&gt;세 컴포넌트가 X에 의존하며, 따라서 X컴포넌트는 변경하지 말아야 할 이유가 세가지나 된다.&lt;/li&gt;
&lt;li&gt;이 경우 'X는 세 컴포넌트를 책임진다' 라고 말한다.&lt;/li&gt;
&lt;li&gt;반대로 X는 어디에도 의존하지 않으므로 X가 변경되도록 만들 수 있는 외적인 형향이 없다. 이 경우 'X는 독립적이라' 라고 말한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-14.6.png&quot; data-origin-width=&quot;729&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNPa8k/btrsC8vPZD0/y20r56RHbmFWUgB5kzGSik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNPa8k/btrsC8vPZD0/y20r56RHbmFWUgB5kzGSik/img.png&quot; data-alt=&quot;Y는 상당히 불안정한 컴포넌트다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNPa8k/btrsC8vPZD0/y20r56RHbmFWUgB5kzGSik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNPa8k%2FbtrsC8vPZD0%2Fy20r56RHbmFWUgB5kzGSik%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;729&quot; height=&quot;292&quot; data-filename=&quot;image-14.6.png&quot; data-origin-width=&quot;729&quot; data-origin-height=&quot;292&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Y는 상당히 불안정한 컴포넌트다&lt;/figcaption&gt;
&lt;/figure&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;Y는 상당히 불안정한 컴포넌트다&lt;/li&gt;
&lt;li&gt;어떤 컴포넌트도 Y에 의존하지 않으므로 Y는 책임성이 없다고 말할 수 있다.&lt;/li&gt;
&lt;li&gt;또한 Y는 세 개의 컴포넌트에 의존하므로 변경이 발생할 수 있는 외부 요인이 세 가지이다.&lt;/li&gt;
&lt;li&gt;이 경우 Y는 의존적이라고 말한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;안정성 지표&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;의존성 개수 세는 방법&lt;/li&gt;
&lt;li&gt;Fan-in : 안으로 들어오는 의존성&lt;/li&gt;
&lt;li&gt;Fan-out : 바깥으로 나가는 의존성&lt;/li&gt;
&lt;li&gt;I(불안정성) : I = Fan-out/(Fan-in + Fan-out)&lt;/li&gt;
&lt;li&gt;이 지표는 [0,1] 범위의 값을 갖는다. 0에 가까울 수록 안정된 컴포넌트라는 뜻이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-14.7.png&quot; data-origin-width=&quot;677&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JpVs1/btrsxE3B2xP/fMT79yrry6pqsuhRLBgPk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JpVs1/btrsxE3B2xP/fMT79yrry6pqsuhRLBgPk0/img.png&quot; data-alt=&quot;예제&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JpVs1/btrsxE3B2xP/fMT79yrry6pqsuhRLBgPk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJpVs1%2FbtrsxE3B2xP%2FfMT79yrry6pqsuhRLBgPk0%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;677&quot; height=&quot;305&quot; data-filename=&quot;image-14.7.png&quot; data-origin-width=&quot;677&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;예제&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Cc의 컴포넌트의 안정성 계산&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Cc내부의 클래스에 의존하며 Cc외부에 있는 클래스는 세 개다. (Fan-in = 3)&lt;/li&gt;
&lt;li&gt;Cc내부의 클래스가 의존하는 Cc외부에 위치한 클래스는 한 개다. (Fan-out = 1)&lt;/li&gt;
&lt;li&gt;I = 1/4 = 0.25&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SDP에서 컴포넌트의 I지표는 그 컴포넌트가 의존하는 다른 컴포넌트들의 I보다 커야 한다고 말한다. 즉, 의존성 방향으로 갈수록 I지표가 값이 감소 해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;모든 컴포넌트가 안정적이어야 하는 것은 아니다&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;세 컴포넌트로 구성된 시스템이 가질 수 있는 이상적인 구조의 다이어그램&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-14.8.png&quot; data-origin-width=&quot;674&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/laDj9/btrsxEvN7WL/n7RJm2pEE1UFUCGHMYjJg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/laDj9/btrsxEvN7WL/n7RJm2pEE1UFUCGHMYjJg1/img.png&quot; data-alt=&quot;세 컴포넌트로 구성된 시스템의 이상적인 구성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/laDj9/btrsxEvN7WL/n7RJm2pEE1UFUCGHMYjJg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlaDj9%2FbtrsxEvN7WL%2Fn7RJm2pEE1UFUCGHMYjJg1%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;674&quot; height=&quot;313&quot; data-filename=&quot;image-14.8.png&quot; data-origin-width=&quot;674&quot; data-origin-height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;세 컴포넌트로 구성된 시스템의 이상적인 구성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위쪽에 변경 가능한 컴포넌트가 있고, 아래의 안정된 컴포넌트에 의존한다.&lt;/li&gt;
&lt;li&gt;다이어그램에서 불안정한 컴포넌트를 관례적으로 위쪽에 둔다.(따르면 유용)&lt;/li&gt;
&lt;li&gt;위로 향하는 화살표가 있으면 SDP를 위배하는(ADP도 위반하는) 상태가 되기 때문이다.&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;b&gt;SDP가 어떻게 위배되는 구조의 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드 (3).png&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;806&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFSth5/btrsC92CYvP/T3kBUn0kxeeuPxpcNwtcl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFSth5/btrsC92CYvP/T3kBUn0kxeeuPxpcNwtcl0/img.png&quot; data-alt=&quot;SDP 위배&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFSth5/btrsC92CYvP/T3kBUn0kxeeuPxpcNwtcl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFSth5%2FbtrsC92CYvP%2FT3kBUn0kxeeuPxpcNwtcl0%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;616&quot; height=&quot;499&quot; data-filename=&quot;다운로드 (3).png&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;806&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;SDP 위배&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Flexible&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;은 변경하기 쉽도록 설계한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;컴포넌트&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;다. 하지만&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Stable 컴포넌트&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;에서 작업하던 개발자가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Flexible&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;에 의존성을 걸게 되었다. 이로 인해 SDP를 위배하는데,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Stable&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Flexible&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;을 의존하기 이전에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Stable&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;I(불안정성)&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;지표는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Flexible&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;I(불안정성)&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;지표보다는 더 작기 때문이다. 결국&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Flexible&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;은 변경하기가 어렵게 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결책&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DIP를 도입하면 이 문제를 해결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드 (4).png&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;544&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qrYzH/btrsxjrBwcf/JLMCppksT4OVg7M37wjbTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qrYzH/btrsxjrBwcf/JLMCppksT4OVg7M37wjbTK/img.png&quot; data-alt=&quot;C는 US 인터페이스를 구현한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qrYzH/btrsxjrBwcf/JLMCppksT4OVg7M37wjbTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqrYzH%2FbtrsxjrBwcf%2FJLMCppksT4OVg7M37wjbTK%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;618&quot; height=&quot;349&quot; data-filename=&quot;다운로드 (4).png&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;544&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;C는 US 인터페이스를 구현한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 US라는 인터페이스를 생성한 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;UServer 컴포넌트에 넣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C가 해당 인터페이스를 구현하도록 만든다. 이를 통해&lt;span&gt;&amp;nbsp;&lt;/span&gt;Stable의&lt;span&gt;&amp;nbsp;&lt;/span&gt;Flexible에 대한 의존성을 끊을 수 있고, 두 컴포넌트는 모두&lt;span&gt;&amp;nbsp;&lt;/span&gt;UServer에 의존하도록 강제한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;UServer는 매우 안정된 상태이며(&lt;span&gt;I&lt;/span&gt;=0),&lt;span&gt;&amp;nbsp;&lt;/span&gt;Flexible은 자신에게 맞는 불안정성(&lt;span&gt;I&lt;/span&gt;=1)을 그대로 유지할 수 있다. 이제 모든 의존성은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;I&lt;/span&gt;가 감소하는 방향으로 향하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;SAP: 안정된 추상화 원칙&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;컴포넌트는 안정된 정도만큼만 추상화되어야 한다.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;고수준 정책을 어디에 위치시켜야 하는가?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;시스템에는 자주 변경해서는 절대로 안 되는 소프트웨어도 있다. &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;고수준 아키텍처나 정책 결정과 관련된 소프트웨어가 그 예다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;업무 로직이나 아키텍처와 관련된 결정에는 변동성이 없기를 기대한다. &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;따라서 시스템에서 고수준 정책을 캡슐화하는 소프트웨어는 반드시 안정된 컴포넌트(I=0)에 위치해야 한다. &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;불안정한 컴포넌트(I=1)는 반드시 변동성이 큰 소프트웨어, 즉 빠르게 변경할 수 있는 소프트웨어만을 포함해야 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;하지만 고수준 정책을 안정된 컴포넌트에 위치시키면, 그 정책을 포함하는 소스 코드는 수정하기가 어려워진다. &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이로 인해 시스템 전체 아키텍처가 유연성을 잃는다. &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;컴포넌트가 최고로 안정된 상태이면서도(I=0) 동시에 변경에 충분히 대응할 수 있을 정도로 유연하게 만들 수 있다. 개방&amp;nbsp;폐쇄 원칙(OCP)를 활용하는 것이다. &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;OCP 에서는 클래스를 수정하지 않고도 확장이 충분히 가능할 정도로 클래스를 유연하게 만들 수 있다. &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;추상(abstract) 클래스가 이 원칙을 준수한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안정된 추상화 원칙&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안정된 추상화 원칙(Stable Abstractions Principle, SAP)은 안정성(stability)과 추상화 정도(abstractness) 사이의 관계를 정의한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;안정된 컴포넌트는&lt;span&gt;&amp;nbsp;&lt;/span&gt;추상 컴포넌트여야 하며, 안정성이 컴포넌트를 확장하는 일을 방해해서는 안 된다고 말한다.&lt;/li&gt;
&lt;li&gt;불안정한 컴포넌트는 반드시&lt;span&gt;&amp;nbsp;&lt;/span&gt;구체 컴포넌트여야 하며, 불안정하므로 컴포넌트 내부의 구체적인 코드를 쉽게 변경할 수 있어야 하기 때문이다.&lt;/li&gt;
&lt;li&gt;SAP와 SDP를 결합하면 컴포넌트에 대한 DIP나 마찬가지가 된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실제로 SDP에서는 의존성이 반드시 안정성의 방향으로 향해야 한다고 말하고&lt;/li&gt;
&lt;li&gt;SDP에서는 안정성이 결국 추상화를 의미한다고 말하기 때문이다.&lt;/li&gt;
&lt;li&gt;따라서&lt;span&gt;&amp;nbsp;&lt;/span&gt;의존성은 추상화의 방향으로 향하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;핵심은,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;안정적인 컴포넌트라면 반드시 인터페이스와 추상 클래스로 구성되어 쉽게 확장할 수 있어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;추상화 정도 측정하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 컴포넌트의 클래스 총 수 대비 인터페이스와 추상 클래스의 개수를 단순히 계산한 값이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;NC: 컴포넌트의 클래스 개수&lt;/li&gt;
&lt;li&gt;Na: 컴포넌트의 추상 클래스와 인터페이스의 개수&lt;/li&gt;
&lt;li&gt;A: 추상화 정도&lt;span&gt;&amp;nbsp;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A = Na / Nc&lt;/li&gt;
&lt;li&gt;A가 0이면 추상 클래스가 한개도 없고, 1이면 오로지 추상 클래스만 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주계열&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A(추상화 정도) /&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;I&lt;/span&gt;(안정성) 그래프&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최고로 안정적이며 추상화된&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는 좌측상단 (0,1)에 해당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최고로 불안정적이며 구체화된&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는 우측하단 (1,0)에 해당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 모든&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트가 이 두 지점에 위치하지는 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어 추상클래스는 흔히 또 다른 추상클래스를 파생한다. 이 파생된 클래스는 추상적이면서도 최고로 안정적인것은 아니다. 의존성으로 인해 안정성이 감소했기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 모든&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트가 두 지점에 위치한다는 규칙을 강요할 수 없으므로 A/I 그래프상 합리적인 지점을 정의하는 점의 궤적이 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;고통의 구역&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(0,0) 주변 구역에 위치한&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는 매우 안정적이며 구체적이다. 추상적이지 않으므로 확장할 수 없고, 안정적이므로 변경하기도 상당히 어렵다. (0,0) 주변 영역은 배제해야 할 구역이며, 고통의 구역이라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(0,0) 근처에 위치한 또 다른 소프트웨어로는 구체적인 유틸리티 라이브러리중&lt;span&gt;&amp;nbsp;&lt;/span&gt;String컴포넌트를 예로 들 수 있다. 이&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는 광범위하게 사용되므로 수정해버리면 혼란을 초래한다. 따라서 변동성이 거의 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변동성이 없는 컴포넌트는 (0,0) 구역에 위치했더라도 해롭지 않다. 변동될 가능성이 없기 때문에 변동성이 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트만 고통의 구역에서 문제가 된다고 정의할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;쓸모없는 구역&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;(1,1&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;) 주변의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;컴포넌트&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;는 최고로 추상적이지만, 누구도 이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;컴포넌트&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;에 의존하지 않기 때문에 쓸모없는 구역이라고 불린다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;배제 구역 벗어나기&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 배제 구역으로부터 가능한 멀리 떨어진 궤적은 (1,0)과 (0,1)을 잇는 선분인 주계열이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주계열에 위치한&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는 자신의 안정성에 비해 '너무 추상적'이지도 않고, 추상화 정도에 비해 '너무 불안정'하지도 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트가 위치할 수 있는 가장 바람직한 지점은 주계열의 두 종점이지만 저자는 경험을 통해 대규모 시스템에서 소수의 일부 컴포넌트는 완벽히 추상적이거나 완전하게 안정적일 수 없다고 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주계열과의 거리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 주계열로부터의 거리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D&lt;span&gt;&amp;nbsp;&lt;/span&gt;= |&lt;span&gt;&amp;nbsp;&lt;/span&gt;A&lt;span&gt;&amp;nbsp;&lt;/span&gt;+&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;I&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;- 1 |&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0 &amp;le;&lt;span&gt;&amp;nbsp;&lt;/span&gt;D&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;le; 1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D가 0이면&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트가 주계열 바로위에 위치하며, 1이면 주계열로부터 가장 멀리 위치함을 뜻한다.&lt;/p&gt;</description>
      <category>Clean Architecture</category>
      <category>Clean Architecture</category>
      <category>component</category>
      <category>설계</category>
      <category>안정성</category>
      <category>의존성</category>
      <category>추상화</category>
      <category>컴포넌트</category>
      <category>컴포넌트 결합</category>
      <category>컴포넌트 의존성</category>
      <category>클린 아키텍처</category>
      <author>라크라꾸</author>
      <guid isPermaLink="true">https://lakue.tistory.com/79</guid>
      <comments>https://lakue.tistory.com/79#entry79comment</comments>
      <pubDate>Sun, 6 Feb 2022 13:32:16 +0900</pubDate>
    </item>
    <item>
      <title>Clean Architecture 스터디[13장] 컴포넌트 응집도</title>
      <link>https://lakue.tistory.com/78</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;컴포넌트란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트는 배포할 수 있는 가장 작은 단위&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔히 .jar(java archive resource)이 컴포넌트에 해당&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트를 서로 링크하여 실행 가능한 파일이나 .war파일과 같은 단일 아카이브 파일로도 만듦&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 설계된&lt;span&gt;&amp;nbsp;&lt;/span&gt;컴포넌트는 독립적으로 배포, 개발이 가능해야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;REP 재사용/릴리즈 등가 원칙&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&quot;재사용단위는 릴리즈 단위와 같다.&quot;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1643988533813&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dependencies {
	...
    //Lottie
    implementation 'com.airbnb.android:lottie:4.2.0'
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자는 Maven, Gradle와 같은 모듈 관리 도구를 사용하여 다음과 같이 다른사람들이 만들어 놓은 라이브러리를 적용해 재사용을 한다. 만약, Maven이나 Gradle를 통해 라이브러리를 가져오는데, 릴리스 번호가 부여되지 않는다면, 컴포넌트의 호환성을 보증할 방법이 없어지게 된다.&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;REP를 소프트웨어 설계와 아키텍쳐 관점에서 보게되면 단일&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;컴포넌트&lt;/b&gt;는 단순히 뒤죽박죽 임의로 선택된 클래스와 모듈로 구성되어서는 안된다.&lt;span&gt;&amp;nbsp;&lt;/span&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;span&gt;&amp;nbsp;&lt;/span&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;h2 data-ke-size=&quot;size26&quot;&gt;CCP 공통 폐쇄 원칙&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;동일한 이유로 동일 시점에 변경되는 클래스를 같은 컴포넌트로 묶어라&lt;br /&gt;서로 다른 시점에 다른 이유로 변경되는 클래스는 다른 컴포넌트로 분리하라.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일책임원칙(SRP)가 Class수준이라면, CCP는 컴포넌트 수준의 원칙이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;CCP를 통해 단일 컴포넌트로 제안하면, 해당 컴포넌트만 재배포 하면 되기 때문에 소프트웨어를 릴리즈, 재검증, 배포하는 일과 관련된 작업량을 최소화할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;CCP는, 클래스는 변경에 닫혀있고 확장에는 열려있어야한다는 OCP(개방 폐쇄원칙)와도 밀접한 관련이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CRP 공통 재사용 원칙&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;컴포넌트 사용자들을 필요하지 않는 것에 의존하게 강요하지 말라.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공통 재사용 원칙도 클래스와 모듈을 어느 컴포넌트에 위치시킬지 결정할 때 도움되는 원칙이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대체로 재사용 가능한 클래스는 재사용 모듈의 일부로써 모듈내 다른 클래스와 상호작용 하는 경우가 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;A라는 컴포넌트가 B라는 컴포넌트를 사용하게 되면, A는 B에 의존적인 컴포넌트가 된다.&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;이 같은 의존성으로 인해 사용되는 B컴포넌트가 변경될 때마다 사용하는 A컴포넌트도 변경해야 할 가능성이 높다. 또는, 사용하는 컴포넌트를 변경하지 않더라도, 재컴파일, 재검증, 재배포를 해야 하는 가능성은 여전히 남아있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 방지하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;인터페이스 분리원칙(ISP)에서는 사용하지 않는 메서드가 있는 클래스에 의존하지 말라고 했다면, CRP는 사용하지 않는 클래스를 가진 컴포넌트에 의존하지 말라고 조언한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;컴포넌트 응집도에 대한 균형 다이어그램&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;imagedd.png&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dJgfx5/btrsysIiWHj/7ePnGmh3dquJWduTlAdkN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dJgfx5/btrsysIiWHj/7ePnGmh3dquJWduTlAdkN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dJgfx5/btrsysIiWHj/7ePnGmh3dquJWduTlAdkN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdJgfx5%2FbtrsysIiWHj%2F7ePnGmh3dquJWduTlAdkN1%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;821&quot; height=&quot;556&quot; data-filename=&quot;imagedd.png&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;556&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;REP와 CCP는 포함원칙으로, 컴포넌트의 크기를 크게 만들고, CRP는 배제의 원칙으로 컴포넌트를 작게 만든다.&lt;/li&gt;
&lt;li&gt;REP - 릴리즈에 따라 컴포넌트의 크기가 커짐&lt;/li&gt;
&lt;li&gt;CCP - 단일 컴포넌트가 가지고 있는 책임에 대한 변경이 올 때 커짐&lt;/li&gt;
&lt;li&gt;CRP - 컴포넌트내에 재사용 클래스의 수많은 의존성에 의해 내부의 응집도가 커지므로, 컴포넌트의 크기는 작아짐&lt;/li&gt;
&lt;li&gt;REP와 CRP에만 중점을 두면, 변경이 생겼을 때, 많은 컴포넌트에 영향을 미친다.&lt;/li&gt;
&lt;li&gt;CCP와 REP에 집중하면 불필요한 릴리즈가 많아진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;프로젝트의 컴포넌트 구조는 시간과 성숙도에 따라 변한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;어느 클래스들을 묶어서 컴포넌트를 만들지 결정할 때, 재사용성과 개발가능성이라는 상충하는 힘을 반드시 고려해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Clean Architecture</category>
      <category>CCP</category>
      <category>Clean Architecture</category>
      <category>component</category>
      <category>CRP</category>
      <category>Rep</category>
      <category>study</category>
      <category>스터디</category>
      <category>응집도</category>
      <category>컴포넌트</category>
      <category>클린 아키텍처</category>
      <author>라크라꾸</author>
      <guid isPermaLink="true">https://lakue.tistory.com/78</guid>
      <comments>https://lakue.tistory.com/78#entry78comment</comments>
      <pubDate>Sat, 5 Feb 2022 01:52:57 +0900</pubDate>
    </item>
  </channel>
</rss>