<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>효딩일지</title>
    <link>https://eunoo.tistory.com/</link>
    <description>으누의 공부 정리장</description>
    <language>ko</language>
    <pubDate>Wed, 23 Sep 2026 16:26:33 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>eunoo</managingEditor>
    <item>
      <title>[Spring] Dynamic Web Project Intellij 세팅</title>
      <link>https://eunoo.tistory.com/114</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Project Structure&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;918&quot; data-origin-height=&quot;453&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXGaQk/dJMcaiINpDI/4q27JXQmjAtUBdKvjfrtok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXGaQk/dJMcaiINpDI/4q27JXQmjAtUBdKvjfrtok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXGaQk/dJMcaiINpDI/4q27JXQmjAtUBdKvjfrtok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXGaQk%2FdJMcaiINpDI%2F4q27JXQmjAtUBdKvjfrtok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;918&quot; height=&quot;453&quot; data-origin-width=&quot;918&quot; data-origin-height=&quot;453&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0Kb08/dJMcaiPyxfF/fu90wvi0AVkT5zCRYaTkk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0Kb08/dJMcaiPyxfF/fu90wvi0AVkT5zCRYaTkk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0Kb08/dJMcaiPyxfF/fu90wvi0AVkT5zCRYaTkk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0Kb08%2FdJMcaiPyxfF%2Ffu90wvi0AVkT5zCRYaTkk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1246&quot; height=&quot;478&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;478&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;769&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bX4fYB/dJMcafk2PGf/Liwuhp8mzn7jPM5TQXzrd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bX4fYB/dJMcafk2PGf/Liwuhp8mzn7jPM5TQXzrd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bX4fYB/dJMcafk2PGf/Liwuhp8mzn7jPM5TQXzrd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbX4fYB%2FdJMcafk2PGf%2FLiwuhp8mzn7jPM5TQXzrd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1246&quot; height=&quot;769&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;769&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;633&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzyHAy/dJMcacPojOC/fgPAFKET8fIY26BkxcWyj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzyHAy/dJMcacPojOC/fgPAFKET8fIY26BkxcWyj0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzyHAy/dJMcacPojOC/fgPAFKET8fIY26BkxcWyj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzyHAy%2FdJMcacPojOC%2FfgPAFKET8fIY26BkxcWyj0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1196&quot; height=&quot;633&quot; data-origin-width=&quot;1196&quot; data-origin-height=&quot;633&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;633&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m2uD5/dJMcafehw2V/0TuuNZ3lOV4oWSUKMGKjP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m2uD5/dJMcafehw2V/0TuuNZ3lOV4oWSUKMGKjP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m2uD5/dJMcafehw2V/0TuuNZ3lOV4oWSUKMGKjP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm2uD5%2FdJMcafehw2V%2F0TuuNZ3lOV4oWSUKMGKjP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1202&quot; height=&quot;633&quot; data-origin-width=&quot;1202&quot; data-origin-height=&quot;633&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;507&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M5ZjR/dJMcaacX5Wc/GKZd4ffJeY9WCnLk61JgVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M5ZjR/dJMcaacX5Wc/GKZd4ffJeY9WCnLk61JgVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M5ZjR/dJMcaacX5Wc/GKZd4ffJeY9WCnLk61JgVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM5ZjR%2FdJMcaacX5Wc%2FGKZd4ffJeY9WCnLk61JgVK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1240&quot; height=&quot;507&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;507&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;633&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RJhLi/dJMcaiB1m4i/lGHqsvgwUj0SydjB3kkKDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RJhLi/dJMcaiB1m4i/lGHqsvgwUj0SydjB3kkKDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RJhLi/dJMcaiB1m4i/lGHqsvgwUj0SydjB3kkKDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRJhLi%2FdJMcaiB1m4i%2FlGHqsvgwUj0SydjB3kkKDK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1194&quot; height=&quot;633&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;633&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1195&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCW0y5/dJMcadHuvNp/O0Hxua7WggS3Y3UyQk11qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCW0y5/dJMcadHuvNp/O0Hxua7WggS3Y3UyQk11qk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCW0y5/dJMcadHuvNp/O0Hxua7WggS3Y3UyQk11qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCW0y5%2FdJMcadHuvNp%2FO0Hxua7WggS3Y3UyQk11qk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1195&quot; height=&quot;628&quot; data-origin-width=&quot;1195&quot; data-origin-height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Edit Configuration&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oO52r/dJMcacV820S/WjmxO4Ll313jtvkYD2mLB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oO52r/dJMcacV820S/WjmxO4Ll313jtvkYD2mLB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oO52r/dJMcacV820S/WjmxO4Ll313jtvkYD2mLB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoO52r%2FdJMcacV820S%2FWjmxO4Ll313jtvkYD2mLB0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;732&quot; height=&quot;720&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;719&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beXE0v/dJMcag5kSv6/mLKbrKFoZ5D0X0KgvXoxeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beXE0v/dJMcag5kSv6/mLKbrKFoZ5D0X0KgvXoxeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beXE0v/dJMcag5kSv6/mLKbrKFoZ5D0X0KgvXoxeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeXE0v%2FdJMcag5kSv6%2FmLKbrKFoZ5D0X0KgvXoxeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;727&quot; height=&quot;719&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;719&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <author>eunoo</author>
      <guid isPermaLink="true">https://eunoo.tistory.com/114</guid>
      <comments>https://eunoo.tistory.com/114#entry114comment</comments>
      <pubDate>Fri, 16 Jan 2026 09:41:33 +0900</pubDate>
    </item>
    <item>
      <title>[모던 자바 인 액션] Collectors 클래스</title>
      <link>https://eunoo.tistory.com/92</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;6장에서 배운 것&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Collectors 클래스로 컬렉션 만들고 사용하기&lt;/li&gt;
&lt;li&gt;스트림 리듀스&lt;/li&gt;
&lt;li&gt;특별한 리듀싱 요약 연산&lt;/li&gt;
&lt;li&gt;데이터 그룹화와 분할&lt;/li&gt;
&lt;li&gt;커스텀 컬렉터&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; Collector&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스트림 전체는 reduce(), 그룹별로 나눠 사용할 때는 collect() 메서드를 사용한다.&lt;/li&gt;
&lt;li&gt;collect메서드의 파라미터는 Collector 인터페이스이다.&lt;/li&gt;
&lt;li&gt;Collector 인터페이스의 구현 클래스 Collectors 클래스가 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  Collectors의 메서드 정리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약 연산 - summingInt, averagingInt, summarizingInt&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;summingInt, summingDouble 등 : 값을 누적하여 더한다.&lt;/li&gt;
&lt;li&gt;averagingInt, averagingDoublre 등 : 평균값 계산&lt;/li&gt;
&lt;li&gt;summarizingInt, summarizingDouble 등 : 합계, 평균, 최댓값, 최솟값 등을 한 번에 계산&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;import static java.util.stream.Collectors.*;

//summingInt 예시
int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));

//averagingInt 예시
double avgCalories = menu.stream().collect(averagingInt(Dish::getCalories));

//summarizingInt 예시
IntSummaryStatistics menuStatistics = menu.stream().collect(summarizingInt(Dish::getCalories));
//IntSummaryStatistics{count, sum, min, average, max} 값이 담겨있다.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최대값, 최솟값 구하기 - maxBy, minBy&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 점수 높은 학생 뽑기
OptionalInt topScore = studentStream.mapToInt(Student::getTotalScore).max();//Stream&amp;lt;Student&amp;gt; -&amp;gt; IntStream ,max 점수뽑기
Optional&amp;lt;Student&amp;gt; topStudent = stuStream1.max(Comparator.comparingInt(Student::getTotalScore)); // 점수 높은 학생 뽑기
Optional&amp;lt;Student&amp;gt; top = stuStream2.collect(Collectors.maxBy(Comparator.comparingInt(Student::getTotalScore)));//위와같음
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문자열 연결 - joining&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;joining 메서드는 내부적으로 StringBuilder를 이용해서 문자열을 하나로 만듦.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;import static java.util.stream.Collectors.*;

String stuNames = stuStream.map(Student::getName).collect(joining());
String stuNames = stuStream.map(Student::getName).collect(joining(&quot;,&quot;));
String stuNames = stuStream.map(Student::getName).collect(joining(&quot;,&quot;, &quot;[&quot;, &quot;]&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리듀싱 - reducing&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초기값에 BinaryOperator를 계산하여 누적함. reduce랑 동작방식 같음&lt;/li&gt;
&lt;li&gt;reducing 세 가지
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;reducing(초기값, Function, BinaryOperator)&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Function을 계산한 결과로 BinaryOperator를 실행.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reducing(초기값,BinaryOperator)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reducing(BinaryOperator)&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;reduce 메서드와 마찬가지로 초기값이 없으면 Optional로 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;livescript&quot;&gt;&lt;code&gt;// 메뉴의 모든 칼로리 합계 계산하기
int totalCalories = menu.stream().collect(reducing(0, Dish::getCalories, (i,j) -&amp;gt; i + j));

// 칼로리 높은 요리 찾기
Optional&amp;lt;Dish&amp;gt; mostCalorieDish = menu.stream().collect(reducing((d1, d2) -&amp;gt; d1.getCalories &amp;gt; d2.getCalories() ? d1 : d2));
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;collect와 reduce 차이
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;collect는 누적 계산 후 그 결과를 변환해도 되지만, reduce는 누적하여 계산한 결과를 변환하면 의미적으로 잘 못 사용되는 것이다.&lt;/li&gt;
&lt;li&gt;병렬 : reduce를 병렬 떄 사용하면 누적값에 대해 동시성 문제가 발생한다. 따라서 병렬 실행 때는 collect를 사용해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;그룹화 - groupingBy&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;종류 세 가지
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;groupingBy(Function)&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사실 &lt;code&gt;groupingBy(Function, toList())&lt;/code&gt; 이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;groupingBy(Function, Collector)&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Function으로 그룹화한 뒤, Collector 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;groupingBy(Function, Supplier)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;요리 종류로 단순 그룹화하기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;Map&amp;lt;Dish.Type, List&amp;lt;Dish&amp;gt;&amp;gt; dishesByType = menu.stream().collect(groupingBy(Dish::getType));&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;칼로리로 그룹화하기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;Map&amp;lt;CaloricLevel, List&amp;lt;Dish&amp;gt;&amp;gt; dishesByCaloricLevel = menu.stream().collect(groupingBy( dish -&amp;gt; {
    if(dish.getCalories() &amp;lt;= 400) {
        return CaloricLevel.DIET;
    } else if (dish.getCalories() &amp;lt;= 700) {
        return CaloricLevel.NORMAL;
    } else {
        return CaloricLevel.FAT;
    }
}));&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요리 종류로 그룹화한 후 필터링하기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 칼로리 높은 음식 그룹화하기
Map&amp;lt;Dish.Type, List&amp;lt;Dish&amp;gt;&amp;gt; dishesByType = menu.stream().collect(groupingBy(Dish::getType, filtering(dish -&amp;gt; dish.getCalories() &amp;gt; 500, toList())));&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요리 종류로 그룹화한 후 매핑하기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;// 이름으로 그룹화하기
Map&amp;lt;Dish.Type, List&amp;lt;String&amp;gt;&amp;gt; dishNamesByType = menu.stream().collect(groupingBy(Dish::getType), mapping(Dish::getName, toList()));&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다중화 그룹화
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;gourpingBy를 두 번 써서 여러 번 그룹화가 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;중첩 컬렉터 - collectingAndThen&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;collectingAndThen(Collector, Function)&lt;/li&gt;
&lt;li&gt;Collector 메서드를 실행한 결과로 Function을 실행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 타입으로 그룹화하고, 요리 중 칼로리 높은 것울 추출하고, 그 결과를 Optional::get을 실행하여 반환한다.
menu.stream().collect(groupingBy(Dish::getType, collectingAndThen(maxBy(comparingInt(Dish::getCalories)), Optional::get)));&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ture, false로 그룹화 - partitioningBy&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;partitioningBy(Predicate)&lt;/li&gt;
&lt;li&gt;partitioningBy(Predictae, Collector)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;// 채식인 요리, 아닌 요리로 그룹화하기
Map&amp;lt;Boolean, List&amp;lt;Dish&amp;gt;&amp;gt; partitionedMenu = menu.stream().collect(partitioningBy(Dish::isVegetarian));
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt; Collector 인터페이스의 추상 메서드&lt;/h2&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;public interface Collector&amp;lt;T, A, R&amp;gt; {
  Supplier&amp;lt;A&amp;gt; supplier();
  BiConsumer&amp;lt;A, T&amp;gt; accumulator();
  Function&amp;lt;A, R&amp;gt; finisher();
  BinaryOperator&amp;lt;A&amp;gt; combiner();
  Set&amp;lt;Characteristics&amp;gt; characteristics();
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;T는 수집될 스트림의 타입이다.&lt;/li&gt;
&lt;li&gt;A는 누적자, 즉 중간 결과를 누적하는 객체의 타입이다.&lt;/li&gt;
&lt;li&gt;R은 연산 결과 타입이다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>eunoo</author>
      <guid isPermaLink="true">https://eunoo.tistory.com/92</guid>
      <comments>https://eunoo.tistory.com/92#entry92comment</comments>
      <pubDate>Fri, 14 Jul 2023 22:52:07 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] 생성자 주입, 순환 참조(circular reference)</title>
      <link>https://eunoo.tistory.com/77</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;문제 발생&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부하면서 테스트를 하다가 다음과 같은 에러를 만났다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;172&quot; data-origin-height=&quot;137&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSku9T/btsbO3ru3RN/WuXZoN67gJdCV83AO9zZkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSku9T/btsbO3ru3RN/WuXZoN67gJdCV83AO9zZkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSku9T/btsbO3ru3RN/WuXZoN67gJdCV83AO9zZkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSku9T%2FbtsbO3ru3RN%2FWuXZoN67gJdCV83AO9zZkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;172&quot; height=&quot;137&quot; data-origin-width=&quot;172&quot; data-origin-height=&quot;137&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;br /&gt;Caused by: org.springframework.beans.factory.&lt;b&gt;BeanCurrentlyInCreationException&lt;/b&gt;: Error creating bean with name 'appConfig': Requested bean is currently in creation: Is there an unresolvable circular reference?&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순환 참조에 관한 에러인데, 순환 참조가 발생하면 &lt;b&gt;BeanCurrentlyInCreationException&lt;/b&gt;이 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순환 참조가 무엇인지 왜 발생했는지 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;문제 발생 이유&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순환 참조는 두 가지 조건이 부합하면 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 빈 A와 빈 B가 둘 다 &lt;b&gt;서로&lt;/b&gt;를 &lt;b&gt;의존&lt;/b&gt;하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2. DI 할 때, &lt;b&gt;생성자&lt;/b&gt;로 &lt;b&gt;주입&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 경우 AppConfig 클래스와 TransactionAdvice 클래스가 서로 의존하고 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[AppConfig.java]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1682055415061&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
public class AppConfig {
  
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Autowired
    TransactionAdvice transactionAdvice;
    
    @Bean
    public PointcutAdvisor transactionAdvisor() {
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setPointcut(transactionPointcut());
        advisor.setAdvice(transactionAdvice);
        return advisor;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[TransactionAdvice.java]&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1682055613696&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
@RequiredArgsConstructor
public class TransactionAdvice implements MethodInterceptor {
    private final PlatformTransactionManager transactionManager;
	... 생략
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보면 AppConfig에서 TransactionAdvice를 주입하고, TransactionAdvice에서 AppConfig에서 등록할 bean을 주입한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 TransactionAdvcie에서 &lt;b&gt;생성자 주입&lt;/b&gt;을 사용한다는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너는 빈을 등록할 때, 주입되는 빈이 있으면 그 빈을 먼저 등록 후, 빈을 주입해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AppConfig를 빈으로 등록하려고 하는데, TransactionAdvice가 주입된다. 그래서 TransactionAdvice를 빈으로 등록하려고 하는데, AppConfig의 PlatformTransactionManager를 생성자로 주입하려고 한다. 이렇게 순환 참조가 발생하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;문제 해결&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;setter 주입&lt;/b&gt;을 사용하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setter 주입은 권장되는 방법은 아니지만, 생성자 주입때문에 순환 참조가 발생할 경우 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[TransactionAdvice.java]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1682057179328&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
public class TransactionAdvice implements MethodInterceptor {
    private  PlatformTransactionManager transactionManager;

    public void setTransactionManager(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

	...생략
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[AppConfig.java]&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1682057247629&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
public class AppConfig {
  
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Autowired
    TransactionAdvice transactionAdvice;
    
    @Bean
    public PointcutAdvisor transactionAdvisor() {
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setPointcut(transactionPointcut());
        
        // setter로 주입
        transactionAdvice.setTransactionManager(transactionManager());
        advisor.setAdvice(transactionAdvice);
        return advisor;
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Spring</category>
      <author>eunoo</author>
      <guid isPermaLink="true">https://eunoo.tistory.com/77</guid>
      <comments>https://eunoo.tistory.com/77#entry77comment</comments>
      <pubDate>Fri, 21 Apr 2023 15:08:31 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] XML로 빈 등록하는 방법</title>
      <link>https://eunoo.tistory.com/76</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;스프링에서 설정 파일의 종류는 두 가지가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;java 파일&lt;/b&gt;과&lt;b&gt; xml 파일&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 설정 파일과 XML 설정 파일의 작성법에 대해 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시&amp;gt; UserDao에 ConnectionMaker가 의존한다.&lt;/p&gt;
&lt;pre id=&quot;code_1680495638595&quot; class=&quot;angelscript&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class UserDao {
    private ConnectionMaker connectionMaker;
    public void setConnectionMaker(ConnectionMaker connectionMaker) {
    	this.connectionMaker = connectionMaker;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1680496223285&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class DConnectionMaker implements ConnectionMaker {
    @Override
    public Connection getConnection(){...생략...}
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자바로 설정파일 작성&lt;/h3&gt;
&lt;pre id=&quot;code_1680488188472&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
public class AppConfig {

    @Bean
    public UserDao userDao(ConnectionMaker connectionMaker) {
    	UserDao userDao = new UserDao();
        userDao.setConnectionMaker(connectionMaker())
        return userDao;
    }
    
    @Bean
    public ConnectionMaker connectionMaker() {
        return new DConnectionMaker();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;XML로 설정파일 작성&lt;/h3&gt;
&lt;pre id=&quot;code_1680488298363&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;beans&amp;gt;
    &amp;lt;bean id=&quot;userDao&quot; class=&quot;&quot;com.springTest.UserDao&amp;gt;
    	&amp;lt;property name=&quot;네임&quot; ref=&quot;connectionMaker&quot;&amp;gt;
    &amp;lt;/bean&amp;gt;
    &amp;lt;bean id=&quot;connectionMaker&quot; class=&quot;com.springTest.DConnectionMaker&quot;/&amp;gt;
&amp;lt;/beans&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;property는 setter로 주입한다. 따라서 UserDao에서 setter 작성이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring</category>
      <author>eunoo</author>
      <guid isPermaLink="true">https://eunoo.tistory.com/76</guid>
      <comments>https://eunoo.tistory.com/76#entry76comment</comments>
      <pubDate>Fri, 21 Apr 2023 10:42:00 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] ObjectMapper</title>
      <link>https://eunoo.tistory.com/73</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Jackson에서 제공하는 ObjectMapper는 serialize(자바 객체를 JSON으로 변환) , deserialize(JSON을 자바 객체로 변환) 할 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. Jackson 라이브러리 종속성 추가한 후 사용&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Maven&amp;gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1673916097533&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.fasterxml.jackson.core&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;jackson-databind&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;2.12.3&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gradle&amp;gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1673916120951&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.3'&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. Java Object -&amp;gt; JSON&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1673916634098&quot; class=&quot;pgsql&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ObjectMapper mapper = new Objectmapper;
User user = new User(&quot;eun&quot;,20);

mapper.writeValue(new File(&quot;user.json&quot;,user));//json으로 변환 후 user.json 파일로 저장
String userAsString = mapper.writeValueAsAtring(user);//객체를 json(문자열)로 변환
//{&quot;name&quot;: &quot;eun&quot;, &quot;age&quot;:20}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. JSON -&amp;gt; Java Object&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1673917719091&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//String -&amp;gt; Object
String json = &quot;{ \&quot;name\&quot; : \&quot;eun\&quot; , \&quot;age\&quot; : 20 }&quot;;
User user = mapper.readValue(json, User.class);&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Spring</category>
      <author>eunoo</author>
      <guid isPermaLink="true">https://eunoo.tistory.com/73</guid>
      <comments>https://eunoo.tistory.com/73#entry73comment</comments>
      <pubDate>Tue, 17 Jan 2023 13:41:47 +0900</pubDate>
    </item>
    <item>
      <title>[Java] 추상화 (feat. 추상 클래스)</title>
      <link>https://eunoo.tistory.com/62</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;추상화란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 클래스의 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;공통부분을 뽑아&lt;/b&gt;&lt;/span&gt; 부모 클래스를 만드는 것을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속 계층을 보면 내려갈수록 구체화되어 있고, 올라갈수록 추상화되어있다. 다시 말하자면, 내려갈수록 세분화되어 있고, 올라갈수록 공통요소만 남는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서 추상화의 예로 추상 클래스, 추상 메서드, 인터페이스를 들 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;추상 클래스?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: &lt;b&gt;추상 메서드를 가지고 있는 클래스.&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;미완성 설계도&lt;/span&gt;&lt;/b&gt;. 미완성이기 때문에 &lt;b&gt;인스턴스를 생성할 수 없다.&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;추상 메서드?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;선언부만 있고, 구현부는 없는 메서드&lt;/b&gt;. &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;미완성 메서드&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;자식 클래스에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;오버라이딩을 통해 &lt;b&gt;구현부를 완성시켜야한다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1665783712910&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Marine{
    int x, y;
    void move(int x, int y){...}
    void stop(){...}
    void stimPack(){...}
}
class Tank{
    int x, y;
    void move(int x, int y){...}
    void stop(){...}
    void changeMode(){...}
}
class Dropship{
    int x, y;
    void move(int x, int y){...}
    void stop(){...}
    void load(){...}
    void unload(){...}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 게임에 나오는 유닛들을 클래스로 정의하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;공통부분&lt;/b&gt;을 뽑아내어 &lt;b&gt;Unit 추상 클래스&lt;/b&gt;를 만들고 Unit 클래스를 &lt;b&gt;상속&lt;/b&gt;받도록 작성해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1665783961589&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class Unit{//추상 클래스
    int x, y;
    abstract void move(int x, int y);//추상 메서드
    void stop(){...}
}

class Marine extends Unit{
    void move(int x, int y){...}
    void stimPack(){...}
}
class Tank extends Unit{
    void move(int x, int y){...}
    void changeMode(){...}
}
class Dropship extends Unit{
    void move(int x, int y){...}
    void unload(){...}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;stop메서드는 선언부와 구현부 모두 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Marine, Tank는 지상 유닛이고, Dropship은 공중유닛이기 때문에 이동하는 방법이 달라서 move메서드의 구현부 내용은 다를 것이다. 이렇게 &lt;b&gt;선언부는 같지만 구현부는 다른 메서드는 추상 메서드로 작성할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 다른 유닛들을 추가하려면 Unit 클래스를 상속받아 작성하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아예 처음부터 작성하는 것보단 공통적인 부분을 가지고 있는 추상 클래스를 상속받아 아직 미완성인 부분을 완성해나가며 작성하는 것이 더 효율적이다.&lt;/p&gt;</description>
      <category>Java</category>
      <author>eunoo</author>
      <guid isPermaLink="true">https://eunoo.tistory.com/62</guid>
      <comments>https://eunoo.tistory.com/62#entry62comment</comments>
      <pubDate>Sat, 15 Oct 2022 07:05:41 +0900</pubDate>
    </item>
    <item>
      <title>[Java] 다형성</title>
      <link>https://eunoo.tistory.com/61</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;다형성이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;여러 형태의 데이터를 가질 수 있는 능력.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서 다형성을 잘 나타낸 것은&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;부모 클래스 타입의 참조변수가 자식 클래스 타입의 인스턴스를 참조할 수 있다&lt;/b&gt;&lt;/span&gt;는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1665610950501&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Tv{
    boolean power;
    int channel;

    void power(){power= !power;}
    void channelUp(){++channel;}
    void channelDown(){--channel;}
    void method(){...}
}

class SmartTv extends Tv{
    String text;
    void caption(){...}
    void method(){...}// 오버라이드
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 SmartTv 클래스는 Tv 클래스를 상속받았다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Tv t1 = new SmartTv();&lt;br /&gt;SmartTv t2 = new SmartTv();&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;같은 SmartTv의 인스턴스이지만 t1과 t2의 차이는 뭘까?&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;t1은 타입이 Tv 클래스이다. 즉, Tv 클래스의 멤버만 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;t2는 Tv 클래스의 멤버와 SmartTv 클래스의 멤버 모두 사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하자면 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;u&gt;같은 클래스의 인스턴스이더라도 참조변수의 타입에 따라 사용할 수 있는 멤버가 다르다.&lt;/u&gt;&lt;/b&gt;&lt;/span&gt; 이것이 다형성의 핵심이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;주의할 점&lt;/span&gt;: t1이 method()를 호출한다면?&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;오버라이드된 SmartTv의 method()를 호출하는 것.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 타입인 참조변수가 메서드를 호출할 때, 보통 부모의 메서드를 호출하는 것이지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오버라이딩한 메서드는 자식에서 호출&lt;/b&gt;하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참조변수의 형변환&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동 형변환 : 자식 타입을 부모 타입으로 변환할 때.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강제 형변환 : 부모 타입을 자식 타입으로 변환할 때. 단, 인스턴스가 자식일 때만 형변환을 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1665613147583&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Tv t = new SmartTv(); //자동 형변환

Tv t2 = new SmartTv();
SmartTv st1 = (SmartTv) t2; //강제 형변환

Tv t3= new Tv();
SmartTv st2 = (SmartTv) t3;//에러.부모 인스턴스가 자식 타입이 될 순 없음.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강제 형변환 시 참조변수가 참조하는 것이 자식 인스턴스일때만 가능하기 때문에 먼저 타입을 확인하는 작업이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는&lt;b&gt;&amp;nbsp;instanceof 연산자를 통해 타입을 확인&lt;/b&gt;할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1665611936239&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;void convert(Tv t){
    if(t instanceof SmartTv){//t가 SmartTv의 인스턴스인지 확인 후 강제 형변환
        SmartTv st = (SmartTv)t;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;참조변수의 형변환&lt;/span&gt;&lt;/b&gt;을 통해 참조변수가 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;사용할 멤버의 개수를 조절&lt;/b&gt;&lt;/span&gt;할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다형성의 예시)&lt;/p&gt;
&lt;pre id=&quot;code_1665614172856&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Product{}
class Computer extends Product{}
class Tv extends Product{}
class Audio extends Product{}

class Buyer{
    Product cart[] = new Product[10];
    int i=0;
    void buy(Product p){
        cart[i++] = p;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;매개변수의 다형성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Buyer 클래스의 buy메서드를 보면 매개변수 타입이 Product이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Computer 타입으로 정의하면 buy메서드에는 Computer만 들어올 수 있다. 그럼 또 Tv, Audio에 대한 buy메서드를 작성해주어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Product 타입으로 정의하면 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;매개변수로 Product의 자손 타입의 참조변수가 들어올 수 있기 때문에&lt;/b&gt;&lt;/span&gt; 하나의 메서드로 간단히 처리할 수 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;여러 종류의 객체를 하나의 배열로 다루기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 타입의 배열을 사용하면 여러 자식 객체를 하나로 묶어 사용할 수가 있다. 여러 종류의 객체를 하나의 배열로 묶을 수 있다는 소리다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구입한 제품을 담기 위해 Buyer에 Product 배열인 cart을 작성하였다. 구입을 하면 제품이 배열 cart에 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제품 클래스의&lt;span style=&quot;color: #006dd7;&quot;&gt; &lt;b&gt;조상인 Product 타입의 배열&lt;/b&gt;&lt;/span&gt;을 사용함으로써&lt;span style=&quot;color: #006dd7;&quot;&gt; &lt;b&gt;여러 종류의 제품들&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(Product의 자손들)&lt;/span&gt;&lt;/span&gt;을 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;하나의 배열&lt;/b&gt;&lt;/span&gt;로 관리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java</category>
      <author>eunoo</author>
      <guid isPermaLink="true">https://eunoo.tistory.com/61</guid>
      <comments>https://eunoo.tistory.com/61#entry61comment</comments>
      <pubDate>Thu, 13 Oct 2022 07:53:20 +0900</pubDate>
    </item>
    <item>
      <title>[Java] 캡슐화</title>
      <link>https://eunoo.tistory.com/60</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;캡슐화&lt;/b&gt;란 쉽게 말해 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;데이터 감추기&lt;/b&gt;&lt;/span&gt;이다. 즉 외부로부터 접근을 막는 것을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;접근 제어자&lt;/b&gt;&lt;/span&gt;를 통해&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt; 캡슐화&lt;/b&gt;&lt;/span&gt;를 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;접근 제어자의 종류&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;private : 클래스 내에서만 접근 가능&lt;/li&gt;
&lt;li&gt;(default) : 같은 패키지 내에서만 접근 가능&lt;/li&gt;
&lt;li&gt;protected : 같은 패키지, 자손클래스에서 접근 가능&lt;/li&gt;
&lt;li&gt;public : 제한 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;접근 제어자를 사용하는 이유&lt;/h4&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;외부에서는 접근하지 않고, 내부에서만 쓰이는 부분은 감추기 위해&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접근 제어자를 사용함으로써 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;클래스 내부의 데이터를 보호&lt;/b&gt;&lt;/span&gt;할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;멤버변수를 private으로 하여&lt;/b&gt; 외부로부터 접근을 막는다. 대신 멤버변수의 값을 읽는 getter와 멤버변수의 값을 변경하는 setter를 public으로 작성하여 간접적으로 멤버변수에 접근을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 &lt;b&gt;내부에서만 쓰이는 멤버도 private&lt;/b&gt;으로 하여 클래스 내부를 감춘다. 외부에서 필요없는 부분은 외부로 노출시키지 않음으로써 복잡성을 줄인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속을 통해 확장 가능한 클래스&lt;b&gt;(부모클래스)의 멤버는 protected&lt;/b&gt;로 하여 외부로부터 접근 제한을 주되, 자식 클래스에서는 접근 가능하게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;접근 제어자의 범위는 항상 최소화&lt;/b&gt;시키고 필요할 때 넓히면 된다는 것을 명심하자!&lt;/p&gt;</description>
      <category>Java</category>
      <author>eunoo</author>
      <guid isPermaLink="true">https://eunoo.tistory.com/60</guid>
      <comments>https://eunoo.tistory.com/60#entry60comment</comments>
      <pubDate>Tue, 11 Oct 2022 08:50:44 +0900</pubDate>
    </item>
    <item>
      <title>[Java] 인터페이스</title>
      <link>https://eunoo.tistory.com/57</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;추상메서드의 집합&lt;/b&gt;&lt;/span&gt;이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스는 다음과 같은 특징을 가지고 있다.&lt;/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;public static final&lt;/b&gt; 이며, 생략할 수 있다.&lt;/li&gt;
&lt;li&gt;인터페이스의 메서드는 &lt;b&gt;public abstract&lt;/b&gt; 이며, 생략할 수 있다. (단, static 메서드와 디폴트 메서드는 예외)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인터페이스의 상속&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스의 조상은 인터페이스만 가능하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다중 상속&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인터페이스의 구현&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스의 추상 메서드를 완성을 해야 사용이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 인터페이스는 그 자체로 인스턴스를 생성할 수 없고, 인터페이스를 구현한 클래스를 선언 후 사용이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현한다는 의미의 implements를 사용하여 인터페이스를 구현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1664017651226&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Fightable{
	void move(int x, int y); // public abstract 생략
   	void attack(Unit u);// public abstract 생략
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1664017734842&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Fighter implements Fightable{
	public void move(int x, int y){/*내용생략*/}
    	public void attack(Unit u){/*내용생략*/}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fighter 클래스는 Fightable 인터페이스를 구현한 구현 클래스이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fightable 인터페이스의 추상 메서드를 Fighter 클래스에서 모두 오버라이딩하여 작성해야 한다. 모두 오버라이딩하지 않고 일부의 메서드만 작성한다면, Fighter 클래스 앞에 abstract를 붙여 추상 클래스로 선언해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인터페이스의 다형성&lt;/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;/ul&gt;
&lt;pre id=&quot;code_1664172681267&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Fightable f = new Fighter();
//Fightable f = (Fightable) new Fighter(); 와 같음. 인터페이스 타입으로 자동 형변환.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;인터페이스 왜 사용할까? 인터페이스의 장점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;1. 변경에 유리한 코드, 느슨한 결합&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;인터페이스는 두 객체 간의 연결을 돕는다. A와 B라는 클래스가 있을 때, 사이에 I라는 인터페이스를 두어 유연한 코드, 변경에 유리한 코드를 만들 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[직접적인 관계]&lt;/p&gt;
&lt;pre id=&quot;code_1664173684438&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class A{
	public void methodA(B b){  b.methodB();  }
}
class B{
	public void methodB(){  System.out.println(&quot;methodB()&quot;);  }
}
class InterfaceTest(){
	public static void main(String args[]){
    		A a = new A();
        	a.methodA(new B());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A의 methodA()에서 매개변수 타입을 B클래스에서 C클래스로 변경하려고 할 때, A클래스의 변경이 불가피하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 아래와 같이 인터페이스를 사용하면 &lt;b&gt;A 클래스의 변경이 필요없다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[간접적인 관계]&lt;/p&gt;
&lt;pre id=&quot;code_1664173951420&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class A{
	public void methodA(I i){  i.methodTest();  }
}
interface I {  void methodTest();  }
class B implements I {
	public void methodTest(){
    	System.out.println(&quot;B클래스의 methodTest()&quot;);
    }
}
class C implements I {
	public void methodTest(){
    	System.out.println(&quot;C클래스의 methodTest()&quot;);
    }
}
class InterfaceTest{
	public static main(String args[]){
    	A a = new A();
        a.methodA(new B());//B클래스의 methodTest()
        a.methodA(new C());//C클래스의 methodTest()
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;개발 시간을 단축시킨다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A클래스에서 B클래스를 사용한다했을 때, B클래스를 인터페이스의 구현 클래스로 정의한다면 B가 구현이 안되어있어도 A를 작성하는 것이 가능하다. A에서는 선언부만 알면 되기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;서로 관계없는 클래스들을 관계 맺어 줄 수 있다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무런 관계가 없는 클래스들에게 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어 줄 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;디폴트 메서드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스에서 추상 메서드를 추가하거나 변경하면, 그 구현 클래스 변경 역시 불가피하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 구현 클래스의 변경을 방지하기 위해 JDK1.8 부터 인터페이스에 디폴트 메서드라는 개념이 추가되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;디폴트 메서드&lt;/b&gt;는&lt;b&gt; 구현부가 있는 메서드&lt;/b&gt;로 인터페이스에 추가되어도 구현 클래스의 변경이 필요없다.&lt;/p&gt;
&lt;pre id=&quot;code_1666486148316&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface MyInterface{
	void method();
    	default void newMethod(){ ... }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신&lt;span style=&quot;color: #009a87;&quot;&gt; &lt;b&gt;디폴트 메서드 간의 충돌&lt;/b&gt;&lt;/span&gt;이 발생할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 인터페이스의 디폴트 메서드 충돌 시, 인터페이스의 구현 클래스에서 &lt;b&gt;오버라이딩 필요&lt;/b&gt;하다.&lt;/li&gt;
&lt;li&gt;디폴트 메서드와 부모 클래스의 메서드 충돌 시, &lt;b&gt;부모 클래스의 메서드가 상속&lt;/b&gt;된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Java</category>
      <author>eunoo</author>
      <guid isPermaLink="true">https://eunoo.tistory.com/57</guid>
      <comments>https://eunoo.tistory.com/57#entry57comment</comments>
      <pubDate>Sat, 24 Sep 2022 20:10:51 +0900</pubDate>
    </item>
    <item>
      <title>SQL문 정리</title>
      <link>https://eunoo.tistory.com/36</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;테이블 컬럼 보기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;show colums from [테이블명];&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블 속성 삭제&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;alter table [스키마명].[테이블명] drop [속성명];&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제약 조건명 보기 - 제약 조건명 찾아서 복사&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;select * from information_schema.table_constraints;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 속성에 pk 조건 추가&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;alter table [&lt;span style=&quot;color: #006dd7;&quot;&gt;스키마명&lt;/span&gt;].[&lt;span style=&quot;color: #006dd7;&quot;&gt;테이블명&lt;/span&gt;] modify column &lt;span style=&quot;color: #006dd7;&quot;&gt;속성명&lt;/span&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;속성타입&lt;/span&gt; primary key;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fk 연결 끊기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;alter table &lt;span style=&quot;color: #006dd7;&quot;&gt;USER_SECRET&lt;/span&gt; drop foreign key &lt;span style=&quot;color: #006dd7;&quot;&gt;FK_USER_TO_USER_SECRET_1&lt;/span&gt;;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fk 연결 하기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;alter table &lt;span style=&quot;color: #006dd7;&quot;&gt;USER_SECRET&lt;/span&gt; add foreign key (&lt;span style=&quot;color: #006dd7;&quot;&gt;user_id&lt;/span&gt;) references &lt;span style=&quot;color: #006dd7;&quot;&gt;USER&lt;/span&gt; (&lt;span style=&quot;color: #006dd7;&quot;&gt;user_id&lt;/span&gt;) on delete cascade on update cascade;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컬럼 타입 수정하기&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;alter table [테이블명] modify [속성이름] [바꿀타입];&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 컬럼 뒤로 컬럼 이동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;ALTER TABLE &lt;span style=&quot;color: #006dd7;&quot;&gt;user_pwd_upd_hist&amp;nbsp;&lt;/span&gt; MODIFY COLUMN &lt;span style=&quot;color: #006dd7;&quot;&gt;user_pwd&lt;/span&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;varchar(50)&lt;/span&gt; AFTER &lt;span style=&quot;color: #006dd7;&quot;&gt;user_id&lt;/span&gt;;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컬럼 첫번째 위치로 이동&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;ALTER TABLE 테이블명 MODIFY COLUMN 컬럼명 자료형 FIRST;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>데이터베이스</category>
      <author>eunoo</author>
      <guid isPermaLink="true">https://eunoo.tistory.com/36</guid>
      <comments>https://eunoo.tistory.com/36#entry36comment</comments>
      <pubDate>Thu, 11 Aug 2022 20:57:11 +0900</pubDate>
    </item>
  </channel>
</rss>