<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>폐관코딩</title>
    <link>https://shutcoding.tistory.com/</link>
    <description>하도 공부안해서 만드는 블로그</description>
    <language>ko</language>
    <pubDate>Sat, 11 Apr 2026 07:44:26 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>닥치고개돌</managingEditor>
    <image>
      <title>폐관코딩</title>
      <url>https://tistory1.daumcdn.net/tistory/3077726/attach/d07414d3da64461cba8056ee39cc0172</url>
      <link>https://shutcoding.tistory.com</link>
    </image>
    <item>
      <title>이걸 카카오 cdn에 저장하는건가?</title>
      <link>https://shutcoding.tistory.com/entry/%EC%9D%B4%EA%B1%B8-%EC%B9%B4%EC%B9%B4%EC%98%A4-cdn%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%98%EB%8A%94%EA%B1%B4%EA%B0%80</link>
      <description>&lt;p&gt;&lt;figure class=&quot;fileblock&quot; data-ke-align=&quot;alignCenter&quot;&gt;&lt;a href=&quot;https://blog.kakaocdn.net/dn/c45q7Q/btsKRGckbjK/1HT8j7565SYEp2HUmio28K/plugins.bundle.min.js?attach=1&amp;amp;knm=tfile.js&quot; class=&quot;&quot;&gt;
    &lt;div class=&quot;image&quot;&gt;&lt;/div&gt;
    &lt;div class=&quot;desc&quot;&gt;&lt;div class=&quot;filename&quot;&gt;&lt;span class=&quot;name&quot;&gt;plugins.bundle.min.js&lt;/span&gt;&lt;/div&gt;
&lt;div class=&quot;size&quot;&gt;2.16MB&lt;/div&gt;
&lt;/div&gt;
  &lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 카카오 cdn에 저장하는건가?&lt;/p&gt;</description>
      <author>닥치고개돌</author>
      <guid isPermaLink="true">https://shutcoding.tistory.com/103</guid>
      <comments>https://shutcoding.tistory.com/entry/%EC%9D%B4%EA%B1%B8-%EC%B9%B4%EC%B9%B4%EC%98%A4-cdn%EC%97%90-%EC%A0%80%EC%9E%A5%ED%95%98%EB%8A%94%EA%B1%B4%EA%B0%80#entry103comment</comments>
      <pubDate>Fri, 22 Nov 2024 14:24:02 +0900</pubDate>
    </item>
    <item>
      <title>[TDD한걸음] 2편 따라하면 바로 완성되는 TDD</title>
      <link>https://shutcoding.tistory.com/entry/TDD%ED%95%9C%EA%B1%B8%EC%9D%8C-2%ED%8E%B8-%EB%94%B0%EB%9D%BC%ED%95%98%EB%A9%B4-%EB%B0%94%EB%A1%9C-%EC%99%84%EC%84%B1%EB%90%98%EB%8A%94-TDD</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;(comming soon)&lt;/p&gt;</description>
      <category>TDD한걸음</category>
      <author>닥치고개돌</author>
      <guid isPermaLink="true">https://shutcoding.tistory.com/102</guid>
      <comments>https://shutcoding.tistory.com/entry/TDD%ED%95%9C%EA%B1%B8%EC%9D%8C-2%ED%8E%B8-%EB%94%B0%EB%9D%BC%ED%95%98%EB%A9%B4-%EB%B0%94%EB%A1%9C-%EC%99%84%EC%84%B1%EB%90%98%EB%8A%94-TDD#entry102comment</comments>
      <pubDate>Tue, 26 Mar 2024 18:56:03 +0900</pubDate>
    </item>
    <item>
      <title>HttpStatus 잘 사용하는법</title>
      <link>https://shutcoding.tistory.com/entry/HttpStatus-%EC%9E%98-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;RestAPI 요청을 하면 HTTP status와 함게 응답을 내려준다.&lt;br /&gt;이 글은 요청에 대한 값이 없을때 http status가 200인가,400인가 ,404인가에 대한 고민을 하다가 찾아본 결과를 정리하는 글이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Resources와 representation의 차이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 RFC에서 404 Not Found에 대한 정의를 보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;oxygene&quot;&gt;&lt;code&gt;[https://tools.ietf.org/html/rfc7231#section-6.5.4](https://tools.ietf.org/html/rfc7231#section-6.5.4)The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not    willing to disclose that one exists. A 404 status code does not    indicate whether this lack of representation is temporary or permanent; the 410 (Gone) status code is preferred over 404 if the origin server knows, presumably through some configurable means, that the condition is likely to be permanent.   
A 404 response is cacheable by default; i.e., unless otherwise indicated by the method definition or explicit cache controls (see  
 [Section 4.2.2 of [RFC7234]](https://datatracker.ietf.org/doc/html/rfc7234#section-4.2.2)).&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;요청한 리소스가 없을 때 가리킨다. 더 정확히는 요청한 리소스에 대한 현재 representation 을 찾을 수 없을 때 사용한다고 한다. 간단하게 설명하면 해당 링크가 존재하지 않는다는 뜻&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 resource와 representation을 구분해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET 메서드의 정의는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;oxygene&quot;&gt;&lt;code&gt;The GET method requests transfer of a current selected representation
for the target resource.&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;즉, target resource에 대한 현재의 선택된 representation 하나를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 정의에서 &amp;ldquo;target resource&amp;rdquo;란 &lt;a href=&quot;https://example.org/greeting&quot;&gt;https://example.org/greeting&lt;/a&gt; 라는 uri가 가리키는 리소스, 바로 HTTP 요청의 대상이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;그럼 &amp;ldquo;현재의 선택된 representation&amp;rdquo;이란 무엇인가? 어떤 리소스의 특정 시점의 상태를 반영하고 있는 정보이다. 하나의 representation은 representation data와 representation metadata로 구성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 리소스에서 hello라는 응답이 왔으면 &amp;ldquo;hello&amp;rdquo;가 representation data이고, &amp;ldquo;Content-Type: text/plain&amp;rdquo;과 &amp;ldquo;Content-Language: en&amp;rdquo;이 representation metadata이다.&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;쉽게말해 resource는 요청한 uri, representation은 리소스에 대한 리턴값이라고 생각하면된다. 즉 성공시 리턴값, 실패시 에러메시지 또한 representation이다.&lt;br /&gt;-&amp;gt; 사실 깊게 들어가면 http메시지의 payload로 전달되는 모든 것도 하나의 representation이지만 여기선 httpstatus에 대한 주제를 다룸으로 리턴값으로만 한정. 자세한 내용은 (&lt;a href=&quot;https://blog.npcode.com/2017/04/03/rest%EC%9D%98-representation%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80/)%EC%B0%B8%EC%A1%B0&quot;&gt;https://blog.npcode.com/2017/04/03/rest%EC%9D%98-representation%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80/)&lt;/a&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&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;br /&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;GET /users/{userId} : 조회한 userId가 없을경우 404&lt;br /&gt;-&amp;gt; 위에 첨부된 404 내용을 보면 리소스가 존재하고, 그에대한 응답(에러메시지)도 존재함으로 404가 적합함&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;GET /usersff/{userId} : 해당 리소스가 없음으로 404&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;GET /users?name='test' : 검색한 name이 없을경우 200&lt;br /&gt;-&amp;gt; /users란 리소스는 존재, representation도 빈값으로 존재&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;POST /users/login : 로그인 요청시 페이로드가 잘못된경우 ??&lt;br /&gt;-&amp;gt; 가장 논란이 많은부분. 계정이 없는경우 400, 404, 200 등 다양한 의견이 있다.&lt;br /&gt;내용을 들어보면 모두 그럴듯함. 400은 로그인은 이미 존재하는 계정이라는 전제하에 시도하는데 없는 계정을 요청했다면 요청자체가 잘못이라 400이다, 없는 계정요청이니 404다, 요청은 성공했고 로그인에 대한 예외상태를 상세히 나누면 해커들의 먹이가되기에 200으로 하고 로그인 실패만 나타낸다 등.&lt;br /&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 data-ke-size=&quot;size16&quot;&gt;나머지 부분은 논란의 여지가 크지않아 명세에 맞게 잘 사용하면 될듯!&lt;/p&gt;</description>
      <category>분석설계고민</category>
      <author>닥치고개돌</author>
      <guid isPermaLink="true">https://shutcoding.tistory.com/101</guid>
      <comments>https://shutcoding.tistory.com/entry/HttpStatus-%EC%9E%98-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EB%B2%95#entry101comment</comments>
      <pubDate>Thu, 21 Mar 2024 11:48:12 +0900</pubDate>
    </item>
    <item>
      <title>과제테스트 회고</title>
      <link>https://shutcoding.tistory.com/entry/%EA%B3%BC%EC%A0%9C%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;과제 테스트를 끝냈다.&lt;br /&gt;기간은 일주일이 주어졌지만 실질적으로 작업 한 시간은 주말 2틀정도?&lt;br /&gt;왜 하필 그 전주에는 해외여행다녀와서 여독이 있었으며, 업무는 왜 또 많았고, 술자리도 많았을까? 머피의 법칙 같은걸까?(머피 rosha...)&lt;br /&gt;핑계는 이정도하고 잘한 점, 잘못한 점, 아쉬웠던 점, 앞으로 점점 발전할 점에 대한 회고를 기록하려 한다.&lt;br /&gt;다른 사람이 과제 테스트를 진행하기 전에 이 글을 보면 도움이 될 수 있도록 상세히...&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;잘한 점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐가 있으려나? 있긴하려나&lt;br /&gt;굳이 생각해보자면, 과제테스트를 시도했던 점? 뭔가 결과를 내기위해 몰입했던 점?, 실제로 TDD로 구현했던 점? 좋은 코드를 짜기위해 고민했던 점?&lt;br /&gt;생각해보니 많은데 전부 잘 한 부분이면서 못한 부분인 아이러니한 상황&lt;br /&gt;먼저, 과제테스트를 시도했던점은 제일 잘 한 부분인것같다. 밑에서 적겠지만 이번 과제테스트로 굉장히 많이 배우고, 성장한게 느껴졌다. 일단 부딪혀봐야 깨지고 성장한다는 말이 뭔지 느낄 수 있었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-19 오후 5.15.36.png&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;1010&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cn5YdF/btsFUcT4RVF/Jwn5VUUlTn0tbvIMvBRwBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cn5YdF/btsFUcT4RVF/Jwn5VUUlTn0tbvIMvBRwBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cn5YdF/btsFUcT4RVF/Jwn5VUUlTn0tbvIMvBRwBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcn5YdF%2FbtsFUcT4RVF%2FJwn5VUUlTn0tbvIMvBRwBK%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;400&quot; height=&quot;371&quot; data-filename=&quot;스크린샷 2024-03-19 오후 5.15.36.png&quot; data-origin-width=&quot;1088&quot; data-origin-height=&quot;1010&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;erlang-repl&quot;&gt;&lt;code&gt;이 세계 벽 절대 안 높아. 할 수 있어!
남자는 뭐? 자신감! 자신감! 남자는 뭐? 자신감이야.
일단 붙어봐야 될 것 아니야. 저질러보고. 깨지고, 박어.
가슴만 뛰는 개발자 아니라, 가슴하고 내가 같이 뛰어야 돼.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;갓웅정의 명언. 겪어보고 나서야 이해가 되는 말이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두번째로 결과를 내기 위해 몰입 했던 점은, 내가 개발하면서 하루종일 앉아서 집중하고, 늦은 시간까지 열정적으로 무언갈 만든게 최근 몇 년간 있었던가? 익숙해서 나태해진 업무의 코드들, 혼자 짜다보니 짜게식은 코딩컨벤션 등 나태해진 내 상태를 바로 알 수 있게 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세번째로 TDD는 말로만 해야지~ 또는 업무코드는 너무 복잡하고, 급한 이슈부터 처리해야지~ 하다가실제로 처음 적용해봤다. 미친놈이지. 시간도 없고, 할줄도 모르는 상태에서 처음시도해보다니. 근데 막상 적용하니 좋은 점이 많았다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;매번 빌드해서 포스트맨으로 테스트하던 내가 테스트 코드가 익숙해지고, 검증이 완성된 코드를 적용하였다.&lt;/li&gt;
&lt;li&gt;제출 6시간 전 발견했던 버그 및 미구현 기능들을 고치고 추가하는데 적은 시간이 들었다.&lt;/li&gt;
&lt;li&gt;테스트하기 쉽게 기능들을 파일로 나누었고, 그결과 자동적으로 객체지향적인 코드작성이 가능했고 리팩토링이나 기능수정 시 버그가 현저히 줄었다.&lt;/li&gt;
&lt;li&gt;리팩토링 대상이 줄었으며 막상 진행해도 굉장히 쉬웠고 안정적이었다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네번째로 좋은 코드를 짜기위해 고민했던 점인데 그동안 책이나 블로그로 열심히 눈동냥했던 내용들을 적용해봤다. 정책은 언제든 변경이 일어나기때문에 확장 가능한 코드를 짜고싶었다. 그외에도 스태틱빌드패턴, TDD, 테스트모듈화 등 다양한 기능을 적용해본것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘한 점이 있긴 한가? 해놓고 많이쓴 느낌...&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;잘못한 점&lt;/h3&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;br /&gt;준비가 안돼있었다. 아쉬운 점에 쓸까 하다가 여기 적는게 맞는것 같다.&lt;br /&gt;평소에 준비안한게 내 잘못이다.&lt;br /&gt;성공에 운이 정말 중요하다고 하지만 그 운도 볼 줄 모르고, 능력도 안되면 잡을 수 없는것같다.&lt;br /&gt;&quot;난 내가 능력이 좋아서 성공했다고 생각하지 않아요. 정말 운이 좋았어요&quot; 라고 말하는 사람들은 본인 기준이 높을뿐 그 운을 잡을 능력이 있었고 준비된 사람이라 생각한다.&lt;br /&gt;또 과제를 진행하며 잘못한 점은 침착하지 못했던 것 같다.&lt;br /&gt;평소였으면 큰 문제가 있다면 작은 단위로 나눠서 해결하여 진행했을 것 같은데, 겁많은 개가 사납게 짖는걸까? 뭔가 이만큼이나 알고있다고 보여주고 싶어서였을까? 큰그림을 그려놓고 크게 개발을 해버렸다.&lt;br /&gt;큰 그림을 그리고 작은단위로 완성해나가야 하는데 그 부분이 아쉬웠다. 이부분은 밑에 아쉬운 점에 나오겠지만 평소에 구현해보지 않았던 스프링시큐리티가 큰 부분을 차지하는 것 같다. 개념도 잘모르고, 구현할줄도 모르는데 이틀만에 하려다보니 시간에 쫒기는 느낌... 평소에 준비가 너무 안된게 드러났다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;아쉬웠던 점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘못한 점과 마찬가지로 준비가 너무 안돼있었다.&lt;br /&gt;평소에 보일러플레이트처럼 과제테스트용으로 준비된 레포가 있었다면 기본적인 구현시간은 줄일 수 있지 않았을까?&lt;br /&gt;그 시간에 비즈니스적으로 처리할 로직이나, 예외처리등 진행이 부족했던게 너무 아쉽다.&lt;br /&gt;실제 평가 기준이 어떨지 모르지만 내가 심사를 한다면 이런 비중에 더 큰 점수를 주지 않을까?&lt;br /&gt;알면서 못한게 가장 아쉽다.. 지금 내가 하는 업무, 강조되는 부분이 그 부분인데!!!&lt;br /&gt;구현에 바빠 로직에 신경쓰지 못한게 이번 과제테스트에서 가장 아쉬운 부분이다. readme도 @쌈뽕하게 적고, 예외처리도 이런것 까지 생각했어? 들 정도로 하고싶었는데...&lt;br /&gt;지금이라도 생각나는 부분을 적어보자면&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정책적으로 정해져야 할 부분정리, 그중 임의로 하나 진행후 주석으로 표시&lt;/li&gt;
&lt;li&gt;스크래핑시 컬림이 있을경우, 없을경우&lt;/li&gt;
&lt;li&gt;스크래핑 요청이 여러번 올 경우 처리 방안(처리하긴햇는데.. 중복조건 잘못줌..연도별로 스크래핑 하는건데 중복 조건에 연도가 빠졌어요 담당자님....)&lt;/li&gt;
&lt;li&gt;외부api요청시 타임아웃관련 설정들&lt;/li&gt;
&lt;li&gt;jwt refreshToken관련&lt;/li&gt;
&lt;li&gt;예외처리 부분에 대한 좀 더 상세한 테스트코드&lt;/li&gt;
&lt;li&gt;등등&lt;br /&gt;다음에 잘할게요는 없다. 이 글을 읽으신 분은 지금부터 잘하길... 나도 지금부터 잘할게요&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;발전할 점&lt;/h3&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;br /&gt;먼저 잘못된 점에서 발전 할 부분은 평소에 준비를 해놔야겠다.&lt;br /&gt;스프링은 php와 다르게 공부할 부분이 너무 많다. 정말 뛰어난 개발자들이 구현한 기능을 잘 가져다 쓰면되는 편함도 있지만, 알지못하면 제대로 쓰지도 못한다... 컨벤션도 빡빡하고,,, 공부할게 많다.&lt;br /&gt;주변에 있는(이번에 이직하는) 개발자친구는 새로운 기술이나 관심있는 기술이 있다면 깃허브 저장소 하나 파서 붙여본다고 한다...역시 이직자는 뭐가 달라도 다르다. 내가 생각하는 이직하는 사람의 기준은 회사에서,적어도 팀에서 가장 잘하고 인정받는 사람인것같다. (나처럼 운이좋거나, 옆그레이드가 아닌 하고싶은 도메인이나, 원하는 회사로 이직하는 사람 기준)&lt;br /&gt;아무튼, 기본적인 기술에 대해서는 가볍게라도 적용 해 봄으로써 사용법정도는 익혀놔야할것같다.&lt;br /&gt;그래야 필요한 부분이 있으면 추가로 적용하고, 고칠 수 있으니 말이다.&lt;br /&gt;이번 잘한점에서 적은 TDD도 업무에 적용해서 고도화 시키면 과제테스트 같은 간단한 테스트는 금방 짤 수 있을 것같다. 우선 테스트코드가 익숙해질 수 있도록 테스트 방식이나 어노테이션들 정리를 진행 할 예정.&lt;br /&gt;우선 가볍게 이정도? 이정도만 발전해도 다음 과제테스트가 있을때&lt;/p&gt;
&lt;p&gt;&lt;del&gt;(없길바래봄)&lt;/del&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현에 힘쓰지않고 좀더 도메인의 비즈니스로직이나 예외처리 부분에 집중할 수 있을 것 같다 .&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;br /&gt;이 글을 읽을 누군가도 갓웅정의 명언을 따라 이 경험을 해봤으면 좋겟다.&lt;br /&gt;나는 이만 또 깨지로 가야겠다.(어제 한 마이그레이션 잘 못 된듯)&lt;/p&gt;</description>
      <category>기타</category>
      <author>닥치고개돌</author>
      <guid isPermaLink="true">https://shutcoding.tistory.com/100</guid>
      <comments>https://shutcoding.tistory.com/entry/%EA%B3%BC%EC%A0%9C%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%9A%8C%EA%B3%A0#entry100comment</comments>
      <pubDate>Tue, 19 Mar 2024 13:23:02 +0900</pubDate>
    </item>
    <item>
      <title>Spring Security 개념정리</title>
      <link>https://shutcoding.tistory.com/entry/Spring-Security-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 시스템에서는 회원의 관리를 하고 있고, 그에 따른 인증(Authentication)과 인가(Authorization)에 대한 처리를 해주어야 한다. Spring에서는 Spring Security라는 별도의 프레임워크에서 관련된 기능을 제공하고 있는데, 이번에는 Spring Security에 대해서 알아보도록 하겠다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 보안용어를 이해하고 넘어가야 한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;접근 주체(Principal) : 보호된 리소스에 접근하는 대상&lt;/li&gt;
&lt;li&gt;인증(Authentication) : 보호된 리소스에 접근한 대상에 대해 이 유저가 누구인지, 애플리케이션의 작업을 수행해도 되는 주체인지 확인하는 과정&lt;/li&gt;
&lt;li&gt;인가(Authorize) : 해당 리소스에 대해 접근 가능한 권한을 가지고 있는지 확인하는 과정(After Authentication, 인증 이후)&lt;/li&gt;
&lt;li&gt;권한 : 어떠한 리소스에 대한 접근 제한, 모든 리소스는 접근 제어 권한이 걸려있다. 즉, 인가 과정에서 해당 리소스에 대한 제한된 최소한의 권한을 가졌는지 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Spring Security란?&lt;/b&gt;&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Spring Security란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Security는 Spring 기반의 애플리케이션의 보안(인증과 권한, 인가 등)을 담당하는 스프링 하위 프레임워크이다. Spring Security는 '인증'과 '권한'에 대한 부분을 Filter 흐름에 따라 처리하고 있다. Filter는 Dispatcher Servlet으로 가기 전에 적용되므로 가장 먼저 URL 요청을 받지만, Interceptor는 Dispatcher와 Controller사이에 위치한다는 점에서 적용 시기의 차이가 있다. Spring Security는 보안과 관련해서 체계적으로 많은 옵션을 제공해주기 때문에 개발자 입장에서는 일일이 보안관련 로직을 작성하지 않아도 된다는 장점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;Spring Security 인증관련 아키텍쳐&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.36.24.png&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;832&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0BFqV/btsFJ2QvHQo/aOTZHluTUkRnzK3KRYznV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0BFqV/btsFJ2QvHQo/aOTZHluTUkRnzK3KRYznV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0BFqV/btsFJ2QvHQo/aOTZHluTUkRnzK3KRYznV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0BFqV%2FbtsFJ2QvHQo%2FaOTZHluTUkRnzK3KRYznV0%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;1394&quot; height=&quot;832&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.36.24.png&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;832&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Spring Security 주요 모듈&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.36.58.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;908&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnWcsj/btsFIufVyxR/44KE1k7jmtuDqBdRaD34YK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnWcsj/btsFIufVyxR/44KE1k7jmtuDqBdRaD34YK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnWcsj/btsFIufVyxR/44KE1k7jmtuDqBdRaD34YK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnWcsj%2FbtsFIufVyxR%2F44KE1k7jmtuDqBdRaD34YK%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;798&quot; height=&quot;518&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.36.58.png&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;908&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ SecurityContextHolder ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SecurityContextHolder는 보안 주체의 세부 정보를 포함하여 응용프래그램의 현재 보안 컨텍스트에 대한 세부 정보가 저장된다. SecurityContextHolder는 기본적으로 SecurityContextHolder.MODE_INHERITABLETHREADLOCAL 방법과SecurityContextHolder.MODE_THREADLOCAL 방법을 제공한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ SecurityContext ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Authentication을 보관하는 역할을 하며, SecurityContext를 통해 Authentication 객체를 꺼내올 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ Authentication ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Authentication는 현재 접근하는 주체의 정보와 권한을 담는 인터페이스이다. Authentication 객체는 Security Context에 저장되며, SecurityContextHolder를 통해 SecurityContext에 접근하고, SecurityContext를 통해 Authentication에 접근할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.37.54.png&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d9wboi/btsFIk5CO9s/mxTg6esDeB7gv0wGLF3ab0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d9wboi/btsFIk5CO9s/mxTg6esDeB7gv0wGLF3ab0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d9wboi/btsFIk5CO9s/mxTg6esDeB7gv0wGLF3ab0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd9wboi%2FbtsFIk5CO9s%2FmxTg6esDeB7gv0wGLF3ab0%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;1390&quot; height=&quot;720&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.37.54.png&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ UsernamePasswordAuthenticationToken ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UsernamePasswordAuthenticationToken은 Authentication을 implements한 AbstractAuthenticationToken의 하위 클래스로, User의 ID가 Principal 역할을 하고, Password가 Credential의 역할을 한다. UsernamePasswordAuthenticationToken의 첫 번째 생성자는 인증 전의 객체를 생성하고, 두번째 생성자는 인증이 완려된 객체를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.38.31.png&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;1060&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyISzq/btsFF7Tu1JY/KWj1JgmPKNxMBOvXWRVLc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyISzq/btsFF7Tu1JY/KWj1JgmPKNxMBOvXWRVLc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyISzq/btsFF7Tu1JY/KWj1JgmPKNxMBOvXWRVLc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyISzq%2FbtsFF7Tu1JY%2FKWj1JgmPKNxMBOvXWRVLc0%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;1374&quot; height=&quot;1060&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.38.31.png&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;1060&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ AuthenticationProvider ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AuthenticationProvider에서는 실제 인증에 대한 부분을 처리하는데, 인증 전의 Authentication객체를 받아서 인증이 완료된 객체를 반환하는 역할을 한다. 아래와 같은 AuthenticationProvider 인터페이스를 구현해서 Custom한 AuthenticationProvider을 작성해서 AuthenticationManager에 등록하면 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.38.49.png&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drK10O/btsFJkKQHPi/7KLC0MaIDsUhzfhfc7eWkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drK10O/btsFJkKQHPi/7KLC0MaIDsUhzfhfc7eWkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drK10O/btsFJkKQHPi/7KLC0MaIDsUhzfhfc7eWkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdrK10O%2FbtsFJkKQHPi%2F7KLC0MaIDsUhzfhfc7eWkK%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;1380&quot; height=&quot;320&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.38.49.png&quot; data-origin-width=&quot;1380&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ Authentication Manager ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증에 대한 부분은 SpringSecurity의 AuthenticatonManager를 통해서 처리하게 되는데, 실질적으로는 AuthenticationManager에 등록된 AuthenticationProvider에 의해 처리된다. 인증이 성공하면 2번째 생성자를 이용해 인증이 성공한(isAuthenticated=true) 객체를 생성하여 Security Context에 저장한다. 그리고 인증 상태를 유지하기 위해 세션에 보관하며, 인증이 실패한 경우에는 AuthenticationException를 발생시킨다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.39.12.png&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;176&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rWSf3/btsFGBG3KoP/6kLO4l9KLdMwbFmuKakOvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rWSf3/btsFGBG3KoP/6kLO4l9KLdMwbFmuKakOvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rWSf3/btsFGBG3KoP/6kLO4l9KLdMwbFmuKakOvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrWSf3%2FbtsFGBG3KoP%2F6kLO4l9KLdMwbFmuKakOvk%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;1386&quot; height=&quot;176&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.39.12.png&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;176&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;AuthenticationManager를 implements한 ProviderManager는 실제 인증 과정에 대한 로직을 가지고 있는 AuthenticaionProvider를 List로 가지고 있으며, ProividerManager는 for문을 통해 모든 provider를 조회하면서 authenticate 처리를 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.39.34.png&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;1300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B7V7t/btsFKRVs1bh/kbO9WkOpKxHVbWPMC3SHSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B7V7t/btsFKRVs1bh/kbO9WkOpKxHVbWPMC3SHSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B7V7t/btsFKRVs1bh/kbO9WkOpKxHVbWPMC3SHSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB7V7t%2FbtsFKRVs1bh%2FkbO9WkOpKxHVbWPMC3SHSK%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;1386&quot; height=&quot;1300&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.39.34.png&quot; data-origin-width=&quot;1386&quot; data-origin-height=&quot;1300&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;위에서 설명한 ProviderManager에 우리가 직접 구현한 CustomAuthenticationProvider를 등록하는 방법은 WebSecurityConfigurerAdapter를 상속해 만든 SecurityConfig에서 할 수 있다. WebSecurityConfigurerAdapter의 상위 클래스에서는 AuthenticationManager를 가지고 있기 때문에 우리가 직접 만든 CustomAuthenticationProvider를 등록할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.39.51.png&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sKFv4/btsFKN6DNza/rzN0S7bQai1nPUa3vJuzv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sKFv4/btsFKN6DNza/rzN0S7bQai1nPUa3vJuzv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sKFv4/btsFKN6DNza/rzN0S7bQai1nPUa3vJuzv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsKFv4%2FbtsFKN6DNza%2FrzN0S7bQai1nPUa3vJuzv1%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;1382&quot; height=&quot;748&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.39.51.png&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;748&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ UserDetails ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인증에 성공하여 생성된 UserDetails 객체는 Authentication객체를 구현한 UsernamePasswordAuthenticationToken을 생성하기 위해 사용된다. UserDetails 인터페이스를 살펴보면 아래와 같이 정보를 반환하는 메소드를 가지고 있다. UserDetails 인터페이스의 경우 직접 개발한 UserVO 모델에 UserDetails를 implements하여 이를 처리하거나 UserDetailsVO에 UserDetails를 implements하여 처리할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.40.07.png&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;684&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmgYbv/btsFGlxG6jH/lkB3tuOZeaHm05HahIPAtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmgYbv/btsFGlxG6jH/lkB3tuOZeaHm05HahIPAtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmgYbv/btsFGlxG6jH/lkB3tuOZeaHm05HahIPAtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmgYbv%2FbtsFGlxG6jH%2FlkB3tuOZeaHm05HahIPAtK%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;1384&quot; height=&quot;684&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.40.07.png&quot; data-origin-width=&quot;1384&quot; data-origin-height=&quot;684&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ UserDetailsService ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UserDetailsService 인터페이스는 UserDetails 객체를 반환하는 단 하나의 메소드를 가지고 있는데, 일반적으로 이를 구현한 클래스의 내부에 UserRepository를 주입받아 DB와 연결하여 처리한다. UserDetails 인터페이스는 아래와 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.40.17.png&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;210&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FU72v/btsFKPQS9CZ/TlXSfj0fXBByWVgocULMQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FU72v/btsFKPQS9CZ/TlXSfj0fXBByWVgocULMQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FU72v/btsFKPQS9CZ/TlXSfj0fXBByWVgocULMQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFU72v%2FbtsFKPQS9CZ%2FTlXSfj0fXBByWVgocULMQk%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;1390&quot; height=&quot;210&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.40.17.png&quot; data-origin-width=&quot;1390&quot; data-origin-height=&quot;210&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ Password Encoding ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AuthenticationManagerBuilder.userDetailsService().passwordEncoder() 를 통해 패스워드 암호화에 사용될 PasswordEncoder 구현체를 지정할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.40.36.png&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;402&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTKqZv/btsFI6MSz7D/cWNHkWloR44al75xnQkCfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTKqZv/btsFI6MSz7D/cWNHkWloR44al75xnQkCfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTKqZv/btsFI6MSz7D/cWNHkWloR44al75xnQkCfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTKqZv%2FbtsFI6MSz7D%2FcWNHkWloR44al75xnQkCfk%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;1372&quot; height=&quot;402&quot; data-filename=&quot;스크린샷 2024-03-12 오후 1.40.36.png&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;402&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ GrantedAuthority ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GrantAuthority는 현재 사용자(principal)가 가지고 있는 권한을 의미한다. ROLE_ADMIN나 ROLE_USER와 같이 ROLE_*의 형태로 사용하며, 보통 &quot;roles&quot; 이라고 한다. GrantedAuthority 객체는 UserDetailsService에 의해 불러올 수 있고, 특정 자원에 대한 권한이 있는지를 검사하여 접근 허용 여부를 결정한다.&lt;/p&gt;</description>
      <category>Java &amp;amp; Spring</category>
      <author>닥치고개돌</author>
      <guid isPermaLink="true">https://shutcoding.tistory.com/99</guid>
      <comments>https://shutcoding.tistory.com/entry/Spring-Security-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC#entry99comment</comments>
      <pubDate>Tue, 12 Mar 2024 13:35:59 +0900</pubDate>
    </item>
    <item>
      <title>java8 람다 표현식</title>
      <link>https://shutcoding.tistory.com/entry/java8-%EB%9E%8C%EB%8B%A4-%ED%91%9C%ED%98%84%EC%8B%9D</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;람다란 무엇인가?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;b7cc857c63cf44a1aa74c7cceae5f2f2&quot;&gt;
&lt;div data-block-content=&quot;b7cc857c63cf44a1aa74c7cceae5f2f2&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;4368c798459444339db42b7dfbb6c3bc&quot;&gt;&lt;span data-offset-key=&quot;4368c798459444339db42b7dfbb6c3bc:0&quot;&gt;람다 표현식은 메서드로 전달할 수 있는 익명 함수를 단순화한 것이다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;즉, 람다는 어떤 함수의 매개변수로 다른 함수를 넣고 싶을 때 사용한다.&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJoZWFkaW5nLTElMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQiU5RSU4QyVFQiU4QiVBNCVFQiU5RSU4MCUyMCVFQiVBQyVCNCVFQyU5NyU4NyVFQyU5RCVCOCVFQSVCMCU4MCUzRiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIybHVlRHhZTkJ1MVAzJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyNWNlVEVYYXdPRXNWJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUIlOUUlOEMlRUIlOEIlQTQlMjAlRUQlOTElOUMlRUQlOTglODQlRUMlOEIlOUQlRUMlOUQlODAlMjAlRUIlQTklOTQlRUMlODQlOUMlRUIlOTMlOUMlRUIlQTElOUMlMjAlRUMlQTAlODQlRUIlOEIlQUMlRUQlOTUlQTAlMjAlRUMlODglOTglMjAlRUMlOUUlODglRUIlOEElOTQlMjAlRUMlOUQlQjUlRUIlQUElODUlMjAlRUQlOTUlQTglRUMlODglOTglRUIlQTUlQkMlMjAlRUIlOEIlQTglRUMlODglOUMlRUQlOTklOTQlRUQlOTUlOUMlMjAlRUElQjIlODMlRUMlOUQlQjQlRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI0MzY4Yzc5ODQ1OTQ0NDMzOWRiNDJiN2RmYmI2YzNiYyUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmI3Y2M4NTdjNjNjZjQ0YTFhYTc0YzdjY2VhZTVmMmYyJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIybGlzdC11bm9yZGVyZWQlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmxpc3QtaXRlbSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUMlOUQlQjUlRUIlQUElODUlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyYm9sZCUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCUzQSUyMCVFQiVCMyVCNCVFRCU4NiVCNSVFQyU5RCU5OCUyMCVFQiVBOSU5NCVFQyU4NCU5QyVFQiU5MyU5QyVFQyU5OSU4MCUyMCVFQiU4QiVBQyVFQiVBNiVBQyUyMCVFQyU5RCVCNCVFQiVBNiU4NCVFQyU5RCVCNCUyMCVFQyU5NyU4NiVFQyU5QyVCQyVFQiVBRiU4MCVFQiVBMSU5QyUyMCVFQyU5RCVCNSVFQiVBQSU4NSVFQyU5RCVCNCVFQiU5RCVCQyUyMCVFRCU5MSU5QyVFRCU5OCU4NCVFRCU5NSU5QyVFQiU4QiVBNC4lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmQzNjY4NDliYzhlYzRmZmM4MjA1M2MwNDljOTMzNTE5JTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYWU3NzgxYWY5N2NiNGEzYmFmMmU2ODEyZjc4OTZiMmUlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJiNjE5MDY2OWZkMDA0ZTdjYWE4NDEzYzNkMGEzNmZkOCUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmxpc3QtaXRlbSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUQlOTUlQTglRUMlODglOTglMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyYm9sZCUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCUzQSUyMCVFQiU5RSU4QyVFQiU4QiVBNCVFQiU4QSU5NCUyMCVFQiVBOSU5NCVFQyU4NCU5QyVFQiU5MyU5QyVFQyVCMiU5OCVFQiU5RiVCQyUyMCVFRCU4QSVCOSVFQyVBMCU5NSUyMCVFRCU4MSVCNCVFQiU5RSU5OCVFQyU4QSVBNCVFQyU5NyU5MCUyMCVFQyVBMiU4NSVFQyU4NiU4RCVFQiU5MCU5OCVFQyVBNyU4MCUyMCVFQyU5NSU4QSVFQyU5QyVCQyVFQiVBRiU4MCVFQiVBMSU5QyUyMCVFRCU5NSVBOCVFQyU4OCU5OCVFQiU5RCVCQyVFQSVCMyVBMCUyMCVFQiVCNiU4MCVFQiVBNSVCOCVFQiU4QiVBNC4lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjA5NjA5YTZmZmUxNTQxZWZhOThmMTEzZDljMmZjN2YwJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYWFmOTg5MTNjYjNkNGU2NjgzZDMxYWRhNmQ1YTlkNTklMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJiYTNiODNmYTVmYjc0NWFiOTlhNWU3ZGY0OTY5NjAwOCUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmxpc3QtaXRlbSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUMlQTAlODQlRUIlOEIlQUMlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyYm9sZCUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCUzQSUyMCVFQiU5RSU4QyVFQiU4QiVBNCUyMCVFRCU5MSU5QyVFRCU5OCU4NCVFQyU4QiU5RCVFQyU5RCU4NCUyMCVFQiVBOSU5NCVFQyU4NCU5QyVFQiU5MyU5QyUyMCVFQyU5RCVCOCVFQyU4OCU5OCVFQiVBMSU5QyUyMCVFQyVBMCU4NCVFQiU4QiVBQyVFRCU5NSU5OCVFQSVCMSVCMCVFQiU4MiU5OCUyMCVFQiVCMyU4MCVFQyU4OCU5OCVFQiVBMSU5QyUyMCVFQyVBMCU4MCVFQyU5RSVBNSVFRCU5NSVBMCUyMCVFQyU4OCU5OCUyMCVFQyU5RSU4OCVFQiU4QiVBNC4lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmMzZTMxYmJmN2E3NjQ5YjRiYzZlOGI0ZGZjMTZjNmExJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZWRmZWY0MGEzYjY5NDQzMGEwNmE2OWNmYjJiMmRjZWQlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI2NTllODFkNmVlNmM0ZGJhYTBhYTY0OTVhNWUwMjJiMCUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmxpc3QtaXRlbSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUElQjAlODQlRUElQjIlQkQlRUMlODQlQjElMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyYm9sZCUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCUzQSUyMCVFQyU5RCVCNSVFQiVBQSU4NSUyMCVFRCU4MSVCNCVFQiU5RSU5OCVFQyU4QSVBNCVFQyVCMiU5OCVFQiU5RiVCQyUyMCVFQiVBNyU4RSVFQyU5RCU4MCUyMCVFQyU5RSU5MCVFQyVBNyU4OCVFQSVCNSVBQyVFQiVBMCU4OCVFRCU5NSU5QyUyMCVFQyVCRCU5NCVFQiU5MyU5QyVFQiVBNSVCQyUyMCVFQSVCNSVBQyVFRCU5OCU4NCVFRCU5NSVBMCUyMCVFRCU5NSU4NCVFQyU5QSU5NCVFQSVCMCU4MCUyMCVFQyU5NyU4NiVFQiU4QiVBNC4lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjEyMjc2MzdmZDQyZjRmMDY5NjlkYTg0OTM5OWQ3OWU0JTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYjAxMjM5NzJmNGYyNDZhNmJjNjU0NTUyZmFmMTAxMmUlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJhMDA1YTdmNDkwNjE0YmViYjk0MTZhZDZjYzQ3OTEzYyUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjI0MmYyMGU2ZGIxOTRjMWM4OTU1MDA3NDVhM2VkNGQzJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyVGwyNkp3QXZDNlYxJTIyJTdE&quot;&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div data-key=&quot;242f20e6db194c1c895500745a3ed4d3&quot;&gt;
&lt;div data-block-content=&quot;242f20e6db194c1c895500745a3ed4d3&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-key=&quot;b6190669fd004e7caa8413c3d0a36fd8&quot;&gt;
&lt;div data-block-content=&quot;b6190669fd004e7caa8413c3d0a36fd8&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;ae7781af97cb4a3baf2e6812f7896b2e&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;d366849bc8ec4ffc82053c049c933519&quot;&gt;&lt;b&gt;익명&lt;/b&gt;&lt;span data-offset-key=&quot;d366849bc8ec4ffc82053c049c933519:1&quot;&gt; : 보통의 메서드와 달리 이름이 없으므로 익명이라 표현한다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-key=&quot;ba3b83fa5fb745ab99a5e7df49696008&quot;&gt;
&lt;div data-block-content=&quot;ba3b83fa5fb745ab99a5e7df49696008&quot;&gt;
&lt;div&gt;&lt;b&gt;함수&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; data-offset-key=&quot;09609a6ffe1541efa98f113d9c2fc7f0:1&quot;&gt; : 람다는 메서드처럼 특정 클래스에 종속되지 않으므로 함수라고 부른다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-key=&quot;659e81d6ee6c4dbaa0aa6495a5e022b0&quot;&gt;
&lt;div data-block-content=&quot;659e81d6ee6c4dbaa0aa6495a5e022b0&quot;&gt;
&lt;div&gt;&lt;b&gt;전달&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; data-offset-key=&quot;c3e31bbf7a7649b4bc6e8b4dfc16c6a1:1&quot;&gt; : 람다 표현식을 메서드 인수로 전달하거나 변수로 저장할 수 있다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJsaXN0LWl0ZW0lMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVDJTlEJUI1JUVCJUFBJTg1JTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmJvbGQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlM0ElMjAlRUIlQjMlQjQlRUQlODYlQjUlRUMlOUQlOTglMjAlRUIlQTklOTQlRUMlODQlOUMlRUIlOTMlOUMlRUMlOTklODAlMjAlRUIlOEIlQUMlRUIlQTYlQUMlMjAlRUMlOUQlQjQlRUIlQTYlODQlRUMlOUQlQjQlMjAlRUMlOTclODYlRUMlOUMlQkMlRUIlQUYlODAlRUIlQTElOUMlMjAlRUMlOUQlQjUlRUIlQUElODUlRUMlOUQlQjQlRUIlOUQlQkMlMjAlRUQlOTElOUMlRUQlOTglODQlRUQlOTUlOUMlRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIyT0dycW5nYWx1MVglMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIweEgzWlRTMDEwU2wlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIzZGthcFhUUDR1OUUlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJsaXN0LWl0ZW0lMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVEJTk1JUE4JUVDJTg4JTk4JTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmJvbGQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlM0ElMjAlRUIlOUUlOEMlRUIlOEIlQTQlRUIlOEElOTQlMjAlRUIlQTklOTQlRUMlODQlOUMlRUIlOTMlOUMlRUMlQjIlOTglRUIlOUYlQkMlMjAlRUQlOEElQjklRUMlQTAlOTUlMjAlRUQlODElQjQlRUIlOUUlOTglRUMlOEElQTQlRUMlOTclOTAlMjAlRUMlQTIlODUlRUMlODYlOEQlRUIlOTAlOTglRUMlQTclODAlMjAlRUMlOTUlOEElRUMlOUMlQkMlRUIlQUYlODAlRUIlQTElOUMlMjAlRUQlOTUlQTglRUMlODglOTglRUIlOUQlQkMlRUElQjMlQTAlMjAlRUIlQjYlODAlRUIlQTUlQjglRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIwOTYwOWE2ZmZlMTU0MWVmYTk4ZjExM2Q5YzJmYzdmMCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmFhZjk4OTEzY2IzZDRlNjY4M2QzMWFkYTZkNWE5ZDU5JTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYmEzYjgzZmE1ZmI3NDVhYjk5YTVlN2RmNDk2OTYwMDglMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJsaXN0LWl0ZW0lMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVDJUEwJTg0JUVCJThCJUFDJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmJvbGQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlM0ElMjAlRUIlOUUlOEMlRUIlOEIlQTQlMjAlRUQlOTElOUMlRUQlOTglODQlRUMlOEIlOUQlRUMlOUQlODQlMjAlRUIlQTklOTQlRUMlODQlOUMlRUIlOTMlOUMlMjAlRUMlOUQlQjglRUMlODglOTglRUIlQTElOUMlMjAlRUMlQTAlODQlRUIlOEIlQUMlRUQlOTUlOTglRUElQjElQjAlRUIlODIlOTglMjAlRUIlQjMlODAlRUMlODglOTglRUIlQTElOUMlMjAlRUMlQTAlODAlRUMlOUUlQTUlRUQlOTUlQTAlMjAlRUMlODglOTglMjAlRUMlOUUlODglRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJjM2UzMWJiZjdhNzY0OWI0YmM2ZThiNGRmYzE2YzZhMSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmVkZmVmNDBhM2I2OTQ0MzBhMDZhNjljZmIyYjJkY2VkJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyNjU5ZTgxZDZlZTZjNGRiYWEwYWE2NDk1YTVlMDIyYjAlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJsaXN0LWl0ZW0lMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVBJUIwJTg0JUVBJUIyJUJEJUVDJTg0JUIxJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmJvbGQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlM0ElMjAlRUMlOUQlQjUlRUIlQUElODUlMjAlRUQlODElQjQlRUIlOUUlOTglRUMlOEElQTQlRUMlQjIlOTglRUIlOUYlQkMlMjAlRUIlQTclOEUlRUMlOUQlODAlMjAlRUMlOUUlOTAlRUMlQTclODglRUElQjUlQUMlRUIlQTAlODglRUQlOTUlOUMlMjAlRUMlQkQlOTQlRUIlOTMlOUMlRUIlQTUlQkMlMjAlRUElQjUlQUMlRUQlOTglODQlRUQlOTUlQTAlMjAlRUQlOTUlODQlRUMlOUElOTQlRUElQjAlODAlMjAlRUMlOTclODYlRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIxMjI3NjM3ZmQ0MmY0ZjA2OTY5ZGE4NDkzOTlkNzllNCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmIwMTIzOTcyZjRmMjQ2YTZiYzY1NDU1MmZhZjEwMTJlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYTAwNWE3ZjQ5MDYxNGJlYmI5NDE2YWQ2Y2M0NzkxM2MlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJwdVNNeE1XbGhqNXolMjIlN0Q=&quot;&gt;
&lt;div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-key=&quot;a005a7f490614bebb9416ad6cc47913c&quot;&gt;
&lt;div data-block-content=&quot;a005a7f490614bebb9416ad6cc47913c&quot;&gt;
&lt;div&gt;&lt;b&gt;간결성&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; data-offset-key=&quot;1227637fd42f4f06969da849399d79e4:1&quot;&gt; : 익명 클래스처럼 많은 자질구레한 코드를 구현할 필요가 없다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;람다의 구성 요소&lt;br /&gt;- 파라미터 리스트 &lt;br /&gt;- 화살표 : 파라미터 리스트와 바디를 구분한다&lt;br /&gt;- 바디 : 람다의 반환값에 해당하는 표현식&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFRCU5NSVBOCVFQyU4OCU5OCVFRCU5OCU5NSUyMCVFQyU5RCVCOCVFRCU4NCVCMCVFRCU4RSU5OCVFQyU5RCVCNCVFQyU4QSVBNCVFQiU4QSU5NCUyMCVFQyVBMCU5NSVFRCU5OSU5NSVFRCU5RSU4OCUyMCVFRCU5NSU5OCVFQiU4MiU5OCVFQyU5RCU5OCUyMCVFQyVCNiU5NCVFQyU4MyU4MSUyMCVFQiVBOSU5NCVFQyU4NCU5QyVFQiU5MyU5QyVFQiVBNSVCQyUyMCVFQyVBNyU4MCVFQyVBMCU5NSVFRCU5NSU5OCVFQiU4QSU5NCUyMCVFQyU5RCVCOCVFRCU4NCVCMCVFRCU4RSU5OCVFQyU5RCVCNCVFQyU4QSVBNCVFQyU5RCVCNCVFQiU4QiVBNC4lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjAxeGt5Y0d3bFBjTSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMnlaTU02Skxwa2s4NiUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMkxKcWZIbmlLR3o4ciUyMiU3RA==&quot;&gt;함수형 인터페이스는 정확히 하나의 추상 메서드를 지정하는 인터페이스이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@FunctionalInterface&lt;span data-offset-key=&quot;e402311bcc8d44229284e11414d2b7af:2&quot;&gt; 어노테이션을 붙여 주면 메서드가 2개 이상일 경우 &lt;/span&gt;컴파일 &lt;span data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiU0MEZ1bmN0aW9uYWxJbnRlcmZhY2UlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCVFQyU5NiVCNCVFQiU4NSVCOCVFRCU4NSU4QyVFQyU5RCVCNCVFQyU4NSU5OCVFQyU5RCU4NCUyMCVFQiVCNiU5OSVFQyU5NyVBQyUyMCVFQyVBMyVCQyVFQiVBOSVCNCUyMCVFQiVBOSU5NCVFQyU4NCU5QyVFQiU5MyU5QyVFQSVCMCU4MCUyMDIlRUElQjAlOUMlMjAlRUMlOUQlQjQlRUMlODMlODElRUMlOUQlQkMlMjAlRUElQjIlQkQlRUMlOUElQjAlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVDJUJCJUI0JUVEJThDJThDJUVDJTlEJUJDJTIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUIlOEIlQTglRUElQjMlODQlRUMlOTclOTAlRUMlODQlOUMlMjAlRUMlOTclOTAlRUIlOUYlQUMlRUIlQTUlQkMlMjAlRUIlQjAlOUMlRUMlODMlOUQlMjAlRUMlOEIlOUMlRUQlODIlQUMlMjAlRUMlODglOTglMjAlRUMlOUUlODglRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJUSXRBbHRvenBmZjklMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJkdUY3SVlHTDVDbUslMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJxSjE5dFBHc3NDUWolMjIlN0Q=&quot; data-offset-key=&quot;e402311bcc8d44229284e11414d2b7af:4&quot;&gt;단계에서 에러를 발생 시킬 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJoZWFkaW5nLTElMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFRCU5NSVBOCVFQyU4OCU5OCVFRCU5OCU5NSUyMCVFQyU5RCVCOCVFRCU4NCVCMCVFRCU4RSU5OCVFQyU5RCVCNCVFQyU4QSVBNCUyMCVFQyU4MiVBQyVFQyU5QSVBOSUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMXJDZ25DV0pxZGFGJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIySmF4aDNPVGZFR1dWJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZUVkNG1EdHdwNnpzJTIyJTdE&quot;&gt;함수형 인터페이스 사용&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;dea1fe52700e4657b3cd683c84c35ac1&quot;&gt;
&lt;div data-block-content=&quot;dea1fe52700e4657b3cd683c84c35ac1&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;text-predicate&quot; data-rnwr700-gg6oyi-ubezar-135wba7-1kfrs79=&quot;true&quot; data-rnwrdesktop-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot;&gt;&lt;b&gt;&lt;span data-key=&quot;0f8930bdeb1b473db9a87733e467644b&quot;&gt;&lt;span data-offset-key=&quot;0f8930bdeb1b473db9a87733e467644b:0&quot;&gt;Predicate&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;e3fe177d7ee1446696a3451369713458&quot;&gt;
&lt;div data-block-content=&quot;e3fe177d7ee1446696a3451369713458&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;ef872d2d19d146929b12202c1475e48a&quot;&gt;java.util.function.Predicate&lt;span data-offset-key=&quot;ef872d2d19d146929b12202c1475e48a:1&quot;&gt; 인터페이스는 test라는 추상 메서드를 정의하며 test는 제네릭 형식 T의 객체를 인수로 받아 boolean을 반환한다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;ccca65128edd4972b3265083ae7944b0&quot;&gt;
&lt;div data-block-content=&quot;ccca65128edd4972b3265083ae7944b0&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;text-consumer&quot; data-rnwr700-gg6oyi-ubezar-135wba7-1kfrs79=&quot;true&quot; data-rnwrdesktop-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot;&gt;&lt;b&gt;&lt;span data-key=&quot;181e309a415f42baa4810cce1aff973e&quot;&gt;&lt;span data-offset-key=&quot;181e309a415f42baa4810cce1aff973e:0&quot;&gt;Consumer&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;766611227bd24a42aec74c0c8902008d&quot;&gt;
&lt;div data-block-content=&quot;766611227bd24a42aec74c0c8902008d&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;0c21738416b04ddf8e69fae40b6cea92&quot;&gt;java.util.function.Consumer&lt;span data-offset-key=&quot;0c21738416b04ddf8e69fae40b6cea92:1&quot;&gt; 인터페이스는 제네릭 형식 T 객체를 받아서 &lt;/span&gt;void&lt;span data-offset-key=&quot;0c21738416b04ddf8e69fae40b6cea92:3&quot;&gt;를 반환하는 &lt;/span&gt;accept&lt;span data-offset-key=&quot;0c21738416b04ddf8e69fae40b6cea92:5&quot;&gt;라는 추상 메서드를 정의한다. T 형식의 객체를 인수로 받아서 어떤 동작을 수행하고 싶을 때 Consumer 인터페이스를 사용할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;e60ad31237d84182924266d1efc2dfbc&quot;&gt;
&lt;div data-block-content=&quot;e60ad31237d84182924266d1efc2dfbc&quot;&gt;
&lt;div&gt;
&lt;div id=&quot;text-function&quot; data-rnwr700-gg6oyi-ubezar-135wba7-1kfrs79=&quot;true&quot; data-rnwrdesktop-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot;&gt;&lt;b&gt;&lt;span data-key=&quot;e3b8949aefae4c4cbb596a49768c860c&quot;&gt;&lt;span data-offset-key=&quot;e3b8949aefae4c4cbb596a49768c860c:0&quot;&gt;Function&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJoZWFkaW5nLTIlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMlByZWRpY2F0ZSUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZnVmWHBYRkRTZmtyJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyRDhBdmhhNDNvMU1pJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJqYXZhLnV0aWwuZnVuY3Rpb24uUHJlZGljYXRlJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlRUMlOUQlQjglRUQlODQlQjAlRUQlOEUlOTglRUMlOUQlQjQlRUMlOEElQTQlRUIlOEElOTQlMjB0ZXN0JUVCJTlEJUJDJUVCJThBJTk0JTIwJUVDJUI2JTk0JUVDJTgzJTgxJTIwJUVCJUE5JTk0JUVDJTg0JTlDJUVCJTkzJTlDJUVCJUE1JUJDJTIwJUVDJUEwJTk1JUVDJTlEJTk4JUVEJTk1JTk4JUVCJUE5JUIwJTIwdGVzdCVFQiU4QSU5NCUyMCVFQyVBMCU5QyVFQiU4NCVBNCVFQiVBNiVBRCUyMCVFRCU5OCU5NSVFQyU4QiU5RCUyMFQlRUMlOUQlOTglMjAlRUElQjAlOUQlRUMlQjIlQjQlRUIlQTUlQkMlMjAlRUMlOUQlQjglRUMlODglOTglRUIlQTElOUMlMjAlRUIlQjAlOUIlRUMlOTUlODQlMjAlRUIlQjYlODglRUIlQTYlQjAlRUMlOUQlODQlMjAlRUIlQjAlOUIlRUQlOTklOTglRUQlOTUlOUMlRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlZjg3MmQyZDE5ZDE0NjkyOWIxMjIwMmMxNDc1ZTQ4YSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmUzZmUxNzdkN2VlMTQ0NjY5NmEzNDUxMzY5NzEzNDU4JTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyaGVhZGluZy0yJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJDb25zdW1lciUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMTgxZTMwOWE0MTVmNDJiYWE0ODEwY2NlMWFmZjk3M2UlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJjY2NhNjUxMjhlZGQ0OTcyYjMyNjUwODNhZTc5NDRiMCUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyamF2YS51dGlsLmZ1bmN0aW9uLkNvbnN1bWVyJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlRUMlOUQlQjglRUQlODQlQjAlRUQlOEUlOTglRUMlOUQlQjQlRUMlOEElQTQlRUIlOEElOTQlMjAlRUMlQTAlOUMlRUIlODQlQTQlRUIlQTYlQUQlMjAlRUQlOTglOTUlRUMlOEIlOUQlMjBUJTIwJUVBJUIwJTlEJUVDJUIyJUI0JUVCJUE1JUJDJTIwJUVCJUIwJTlCJUVDJTk1JTg0JUVDJTg0JTlDJTIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMnZvaWQlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQiVBNSVCQyUyMCVFQiVCMCU5OCVFRCU5OSU5OCVFRCU5NSU5OCVFQiU4QSU5NCUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJhY2NlcHQlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQiU5RCVCQyVFQiU4QSU5NCUyMCVFQyVCNiU5NCVFQyU4MyU4MSUyMCVFQiVBOSU5NCVFQyU4NCU5QyVFQiU5MyU5QyVFQiVBNSVCQyUyMCVFQyVBMCU5NSVFQyU5RCU5OCVFRCU5NSU5QyVFQiU4QiVBNC4lMjBUJTIwJUVEJTk4JTk1JUVDJThCJTlEJUVDJTlEJTk4JTIwJUVBJUIwJTlEJUVDJUIyJUI0JUVCJUE1JUJDJTIwJUVDJTlEJUI4JUVDJTg4JTk4JUVCJUExJTlDJTIwJUVCJUIwJTlCJUVDJTk1JTg0JUVDJTg0JTlDJTIwJUVDJTk2JUI0JUVCJTk2JUE0JTIwJUVCJThGJTk5JUVDJTlFJTkxJUVDJTlEJTg0JTIwJUVDJTg4JTk4JUVEJTk2JTg5JUVEJTk1JTk4JUVBJUIzJUEwJTIwJUVDJThCJUI2JUVDJTlEJTg0JTIwJUVCJTk1JThDJTIwQ29uc3VtZXIlMjAlRUMlOUQlQjglRUQlODQlQjAlRUQlOEUlOTglRUMlOUQlQjQlRUMlOEElQTQlRUIlQTUlQkMlMjAlRUMlODIlQUMlRUMlOUElQTklRUQlOTUlQTAlMjAlRUMlODglOTglMjAlRUMlOUUlODglRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIwYzIxNzM4NDE2YjA0ZGRmOGU2OWZhZTQwYjZjZWE5MiUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjc2NjYxMTIyN2JkMjRhNDJhZWM3NGMwYzg5MDIwMDhkJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyaGVhZGluZy0yJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJGdW5jdGlvbiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZTNiODk0OWFlZmFlNGM0Y2JiNTk2YTQ5NzY4Yzg2MGMlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJlNjBhZDMxMjM3ZDg0MTgyOTI0MjY2ZDFlZmMyZGZiYyUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyamF2YS51dGlsLmZ1bmN0aW9uLkZ1bmN0aW9uJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlRUMlOUQlQjglRUQlODQlQjAlRUQlOEUlOTglRUMlOUQlQjQlRUMlOEElQTQlRUIlOEElOTQlMjAlRUMlQTAlOUMlRUIlODQlQTQlRUIlQTYlQUQlMjAlRUQlOTglOTUlRUMlOEIlOUQlMjBUJUVCJUE1JUJDJTIwJUVDJTlEJUI4JUVDJTg4JTk4JUVCJUExJTlDJTIwJUVCJUIwJTlCJUVDJTk1JTg0JUVDJTg0JTlDJTIwJUVDJUEwJTlDJUVCJTg0JUE0JUVCJUE2JUFEJTIwJUVEJTk4JTk1JUVDJThCJTlEJTIwUiUyMCVFQSVCMCU5RCVFQyVCMiVCNCVFQiVBNSVCQyUyMCVFQiVCMCU5OCVFRCU5OSU5OCVFRCU5NSU5OCVFQiU4QSU5NCUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJhcHBseSUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybWFyayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCU3RCU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVCJTlEJUJDJUVCJThBJTk0JTIwJUVDJUI2JTk0JUVDJTgzJTgxJTIwJUVCJUE5JTk0JUVDJTg0JTlDJUVCJTkzJTlDJUVCJUE1JUJDJTIwJUVDJUEwJTk1JUVDJTlEJTk4JUVEJTk1JTlDJUVCJThCJUE0LiUyMCVFQyU5RSU4NSVFQiVBMCVBNSVFQyU5RCU4NCUyMCVFQyVCNiU5QyVFQiVBMCVBNSVFQyU5QyVCQyVFQiVBMSU5QyUyMCVFQiVBNyVBNCVFRCU5NSU5MSVFRCU5NSU5OCVFQiU4QSU5NCUyMCVFQiU5RSU4QyVFQiU4QiVBNCVFQiVBNSVCQyUyMCVFQyVBMCU5NSVFQyU5RCU5OCVFRCU5NSVBMCUyMCVFQiU5NSU4QyUyMEZ1bmN0aW9uJTIwJUVDJTlEJUI4JUVEJTg0JUIwJUVEJThFJTk4JUVDJTlEJUI0JUVDJThBJUE0JUVCJUE1JUJDJTIwJUVEJTk5JTlDJUVDJTlBJUE5JUVEJTk1JUEwJTIwJUVDJTg4JTk4JTIwJUVDJTlFJTg4JUVCJThCJUE0LiUyMCVFQyU5RSU5MCVFQiVCMCU5NCUyMDglRUMlOTclOTAlRUMlODQlOUMlRUIlOEElOTQlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVBJUI4JUIwJUVCJUIzJUI4JUVEJTk4JTk1JTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUMlOUQlODQlMjAlRUMlOUUlODUlRUMlQjYlOUMlRUIlQTAlQTUlRUMlOUMlQkMlRUIlQTElOUMlMjAlRUMlODIlQUMlRUMlOUElQTklRUQlOTUlOTglRUIlOEElOTQlMjAlRUMlODMlODElRUQlOTklQTklRUMlOTclOTAlRUMlODQlOUMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVDJTk4JUE0JUVEJTg2JUEwJUVCJUIwJTk1JUVDJThCJUIxJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlRUIlOEYlOTklRUMlOUUlOTElRUMlOUQlODQlMjAlRUQlOTQlQkMlRUQlOTUlQTAlMjAlRUMlODglOTglMjAlRUMlOUUlODglRUIlOEYlODQlRUIlQTElOUQlMjAlRUQlOEElQjklRUIlQjMlODQlRUQlOTUlOUMlMjAlRUIlQjIlODQlRUMlQTAlODQlRUMlOUQlOTglMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVEJTk1JUE4JUVDJTg4JTk4JUVEJTk4JTk1JTIwJUVDJTlEJUI4JUVEJTg0JUIwJUVEJThFJTk4JUVDJTlEJUI0JUVDJThBJUE0JTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUIlQTUlQkMlMjAlRUMlQTAlOUMlRUElQjMlQjUlRUQlOTUlOUMlRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI5NWM1ZjQxZjg1ODA0OWI5YWZjNWIyMTY3Y2NiNzRiNyUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjdiNmQyNzQ1Nzk0MjRjZTE4ZTg2YTk5NmMyNTk5NTVjJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyS2N5RXcwV2JoRm5RJTIyJTdE&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;7b6d274579424ce18e86a996c259955c&quot;&gt;
&lt;div data-block-content=&quot;7b6d274579424ce18e86a996c259955c&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;95c5f41f858049b9afc5b2167ccb74b7&quot;&gt;java.util.function.Function&lt;span data-offset-key=&quot;95c5f41f858049b9afc5b2167ccb74b7:1&quot;&gt; 인터페이스는 제네릭 형식 T를 인수로 받아서 제네릭 형식 R 객체를 반환하는 &lt;/span&gt;apply&lt;span data-offset-key=&quot;95c5f41f858049b9afc5b2167ccb74b7:3&quot;&gt;라는 추상 메서드를 정의한다. 입력을 출력으로 매핑하는 람다를 정의할 때 Function 인터페이스를 활용할 수 있다. 자바 8에서는 &lt;/span&gt;기본형&lt;span data-offset-key=&quot;95c5f41f858049b9afc5b2167ccb74b7:5&quot;&gt;을 입출력으로 사용하는 상황에서 &lt;/span&gt;오토박싱&lt;span data-offset-key=&quot;95c5f41f858049b9afc5b2167ccb74b7:7&quot;&gt; 동작을 피할 수 있도록 특별한 버전의 &lt;/span&gt;함수형 인터페이스&lt;span data-offset-key=&quot;95c5f41f858049b9afc5b2167ccb74b7:9&quot;&gt;를 제공한다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;Supplier&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;매개 변수는 없고, 반환 값이 있는 함수형 인터페이스이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;추상 메소드&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;T supplier()&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;를 가진다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;b7a1963f94d84ae39bd83ea767133277&quot;&gt;
&lt;div data-block-content=&quot;b7a1963f94d84ae39bd83ea767133277&quot;&gt;
&lt;div&gt;
&lt;h4 data-rnwr700-gg6oyi-ubezar-135wba7-1kfrs79=&quot;true&quot; data-rnwrdesktop-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 id=&quot;text-undefined-8&quot; data-rnwr700-gg6oyi-ubezar-135wba7-1kfrs79=&quot;true&quot; data-rnwrdesktop-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span data-key=&quot;6c6be1fcdf0f44f0bc0ddcc0d32b9122&quot;&gt;&lt;span data-offset-key=&quot;6c6be1fcdf0f44f0bc0ddcc0d32b9122:0&quot;&gt;메서드 레퍼런스&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;6bdec5ec22424df8bd0d9c9020381830&quot;&gt;
&lt;div data-block-content=&quot;6bdec5ec22424df8bd0d9c9020381830&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;602829c6c3c04078a8d253106fa792de&quot;&gt;&lt;span data-offset-key=&quot;602829c6c3c04078a8d253106fa792de:0&quot;&gt;메서드 레퍼런스는 특정 메서드만을 호출하는 람다의 &lt;/span&gt;축약형&lt;span data-offset-key=&quot;602829c6c3c04078a8d253106fa792de:2&quot;&gt;이다. 메서드 레퍼런스를 새로운 기능이 아니라 하나의 메서드를 참조하는 람다를 편리게 표현할 수 있는 문법으로 간주 할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-key=&quot;6f726334b2ad4f96a6c29658c3234739&quot; data-slate-void=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;6f726334b2ad4f96a6c29658c3234739&quot;&gt;
&lt;div data-block-content=&quot;6f726334b2ad4f96a6c29658c3234739&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr data-rnwi-handle=&quot;table-row&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;td&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-document-key=&quot;890ddf07c1d7483a9d4b90018b6b4ae0&quot; data-slate-editor=&quot;true&quot; data-fragment=&quot;true&quot; data-key=&quot;d122b8ea79c440e5bc0e62c93f3fc71f&quot;&gt;
&lt;div data-key=&quot;a3e1b0f044c0405fa1e492fd2f1c69c9&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;fda062e9f87f4a9ab192d44f2ea0cdfa&quot;&gt;&lt;span data-offset-key=&quot;fda062e9f87f4a9ab192d44f2ea0cdfa:0&quot;&gt;람다&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-document-key=&quot;890ddf07c1d7483a9d4b90018b6b4ae0&quot; data-slate-editor=&quot;true&quot; data-fragment=&quot;true&quot; data-key=&quot;1c3c05c978cb41edb48349cf72102b47&quot;&gt;
&lt;div data-key=&quot;45ea4d36ae6944709fe02218957ede8f&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;77dfd310b56c43128be267291a27efb5&quot;&gt;&lt;span data-offset-key=&quot;77dfd310b56c43128be267291a27efb5:0&quot;&gt;메서드 레퍼런스 단축 표&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-rnwi-handle=&quot;table-row&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;td&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-document-key=&quot;890ddf07c1d7483a9d4b90018b6b4ae0&quot; data-slate-editor=&quot;true&quot; data-fragment=&quot;true&quot; data-key=&quot;1f41ca62f7314a868a2d2d1238f8c724&quot;&gt;
&lt;div data-key=&quot;d468970e3d1c45be9292536cbfc21af0&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;294e9a98d2cc4fee9e595e24e82aa483&quot;&gt;&lt;span data-offset-key=&quot;294e9a98d2cc4fee9e595e24e82aa483:0&quot;&gt;(Apple a) &amp;rarr; a.getWeight()&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-document-key=&quot;890ddf07c1d7483a9d4b90018b6b4ae0&quot; data-slate-editor=&quot;true&quot; data-fragment=&quot;true&quot; data-key=&quot;08a16221b6034d5d8f15d51a8356042b&quot;&gt;
&lt;div data-key=&quot;9f12964ae1da41af9604250d3a4a2499&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;8d1343c87a2b486d80fc7537a4d7b478&quot;&gt;&lt;span data-offset-key=&quot;8d1343c87a2b486d80fc7537a4d7b478:0&quot;&gt;Apple::getWeight&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-rnwi-handle=&quot;table-row&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;td&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-document-key=&quot;890ddf07c1d7483a9d4b90018b6b4ae0&quot; data-slate-editor=&quot;true&quot; data-fragment=&quot;true&quot; data-key=&quot;db1674e5d7ab462db63e4aa9b5f9bf0b&quot;&gt;
&lt;div data-key=&quot;c7f4ece89cc74bc5ba8477a5e1714974&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;9aa37ff42ec944348dd5de76beb465ae&quot;&gt;&lt;span data-offset-key=&quot;9aa37ff42ec944348dd5de76beb465ae:0&quot;&gt;() &amp;rarr; Thread.currentThread().dumpStack()&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-document-key=&quot;890ddf07c1d7483a9d4b90018b6b4ae0&quot; data-slate-editor=&quot;true&quot; data-fragment=&quot;true&quot; data-key=&quot;6a8d6e06b3f14979a4ea5ef810038116&quot;&gt;
&lt;div data-key=&quot;7fa460913d064b6585b2f98b1489dfe1&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;968bb984b7b446d98edfb071ead48f0d&quot;&gt;&lt;span data-offset-key=&quot;968bb984b7b446d98edfb071ead48f0d:0&quot;&gt;Thread.currentThread()::dumpStack&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-rnwi-handle=&quot;table-row&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;td&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-document-key=&quot;890ddf07c1d7483a9d4b90018b6b4ae0&quot; data-slate-editor=&quot;true&quot; data-fragment=&quot;true&quot; data-key=&quot;e17fbf35a1f54d4bbf2b965bef7e1b4c&quot;&gt;
&lt;div data-key=&quot;dbe6d9e3a3d447cc81df03d0501b3c10&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;9ca060567b614a8e9c6dedca3ea1a504&quot;&gt;&lt;span data-offset-key=&quot;9ca060567b614a8e9c6dedca3ea1a504:0&quot;&gt;(str, i) &amp;rArr; str.substring(i)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-document-key=&quot;890ddf07c1d7483a9d4b90018b6b4ae0&quot; data-slate-editor=&quot;true&quot; data-fragment=&quot;true&quot; data-key=&quot;4f1c528c49c14b27b07fbb6ff5982689&quot;&gt;
&lt;div data-key=&quot;750794dd7194421b8f4ce3233f44845a&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;9852555e2e78486e89a4c837a3c2add7&quot;&gt;&lt;span data-offset-key=&quot;9852555e2e78486e89a4c837a3c2add7:0&quot;&gt;String::substring&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-rnwi-handle=&quot;table-row&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;td&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-document-key=&quot;890ddf07c1d7483a9d4b90018b6b4ae0&quot; data-slate-editor=&quot;true&quot; data-fragment=&quot;true&quot; data-key=&quot;8f1dda2875834dcfacf55dc69f12f72b&quot;&gt;
&lt;div data-key=&quot;982d653029f540bcbf651399bcac31b7&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;ccbef01ddc9c4f0e8c16402912d6c847&quot;&gt;&lt;span data-offset-key=&quot;ccbef01ddc9c4f0e8c16402912d6c847:0&quot;&gt;(String s) &amp;rarr; System.out.println(s)&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-document-key=&quot;890ddf07c1d7483a9d4b90018b6b4ae0&quot; data-slate-editor=&quot;true&quot; data-fragment=&quot;true&quot; data-key=&quot;ffd4e759cf5f4afba18bd2734540c105&quot;&gt;
&lt;div data-key=&quot;d96bd2232d9a4989a4dbd866519a382a&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;4ed3cdb7085f410fbdd89e1cd1e03f80&quot;&gt;&lt;span data-offset-key=&quot;4ed3cdb7085f410fbdd89e1cd1e03f80:0&quot;&gt;System.out::println&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;4bb0ed1fa92b40bd840df5620108f636&quot;&gt;
&lt;div data-block-content=&quot;4bb0ed1fa92b40bd840df5620108f636&quot;&gt;
&lt;div&gt;
&lt;h3 id=&quot;text-undefined-9&quot; data-rnwr700-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot; data-rnwrdesktop-gg6oyi-1x35g6-37tt59-b88u0q=&quot;true&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span data-key=&quot;65437095401e4fddb162b6b83cc7b407&quot;&gt;&lt;span data-offset-key=&quot;65437095401e4fddb162b6b83cc7b407:0&quot;&gt;람다, 메서드 레퍼런스 활용하기&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span data-key=&quot;65437095401e4fddb162b6b83cc7b407&quot;&gt;&lt;span data-offset-key=&quot;65437095401e4fddb162b6b83cc7b407:0&quot;&gt;아래와 같은 순서로 사용하면 편하다&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-key=&quot;9ccd231bcd2345b98fb034c80c8848ac&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;div data-block-content=&quot;9ccd231bcd2345b98fb034c80c8848ac&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;a311c88fcb9343c3b8abfa61bee55165&quot;&gt;
&lt;div data-block-content=&quot;a311c88fcb9343c3b8abfa61bee55165&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;071ce0adebd5470c8edd3585461311eb&quot;&gt;&lt;span data-offset-key=&quot;071ce0adebd5470c8edd3585461311eb:0&quot;&gt;코드전달 &amp;rarr; 익명 클래스 사용 &amp;rarr; 람다 표현식 사용 &amp;rarr; 메서드 레퍼런스 사용&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;45bdcdfcfd0b46e0a7c80ec7b23142b3&quot;&gt;
&lt;div data-block-content=&quot;45bdcdfcfd0b46e0a7c80ec7b23142b3&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;2891bca65f684a23a34dcccea9fe0d0e&quot;&gt;Comparator&lt;span data-offset-key=&quot;2891bca65f684a23a34dcccea9fe0d0e:1&quot;&gt;는 &lt;/span&gt;Comparable&lt;span data-offset-key=&quot;2891bca65f684a23a34dcccea9fe0d0e:3&quot;&gt; 키를 추출해서 &lt;/span&gt;Comparator&lt;span data-offset-key=&quot;2891bca65f684a23a34dcccea9fe0d0e:5&quot;&gt; 객체로 만드는 &lt;/span&gt;Function&lt;span data-offset-key=&quot;2891bca65f684a23a34dcccea9fe0d0e:7&quot;&gt; 함수를 인수로 받는 정적 메서드 &lt;/span&gt;comparing&lt;span data-offset-key=&quot;2891bca65f684a23a34dcccea9fe0d0e:9&quot;&gt;을 포함한다. 그러므로 다음처럼 사용할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div data-key=&quot;db482025f8734a6dbeccadcab18c0e12&quot;&gt;
&lt;div data-block-content=&quot;db482025f8734a6dbeccadcab18c0e12&quot;&gt;
&lt;div data-rnwi-handle=&quot;codeblock-toolbar&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;476118893ebf4bb3b7cbf7e2dfeed605&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div data-key=&quot;91adb3f88a164aa799fa736c1600c90e&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1709301981353&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import static java.util.Comparator.comparing;

inventory.sort(comparing((a) -&amp;gt; a.getWeight()));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-rnwi-handle=&quot;nearest&quot; data-rnwicodeblock-toolbar-visible-hover-focus=&quot;true&quot; data-rnwicodeblock-toolbar-hidden-=&quot;true&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;749e4a2a0231453ebb73baa46cceb046&quot;&gt;
&lt;div data-block-content=&quot;749e4a2a0231453ebb73baa46cceb046&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;bb7b4b24315a4557a13d68e6ed80b7a4&quot;&gt;&lt;span data-offset-key=&quot;bb7b4b24315a4557a13d68e6ed80b7a4:0&quot;&gt;메서드 레퍼런스를 사용했을 때&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div data-key=&quot;6337430abbe54020a3f98f138e617720&quot;&gt;
&lt;div data-block-content=&quot;6337430abbe54020a3f98f138e617720&quot;&gt;
&lt;div data-rnwi-handle=&quot;codeblock-toolbar&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;0cd000375152484c9849977cf43ef35e&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1709302028349&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;inventory.sort(comparing(Apple::getWeight));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-rnwi-handle=&quot;nearest&quot; data-rnwicodeblock-toolbar-visible-hover-focus=&quot;true&quot; data-rnwicodeblock-toolbar-hidden-=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div data-rnwi-handle=&quot;button&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot; data-rnwi-37p410-1iadl42-hover-focus=&quot;true&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;148d1f96d50c44b0ba43373f163880a2&quot;&gt;
&lt;div data-block-content=&quot;148d1f96d50c44b0ba43373f163880a2&quot;&gt;
&lt;div&gt;
&lt;h3 id=&quot;text-undefined-10&quot; data-rnwr700-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot; data-rnwrdesktop-gg6oyi-1x35g6-37tt59-b88u0q=&quot;true&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span data-key=&quot;6a1885561df8479ca4bd065a94c57735&quot;&gt;&lt;span data-offset-key=&quot;6a1885561df8479ca4bd065a94c57735:0&quot;&gt;람다 표현식을 조합할 수 있는 유용한 메서드&lt;/span&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;bc2445a7686e478cafc76fd18b9654e0&quot;&gt;
&lt;div data-block-content=&quot;bc2445a7686e478cafc76fd18b9654e0&quot;&gt;
&lt;div&gt;
&lt;h4 id=&quot;text-undefined-11&quot; data-rnwr700-gg6oyi-ubezar-135wba7-1kfrs79=&quot;true&quot; data-rnwrdesktop-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span data-key=&quot;d6f32036f5b148caa0100b38791368a1&quot;&gt;&lt;span data-offset-key=&quot;d6f32036f5b148caa0100b38791368a1:0&quot;&gt;역정렬&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;173a706462174e238f1a9736f819460a&quot;&gt;
&lt;div data-block-content=&quot;173a706462174e238f1a9736f819460a&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;d34793cbb4f34ee4884293e88aa7ea04&quot;&gt;비교자 구현&lt;span data-offset-key=&quot;d34793cbb4f34ee4884293e88aa7ea04:1&quot;&gt;을 그대로 재사용하여 사과의 무게를 기준으로 &lt;/span&gt;역정렬&lt;span data-offset-key=&quot;d34793cbb4f34ee4884293e88aa7ea04:3&quot;&gt;할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div data-key=&quot;b93926d3601540c8bfc96e5709831d3f&quot;&gt;
&lt;div data-block-content=&quot;b93926d3601540c8bfc96e5709831d3f&quot;&gt;
&lt;div data-rnwi-handle=&quot;codeblock-toolbar&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;d4d3bc114bb546619c3bc6fe44038d5d&quot;&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1709302150389&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 무게를 내림차순으로 정렬

Inventory.sort(comparing(Apple::getWeight).reserved());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-rnwi-handle=&quot;nearest&quot; data-rnwicodeblock-toolbar-visible-hover-focus=&quot;true&quot; data-rnwicodeblock-toolbar-hidden-=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div data-rnwi-handle=&quot;button&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot; data-rnwi-37p410-1iadl42-hover-focus=&quot;true&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;e6d103cddcc94ddc8e0c717681ab60ce&quot;&gt;
&lt;div data-block-content=&quot;e6d103cddcc94ddc8e0c717681ab60ce&quot;&gt;
&lt;div&gt;
&lt;h4 id=&quot;text-comparator&quot; data-rnwr700-gg6oyi-ubezar-135wba7-1kfrs79=&quot;true&quot; data-rnwrdesktop-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span data-key=&quot;10b26bc0e3094ae2981acb8c85abda25&quot;&gt;&lt;span data-offset-key=&quot;10b26bc0e3094ae2981acb8c85abda25:0&quot;&gt;Comparator 연결&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;faf703c2c35a4d979029c018f26cc47f&quot;&gt;
&lt;div data-block-content=&quot;faf703c2c35a4d979029c018f26cc47f&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;cc8733f0151441669b5055fd830baf42&quot;&gt;thenComparing&lt;span data-offset-key=&quot;cc8733f0151441669b5055fd830baf42:1&quot;&gt;은 함수를 인수로 받아 첫 번째 비교자를 이요해서 두 객체가 같다고 판단되면 두 번째 비교자에 객체를 전달한다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;c2ec4579d7c34f168c16c9edd4217ced&quot;&gt;
&lt;div data-block-content=&quot;c2ec4579d7c34f168c16c9edd4217ced&quot;&gt;
&lt;div data-rnwi-handle=&quot;codeblock-toolbar&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;c6db1ed45e1c425b9dc4fb52810b2493&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1709302160553&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 무게를 내림차순으로 정렬하고 두 사과의 무게가 같으면 국가별로 정렬할것

inventory.sort(comparing(Apple::getWeight)

.recered()

.thenComparing(Apple::getContry));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;4e547e1f59d0437b9bf3333a4acc2710&quot;&gt;
&lt;div data-block-content=&quot;4e547e1f59d0437b9bf3333a4acc2710&quot;&gt;
&lt;div&gt;
&lt;h4 data-rnwr700-gg6oyi-ubezar-135wba7-1kfrs79=&quot;true&quot; data-rnwrdesktop-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 id=&quot;text-predicate-1&quot; data-rnwr700-gg6oyi-ubezar-135wba7-1kfrs79=&quot;true&quot; data-rnwrdesktop-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span data-key=&quot;c7ec4b540d9f456cb5b19732698be82a&quot;&gt;&lt;span data-offset-key=&quot;c7ec4b540d9f456cb5b19732698be82a:0&quot;&gt;Predicate 조합&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;1050414ccac14fd9b43ee73c9ed77d54&quot;&gt;
&lt;div data-block-content=&quot;1050414ccac14fd9b43ee73c9ed77d54&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;2b526e4621ab41eab31a5b798630dc5f&quot;&gt;Predicate&lt;span data-offset-key=&quot;2b526e4621ab41eab31a5b798630dc5f:1&quot;&gt; 인터페이스는 복잡한 &lt;/span&gt;Predicate&lt;span data-offset-key=&quot;2b526e4621ab41eab31a5b798630dc5f:3&quot;&gt;를 만들 수 있도록 &lt;/span&gt;negate&lt;span data-offset-key=&quot;2b526e4621ab41eab31a5b798630dc5f:5&quot;&gt;, &lt;/span&gt;and&lt;span data-offset-key=&quot;2b526e4621ab41eab31a5b798630dc5f:7&quot;&gt;, &lt;/span&gt;or&lt;span data-offset-key=&quot;2b526e4621ab41eab31a5b798630dc5f:9&quot;&gt; 세 가지 메서드를 제공한다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div data-key=&quot;d40c5c49e66944f68bb99e38a7d9a144&quot;&gt;
&lt;div data-block-content=&quot;d40c5c49e66944f68bb99e38a7d9a144&quot;&gt;
&lt;div data-rnwi-handle=&quot;codeblock-toolbar&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;b84e851545354e558bf5455cbfcb94e7&quot;&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1709302170327&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 빨간색이면서 무거운(150그램 이상) 사과 또는 그냥 녹색 사과

Predicate&amp;lt;Apple&amp;gt; redAndHeavyAppleOrGreen =

redApple.and(a -&amp;gt; a.getWeight() &amp;gt; 150)

.or(a -&amp;gt; &quot;green&quot;.equals(a.getColor()));&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-rnwi-handle=&quot;nearest&quot; data-rnwicodeblock-toolbar-visible-hover-focus=&quot;true&quot; data-rnwicodeblock-toolbar-hidden-=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div data-rnwi-handle=&quot;button&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot; data-rnwi-37p410-1iadl42-hover-focus=&quot;true&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;f7978008bac746d399c5b3ca2ab29cb9&quot;&gt;
&lt;div data-block-content=&quot;f7978008bac746d399c5b3ca2ab29cb9&quot;&gt;
&lt;div&gt;
&lt;h4 id=&quot;text-function-1&quot; data-rnwr700-gg6oyi-ubezar-135wba7-1kfrs79=&quot;true&quot; data-rnwrdesktop-gg6oyi-adyw6z-135wba7-b88u0q=&quot;true&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span data-key=&quot;e11431df1de243ab870b1c3cb1ec36ae&quot;&gt;&lt;span data-offset-key=&quot;e11431df1de243ab870b1c3cb1ec36ae:0&quot;&gt;Function 조합&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;cb2ff588ce4f48da90b9d6b419a6eee4&quot;&gt;
&lt;div data-block-content=&quot;cb2ff588ce4f48da90b9d6b419a6eee4&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;78cff46b933a4821b455402f9bf9e15b&quot;&gt;Function&lt;span data-offset-key=&quot;78cff46b933a4821b455402f9bf9e15b:1&quot;&gt; 인터페이스는 &lt;/span&gt;andThen&lt;span data-offset-key=&quot;78cff46b933a4821b455402f9bf9e15b:3&quot;&gt;, &lt;/span&gt;compose&lt;span data-offset-key=&quot;78cff46b933a4821b455402f9bf9e15b:5&quot;&gt; 두 가지 디폴트 메서드를 제공한다. &lt;/span&gt;andThen&lt;span data-offset-key=&quot;78cff46b933a4821b455402f9bf9e15b:7&quot;&gt; 메서드는 주어진 함수를 먼저 적용한 결과를 다른 함수의 입력으로 전달하는 함수를 반환한다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div data-key=&quot;0b209ba866304276bcb8307f3c80fa7a&quot;&gt;
&lt;div data-block-content=&quot;0b209ba866304276bcb8307f3c80fa7a&quot;&gt;
&lt;div data-rnwi-handle=&quot;codeblock-toolbar&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;246c32b1b1a545cf955e4c2335ed25bd&quot;&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1709302179844&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Function&amp;lt;Integer, Integer&amp;gt; f = x -&amp;gt; x + 1;

Function&amp;lt;Integer, Integer&amp;gt; g = x -&amp;gt; x * 2;

Function&amp;lt;Integer, Integer&amp;gt; h = f.andThen(g);

int result = h.apply(1); // 4&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-rnwi-handle=&quot;nearest&quot; data-rnwicodeblock-toolbar-visible-hover-focus=&quot;true&quot; data-rnwicodeblock-toolbar-hidden-=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div data-rnwi-handle=&quot;button&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot; data-rnwi-37p410-1iadl42-hover-focus=&quot;true&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-key=&quot;18f055e025f942ba9c0110ff4207971b&quot;&gt;
&lt;div data-block-content=&quot;18f055e025f942ba9c0110ff4207971b&quot;&gt;
&lt;div&gt;&lt;span data-key=&quot;f6da8170f57846ddbe84c90a0df526cc&quot;&gt;compose&lt;span data-offset-key=&quot;f6da8170f57846ddbe84c90a0df526cc:1&quot;&gt; 메서드는 인수로 주어진 함수를 먼저 실행한 다음에 그 결과를 외부 함수의 인수로 제공한다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div data-slate-fragment=&quot;JTdCJTIyb2JqZWN0JTIyJTNBJTIyZG9jdW1lbnQlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJoZWFkaW5nLTElMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQiU5RSU4QyVFQiU4QiVBNCUyQyUyMCVFQiVBOSU5NCVFQyU4NCU5QyVFQiU5MyU5QyUyMCVFQiVBMCU4OCVFRCU4RCVCQyVFQiU5RiVCMCVFQyU4QSVBNCUyMCVFRCU5OSU5QyVFQyU5QSVBOSVFRCU5NSU5OCVFQSVCOCVCMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIycGh2bWJEdlBPWXRSJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyc1hQc3g4R0NObkRxJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyYmxvY2txdW90ZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUMlQkQlOTQlRUIlOTMlOUMlRUMlQTAlODQlRUIlOEIlQUMlMjAlRTIlODYlOTIlMjAlRUMlOUQlQjUlRUIlQUElODUlMjAlRUQlODElQjQlRUIlOUUlOTglRUMlOEElQTQlMjAlRUMlODIlQUMlRUMlOUElQTklMjAlRTIlODYlOTIlMjAlRUIlOUUlOEMlRUIlOEIlQTQlMjAlRUQlOTElOUMlRUQlOTglODQlRUMlOEIlOUQlMjAlRUMlODIlQUMlRUMlOUElQTklMjAlRTIlODYlOTIlMjAlRUIlQTklOTQlRUMlODQlOUMlRUIlOTMlOUMlMjAlRUIlQTAlODglRUQlOEQlQkMlRUIlOUYlQjAlRUMlOEElQTQlMjAlRUMlODIlQUMlRUMlOUElQTklMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjA3MWNlMGFkZWJkNTQ3MGM4ZWRkMzU4NTQ2MTMxMWViJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYTMxMWM4OGZjYjkzNDNjM2I4YWJmYTYxYmVlNTUxNjUlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI5Y2NkMjMxYmNkMjM0NWI5OGZiMDM0YzgwYzg4NDhhYyUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyQ29tcGFyYXRvciUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybWFyayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCU3RCU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVCJThBJTk0JTIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMkNvbXBhcmFibGUlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCVFRCU4MiVBNCVFQiVBNSVCQyUyMCVFQyVCNiU5NCVFQyVCNiU5QyVFRCU5NSVCNCVFQyU4NCU5QyUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJDb21wYXJhdG9yJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlRUElQjAlOUQlRUMlQjIlQjQlRUIlQTElOUMlMjAlRUIlQTclOEMlRUIlOTMlOUMlRUIlOEElOTQlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyRnVuY3Rpb24lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCVFRCU5NSVBOCVFQyU4OCU5OCVFQiVBNSVCQyUyMCVFQyU5RCVCOCVFQyU4OCU5OCVFQiVBMSU5QyUyMCVFQiVCMCU5QiVFQiU4QSU5NCUyMCVFQyVBMCU5NSVFQyVBMCU4MSUyMCVFQiVBOSU5NCVFQyU4NCU5QyVFQiU5MyU5QyUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJjb21wYXJpbmclMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyU5RCU4NCUyMCVFRCU4RiVBQyVFRCU5NSVBOCVFRCU5NSU5QyVFQiU4QiVBNC4lMjAlRUElQjclQjglRUIlOUYlQUMlRUIlQUYlODAlRUIlQTElOUMlMjAlRUIlOEIlQTQlRUMlOUQlOEMlRUMlQjIlOTglRUIlOUYlQkMlMjAlRUMlODIlQUMlRUMlOUElQTklRUQlOTUlQTAlMjAlRUMlODglOTglMjAlRUMlOUUlODglRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIyODkxYmNhNjVmNjg0YTIzYTM0ZGNjY2VhOWZlMGQwZSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjQ1YmRjZGZjZmQwYjQ2ZTBhN2M4MGVjN2IyMzE0MmIzJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiUyMnN5bnRheCUyMiUzQSUyMmphdmElMjIlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUtbGluZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyaW1wb3J0JTIwc3RhdGljJTIwamF2YS51dGlsLkNvbXBhcmF0b3IuY29tcGFyaW5nJTNCJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI0N2ViMmJkODA5MmM0NWRmOWRhMTczM2IxZjg0M2RlZiUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjQ3NjExODg5M2ViZjRiYjNiN2NiZjdlMmRmZWVkNjA1JTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZS1saW5lJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJpbnZlbnRvcnkuc29ydChjb21wYXJpbmcoKGEpJTIwLSUzRSUyMGEuZ2V0V2VpZ2h0KCkpKSUzQiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyNTM2NTUzZGFkZTNkNGZlOWI1MDk3M2ZmNTU1Yjg2YmMlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI5MWFkYjNmODhhMTY0YWE3OTlmYTczNmMxNjAwYzkwZSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmRiNDgyMDI1Zjg3MzRhNmRiZWNjYWRjYWIxOGMwZTEyJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUIlQTklOTQlRUMlODQlOUMlRUIlOTMlOUMlMjAlRUIlQTAlODglRUQlOEQlQkMlRUIlOUYlQjAlRUMlOEElQTQlRUIlQTUlQkMlMjAlRUMlOUQlQjQlRUQlOTUlOTglRUIlQTklQjQlMjAlRUIlOEQlOTQlMjAlRUElQjklOTQlRUIlODElOTQlRUQlOTUlOTglRUElQjIlOEMlMjAlRUQlOTElOUMlRUQlOTglODQlRUIlOEYlODQlMjAlRUElQjAlODAlRUIlOEElQTUlRUQlOTUlOTglRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJiYjdiNGIyNDMxNWE0NTU3YTEzZDY4ZTZlZDgwYjdhNCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjc0OWU0YTJhMDIzMTQ1M2ViYjczYmFhNDZjY2ViMDQ2JTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiUyMnN5bnRheCUyMiUzQSUyMmphdmElMjIlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUtbGluZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyaW52ZW50b3J5LnNvcnQoY29tcGFyaW5nKEFwcGxlJTNBJTNBZ2V0V2VpZ2h0KSklM0IlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjg0ZDM1YjU5NzYwZDRiYjA5NTI5MWZjZGRiMTk2NDRjJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMGNkMDAwMzc1MTUyNDg0Yzk4NDk5NzdjZjQzZWYzNWUlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI2MzM3NDMwYWJiZTU0MDIwYTNmOThmMTM4ZTYxNzcyMCUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmhlYWRpbmctMSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVCJTlFJThDJUVCJThCJUE0JTIwJUVEJTkxJTlDJUVEJTk4JTg0JUVDJThCJTlEJUVDJTlEJTg0JTIwJUVDJUExJUIwJUVEJTk1JUE5JUVEJTk1JUEwJTIwJUVDJTg4JTk4JTIwJUVDJTlFJTg4JUVCJThBJTk0JTIwJUVDJTlDJUEwJUVDJTlBJUE5JUVEJTk1JTlDJTIwJUVCJUE5JTk0JUVDJTg0JTlDJUVCJTkzJTlDJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI2YTE4ODU1NjFkZjg0NzljYTRiZDA2NWE5NGM1NzczNSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjE0OGQxZjk2ZDUwYzQ0YjBiYTQzMzczZjE2Mzg4MGEyJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyaGVhZGluZy0yJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUMlOTclQUQlRUMlQTAlOTUlRUIlQTAlQUMlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmQ2ZjMyMDM2ZjViMTQ4Y2FhMDEwMGIzODc5MTM2OGExJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYmMyNDQ1YTc2ODZlNDc4Y2FmYzc2ZmQxOGI5NjU0ZTAlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQiVCOSU4NCVFQSVCNSU5MCVFQyU5RSU5MCUyMCVFQSVCNSVBQyVFRCU5OCU4NCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybWFyayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCU3RCU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVDJTlEJTg0JTIwJUVBJUI3JUI4JUVCJThDJTgwJUVCJUExJTlDJTIwJUVDJTlFJUFDJUVDJTgyJUFDJUVDJTlBJUE5JUVEJTk1JTk4JUVDJTk3JUFDJTIwJUVDJTgyJUFDJUVBJUIzJUJDJUVDJTlEJTk4JTIwJUVCJUFDJUI0JUVBJUIyJThDJUVCJUE1JUJDJTIwJUVBJUI4JUIwJUVDJUE0JTgwJUVDJTlDJUJDJUVCJUExJTlDJTIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiVFQyU5NyVBRCVFQyVBMCU5NSVFQiVBMCVBQyUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybWFyayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCU3RCU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJUVEJTk1JUEwJTIwJUVDJTg4JTk4JTIwJUVDJTlFJTg4JUVCJThCJUE0LiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZDM0NzkzY2JiNGYzNGVlNDg4NDI5M2U4OGFhN2VhMDQlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIxNzNhNzA2NDYyMTc0ZTIzOGYxYTk3MzZmODE5NDYwYSUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlMjJzeW50YXglMjIlM0ElMjJqYXZhJTIyJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlLWxpbmUlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyRiUyRiUyMCVFQiVBQyVCNCVFQSVCMiU4QyVFQiVBNSVCQyUyMCVFQiU4MiVCNCVFQiVBNiVCQyVFQyVCMCVBOCVFQyU4OCU5QyVFQyU5QyVCQyVFQiVBMSU5QyUyMCVFQyVBMCU5NSVFQiVBMCVBQyUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYzBiYTUzY2E1NzI2NDA1Yzg2ZWZlMGNkYmRlNzNiNDUlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJkNGQzYmMxMTRiYjU0NjYxOWMzYmM2ZmU0NDAzOGQ1ZCUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUtbGluZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIySW52ZW50b3J5LnNvcnQoY29tcGFyaW5nKEFwcGxlJTNBJTNBZ2V0V2VpZ2h0KS5yZXNlcnZlZCgpKSUzQiUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyNjI0MjA1MzBmMjRhNDQ2OWE1ZGQ0Y2NiZWQ4ZjYzOTIlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIyMzgyY2Q2ZjAwNzM0NGY1OWFmNjVkYWUwOWJmYTk3NyUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmI5MzkyNmQzNjAxNTQwYzhiZmM5NmU1NzA5ODMxZDNmJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyaGVhZGluZy0yJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJDb21wYXJhdG9yJTIwJUVDJTk3JUIwJUVBJUIyJUIwJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIxMGIyNmJjMGUzMDk0YWUyOTgxYWNiOGM4NWFiZGEyNSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmU2ZDEwM2NkZGNjOTRkZGM4ZTBjNzE3NjgxYWI2MGNlJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIycGFyYWdyYXBoJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJ0aGVuQ29tcGFyaW5nJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUMlOUQlODAlMjAlRUQlOTUlQTglRUMlODglOTglRUIlQTUlQkMlMjAlRUMlOUQlQjglRUMlODglOTglRUIlQTElOUMlMjAlRUIlQjAlOUIlRUMlOTUlODQlMjAlRUMlQjIlQUIlMjAlRUIlQjIlODglRUMlQTclQjglMjAlRUIlQjklODQlRUElQjUlOTAlRUMlOUUlOTAlRUIlQTUlQkMlMjAlRUMlOUQlQjQlRUMlOUElOTQlRUQlOTUlQjQlRUMlODQlOUMlMjAlRUIlOTElOTAlMjAlRUElQjAlOUQlRUMlQjIlQjQlRUElQjAlODAlMjAlRUElQjAlOTklRUIlOEIlQTQlRUElQjMlQTAlMjAlRUQlOEMlOTAlRUIlOEIlQTglRUIlOTAlOTglRUIlQTklQjQlMjAlRUIlOTElOTAlMjAlRUIlQjIlODglRUMlQTclQjglMjAlRUIlQjklODQlRUElQjUlOTAlRUMlOUUlOTAlRUMlOTclOTAlMjAlRUElQjAlOUQlRUMlQjIlQjQlRUIlQTUlQkMlMjAlRUMlQTAlODQlRUIlOEIlQUMlRUQlOTUlOUMlRUIlOEIlQTQuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJjYzg3MzNmMDE1MTQ0MTY2OWI1MDU1ZmQ4MzBiYWY0MiUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmZhZjcwM2MyYzM1YTRkOTc5MDI5YzAxOGYyNmNjNDdmJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiUyMnN5bnRheCUyMiUzQSUyMmphdmElMjIlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUtbGluZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJTJGJTJGJTIwJUVCJUFDJUI0JUVBJUIyJThDJUVCJUE1JUJDJTIwJUVCJTgyJUI0JUVCJUE2JUJDJUVDJUIwJUE4JUVDJTg4JTlDJUVDJTlDJUJDJUVCJUExJTlDJTIwJUVDJUEwJTk1JUVCJUEwJUFDJUVEJTk1JTk4JUVBJUIzJUEwJTIwJUVCJTkxJTkwJTIwJUVDJTgyJUFDJUVBJUIzJUJDJUVDJTlEJTk4JTIwJUVCJUFDJUI0JUVBJUIyJThDJUVBJUIwJTgwJTIwJUVBJUIwJTk5JUVDJTlDJUJDJUVCJUE5JUI0JTIwJUVBJUI1JUFEJUVBJUIwJTgwJUVCJUIzJTg0JUVCJUExJTlDJTIwJUVDJUEwJTk1JUVCJUEwJUFDJUVEJTk1JUEwJUVBJUIyJTgzJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI5NGFiZTdmYjkzNWI0MzY4YjlmM2Q2YmMyMWMwNzc5YiUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmM2ZGIxZWQ0NWUxYzQyNWI5ZGM0ZmI1MjgxMGIyNDkzJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZS1saW5lJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJpbnZlbnRvcnkuc29ydChjb21wYXJpbmcoQXBwbGUlM0ElM0FnZXRXZWlnaHQpJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJhOWNlZmM5ZjA1YTI0NGZmYjA4MGI4NmEyOTllZmE4MCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjJhZjRkMjY1YzU5YzQ4NzhhYjRiODYyMzFlNmI1NDlhJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZS1saW5lJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlMjAlMjAlMjAucmVjZXJlZCgpJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI4NmRiYzdmNWI1MDY0M2RjYmZkYzc1M2JlYmZhMjEwNiUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmM4MjliNjBhMWExYTQwNDliMzg5OGQ1MjAxM2U3NTQ0JTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZS1saW5lJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlMjAlMjAlMjAudGhlbkNvbXBhcmluZyhBcHBsZSUzQSUzQWdldENvbnRyeSkpJTNCJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIxMjdlNzhiYjQyMWU0NDgyOThhMzI5MjUwZGM3Zjc0MSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmQwNzEyYmY1MDY3NzRjYjA4MjA2ZDFhMmEwZDE4YTdlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYzJlYzQ1NzlkN2MzNGYxNjhjMTZjOWVkZDQyMTdjZWQlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJoZWFkaW5nLTIlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMlByZWRpY2F0ZSUyMCVFQyVBMSVCMCVFRCU5NSVBOSUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYzdlYzRiNTQwZDlmNDU2Y2I1YjE5NzMyNjk4YmU4MmElMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI0ZTU0N2UxZjU5ZDA0MzdiOWJmMzMzM2E0YWNjMjcxMCUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyUHJlZGljYXRlJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMjAlRUMlOUQlQjglRUQlODQlQjAlRUQlOEUlOTglRUMlOUQlQjQlRUMlOEElQTQlRUIlOEElOTQlMjAlRUIlQjMlQjUlRUMlOUUlQTElRUQlOTUlOUMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyUHJlZGljYXRlJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlRUIlQTUlQkMlMjAlRUIlQTclOEMlRUIlOTMlQTQlMjAlRUMlODglOTglMjAlRUMlOUUlODglRUIlOEYlODQlRUIlQTElOUQlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIybmVnYXRlJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyYW5kJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyb3IlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCVFQyU4NCVCOCUyMCVFQSVCMCU4MCVFQyVBNyU4MCUyMCVFQiVBOSU5NCVFQyU4NCU5QyVFQiU5MyU5QyVFQiVBNSVCQyUyMCVFQyVBMCU5QyVFQSVCMyVCNSVFRCU5NSU5QyVFQiU4QiVBNC4lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjJiNTI2ZTQ2MjFhYjQxZWFiMzFhNWI3OTg2MzBkYzVmJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMTA1MDQxNGNjYWMxNGZkOWI0M2VlNzNjOWVkNzdkNTQlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTIyc3ludGF4JTIyJTNBJTIyamF2YSUyMiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZS1saW5lJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMkYlMkYlMjAlRUIlQjklQTglRUElQjAlODQlRUMlODMlODklRUMlOUQlQjQlRUIlQTklQjQlRUMlODQlOUMlMjAlRUIlQUMlQjQlRUElQjElQjAlRUMlOUElQjQoMTUwJUVBJUI3JUI4JUVCJTlFJUE4JTIwJUVDJTlEJUI0JUVDJTgzJTgxKSUyMCVFQyU4MiVBQyVFQSVCMyVCQyUyMCVFQiU5OCU5MCVFQiU4QSU5NCUyMCVFQSVCNyVCOCVFQiU4MyVBNSUyMCVFQiU4NSVCOSVFQyU4MyU4OSUyMCVFQyU4MiVBQyVFQSVCMyVCQyUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyODUzMDdlOWRlMDgxNGM3N2JiZWI1NzZmZTI1MjY0ZjIlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJiODRlODUxNTQ1MzU0ZTU1OGJmNTQ1NWNiZmNiOTRlNyUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUtbGluZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyUHJlZGljYXRlJTNDQXBwbGUlM0UlMjByZWRBbmRIZWF2eUFwcGxlT3JHcmVlbiUyMCUzRCUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZmVlMjliMGZjMTkzNDZhOWI2YmViNTZkYWVlYmJmZWIlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJhZTdkMjUzM2U2NzI0Yzg4OTg4NWRlNGVlYTlmYTNkZSUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUtbGluZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmVkQXBwbGUuYW5kKGElMjAtJTNFJTIwYS5nZXRXZWlnaHQoKSUyMCUzRSUyMDE1MCklMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmY5Yzg3NTI0NGJmMzQ0NTdhZDJlMDg0MTFlZjFiNDViJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMmIyYWE5MmVlZDY3NDdkYzhhMjc0M2NjZmE4MzQxNjUlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlLWxpbmUlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMC5vcihhJTIwLSUzRSUyMCU1QyUyMmdyZWVuJTVDJTIyLmVxdWFscyhhLmdldENvbG9yKCkpKSUzQiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyYmY4NzJhZTU1YzJjNGQ2Y2JiOTEzMmNkYTdkNjA4OGElMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI3Zjk2YTA0YTY4MzM0MGI5OTJhOTdiMjg4OGUxZWUwNiUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmQ0MGM1YzQ5ZTY2OTQ0ZjY4YmI5OWUzOGE3ZDlhMTQ0JTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyaGVhZGluZy0yJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJGdW5jdGlvbiUyMCVFQyVBMSVCMCVFRCU5NSVBOSUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZTExNDMxZGYxZGUyNDNhYjg3MGIxYzNjYjFlYzM2YWUlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJmNzk3ODAwOGJhYzc0NmQzOTljNWIzY2EyYWIyOWNiOSUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMnBhcmFncmFwaCUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyRnVuY3Rpb24lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCVFQyU5RCVCOCVFRCU4NCVCMCVFRCU4RSU5OCVFQyU5RCVCNCVFQyU4QSVBNCVFQiU4QSU5NCUyMCUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJhbmRUaGVuJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJtYXJrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTdEJTVEJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjIlMkMlMjAlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyY29tcG9zZSUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybWFyayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCU3RCU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJTIwJUVCJTkxJTkwJTIwJUVBJUIwJTgwJUVDJUE3JTgwJTIwJUVCJTk0JTk0JUVEJThGJUI0JUVEJThBJUI4JTIwJUVCJUE5JTk0JUVDJTg0JTlDJUVCJTkzJTlDJUVCJUE1JUJDJTIwJUVDJUEwJTlDJUVBJUIzJUI1JUVEJTk1JTlDJUVCJThCJUE0LiU1Q24lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyYW5kVGhlbiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybWFyayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCU3RCU1RCU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyJTIwJUVCJUE5JTk0JUVDJTg0JTlDJUVCJTkzJTlDJUVCJThBJTk0JTIwJUVDJUEzJUJDJUVDJTk2JUI0JUVDJUE3JTg0JTIwJUVEJTk1JUE4JUVDJTg4JTk4JUVCJUE1JUJDJTIwJUVCJUE4JUJDJUVDJUEwJTgwJTIwJUVDJUEwJTgxJUVDJTlBJUE5JUVEJTk1JTlDJTIwJUVBJUIyJUIwJUVBJUIzJUJDJUVCJUE1JUJDJTIwJUVCJThCJUE0JUVCJUE1JUI4JTIwJUVEJTk1JUE4JUVDJTg4JTk4JUVDJTlEJTk4JTIwJUVDJTlFJTg1JUVCJUEwJUE1JUVDJTlDJUJDJUVCJUExJTlDJTIwJUVDJUEwJTg0JUVCJThCJUFDJUVEJTk1JTk4JUVCJThBJTk0JTIwJUVEJTk1JUE4JUVDJTg4JTk4JUVCJUE1JUJDJTIwJUVCJUIwJTk4JUVEJTk5JTk4JUVEJTk1JTlDJUVCJThCJUE0LiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyNzhjZmY0NmI5MzNhNDgyMWI0NTU0MDJmOWJmOWUxNWIlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJjYjJmZjU4OGNlNGY0OGRhOTBiOWQ2YjQxOWE2ZWVlNCUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlMjJzeW50YXglMjIlM0ElMjJqYXZhJTIyJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlLWxpbmUlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMkZ1bmN0aW9uJTNDSW50ZWdlciUyQyUyMEludGVnZXIlM0UlMjBmJTIwJTNEJTIweCUyMC0lM0UlMjB4JTIwJTJCJTIwMSUzQiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyNGUwZDBiMzgxNGViNGRjM2IxNDYzZTEyMTlkOTBmNzElMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIyNDZjMzJiMWIxYTU0NWNmOTU1ZTRjMjMzNWVkMjViZCUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUtbGluZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyRnVuY3Rpb24lM0NJbnRlZ2VyJTJDJTIwSW50ZWdlciUzRSUyMGclMjAlM0QlMjB4JTIwLSUzRSUyMHglMjAqJTIwMiUzQiUyMiUyQyUyMm1hcmtzJTIyJTNBJTVCJTVEJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMzkyY2VkOTYyYzQ4NGRjNmExZDhkZDIwM2Q2ZDY0ZWIlMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI2MDNhYzJmYzMxMWQ0ZDFiODNiNzY1MGZkZTkwZDBiMiUyMiU3RCUyQyU3QiUyMm9iamVjdCUyMiUzQSUyMmJsb2NrJTIyJTJDJTIydHlwZSUyMiUzQSUyMmNvZGUtbGluZSUyMiUyQyUyMmlzVm9pZCUyMiUzQWZhbHNlJTJDJTIyZGF0YSUyMiUzQSU3QiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIydGV4dCUyMiUyQyUyMmxlYXZlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMmxlYWYlMjIlMkMlMjJ0ZXh0JTIyJTNBJTIyRnVuY3Rpb24lM0NJbnRlZ2VyJTJDJTIwSW50ZWdlciUzRSUyMGglMjAlM0QlMjBmLmFuZFRoZW4oZyklM0IlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmVkOTQwZDA5ZmNlZDQ1ZDY5MTg1NTAzNWQzYTY0MGFkJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyM2E5ZTliMDA1YmZkNGE4Y2EzMTlmYTYzM2NhYWFiNGYlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlLWxpbmUlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMmludCUyMHJlc3VsdCUyMCUzRCUyMGguYXBwbHkoMSklM0IlMjAlMkYlMkYlMjA0JTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJkN2I0NGUyY2ZkMjk0YzMwODY2NThmYTYyZjZmNDM3YiUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmRiMjNjNWY0ZmIzNDRkOGY5ZTJmYjQ3ODNjMjg4NzJjJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMGIyMDliYTg2NjMwNDI3NmJjYjgzMDdmM2M4MGZhN2ElMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJwYXJhZ3JhcGglMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMmNvbXBvc2UlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMm1hcmslMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZSUyMiUyQyUyMmRhdGElMjIlM0ElN0IlN0QlN0QlNUQlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMiUyMCVFQiVBOSU5NCVFQyU4NCU5QyVFQiU5MyU5QyVFQiU4QSU5NCUyMCVFQyU5RCVCOCVFQyU4OCU5OCVFQiVBMSU5QyUyMCVFQyVBMyVCQyVFQyU5NiVCNCVFQyVBNyU4NCUyMCVFRCU5NSVBOCVFQyU4OCU5OCVFQiVBNSVCQyUyMCVFQiVBOCVCQyVFQyVBMCU4MCUyMCVFQyU4QiVBNCVFRCU5NiU4OSVFRCU5NSU5QyUyMCVFQiU4QiVBNCVFQyU5RCU4QyVFQyU5NyU5MCUyMCVFQSVCNyVCOCUyMCVFQSVCMiVCMCVFQSVCMyVCQyVFQiVBNSVCQyUyMCVFQyU5OSVCOCVFQiVCNiU4MCUyMCVFRCU5NSVBOCVFQyU4OCU5OCVFQyU5RCU5OCUyMCVFQyU5RCVCOCVFQyU4OCU5OCVFQiVBMSU5QyUyMCVFQyVBMCU5QyVFQSVCMyVCNSVFRCU5NSU5QyVFQiU4QiVBNC4lMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmY2ZGE4MTcwZjU3ODQ2ZGRiZTg0YzkwYTBkZjUyNmNjJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMThmMDU1ZTAyNWY5NDJiYTljMDExMGZmNDIwNzk3MWIlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTIyc3ludGF4JTIyJTNBJTIyamF2YSUyMiU3RCUyQyUyMm5vZGVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZS1saW5lJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJGdW5jdGlvbiUzQ0ludGVnZXIlMkMlMjBJbnRlZ2VyJTNFJTIwZiUyMCUzRCUyMHglMjAtJTNFJTIweCUyMCUyQiUyMDElM0IlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmMwYTczNzhkM2UwNTQ3NWViMWY3ODA4MWRkMTM0MTkwJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZjRiODQ1NTYzYjlkNGVlYThhYTBmYjA4NjkxNjIwODAlMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlLWxpbmUlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMkZ1bmN0aW9uJTNDSW50ZWdlciUyQyUyMEludGVnZXIlM0UlMjBnJTIwJTNEJTIweCUyMC0lM0UlMjB4JTIwKiUyMDIlM0IlMjIlMkMlMjJtYXJrcyUyMiUzQSU1QiU1RCU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjgzMTFmYTEyOTFkYzQwMTBiZDE2MDc5M2YzZTBjZjJjJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyMWZiNWYzNjY4NThhNDUzNWJkYzIwM2U0Y2RjNWRlNDclMjIlN0QlMkMlN0IlMjJvYmplY3QlMjIlM0ElMjJibG9jayUyMiUyQyUyMnR5cGUlMjIlM0ElMjJjb2RlLWxpbmUlMjIlMkMlMjJpc1ZvaWQlMjIlM0FmYWxzZSUyQyUyMmRhdGElMjIlM0ElN0IlN0QlMkMlMjJub2RlcyUyMiUzQSU1QiU3QiUyMm9iamVjdCUyMiUzQSUyMnRleHQlMjIlMkMlMjJsZWF2ZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJsZWFmJTIyJTJDJTIydGV4dCUyMiUzQSUyMkZ1bmN0aW9uJTNDSW50ZWdlciUyQyUyMEludGVnZXIlM0UlMjBoJTIwJTNEJTIwZi5jb21wb3NlKGcpJTNCJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjIzZjQ0NzMxNTNiYjc0YmVkOThhZGM4MTdlMjIxNDIyMCUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMmM5NmU2NTE4YmYxMDQyYzk4YzEzODUxNjBlMzFiZDIxJTIyJTdEJTJDJTdCJTIyb2JqZWN0JTIyJTNBJTIyYmxvY2slMjIlMkMlMjJ0eXBlJTIyJTNBJTIyY29kZS1saW5lJTIyJTJDJTIyaXNWb2lkJTIyJTNBZmFsc2UlMkMlMjJkYXRhJTIyJTNBJTdCJTdEJTJDJTIybm9kZXMlMjIlM0ElNUIlN0IlMjJvYmplY3QlMjIlM0ElMjJ0ZXh0JTIyJTJDJTIybGVhdmVzJTIyJTNBJTVCJTdCJTIyb2JqZWN0JTIyJTNBJTIybGVhZiUyMiUyQyUyMnRleHQlMjIlM0ElMjJpbnQlMjByZXN1bHQlMjAlM0QlMjBoLmNvbXBvc2UoMSklM0IlMjAlMkYlMkYlMjAzJTIyJTJDJTIybWFya3MlMjIlM0ElNUIlNUQlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjI1NWJmMzFjM2E3NWU0ZWMyOWU1OTRjM2JhY2NlZWMyZSUyMiU3RCU1RCUyQyUyMmtleSUyMiUzQSUyMjg1ZWRlN2JlMzk2ZDQ5ZWU5OGZmMTQ5MTFkNTMyZDBlJTIyJTdEJTVEJTJDJTIya2V5JTIyJTNBJTIyZTgyMmVjZTA5OGI5NDI4N2JmOWM3ODMyYWFhYjc1ZDglMjIlN0QlNUQlMkMlMjJrZXklMjIlM0ElMjJBZU9aU3VlNjJUclUlMjIlN0Q=&quot;&gt;
&lt;div data-rnwr700-1777fci=&quot;true&quot; data-rnwr1490-1777fci=&quot;true&quot;&gt;
&lt;div data-key=&quot;e822ece098b94287bf9c7832aaab75d8&quot;&gt;
&lt;div data-block-content=&quot;e822ece098b94287bf9c7832aaab75d8&quot;&gt;
&lt;div data-rnwi-handle=&quot;codeblock-toolbar&quot; data-rnwi-5xr8s6-dse9kg-1rbj2e8-2fw26j-focus-visible=&quot;true&quot;&gt;
&lt;div data-key=&quot;f4b845563b9d4eea8aa0fb0869162080&quot;&gt;
&lt;pre id=&quot;code_1709302186061&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Function&amp;lt;Integer, Integer&amp;gt; f = x -&amp;gt; x + 1;

Function&amp;lt;Integer, Integer&amp;gt; g = x -&amp;gt; x * 2;

Function&amp;lt;Integer, Integer&amp;gt; h = f.compose(g);

int result = h.compose(1); // 3&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Java &amp;amp; Spring</category>
      <category>람다</category>
      <category>람다란?</category>
      <category>람다표현식</category>
      <author>닥치고개돌</author>
      <guid isPermaLink="true">https://shutcoding.tistory.com/98</guid>
      <comments>https://shutcoding.tistory.com/entry/java8-%EB%9E%8C%EB%8B%A4-%ED%91%9C%ED%98%84%EC%8B%9D#entry98comment</comments>
      <pubDate>Fri, 1 Mar 2024 22:58:11 +0900</pubDate>
    </item>
    <item>
      <title>[TDD한걸음] 1편 Springboot TestAnotation정리</title>
      <link>https://shutcoding.tistory.com/entry/TDD%ED%95%9C%EA%B1%B8%EC%9D%8C-1%ED%8E%B8-Springboot-TestAnotation%EC%A0%95%EB%A6%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;TDD 들어가기 전에 기본적으로 테스트 코드를 작성하기 위한 문법을 알아야 TDD도 가능하다.&lt;br /&gt;먼저 테스트 코드 작성을 돕는 어노테이션들을 알아보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Boot는 기본적으로 웬만한 테스트 라이브러리들을 한데 뭉쳐놓은 테스트 스타터를 제공한다. (spring-boot-starter-test)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 기본적으로 자주 사용되는 어노테이션들을 살펴보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;@SpringBootTest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@WebMvcTest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@DataJpaTest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@RestClientTest&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@JsonTest&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;@SpringBootTest&lt;/h2&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;code&gt;@SpringBootTest&lt;/code&gt;는 &lt;b&gt;통합 테스트를 제공&lt;/b&gt;하는 기본적인 스프링부트 테스트 어노테이션이다.&lt;br /&gt;애플리케이션이 실행될 때의 설정을 임의로 바꾸어 테스트를 진행할 수 있으며 여러 단위 테스트를 하나의 통합된 테스트로 수행할 때 적합하다. Spring Boot 프로젝트를 만들면 메인 클레스와 함께 기본으로 제공된다.&lt;br /&gt;&lt;code&gt;@SpringBootTest&lt;/code&gt;는 만능이라 할 수 있는데, &lt;b&gt;실제 구동되는 애플리케이션과 똑같이 ApplicationContext를 로드하여 테스트하기 때문에 하고 싶은 테스트를 모두 수행할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단, 애플리케이션에 설정된 빈을 모두 로드하기 때문에 애플리케이션의 규모가 클수록 느려진다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootTestApplicationTests {

    @Test
    public void contextLoads() {
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 클래스를 실행하면 애플리케이션 컨텍스트를 로드하여 스프링 부트 테스트를 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;@RunWith&lt;/code&gt; 어노테이션을 사용하면 JUnit에 내장된 러너를 사용하는 대신 어노테이션에 정의된 러너 클래스를 사용한다. &lt;code&gt;@SpringBootTest&lt;/code&gt; 어노테이션을 사용하려면 JUnit 실행에 필요한 &lt;code&gt;SpringJUnit4ClassRunner&lt;/code&gt; 클래스를 상속받은 &lt;code&gt;@RunWith(SpringRunner.class)&lt;/code&gt;를 꼭 붙여서 사용해야 한다. 그렇지 않으면 정상적으로 동작하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JUnit5부터는 @ExtendWIth(SpringExtension.class) 이렇게 사용!&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@ActiveProfiles(&quot;test&quot;) : 프로파일 환경(개발, QA, 운영 환경)마다 다른 데이터소스(DataSource)를 갖는다면, &lt;b&gt;&lt;code&gt;@ActiveProfiles(&quot;test&quot;)&lt;/code&gt;과 같은 방식으로 원하는 프로파일 환경값을 부여&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;@Transactional 을 사용하면 테스트를 마치고 나서 수정된 &lt;b&gt;데이터가 롤백된다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;@SpringBootTest는 기본적으로 검색 알고리즘을 사용하여 &lt;code&gt;@SpringBootApplication&lt;/code&gt;이나 &lt;code&gt;@SpringBootConfiguration&lt;/code&gt; 어노테이션을 찾는다. 스프링 부트 테스트이기 때문에 해당 어노테이션 중 하나는 필수&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;@DataJpaTest&lt;/h2&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;code&gt;@DataJpaTest&lt;/code&gt; 어노테이션은 JPA 관련 테스트 설정만 로드한다.&lt;br /&gt;데이터소스의 설정이 정상적인지, JPA를 사용하여 데이터를 제대로 생성, 수정, 삭제하는지 등의 테스트가 가능하다. 또한 내장형 DB를 사용하여 실제 데이터베이스를 사용하지 않고 테스트 데이터베이스로 테스트할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;@DataJpaTest&lt;/code&gt;는 기본적으로 인메모리 임베디드 데이터베이스를 사용하며, &lt;code&gt;@Entity&lt;/code&gt; 클래스를 스캔하여 스프링 데이터 JPA 저장소를 구성한다. 만약, 최적화한 별도의 데이터소스를 사용하여 테스트하고 싶다면 기본 설정된 데이터소스를 사용하지 않도록 다음과 같이 설정한다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@RunWith(SpringRunner.class)
@DataJpaTest
@ActiveProfiles(&quot;...&quot;) // &amp;larr; 여기에 주목
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class JpaTest {
    // ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;@AutoConfigureTestDatabase&lt;/code&gt; 어노테이션의 기본 설정값인 &lt;code&gt;Replace.Any&lt;/code&gt;를 사용하면 기본적으로 내장된 데이터소스를 사용한다. 위와 같이 &lt;code&gt;Replace.NONE&lt;/code&gt;으로 설정하면 &lt;code&gt;@ActiveProfiles&lt;/code&gt;에 설정한 프로파일 환경값에 따라 데이터소스가 적용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 자동 설정 방식을 이용해 설정할 수도 있다. application.yml에서 프로퍼티 설정을 &lt;code&gt;spring.test.database.replace: NONE&lt;/code&gt;으로 변경하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;@DataJpaTest&lt;/code&gt;는 &lt;b&gt;JPA 테스트가 끝날 때마다 자동으로 테스트에 사용한 데이터를 롤백한다.&lt;/b&gt; 또한 어떤 테스트 데이터베이스를 사용할 것인지도 선택할 수 있다. &lt;code&gt;spring.test.database.connection: H2&lt;/code&gt;와 같이 프로퍼티를 설정하는 방법과, &lt;code&gt;@AutoConfigureTestDatabase(connection = H2)&lt;/code&gt; 어노테이션으로 설정하는 방법이 있다. connection의 옵션으로 H2, Derby, HSQL 등의 테스트 데이터베이스 종류를 선택할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 &lt;code&gt;@DataJpaTest&lt;/code&gt;에서 &lt;code&gt;EntityManager&lt;/code&gt;의 대체제로 만들어진 테스트용 &lt;code&gt;TestEntityManager&lt;/code&gt;를 사용하면 &lt;code&gt;persist&lt;/code&gt;, &lt;code&gt;flush&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt; 등과 같은 기본적인 JPA 테스트를 할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@RunWith(SpringRunner.class)
@DataJpaTest
public class BoardJpaTest {

    @Autowired
    private TestEntityManager boardTestEntityManager;

    @Autowired
    private BoardRepository boardRepository;

    @Test
    void Board_save_and_delete_test() {
        Board board1 = Board.builder()
                        .title(&quot;제목&quot;)
                        .createdAt(LocalDateTime.now()).build();
        boardTestEntityManager.persist(board1);

        Board board2 = Board.builder()
                        .title(&quot;제목2&quot;)
                        .createdAt(LocalDateTime.now()).build();
        boardTestEntityManager.persist(board2);

        boardRepository.deleteAll();
        assertThat(boardRepository.findAll(), IsEmptyCollection.empty());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제처럼 boardRepository의 deleteAll을 테스트하고싶을경우 save에 의존하지않고 저장된 Board객체가 두개 다 삭제 됐는지 테스트할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;@RestClientTest&lt;/h2&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;code&gt;@RestClientTest&lt;/code&gt;는 REST 관련 테스트를 도와주는 어노테이션이다. REST 통신의 데이터형으로 사용되는 JSON 형식이 예상대로 응답을 반환하는지 등을 테스트할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;@JsonTest&lt;/h2&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;code&gt;@JsonTest&lt;/code&gt;는 JSON 테스트를 지원하는 어노테이션이다. JSON의 직렬화와 역직렬화를 수행하는 라이브러리인 Gson과 Jackson API의 테스트를 제공한다. 각각 &lt;code&gt;GsonTester&lt;/code&gt;와 &lt;code&gt;JacksonTester&lt;/code&gt;를 사용하여 테스트를 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSON 테스트는 크게 두 가지로 나뉜다. 문자열로 나열된 JSON 데이터를 객체로 변환하여 변환된 객체값을 테스트하거나 그 반대의 경우이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;@RunWith vs @ExtendWith&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 어노테이션들은 JUnit Test를 Spring TestContext Framework와 결합하는 것이다. JUnit 버전에 따라 다음과 같이 사용해야 한다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;// JUnit4
@RunWith(SpringRunner.class)

// JUnit5
@ExtendWIth(SpringExtension.class)&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;추가조사&lt;/h2&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;@ContextConfiguration&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@EnableAutoConfiguration&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@AutoConfigureRestDocs&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@AutoConfigureMockMvc&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@Mock&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@Spy&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@MockBean&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@Bean&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@InjectMocks&lt;br /&gt;@Autowired&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@Nested&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@Captor&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@BeforeEach&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@AfterEach&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@ParameterizedTest&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@ValueSource&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@TestConfiguration&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>TDD한걸음</category>
      <category>TDD</category>
      <category>TDD하는법</category>
      <category>테스트 어노테이션</category>
      <category>테스트코드 작성 방법</category>
      <author>닥치고개돌</author>
      <guid isPermaLink="true">https://shutcoding.tistory.com/97</guid>
      <comments>https://shutcoding.tistory.com/entry/TDD%ED%95%9C%EA%B1%B8%EC%9D%8C-1%ED%8E%B8-Springboot-TestAnotation%EC%A0%95%EB%A6%AC#entry97comment</comments>
      <pubDate>Tue, 20 Feb 2024 19:52:13 +0900</pubDate>
    </item>
    <item>
      <title>msa란? msa 고도화</title>
      <link>https://shutcoding.tistory.com/entry/msa%EB%9E%80-msa-%EA%B3%A0%EB%8F%84%ED%99%94-%EC%9E%91%EC%84%B1%EC%A4%91</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;msa 개념&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MicroService Architecture(MSA)는 loosely coupled를 기반으로 여러 개의 작은 서비스로 구성되어 각 서비스가 독립적으로 개발되고 빠른 배포주기, 폴리그랏 프로그래밍, 관심사의 집중 등의 장점을 발휘해 Enterprise IT에서 가장 주목받고 있는 아키텍처이다.&lt;/li&gt;
&lt;li&gt;폴리그랏 프로그래밍 : 단일 언어로 제공되지 않는 추가 기능과 효율성을 극대화 하기 위해 여러 언어로 코드를 작성하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;msa 장점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MSA를 도입하여 느슨한 결합, 관심사의 집중, 단일 책임 원칙, 빠른 배포주기, 폴리그랏, Scalability, 장애의 격리, 유연성, 확장성 등 여러 이점&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;msa 단점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Shared 관계형 데이터베이스 장점 사용 불가
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터를 효율적으로 보관하고 조회/삭제 등 기능의 효율을 높이는 장점&lt;/li&gt;
&lt;li&gt;테이블 조인을 통한 통합 뷰 제공&lt;/li&gt;
&lt;li&gt;ACID 원칙에 따른 트랜잭션 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;서비스가 뭉쳐져 있을 때 발휘되던 장점을 활용하지 못함&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;현재 서비스의 단점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글을 쓰는 이유이자 공유의 목적이다.&lt;br /&gt;현재 서비스가 msa 구조로 나뉘어 질 때 같이 개발하지 않았지만, 인수인계도 없이 현재 서비스를 맡았을 때 이해가지 않거나, 아쉽게 구현된 msa환경의 불편함을 공유하여 같은 실수를 겪지 않았으면 한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&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;Monolithic한 구조에서 MSA로 가기위해선 서비스를 어떻게 분리할 것인지 기준이 있어야한다.&lt;/li&gt;
&lt;li&gt;대표적으로 비즈니스 구조를 기반으로 분리, 도메인간의 결합도, 응집도에 따라 분리&lt;/li&gt;
&lt;li&gt;비즈니스 구조를 기반으로 분리한다면 현재 대상 서비스가 세금계산서 하나여서 분리하기 어려움&lt;/li&gt;
&lt;li&gt;도메인간 결함도,응집도에 따라 분리해야 하는데, 이게 분리돼야하는 서비스인가?하는 부분까지 별도의 api로 분리돼있음 예를들어 유니크한 문서번호만을 생성하는 api가 있다. 왜 32자리의 대,소문자+숫자 조합의 유니크한 값을 별도의 서비스가 생성해야하는거지?&lt;/li&gt;
&lt;li&gt;문서 번호생성은 결국 문서생성 api와 결합도가 생길 것이고 이러한 작은 기능까지 별도의 서비스로 분리하여 관리 할 api가 많아지면 개발복잡도 증가는 물론, 패킷유실, 트랜잭션처리 등 msa의 단점만 커지는것 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Database Per Service가 지켜지지 않음&lt;br /&gt;msa의 목적은 결국 응집력은 높이고 결합도를 낮춰 서비스를 독립적으로 개발,배포 및 확장시키고 서비스간 유기적인 통신을 하는것이다. 하지만 현재 구조는 Database하나를 여러 서비스가 참조하고, 하나의 서비스가 여러 데이터베이를 참조하는 강결합을 보여주고있다. &lt;br /&gt;서비스가 나눠져있으니 상관없는게 아니냐?라고 생각할 수 있지만 이런 형태는 우선 트랜잭션 처리를 어렵게한다. 트랜잭션은 결국 데이터베이스에서 관장하는데 하나의 요청에 서로 다른 데이터베이스가 변경돼야하면 트랜잭션처리는 할수 없다.(보상 트랜잭션이 있지만... 결국 서비스단에서의 추가 요청이고, 보상트랜잭션이 실패한다면..?) &lt;br /&gt;또한 데이터베이스의 컬럼추가나 서비스의 변경으로 데이터베이스가 변경되면 관련 서비스들도 전부 개발 및 배포가 이루어 져야한다. 관리 repo가 많아지면 결국 이 DB가 어느 api를 보고있는지, 어디를 고쳐야하는지 찾기힘들어지고 버그 포인트만 늘어나게된다. 이는 결국&lt;b&gt; 비싸고 유실많은 TCP통신을 하며, 코드 검색 및 관리하기도 힘든 api들로 이루어진 초 거대 Monolithic 구조로 개발하는것&lt;/b&gt;이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D8CPF/btsEHGhhZJF/wtY4pZaUmgkgzKhsnJZMN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D8CPF/btsEHGhhZJF/wtY4pZaUmgkgzKhsnJZMN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D8CPF/btsEHGhhZJF/wtY4pZaUmgkgzKhsnJZMN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD8CPF%2FbtsEHGhhZJF%2FwtY4pZaUmgkgzKhsnJZMN0%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;1204&quot; height=&quot;456&quot; data-origin-width=&quot;1204&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;MSA 단점 보완(Event Driven MicroService 란?)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 msa의 단점이 극대화 된 경우 이를 보완하는 다양한 방법으로 EDM을 추천하곤한다.&lt;br /&gt;EDM이란? MSA가 적용된 시스템에서 이벤트 발생시 해당 이벤트 로그를 보관하고 이를 기반으로 동작하며, 비동기 통신을 통해 시스템 내 통합(integration)을 수행하는 Architecture이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;EDM의 특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이벤트 : 상태의 변경. 즉, 데이터의 변경,생성,삭제(CUD)를 통해 발생하는 서비스의 의미있는 변화&lt;/li&gt;
&lt;li&gt;비동기 통신 : amqp, mqtt, jms 등 메세징 프로토콜을 통한 메세지 큐 방식이 자주 사용, 서비스에서 데이터의 생성,변경,삭제(CUD)를 통해 이벤트가 발생하면 발행 서비스는 메세지의 형태로 이벤트를 발행하고, 해당 이벤트에 관심이 있는 서비스에서 구독을 수행&lt;/li&gt;
&lt;li&gt;시스템 내 통합(integration) : Database Per Service를 적용하면 Shared Database 구성의 DBMS 레벨에서 제공하던 기능을 Application 레벨에서 해결해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;EDM의 효과&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비즈니스 흐름에 따른 로직 수행&lt;/li&gt;
&lt;li&gt;분산 트랜잭션 처리&lt;/li&gt;
&lt;li&gt;서비스 간 반정규화 데이터 동기 처리&lt;/li&gt;
&lt;li&gt;적절한 시스템 내 통합&lt;/li&gt;
&lt;li&gt;최종적인 일관성&lt;/li&gt;
&lt;li&gt;동기 통신비용의 절감&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고 :&amp;nbsp;&lt;a href=&quot;https://medium.com/dtevangelist/event-driven-microservice-%EB%9E%80-54b4eaf7cc4a&quot;&gt;https://medium.com/dtevangelist/event-driven-microservice-%EB%9E%80-54b4eaf7cc4a&lt;/a&gt;&lt;/p&gt;</description>
      <category>분석설계고민</category>
      <author>닥치고개돌</author>
      <guid isPermaLink="true">https://shutcoding.tistory.com/95</guid>
      <comments>https://shutcoding.tistory.com/entry/msa%EB%9E%80-msa-%EA%B3%A0%EB%8F%84%ED%99%94-%EC%9E%91%EC%84%B1%EC%A4%91#entry95comment</comments>
      <pubDate>Sun, 4 Feb 2024 21:54:19 +0900</pubDate>
    </item>
    <item>
      <title>각종 타임아웃(timeout)설명과 설정 팁</title>
      <link>https://shutcoding.tistory.com/entry/%EA%B0%81%EC%A2%85-%ED%83%80%EC%9E%84%EC%95%84%EC%9B%83timeout%EC%84%A4%EB%AA%85%EA%B3%BC-%EC%84%A4%EC%A0%95-%ED%8C%81</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Connection Timeout&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트가 서버측으로 connection을 맺길 원하지만 서버의 장애 상황으로 connection조차 맺어지지 못할 때 발생하는 timeout이다.&lt;/li&gt;
&lt;li&gt;우리가 흔히 알고있는 TCP 3 way handshake를 통해 TCP 연결이 생성되지 못한것을 의미함.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Read Timeout&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트와 서버가 connection을 맺으면 하나의 데이터 덩어리가 아닌 여러개의 패킷으로 나눠서 전송하게 되는데, I/O작업이 길어지거나 락이 걸려 요청이 처리되지 못하고 있을 때 클라이언트는 더 이상 기다리지 못하고 커넥션을 끊는다. 즉, 응답을 기다리지 못하는 것이다. 이런 상황을 Read Timeout 이라고 하는데 java에서는 SocketTimeout Exception이 떨어진다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-02-04 오후 5.38.36.png&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2LDu6/btsEmDeJch0/aCAL0GKkWztv6v7eHoHwpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2LDu6/btsEmDeJch0/aCAL0GKkWztv6v7eHoHwpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2LDu6/btsEmDeJch0/aCAL0GKkWztv6v7eHoHwpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2LDu6%2FbtsEmDeJch0%2FaCAL0GKkWztv6v7eHoHwpk%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;584&quot; height=&quot;318&quot; data-filename=&quot;스크린샷 2024-02-04 오후 5.38.36.png&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;java에서의 Connection, Socket/Read timeout과 관련된 예외&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;java.net.SocketException&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: Thrown to indicate that there is an error creating or accessing a Socket. &amp;rarr; connection timeout&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;java.net.SocketTimeoutException : Signals that a timeout has occurred on a socket read or accept. &amp;rarr; socket timeout, read timeout&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;Write Timeout&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트가 서버로 패킷을 보낼 수 있는 timeout을 설정할 수 있다. 클라이언트와 서버가 connection은 맺어졌지만 설정된 timeout의 값 보다 데이터를 보내는(요청) 시간이 길어지면 Write Timeout이 발생하여 Exception이 떨어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Statement Timeout&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크 연결 장애에 대한 timeout을 담당하는 것이 아니다.&lt;/li&gt;
&lt;li&gt;Statement 하나가 얼마나 오래 수행되어도 괜찮은지에 대한 한계 값이다. JDBC API인 Statement에 타임아웃 값을 설정하며, 이 값을 바탕으로 JDBC 드라이버가 StatementTimeout을 처리한다. JDBC API인 java.sql.Statement.setQueryTimeout(int timeout) 메서드로 설정한다.&lt;/li&gt;
&lt;li&gt;네트워크 장애에 대비하는 타임아웃은 JDBC Driver SoecketTimeout이 처리해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;Transaction Timeout&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;간단히 설명하면 &quot;StatementTimeout x N(Statement 수행 수) + &amp;alpha;(가비지 컬렉션 및 기타)&quot;라고 할 수 있다. 전체 Statement 수행 시간을 허용할 수 있는 최대 시간 이내로 제한하려 할 때 TransactionTimeout을 사용한다.&lt;/li&gt;
&lt;li&gt;Statement 한 개를 수행할 때 0.1초가 필요하다면, 몇 개 안 되는 Statement를 수행할 때에는 문제가 없다. 그러나 Statement 10만 개를 수행할 때에는 일만 초(약 7시간)가 필요하다. TransactionTimeout은 이런 경우에 사용할 수 있다.&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;JDBC Driver&amp;rsquo;s SocketTimeout&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JDBC Driver Type4는 소켓을 사용하여 DBMS에 연결하는 방식이고, 애플리케이션과 DBMS 사이의 ConnectTimeout 처리는 DBMS에서 하지 않는다.&lt;/li&gt;
&lt;li&gt;JDBC 드라이버의 SocketTimeout 값은 DBMS가 비정상으로 종료되었거나 네트워크 장애(기기 장애 등)가 발생했을 때 필요한 값이다. TCP/IP의 구조상 소켓에는 네트워크의 장애를 감지할 수 있는 방법이 없다. 그렇기 때문에 애플리케이션은 DBMS와의 연결 끊김을 알 수 없다. 이럴 때 SocketTimeout이 설정되어 있지 않다면 애플리케이션은 DBMS로부터의 결과를 무한정 기다릴 수도 있다(이러한 Connection을 Dead Connection이라고 부르기도 한다). 이러한 상태를 방지하기 위해 소켓에 타임아웃을 설정해야 한다. SocketTimeout은 JDBC 드라이버에서 설정할 수 있다. SocketTimeout을 설정하면 네트워크 장애 발생 시 무한 대기 상황을 방지하여 장애 시간을 단축할 수 있다.&lt;/li&gt;
&lt;li&gt;SocketTimeout 값을 Statement의 수행 시간 제한을 위해 사용하는 것은 바람직하지 않다. 그러므로 SocketTimeout 값은 StatementTimeout 값보다는 크게 설정해야 한다. SocketTimeout값이 StatementTimeout보다 작으면, SocketTimeout이 먼저 동작하므로 StatementTimeout 값은 의미가 없게 되어 동작하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SocketTimeout에는 아래 두 가지 옵션이 있고, 드라이버별로 설정 방법이 다르다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Socket Connect 시 타임아웃(connectTimeout): Socket.connect(SocketAddress endpoint, int timeout) 메서드를 위한 제한 시간&lt;/li&gt;
&lt;li&gt;Socket Read/Write의 타임아웃(socketTimeout): Socket.setSoTimeout(int timeout) 메서드를 위한 제한 시간&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OS level socket timeout 설정&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SocketTimeout이나 ConnectTimeout을 설정하지 않으면 네트워크 장애가 발생해도 애플리케이션이 대부분 이를 감지할 수 없다. 따라서 연결이 되거나 데이터를 읽을 수 있을 때까지 애플리케이션이 무한정 기다리게 된다. 그러나 서비스에서 발생한 실재 장애 상황에서는 30분 후에 애플리케이션(WAS)이 재연결을 시도하여 문제가 해결되는 경우가 많다. OS에서도 SocketTimeout 시간을 설정할 수 있기 때문이다. 해당 설정 값을 통해 OS 레벨에서 네트워크 연결 끊김을 확인하는 것이다. 만약 리눅스 서버의 KeepAlive 체크 수행 주기가 30분이면 SocketTimeout 설정을 0으로 해도 네트워크 장애로 인한 DBMS 연결 장애 지속 시간이 30분을 넘지 않는 것이다. Linux 서버에서 KeepAlive 체크 수행 주기는 tcp_keepalive_time로 조정할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TCP Retransmission&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실상 TCP 이야기가 나오면 항상 메인 토픽으로 다뤄지는 이야기가 있다. 바로 재전송 (Retransmission)에 관한 내용이다. TCP는 송신에 대한 응답이 오지않는 경우 일정시간을 대기 후에 다시 재전송을 한다. TCP Protocol 자체가 전송에 관한 Protocol이고 그 특성으로 Reliability를 갖고 있는 만큼 재전송에 대한 이야깃거리가 상당히 많다. 그중 대표적인 두가지가 &lt;b&gt;RTO&lt;/b&gt;와 &lt;b&gt;RTT&lt;/b&gt; 이다. &lt;b&gt;RTO&lt;/b&gt;는 &lt;b&gt;Retransmission Timeout&lt;/b&gt; 을 뜻하는 말로 타이머가 작동하는 시간을 의미, &lt;b&gt;RTT&lt;/b&gt;는 &lt;b&gt;Round Trip Time을&lt;/b&gt; 뜻하는 말로 네트워크 통신을 하는 두 노드 간에 패킷이 전달되는데 소요된 시간을 의미한다.&lt;br /&gt;TCP Handshake를 하기 위한 첫 번째 SYN 패킷은 상대방과의 RTT에 대한 정보가 전혀 없기 때문에 &lt;b&gt;InitRTO&lt;/b&gt;라고 부르는 값을 사용하고 OS 마다 값이 조금씩 다르지만, Linux에서는 1초로 되어 있다. 1초 --&amp;gt; 2초 --&amp;gt; 4초 이런 식으로 InitRTO 값은 2의 제곱수로 늘어남. 따라서 애플리케이션에서는 timeout 설정 시 최소 1초 이상을 설정 해야 함.(커넥션 풀 방식으로 네트워크 세션을 미리 만들어 두고 통신하는 경우에는 InitRTO가 발생할 일이 없기 때문에 더 작은 값으로 설정해도 무방함.)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Timeout 설정 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 설명한 것처럼 InitRTO의 경우는 1초로 설정되어 있기 때문에 애플리케이션의 타임아웃은 1초보다 큰 값으로 설정해야 한다. 이미 맺어진 세션에서의 재전송은 RTT를 기반으로 생성되기 때문에 대부분 1초를 넘기지 않겠지만, TCP Handshake를 맺는 과정에서의 재전송은 최소 1초는 소요되기 때문에 애플리케이션에서 타임아웃을 1초로 설정한다면 재전송으로 커버 가능한 통신을 타임아웃 에러로 끊어 버릴 수 있음.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이상적인 Connection Timeout&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 커넥션 타임아웃은 &lt;b&gt;3초&lt;/b&gt; 로 한번정도 애플리케이션 단에서 재전송 하는게 이상적이고 그 이상은 서버 문제가 있지 않은지 확인해야함.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-02-04 오후 5.42.45.png&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NeOPe/btsEmRQ34LW/a0ihwuTvnYlKpxkcKiwFB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NeOPe/btsEmRQ34LW/a0ihwuTvnYlKpxkcKiwFB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NeOPe/btsEmRQ34LW/a0ihwuTvnYlKpxkcKiwFB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNeOPe%2FbtsEmRQ34LW%2Fa0ihwuTvnYlKpxkcKiwFB0%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;576&quot; height=&quot;239&quot; data-filename=&quot;스크린샷 2024-02-04 오후 5.42.45.png&quot; data-origin-width=&quot;1394&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이상적인 Read Timeout&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Read Timeout에 영향을 주는 패킷 재전송을 위한 타임아웃 값인 RTO가 RTT를 기준으로 만들어져서 보통 1초보다 짧기 때문에 RTO의 최소값은 200ms + 상대 서버의 프로세스 처리 시간이 가장 이상적인 값&lt;br /&gt;단순 조회의 경우 짧게 가져가고, 복잡한 로직의경우 프로세스 시간을 여유있게주는게 좋음.&lt;br /&gt;하지만 이도 로드밸런서나 서버단의 idle timeout을 넘지 않도록 설정해야한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재전송은 TCP 메커니즘에 의해서 반드시 발생할 수밖에 없다.&lt;br /&gt;TCP 통신 장애가 일어나지 않게 기도하는 것이 중요한 게 아니고, 재전송이 빨리 일어날 수 있도록 해주는 것이 중요하다.&lt;/p&gt;</description>
      <category>네트워크</category>
      <author>닥치고개돌</author>
      <guid isPermaLink="true">https://shutcoding.tistory.com/94</guid>
      <comments>https://shutcoding.tistory.com/entry/%EA%B0%81%EC%A2%85-%ED%83%80%EC%9E%84%EC%95%84%EC%9B%83timeout%EC%84%A4%EB%AA%85%EA%B3%BC-%EC%84%A4%EC%A0%95-%ED%8C%81#entry94comment</comments>
      <pubDate>Sun, 4 Feb 2024 17:37:35 +0900</pubDate>
    </item>
    <item>
      <title>인덱스(index)란? 인덱스 알고쓰기!</title>
      <link>https://shutcoding.tistory.com/entry/%EC%9D%B8%EB%8D%B1%EC%8A%A4index%EB%9E%80-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EC%95%8C%EA%B3%A0%EC%93%B0%EA%B8%B0</link>
      <description>&lt;h2 id=&quot;인덱스의_개념&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;인덱스란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스란 데이터의 저장(INSERT, UPDATE, DELETE) 의 성능을 희생하고 그 대신에 데이터의 읽기 속도를 높이는 테이블의&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;동작속도(조회)를 높여주는 자료구조&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이다.&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;따라서 사이트의 성능개선의 가장 기본은 효율적인 인덱스 설정이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스를 사용하는 SQL을 만들어 효율적으로 사용한다면 매우 빠른 응답 속도를 얻을 수 있고, 쿼리의 부하가 줄어들기 때문에 시스템 전체 성능이 향상되는 효과를 얻는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나&amp;nbsp;인덱스&amp;nbsp;자체&amp;nbsp;역시&amp;nbsp;하나의&amp;nbsp;데이터&amp;nbsp;덩어리&amp;nbsp;이기&amp;nbsp;때문에,&amp;nbsp;데이터베이스에&amp;nbsp;전체&amp;nbsp;크기의&amp;nbsp;10%나&amp;nbsp;되는&amp;nbsp;추가적인&amp;nbsp;공간을&amp;nbsp;할당해줘야&amp;nbsp;하고,&amp;nbsp;잘못&amp;nbsp;사용할&amp;nbsp;경우&amp;nbsp;성능이&amp;nbsp;오히려&amp;nbsp;크게&amp;nbsp;떨어질&amp;nbsp;수&amp;nbsp;있다는&amp;nbsp;단점이&amp;nbsp;있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;(ex.&amp;nbsp;변경&amp;nbsp;작업이&amp;nbsp;자주&amp;nbsp;일어나는&amp;nbsp;경우,&amp;nbsp;인덱스가&amp;nbsp;적절하지&amp;nbsp;않은&amp;nbsp;경우)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;인덱스_알고리즘_종류&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;인덱스 저장방식 (알고리즘)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 저장 방식별로 구분하는 것은 사실 상당히 많은 분류가 가능하겠지만, 가장 보편적인 방식은 B-Tree 방식 알고리즘을 다루겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스는 B-tree구조를 사용하며 데이터가 정렬된 상태를 유지한다. 때문에 어떤 값에 대해서도 같은 시간에 결과를 얻을 수 있게 된다 (트리의 높이가 다른 경우 약간의 차이는 있을 수 있지만 &lt;b&gt;O(logN)&lt;/b&gt;의 시간을 가진다).&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;인덱스_타입_종류&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;인덱스 타입 종류&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;인덱스의 타입은 크게 두가지로 나뉘는데 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Primary(클러스터) 인덱스&lt;/b&gt;&lt;/span&gt; 와 &lt;span style=&quot;color: #6164c6;&quot;&gt;&lt;b&gt;Secondary(보조) 인덱스&lt;/b&gt;&lt;/span&gt;로 나뉘어 진다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;클러스터&amp;nbsp;인덱스는&amp;nbsp;처음부터&amp;nbsp;정렬이&amp;nbsp;되어있는&amp;nbsp;영어&amp;nbsp;사전&amp;nbsp;과&amp;nbsp;같은&amp;nbsp;개념이고,&amp;nbsp;보조&amp;nbsp;인덱스는&amp;nbsp;책&amp;nbsp;뒤의&amp;nbsp;찾아보기&amp;nbsp;의&amp;nbsp;개념과&amp;nbsp;비슷하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;클러스터_인덱스_primary_index&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;클러스터 인덱스 &lt;b&gt;(Primary Index)&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;클러스터형 인덱스는&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;테이블 전체가 정렬된 인덱스가 되는 방식&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;그래서 클러스터형 인덱스 생성 시에는 데이터 페이지 전체가 다시 정렬된다.&lt;/li&gt;
&lt;li&gt;하지만 이러한 정렬 특징 때문에, 이미 대용량의 데이터가 입력된 상태라면 클러스터형 인덱스 생성은 심각한 시스템 &lt;span style=&quot;color: #ee2323;&quot;&gt;부하&lt;/span&gt;를 줄 수 있다.&lt;/li&gt;
&lt;li&gt;한개의 테이블당&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;한개만&lt;/span&gt; 만들 수 있다. 특정 컬럼을 PK로 지정하면 클러스터형 인덱스를 생성, 혹은 Unique + Not null로 지정해도 클러스터형 인덱스를 생성, PK가 우선으로 선정됨&lt;/li&gt;
&lt;li&gt;본래 인덱스는 생성 시 데이터들의 배열정보를 따로 저장하는 공간을 사용하나, 클러스터 인덱스는 따로 저장하는 정보 &lt;span style=&quot;color: #ee2323;&quot;&gt;공간을 적게 사용&lt;/span&gt;하면서 테이블 공간 자체를 활용한다.&lt;/li&gt;
&lt;li&gt;인덱스 자체의 리프 페이지가 곧 데이터이기 때문에 인덱스 자체에 데이터가 포함되어있다고 볼 수 있다.&lt;/li&gt;
&lt;li&gt;보조 인덱스 보다 &lt;span style=&quot;color: #ee2323;&quot;&gt;검색 속도는 더 빠르지만 &lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;입력/수정/삭제는 더 느리다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;MySQL에서는 Primary Key가 있다면 Primary Key를 Clustered INDEX로, 없다면 UNIQUE 하면서 NOT NULL인 컬럼을, 그것도 없으면 임의로 보이지않는 컬럼을 만들어 Clustered Index로 지정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;보조_인덱스_secondary_index&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;논 클러스터형 인덱스 (Non-Clustered Index)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 인덱스는 &lt;span style=&quot;color: #ee2323;&quot;&gt;보조 인덱스 (Secondary index)&lt;/span&gt; 라고도 불린다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;별도의 페이지에서 인덱스를 구성하니, 클러스터와는 달리 자동 정렬을 하지 않는다.&lt;/li&gt;
&lt;li&gt;개념적으로는 후보키에만 부여 할 수 있는 인덱스다. &lt;br /&gt;(후보키 : 고유 식별 번호, 주민번호 같이 각 데이터를 인식할 수 있는 최소한의 고유 식별 속성 집합)&lt;/li&gt;
&lt;li&gt;보조 인덱스의 생성시에는 데이터 페이지는 그냥 둔 상태에서 &lt;span style=&quot;color: #ee2323;&quot;&gt;별도의 페이지&lt;/span&gt;에 인덱스를 구성하여 실제 데이터를 가지고 있지 않다.&lt;/li&gt;
&lt;li&gt;클러스터형 보다 검색 속도는 더 느리지만 데이터의 입력/수정/삭제는 덜 느리고 &lt;span style=&quot;color: #ee2323;&quot;&gt;여러 개 생성&lt;/span&gt;할 수 있지만 많을수록 오히려 성능을 떨어뜨릴 수 있다. (테이블당 3~4개 권장)&lt;/li&gt;
&lt;li&gt;각 데이터에 대해서 고유 값 (unique) 들이 있는 목록에 생성 할 수 있는 인덱스다. (unique key)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;인덱스_설계_핵심_tip&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;인덱스 설계 핵심 TIP&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스의 원리를 알았으니 실전으로 인덱스를 효율적으로 사용하는 설계의 핵심을 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;효율적인_인덱스_설계&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;효율적인 인덱스 설계&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;WHERE 절에 사용되는 열 &lt;/span&gt;&lt;/span&gt;(WHERE 절에 사용되는 열이라도&amp;nbsp;자주 사용해야 가치가 있음)&lt;/li&gt;
&lt;li&gt;중복도가 낮은 컬럼에 INDEX를 설정해야 한다&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;SELECT 절에 자주 등장하는 컬럼&lt;/span&gt;들을 잘 조합해서 INDEX로 만들어두면 INDEX 조회 후 다시 데이터에서 조회할 필요가 없으므로 빠르게 검색이 가능하다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;JOIN절에 자주 사용되는 열&lt;/span&gt;에는 인덱스의 효율이 좋음.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;ORDER BY 절에 사용되는 열&lt;/span&gt;은 데이터 페이지가 자동 정렬됐기 때문에 &lt;span style=&quot;color: #ee2323;&quot;&gt;클러스터형 인덱스&lt;/span&gt;가 유리&lt;/li&gt;
&lt;li&gt;외래키는 자동으로 INDEX가 걸린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;금지해야_할_인덱스_설계&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;금지해야 할 인덱스 설계&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;조회보다 대용량 &lt;span style=&quot;color: #ee2323;&quot;&gt;데이터가 자주 입력&lt;/span&gt;되는 경우,&lt;br /&gt;클러스터형 INDEX 경우 빈번한 페이징이 일어나기 때문에 부하가 생긴다. &lt;br /&gt;따라서 INDEX 필요한 경우 primary(클러스터) 대신 unique만 설정하는 게 좋을 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;데이터 중복도&lt;/span&gt;가 높은 열은 INDEX 효과가 없다. &lt;br /&gt;예를 들어 성별 컬럼에 M, F만 있다고 하면 INDEX를 안쓰는 게 낫다. INDEX를 봤다가 데이터를 봤다가 하여 성능이 느려진다&lt;br /&gt;따라서 일반 보조 인덱스보다 unique 보조 인덱스가 빠른 이유가 이것이다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;자주 조회되지 않으면&lt;/span&gt; 성능 저하를 초래할 수 있음. (INSERT만 주구장창 하는 시스템이라면, 사용해보지도 못하고 데이터 입력에 걸리는 작업량만 많아진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;인덱스를_사용할_때_주의할_점&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인덱스 주의할 점(금지와 연계)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 변경(삽입, 수정, 삭제) 작업이 얼마나 자주 일어나는지 고려해야 함.&lt;/li&gt;
&lt;li&gt;단일 테이블에 인덱스가 많으면 속도가 느려질 수있다. (&lt;span style=&quot;color: #006dd7;&quot;&gt;테이블당 3~4개 권장&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;검색할 데이터가 전체 데이터의 20% 이상&lt;/span&gt;이라면, MySQL에서 인덱스를 사용하지 않음. (강제로 사용할 시 성능 저하를 초래할 수 있음)&lt;/li&gt;
&lt;li&gt;사용하지 않는 인덱스는 제거하는 것이 바람직함.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;테이블에&amp;nbsp;클러스터형 인덱스가 아예 없는 것이 좋은 경우도 있음&lt;/li&gt;
&lt;li&gt;테이블이 가지고 있는 전체 데이터양의 10~15% 이내의 데이터가 출력될때만 INDEX를 타는게 효율적&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;인덱스가_안_되는_쿼리&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;인덱스가 안 되는 쿼리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;INDEX가 있다고 모든 쿼리에서 INDEX를 활용하는 것은 아니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스 입힌 컬럼을 가공
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;WHERE SUBSTR(컬럼명, 1,4) = &amp;lsquo;2019&amp;rsquo; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;해결 &amp;rarr; &lt;span style=&quot;color: #006dd7;&quot;&gt;WHERE 컬럼명 LIKE &amp;lsquo;2019%&amp;rsquo;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인덱스 컬럼을 OR절 사용 비교는 비교해야할 Row를 늘리는 역할을 하여 풀스캔이 발생할 확률이 높다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;WHERE 컬럼명 = 'A' OR 컬럼명 = 'B'&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;해결 &amp;rarr;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;WHERE 컬럼명 IN ('A','B')&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인덱스가 있는 열 이름에는 함수나 연산을 가함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;WHERE count*10=100&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;해결 &amp;rarr;&lt;span&gt; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;WHERE count=100/10&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인덱스 컬럼의 묵시적 형변환(같은 타입으로 비교해야함)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;WHERE &lt;span style=&quot;color: #ee2323;&quot;&gt;컬럼명&lt;/span&gt; = &amp;lsquo;20190730&amp;rsquo; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;해결 &amp;rarr;&lt;/span&gt;&amp;nbsp;&lt;span style=&quot;color: #006dd7;&quot;&gt;WHERE &lt;span style=&quot;color: #006dd7;&quot;&gt;컬럼명&lt;/span&gt; = TO_DATE(&amp;lsquo;20190730&amp;rsquo;, &amp;lsquo;YYYYMMDD&amp;rsquo;)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인덱스 컬럼 부정형 비교.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;WHERE &lt;span style=&quot;color: #ee2323;&quot;&gt;컬럼명&lt;/span&gt; != &amp;lsquo;10&amp;rsquo; &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;해결 &amp;rarr; &lt;span style=&quot;color: #006dd7;&quot;&gt;WHERE &lt;span style=&quot;color: #006dd7;&quot;&gt;컬럼명&lt;/span&gt; IN(&amp;lsquo;20&amp;rsquo;, &amp;lsquo;30&amp;rsquo;)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;LIKE %가 앞에 위치.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;WHERE &lt;span style=&quot;color: #ee2323;&quot;&gt;컬럼명&lt;/span&gt; LIKE &amp;lsquo;%2019&amp;rsquo;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;해결 &amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;or 조건 사용 &lt;span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;WHERE &lt;span style=&quot;color: #006dd7;&quot;&gt;컬럼명&lt;/span&gt; IN(&amp;lsquo;102019&amp;rsquo;,&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;lsquo;202019&amp;rsquo;,&lt;span style=&quot;color: #006dd7;&quot;&gt;&amp;lsquo;302019&amp;rsquo;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;between, like, &amp;lt;, &amp;gt; 등 범위 조건은 해당컬럼은 인덱스를 타지만, 그 뒤 인덱스 컬럼들은 인덱스가 사용되지 않음.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;order_by_와_group_by에_대한_인덱스&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ORDER BY 와 GROUP BY에 대한 인덱스&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;INDEX는 ORDER BY와 GROUP BY에도 영향을 끼치는데 다음과 같은 경우에는 INDEX를 타지 않는다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;ORDER BY 인덱스컬럼1, 컬럼2&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;복수의 키에 대해서 ORDER BY를 사용한 경우&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;WHERE 컬럼1='값' ORDER BY 인덱스 컬럼&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;연속하지 않은 컬럼에 대해 ORDER BY를 실행한 경우&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;ORDER BY 인덱스컬럼1 DESC, 인덱스컬럼2 ASC&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;DESC와 ASC를 혼합해서 사용한 경우&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;GROUP BY 컬럼1 ORDER BY 컬럼2&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;GROUP BY와 ORDER BY의 컬럼이 다른 경우&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;ORDER BY ABS(컬럼)&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;ORDER BY 절에 다른 표현을 사용한 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;인덱스_정렬&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;제약 조건을 설정할 때 인덱스 성능 주의점&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;보통 제약 조건의 설정은 대개 테이블의 생성 구문(create)에서 하거나, 테이블 생성하고 뒤에 alter문으로 따로 진행한다.&lt;br /&gt;그러므로 아직 테이블에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;데이터가 입력되기 전&lt;/span&gt;에 primary key 및 unique 키의 열에는 인덱스가 생성되어져 있기 때문에, 인덱스 자체를 구성하는 시간이 걸리지 않는다.&lt;br /&gt;&lt;br /&gt;하지만&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;많은 데이터가 입력된 후&lt;/span&gt;에 alter문으로 unique 나 primary를 지정하면 인덱스를 구성하는데 많은 시간이 걸릴 수도 있다. (페이지 분할하고 다시 정렬하고 하니까)&lt;br /&gt;즉, 업무시간에 함부로 기존에 운영되는 대량의 테이블의 인덱스를 생성하면 시스템이 엄청나게 느려져 심각한 상황이 발생될 수도 있으니 주의해야 한다. (데이터의 양에 따라서 몇 시간이나 그 이사의 시간이 걸릴 수도 있다.)&lt;/p&gt;
&lt;h3 id=&quot;인덱스_정렬&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;인덱스 정렬&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인덱스를 생성할 때 인덱스에 포함되는 필드의 정렬 방식을 설정할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;DESC&amp;nbsp;&lt;/span&gt;키워드를 사용하면 내림차순으로 정렬되며,&amp;nbsp;&lt;span style=&quot;color: #8a3db6;&quot;&gt;ASC&lt;/span&gt;&amp;nbsp;키워드를 사용하면 오름차순으로 정렬된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;codeBlock_stylish&quot;&gt;&lt;span data-ke-language=&quot;sql&quot;&gt;sql&lt;/span&gt;&lt;/div&gt;
&lt;pre id=&quot;code_1654236691633&quot; class=&quot;pgsql&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;sql&quot;&gt;&lt;code&gt;CREATE INDEX 인덱스이름
ON 테이블이름 (필드이름 DESC) -- 인덱스 지정한 필드이름은 내림차순으로 정렬됨

CREATE INDEX 인덱스이름
ON 테이블이름 (필드이름 ASC) -- 인덱스 지정한 필드이름은 오름차순으로 정렬됨&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;다중_컬럼_인덱스&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;다중 컬럼 인덱스&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다중 컬럼 인덱스는&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;두개 이상의 필드를 조합해서 생성한 INDEX&lt;/span&gt;이다. (MySQL은 INDEX에 최대 15개 컬럼으로 구성 가능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;1번째 조건과 이를 만족하는 2번째 조건을 함께&lt;/span&gt; INDEX해서 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다중 컬럼 인덱스는&amp;nbsp;단일 컬럼 인덱스 보다 더 비효율적으로 INDEX/UPDATE/DELETE를 수행하기 때문에 신중해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 가급적 UPDATE가 안되는 값을 선정 해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;email, id 컬럼에 각각 단일 인덱스가 걸려있는 경우&amp;nbsp; 어떤 컬럼의 수가&amp;nbsp; 더 빠르게 검색되는지 판단 후 빠른쪽을 먼저 검색하고 그다음 다른 컬럼을 검색하는데 다중 컬럼 인덱스의 경우 INDEX를 저장할 때 email,id를 같이 저장하기 때문에 같이 색인하고 검색이 더빠르다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;실제로 조회 쿼리 사용시 인덱스를 태우려면 최소한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;첫번째 인덱스 조건은 조회조건에 포함&lt;/b&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;되어야 한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;첫번째 인덱스 컬럼이 조회 쿼리에 없으면 인덱스를 타지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의) 그렇지만 다중 컬럼 인덱스를 순서가 안맞거나 이빨빠지게 조회하면 인덱스의 효과를 기대하기 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근엔 개선됐다고 하지만 맞춰주는게 맘편함!&lt;/p&gt;</description>
      <author>닥치고개돌</author>
      <guid isPermaLink="true">https://shutcoding.tistory.com/93</guid>
      <comments>https://shutcoding.tistory.com/entry/%EC%9D%B8%EB%8D%B1%EC%8A%A4index%EB%9E%80-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EC%95%8C%EA%B3%A0%EC%93%B0%EA%B8%B0#entry93comment</comments>
      <pubDate>Thu, 1 Feb 2024 13:18:58 +0900</pubDate>
    </item>
  </channel>
</rss>