<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>발전하는 개발자가 되자</title>
    <link>https://jar100.tistory.com/</link>
    <description>개발 공부를 하는 블로그 알고리즘, java, cs, spring 등등</description>
    <language>ko</language>
    <pubDate>Sat, 27 Jun 2026 06:21:56 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>백경훈</managingEditor>
    <item>
      <title>REST full, REST API 란 무엇 일까?</title>
      <link>https://jar100.tistory.com/31</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;
&lt;h2&gt;REST 란?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;REST&lt;/code&gt; 는 웹을 위한 아키텍쳐 스타일 이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;아키텍쳐 스타일 :  제약조건의 집합&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;그래서 제약조건을 모두 만족해야 &lt;code&gt;REST&lt;/code&gt;라 할 수 있다.&lt;/p&gt;
&lt;h2&gt;REST 의 제약조건&lt;/h2&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Client -server&lt;br&gt;
- 서버와 클라이언트를 가져야 한다.&lt;/li&gt;
&lt;li&gt;Stateless&lt;br&gt;
- 상태를 가지면 안된다.&lt;/li&gt;
&lt;li&gt;Cacheable&lt;br&gt;
- 캐시를 가져야 한다.&lt;/li&gt;
&lt;li&gt;Layerd system&lt;br&gt;
- 레이어드 시스템 이어야 한다.&lt;/li&gt;
&lt;li&gt;code-on-demand (optional)&lt;br&gt;
- 서버에서 코드를 클라이언트에게보내서 실행 가능해야한다.  (js)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;위의 조건들은 HTTP 통신을 이용하면 자동으로 만족한다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;uniform interface&lt;br&gt;
- identifcation of resources&lt;br&gt;
- manipulation of resources through representations&lt;br&gt;
- self-descriptive messages&lt;br&gt;
- hypermedia as the engine of application state (HATEOAS)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;하지만 &lt;code&gt;Uniform Interface&lt;/code&gt; 은 만족하는 것도 있고 만족 하지 않는 것도 있다.&lt;/p&gt;
&lt;h2&gt;Uniform Interface&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;HTTP 통신을 하면 만족하는 것&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Identifcation of resources&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;자원으로 식별 할 수 있어야한다.&lt;/li&gt;
&lt;li&gt;URI 를 통한 식별&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Manipulation of resources through representations&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;표현을 통해 자원을 조작 할 수 있어야 한다.&lt;/li&gt;
&lt;li&gt;HTTP 메소드를 통해 자원 조작 (CRUD 가능)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;만족하지 않는 것 추가 구현을 통해 만족 시켜야 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;
&lt;p&gt;Self-descriptive messages&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;메시지가 스스로를 설명 해야한다.&lt;/li&gt;
&lt;li&gt;목적지가 있아여 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Hypermedia as the engine of application state (HATEOAS)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;애플리케이션의 상태가 Hyperlink 를 통해서 전송되어야한다.&lt;/li&gt;
&lt;li&gt;다음 상태를 링크로 표시해야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;웹을 사용하면 만족한다. 하지만 &lt;code&gt;REST API&lt;/code&gt; 는 만족하지 않는다.
이유는 우리가 말하는 &lt;code&gt;REST API&lt;/code&gt; 들은 대부분 &lt;code&gt;Json&lt;/code&gt;으로 데이터를 전송한다.&lt;/p&gt;
&lt;h3&gt;웹과 api 차이&lt;/h3&gt;
&lt;p&gt;웹은 &lt;code&gt;REST&lt;/code&gt; 를 잘 만족하고 지킨다.&lt;br&gt;
하지만 &lt;code&gt;API&lt;/code&gt; 는 그렇지 못하다 왤까????&lt;br&gt;
미디어 타입때문이다.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;html : 하이퍼링크됨, 셀프 디스크립트 됨&lt;br&gt;
json : 하이퍼링크 안됨, 셀프 디스크립트 불완전 (문법같은 것은 정의 값이 어떤값인지는 정의가 안되있다.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;따라서 api 문서를 만들고 json 요청에도 링크를 통한 추가 구현을 해야 한다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;REST API 는 REST 를 다 지켜야 하는가?&lt;/h2&gt;
&lt;p&gt;로이필딩은 그렇다고 한다.
셀프디스크립트와 헤이티오스를 지켜야 한다고 말한다.&lt;/p&gt;
&lt;h3&gt;지켜야 하는 이유&lt;/h3&gt;
&lt;p&gt;서버와 클라이언트는 독립적 진화를 해야한다.
서버의 기능이 변경되어도 클라이언트를 업데이트 할 필요가 없다.&lt;/p&gt;
&lt;h3&gt;현재상태&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;REST API&lt;/code&gt; 가 아니지만 &lt;code&gt;REST API&lt;/code&gt; 라 부른다.
어느정도는 &lt;code&gt;REST&lt;/code&gt;를  만족하지만 완벽히 만족한다고 할 순 없다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Self - descriptive 와 HATEOAS 가 독립적 진화에 도움이 될까?&lt;/h3&gt;
&lt;p&gt;서버가 어떻게 변하든 메세지만 갖고 해석이 가능해서 상관이 없어진다.
서버가 링크를 바꿔도 클라이언트의 동작엔 아무 문제가 없다.&lt;/p&gt;
&lt;h3&gt;만족시키려면&lt;/h3&gt;
&lt;h4&gt;Self - descriptive&lt;/h4&gt;
&lt;p&gt;IANA에 미디어 타입을 등록한다. 이 때 만든 문서를 미디어 타입의 명세로 등록한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ex) Content-Type: application/vnd.todos+json&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;단점&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;매번 media type을 정의해야한다&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Link 헤더에 profile relation으로 해당 명세를 링크한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ex) Link: &lt;a href=&quot;https://example.org/docs/todos&quot;&gt;https://example.org/docs/todos&lt;/a&gt;; rel=&amp;quot;profile&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;단점&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트가 Link 헤더(RFC 5988)와 profile(RFC 6906)을 이해해야한다.&lt;/li&gt;
&lt;li&gt;Content negotiation을 할 수 없다&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4&gt;HATEOAS&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;data 에 링크를 주어 표현한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;GET /todos HTTP/1.1
Host: example.org

HTTP/1.1 200 OK
Content-Type: application/json
Link: &amp;lt;https://example.org/docs/todos&amp;gt;; rel=&amp;quot;profile&amp;quot;

[ 
  {
    &amp;quot;link&amp;quot;: &amp;quot;https://example.org/todos/1&amp;quot;,
    &amp;quot;title&amp;quot;: &amp;quot;회사 가기&amp;quot;
  },
  {
    &amp;quot;link&amp;quot;: &amp;quot;https://example.org/todos/2&amp;quot;,
    &amp;quot;title&amp;quot;: &amp;quot;집에 가기&amp;quot;
  }
]
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;GET /todos HTTP/1.1
Host: example.org

HTTP/1.1 200 OK
Content-Type: application/json
Link: &amp;lt;https://example.org/docs/todos&amp;gt;; rel=&amp;quot;profile&amp;quot;

{
  &amp;quot;links&amp;quot;: {
    &amp;quot;todo&amp;quot;: &amp;quot;https://example.org/todos/{id}&amp;quot;
  },
  &amp;quot;data&amp;quot;: [{
    &amp;quot;id&amp;quot;: 1,
    &amp;quot;title&amp;quot;: &amp;quot;회사 가기&amp;quot;
  }, {
    &amp;quot;id&amp;quot;: 2,
    &amp;quot;title&amp;quot;: &amp;quot;집에 가기&amp;quot;
  }]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;단점 : 링크를 표현하는 방법을 직접 정의 해야한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;HTTP 헤더에 표현한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;POST /todos HTTP/1.1
Content-Type: application/json

{
    &amp;quot;title&amp;quot;: &amp;quot;점심 약속&amp;quot;
}

HTTP/1.1 204 No Content
Location: /todos/1
Link: &amp;lt;/todos/&amp;gt;; rel=&amp;quot;collection&amp;quot;

&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;단점: 정의된 relation만 활용한다면 표현에 한계가 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;정리&lt;/h2&gt;
&lt;p&gt;오늘날 &lt;code&gt;REST API&lt;/code&gt; 는 사실 &lt;code&gt;REST&lt;/code&gt;를 따르지 않고 있다.
개발자가 상황에 맞게 &lt;code&gt;REST&lt;/code&gt; 따를지 말지 스스로 판단하자.
만족시키려면 Self-descriptive 와 HATEOAS 를 만족 시키면된다.
따르지 않겠다면 &lt;code&gt;http api&lt;/code&gt; 라 부르던가 그냥 &lt;code&gt;rest api&lt;/code&gt; 라 부르자.
현재는 완벽히 만족하지 않지만 &lt;code&gt;REST API&lt;/code&gt; 라고 부르고 있다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;참조&lt;/h2&gt;
&lt;p&gt;https://www.youtube.com/watch?v=RP_f5dMoHFc&lt;/p&gt;


&lt;/article&gt;</description>
      <category>개발공부/CS</category>
      <category>REST</category>
      <category>REST API</category>
      <author>백경훈</author>
      <guid isPermaLink="true">https://jar100.tistory.com/31</guid>
      <comments>https://jar100.tistory.com/31#entry31comment</comments>
      <pubDate>Mon, 27 May 2019 14:53:00 +0900</pubDate>
    </item>
    <item>
      <title>JVM과 GC(Garbage Collection)</title>
      <link>https://jar100.tistory.com/30</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;
&lt;h2&gt;JVM과 GC&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;JVM 이란?&lt;br /&gt;GC 란?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;JVM (Java Virtual Machine) 이란&lt;/h3&gt;
&lt;p&gt;자바 버추얼 머신으로 자바 프로그램이 컴파일 되고 class 파일이 만들어지면 그 클래스 파일을 기계어로 변화시키고 하는 명세 cpu 나 운영체제의 종류에 무관하게 동작한다 운영체제 위에서 동작하는 프로세스로 자바 코드를 컴파일해서 얻은 바이트 코드를 해당 운영체제가 이해할 수 있는 기계어로 바꿔 실행시켜주는 역할을 한다.&lt;/p&gt;
&lt;h3&gt;JVM 메모리 구조&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Method area, Heap area, Stack area, PC Register , Native method stack&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgyizE/btqvgGMNrDE/bPROU95pTk1RNjaLxgGMG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgyizE/btqvgGMNrDE/bPROU95pTk1RNjaLxgGMG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgyizE/btqvgGMNrDE/bPROU95pTk1RNjaLxgGMG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgyizE%2FbtqvgGMNrDE%2FbPROU95pTk1RNjaLxgGMG0%2Fimg.png&quot; width=&quot;100%&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;ol&gt;
&lt;li&gt;Method area : 상수, 메소드 클래스 코드가 적제되는 영역&lt;/li&gt;
&lt;li&gt;Heap area : new Car 와 같이 실제 객체, 전역변수 등이 적제되는 영역&lt;/li&gt;
&lt;li&gt;Stack area : Car car1 의 car1이 적제 되는 영역 new Car()의 주소를 참조한다.&lt;/li&gt;
&lt;li&gt;PC Register : Thread(쓰레드)가 생성될 때마다 생성되는 영역으로 Program Counter 즉, 현재 쓰레드가 실행되는 부분의 주소와 명령을 저장하고 있는 영역&lt;/li&gt;
&lt;li&gt;Native method stack : c, c++ 등의 코드를 실행하기 위한 영역&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;GC&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;가비지 컬렉션 : 메모리가 가득 차 발생하는 오버플로를 방지함 Parallel Collector 는 에덴, 서바이버1, 서바이버2, 올드로 구성이 되어있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KC21W/btqvjLzhcgW/q5eMkkFlAQ9HYFzRNXr2U1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KC21W/btqvjLzhcgW/q5eMkkFlAQ9HYFzRNXr2U1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KC21W/btqvjLzhcgW/q5eMkkFlAQ9HYFzRNXr2U1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKC21W%2FbtqvjLzhcgW%2Fq5eMkkFlAQ9HYFzRNXr2U1%2Fimg.png&quot; width=&quot;100%&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;h4&gt;GC 의 종류&lt;/h4&gt;
&lt;p&gt;Serial Collector - 쓰레드 1개가 GC 수행&lt;/p&gt;
&lt;p&gt;Parallel Collector - 자바 버전7의 디폴트 GC, 여러개의 쓰레드가 동시에 '마이너' GC수행 ('메이저'GC는 여전히 싱글쓰레드)&lt;/p&gt;
&lt;p&gt;CMS Collector : Full GC도 병렬 처리 (문제가 많아 쓰지 않음)&lt;/p&gt;
&lt;p&gt;G1 Collector : 자바 버전9의 디폴트 GC, 사용은 자바 7버전부터 사용 가능 P GC 와 CMS를 조합한 형태&lt;/p&gt;
&lt;h3&gt;GC 동작 방식&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Parallel Collector (java7, java8 default)&lt;/p&gt;
&lt;h4&gt;마이너 GC&lt;/h4&gt;
&lt;p&gt;힙영역의 에덴에 객체가 생성되고 에딘이 가득차면 서바이버중 1개에 객체들을 옮긴다. 다시 에덴 데이터를 적제하고 가득찬다면 서바이버에 저장되있는 객체와 에덴이 있는객체중 중복된 객체를 다른 서바이버로 옮기고 카운트를 증가시킨다 이와 같이 반복시키고 일정 카운트 이상인 객체를 올드로 옮긴다.&lt;/p&gt;
&lt;h4&gt;메이저 GC&lt;/h4&gt;
&lt;p&gt;메이저 gc는 올드의 데이터를 처리하는것으로 마이너 GC보다 많은 메모리를 잡아먹는다. stop-the-world 가 발생한다. (GC 를 실행하기 위해 어플리케이션 실행이 멈춘다)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;G1 Collector (java9 default)&lt;br /&gt;Heap 영역을 여러개의 region 으로 나누어 동작. region 들을 eden, survivor, old 등으로 할당하고 사용 각각 크기를 가변적으로 사용가능하다. 지속적으로 region들을 한곳으로 모아 압축하여 공간을 확보한다. 또한 병렬적으로 각 영역을 마킹하고 회수하기 때문에 stop-the-world 시간이 줄고 처리 속도가 늘어났다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/I8JY8/btqvicYDhpv/320DAPi0BpmU5bM9kaCEG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/I8JY8/btqvicYDhpv/320DAPi0BpmU5bM9kaCEG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/I8JY8/btqvicYDhpv/320DAPi0BpmU5bM9kaCEG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FI8JY8%2FbtqvicYDhpv%2F320DAPi0BpmU5bM9kaCEG0%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;참조&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://jeong-pro.tistory.com/148&quot;&gt;https://jeong-pro.tistory.com/148&lt;/a&gt; [기본기를 쌓는 정아마추어 코딩블로그]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://starblood.tistory.com/entry/Java8-G1-garbage-collection-%ED%8A%B9%EC%A7%95&quot;&gt;https://starblood.tistory.com/entry/Java8-G1-garbage-collection-특징&lt;/a&gt; [Drink and Be happy]&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://d2.naver.com/helloworld/1329&quot;&gt;https://d2.naver.com/helloworld/1329&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html&quot;&gt;https://www.oracle.com/technetwork/tutorials/tutorials-1876574.html&lt;/a&gt;&lt;/p&gt;
&lt;/article&gt;</description>
      <category>개발공부/Java</category>
      <author>백경훈</author>
      <guid isPermaLink="true">https://jar100.tistory.com/30</guid>
      <comments>https://jar100.tistory.com/30#entry30comment</comments>
      <pubDate>Wed, 15 May 2019 17:03:38 +0900</pubDate>
    </item>
    <item>
      <title>객체지향설계의 5원칙 솔리드(SOLID)?</title>
      <link>https://jar100.tistory.com/29</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;
&lt;h2&gt;SRP (단일책임의 원칙: Single Responsibility Principle)&lt;/h2&gt;
&lt;p&gt;작성된 클래스는 하나의 기능만 가지며 클래스가 제공하는 모든 서비스는 그 하나의 책임(변화의 축: axis of change)을 수행하는 데 집중되어 있어야 한다는 원칙입니다. 이는 어떤 변화에 의해 클래스를 변경해야 하는 이유는 오직 하나뿐이어야 함을 의미합니다. SRP원리를 적용하면 무엇보다도 책임 영역이 확실해지기 때문에 한 책임의 변경에서 다른 책임의 변경으로의 연쇄작용에서 자유로울 수 있습니다. 뿐만 아니라 책임을 적절히 분배함으로써 코드의 가독성 향상, 유지보수 용이라는 이점까지 누릴 수 있으며 객체지향 원리의 대전제 격인 OCP원리뿐 아니라 다른 원리들을 적용하는 기초가 됩니다. 이 원리는 다른 원리들에 비해서 개념이 비교적 단순하지만, 이 원리를 적용해서 직접 클래스를 설계하기가 그리 쉽지만은 않습니다. 왜냐하면, 실무의 프로세스는 매우 복잡 다양하고 변경 또한 빈번하기 때문에 경험이 많지 않거나 도메인에 대한 업무 이해가 부족하면 나도 모르게 SRP원리에서 멀어져 버리게 됩니다. 따라서 평소에 많은 연습(&amp;lsquo;책임&amp;rsquo;이란 단어를 상기하는)과 경험이 필요한 원칙입니다.&lt;/p&gt;
&lt;h3&gt;정리&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Class&lt;/code&gt;와 &lt;code&gt;Method&lt;/code&gt;는 하나의 '역할'만 하도록 해야 한다. 만약 상태와 행위가 변화의 시기와 이유가 달라진다면 클래스나 메소드를 분리해야 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;OCP (개방폐쇄의 원칙: Open Close Principle)&lt;/h2&gt;
&lt;p&gt;버틀란트 메이어(Bertrand Meyer)박사가 1998년 객체지향 소프트웨어 설계 라는 책에서 정의한 내용으로 소프트웨어의 구성요소(컴포넌트, 클래스, 모듈, 함수)는 확장에는 열려있고, 변경에는 닫혀있어야 한다는 원리입니다. 이것은 변경을 위한 비용은 가능한 줄이고 확장을 위한 비용은 가능한 극대화 해야 한다는 의미로, 요구사항의 변경이나 추가사항이 발생하더라도, 기존 구성요소는 수정이 일어나지 말아야 하며, 기존 구성요소를 쉽게 확장해서 재사용할 수 있어야 한다는 뜻입니다. 로버트 C. 마틴은 OCP는 관리가능하고 재사용 가능한 코드를 만드는 기반이며, OCP를 가능케 하는 중요 메커니즘은 추상화와 다형성이라고 설명하고 있습니다. OCP는 객체지향의 장점을 극대화하는 아주 중요한 원리라 할 수 있습니다.&lt;/p&gt;
&lt;h3&gt;정리&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;확장에는 열려있고, 변경에는 닫혀있어야 한다. 변경이나 추가사항이 발생해도 기존 코드의 수정이 최소한으로 발생해야한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;LSP (리스코브 치환의 원칙: The Liskov Substitution Principle)&lt;/h2&gt;
&lt;p&gt;이 원칙은 5가지 원칙 중에서 좀처럼 쉽게 이해 되지 않는 원칙의 하나로 LSP라는 이름에서는 도저히 원칙에 대한 내용을 도출 할 수 없는 원칙입니다. LSP를 한마디로 한다면, &amp;ldquo;서브 타입은 언제나 기반 타입으로 교체할 수 있어야 한다.&amp;rdquo;라고 할 수 있습니다. 즉, 서브 타입은 언제나 기반 타입과 호환될 수 있어야 합니다. 달리 말하면 서브 타입은 기반 타입이 약속한 규약(public 인터페이스, 물론 메소드가 던지는 예외까지 포함됩니다.)을 지켜야 합니다. 상속은 구현상속(extends 관계)이든 인터페이스 상속(implements 관계)이든 궁극적으로는 다형성을 통한 확장성 획득을 목표로 합니다. LSP원리도 역시 서브 클래스가 확장에 대한 인터페이스를 준수해야 함을 의미합니다. 다형성과 확장성을 극대화 하려면 하위 클래스를 사용하는 것보다는 상위의 클래스(인터페이스)를 사용하는 것이 더 좋습니다. 일반적으로 선언은 기반 클래스로 생성은 구체 클래스로 대입하는 방법을 사용합니다. 생성 시점에서 구체 클래스를 노출시키기 꺼려질 경우 생성 부분을 Abstract Factory 등의 패턴을 사용하여 유연성을 높일 수 있습니다. 상속을 통한 재사용은 기반 클래스와 서브 클래스 사이에 IS-A관계가 있을 경우로만 제한 되어야 합니다. 그 외의 경우에는 합성(composition)을 이용한 재사용을 해야 합니다. 상속은 다형성과 따로 생각할 수 없습니다. 그리고 다형성으로 인한 확장 효과를 얻기 위해서는 서브 클래스가 기반 클래스와 클라이언트 간의 규약(인터페이스)를 어겨서는 안 됩니다. 결국 이 구조는 다형성을 통한 확장의 원리인 OCP를 제공 하게 됩니다. 따라서 LSP는 OCP를 구성하는 구조가 됩니다. 객체지향 설계 원리는 이렇게 서로가 서로를 이용하기도 하고 포함하기도 하는 특징이 있습니다. LSP는 규약을 준수하는 상속구조를 제공 합니다. LSP를 바탕으로 OCP는 확장하는 부분에 다형성을 제공해 변화에 열려있는 프로그램을 만들 수 있도록 합니다.&lt;/p&gt;
&lt;h3&gt;정리&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;서브 타입은 기반 타입과 호환이 되어야 한다. 즉 서브 클래스는 슈퍼 클래스의 형태로 사용 가능해야한다. 이를 바탕으로 확장에 용이해 진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;List list1 = new ArrayList();
List list2 = new LinkedList(); 
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;ISP (인터페이스 분리의 원칙: Interface Segregation Principle)&lt;/h2&gt;
&lt;p&gt;ISP원리는 한 클래스는 자신이 사용하지 않는 인터페이스는 구현하지 말아야 한다는 원리입니다. 즉 어떤 클래스가 다른 클래스에 종속될 때에는 가능한 최소한의 인터페이스만을 사용해야 합니다. ISP를 &amp;lsquo;하나의 일반적인 인터페이스보다는, 여러 개의 구체적인 인터페이스가 낫다&amp;rsquo;라고 정의할 수 도 있습니다. 만약 어떤 클래스를 이용하는 클라이언트가 여러 개고 이들이 해당 클래스의 특정 부분집합만을 이용한다면, 이들을 따로 인터페이스로 빼내어 클라이언트가 기대하는 메시지만을 전달할 수 있도록 합니다. SRP가 클래스의 단일책임을 강조한다면 ISP는 인터페이스의 단일책임을 강조합니다. 하지만 ISP는 어떤 클래스 혹은 인터페이스가 여러 책임 혹은 역할을 갖는 것을 인정합니다. 이러한 경우 ISP가 사용되는데 SRP가 클래스 분리를 통해 변화에의 적응성을 획득하는 반면, ISP에서는 인터페이스 분리를 통해 같은 목표에 도달 합니다.&lt;/p&gt;
&lt;h3&gt;정리&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;어떠한 인터페이스를 구현할 때 꼭 사용하는 것만 구현해야한다. 다른 클레스에서 사용하지 않는다면 인터페이스를 분리해 추가 구현하자.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public interface Animal {
    void eat();
    void cry();
}

public interface Bird {
    void fly();
}

public interface Mammal {
    void run();
}

public class Cat implements Animal,Mammal {
    @Override
    public void eat() {
        System.out.println(&quot;냠냠&quot;);
    }

    @Override
    public void cry() {
        System.out.println(&quot;냐옹&quot;);
    }

    @Override
    public void run() {
        System.out.println(&quot;사뿐사뿐&quot;);
    }
}

public class Parrot implements Animal,Bird {
    @Override
    public void eat() {
        System.out.println(&quot;쩝쩝&quot;);
    }

    @Override
    public void cry() {
        System.out.println(&quot;안녕&quot;);
    }

    @Override
    public void fly() {
        System.out.println(&quot;푸더더덕&quot;);
    }
}

&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;DIP (의존성역전의 원칙: Dependency Inversion Principle)&lt;/h2&gt;
&lt;p&gt;의존 관계의 역전 Dependency Inversion 이란 구조적 디자인에서 발생하던 하위 레벨 모듈의 변경이 상위 레벨 모듈의 변경을 요구하는 위계관계를 끊는 의미의역전입니다. 실제 사용 관계는 바뀌지 않으며, 추상을 매개로 메시지를 주고 받음으로써 관계를 최대한 느슨하게 만드는 원칙입니다.&lt;/p&gt;
&lt;p&gt;DIP는 복잡하고 지난한 컴포넌트간의 커뮤니케이션 관계를 단순화하기 위한 원칙입니다. 실 세계에서도 헐리우드 원칙에서와 같이 귀찮도록 자주 질문과 요청을 하는 동료에게도 써먹어 볼만한 원칙입니다.&lt;/p&gt;
&lt;h3&gt;정리&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;자주 변화하는 것보다 변화하기 어려운 것, 변화가 거의 없는 것에 의존하라는 것. 구체적인 클래스로 의존관계를 맺지말고 추상화 된 인터페이스를 구현해 의존관계를 맺어 확장에 용이하게 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class Farm {
    private Animal animal;

    public void init(Animal animal) {
        animal = animal;
    }

    public void check() {
        animal.cry();
    }

    public void giveFood() {
        animal.eat();
    }
}

public interface Animal {
    void eat();
    void cry();
}

public class Bard implements Animal {
    @Override
    public void eat() {
        System.out.println(&quot;콕콕콕&quot;);
    }

    @Override
    public void cry() {
        System.out.println(&quot;안녕&quot;);

    }
}

public class Chicken implements Animal {
    @Override
    public void eat() {
        System.out.println(&quot;콕콕콕&quot;);
    }

    @Override
    public void cry() {
        System.out.println(&quot;꼬꼬&quot;);

    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;객체지향 개발 5대 원리를 지켜야 하는 이유&lt;/h2&gt;
&lt;p&gt;5원칙을 만족하면 유지 보수가 용이 해지고 가독성도 상승한다. 그리고 코드의 재사용이 가능하며 추가 요구사항 구현할 때 다른 코드들의 변경사항을 최소화 할 수 있다.또한 의존관계를 추상화된 인터페이스로 받게 되면서 다형성도 보장 할 수 있다.&lt;/p&gt;
&lt;p&gt;5대 원리를 따르면 확장성, 다형성, 가독성, 재사용성을 보장할 수 있다.&lt;/p&gt;
&lt;h2&gt;참고&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;http://www.nextree.co.kr/p6960/&quot;&gt;http://www.nextree.co.kr/p6960/&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://wkdtjsgur100.github.io/solid-principle/&quot;&gt;https://wkdtjsgur100.github.io/solid-principle/&lt;/a&gt;&lt;/p&gt;
&lt;/article&gt;</description>
      <category>개발공부/Java</category>
      <category>java</category>
      <category>OOP</category>
      <category>Solid</category>
      <author>백경훈</author>
      <guid isPermaLink="true">https://jar100.tistory.com/29</guid>
      <comments>https://jar100.tistory.com/29#entry29comment</comments>
      <pubDate>Mon, 6 May 2019 17:53:12 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 알고리즘 : 도둑질 (java)</title>
      <link>https://jar100.tistory.com/28</link>
      <description> &lt;h1&gt;프로그래머스 알고리즘 (java)&lt;/h1&gt;
&lt;h2&gt;도둑질&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42897?language=java&quot;&gt;프로그래머스 (도둑질)&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;도둑이 어느 마을을 털 계획을 하고 있습니다. 이 마을의 모든 집들은 아래 그림과 같이 동그랗게 배치되어 있습니다.
&lt;img src=&quot;https://grepp-programmers.s3.amazonaws.com/files/ybm/e7dd4f51c3/a228c73d-1cbe-4d59-bb5d-833fd18d3382.png&quot; alt=&quot;도둑질&quot;&gt;
각 집들은 서로 인접한 집들과 방범장치가 연결되어 있기 때문에 인접한 두 집을 털면 경보가 울립니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;각 집에 있는 돈이 담긴 배열 money가 주어질 때, 도둑이 훔칠 수 있는 돈의 최댓값을 return 하도록 solution 함수를 작성하세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;코드리뷰&lt;/h2&gt;
&lt;h3&gt;조건&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;1번째 집을 털면 마지막 집은 털지 못한다.&lt;/li&gt;
&lt;li&gt;인접한 집은 털지 못한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;풀이방향&lt;/h3&gt;
&lt;p&gt;인접한 집을 털지 못하니 1번집을 털 경우와 2번집을 털 경우 그리고 한 칸씩 띄워서 두개의 최대 값을 비교하면 된다 생각하고 문제를 풀었습니다.
하지만 두칸 건널 수도 있다는 경우를 생각 못해 문제 풀기에 실패 했습니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;money[i]&lt;/code&gt; 의 값이 주어 졌을 때 이 값을 포함한 최대 값을 구하여 전체를 다 탐색하는 방법으로 풀었습니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;money[i]&lt;/code&gt; 를 포함한 최대 값 &lt;code&gt;result[i + 2]&lt;/code&gt; 는 두 칸 뒤에 있는 &lt;code&gt;result[i]&lt;/code&gt; 와 3칸 뒤에 있는 &lt;code&gt;result[i - 1]&lt;/code&gt; 값 중 큰 값을 선택 하면 됩니다.&lt;/p&gt;
&lt;h3&gt;코드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class Thievery {
    public int solution(int[] money) {
        int answer = 0;
        //첫번째 집부터 구하기
        int[] result = new int[money.length + 2];
        //두번째 집부터 구하기
        int[] result2 = new int[money.length + 2];

        //초기값 입력
        result[2] = money[0];
        result2[3] = money[1];

        //i를 증가 시키면서 money[i] 를 사용할 때 최고 값을 구한다.
        for (int i = 1; i &amp;lt; money.length; i++) {
            // dp
            //첫번째 집을 구할땐 마지막 집을 못 더한다.
            if (i &amp;lt; money.length - 1) {
                dp(money, result, i);
            }
            //두번째 집부터 구하려면 첫번째 집은 못 더한다.
            if (i &amp;gt; 1) {
                dp(money, result2, i);
            }
            //나온 결과 값들중 가장 큰값을 뽑는다.

            answer = findMax(answer, result[i + 2], result2[i + 2]);
        }

        return answer;
    }

    private int findMax(int answer, int result1, int result2) {
        int newResult = result1 &amp;gt; result2 ? result1 : result2;
        if (answer &amp;gt; newResult) {
            return answer;
        }
        return newResult;
    }

    private void dp(int[] money, int[] result, int i) {
        if (result[i] &amp;gt; result[i - 1]) {
            result[i + 2] = money[i] + result[i];
        } else {
            result[i + 2] = money[i] + result[i - 1];
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;느낀점&lt;/h3&gt;
&lt;p&gt;문제가 정말 어렵다고 느껴 졌습니다. 저는 집을 기준으로 하나씩 띄워 계산을 하는 방법을 생각 했는데 너무 로직이 복잡해지고 답도 계속 다르게 나와 맨탈이 터져 검색을 해보니 다른사람들이 푼 코드를 봤는데 정말 천재들은 많구나 다시 한번 느꼈습니다.&lt;/p&gt;
&lt;p&gt;그분들의 풀이를 참고해 &lt;code&gt;money[i]&lt;/code&gt; 를 기준으로 다 확인 해 주니 문제가 풀렸습니다. 정말 어렵지만 재밌는 문제였고 한번 더 발전하는 계기가 된거 같습니다.&lt;/p&gt;
&lt;h2&gt;참조&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://chaibin0.tistory.com/entry/%EB%8F%84%EB%91%91%EC%A7%88&quot;&gt;https://chaibin0.tistory.com/entry/도둑질&lt;/a&gt;&lt;/p&gt;</description>
      <category>개발공부/알고리즘</category>
      <category>java</category>
      <category>알고리즘</category>
      <category>프로그래머스</category>
      <author>백경훈</author>
      <guid isPermaLink="true">https://jar100.tistory.com/28</guid>
      <comments>https://jar100.tistory.com/28#entry28comment</comments>
      <pubDate>Mon, 22 Apr 2019 17:25:02 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 알고리즘 : 등굣길 (java)</title>
      <link>https://jar100.tistory.com/27</link>
      <description>&lt;h1&gt;프로그래머스 알고리즘 (java)&lt;/h1&gt;
&lt;h2&gt;등굣길&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42898?language=java&quot;&gt;프로그래머스 (등굣길)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://grepp-programmers.s3.amazonaws.com/files/ybm/056f54e618/f167a3bc-e140-4fa8-a8f8-326a99e0f567.png&quot; alt=&quot;등굣길&quot;&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;가장 왼쪽 위, 즉 집이 있는 곳의 좌표는 (1, 1)로 나타내고 가장 오른쪽 아래, 즉 학교가 있는 곳의 좌표는 (m, n)으로 나타냅니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;격자의 크기 m, n과 물이 잠긴 지역의 좌표를 담은 2차원 배열 puddles이 매개변수로 주어질 때, 학교에서 집까지 갈 수 있는 최단경로의 개수를 1,000,000,007로 나눈 나머지를 return 하도록 solution 함수를 작성해주세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;코드리뷰&lt;/h2&gt;
&lt;h3&gt;조건&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;최단거리를 가야하기 때문에 &lt;code&gt;왼쪽&lt;/code&gt; 과 &lt;code&gt;아래&lt;/code&gt; 밖에 못 움직인다.&lt;/li&gt;
&lt;li&gt;웅덩이가 있는곳은 못 지나간다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;풀이방향&lt;/h3&gt;
&lt;p&gt;이차원 배열을 만들고 웅덩이를 표시하고 거기서부터는 예전 수학시간에 배운 최단거리를 구하는 방법처럼 구해봤습니다. 웅덩이는 -1 로 미리 표시해 두고 최단거리를 구할 때 -1 이 나오면 0 으로 바꾸었 습니다.&lt;/p&gt;
&lt;p&gt;만약 m = 4, n = 2 웅덩이가 {2, 2}, {4, 2} 로 주어 진다면, 웅덩이를 표시하고 점을 하나 씩 탐색 해 가면서 점의 위치로 올수 있는 경우의 숫자들을 다 더해 줬습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biq2SE/btquJs1JQEC/amSonAR7KDhoMW3Q2bZKP0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biq2SE/btquJs1JQEC/amSonAR7KDhoMW3Q2bZKP0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biq2SE/btquJs1JQEC/amSonAR7KDhoMW3Q2bZKP0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/biq2SE/btquJs1JQEC/amSonAR7KDhoMW3Q2bZKP0/img.gif&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt;코드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class GoToSchool {
    public int solution(int m, int n, int[][] puddles) {
        int answer = 0;
        int[][] dp = new int[n + 1][m + 1];

        //시작위치를 1로 초기화
        dp[1][1] = 1;
        //웅덩이들 -1로 초기화
        for (int[] puddle : puddles) {
            dp[puddle[1]][puddle[0]] = -1;
        }

        for (int i = 1; i &amp;lt; dp.length; i++) {
            for (int j = 1; j &amp;lt; dp[i].length; j++) {
                // 웅덩이는 0 으로 바꾸고 넘어간다.
                if (dp[i][j] == -1) {
                    dp[i][j] = 0;
                } else {
                    if (i == 1) {
                        dp[i][j] += dp[i][j - 1];
                    } else {
                        dp[i][j] = (dp[i - 1][j] + dp[i][j - 1]) % 1000000007;
                    }
                }

                //마지막 값 answer
                if (j == dp[i].length - 1) {
                    answer = dp[i][j];
                }
            }
        }
        return answer;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;느낀점&lt;/h3&gt;
&lt;p&gt;테스트케이스는 쉽게 통과해 빠르게 풀거라 생각했었습니다. 그런데 제출을 해보니 거의 대부분의 케이스를 통과 못 했습니다.&lt;br&gt;왜 그럴까 생각해보니 &lt;code&gt;m, n&lt;/code&gt; 을 잘못 생각하고 있었다는것을 알게 되었습니다.&lt;br&gt;저는 웅덩이의 좌표는 &lt;code&gt;n, m&lt;/code&gt; 이고 &lt;code&gt;i, j&lt;/code&gt; 로 대입하면 될 것 이라 생각 했는데 글을 다시 읽어보니 &lt;code&gt;m, n&lt;/code&gt; 이었습니다. 결국 &lt;code&gt;j,i&lt;/code&gt; 로 대입해 풀었습니다.&lt;br&gt;문제의 조건을 재대로 파악 하지 못해 해맸던 문제 였습니다. 정말 문제의 조건을 잘 읽어야 겠다 생각이 들었습니다.&lt;/p&gt;</description>
      <category>개발공부/알고리즘</category>
      <category>java</category>
      <category>알고리즘</category>
      <category>프로그래머스</category>
      <author>백경훈</author>
      <guid isPermaLink="true">https://jar100.tistory.com/27</guid>
      <comments>https://jar100.tistory.com/27#entry27comment</comments>
      <pubDate>Mon, 22 Apr 2019 17:04:30 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 알고리즘 : 정수 삼각형 (java)</title>
      <link>https://jar100.tistory.com/26</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;
 &lt;h1&gt;프로그래머스 알고리즘 (java)&lt;/h1&gt;
&lt;h2&gt;정수 삼각형&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/43105?language=java&quot;&gt;프로그래머스 (정수 삼각형)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://grepp-programmers.s3.amazonaws.com/files/production/97ec02cc39/296a0863-a418-431d-9e8c-e57f7a9722ac.png&quot; alt=&quot;정수 삼각형&quot;&gt;&lt;/p&gt;
&lt;h2&gt;코드 리뷰&lt;/h2&gt;
&lt;p&gt;같은 삼각형의 꼭대기에서 바닥까지 이어지는 경로 중, 거쳐간 숫자의 합이 가장 큰 경우를 찾아보려고 합니다. 아래 칸으로 이동할 때는 대각선 방향으로 한 칸 오른쪽 또는 왼쪽으로만 이동 가능합니다. 예를 들어 3에서는 그 아래칸의 8 또는 1로만 이동이 가능합니다.&lt;/p&gt;
&lt;h3&gt;조건&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;맨위 부터 아래로 내려가며 숫자를 증가시킨다.&lt;/li&gt;
&lt;li&gt;마지막 까지 내려가 가장 큰 수를 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;풀이방향&lt;/h3&gt;
&lt;p&gt;현재 위치의 값을 구할 때 이전 값이 필요합니다.
그래서 저는 배열을 만들었고 이전 배열과 현재 배열을 더하는 식으로 접근 했습니다.
그러다 보니 양쪽 끝부분은 가지수가 1개이고 사이 &lt;code&gt;[j]&lt;/code&gt; 값 은 이전 &lt;code&gt;[j]&lt;/code&gt;, &lt;code&gt;[j - 1]&lt;/code&gt; 값을 비교해 큰 값을 더했습니다.&lt;/p&gt;
&lt;h3&gt;코드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class EssenceTriangle {
    private int answer = 0;

    public int solution(int[][] triangle) {
        this.answer = 0;
        for (int i = 1; i &amp;lt; triangle.length; i++) {
            int previewMax = triangle[i - 1].length;
            int max = triangle[i].length;

            triangle[i][0] = compareAnswer(triangle[i][0] + triangle[i - 1][0]);
            for (int j = 1; j &amp;lt; previewMax; j++) {
                int left = triangle[i - 1][j - 1];
                int right = triangle[i - 1][j];
                if (left &amp;gt; right) {
                    triangle[i][j] = compareAnswer( left + triangle[i][j]);
                } else {
                    triangle[i][j] = compareAnswer( right + triangle[i][j]);
                }
            }
            triangle[i][max - 1] = compareAnswer(triangle[i][max - 1] + triangle[i - 1][previewMax - 1]);

        }
        return this.answer;
    }

    private int compareAnswer(int newAnswer) {
        if (this.answer &amp;lt; newAnswer) {
            this.answer = newAnswer;
        }
        return newAnswer;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;느낀점&lt;/h3&gt;
&lt;p&gt;처음엔 배열을 새롭게 만들고 풀었는데 생각해보니 &lt;code&gt;triangle&lt;/code&gt; 배열을 그대로 사용해도 될 거라는 걸 깨닫고 리팩토링을 하였습니다.
그리고 answer 를 구할 때는&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;Arrays.stream(triangle[triangle.length - 1]).max().getAsInt();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;와 같이 재일 큰 값을 구했지만 &lt;code&gt;answer&lt;/code&gt; 를 &lt;code&gt;class 변수&lt;/code&gt;로 뽑고 배열의 각 값을 구할 때 &lt;code&gt;this.answer&lt;/code&gt; 와 비교해 &lt;code&gt;answer&lt;/code&gt;를 바꿔 값을 출력하게 바꿨습니다.&lt;/p&gt;

&lt;/article&gt;</description>
      <category>개발공부/알고리즘</category>
      <category>java</category>
      <category>알고리즘</category>
      <category>프로그래머스</category>
      <author>백경훈</author>
      <guid isPermaLink="true">https://jar100.tistory.com/26</guid>
      <comments>https://jar100.tistory.com/26#entry26comment</comments>
      <pubDate>Sat, 20 Apr 2019 15:16:44 +0900</pubDate>
    </item>
    <item>
      <title>Mybatis 와 JPA 비교</title>
      <link>https://jar100.tistory.com/25</link>
      <description>&lt;h1&gt;Mybatis 와 JPA&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Mybatis 특징&lt;/li&gt;
&lt;li&gt;JPA 특징&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Mybatis&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;JDBC&lt;/code&gt; 를 좀더 편하게 사용할 수 있도록 객체를 SQL 이나 저장 프로시저와 매핑 해주는 퍼시스턴스 프레임워크 SQL 구문을 java 메소드와 매핑해준다.&lt;/p&gt;
&lt;h3&gt;장점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;다른 프레임워크에 비해 간단하다.&lt;/li&gt;
&lt;li&gt;소스 코드와 SQL 의 분리 (생산성, DBA와의 협업)&lt;/li&gt;
&lt;li&gt;SQL을 직접 다뤄 복잡한 쿼리 작성, SQL 함수나 저장 프로시저를 자유롭게 이용가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;단점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;반복적인 코드와 CRUD SQL 작업&lt;/li&gt;
&lt;li&gt;SQL과 데이터베이스 벤더에 대한 종속성(오라클에서 mySQL 로 바꾸면 함수들을 바꿔줘야한다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ORM(JPA)&lt;/h2&gt;
&lt;p&gt;자바 객체를 데이터테이블과 매핑시킨다.&lt;br&gt;&lt;code&gt;ORM&lt;/code&gt; : 데이터베이스 객체를 자바 객체로 매핑하여 객체 간의 관계를 바탕으로 SQL을 자동으로 생성&lt;br&gt;&lt;code&gt;JPA&lt;/code&gt; : 자바 진영의 ORM 표준 기술&lt;/p&gt;
&lt;h3&gt;장점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;생산성 CRUD 같은 간단한 쿼리는 자동으로 된다.&lt;/li&gt;
&lt;li&gt;entity 에 추가 속성이 생기면 Mybatis 의 경우 쿼리에 각각 다 추가해줘야하지만 JPA는 Entity에 속성만 추가 시켜주면 된다.&lt;/li&gt;
&lt;li&gt;데이터 접근 추상화 벤더 독립성&lt;/li&gt;
&lt;li&gt;SQL 중심적인 개발에서 객체 중심으로 개발가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;단점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;상대적으로 높은 학습 곡선&lt;/li&gt;
&lt;li&gt;복잡한 쿼리작성의 어려움&lt;ul&gt;
&lt;li&gt;JPQL을 통해 해결가능&lt;/li&gt;
&lt;li&gt;Native SQL로 직접 작성가능&lt;/li&gt;
&lt;li&gt;mybatis 와 혼용가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;결론&lt;/h2&gt;
&lt;p&gt;JPA를 사용하면 mybatis 를 사용할 때 보다 아래 그림과 같이 중복을 제거할 수 있다.&lt;br&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d4zVY7/btquwmGC4Gt/lOApDf1swHB0ovYcotuqnK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d4zVY7/btquwmGC4Gt/lOApDf1swHB0ovYcotuqnK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d4zVY7/btquwmGC4Gt/lOApDf1swHB0ovYcotuqnK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd4zVY7%2FbtquwmGC4Gt%2FlOApDf1swHB0ovYcotuqnK%2Fimg.jpg&quot; width=&quot;100%&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;br&gt;그리고 더 나은 객체지향적 설계가 가능하다.&lt;br&gt;하지만 학습비용이 높다. 그러므로 아직은 mybatis와 JPA를 혼용 하면서 좀더 나은 코드로 발전시키면 될 것 같다.&lt;/p&gt;
&lt;h2&gt;참고&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=XQZY0yN9gz0&quot;&gt;https://www.youtube.com/watch?v=XQZY0yN9gz0&lt;/a&gt;&lt;/p&gt;</description>
      <category>개발공부/Spring</category>
      <category>jpa</category>
      <category>mybatis</category>
      <category>spring</category>
      <author>백경훈</author>
      <guid isPermaLink="true">https://jar100.tistory.com/25</guid>
      <comments>https://jar100.tistory.com/25#entry25comment</comments>
      <pubDate>Fri, 12 Apr 2019 17:58:09 +0900</pubDate>
    </item>
    <item>
      <title>Http 프로토콜 에서 get  과 post 의 차이</title>
      <link>https://jar100.tistory.com/24</link>
      <description>&lt;h1&gt;get 과 post 의 차이&lt;/h1&gt;
&lt;h2&gt;get 과 post는 무엇일까.&lt;/h2&gt;
&lt;p&gt;http 메소드중 하나 서버에 데이터를 주고 받을 때 사용하는 메소드 &lt;code&gt;get&lt;/code&gt;은 &lt;code&gt;select&lt;/code&gt; 성격을 갖고있다. &lt;code&gt;post&lt;/code&gt;는 서버의 값이나 상태를 바꿀 때 사용한다.&lt;/p&gt;
&lt;h2&gt;get 특징&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;get&lt;/code&gt;은 데이터를 조회 하는데 사용하는 메소드다.&lt;br /&gt;&lt;code&gt;get&lt;/code&gt;으로 서버에 데이터를 포함해 보낼 수도 있다.&lt;/p&gt;
&lt;p&gt;그럴 경우에는 &lt;code&gt;url&lt;/code&gt; 에 정보들 담아 요청을 보낸다.&lt;/p&gt;
&lt;pre class=&quot;ceylon&quot;&gt;&lt;code&gt;/RegisterDao.jsp?name1=value1&amp;amp;name2=value2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;? key = value 형태로 데이터를 보낸다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TzBC2/btquugHakKE/o92yH1zTlXWvIdAPjwB8Vk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TzBC2/btquugHakKE/o92yH1zTlXWvIdAPjwB8Vk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TzBC2/btquugHakKE/o92yH1zTlXWvIdAPjwB8Vk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTzBC2%2FbtquugHakKE%2Fo92yH1zTlXWvIdAPjwB8Vk%2Fimg.png&quot; width=&quot;100%&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;h2&gt;post 특징&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;get&lt;/code&gt; 과 다르게 http 메세지의 바디부분에 데이터를 담아 요청을 보낸다. &lt;code&gt;post&lt;/code&gt; 는 &lt;code&gt;http body&lt;/code&gt; 에 정보를 담아 &lt;code&gt;get&lt;/code&gt; 보다는 더 많은 데이터를 보낼 수 있다. 또한 &lt;code&gt;url&lt;/code&gt; 이 간소화 된다.&lt;/p&gt;
&lt;p&gt;하지만 &lt;code&gt;body&lt;/code&gt; 에 담고 &lt;code&gt;url&lt;/code&gt;에 데이터가 안보인다 해도 안전한 것은 아니다. 얼마든지 &lt;code&gt;Fiddler&lt;/code&gt;와 같은 툴로 요청과 데이터를 확인할 수 있다. 따라서 민감한 데이터는 암호화를 통해 보호 해야한다.&lt;/p&gt;
&lt;p&gt;또한 &lt;code&gt;post&lt;/code&gt; 로 데이터를 삭제 수정 할 수 있지만 메소드가 어떤 행동을 하는지 명확하게 하기 위해 &lt;code&gt;delet&lt;/code&gt; 와 &lt;code&gt;put&lt;/code&gt;, &lt;code&gt;patch&lt;/code&gt; 등으로 구분해서 사용하자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kTCvW/btquqkiMhPK/e5h6z4QF1JbU7Wdz7lhXf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kTCvW/btquqkiMhPK/e5h6z4QF1JbU7Wdz7lhXf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kTCvW/btquqkiMhPK/e5h6z4QF1JbU7Wdz7lhXf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkTCvW%2FbtquqkiMhPK%2Fe5h6z4QF1JbU7Wdz7lhXf0%2Fimg.png&quot; width=&quot;100%&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;h2&gt;get으로 데이터를 보내면 장점?&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;post&lt;/code&gt;는 &lt;code&gt;url&lt;/code&gt;로 같은 요청을 보내려면 &lt;code&gt;http body&lt;/code&gt; 에 데이터를 담아야 하기 때문에 어렵다. 하지만 &lt;code&gt;get&lt;/code&gt;으로 데이터를 보내면 &lt;code&gt;url&lt;/code&gt;에 데이터가 담기기 때문에 &lt;code&gt;url&lt;/code&gt;만으로 요청을 서버에 전달 할 수있다.&lt;/p&gt;
&lt;h2&gt;정리&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;get&lt;/code&gt;은 데이터를 조회 할때 사용하자.&lt;br /&gt;&lt;code&gt;post&lt;/code&gt; 는 데이터를 서버에 입력 할때 사용하자&lt;/p&gt;
&lt;p&gt;삭제와 수정은 &lt;code&gt;delet&lt;/code&gt;, &lt;code&gt;put&lt;/code&gt;, &lt;code&gt;patch&lt;/code&gt; 등을 사용하자.&lt;/p&gt;
&lt;h2&gt;참고&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.outsider.ne.kr/312#recentComments&quot;&gt;https://blog.outsider.ne.kr/312#recentComments&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://hongsii.github.io/2017/08/02/what-is-the-difference-get-and-post/&quot;&gt;https://hongsii.github.io/2017/08/02/what-is-the-difference-get-and-post/&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://www.javatpoint.com/get-vs-post&quot;&gt;https://www.javatpoint.com/get-vs-post&lt;/a&gt;&lt;/p&gt;</description>
      <category>개발공부/CS</category>
      <category>get</category>
      <category>http</category>
      <category>POST</category>
      <author>백경훈</author>
      <guid isPermaLink="true">https://jar100.tistory.com/24</guid>
      <comments>https://jar100.tistory.com/24#entry24comment</comments>
      <pubDate>Fri, 12 Apr 2019 14:47:27 +0900</pubDate>
    </item>
    <item>
      <title>equals 와 == 차이 (java)</title>
      <link>https://jar100.tistory.com/23</link>
      <description>&lt;h1&gt;equals 와 == 차이&lt;/h1&gt;
&lt;p&gt;면접을 보다 equals 와 == 의 차이를 설명해달라는 질문을 들었다.&lt;br&gt;정말 쉬운 질문 하지만 나는 면접에서 대답을 하지 못했다. 왜 그럴까?&lt;/p&gt;
&lt;p&gt;고민을 해보니 머리로는 이해 했지만 머리속의 내용을 풀어 말로 표현 하려니 정리가 안되서 그랬던거 같다.&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;equals()&lt;/code&gt; 와 &lt;code&gt;==&lt;/code&gt; 는 무슨 차이가 있을까?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;==&lt;/code&gt; 는 객체의 주소값을 비교하게 된다. 그래서 같은 값이라도 주소값이 다르게 되면 다르다고 나온다.&lt;br&gt;  따라서 &lt;code&gt;==&lt;/code&gt; 은 &lt;code&gt;int&lt;/code&gt; 와 같은 &lt;code&gt;Primitive Type&lt;/code&gt; 을 비교할 때 사용한다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;equals()&lt;/code&gt; 는 개발자가 정의한 논리적인 비교를 하게 된다.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
import org.junit.Test;

import java.util.Objects;

import static org.assertj.core.api.Java6Assertions.assertThat;

public class EqualsObjectTest {
    class EqualsObject {
        private int a;

        public EqualsObject(int a) {
            this.a = a;
        }

    }

    @Test
    public void 동일성() {
        int a = 7;
        int b = 7;
        System.out.println(Objects.hash(a));
        System.out.println(Objects.hash(b));
        assertThat(a == b).isTrue();
    }

    @Test
    public void 객체동일성비교() {
        EqualsObject a = new EqualsObject(1);
        EqualsObject b = new EqualsObject(1);
        System.out.println(a);
        System.out.println(b);
        assertThat(a == b).isFalse();
    }

    @Test
    public void 동등성() {
        EqualsObject a = new EqualsObject(1);
        EqualsObject b = new EqualsObject(1);
        assertThat(a.equals(b)).isTrue();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;예제와 같이 &lt;code&gt;EqualsObject&lt;/code&gt; &lt;code&gt;a&lt;/code&gt; 와 &lt;code&gt;b&lt;/code&gt; 는 각각 &lt;code&gt;int&lt;/code&gt; 1을 가진다.&lt;/p&gt;
&lt;p&gt;둘을 비교하면 &lt;code&gt;==&lt;/code&gt; 으로 비교하든 &lt;code&gt;equlas&lt;/code&gt; 로 비교하든 둘다 &lt;code&gt;false&lt;/code&gt; 가 나온다.&lt;/p&gt;
&lt;p&gt;이유는 &lt;code&gt;equals()&lt;/code&gt;를 재정의 하지 않았기 때문에 상위 클래스인 &lt;code&gt;Object&lt;/code&gt; 에서 정의된 &lt;code&gt;equals()&lt;/code&gt; 로 동작하게 된다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Object&lt;/code&gt;는 &lt;code&gt;equals()&lt;/code&gt; 을 아래와 같이 정의 하고있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public boolean equals(Object obj) {
        return (this == obj);
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그래서 아직은 둘다 주소를 비교해 &lt;code&gt;false&lt;/code&gt; 로 나온다.&lt;/p&gt;
&lt;p&gt;그래서 아래와 같이 &lt;code&gt;equlas()&lt;/code&gt; 를 재정의 해주면&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
class EqualsObject {
    private int a;

    public EqualsObject(int a) {
        this.a = a;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        EqualsObject that = (EqualsObject) o;
        return a == that.a;
    }

    @Override
    public int hashCode() {
        return Objects.hash(a);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;@Test
public void 동등성() {
    EqualsObject a = new EqualsObject(1);
    EqualsObject b = new EqualsObject(1);
    assertThat(a.equals(b)).isTrue();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;a 와 b는 같다고 나온다.&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;hashCode&lt;/code&gt; 를 같이 재정의 해주는 이유&lt;/h2&gt;
&lt;p&gt;list 는 주소를 참조해 보관하고 있는데&lt;br&gt;&lt;code&gt;hashCode()&lt;/code&gt; 를 재정의 해주지 않으면 다르다고 판별게 된다.&lt;/p&gt;
&lt;p&gt;그래서 &lt;code&gt;equals()&lt;/code&gt; 를 재정의 할 땐 &lt;code&gt;hashCode()&lt;/code&gt; 도 재정의 해주는게 좋다.&lt;/p&gt;</description>
      <category>개발공부/Java</category>
      <category>java</category>
      <author>백경훈</author>
      <guid isPermaLink="true">https://jar100.tistory.com/23</guid>
      <comments>https://jar100.tistory.com/23#entry23comment</comments>
      <pubDate>Thu, 11 Apr 2019 16:58:49 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 알고리즘 :  H-index (java)</title>
      <link>https://jar100.tistory.com/22</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;
 &lt;h1&gt;프로그래머스 알고리즘 (java)&lt;/h1&gt;
&lt;h2&gt;H-index&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42747?language=java&quot;&gt;프로그래머스 (H-index)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;코드 리뷰&lt;/h2&gt;
&lt;p&gt;어떤 과학자가 발표한 논문의 인용 횟수를 담은 배열 citations가 매개변수로 주어질 때, 이 과학자의 H-Index를 return 하도록 solution 함수를 작성해주는 문제 입니다.&lt;/p&gt;
&lt;h3&gt;조건&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;논문수 = 배열의크기 &lt;code&gt;n&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;인용 횟수 &lt;code&gt;h&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;인용횟수가 &lt;code&gt;h&lt;/code&gt; 인 논문의 수가 &lt;code&gt;h&lt;/code&gt; 이면 통과&lt;/li&gt;
&lt;li&gt;반복 횟수 &lt;code&gt;k&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;풀이 방향&lt;/h3&gt;
&lt;h4&gt;가정 -1&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;작은수로 정렬&lt;/li&gt;
&lt;li&gt;작은수를 기준으로 h 를 선정&lt;/li&gt;
&lt;li&gt;k  = 배열의 크기 - 기준인 h 의 인덱스&lt;/li&gt;
&lt;li&gt;k &amp;lt; h 보다 작으면 증가&lt;/li&gt;
&lt;li&gt;K &amp;gt;= h 일 때 까지 반복&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;가정 -1 문제&lt;/h4&gt;
&lt;p&gt;h가 바로 통과 함&lt;br&gt;
그럼 내림차순으로 정렬하고 해보자&lt;/p&gt;
&lt;h4&gt;가정-2&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;큰수로 정렬&lt;/li&gt;
&lt;li&gt;큰수를 기준으로 h 를 선정&lt;/li&gt;
&lt;li&gt;k  = 배열의 크기 - 기준인 h 의 인덱스&lt;/li&gt;
&lt;li&gt;k &amp;lt; h 보다 작으면 증가&lt;/li&gt;
&lt;li&gt;K &amp;gt;= h 일 때 까지 반복&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;기준을 잘못잡았다.&lt;/h4&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;k &amp;lt; h 보다 작으면 증가&lt;/li&gt;
&lt;li&gt;K &amp;gt;= h 일 때 까지 반복
이 아닌 k &amp;lt;= h 면 그만둬야함&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;코드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;import java.util.Arrays;

public class HIndex {
    public int solution(int[] citations) {
        int answer = 0;
        int length = citations.length;
        int h = 0;
        int k = 0;
        Arrays.sort(citations);

        for (int i = 0; i &amp;lt; citations.length; i++) {
            h = citations[i];
            k =  citations.length - i;
            if (k &amp;lt;= h) {
                answer = k;
                break;
            }
        }
        return answer;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;느낀 점&lt;/h3&gt;
&lt;p&gt;저는 알고리즘을 풀 때 어떤식으로 풀어야 쉽게 문제를 풀 수 있을지 생각하는 시간이 오래 걸렸습니다. 그래서 이번엔 가정을 새우고 그 가정에 따라 코드를 구현하고 반례가 있나 확인한 후 다시 가정을 수정하는 식으로 문제를 접근했더니 예전보다 코드구현 속도가 빨라진거 같았습니다. 문제를 해결할 때 이런식으로 접근하면 알고리즘 문제를 빠르게 풀 수 있을거 같다는 자신감을 얻었습니다.&lt;/p&gt;

&lt;/article&gt;</description>
      <category>개발공부/알고리즘</category>
      <category>java</category>
      <category>알고리즘</category>
      <author>백경훈</author>
      <guid isPermaLink="true">https://jar100.tistory.com/22</guid>
      <comments>https://jar100.tistory.com/22#entry22comment</comments>
      <pubDate>Thu, 21 Mar 2019 20:14:50 +0900</pubDate>
    </item>
  </channel>
</rss>