<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Liam 일지</title>
    <link>https://liam-aos.tistory.com/</link>
    <description>이직을 위한 스터디 공부</description>
    <language>ko</language>
    <pubDate>Tue, 12 May 2026 17:13:58 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Liam의 일지</managingEditor>
    <image>
      <title>Liam 일지</title>
      <url>https://tistory1.daumcdn.net/tistory/4691143/attach/b34ed49d563945e9b36e8b805a3aac9e</url>
      <link>https://liam-aos.tistory.com</link>
    </image>
    <item>
      <title>옵저버 패턴</title>
      <link>https://liam-aos.tistory.com/30</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;옵저버 패턴이란&lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;옵저버 패턴은 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&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;b&gt;&lt;span&gt;일대다 객체 의존 관계를 구성&lt;/span&gt;&lt;/b&gt;&lt;span&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;/span&gt;&lt;b&gt;&lt;span&gt;상대 클래스나 객체에 의존하지 않으면서 데이터 변경을 통보하고자 할 때&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;&lt;span&gt; 유용하다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ex) 새로운 파일이 추가되거나 기존 파일이 삭제되었을 때 탐색기는 다른 탐색기에게 즉시 변경을 통보해야한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;옵저버 패턴은 통보 대상 객체의 관리를 Subject 클래스와 Observer 인터페이스로 일반화한다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;이를 통해 데이터 변경을 통보하는 클래스(ConcreteSubject)는 통보 대상 클래스나 객체에(ContcreteObserver)에 대한 의존성을 없앨 수 있다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;결과적으로 통보 대상 클래스나 대상 객체의 변경에도 통보하는 클래스(ConcreteSubject)를 수정 없이 그대로 사용할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;2325&quot; data-origin-height=&quot;750&quot; data-filename=&quot;observer_table.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIb31N/btq8QqoZqi3/Y6ujhKLgBV1zHPjDshhZeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIb31N/btq8QqoZqi3/Y6ujhKLgBV1zHPjDshhZeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIb31N/btq8QqoZqi3/Y6ujhKLgBV1zHPjDshhZeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIb31N%2Fbtq8QqoZqi3%2FY6ujhKLgBV1zHPjDshhZeK%2Fimg.png&quot; data-origin-width=&quot;2325&quot; data-origin-height=&quot;750&quot; data-filename=&quot;observer_table.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;역할이 수행하는 작업&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Observer&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;데이터의 변경을 통보 받는 인터페이스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;즉, Subject에서는 Observer 인터페이스의 update메서드를 호출함으로써 ConcreteSubject의 데이터 변경을 ConcreteObserver에게 통보한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Subject&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ConcreteObserver 객체를 관리하는 요소&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Observer 인터페이스를 참조해서 ConcreteObserver를 관리하므로 ConcreteObserver의 변화에 독립적일 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;ConcreteSubject&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;변경 관리 대상이 되는 데이터가 있는 클래스(통보하는 클래스)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;데이터의 변경을 위한 메서드인 setState가 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;setState 메서드에서는 자신의 데이터인 subjectState를 변경하고 Subject의 notifyObservers 메서드를 호출해서 ConcreteObserver 객체에 변경을 통보한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;ConcreteObserver&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-mark=&quot;-&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;ConcreteSubject의 변경을 통보받는 클래스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Observer인터페이스의 update 메서드를 구현함으로써 변경을 통보받는다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;변경된 데이터는 ConcreteSubject의 get State메서드를 호출함으로써 변경을 조회한다.&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;/p&gt;
&lt;pre id=&quot;code_1625396165784&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Subject{
    public void attach(Observer o); // Subject에 Observer를 구독자로 등록한다.
    public void detach(Observer o); // Subject에 등록한 Observer의 구독을 해지한다.
    public void notify(); // Subject에서 모든 Observer에 정보를 전달한다.
}

class SubjectImpl implements Subject{
    private List&amp;lt;Observer&amp;gt; observers= new ArrayList&amp;lt;&amp;gt;();
    private Data data1;
    private Data data2;
    
    public void attach(Observer o){
        observers.add(o);
    }
    public void detach(Observer o){
        observers.remove(o);
    }
    
    public void notify(){
        //모든 옵저버를 순회하며 업데이트 적용
        for (Observer o: observers){
            o.update(this);
        }
    }
    public void setData1(Data d){
        this.data1=d;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의할점&lt;a href=&quot;https://mfamcs.netlify.app/docs/design-pattern/%EC%98%B5%EC%A0%80%EB%B2%84%20%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80#%EC%A3%BC%EC%9D%98%ED%95%A0%EC%A0%90&quot;&gt;#&lt;/a&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;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;상태는 Subject의 담당이므로 Subject와 Observer의 일대다 관계가 성립한다.&lt;/li&gt;
&lt;li&gt;예제에서는 Observer가 update를 통해 값을 전달받고 저장하지만, 상태를 굳이 저장할 필요가 없는 경우에는 상태를 저장하지 않아도 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Notify를 누가 호출해야할지&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GoF는 다음 두 가지 방법 중에서 선택하라고 권유한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Subject에서 변경이 발생할 때, 변경을 저장하는 메소드가 Notify()를 호출하는 방법.&lt;/li&gt;
&lt;li&gt;사용자(main 등)가 적절한 시기에 Notify()를 호출하는 방법.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Observer의 행위가 Subject에 영향을 주는 경우&lt;/b&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Subject가 notify를 호출한다.&lt;/li&gt;
&lt;li&gt;Observer의 update가 호출된다.&lt;/li&gt;
&lt;li&gt;Observer::update 실행도중 Subject에 영향을 준다.&lt;/li&gt;
&lt;li&gt;Goto 1&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;만약 Observer의 행위가 Subject에 영향을 주는 로직이 있다면, 무한 루프가 발생할 수 있으므로 주의할 필요가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;관련 면접질문&lt;a href=&quot;https://mfamcs.netlify.app/docs/design-pattern/%EC%98%B5%EC%A0%80%EB%B2%84%20%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80#%EA%B4%80%EB%A0%A8-%EB%A9%B4%EC%A0%91%EC%A7%88%EB%AC%B8&quot;&gt;#&lt;/a&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;-&amp;gt; Subject와 observer가 느슨하게 결합되어 있는 객체 디자인을 제공할 수 있다. 그로인해 옵저버의 추가, 제거가 자유로워 지고 새로운 형식의 옵저버를 추가하기도 쉬워진다. 예를 들면 Android의 EventListener처럼 대부분의 이벤트들이 옵저버 패턴 방식으로 사용되고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고 자료:&lt;a href=&quot;https://mfamcs.netlify.app/docs/design-pattern/%EC%98%B5%EC%A0%80%EB%B2%84%20%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80#%EC%B0%B8%EA%B3%A0-%EC%9E%90%EB%A3%8C&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2018/07/08/observer-pattern.html&quot;&gt;옵저버 패턴&amp;nbsp; :&lt;/a&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2018/07/08/observer-pattern.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gmlwjd9405.github.io/2018/07/08/observer-pattern.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS</category>
      <category>CS</category>
      <category>Observer</category>
      <category>디자인패턴</category>
      <category>옵저버패턴</category>
      <author>Liam의 일지</author>
      <guid isPermaLink="true">https://liam-aos.tistory.com/30</guid>
      <comments>https://liam-aos.tistory.com/30#entry30comment</comments>
      <pubDate>Sun, 4 Jul 2021 19:57:12 +0900</pubDate>
    </item>
    <item>
      <title>안드로이드 4대 Component</title>
      <link>https://liam-aos.tistory.com/29</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;안드로이드의 4대 컴포넌트란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;안드로이드의 주요 4대 컴포넌트는 액티비티(Activity), 서비스(Service), 브로드캐스트 리시버(Broadcase Receiver), 콘텐츠 프로바이더(Content Provider)를 말합니다. 각 컴포넌트들은 하나의 독립된 형태로 존재하며, 정해진 역할을 수행합니다. 또한 각 컴포넌트들은 인텐트(Intent)라는 일종의 메시지 객체를 사용하여 상호 통신을 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;592&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8abl5/btq4RMRfHuj/R8LIDMnk2LPRbDokolMbK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8abl5/btq4RMRfHuj/R8LIDMnk2LPRbDokolMbK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8abl5/btq4RMRfHuj/R8LIDMnk2LPRbDokolMbK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8abl5%2Fbtq4RMRfHuj%2FR8LIDMnk2LPRbDokolMbK0%2Fimg.png&quot; data-origin-width=&quot;678&quot; data-origin-height=&quot;592&quot; data-ke-mobilestyle=&quot;widthOrigin&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;액티비티(Activity)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;액티비티는 UI화면을 담당하는 컴포넌트입니다.&lt;/li&gt;
&lt;li&gt;안드로이드 애플리케이션은 반드시 하나의 액티비티를 가지고 있어야합니다.&lt;/li&gt;
&lt;li&gt;각 액티비티는 매니페스트파일에 등록되어있어야 합니다.&lt;/li&gt;
&lt;li&gt;액티비티는 하나 이상의 view를 가질 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;서비스(Service)&lt;/b&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;UI를 가지고 있지 않습니다.&lt;/li&gt;
&lt;li&gt;한번 시작된 서비스는 애플리케이션이 종료되고 다른 애플리케이션으로 이동해도 계속 백그라운드에서 실행됩니다.&lt;/li&gt;
&lt;li&gt;모든 서비스는 Service 클래스를 상속받아서 작성됩니다.&lt;/li&gt;
&lt;li&gt;네트워크를 통하여 데이터를 받아올 수도 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;방송수신자(Broadcast Receiver)&lt;/b&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;일반적으로 UI를 가지고 있지 않습니다.&lt;/li&gt;
&lt;li&gt;단말기에서 발생하는 일 중에서 애플리케이션이 알아야 하는 상황이 발생하면 방송을 해줍니다.&lt;/li&gt;
&lt;li&gt;수신기(Broadcast Receiver)를 통해 상황을 감지하고 적절한 작업을 수행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;컨텐츠 제공자(Content Provider)&lt;/b&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;데이터는 파일 시스템이나 SQLite 데이터베이스, 웹상에 저장될 수 있습니다.&lt;/li&gt;
&lt;li&gt;컨텐츠 제공자를 통해서 다른 애플리케이션의 데이터를 쿼리하거나 변경가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android</category>
      <author>Liam의 일지</author>
      <guid isPermaLink="true">https://liam-aos.tistory.com/29</guid>
      <comments>https://liam-aos.tistory.com/29#entry29comment</comments>
      <pubDate>Thu, 13 May 2021 19:09:24 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 가장 긴 팰린드롬</title>
      <link>https://liam-aos.tistory.com/28</link>
      <description>&lt;p&gt;&lt;b&gt;문제 설명&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;앞뒤를 뒤집어도 똑같은 문자열을 팰린드롬(palindrome)이라고 합니다.&lt;br /&gt;문자열 s가 주어질 때, s의 부분문자열(Substring)중 가장 긴 팰린드롬의 길이를 return 하는 solution 함수를 완성해 주세요.&lt;/p&gt;
&lt;p&gt;예를들면, 문자열 s가 &quot;abcdcba&quot;이면 7을 return하고 &quot;abacde&quot;이면 3을 return합니다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;제한사항&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;문자열 s의 길이 : 2,500 이하의 자연수&lt;/li&gt;
&lt;li&gt;문자열 s는 알파벳 소문자로만 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1620625322518&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def palindrome(string):
    if len(string)&amp;lt;=1:
        return True
    
    if string[0]==string[-1]:
        return palindrome(string[1:-1])
    else:
        return False
    
def solution(s):
    answer = 0
    check=False
    for i in range(len(s),0,-1):
        for j in range(len(s)):
            cut=s[j:j+i]
            check=palindrome(cut)
            if check==True:
                return len(cut)
            if j+i&amp;gt;=len(s):
                break
                

    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;처음 코드는 재귀를 통해서 가장 긴 문자열에서 순차적으로 길이를 줄여가며 palindrome을 검사했습니다.&lt;/p&gt;
&lt;p&gt;하지만 이럴경우 정확도는 전부 통과가 되지만 효율성에서 1개의 케이스가 런타임이 발생합니다..&lt;/p&gt;
&lt;pre id=&quot;code_1620625288008&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def palindrome(string):
    if len(string) &amp;lt;= 1:
        return True

    start = 0
    end = len(string) - 1

    for i in range(len(string) // 2):
        if string[start + i] != string[end - i]:
            return False

    return True


def solution(s):
    answer = 0
    check = False
    for i in range(len(s), 0, -1):
        for j in range(len(s)):
            cut = s[j:j + i]
            if palindrome(cut) == True:
                return len(cut)
            if j + i &amp;gt;= len(s):
                break

    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;위와 같은 런타임을 없애기 위해 가장 긴 문자열에서 길이를 줄여가며 palindrome을 검사하는 것은 동일하지만&lt;/p&gt;
&lt;p&gt;재귀를 통한것이 아닌 주어진 문자열의 반 만큼을 for문을 통해 검사를 하여 효율성을 통과했습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;사용언어: python&lt;/p&gt;
&lt;p&gt;문제출처: &lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/12904&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;programmers.co.kr/learn/courses/30/lessons/12904&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1620625439606&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;코딩테스트 연습 - 가장 긴 팰린드롬&quot; data-og-description=&quot;앞뒤를 뒤집어도 똑같은 문자열을 팰린드롬(palindrome)이라고 합니다. 문자열 s가 주어질 때, s의 부분문자열(Substring)중 가장 긴 팰린드롬의 길이를 return 하는 solution 함수를 완성해 주세요. 예를들&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/12904&quot; data-og-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/12904&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/uO4X5/hyJ9Vsf9if/FPghbhZjofSgHCDwclWT5k/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/bSd3ji/hyJ7YYqXlw/p7PHOFNe2sitPzBKRNfvV0/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/12904&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/12904&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/uO4X5/hyJ9Vsf9if/FPghbhZjofSgHCDwclWT5k/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/bSd3ji/hyJ7YYqXlw/p7PHOFNe2sitPzBKRNfvV0/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;코딩테스트 연습 - 가장 긴 팰린드롬&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;앞뒤를 뒤집어도 똑같은 문자열을 팰린드롬(palindrome)이라고 합니다. 문자열 s가 주어질 때, s의 부분문자열(Substring)중 가장 긴 팰린드롬의 길이를 return 하는 solution 함수를 완성해 주세요. 예를들&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm(백준)</category>
      <category>level3</category>
      <category>알고리즘</category>
      <category>재귀</category>
      <category>프로그래머스</category>
      <author>Liam의 일지</author>
      <guid isPermaLink="true">https://liam-aos.tistory.com/28</guid>
      <comments>https://liam-aos.tistory.com/28#entry28comment</comments>
      <pubDate>Mon, 10 May 2021 14:44:14 +0900</pubDate>
    </item>
    <item>
      <title>백준 1926번 그림</title>
      <link>https://liam-aos.tistory.com/27</link>
      <description>&lt;h1 contenteditable=&quot;true&quot;&gt;&lt;span&gt;그림 성공분류&lt;/span&gt;&lt;/h1&gt;
&lt;p&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;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;2 초&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;128 MB&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;7594&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;3370&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;2385&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;span&gt;43.269%&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 contenteditable=&quot;true&quot;&gt;&lt;span&gt;문제&lt;/span&gt;&lt;/h2&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;어떤 큰 도화지에 그림이 그려져 있을 때, 그 그림의 개수와, 그 그림 중 넓이가 가장 넓은 것의 넓이를 출력하여라. 단, 그림이라는 것은 1로 연결된 것을 한 그림이라고 정의하자. 가로나 세로로 연결된 것은 연결이 된 것이고 대각선으로 연결이 된 것은 떨어진 그림이다. 그림의 넓이란 그림에 포함된 1의 개수이다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 contenteditable=&quot;true&quot;&gt;&lt;span&gt;입력&lt;/span&gt;&lt;/h2&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;첫째 줄에 도화지의 세로 크기 n(1 &amp;le; n &amp;le; 500)과 가로 크기 m(1 &amp;le; m &amp;le; 500)이 차례로 주어진다. 두 번째 줄부터 n+1 줄 까지 그림의 정보가 주어진다. (단 그림의 정보는 0과 1이 공백을 두고 주어지며, 0은 색칠이 안된 부분, 1은 색칠이 된 부분을 의미한다)&lt;/span&gt;&lt;/p&gt;
&lt;h2 contenteditable=&quot;true&quot;&gt;&lt;span&gt;출력&lt;/span&gt;&lt;/h2&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;첫째 줄에는 그림의 개수, 둘째 줄에는 그 중 가장 넓은 그림의 넓이를 출력하여라. 단, 그림이 하나도 없는 경우에는 가장 넓은 그림의 넓이는 0이다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 contenteditable=&quot;true&quot;&gt;&lt;span&gt;문제설명&lt;/span&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span&gt;주어진 도화지에서 그려져 있는 곳 1마다 deque를 통한 탐색을 진행하여 그림의 넓이를 return 하고 이를 최대값과 비교합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;deque를 통한 탐색이 진행된 횟수는 그림의 개수이고 전체의 도화지가 탐색이 완료되었을 때의 max_draw가 최대 넒이가 됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1620623522555&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import deque


def solution(arr, x, y, visit):
    dx = [-1, 0, 1, 0]
    dy = [0, 1, 0, -1]

    cnt = 1  # 넓이
    q = deque()

    q.append([x, y])
    visit[x][y] = True

    while q:
        cx, cy = q.popleft()
        for i in range(4):
            nx = cx + dx[i]
            ny = cy + dy[i]
            if 0 &amp;lt;= nx &amp;lt; n and 0 &amp;lt;= ny &amp;lt; m and visit[nx][ny] == False and arr[nx][ny]==1:
                visit[nx][ny] = True
                cnt += 1
                q.append([nx, ny])

    return cnt


n, m = map(int, input().split())
result = 0  # 총 그림의 개수
max_draw = 0  # 가장 큰 그림의 넒이
draw = []
visit = [[False] * m for _ in range(n)]

for i in range(n):
    draw.append(list(map(int, input().split())))


for i in range(n):
    for j in range(m):
        if draw[i][j] == 1 and visit[i][j] == False:
            result += 1
            max_draw = max(solution(draw, i, j, visit), max_draw)

print(result)
print(max_draw)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;사용언어: python&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;문제출처: &lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1926&quot;&gt;https://www.acmicpc.net/problem/1926&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1620623535532&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;1926번: 그림&quot; data-og-description=&quot;어떤 큰 도화지에 그림이 그려져 있을 때, 그 그림의 개수와, 그 그림 중 넓이가 가장 넓은 것의 넓이를 출력하여라. 단, 그림이라는 것은 1로 연결된 것을 한 그림이라고 정의하자. 가로나 세로&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/1926&quot; data-og-url=&quot;https://www.acmicpc.net/problem/1926&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bTJKLm/hyJ77A618Q/RP3XpqKBzlKQG7KYFanuk1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1926&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/1926&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bTJKLm/hyJ77A618Q/RP3XpqKBzlKQG7KYFanuk1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;1926번: 그림&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;어떤 큰 도화지에 그림이 그려져 있을 때, 그 그림의 개수와, 그 그림 중 넓이가 가장 넓은 것의 넓이를 출력하여라. 단, 그림이라는 것은 1로 연결된 것을 한 그림이라고 정의하자. 가로나 세로&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm(백준)</category>
      <category>deque</category>
      <category>dfs</category>
      <category>그림</category>
      <category>백준</category>
      <category>알고리즘</category>
      <author>Liam의 일지</author>
      <guid isPermaLink="true">https://liam-aos.tistory.com/27</guid>
      <comments>https://liam-aos.tistory.com/27#entry27comment</comments>
      <pubDate>Mon, 10 May 2021 14:12:27 +0900</pubDate>
    </item>
    <item>
      <title>RESTful API란?</title>
      <link>https://liam-aos.tistory.com/26</link>
      <description>&lt;p&gt;&lt;span&gt;RestAPI(RESTful API)란 REST아키텍처의 제약 조건을 준수하는 애플리케이션 프로그래밍 인터페이스이다.&lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;전반적인 이해를 위해 REST와 RESTful의 개념에 대해서 설명하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 contenteditable=&quot;true&quot;&gt;&lt;span&gt;REST란&lt;/span&gt;&lt;/h3&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;REST의 정의&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;&quot;Representational State Transfer&quot;의 약자&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;월드 와이드 웹(www)과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 개발 아키텍처의 한 형식&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;REST는 기본적으로 웹의 기존 기술과 HTTP 프로토콜을 그대로 활용하기 때문에 웹의 장점을 최대한 활용할 수 있는 아키텍처 스타일이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;REST는 네트워크 상에서 Client와 Server 사이의 통신 방식 중 하나이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;REST의 구체적인 개념&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;HTTP URI(Uniform Resource Identifier)를 통해 자원(Resource)을 명시하고, HTTP Method(Post, Get, Put, Delete)를 통해 해당 자원에 대한 CRUD Operation을 적용하는 것을 의미한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;즉, REST는 자원 기반의 구조(ROA, Resource Oreiented Architecture) 설계의 중심에 Resource가 있고 HTTP Method를 통해 Resource를 처리하도록 설계된 아키텍쳐를 의미한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;웹 사이트의 이미지, 텍스트, DB 내용 등의 모든 자원에 고유한 ID인 HTTP URI를 부여한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;REST 장단점&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;장점&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;여러 가지 서비스 디자인에서 생길 수 있는 문제를 최소하해준다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Hypermedia API의 기본을 충실히 지키면서 범용성을 보장한다.(Hypermedia란 하나의 컨텐츠가 텍스트나 이미지, 사운드와 같은 다양한 포맷의 컨텐츠를 링크하는 개념이다.)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;HTTP 프로토콜의 표준을 최대한 활용하여 여러 추가적인 장점을 함께 가져갈 수 있게 해준다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;단점&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;브라우저를 통해 테스트할 일이 많은 서비스라면 쉽게 고칠 수 있는 URL보다 Header값이 왠지 더 어렵게 느껴진다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;구형 브라우저가 아직 제대로 지원해주지 못하는 부분이 존재한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;REST가 필요한 이유&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;'애플리케이션 분리 및 통합'&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;다양한 클라이언트의 등장&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;최근의 서버 프로그램은 다양한 브라우저와 안드로이드, 아이폰과 같은 모바일 디바이스에서도 통신이 가능해야한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;REST의 구성 요소&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;자원(Resource):URI&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;모든 자원에 고유한 ID가 존재하고, 이 자원은 Server에 존재한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;자원을 구별하는 ID는 HTTP URI다. (ex. '/groups/:group_id')&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Client는 URI를 이용해서 자원을 지정하고 해당 자원의 정보에 대한 조작을 Server에 요청한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;행위: HTTP Method&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;HTTP 프로토콜의 Method를 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;HTTP 프로토콜은 &lt;/span&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;GET, POST, PUT, DELELE, HEAD&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;&lt;span&gt;와 같은 메서드를 제공한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;표현(Representation of Resource)&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;REST에서 하나의 자원은 JSON, XML, TEXT, RSS 등 여러 형태의 Representation으로 나타내어 질 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;JSON 혹은 XML를 통해 데이터를 주고 받는 것이 일반적이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;REST 특징&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;Server-client구조&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Stateless(무상태성) -&amp;gt; 작업을 위한 상태정보를 따로 저장하고 관리하지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Cacheable(캐시가능) -&amp;gt; REST의 가장 큰 특징은 HTTP라는 기존 웹 표준을 그대로 사용하기 때문에, 웹에서 사용하는 기존 인프라를 사용할 수 있다. 따라서 HTTP가 가진 캐싱 기능을 적용할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Self-descriptiveness(자체 표현 구조) -&amp;gt; REST API 메시지만 보고도 이를 쉽게 이해할 수 있는 자체 표현 구조로 되어 있다는 뜻&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;계층형 구조 -&amp;gt; REST 서버는 다중 계층으로 구성될 수 있으며, 보안, 로드밸런싱, 암호화 계층을 추가해 구조상의 유연성을 둘 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Uniform(유니폼 인터페이스) -&amp;gt; 특정 언어나 기술에 종속되지 않고 모든 플랫폼에 사용할 수 있으며, URI로 지정한 리소스에 대한 조작이 가능한 아키텍처 스타일을 의미한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 contenteditable=&quot;true&quot;&gt;&lt;span&gt;REST API란&lt;/span&gt;&lt;/h3&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;REST API&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;REST API의 정의&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;REST 기반으로 서비스 API를 구현한 것&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;REST API의 특징&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;REST는 HTTP 표준을 기반으로 구현하므로, HTTP를 지원하는 프로그램 언어로 클라이언트, 서버를 구현할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;즉, REST API를 제작하면 델파이 클라이언트 뿐 아니라, 자바, C#, 웹 등을 이용해 클라이언트를 제작할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;REST API 설계 규칙&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;URI는 정보의 자원을 표현해야한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;자원에 대한 행위는 HTTP Method(Get, Put, Post, Delete 등)로 표현한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;소문자 사용 (최소한 대소문자 구분)한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;슬래시 구분자는 계층 관계를 나타내는데 사용한다. (ex. '/groups/:group_id')&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;URI의 마지막 문자로 슬래시를 포함하지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;하이픈(-)은 URI 가독성을 높이는데 사용한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;밑줄(_)은 URI에 사용하지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;RESTful&lt;/span&gt;&lt;/p&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;RESTful 의 개념&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;RESTful은 일반적으로 REST라는 아키텍처를 구현하는 웹 서시브를 나타내기 위해 사용되는 용어이다.&lt;/span&gt;&lt;/li&gt;
&lt;li contenteditable=&quot;true&quot;&gt;&lt;span&gt;-&amp;gt; 즉, REST 원리를 따르는 시스템은 RESTful이란 용어로 지칭된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;RESTful은 REST를 REST답게 쓰기 위한 방법으로, 누군가가 공식적으로 발표한 것이 아니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;RESTful의 목적&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;이해하기 쉽고 사용하기 쉬운 REST API를 만드는 것&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;RESTful API를 구현하는 근본적인 목적이 퍼포먼스 향상에 있는게 아니라, 일관적인 컨벤션을 통한 API의 이해도 및 호환성을 높이는게 주 동기이니, 퍼포먼스가 중요한 상황에서는 굳이 RESTful API를 구현할 필요는 없다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;RESTful 하지 못한 경우&lt;/span&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;CRUD 기능을 모두 POST로만 처리하는 API&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;route에 resource, id외의 정보다 들어가는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;응답에 대한 메타데이터가 Body에 포함된 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;URL에 동사가 포함되어 있는 경우&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;URL에 RPC 호출 메서드 명이 있는 경우 (ex. &lt;/span&gt;&lt;span&gt;&lt;span&gt;**&lt;/span&gt;&lt;b&gt;&lt;span&gt;?action=createReservation&lt;/span&gt;&lt;/b&gt;&lt;span&gt;**&lt;/span&gt;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 contenteditable=&quot;true&quot;&gt;&lt;span&gt;면접 예상 질문&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;1. REST란 무엇이고, RESTful 하게 API를 디자인한다는 것은 무엇인가요?&lt;/span&gt;&lt;/p&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;REST는 Representational State Transfer의 약자입니다. 간단히 말해서 URI와 HTTP 메소드를 이용해 객체화된 서비스에 접근하는 것입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;RESTful 하게 API를 디자인 한다는 것은 URI를 규칙에 맞게 잘 설계했는지의 여부입니다.(설계규칙을 참고하시면 됩니다.)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;2.REST API를 사용하는 이유는 무엇인가요?&lt;/span&gt;&lt;/p&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;분산 시스템을 사용하기 위해서이다. 이를 사용하면 거대한 애플리케이션을 모듈, 기능별로 분리하기 쉬워지고 REST API를 서비스하면 어떤 다른 모듈 또는 애플리케이션이라도 상호간의 통신을 할 수 있기 때문이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;span&gt;3. HTTP Method의 종류에는 무엇이 있나요?&lt;/span&gt;&lt;/p&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;크게 GET, POST, PUT, DELETE, HEAD가 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 contenteditable=&quot;true&quot;&gt;&lt;span&gt;참고 자료&lt;/span&gt;&lt;/h3&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;&lt;a href=&quot;http://www.incodom.kr/REST&quot;&gt;http://www.incodom.kr/REST&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://ijbgo.tistory.com/20&quot;&gt;https://ijbgo.tistory.com/20&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html&quot;&gt;https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://beyondj2ee.wordpress.com/2013/03/21/%EB%8B%B9%EC%8B%A0%EC%9D%98-api%EA%B0%80-restful-%ED%95%98%EC%A7%80-%EC%95%8A%EC%9D%80-5%EA%B0%80%EC%A7%80-%EC%A6%9D%EA%B1%B0/&quot;&gt;https://beyondj2ee.wordpress.com/2013/03/21/%EB%8B%B9%EC%8B%A0%EC%9D%98-api%EA%B0%80-restful-%ED%95%98%EC%A7%80-%EC%95%8A%EC%9D%80-5%EA%B0%80%EC%A7%80-%EC%A6%9D%EA%B1%B0/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://wooaoe.tistory.com/51&quot;&gt;https://wooaoe.tistory.com/51&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>CS</category>
      <category>AOS</category>
      <category>CS</category>
      <category>REST</category>
      <category>REST API</category>
      <category>restful</category>
      <category>안드로이드</category>
      <author>Liam의 일지</author>
      <guid isPermaLink="true">https://liam-aos.tistory.com/26</guid>
      <comments>https://liam-aos.tistory.com/26#entry26comment</comments>
      <pubDate>Mon, 10 May 2021 11:50:43 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 올바른 괄호</title>
      <link>https://liam-aos.tistory.com/25</link>
      <description>&lt;p&gt;&lt;span&gt;문제 설명&lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;괄호가 바르게 짝지어졌다는 것은 '(' 문자로 열렸으면 반드시 짝지어서 ')' 문자로 닫혀야 한다는 뜻입니다. 예를 들어&lt;/span&gt;&lt;/p&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;&quot;()()&quot; 또는 &quot;(())()&quot; 는 올바른 괄호입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&quot;)()(&quot; 또는 &quot;(()(&quot; 는 올바르지 않은 괄호입니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;'(' 또는 ')' 로만 이루어진 문자열 s가 주어졌을 때, 문자열 s가 올바른 괄호이면 true를 return 하고, 올바르지 않은 괄호이면 false를 return 하는 solution 함수를 완성해 주세요.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;제한사항&lt;/span&gt;&lt;/p&gt;
&lt;ul data-mark=&quot;-&quot;&gt;
&lt;li&gt;&lt;span&gt;문자열 s의 길이 : 100,000 이하의 자연수&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;문자열 s는 '(' 또는 ')' 로만 이루어져 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1620614848765&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(s):
   
    check_s={
        ')':'(',
        '}':'{',
        ']':'['
    }

    stack=[]
    for i in s:
        if i=='(' or i =='{' or i=='[':
            stack.append(i)
        else:
            if stack:
                top=stack.pop()
                if check_s[i]!=top:
                    return False
            else: return False

    if len(stack)!=0:
        return False
    return True&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;문제설명: 괄호의 열린 부분과 닫히는 부분을 매칭 시키기위해 dictionary 자료형으로 key와 value 값을 통해서 확인을 했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;span&gt;주어진 문자열을 for문을 통해 순회하면서 열린 부분 '({[' 이 나오면 stack에 추가하고 닫힌 부분이 나오면 그 순간에 스택의 최상단이 dictionary를 통해 맞는 값일경우 pop을 시키고 아닐 경우 False를 반환합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;순회가 끝나고 stack에 남아있는 괄호가 있다면 False를 반환하도록 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;사용언어: python&lt;/span&gt;&lt;/p&gt;
&lt;p contenteditable=&quot;true&quot;&gt;&lt;span&gt;문제출처: &lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/12909?language=python3&quot;&gt;https://programmers.co.kr/learn/courses/30/lessons/12909?language=python3&lt;/a&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1620614857988&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;코딩테스트 연습 - 올바른 괄호&quot; data-og-description=&quot;괄호가 바르게 짝지어졌다는 것은 '(' 문자로 열렸으면 반드시 짝지어서 ')' 문자로 닫혀야 한다는 뜻입니다. 예를 들어 &amp;quot;()()&amp;quot; 또는 &amp;quot;(())()&amp;quot; 는 올바른 괄호입니다. &amp;quot;)()(&amp;quot; 또는 &amp;quot;(()(&amp;quot; 는 올바르지 않은&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/12909?language=python3&quot; data-og-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/12909?language=python3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/FTcD4/hyJ9QqQyoK/OckKRTNgXqCwT3eMtcMKY0/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/89hUT/hyJ7UPcknT/6GYvsllXfQspy3agOZchg0/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/12909?language=python3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/12909?language=python3&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/FTcD4/hyJ9QqQyoK/OckKRTNgXqCwT3eMtcMKY0/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/89hUT/hyJ7UPcknT/6GYvsllXfQspy3agOZchg0/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;코딩테스트 연습 - 올바른 괄호&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;괄호가 바르게 짝지어졌다는 것은 '(' 문자로 열렸으면 반드시 짝지어서 ')' 문자로 닫혀야 한다는 뜻입니다. 예를 들어 &quot;()()&quot; 또는 &quot;(())()&quot; 는 올바른 괄호입니다. &quot;)()(&quot; 또는 &quot;(()(&quot; 는 올바르지 않은&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm(백준)</category>
      <category>Stack</category>
      <category>스택</category>
      <category>알고리즘</category>
      <category>올바른 괄호</category>
      <category>프로그래머스</category>
      <author>Liam의 일지</author>
      <guid isPermaLink="true">https://liam-aos.tistory.com/25</guid>
      <comments>https://liam-aos.tistory.com/25#entry25comment</comments>
      <pubDate>Mon, 10 May 2021 11:47:57 +0900</pubDate>
    </item>
    <item>
      <title>MVVM 패턴이란?</title>
      <link>https://liam-aos.tistory.com/24</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVVM패턴&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;MVVM패턴이란 &lt;span style=&quot;color: #ee2323;&quot;&gt;Model, View, ViewModel&lt;/span&gt;의 줄임말입니다. 하나의 소프트웨어를 최대한 기능적으로 작은 단위로 나누어 테스트가 쉽고 큰 프로젝트도 상대적으로 관리하기가 좋은 구조입니다. 아래의 그림을 바탕으로 설명하면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;800&quot; height=&quot;251&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NmLDY/btq39k1q1gD/cakCe4IW4B2lv98yiHJ47k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NmLDY/btq39k1q1gD/cakCe4IW4B2lv98yiHJ47k/img.png&quot; data-alt=&quot;Mvvm 구조도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NmLDY/btq39k1q1gD/cakCe4IW4B2lv98yiHJ47k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNmLDY%2Fbtq39k1q1gD%2FcakCe4IW4B2lv98yiHJ47k%2Fimg.png&quot; width=&quot;800&quot; height=&quot;251&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Mvvm 구조도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;모든 Input은 View로 전달되며 ViewModel은 입력에 해당하는 Presentation Logic을 처리하고 View에 데이터를 전달합니다. ViewModel은 View를 따로 참조하지 않기 때문에 독립적이며 1:n의 관계를 가집니다.&lt;/p&gt;
&lt;p&gt;따라서 View는 자신이 이용할 ViewModel을 선택해 데이터를 바인딩하여 업데이트를 받게됩니다.&lt;/p&gt;
&lt;p&gt;그 후 Model이 상태 및 데이터가 변경되면 해당하는 ViewModel을 이용하는 View가 자동으로 업데이트됩니다.&lt;/p&gt;
&lt;p&gt;ViewModel은 View를 나타내기 위한 Model이자, View의 Presentation Logic을 처리합니다. MVP와 마찬가지로 M-V 사이의 의존성이 없고, MVP처럼 V-VM이 1:1관계가 아닌 독립적이기 때문에 이 둘 사이의 의존성이 없습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVVM의 특징&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;ViewModel&lt;/b&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;b&gt;View와 Model 사이의 매개체 역할을 합니다&lt;/b&gt;. 즉 Model에서 제공받은 데이터를 UI에서 필요한 정보로 가공한 뒤 View가 가져갈 수 있게 데이터 변경에 대한 &quot;이벤트&quot;를 보내게 됩니다.&lt;/li&gt;
&lt;li&gt;ViewModel과 View는 MVP 패턴과 다르게 1:n의 관계를 가질 수 있습니다.즉, 여러개의 Fragment가 하나의 ViewModel을 가질 수 있습니다.&lt;/li&gt;
&lt;li&gt;ViewModel은 View에 영향을 끼칠 수 있는 Model의 상태 관리도 담당합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;View 또는 Activity Context에 대한 레퍼런스를 가지면 안됩니다. View는 ViewModel의 레퍼런스를 가지지만 ViewModel은 View에 대한 정보가 전혀 없어야 합니다. -&amp;gt; ViewModel이 View의 레퍼런스를 가진다면 LifeCycle에 메모리누수가 발생할 수 있는데, 그 이유는 ViewModel이 destroy외의 라이프사이클에서는 메모리에서 해제되지 않기 때문입니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;앱이 백그라운드에서 죽는 경우에는 뷰모델도 함께 사라지기 때문에 이 경우에 한해서는 onSaveInstanceState를 통해 복구할 데이터를 저장해야합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;View&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Activity, Fragment, CustomView, Dialog, 등의 UI 컴포넌트를 의미합니다.&lt;/li&gt;
&lt;li&gt;View는 UI 업데이트를 위해 ViewModel과 바인딩하게 됩니다. 다른 표현으로는 View가 ViewModel에 구독을 하게되고, ViewModel의 상태가 변경되면 그 이벤트를 받아 UI를 갱신합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;View는 기본적으로 데이터를 보여주기만 해야해서 비즈니스 로직을 포함하지않지만 UI변경과 관련된 일부 로직은 포함될 수 있다.-&amp;gt; 안드로이드는 다른 플랫폼과는 다르게 LifeCycle이라는 특수한 순서를 가지고 있기 때문에 이것을 처리하는 것만으로도 View는 상당히 복잡해지기 때문이다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Model&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DataModel이라고도하며 Network, DB, SharedPreference 등 다양한 데이터 소스로부터 필요한 데이터를 준비합니다.&lt;/li&gt;
&lt;li&gt;ViewModel에서 데이터를 가져갈 수 있게 데이터를 준비하고 그에 대한 &quot;이벤트&quot;를 보냅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVVM의 장점&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;Model과 View 사이, ViewModel과 View사이의 의존성이 없으므로 유닛테스트 및 유지보수가 다른 패턴에 비해 쉽습니다.&lt;/li&gt;
&lt;li&gt;DataBinding 라이브러리를 이용함으로써 서로 간의 의존성을 낮추고, 유닛 테스트를 더욱 쉽게 작성할 수 있으며 UI 코드는 네이티브 코드에 관여하지 않아도 됩니다.&lt;/li&gt;
&lt;li&gt;중복되는 코드를 모듈화 할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVVM의 단점&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;View가 변수와 표현식 모두에 Binding될 수 있으므로 시간이 지남에 따라 관계없는 Presentation Logic이 늘어나고 이를 보완하기 위해 XML에 코드를 추가해야합니다. -&amp;gt; 이렇게 될경우 시간이 지남에 따라 관계없는 Presentation Logic이 늘어나 코드가 증가하게되고 유지보수 단계에서 어려움을 겪을 수 있습니다.&lt;/li&gt;
&lt;li&gt;ViewModel을 설계하기 어려운 문제가 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;참고 자료&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;&lt;a href=&quot;https://velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8C%A8%ED%84%B4-MVVM%EC%9D%B4-%EB%AD%98%EA%B9%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8C%A8%ED%84%B4-MVVM%EC%9D%B4-%EB%AD%98%EA%B9%8C&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1620098531955&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;안드로이드 아키텍처 패턴 - MVVM이 뭘까?&quot; data-og-description=&quot;이전 MVC, MVP에 이어서 이번에는 MVVM 패턴에 대해 간략하게 알아보겠습니다.&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8C%A8%ED%84%B4-MVVM%EC%9D%B4-%EB%AD%98%EA%B9%8C&quot; data-og-url=&quot;https://velog.io/@jojo_devstory/안드로이드-아키텍처-패턴-MVVM이-뭘까&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bJRFPV/hyJ6JERKEC/A7gi8Pe4xIDctRK1VwjMQ0/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426,https://scrap.kakaocdn.net/dn/rrWLC/hyJ418dqMo/XutR2wYbQRA2s5C7GND0p1/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426,https://scrap.kakaocdn.net/dn/XFraq/hyJ6FiambO/otz2GjZkwHfkBJeCrKysR0/img.png?width=2592&amp;amp;height=897&amp;amp;face=0_0_2592_897&quot;&gt;&lt;a href=&quot;https://velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8C%A8%ED%84%B4-MVVM%EC%9D%B4-%EB%AD%98%EA%B9%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8C%A8%ED%84%B4-MVVM%EC%9D%B4-%EB%AD%98%EA%B9%8C&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bJRFPV/hyJ6JERKEC/A7gi8Pe4xIDctRK1VwjMQ0/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426,https://scrap.kakaocdn.net/dn/rrWLC/hyJ418dqMo/XutR2wYbQRA2s5C7GND0p1/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426,https://scrap.kakaocdn.net/dn/XFraq/hyJ6FiambO/otz2GjZkwHfkBJeCrKysR0/img.png?width=2592&amp;amp;height=897&amp;amp;face=0_0_2592_897');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;안드로이드 아키텍처 패턴 - MVVM이 뭘까?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;이전 MVC, MVP에 이어서 이번에는 MVVM 패턴에 대해 간략하게 알아보겠습니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://beomseok95.tistory.com/131&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;beomseok95.tistory.com/131&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1620098539097&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;안드로이드 MVVM 패턴&quot; data-og-description=&quot;안드로이드 MVVM 패턴 MVVM의 기본 구조 MVVM의 기본 구조를 그림으로 표현한 것입니다. View는 ViewModel에게 클릭 이벤트, 필요한 데이터 요청등을 명시적으로 하고, viewModel이 notify 할때까지 기다리게&quot; data-og-host=&quot;beomseok95.tistory.com&quot; data-og-source-url=&quot;https://beomseok95.tistory.com/131&quot; data-og-url=&quot;https://beomseok95.tistory.com/131&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cF2RzQ/hyJ4UabohX/HTUoiXyu2df92gaKFvQZq1/img.png?width=800&amp;amp;height=251&amp;amp;face=0_0_800_251,https://scrap.kakaocdn.net/dn/bQHriU/hyJ4ZP9uOY/fQj97qqlK7TkysBUoK0ktK/img.png?width=800&amp;amp;height=251&amp;amp;face=0_0_800_251,https://scrap.kakaocdn.net/dn/eHSTVh/hyJ480AyGB/X4PHqTUDXx9dS5J5AZ2VDK/img.png?width=800&amp;amp;height=251&amp;amp;face=0_0_800_251&quot;&gt;&lt;a href=&quot;https://beomseok95.tistory.com/131&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://beomseok95.tistory.com/131&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cF2RzQ/hyJ4UabohX/HTUoiXyu2df92gaKFvQZq1/img.png?width=800&amp;amp;height=251&amp;amp;face=0_0_800_251,https://scrap.kakaocdn.net/dn/bQHriU/hyJ4ZP9uOY/fQj97qqlK7TkysBUoK0ktK/img.png?width=800&amp;amp;height=251&amp;amp;face=0_0_800_251,https://scrap.kakaocdn.net/dn/eHSTVh/hyJ480AyGB/X4PHqTUDXx9dS5J5AZ2VDK/img.png?width=800&amp;amp;height=251&amp;amp;face=0_0_800_251');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;안드로이드 MVVM 패턴&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;안드로이드 MVVM 패턴 MVVM의 기본 구조 MVVM의 기본 구조를 그림으로 표현한 것입니다. View는 ViewModel에게 클릭 이벤트, 필요한 데이터 요청등을 명시적으로 하고, viewModel이 notify 할때까지 기다리게&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;beomseok95.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Android</category>
      <category>CS</category>
      <category>MVVM</category>
      <category>디자인패턴</category>
      <category>안드로이드</category>
      <category>정리</category>
      <author>Liam의 일지</author>
      <guid isPermaLink="true">https://liam-aos.tistory.com/24</guid>
      <comments>https://liam-aos.tistory.com/24#entry24comment</comments>
      <pubDate>Tue, 4 May 2021 12:23:03 +0900</pubDate>
    </item>
    <item>
      <title>MVP 패턴이란?</title>
      <link>https://liam-aos.tistory.com/23</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVP패턴&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;MVP 패턴은 Model과 VIew가 상호 의존적인 MVC 패턴의 단점을 보완하기 위해 MVC 패턴에서 파생되어 나온 패턴이며, Model, View, Presenter를 거쳐 상호 동작할 수 있다는 것이 특징이다. 핵심은 MVC와는 다르게 UI(View)와 비즈니스 로직(Model)을 분리하고, 서로 간에 상호작용을 다른 객체(Presenter)에 그 역할을 줌으로 써 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;서로의 영향(의존성)을 최소화&lt;/b&gt;&lt;/span&gt; 하는것에 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tg28F/btq3Wm00O73/uhJwksM6v4ep95qakTs9k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tg28F/btq3Wm00O73/uhJwksM6v4ep95qakTs9k1/img.png&quot; data-alt=&quot;(기본적인 MVP 구조도)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tg28F/btq3Wm00O73/uhJwksM6v4ep95qakTs9k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ftg28F%2Fbtq3Wm00O73%2FuhJwksM6v4ep95qakTs9k1%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;(기본적인 MVP 구조도)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVP의 특징&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;b&gt;Model&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;프로그램 내부적으로 쓰이는 데이터를 저장하고, 처리하는 역할을 한다.&lt;/li&gt;
&lt;li&gt;VIew 또는 Presenter 등 다른 어떤 요소에도 의존적이지 않은 독립적인 영역이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;View&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;UI를 담당하며 안드로이드에서는 Activity, Fragment가 대표적인 예.&lt;/li&gt;
&lt;li&gt;Model에서 처리된 데이터를 Presenter를 통해 받아서 유저에게 보여준다.&lt;/li&gt;
&lt;li&gt;유저 액선 및 액티비티 LifeCycle 상태 변경을 주시하며 Presenter에 보내는 역할을 한다.&lt;/li&gt;
&lt;li&gt;Presenter를 이용해 데이터를 주고받기 때문에 Presenter에 매우 의존적이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Presenter&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Model과 VIew 사이의 매개체.&lt;/li&gt;
&lt;li&gt;모델과 뷰를 매개체라는 점에서 Controller와 유사하지만, View에 직접 연결되는 대신 인터페이스를 통해 상호작용한다는 점이 다르다.&lt;/li&gt;
&lt;li&gt;인터페이스를 통해 상호작용하므로 MVC가 가진 테스트 문제와 함께 모듈화/유연성문제 역시 해결할 수 있다.&lt;/li&gt;
&lt;li&gt;뷰에게 표시할 내용(Data)만 전달하며 어떻게 보여줄지는 View가 담당한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVP의 장점&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;MVC와는 다르게 VIew와 Model간에 의존성이 없다는 것이다. 이유는 Presenter를 통해서만 데이터를 전달받기 때문이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVP의 단점&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;MVC패턴의 단점인 VIew와 Model 사이의 의존성은 해결되었지만, VIew와 Presenter 사이의 의존성이 높아지는 단점이 있습니다. 이또한 앱이 복잡해질수록 View와 Presenter사이의 의존성이 강해지는 단점이 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;다음 포스팅에서는 MVVM패턴에 대해서 정리해보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;참고 자료:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8C%A8%ED%84%B4-MVP%EA%B0%80-%EB%AD%98%EA%B9%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%ED%8C%A8%ED%84%B4-MVP%EA%B0%80-%EB%AD%98%EA%B9%8C&lt;/a&gt;&lt;/p&gt;</description>
      <category>Android</category>
      <category>Android</category>
      <category>MVC</category>
      <category>MVP</category>
      <category>디자인패턴</category>
      <category>안드로이드</category>
      <author>Liam의 일지</author>
      <guid isPermaLink="true">https://liam-aos.tistory.com/23</guid>
      <comments>https://liam-aos.tistory.com/23#entry23comment</comments>
      <pubDate>Mon, 3 May 2021 15:28:05 +0900</pubDate>
    </item>
    <item>
      <title>MVC 패턴이란?</title>
      <link>https://liam-aos.tistory.com/22</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;디자인패턴?&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;MVC패턴에 대해서 공부하기에 앞서 간략하게 위키피디아의 설명에 기반하여 디자인 패턴에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #a6bc00;&quot;&gt;소프트웨어 개발 방법에서 사용되는 디자인 패턴은, 프로그램 개발에서 자주 나타나는 과제를 해결하기 위한 방법 중 하나로, 과거의 소프트웨어 개발 과정에서 발견된 설계의 노하우를 축적하여 이름을 붙여, 이후에 재이용하기 좋은 형태로 특정의 규약을 묶어서 정리한 것이다. 알고리즘과 같이 프로그램 코드로 바로 변활될 수 있는 형태는 아니지만, 특정한 상황에서 구조적인 문제를 해결하는 방식을 설명해 준다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #a6bc00;&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;참조: https://ko.wikipedia.org/wiki/%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1620016466684&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;website&quot; data-og-title=&quot;디자인 패턴 - 위키백과, 우리 모두의 백과사전&quot; data-og-description=&quot;위키백과, 우리 모두의 백과사전. 디자인 패턴(Design pattern)은 건축학 및 컴퓨터 과학에서 사용되는 용어로, 설계 문제에 대한 해답을 문서화하기위해 고안된 형식 방법이다. 이 방식은 건축가 크&quot; data-og-host=&quot;ko.wikipedia.org&quot; data-og-source-url=&quot;https://ko.wikipedia.org/wiki/%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4&quot; data-og-url=&quot;https://ko.wikipedia.org/wiki/%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ko.wikipedia.org/wiki/%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4&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;&gt;디자인 패턴 - 위키백과, 우리 모두의 백과사전&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;위키백과, 우리 모두의 백과사전. 디자인 패턴(Design pattern)은 건축학 및 컴퓨터 과학에서 사용되는 용어로, 설계 문제에 대한 해답을 문서화하기위해 고안된 형식 방법이다. 이 방식은 건축가 크&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;ko.wikipedia.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;디자인패턴을 사용하게되면 코드의 가독성도 좋아지고 유닛테스트 및 유지보수 또한 편해진다고 합니다&lt;/p&gt;
&lt;p&gt;이 효과는 요구사항이 많아지는 앱일수록 계속해서 유지보수가 필요하기 때문에 디자인패턴을 활용하여 Model-View 사이의 관계를 상황에 맞게 다양한 패턴으로 해결할 수 있다고 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVC패턴&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;MVC패턴은 안드로이드와 관계없이 프로그래밍 시 가장 널리 사용되는 구조 중 하나이며 간단하게 &lt;b&gt;Model, View, Control&lt;/b&gt;의 약자입니다.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;MVC&lt;/b&gt; 구조에서의 입력은 모두 Control에서 발생하게 되며 관리되게 되는 구조입니다. 이벤트가 발생한 Control에 의해 각 모듈의 정의와 View의 사용 용도가 달라지게 됩니다.&lt;/p&gt;
&lt;p&gt;쉽게 말하면, 사용자 인터페이스 영역과 비즈니스 로직 영역을 서로 영향없이 쉽게 가칠 수 있도록, 독립적으로 만들기 위해 사용하는 소프트웨어 디자인 패턴입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mt0Oa/btq32zSn40B/iWWKEViB20814gPJx1AXeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mt0Oa/btq32zSn40B/iWWKEViB20814gPJx1AXeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mt0Oa/btq32zSn40B/iWWKEViB20814gPJx1AXeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmt0Oa%2Fbtq32zSn40B%2FiWWKEViB20814gPJx1AXeK%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;(기본적인 MVC 구조)&lt;/p&gt;
&lt;p&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;Model
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;데이터 구조에 관한 영역, DB 등 데이터 저장소에 접근해 데이터를 검색, 삽입, 삭제, 수정하기 위한 코드 등 포함&lt;/li&gt;
&lt;li&gt;View 또는 Control에 묶이지 않아서 재사용이 가능함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;View
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;앱 및 UI와의 상호작용에서 컨트롤러와 통신함&lt;/li&gt;
&lt;li&gt;사용자에게 보여질 화면에 관한 영역, 페이지 레이아웃, 프래그먼트 등 포함&lt;/li&gt;
&lt;li&gt;유저가 어떤 Action을 하든 View는 무엇을 해야할지 모름&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Control
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Model과&amp;nbsp; View 사이에 위치한 영역, 각 영역에서 데이터를 받은 후 처리하고, 사용자에게 제공&lt;/li&gt;
&lt;li&gt;사용자로부터 입력을 받고 이 입력을 모델에 의해 View 정의를 하게 됨.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;다만, 안드로이드에서의 MVC패턴은 약간 형태가 달라집니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;달라지는 이유는 Model, View, Control이 분명히 존재하지만 안드로이드의 화면에서 액티비티(프래그먼트)는 표현할 화면에 대한 레이아웃을 받아오고(Controller), 화면을 그리기 위한 데이터 처리(View, Controller)도 하기 때문에 액티비티가 그려지는 시점에서 View와 Controller역할이 수행되어지기 때문입니다.&lt;/p&gt;
&lt;p&gt;게다가 어떠한 클릭 이벤트같은 처리에 대한 핸들러도 액티비티안에서 이루어질 수 있기 때문에 사실상 액티비티안에서 모든게 이루어질 수 있습니다.&lt;/p&gt;
&lt;p&gt;이렇게 되니 유지보수가 굉장히 어렵게 됩니다.(저 역시... MVC패턴이랍시고 굉장히 지저분한 프로젝트가 많습니다 ㅜㅜ)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RR8TQ/btq353ZMWGw/Uc5ugm9SNHqkk6ebaKfs51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RR8TQ/btq353ZMWGw/Uc5ugm9SNHqkk6ebaKfs51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RR8TQ/btq353ZMWGw/Uc5ugm9SNHqkk6ebaKfs51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRR8TQ%2Fbtq353ZMWGw%2FUc5ugm9SNHqkk6ebaKfs51%2Fimg.png&quot; data-origin-width=&quot;0&quot; data-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;(안드로이드에서의 MVC흐름입니다. 모든 과정을 Activity에서 관여하는 것을 확인할 수 있습니다. )&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVC의 장점&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;Model과 VIew가 분리됨.&lt;/li&gt;
&lt;li&gt;Model의 비종속적으로 재사용 가능함.&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MVC의 단점&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;Model과 VIew사이에 의존성 발생함. (서로간의 의존성을 완전히 없앨 수 없음)&lt;br /&gt;즉, View의 UI갱신을 위해 Model을 직/간접적으로 참조하므로 앱 자체가 커지고 로직이 복잡해질수록 유지보수가 힘들어진다.&lt;/li&gt;
&lt;li&gt;스파게티 코드가 될 가능성이 높음.&lt;/li&gt;
&lt;li&gt;시간이 지날수록 컨트롤러에 많은 코드가 쌓여 코드가 비대화하여 문제 발생 가능&lt;/li&gt;
&lt;li&gt;Controller가 안드로이드 API에 깊게 종속되므로 유닛테스트가 어려움.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;참고 자료&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90-%ED%8C%A8%ED%84%B4-MVC%EA%B0%80-%EB%AD%98%EA%B9%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90-%ED%8C%A8%ED%84%B4-MVC%EA%B0%80-%EB%AD%98%EA%B9%8C&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1620018116358&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-og-type=&quot;article&quot; data-og-title=&quot;안드로이드 아키텍처 패턴 - MVC가 뭘까?&quot; data-og-description=&quot;이번엔 아키텍쳐 디자인 패턴을 말할때 가장 많이 쓰이면서 기본이 되는 MVC에 대해 간략하게 설명 해보려 합니다. 경험상 제가 막 개발자 커리어를 시작한때에도 스타트업에 안드로이드 개발자&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90-%ED%8C%A8%ED%84%B4-MVC%EA%B0%80-%EB%AD%98%EA%B9%8C&quot; data-og-url=&quot;https://velog.io/@jojo_devstory/안드로이드-아키텍쳐-패턴-MVC가-뭘까&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cDMrXy/hyJ4V65xPo/kdjWaL46Oa8Pwwb6n0Ho51/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426,https://scrap.kakaocdn.net/dn/f2YdS/hyJ4V65xXs/oLnzBO9jVAj5PaLFb63qa0/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426,https://scrap.kakaocdn.net/dn/TsVuL/hyJ4UmPLcB/cO18typh74LxEWRMmS0jA0/img.png?width=2518&amp;amp;height=1442&amp;amp;face=0_0_2518_1442&quot;&gt;&lt;a href=&quot;https://velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90-%ED%8C%A8%ED%84%B4-MVC%EA%B0%80-%EB%AD%98%EA%B9%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@jojo_devstory/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B3%90-%ED%8C%A8%ED%84%B4-MVC%EA%B0%80-%EB%AD%98%EA%B9%8C&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cDMrXy/hyJ4V65xPo/kdjWaL46Oa8Pwwb6n0Ho51/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426,https://scrap.kakaocdn.net/dn/f2YdS/hyJ4V65xXs/oLnzBO9jVAj5PaLFb63qa0/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426,https://scrap.kakaocdn.net/dn/TsVuL/hyJ4UmPLcB/cO18typh74LxEWRMmS0jA0/img.png?width=2518&amp;amp;height=1442&amp;amp;face=0_0_2518_1442');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot;&gt;안드로이드 아키텍처 패턴 - MVC가 뭘까?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot;&gt;이번엔 아키텍쳐 디자인 패턴을 말할때 가장 많이 쓰이면서 기본이 되는 MVC에 대해 간략하게 설명 해보려 합니다. 경험상 제가 막 개발자 커리어를 시작한때에도 스타트업에 안드로이드 개발자&lt;/p&gt;
&lt;p class=&quot;og-host&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;a href=&quot;https://awesometic.tistory.com/18&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;awesometic.tistory.com/18&lt;/a&gt;&lt;/p&gt;</description>
      <category>Android</category>
      <category>AOS</category>
      <category>MVC</category>
      <category>디자인패턴</category>
      <category>안드로이드</category>
      <author>Liam의 일지</author>
      <guid isPermaLink="true">https://liam-aos.tistory.com/22</guid>
      <comments>https://liam-aos.tistory.com/22#entry22comment</comments>
      <pubDate>Mon, 3 May 2021 14:00:11 +0900</pubDate>
    </item>
    <item>
      <title>HackerRank</title>
      <link>https://liam-aos.tistory.com/21</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Bu----- 채용 코딩테스트문제&lt;/h3&gt;
&lt;p&gt;문제: 주어진 start-&amp;gt;end 리스트로 연결된 각 그래프의 노드 수의 루트값의 올림한 값을 더한 결과를 나타내라.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1619873949418&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import deque
import math

def connectedSum(graph_nodes, graph_from, graph_to):
    graph =[[] for i in range(graph_nodes+1)]
    result=0
    visit=[False]*(graph_nodes+1)
    for i in range(len(graph_from)):
        graph[graph_from[i]].append(graph_to[i])
        graph[graph_to[i]].append(graph_from[i])

    q=deque()

    for i in graph_from:
        cnt=1
        if visit[i]==False:
            visit[i]=True
            q.append(i)
            while q:
                now=q.popleft()
                for j in graph[now]:
                    if visit[j]==False:
                        visit[j]=True
                        cnt+=1
                        q.append(j)
            result+=int(math.ceil(math.sqrt(cnt)))


    cnt=0
    for i in range(1,graph_nodes+1):
        if visit[i]==False:
            cnt+=1

    result+=cnt

    print(result)




graph_nodes=4
graph_from=[1,1]
graph_to=[2,4]

connectedSum(graph_nodes,graph_from,graph_to)

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm(백준)</category>
      <category>그래프</category>
      <category>알고리즘</category>
      <category>코딩테스트</category>
      <author>Liam의 일지</author>
      <guid isPermaLink="true">https://liam-aos.tistory.com/21</guid>
      <comments>https://liam-aos.tistory.com/21#entry21comment</comments>
      <pubDate>Sat, 1 May 2021 21:59:39 +0900</pubDate>
    </item>
  </channel>
</rss>