<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코딩동굴</title>
    <link>https://jinmak.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 23 Jul 2026 02:39:55 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>진막</managingEditor>
    <image>
      <title>코딩동굴</title>
      <url>https://tistory1.daumcdn.net/tistory/6940482/attach/f9c4293819644932b1fd288bbda1ce4a</url>
      <link>https://jinmak.tistory.com</link>
    </image>
    <item>
      <title>2024 1회차 정보처리기사 자격증 취득 후기</title>
      <link>https://jinmak.tistory.com/50</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;2024&amp;nbsp;1회차&amp;nbsp;정보처리기사&amp;nbsp;자격증&amp;nbsp;취득&amp;nbsp;후기&lt;/h2&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;한창 IT회사로 취업이 불안정한 시기다. 지금도 그렇지만 코로나가 지나가고 나서는 계속 이런 상황이었던 것 같다. 그래선지 2024년, 신년을 맞이했을 때 이번 연도에는 무엇을 해야 할까? 또 나는 어떤 방향으로 전략을 짜야할까에 대한 고민이 많았다. 그중에 하나가 자격증을 취득하는 것이었다. 어학 자격증도 중요하지만 내가 따고자 하는 오픽의 경우 상시 시험이 있기 때문에 1년에 3번밖에 기회가 없는 기사 자격증부터 준비하는 게 전략적으로 좋을 것이라 생각했다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;4학년도 됐겠다. 마침 기사 시험을 볼 수 있는 자격이 생겼다. 그래서 기사 필기 신청날이 되자마자 1회 정보처리기사 필기 시험을 신청했다. 필기시험은 사실 아주 무난했다. 물론 시험을 보기 전까지 공부를 많이 안 해놓은 상태여서 시험 전날엔&amp;nbsp; '그냥 이번 시험은 포기하고 2회차를 볼까' 하는 생각이 들었다. 다행히도 그날 아침에 보고 간 문제 해설 강의에서 배운 많은 문제가 시험에 그대로 나온 덕에 무난하게 필기시험을 합격할 수 있었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;강의에선 필기시험이 끝나자마자 실기 시험을 준비해야 실기를 통과할 수 있다고 말했지만, 시간이 꽤 많이 남아서 딱 한 달 남은 시점에 실기 공부를 시작하기로 마음 먹었다. IT 전공자라고 하기엔 애매하지만, 그렇다고 비전공자라고 하기엔 또 학교에서 배우는 게 아예 없진 않아서 넉넉 잡아 한 달이 적당하다고 생각했다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;결국 한 달 남은 시점, 새해에 사둔 두꺼운 실기책을 처음 펴보았다. 양이 워낙 많아보여서 꼼꼼하게 다 할 생각은 없었다. 최대한 꼼수를 부려 합격할 수 있는 정도로만 공부하자가 내 목표였다. 자격증 시험에서 시험을 가장 잘 본 사람은 60점이라고 생각하기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다행히 문제집에서 이미 중요한 순서를 A, B, C, D 로 구분해 주었다. 나는 그중 한 번이라도 시험에 출제된 적이 있는 A와 B만 공부하기로 했고, 나름대로 노트에 중요하다고 생각하는 부분을 적어 한 번 전체적으로 훑었다. 노트에 정리하는 시간은 딱 2주 동안 평일에 3-4시간씩을 할애하여 정리했다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;남은 2주 동안은 하루에 남는 시간을 이용해 필기한 부분을 복습하자...! 라고 야심 차게 계획을 세웠지만 중간고사 기간, 그리고 졸업 논문 최종 발표가 겹치는 바람에 도저히 정보처리기사에 쓸 시간이 나오지 않았다. 중간고사 마지막 시험이 목요일에 끝났고, 정보처리기사 시험이 토요일에 있었으니 목요일부터 토요일까지 열심히 하면 어떻게든 되지 않겠냐는 생각이었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;중간고사 마지막 시험이 끝나고, 학교 시험이 끝났다는 여유를 즐길새도 없이 기사 시험을 준비했다. 계획대로라면 노트 필기한 개념을 숙지하고 기출을 푸는 것이었는데, 당장 개념도 외우지 못해서 필기한 노트를 토대로 개념을 계속 읽었다. 토요일 저녁까지는 기출은 전혀 보지 않고 개념만 계속해서 외운 것 같다. 시험 전날 밤이 돼서야 기출을 풀 수 있었다. 다행인지 불행인지 정처기가 개정된 지 얼마 안 되어 봐야 하는 기출이 많지는 않았다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;솔직히 기출 중에 이해 안되는 문제가 몇몇 있었는데 당장 시험까지 12시간 정도밖에 남지 않은 나에게 그런 것은 중요하지 않았다. 그나마 할 만한 문제를 붙잡고 확실하게 이해하는 게 차라리 나을 것이란 생각이 들어. 나올 만한 문제를 위주로 강의를 들으며 학습했다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;기출을 어느 정도 보고나니 새벽 2시가 되어 있었다. 시험장에는 9시까지 입실해야 했고 가는 시간과 준비하는 시간까지 고려하면 4시간 30분 정도가 남아있었다. 시험 보기 전까지 개념을 머릿속에 때려 박고 시험 볼 때 후루룩 털어야 했기 때문에 지금까지 봤던 개념을 계속해서 읽었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;슬슬 날이 밝아오기 시작했고, 시험장으로 가기 위한 준비를 해야했다. 머릿속이 뿌연 느낌이 들었지만 샤워를 하고 집 밖을 나오니 머리가 상쾌해지는 착각이 들었다. 새벽껏 A4용지 두 장에 정리해 놓은 개념을 보면서 지하철을 탔지만 졸음이 몰려와 생각한 만큼 개념을 보진 못했다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;시험장은 어느 고등학교에서 치뤘는데, 오랜만에 와 본 고등학교라 그런지 책상과 칠판이 놓인 교실이 어색했다. 물론 대학교에도 강의실은 있지만, 그건 어디까지나 강의를 하는 곳이란 느낌이지 교실 특유의 분위기가 살아있진 않다. 칠판 위에는 액자가 걸려 있었는데, 쓰인 글귀가 참 맘에 들었다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&quot;늦었다고 생각했을 때는 이미 늦은 것이다.&quot;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;시간이 흘러도 고등학생 특유의 유쾌함은 아직 남아 있는 것 같아서 기분이 좋아졌다. 나름 기분 좋은 상태로 시험을 치르기 시작했고, 시험은 생각보다 나쁘지 않았다. 기출에선 보지 못한 새로운 유형의 문제가 많았는데, 문제들이 기사를 준비할 때 접한 문제라기 보단 평소 코딩을 공부할 때 접한 문제가 많아서 꽤나 재밌어하며 문제를 풀었다. 검토도 하고 풀지 못한 문제도 한 번 더 보고 하다 보니 남을 것이라 생각했던 시험 시간이 거의 다 되었음을 깨달았다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그렇게 시험을 끝내고 학교 밖을 나왔다. 날씨가 유난히 화창했던 것으로 기억한다. 밤을 새서 너무 졸렸지만 날씨가 좋아선지 기분이 썩 나쁘진 않았다. 집에 가면서 시험의 가답안을 확인했다. 몇 가지 문제들이 오류가 있기도 했고, 문제 자체가 애매한 경우가 있어서 사람들 간의 논쟁이 붉어졌었다. 나도 가채점을 해봤을 때 딱 합격 컷 점수가 나와 혹시라도 잘못 쓴 답이 있진 않을까 걱정이 많았다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 그 걱정도 잠시 집에 와서 한숨 푹자고 나니 내가 걱정한다고 해서 뭐 어쩔 있는 것은 아니라는 생각이 들었다. 진인사대천명이라 했다. 난 할 만큼 했으니 남은 것은 하늘에 맡기기로 하고 기다리기로 했다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 방금 시험 결과가 나왔다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;30&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAx4eb/btsH2OXVhKH/6iJlxJ9OCOnq0AT2akM4RK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAx4eb/btsH2OXVhKH/6iJlxJ9OCOnq0AT2akM4RK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAx4eb/btsH2OXVhKH/6iJlxJ9OCOnq0AT2akM4RK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAx4eb%2FbtsH2OXVhKH%2F6iJlxJ9OCOnq0AT2akM4RK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;513&quot; height=&quot;30&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;30&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;오&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;공부를 몰아쳐서 하긴 했지만 그래도 이런 자격증 시험은 한 번에 끝내야 한다는 생각이 강했는데, 다행히 1회만에 붙을 수 있어서 다행이었다. 점수도 생각보다 높았는데 아마 논란이 됐던 문제를 모두 정답 처리해 준 것 같다. 그래서 이번 시험의 합격률이 특히 높은 것으로 안다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; 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;</description>
      <category>이것저것</category>
      <author>진막</author>
      <guid isPermaLink="true">https://jinmak.tistory.com/50</guid>
      <comments>https://jinmak.tistory.com/50#entry50comment</comments>
      <pubDate>Tue, 18 Jun 2024 17:15:49 +0900</pubDate>
    </item>
    <item>
      <title>알고리즘 - 정렬</title>
      <link>https://jinmak.tistory.com/49</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;알고리즘 - 정렬&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/45&quot; rel=&quot;noopener&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/a&gt;알고리즘&lt;/h3&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 style=&quot;text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/48&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;알고리즘 - 버블 정렬 (Bubble Sort)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1716975653052&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;알고리즘 - 버블 정렬 (Bubble Sort)&quot; data-og-description=&quot;알고리즘 - 버블 정렬 (Bubble Sort)본 글은&amp;nbsp;https://www.daleseo.com/sort-bubble/에 게시된 글을 학습 목적으로 필기한 글입니다.&amp;nbsp;위 블로그에선 기본적인 버블 정렬 알고리즘 뿐만 아니라 버블 정렬을 어떻&quot; data-og-host=&quot;jinmak.tistory.com&quot; data-og-source-url=&quot;https://jinmak.tistory.com/48&quot; data-og-url=&quot;https://jinmak.tistory.com/48&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/qjQ2L/hyWdnxfNrP/ADPstQu6tFoxzlQEbiEC71/img.png?width=701&amp;amp;height=403&amp;amp;face=0_0_701_403,https://scrap.kakaocdn.net/dn/ccvgbl/hyV9T5BFlL/GKn5cAes1CG029L73z7jp1/img.png?width=701&amp;amp;height=403&amp;amp;face=0_0_701_403&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/48&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jinmak.tistory.com/48&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/qjQ2L/hyWdnxfNrP/ADPstQu6tFoxzlQEbiEC71/img.png?width=701&amp;amp;height=403&amp;amp;face=0_0_701_403,https://scrap.kakaocdn.net/dn/ccvgbl/hyV9T5BFlL/GKn5cAes1CG029L73z7jp1/img.png?width=701&amp;amp;height=403&amp;amp;face=0_0_701_403');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;알고리즘 - 버블 정렬 (Bubble Sort)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;알고리즘 - 버블 정렬 (Bubble Sort)본 글은&amp;nbsp;https://www.daleseo.com/sort-bubble/에 게시된 글을 학습 목적으로 필기한 글입니다.&amp;nbsp;위 블로그에선 기본적인 버블 정렬 알고리즘 뿐만 아니라 버블 정렬을 어떻&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jinmak.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: right;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: right;&quot; 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>
      <author>진막</author>
      <guid isPermaLink="true">https://jinmak.tistory.com/49</guid>
      <comments>https://jinmak.tistory.com/49#entry49comment</comments>
      <pubDate>Wed, 29 May 2024 18:41:08 +0900</pubDate>
    </item>
    <item>
      <title>알고리즘 - 버블 정렬 (Bubble Sort)</title>
      <link>https://jinmak.tistory.com/48</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;알고리즘 - 버블 정렬 (Bubble Sort)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 글은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://www.daleseo.com/sort-bubble/&quot;&gt;https://www.daleseo.com/sort-bubble/&lt;/a&gt;에 게시된 글을 학습 목적으로 필기한 글입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 블로그에선 기본적인 버블 정렬 알고리즘 뿐만 아니라 버블 정렬을 어떻게 최적화할 수 있는지 파이썬과 자바 코드를 통해 상세하게 다루고 있어 눈여겨 볼만하다.&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;버블 정렬이란?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;거품 정렬은 큰 그림에서 보았을 때 뒤에서부터 앞으로 정렬을 해나가는 구조를 가지고 있다. 즉, 맨 뒷자리부터 제일 큰 값을 뒤로 보내고, 제일 큰 값 바로 앞에 두번째로 큰 값을 보낸다. 이를 위해 배열 내의 값들을 앞뒤로 서로 비교해서 자리를 바꾸는 작업을 계속 수행해야 한다. 이렇게 큰 값을 계속해서 뒤로 보내는 모습이 마치 방울이 이동하는 것과 같이 보여서 거품 정렬이라는 이름이 붙었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;141&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ebMuxA/btsHEpqzcqu/JXJ3fb228ufCHQSrtNllE0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ebMuxA/btsHEpqzcqu/JXJ3fb228ufCHQSrtNllE0/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ebMuxA/btsHEpqzcqu/JXJ3fb228ufCHQSrtNllE0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/ebMuxA/btsHEpqzcqu/JXJ3fb228ufCHQSrtNllE0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;401&quot; height=&quot;141&quot; data-origin-width=&quot;401&quot; data-origin-height=&quot;141&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p 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;다음과 같이 1부터 5까지 총 5개의 숫자가 들어있는 배열에 대해서 위 로직을 적용해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716975372087&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;[4, 3, 5, 1, 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;먼저, 4와 3을 비교한다. 4가 3보다 크기 때문에 자리를 바꿔준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716975372088&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;[4, 3, 5, 1, 2]
 ^  ^
 4 &amp;gt; 3 =&amp;gt; Swap
[3, 4, 5, 1, 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;그 다음 4와 5을 비교한다. 4가 5보다 작기 때문에 자리를 바꿀 필요는 없어 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716975372088&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;[3, 4, 5, 1, 2]
    ^  ^
4 &amp;lt; 5 =&amp;gt; No Swap&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;그 다음 5와 1을 비교한다. 5가 1보다 크기 때문에 자리를 바꿔준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716975372089&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;[3, 4, 5, 1, 2]
       ^  ^
 5 &amp;gt; 1 =&amp;gt; Swap
[3, 4, 1, 5, 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;그 다음 5와 2를 비교한다. 5가 2보다 크기 때문에 자리를 바꾼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716975372089&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;[3, 4, 1, 5, 2]
          ^  ^
 5 &amp;gt; 2 =&amp;gt; Swap
[3, 4, 1, 2, 5]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 맨 처음 값부터 시작해서 그 다음 값과 대소를 비교하여 앞의 값이 뒤의 값보다 클 경우 자리를 바꿔주면 결국 제일 큰 값이 맨 뒤로 간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정을 모든 값으로 확장하면 다음과 같이 두 번째로 큰 값을 제일 큰 값 바로 앞으로 보낼 수 있고, 세 번째로 큰 값을 두 번째로 큰 값 바로 앞으로 보낼 수가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716975372090&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;Initial: [4, 3, 5, 1, 2]

 Pass 1: [3, 4, 1, 2, 5]
                      *
 Pass 2: [3, 1, 2, 4, 5]
                   *  *
 Pass 3: [1, 2, 3, 4, 5]
                *  *  *
 Pass 4: [1, 2, 3, 4, 5]
             *  *  *  *
 Pass 5: [1, 2, 3, 4, 5]
          *  *  *  *  *&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;알고리즘 특징&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;버블 정렬은 점점 큰 값들을 뒤에서부터 앞으로 하나씩 쌓아가기 때문에 후반으로 갈수록 정렬 범위가 하나씩 줄어들게 된다.&lt;/li&gt;
&lt;li&gt;왜냐하면, 다음 패스에서는 이전 패스에서 뒤로 보내놓은 가장 큰 값이 있는 위치 전까지만 비교해도 되기 때문이다.&lt;/li&gt;
&lt;li&gt;제일 작은 값을 찾아서 맨 앞에 위치시키는 선택 정렬과 비교했을 때 정반대의 정렬 방향을 가진다.&lt;/li&gt;
&lt;li&gt;다른 정렬 알고리즘에 비해서 자리 교대(swap)가 빈번하게 일어나는 경향을 가지고 있다. 예를 들어, 선택 정렬의 경우 각 패스에서 자리 교새다 딱 한 번만 일어난다.&lt;/li&gt;
&lt;li&gt;최적화 여지가 많은 알고리즘이다. 예를 들어, 위&amp;nbsp; 그림에서 Pass 5는 생략할 수 있는 패스이다. 왜냐하면 Pass 4에서 한 번도 자리 교대가 일어나지 않았기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;복잡도 분석&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;거품 정렬은 별도의 추가 공간을 사용하지 않고 주어진 배열이 차지하고 있는 공간 내에서 값들의 위치만 바꾸기 때문에 O(1)의 공간 복잡도를 가진다.&lt;/li&gt;
&lt;li&gt;시간 복잡도는 우선 루프문을 통해 맨 뒤부터 맨 앞까지 모든 인덱스에 접근해야 하기 때문에 기본적으로 O(N)의 시간을 소모하며, 하나의 루프에서는 인접한 값들의 대소 비교 및 자리 교대를 위해서 O(N)의 시간을 필요로 한다. 따라서 거품 정렬은 총 O(N2)의 시간 복잡도를 가지는 정렬 알고리즘이다.&lt;/li&gt;
&lt;li&gt;하지만, 거품 정렬은 부분적으로 정렬되어 있는 배열에 대해서는 최적화를 통해서 성능을 대폭 개선할 수 있으며, 완전히 정렬되어 있는 배열이 들어올 경우, O(N)까지도 시간 복잡도를 향상시킬 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;구현&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택 정렬과 마찬가지로 두 개의 반복문이 필요하다. 내부 반복문에서는 첫 번째 값부터 이전 패스에서 뒤로 보내놓은 값이 있는 위치 전까지 앞뒤 값을 계속해서 비교해나가 앞의 값이 뒤의 값보다 클 경우 자리 교대(swap)을 한다. 외부 반복문에서는 뒤에서부터 앞으로 정렬 범위를 `n-1`부터 `1`까지 줄여나간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;Python 코드&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1716975372091&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;def bubble_sort(arr):
    for i in range(len(arr)-1, 0, -1):
        for j in range(i):
            if arr[j] &amp;gt; arr[j+1]:
                arr[j], arr[j+1] = arr[[j+1], arr[j]&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;첫 번째 for 문에선 배열을 뒤에서 돌며 전체 범위를 하나씩 줄여나가는 것이 포인트다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;Java 코드&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1716975372092&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Bubble {
    public static void sort(int[] arr) {
        for (int i = arr.length-1; i &amp;gt; 0; i--) {
            for (int j = 0; j &amp;lt;= i; j++) {
                if (arr[j] &amp;gt; arr[j+1])
                    swap(arr, j, j+1);
            }
        }
    }
    
    private static void swap(int[] arr, int a, int b) {
        int tmp = arr[a];
        arr[a] = arr[b];
        arr[b] = tmp;
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ef6f53;&quot;&gt;최적화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 패스에서 앞뒤 자리 비교(swap)이 한 번도 일어나지 않았다면 정렬되지 않는 값이 하나도 없었다고 간주할 수 있다. 따라서 이럴 경우, 이후 패스를 수행하지 않아도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716975372093&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;Initial: [1, 2, 3, 5, 4]

Pass 1 : [ , 2, 3, 4, 5] =&amp;gt; Swap 있었음
                      *
Pass 2 : [ , 2, 3, 4, 5] =&amp;gt; Swap 없었음
                   *  *
                   
=&amp;gt; 이전 패스에서 swap이 한 번도 없었으니 종료&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333; background-color: #f6e199;&quot;&gt;Python 코드&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1716975372093&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;def bubble_sort(arr):
    for i in range(len(arr) - 1, 0, -1):
        swapped = False
        for j in range(i):
            if arr[j] &amp;gt; arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                swapped = True
        if not swapped:
            break&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc9af; color: #333333; text-align: center;&quot;&gt;Java 코드&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1716975372094&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Bubble {
    public static void sort(int[] arr) {
        for (int i = arr.length - 1; i &amp;gt; 0; i--) {
            boolean swapped = false;
            for (int j = 0; j &amp;lt; i; j++) {
                if ( arr[j] &amp;lt; arr[j + 1]) {
                    swap(arr, j, j + 1);
                    swapped = true;
                }
            }
            if (!swapped) break;
        }
    }
    
    private static void swap(int[] arr, int a, int b) {
        int tmp = arr[a];
        arr[a] = arr[b];
        arr[b] = tmp;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;추가 최적화&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이전 패스에서 앞뒤 자리 비교(swap)가 있었는지 여부를 체크하는 대신 마지막으로 앞뒤 자리 비교가 있었던 index를 기억해두면 다음 패스에서는 그 자리 전까지만 정렬해도 된다. 따라서 한 칸씩 정렬 범위를 줄여나가는 대신 한번에 여러 칸씩 정렬 범위를 줄여나갈 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716975372096&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;Initial: [3, 2, 1, 4, 5]

 Pass 1: [2, 1, 3, 4, 5] =&amp;gt; 마지막 Swap 위치가 index 1
             ^        *
 Pass 2: [1, 2, 3, 4, 5] =&amp;gt; 중간 패스 skip하고 바로 index 1로 보낼 값 찾기
          ^     *  *  *&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;Python 코드&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1716975372096&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;def bubble_sort(arr):
    end = len(arr) - 1
    while end &amp;gt; 0:
        last_swap = 0
        for i in range(end):
            if arr[i] &amp;gt; arr[i + 1]:
                arr[i], arr[i + 1] = arr[i + 1], arr[i]
                last_swap = i
        end = last_swap&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffc9af; color: #333333; text-align: center;&quot;&gt;Java 코드&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716975372098&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;public class Bubble {
    public static void sort(int[] arr) {
        int end = arr.length - 1;
        while (end &amp;gt; 0) {
            int last_swap = 0;
            for (int i = 0; i &amp;lt; end; i++) {
                if (arr[i] &amp;gt; arr[i + 1]) {
                    swap(arr, i, i + 1);
                    last_swap = i;
                }
            }
            end = last_swap;
        }
    }
     
    private static void swap(int[] arr, int a, int b) {
        int tmp = arr[a];
        arr[a] = arr[b];
        arr[b] = tmp;
    }
}&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘</category>
      <author>진막</author>
      <guid isPermaLink="true">https://jinmak.tistory.com/48</guid>
      <comments>https://jinmak.tistory.com/48#entry48comment</comments>
      <pubDate>Wed, 29 May 2024 18:36:25 +0900</pubDate>
    </item>
    <item>
      <title>자바 - 업캐스팅(UpCasting) &amp;amp; 다운캐스팅(DownCasting)</title>
      <link>https://jinmak.tistory.com/47</link>
      <description>&lt;h2 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;자바&amp;nbsp;-&amp;nbsp;업캐스팅(UpCasting)&amp;nbsp;&amp;amp;&amp;nbsp;다운캐스팅(DownCasting)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;자바의 참조형 캐스팅&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하나의 데이터 타입을 다른 타입으로 바꾸는 것을 타입 변환 혹은 형변환(캐스팅) 이라고 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;자바의 데이터형을 알아보면 크게 두 가지로 나뉜다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;기본형&lt;/span&gt;(Primitive Type) : boolean, char, float, double, byte, short, int, long&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;참조형&lt;/span&gt;(Reference Type) : Arrays, Strings, Classes, Interfaces, Enums, Objects&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;기본형이든 참조형이든 결국 하나의 타입이기 때문에 서로 타입간의 형변환(&lt;span style=&quot;color: #ef6f53;&quot;&gt;casting&lt;/span&gt;)이 가능하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;기본적으로 자바에선 대입 연산자 '=' 에서 변수와 값 서로 양쪽의 타입이 일치하지 않으면 할당이 불가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;프로그램에서 값의 대입이나 연산을 수행할 때는 같은 타입끼리만 가능하기 때문이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716807157123&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;long d = 10.233; //ERROR&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 우리는 다음과 같이 캐스팅 연산자를 사용하여 강제적으로 타입을 지정하여 변수에 대입하도록 설정해 주었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716807202053&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;long d = (long)10.233;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;상속 관계의 클래스는 크게 부모 클래스(슈퍼 클래스)와 자식 클래스(서브 클래스)로 구분할 수 있다. 기본형 타입을 서로 형변환할 수 있듯이, &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;자바의 상속 관계에 있는 부모와 자식 클래스 간에는 서로 간의 형변환이 가능하다.&lt;/span&gt; 클래스는 refeence 타입으로 분류되니 이를 &lt;span style=&quot;color: #ef6f53;&quot;&gt;참조형 캐스팅(업캐스팅 / 다운캐스팅)&lt;/span&gt;이라고 부른다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;달리 말하면 서로 상속(extends)나 구현(implements) 관계 등에 있지 않는 전혀 다른 두 객체라면, 캐스팅이 일어날 수 없다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716807818970&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Animal {
    public void moving() {
        System.out.println(&quot;움직입니다.&quot;);
    }
}

class Chair {
    public void existing() {
        System.out.println(&quot;여기에 의자가 있다.&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드를 보면, Candy 클래스와 Cup이라는 클래스는 실제 세상에서 딱히 연관이 없을뿐더러 코드에서도 서로 어떤 연관 관계를 가지고 있지 않다. 따라서 두 클래스 간 캐스팅은 불가능하고, 굳이 할 필요도 없다!&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;또한 잠깐 언급했듯이 클래스-상속받은 클래스(extends)간 캐스팅뿐만 아니라 추상 클래스-상속받은 클래스 간(extends), 인터페이스-구현 클래스(implements)간의 캐스팅도 가능하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;업캐스팅(UpCasting)&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;업캐스팅은 자식 클래스가 부모 클래스 타입으로 캐스팅되는 것이다.&lt;/li&gt;
&lt;li&gt;업캐스팅은 캐스팅 연산자 괄호를 생략할 수 있다.&lt;/li&gt;
&lt;li&gt;부모 클래스로 캐스팅된다는 것은 멤버의 개수 감소를 의미한다.(이는 곧 자식 클래스에서만 있는 속성과 메서드는 실행하지 못한다는 뜻이다.)&lt;/li&gt;
&lt;li&gt;업캐스팅을 하고, 메서드를 실행할 때 만약 자식 클래스에서 오버라이딩한 메서드가 있을 경우, 부모 클래스의 메서드가 아닌 오버라이딩 된 메서드가 실행된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716808529690&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Animal {
    String name;
    int age;
    public void bark() {
        System.out.println(&quot;짖습니다.&quot;);
    }
}

class Dog extends Animal {
    String name;
    int age;
    double breed;
    public void bark() {
        System.out.println(&quot;개가 짖습니다.&quot;);
    }

    public void hand() {
        System.out.println(&quot;앞발을 올립니다.&quot;);
    }
}
public class UpCastingDownCasting {
    public static void main(String[] args) {

        Animal upcasting;
        Dog dog = new Dog();
        
        // 업캐스팅(upcasting)
        upcasting = (Animal) dog;
        upcasting = dog; // 업캐스팅은 형변환 괄호 생략 가능
        
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드에선 부모 클래스 Animal을 상속하는 Dog 자식 클래스가 있다. dog 객체를 Animal 자료형을 가진 upcasting 객체에 대입함으로써 dog를 Animal 자료형으로 업캐스팅하고 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;사실 업캐스팅을 이해하는 데 있어 미리 객체 지향(OOP)의 참조 다형성에 대해서 배웠다면 업캐스팅은 꽤나 눈에 익은 작업일 것이다. 늘 해오던 한 번에 대입하느냐 아니면 방금처럼 변수에 나누어 대입하느냐 차이가 있을 뿐 결국 똑같은 작업을 하는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716808922123&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Animal animal_dog = new Dog(); // 참조 다형성

//============================================

Dog dog = new Dog();
Animal animal_up = dog; // 참조형 변수 업캐스팅&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;업캐스팅 멤버 제한&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;업캐스팅에는 주의해야 할 점이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;멤버가 많은 자식 클래스가 부모 클래스로 업캐스팅하면 멤버 개수가 감소하게 된다. 다시 말해 실행할 수 있는 속성과 메서드가 제한된다는 뜻이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716811311316&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Animal {
    String name;
    int age;
    public void bark() {
        System.out.println(&quot;짖습니다.&quot;);
    }
}

class Dog extends Animal {
    String name;
    int age;
    double breed;
    public void bark() {
        System.out.println(&quot;개가 짖습니다.&quot;);
    }

    public void hand() {
        System.out.println(&quot;앞발을 올립니다.&quot;);
    }
}
public class UpCastingDownCasting {
    public static void main(String[] args) {

        Animal upcasting;
        Dog dog = new Dog();
        
        // 업캐스팅(upcasting)
        upcasting = (Animal) dog;
        upcasting = dog; // 업캐스팅은 형변환 괄호 생략 가능
        
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드에서 `upcasting` 참조형 변수에 할당한 데이터 dog 변수는 Dog 객체이다. 그런데 업캐스팅되면서 Animal 타입으로 형변환 되었기 때문에 오로지 부모 클래스에 속한 멤버만 접근이 허용되게 제한되었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 부모 클래스 Animal에 없고 자식 클래스에만 있는 `hand()` 메서드를 실행해 보면, 컴파일 에러가 발생한다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;290&quot; data-origin-height=&quot;81&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqN07K/btsHDxWwXTe/Xpj5uoO5K688B31kuic8Bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqN07K/btsHDxWwXTe/Xpj5uoO5K688B31kuic8Bk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqN07K/btsHDxWwXTe/Xpj5uoO5K688B31kuic8Bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqN07K%2FbtsHDxWwXTe%2FXpj5uoO5K688B31kuic8Bk%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;290&quot; height=&quot;81&quot; data-origin-width=&quot;290&quot; data-origin-height=&quot;81&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이와 같이 업캐스팅을 하게 되면 부모 클래스 멤버로 멤버 개수가 한정되었기 때문에 자식 클래스 내에 모든 멤버에 접근할 수 없게 된다. 이는 메서드뿐만 아니라 필드에도 동일하게 적용된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;요약하면 객체를 업캐스팅 하게 되면 자식과 부모의 공통된 것만 사용할 수 있고 자식 클래스에서 새로 만들어진 건 사용할 수 없다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;업캐스팅 오버라이딩 메서드&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 부모 클래스에도 있는 `bark()` 메서드를 실행해 보자. 그런데 가만 보니 이 `bark` 메서드는 자식 클래스에서 오버라이딩하여 재정의하였다. 이러한 구조에서 업캐스팅한 객체의 bark() 메서드를 실행하면 어느 위치에 있는 클래스 메서드가 실행될까?&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;154&quot; data-origin-height=&quot;38&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhITks/btsHD6KXhpe/RHFhoDsXYoJwOVlkjKNyR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhITks/btsHD6KXhpe/RHFhoDsXYoJwOVlkjKNyR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhITks/btsHD6KXhpe/RHFhoDsXYoJwOVlkjKNyR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhITks%2FbtsHD6KXhpe%2FRHFhoDsXYoJwOVlkjKNyR0%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;154&quot; height=&quot;38&quot; data-origin-width=&quot;154&quot; data-origin-height=&quot;38&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;정답은 오버라이딩된 자식 클래스의 멤버이다. 업캐스팅 되었기 때문에 부모 클래스에 정의된 메서드를 사용할 것 같았지만 오버라이딩 된 자식 클래스의 메서드를 사용하는 것을 볼 수 있다. 이는 오버라이딩 특성상 코드가 실행하는 런타임 환경에서 동적으로 바인딩되었기 때문이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;정리하자면 업캐스팅을 다루는 데 있어 조심해야 할 점은 크게 두 가지이다.&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;업캐스팅해도 오버라이딩된 메서드가 있다면 자식 클래스의 메서드로 실행이 된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;업캐스팅 하는 이유&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그렇다면 업캐스팅은 어떤 상황에서 해야 할까?&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;업캐스팅을 사용하는 이유는 공통적인 부분을 이용해 한 번에 다루기 위해서이다. 상속 관계에서 상속받은 자식 클래스가 몇 개가 되든 하나의 인스턴스로 묶어서 관리할 수 있기 때문이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 다음과 같이 부모 클래스 Shape에 각각 자식 클래스 Rectangle, Triangle, Circle가 상속 관계를 맺었다고 하자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; 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;img1.daumcdn.png&quot; data-origin-width=&quot;345&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biywAt/btsHDjqCWLP/ZeokxoUikdi6HrFtzedkok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biywAt/btsHDjqCWLP/ZeokxoUikdi6HrFtzedkok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biywAt/btsHDjqCWLP/ZeokxoUikdi6HrFtzedkok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiywAt%2FbtsHDjqCWLP%2FZeokxoUikdi6HrFtzedkok%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;345&quot; height=&quot;180&quot; data-filename=&quot;img1.daumcdn.png&quot; data-origin-width=&quot;345&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;본래라면 Rectangle, Triangle, Circle 클래스는 서로 다른 타입이니 각각 타입을 정의해서 사용해야 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716810120759&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Rectangle[] r = new Rectangle[];
r[0] = new Rectangle();
r[1] = new Rectangle();

Triangle[] t = new Triangle[];
t[0] = new Triangle();
t[1] = new Triangle();

Circle[] c = new Circle[];
c[0] = new Circle();
c[1] = new Circle();&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 상속 관계를 맺어 부모 클래스로 업캐스팅이 가능하다면, 다음과 같이 하나의 타입으로 묶어 배열을 구성할 수 있게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716810193435&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Shape[] s = new Shape[];
s[0] = new Rectangle();
s[1] = new Rectangle();
s[2] = new Triangle();
s[3] = new Triangle();
s[4] = new Circle();
s[5] = new Circle();&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하나의 자료형으로 관리하니 코드량도 훨씬 줄어들고 가독성도 좋아지며 유지보수성도 좋아짐을 알 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그런데 만약 자식 클래스에만 있는 고유한 메서드를 실행하려면 어떻게 해야 할까?&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;아쉽지만 오버라이딩 한 메서드가 아닌 이상 업캐스팅한 부모 클래스 타입에서 자식 클래스의 고유 메서드를 실행할 수 없다. 따라서 &lt;span style=&quot;background-color: #ffc9af;&quot;&gt;업캐스팅한 객체를 다시 자식 클래스 타입으로 되돌리는 다운캐스팅이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;다운 캐스팅(DownCasing)&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;업캐스팅의 그림자&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다운캐스팅은 거꾸로 부모 클래스가 자식 클래스 타입으로 캐스팅되는 것이다.&lt;/li&gt;
&lt;li&gt;다운캐스팅은 캐스팅 연산자 괄호를 생략할 수 없다.&lt;/li&gt;
&lt;li&gt;다운캐스팅의 목적은 업캐스팅한 객체를 다시 자식 클래스 타입의 객체로 되돌리는 목적을 둔다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다운캐스팅은 단순히 업캐스팅의 반대가 아닌, 업캐스팅되어 고유의 특성을 잃은 자식 클래스의 필드와 기능을 회복하기 위해 있는 것이다. 다시 말해 원래 있던 기능을 회복하기 위해 다운캐스팅을 하는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716810787370&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Animal {
    String name;
    int age;
    public void bark() {
        System.out.println(&quot;짖습니다.&quot;);
    }
}

class Dog extends Animal {
    String name;
    int age;
    double breed;
    public void bark() {
        System.out.println(&quot;개가 짖습니다.&quot;);
    }

    public void hand() {
        System.out.println(&quot;앞발을 올립니다.&quot;);
    }
}
public class UpCastingDownCasting {
    public static void main(String[] args) {

        Animal upcasting;
        Dog dog = new Dog();

        upcasting = dog;

        // 다운캐스팅(downcasting)
        Dog downCasting = (Dog) upcasting; // 캐스팅 연산자 생략 불가능...
        downCasting.bark();
        downCasting.hand();

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;184&quot; data-origin-height=&quot;72&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWCQ7K/btsHDd43KRS/fZ1sWMy6OwG881xCfFR3Vk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWCQ7K/btsHDd43KRS/fZ1sWMy6OwG881xCfFR3Vk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWCQ7K/btsHDd43KRS/fZ1sWMy6OwG881xCfFR3Vk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWCQ7K%2FbtsHDd43KRS%2FfZ1sWMy6OwG881xCfFR3Vk%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;184&quot; height=&quot;72&quot; data-origin-width=&quot;184&quot; data-origin-height=&quot;72&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;업캐스팅 된 객체 `animal`에서 만일 자식 클래스에만 있는 hand() 메서드를 실행해야 하는 상황이 온다면, 다운 캐스팅을 통해 자식 클래스 타입으로 회귀시킨 뒤 메서드를 실행하면 된다. 만일 메서드를 한 번만 실행할 것이라 따로 변수에 저장해 둘 필요성이 없다면, 아래와 같이 다운 캐스팅을 한 줄로 표현할 수도 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716810904807&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;((Dog) upcasting).hand()&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이때 캐스팅 연산자를 업캐스팅과 달리 생략할 수 없는데, 나름의 이유가 있기 때문이다. 다운캐스팅은 곧 사용할 수 있는 객체 멤버 증가를 의미하는데, 멤버의 증가는 불분명하다. 왜냐하면 실제 참조변수가 가리키는 객체가 무엇인지 모르기 때문에 어떠한 멤버가 추가되는지 알 수가 없다. 그래서 반드시 형변환 괄호를 기재함으로써 증가된 클래스의 멤버가 무엇이었는지 개발자에게 명확히 알려야 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;다운 캐스팅 주의점&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;앞서 다운 캐스팅의 목적은 업캐스팅한 객체를 되돌리는 데 있다고 했다. 그래서 다음과 같이 업캐스팅되지 않은 부모 객체 `animal`일 경우, 이를 그대로 `(Dog) animal` 로 다운캐스팅하면 오류(ClassCastException)가 발생한다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716811622361&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Animal animal = new Animal();

// 다운캐스팅 예외
Dog downCasting_error = (Dog) animal; //! RUNTIME ERROR
animal.bark();	//! RUNTIME ERROR	
animal.hand();	//! COMPILE ERROR&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;101&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dEAj9Z/btsHDzGTvft/IIbKLJklT4zZ2lVTH0qx3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dEAj9Z/btsHDzGTvft/IIbKLJklT4zZ2lVTH0qx3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dEAj9Z/btsHDzGTvft/IIbKLJklT4zZ2lVTH0qx3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdEAj9Z%2FbtsHDzGTvft%2FIIbKLJklT4zZ2lVTH0qx3k%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;850&quot; height=&quot;101&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;101&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;위와 같은 다운 캐스팅 특성에 대해 특히 주의해야 할 이유는 에디터에서 컴파일 에러가 발생하지 않고, 런타임 에러가 발생하는 위험성 때문이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 기본형 캐스팅은 값의 손실만 있을 뿐 프로그램이 작동하는 데는 문제가 없다.((int) 3.16 -&amp;gt; 3)&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 다운 캐스팅은 에디터에서는 빨간 줄이 없는데 코드를 실행 도중 갑자기 에러가 터지기 때문에 프로그램이 중간에 죽어버릴 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;481&quot; data-origin-height=&quot;148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCKveQ/btsHDW2NDXJ/fKLoWSR0dJcdlE9xw2dOn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCKveQ/btsHDW2NDXJ/fKLoWSR0dJcdlE9xw2dOn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCKveQ/btsHDW2NDXJ/fKLoWSR0dJcdlE9xw2dOn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCKveQ%2FbtsHDW2NDXJ%2FfKLoWSR0dJcdlE9xw2dOn0%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;481&quot; height=&quot;148&quot; data-origin-width=&quot;481&quot; data-origin-height=&quot;148&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그나마 다행히 `hand()`는 컴파일 에러를 띄어준다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이처럼 무분별한 다운캐스팅은 컴파일 시점에는 오류가 발생하지 않아도 런타임 오류를 발생시킬 가능성이 있다. 따라서 다운 캐스팅을 다룰 때는 다운캐스팅할 객체가 오리지널 부모 객체인지, 업캐스팅된 부모 객체인지 항상 머릿속에서 생각해 볼 필요가 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다행스럽게도 혼동되는 객체를 구별하기 위해 도움을 주는 연산자를 자바에서 지원해 준다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffc9af;&quot;&gt;instanceof 연산자&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;최대한 다운캐스팅을 하지 않으며 코드를 짜는 게 가장 좋겠지만, 이미 다운캐스팅이 많이 되었다면 instanceof 가 최선의 방법이 될 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;`instanceof` 연산자는 어는 객체 변수가 어느 클래스 타입인지 판별해 true/false를 반환해 준다. 사용 시 주의할 점은 `instanceof` 연산자는 객체에 대한 클래스(참조형) 타입에만 사용할 수 있다는 점이다. int, double 같은 primitive 타입에는 사용할 수 없다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1716812595222&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Animal {
    //...
}

class Dog extends Animal {
    //...
}

public class UpCastingDownCasting {
    public static void main(String[] args) {

        // 업캐스팅 유무
        Dog dog = new Dog();

        if (dog instanceof Animal) {
            System.out.println(&quot;업캐스팅 가능&quot;);
            Animal upcasting = dog;
        } else {
            System.out.println(&quot;업캐스팅 불가능&quot;);
        }

        // 다운캐스팅 유무
        Animal animal1 = new Animal();
        Animal animal2 = new Dog();

        if (animal1 instanceof Dog) {
            System.out.println(&quot;다운캐스팅 가능&quot;);
            Dog dog1 = (Dog) animal1;
        } else {
            System.out.println(&quot;다운캐스팅 불가능&quot;);
        }

        if (animal2 instanceof Dog) {
            System.out.println(&quot;다운캐스팅 가능&quot;);
            Dog dog2 = (Dog) animal2;
        } else {
            System.out.println(&quot;다운캐스팅 불가능&quot;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;참고&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%97%85%EC%BA%90%EC%8A%A4%ED%8C%85-%EB%8B%A4%EC%9A%B4%EC%BA%90%EC%8A%A4%ED%8C%85-%ED%95%9C%EB%B0%A9-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://inpa.tistory.com&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1716812622455&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;☕ JAVA 업캐스팅 &amp;amp; 다운캐스팅 - 완벽 이해하기&quot; data-og-description=&quot;자바의 참조형 캐스팅 하나의 데이터 타입을 다른 타입으로 바꾸는 것을 타입 변환 혹은 형변환(캐스팅) 이라고 한다. 자바의 데이터형을 알아보면 크게 두가지로 나뉘게 된다. 기본형(primitive ty&quot; data-og-host=&quot;inpa.tistory.com&quot; data-og-source-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%97%85%EC%BA%90%EC%8A%A4%ED%8C%85-%EB%8B%A4%EC%9A%B4%EC%BA%90%EC%8A%A4%ED%8C%85-%ED%95%9C%EB%B0%A9-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; data-og-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%97%85%EC%BA%90%EC%8A%A4%ED%8C%85-%EB%8B%A4%EC%9A%B4%EC%BA%90%EC%8A%A4%ED%8C%85-%ED%95%9C%EB%B0%A9-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cwBJZC/hyWdtcPkU1/lqyWOgsZuVusBntg7DbWXk/img.jpg?width=800&amp;amp;height=447&amp;amp;face=0_0_800_447,https://scrap.kakaocdn.net/dn/cxOymb/hyWdoP7sJf/deDKWJqHMIOG81H6KhE6Q0/img.jpg?width=800&amp;amp;height=447&amp;amp;face=0_0_800_447,https://scrap.kakaocdn.net/dn/boFFgS/hyV9Phv1Zp/v5qqFFpovu3hqFiaonpkO0/img.png?width=883&amp;amp;height=669&amp;amp;face=0_0_883_669&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%97%85%EC%BA%90%EC%8A%A4%ED%8C%85-%EB%8B%A4%EC%9A%B4%EC%BA%90%EC%8A%A4%ED%8C%85-%ED%95%9C%EB%B0%A9-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%97%85%EC%BA%90%EC%8A%A4%ED%8C%85-%EB%8B%A4%EC%9A%B4%EC%BA%90%EC%8A%A4%ED%8C%85-%ED%95%9C%EB%B0%A9-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cwBJZC/hyWdtcPkU1/lqyWOgsZuVusBntg7DbWXk/img.jpg?width=800&amp;amp;height=447&amp;amp;face=0_0_800_447,https://scrap.kakaocdn.net/dn/cxOymb/hyWdoP7sJf/deDKWJqHMIOG81H6KhE6Q0/img.jpg?width=800&amp;amp;height=447&amp;amp;face=0_0_800_447,https://scrap.kakaocdn.net/dn/boFFgS/hyV9Phv1Zp/v5qqFFpovu3hqFiaonpkO0/img.png?width=883&amp;amp;height=669&amp;amp;face=0_0_883_669');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;☕ JAVA 업캐스팅 &amp;amp; 다운캐스팅 - 완벽 이해하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자바의 참조형 캐스팅 하나의 데이터 타입을 다른 타입으로 바꾸는 것을 타입 변환 혹은 형변환(캐스팅) 이라고 한다. 자바의 데이터형을 알아보면 크게 두가지로 나뉘게 된다. 기본형(primitive ty&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;inpa.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/Songwonseok/CS-Study/blob/main/Language/Java/Casting.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/Songwonseok&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1716812633120&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;CS-Study/Language/Java/Casting.md at main &amp;middot; Songwonseok/CS-Study&quot; data-og-description=&quot;면접 대비 CS 스터디(+알고리즘). Contribute to Songwonseok/CS-Study development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Songwonseok/CS-Study/blob/main/Language/Java/Casting.md&quot; data-og-url=&quot;https://github.com/Songwonseok/CS-Study/blob/main/Language/Java/Casting.md&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/pkPyC/hyWdezXOvS/4nMJjkcuAtQlK8L4LBAn61/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/EmOn1/hyV9WVhYQ9/2TctkfHnUJDT3HWhRVQ1WK/img.png?width=1008&amp;amp;height=548&amp;amp;face=0_0_1008_548,https://scrap.kakaocdn.net/dn/bJ5QhQ/hyWdjuvZ96/oXB5MevaDMuzpmAQZs3g20/img.png?width=1008&amp;amp;height=548&amp;amp;face=0_0_1008_548&quot;&gt;&lt;a href=&quot;https://github.com/Songwonseok/CS-Study/blob/main/Language/Java/Casting.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Songwonseok/CS-Study/blob/main/Language/Java/Casting.md&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/pkPyC/hyWdezXOvS/4nMJjkcuAtQlK8L4LBAn61/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/EmOn1/hyV9WVhYQ9/2TctkfHnUJDT3HWhRVQ1WK/img.png?width=1008&amp;amp;height=548&amp;amp;face=0_0_1008_548,https://scrap.kakaocdn.net/dn/bJ5QhQ/hyWdjuvZ96/oXB5MevaDMuzpmAQZs3g20/img.png?width=1008&amp;amp;height=548&amp;amp;face=0_0_1008_548');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;CS-Study/Language/Java/Casting.md at main &amp;middot; Songwonseok/CS-Study&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;면접 대비 CS 스터디(+알고리즘). Contribute to Songwonseok/CS-Study development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/자바</category>
      <author>진막</author>
      <guid isPermaLink="true">https://jinmak.tistory.com/47</guid>
      <comments>https://jinmak.tistory.com/47#entry47comment</comments>
      <pubDate>Tue, 28 May 2024 09:57:52 +0900</pubDate>
    </item>
    <item>
      <title>자바 - 익명 클래스(Anonymous Class)</title>
      <link>https://jinmak.tistory.com/42</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;자바&amp;nbsp;-&amp;nbsp;익명&amp;nbsp;클래스(Anonymous&amp;nbsp;Class)&lt;/span&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;익명 클래스는 내부 클래스(Inner Class)의 일종으로 단어 그대로 이름이 없는 클래스를 말한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이름이 없다는 것은 굳이 기억하지 않아도 된다는 것이며, 한 번 쓰고 말 것이라는 의도를 내포한다. 다시 말해 프로그램에서 일시적으로 한 번만 쓰고 버릴 것이니 공들여 이름 붙힐 필요가 없는 클래스다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;보통 어느 클래스의 자원을 상속 받아 재정의하여 사용하려면 먼저 자식이 될 클래스를 만들고 상속(extends) 후에 해당 클래스를 인스턴스화한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712384936214&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 부모 클래스
class Animal {
    public String bark() {
        return &quot;동물이 웁니다&quot;;
    }
}

// 자식 클래스
class Dog extends Animal {
    @Override public String bark() {
        return &quot;개가 짖습니다.&quot;;
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a = new Dog();
        a.bark();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;익명 클래스는 클래스 정의와 동시에 객체를 생성할 수 있다&lt;/span&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따로 클래스 정의없이 메서드 내에서 바로 클래스를 생성해 인스턴스화 할 수 있으며, 이렇게 클래스의 선언과 동시에 객체를 생성하기 때문에 단 한 번만 사용될 수 있고, 익명으로 정의된 클래스는 한 번 쓰고 바로 버려진다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 만일 어느 메서드에서 부모 클래스의 자원을 상속 받아 재정의하여 사용할 자식 클래스가 나중에 쓰이지 않을 것으로 예상된다면, 굳이 클래스를 정의하기보다 익명 클래스로 정의하고 익명 클래스의 역할이 끝나면 저장된 값을 바로 삭제해주는 것이 메모리 관리 측면에서도 유지 보수 측면에서도 유리할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712386902818&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 부모 클래스
class Animal {
    public String bark() {
        return &quot;동물이 짖는다&quot;;
    }
}

public class Main {
    public static void main(String[] args) {
        // 익명 클래스 정의 : 클래스 정의와 객체화를 동시에.
        Animal dog = new Animal() {
            @Override
            public String bark() {
                return &quot;야 어디서 개짖는 소리 좀 안나게 해라!&quot;
            }
        }; // 단 익명 클래스는 끝에 세미콜론을 붙여 statement임을 명시해야 한다.
        
        // 익명 클래스 객체 사용
        dog.bark();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;익명 클래스는 재사용할 필요가 없는 일회성 클래스를 굳이 클래스를 정의하고 생성하기가 너무 귀찮기 때문에, 익명 클래스를 통해 코드를 줄이는 일종의 꼼수같은 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 익명 클래스는 UI 이벤트처리, 스레드 처리 등 단발성 이벤트 처리에 자주 사용된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;익명 클래스의 장점&lt;/span&gt;&lt;/h3&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;간결성&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;익명 클래스는 이어 배울 람다 함수에 토대가 되는 클래스이다. 따라서 람다 함수의 장점은 곧 익명 클래스의 장점이라고도 할 수 있다. 익명 클래스는 위에서 언급했듯이 클래스를 별도로 선언할 필요 없이, 필요한 구현 부분만 직접 작성할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;즉시 사용 가능&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;익명 클래스는 선언과 동시에 인스턴스화되므로, 작성 즉시 사용할 수 있다. 이는 특히 이벤트 처리나 콜벡 메소드 구현 매우 유용하다. 익명 클래스는 특정한 맥락에서 개발 속도를 높이고, 더 빠르게 동적인 기능을 구현할 수 있게 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;익명 클래스의 단점&lt;/span&gt;&lt;/h3&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;재사용성 부족&amp;nbsp;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;익명 클래스는 애초에 재사용하지 않는 클래스를 한 번만 쓰고 버리기 위해 만들어진 클래스이다. 따라서 재사용이 필요할 것으로 예상되는 기능을 익명 클래스로 구현하는 행동은 의미가 없다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;가독성 저하&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;복잡한 로직이나 긴 구현이 필요한 경우, 익명 클래스는 코드의 가독성을 저하시킬 수 있다. 익명 클래스 내부에 긴 코드 블록이나 복잡한 로직이 포함되면, 코드를 이해하고 유지보수하는 데 어려움이 생긴다. 따라서 무작정 익명 클래스를 사용한다면 주말에도 유지 보수를 해야할 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;익명 클래스는 완전히 새로운 클래스를 익명으로 사용하는 것이 아니다. 이미 정의되어 있는 클래스의 멤버들을 재정의하여 사용할 필요가 있지만 한 번 사용하고 말 것 같다면 그 클래스를 익명으로 받아 사용하는 것이다.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;또한 익명 클래스는 이름이 없기 때문에 생성자를 가질 수 없으며, 가질 필요도 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;익명 클래스 유의점&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다만 주의해야할 점이 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이전에 배웠던 자식 클래스의 부모 클래스 상속을 기억해보자. 기존의 부모 클래스를 상속한 자식 클래스에서는 부모 클래스의 메서드를 재정의할 뿐만 아니라 새로운 메서드를 만들어 사용할 수도 있다는 특징이 있었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 익명 클래스 방식으로 선언한다면&amp;nbsp;&lt;b&gt;오버라이딩 한 메서드를 사용&lt;/b&gt;만 가능하고,&amp;nbsp;&lt;b&gt;새로 정의한 메서드는 외부에서 사용이 불가능&lt;/b&gt;하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712387550406&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Animal {
    public String bark() {
        return &quot;동물이 웁니다&quot;;
    }
}

public class AnonymousClassNewMethod {
    public static void main(String[] args) {
        Animal dog = new Animal() {
            // @Override 메서드
            public String bark() {
                return &quot;WALL WALL WALL WALL WALL WALL&quot;;
            }

            // 새로운 정의한 메서드
            public String run() {
                return &quot;RUN RUN RUN RUN RUN RUN RUN&quot;;
            }
        };

        dog.bark();
        //dog.run(); // ERROR! - 익명 클래스에서 새로 정의한 메서드는 외부에서 사용 불가능
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;`new Animal() {}` 를 통해서 생성하는 인스턴스는 별도의 클래스가 아닌 Animal 클래스를 상속받는 익명 클래스이다. 부모인 Animal 클래스 자체에는 `run()` 메서드가 선언되어 있지 않기 외부에선 run() 메서드를 호출할 수 없다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;새로 정의한 메서드는 외부 스코프에서는 호출할 수 없고,&amp;nbsp;&lt;b&gt;익명 클래스 내에서만 호출&lt;/b&gt;이 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그럼 실제로 익명 클래스가 어떻게 쓰이는 지 살펴보자. 익명 클래스는 크게 익명 자식 객체와 익명 구현 객체로 나뉘는데, 두 가지는 부모 클래스를 상속 받느냐, 인터페이스를 구현하느냐에 차이가 있을 뿐 구현 방법에는 큰 차이가 없다. 구현 방법은 세 가지로 필드, 로컬 변수, 매개 변수의 값을 사용하는 방법이 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;익명 자식 객체&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;익명 자식 객체는 부모 클래스를 상속받아 다음과 같이 생성된다. 이렇게 생성된 객체는 부모 타입의 필드, 로컬 변수, 매개 변수의 값으로 대입할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714702401931&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new 부모생성자(매개값, ...) {
    //필드
    //메서드
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;중괄호 블록 안의 필드와 메서드는 익명 자식 객체가 가져야할 멤버로, 중괄호 블록 안에서만 사용할 수 있다. 익명 자식 객체는 부모 타입에 대입되므로 부모 타입에 선언된 멤버만 접근할 수 있기 때문이다. 익명 클래스의 목적은 부모 클래스의 메서드를 특별한 케이스에 일회성으로 쓰고 버리는 데 있으르모 중괄호 블록 안에는 주로 부모 메서드를 재정의하는 코드가 온다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다음 예제는 Tire 클래스의 익명 자식 객체를 생성해서 필드, 로컬 변수, 매개변수의 값으로 사용하는 방법을 보여준다. Tire 클래스는 roll() 메서드를 가지고 있지만, 익명 자식 객체는 roll()을 재정의해 실행 내용을 변경한다.(다형성)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;&amp;lt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;Tire&lt;/span&gt; 부모 클래스&amp;gt;&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714702664597&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Tire {
    public void roll() {
        System.out.println(&quot;일반 타이어가 굴러갑니다.&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;&amp;lt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;Car&lt;/span&gt; 클래스&amp;gt;&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714703237858&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Car {
    //필드에 Tire 객체 대입
    private Tire tire1 = new Tire();
    
    //필드에 익명 자식 객체 대입
    private Tire tire2 = new Tire() {
        @Override
        public void roll() {
            System.out.println(&quot;익명 자식 Tire 객체 1이 굴러갑니다.&quot;);
        }
    };
    //메서드(필드 이용)
    public void run1() {
        tire1.roll();
        tire2.roll();
    }
    
    
    //메서드(로컬 변수 이용)
    public void run2() {
        //로컬 변수에 익명 자식 객체 대입
        Tire tire = new Tire() {
            @Override
            public void roll() {
                System.out.println(&quot;익명 자식 Tire 객체 2가 굴러갑니다.&quot;);
            }
        };
        tire.roll();
    }
    
    //메서드(매개변수 이용)
    public void run3(Tire tire) {
        tire.roll();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;&amp;lt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;CarExample&lt;/span&gt; 메인 클래스&amp;gt;&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714703609773&quot; class=&quot;arduino&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class CarExample {
    public static void main(String[] args) {
        //Car 객체 생성
        Car car = new Car();
        
        //익명 자식 객체가 대입된 필드 사용
        car.run1();
        
        //익명 자식 객체가 대입된 로컬변수 사용
        car.run2();
        
        //익명 자식 객체가 대입된 매개변수 사용
        car.run3(new Tire() {
            @Override
            public void roll() {
                System.out.println(&quot;익명 자식 Tire 객체 3이 굴러갑니다.&quot;);
            }
        });
    }
}&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;익명 구현 객체&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;익명 구현 객체는 인터페이스를 구현해서 다음과 같이 생성된다. 이렇게 생성된 객체는 인터페이스 타입의 필드, 로컬변수, 매개변수의 값으로 대입할 수 있다. 위에서 언급했듯이 익명 구현 객체는 안드로이드와 같은 UI 프로그램에서 이벤트를 처리하는 객체로 많이 사용된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714703710163&quot; class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;new 인터페이스(매개값, ...) {
    //필드
    //메서드
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;중괄호 블록 안의 필드와 메서드는 익명 구현 객체가 가져야 할 멤버로, 중괄호 블록 안에서만 사용할 수 있다. 그 이유는 익명 구현 객체는 인터페이스 타입에 대입되므로 인터페이스 타입에 선언된 멤버만 접근할 수 있기 때문이다. 중괄호 블록 안에는 익명 자식 객체와 마찬가지로 인터페이스의 추상 메서드를 재정의하는 코드가 온다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다음 예제는 RemoteControl 인터페이스의 익명 구현 객체를 생성해서 필드, 로컬 변수, 매개변수 값으로 사용하는 방법을 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;&amp;lt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;RemoteControl&lt;/span&gt;&lt;span&gt; 인터페이스&lt;/span&gt;&amp;gt;&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714703867082&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public interface RemoteControl {
    //추상 메서드
    void turnOn();
    void turnOff();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;&amp;lt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;Home&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;클래스&amp;gt;&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714703867083&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Home {
    //필드에 익명 구현 객체 대입
    private RemoteControl rc = new RemoteControl() {
        @Override
        public void turnOn() {
            System.out.println(&quot;TV를 켭니다.&quot;);
        }
        @Override
        public void turnOff() {
            System.out.println(&quot;TV를 끕니다.&quot;);
        }
    };
    //메서드(필드 이용)
    public void use1() {
        rc.turnOn();
        rc.turnOff();
    }
    
    
    //메서드(로컬 변수 이용)
    public void use2() {
        //로컬 변수에 익명 구현 객체 대입
        RemoteControl rc = new RemoteControl() {
            @Override
            public void turnOn() {
                System.out.println(&quot;에어컨을 켭니다.&quot;);
            }
            @Override
            public void turnOff() {
                System.out.println(&quot;에어컨을 끕니다.&quot;);
            }
        };
        rc.turnOn();
        rc.turnOff();
    }
    
    //메서드(매개변수 이용)
    public void use3(RemoteControl rc) {
        rc.turnOn();
        rc.turnOff();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;&amp;lt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;HomeExample&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;메인 클래스&amp;gt;&amp;gt;&lt;/p&gt;
&lt;pre id=&quot;code_1714703867084&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class HomeExample {
    public static void main(String[] args) {
        //Home 객체 생성
        Home home = new Home();
        
        //익명 구현 객체가 대입된 필드 사용
        home.use1();
        
        //익명 자식 객체가 대입된 로컬변수 사용
        home.use2();
        
        //익명 자식 객체가 대입된 매개변수 사용
        home.use3(new RemoteControl() {
            @Override
            public void turnOn() {
                System.out.println(&quot;난방을 켭니다.&quot;);
            }
            @Override
            public void turnOn() {
                System.out.println(&quot;난방을 끕니다.&quot;);
            }
        });
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;익명 객체와 람다 표현식&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;익명 클래스 기법은 길고 복잡한 자바 문법을 간결하게 하는 것에 초점을 둔다. 그래서 java8의 람다식 문법과 매우 잘 어울린다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 다음과 같은 익명 구현 객체를 람다식을 이용해 획기적으로 코드를 줄일 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714705351904&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//익명 구현 객체
Operate operate = new Operate() {
    public int operate(int a, int b) {
        return a + b;
    }
};

// 람다식으로 줄이기
Operate operate = (a, b) -&amp;gt; {
    return a + b;
);

// 더 짧게 줄이기 (리턴 코드만 있다면 생략 가능)
Operate operate = (a, b) -&amp;gt; a + b;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 람다식 표현의 익명 구현 객체는 항상 만들 수 있는 것은 아니고 2가지 제약이 따른다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;인터페이스로만 만들 수 있다.&lt;/li&gt;
&lt;li&gt;하나의 추상 메서드만 선언되어 있는 인터페이스만 가능하다. (단, defalut 메서드는 제외)&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 두 개 이상의 추상 메서드가 정의되어 있는 인터페이스 같은 경우 기존의 방식대로 가독성이 좋지 않아도 사용하여야 한다. 단 default 메서드는 추상 메서드가 아니기 때문에 예외로 친다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714705879046&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface Operate {
    //추상 메서드가 하나이다.
    int operate(int a, int b);
    
    // default 메서드는 추상 메서드에 포함되지 않는다.
    default void print() {
        System.out.print(&quot;출력&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1714705950106&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Operate operate = (a, b) -&amp;gt; {
    print();
    return a + b;
};&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://curiousjinan.tistory.com/entry/java-anonymous-class&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://curiousjinan.tistory.com/entry/java-anonymous-class&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1714706055145&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Java] 익명 클래스 (Anonymous Class)란?&quot; data-og-description=&quot;이번 포스트에서는 익명 클래스에 대해서 알아보자   서론 Java의 익명 클래스는 주로 단순한 인터페이스 구현이나 추상 클래스 확장에 사용되는데, 이를 잘 활용하면 코드를 더 간결하고 명확&quot; data-og-host=&quot;curiousjinan.tistory.com&quot; data-og-source-url=&quot;https://curiousjinan.tistory.com/entry/java-anonymous-class&quot; data-og-url=&quot;https://curiousjinan.tistory.com/entry/java-anonymous-class&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dW6CPq/hyVZj9JAeI/XkORmwpaKxPnZCVkIdSMU1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Il5ZF/hyVZr7MDmZ/ZITaX86TMvQikpyROzp5W0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://curiousjinan.tistory.com/entry/java-anonymous-class&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://curiousjinan.tistory.com/entry/java-anonymous-class&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dW6CPq/hyVZj9JAeI/XkORmwpaKxPnZCVkIdSMU1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Il5ZF/hyVZr7MDmZ/ZITaX86TMvQikpyROzp5W0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Java] 익명 클래스 (Anonymous Class)란?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 포스트에서는 익명 클래스에 대해서 알아보자   서론 Java의 익명 클래스는 주로 단순한 인터페이스 구현이나 추상 클래스 확장에 사용되는데, 이를 잘 활용하면 코드를 더 간결하고 명확&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;curiousjinan.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B5%EB%AA%85-%ED%81%B4%EB%9E%98%EC%8A%A4Anonymous-Class-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EA%B8%B0#%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4_%EC%9D%B5%EB%AA%85_%EA%B5%AC%ED%98%84_%EA%B0%9D%EC%B2%B4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://inpa.tistory.com&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1714706075445&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;☕ 익명 클래스(Anonymous Class) 사용법 총정리&quot; data-og-description=&quot;익명 클래스 (Anonymous Class) 익명 클래스는 내부 클래스(Inner class) 일종으로 단어 그대로 이름이 없는 클래스를 말한다. 익명, 이름이 없다는 것은 별로 기억되지 않아도 된다는 것이며, 나중에 다&quot; data-og-host=&quot;inpa.tistory.com&quot; data-og-source-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B5%EB%AA%85-%ED%81%B4%EB%9E%98%EC%8A%A4Anonymous-Class-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EA%B8%B0#%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4_%EC%9D%B5%EB%AA%85_%EA%B5%AC%ED%98%84_%EA%B0%9D%EC%B2%B4&quot; data-og-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B5%EB%AA%85-%ED%81%B4%EB%9E%98%EC%8A%A4Anonymous-Class-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EA%B8%B0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bK1ZDy/hyVZsZTQ36/ahaokNTFjuBY8QCHzvd0SK/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/ddKGrx/hyVZhxkZKR/k0ULpbwWQDTZnuJBt5o3I0/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/bIAif5/hyVZtkcQ8H/scHk0aEc3ORfcAK7YKkRY0/img.png?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B5%EB%AA%85-%ED%81%B4%EB%9E%98%EC%8A%A4Anonymous-Class-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EA%B8%B0#%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4_%EC%9D%B5%EB%AA%85_%EA%B5%AC%ED%98%84_%EA%B0%9D%EC%B2%B4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B5%EB%AA%85-%ED%81%B4%EB%9E%98%EC%8A%A4Anonymous-Class-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EA%B8%B0#%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4_%EC%9D%B5%EB%AA%85_%EA%B5%AC%ED%98%84_%EA%B0%9D%EC%B2%B4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bK1ZDy/hyVZsZTQ36/ahaokNTFjuBY8QCHzvd0SK/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/ddKGrx/hyVZhxkZKR/k0ULpbwWQDTZnuJBt5o3I0/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/bIAif5/hyVZtkcQ8H/scHk0aEc3ORfcAK7YKkRY0/img.png?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;☕ 익명 클래스(Anonymous Class) 사용법 총정리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;익명 클래스 (Anonymous Class) 익명 클래스는 내부 클래스(Inner class) 일종으로 단어 그대로 이름이 없는 클래스를 말한다. 익명, 이름이 없다는 것은 별로 기억되지 않아도 된다는 것이며, 나중에 다&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;inpa.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(신용권, 임경균, 이것이 자바다, 한빛미디어, 2015, pp. 413 ~ 419)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;934&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTMgmt/btsG7ZTydxM/CNybIohnqgb9xPKe1O1h2k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTMgmt/btsG7ZTydxM/CNybIohnqgb9xPKe1O1h2k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTMgmt/btsG7ZTydxM/CNybIohnqgb9xPKe1O1h2k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTMgmt%2FbtsG7ZTydxM%2FCNybIohnqgb9xPKe1O1h2k%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;200&quot; height=&quot;257&quot; data-origin-width=&quot;934&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>백엔드/자바</category>
      <author>진막</author>
      <guid isPermaLink="true">https://jinmak.tistory.com/42</guid>
      <comments>https://jinmak.tistory.com/42#entry42comment</comments>
      <pubDate>Fri, 3 May 2024 12:23:09 +0900</pubDate>
    </item>
    <item>
      <title>게시판 항해 일지 #8 - 게시판 설계 작업</title>
      <link>https://jinmak.tistory.com/35</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;게시판&amp;nbsp;항해&amp;nbsp;일지&amp;nbsp;#8&amp;nbsp;-&amp;nbsp;게시판&amp;nbsp;설계&amp;nbsp;작업&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;약 한 달 동안 졸업 작품, 중간 고사, 정처기 시험 때문에 블로그를 관리할 시간이 없었다. 운동하다가 발목도 아작이 나는 바람에 여러모로 활동성이 제한되어 지금 생각해보면 어거지로 위 세 가지를 마무리 지은 것 같다. 이제 시험도 끝났으니 좀 더 홀가분한 마음으로 코딩 공부를 할 수 있을 것 같다. 문제는 오랜만에 들어와서인지 그동안 공부했던 게 살짝 흐릿해졌고, 블로그 설계 작업도 어디서부터 해야할 지 막막하다는 것이다. 그래서 지금 내가 어디까지 했고 무엇을 해야하는 지를 좀 정리해보려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 자바 관련 포스팅은 무엇을 했나. 포스팅이라고는 이 블로그는 나의 노트 같은 것이다. 이번에 정처기 공부를 하면서 느낀 바는 이미 정리된 자료가 있으니 확실히 노트 필기하기가 편하다는 점이다. 대학 친구 중에 회계사 공부를 하는 친구가 있는데 회계사 공부와 같은 고시 공부는 이미 모든 내용이 정해져 있으니 노트 필기가 공부하는 데 유리할 것이다. 정처기 시험도 이미 내용이 정리되어 있고 그 내용을 알기만 하면 되니까 노트 필기가 편할 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 코딩을 공부할 때는 아무래도 노트보단 블로그에 정리하는게 훨씬 더 편하고 내용도 잘 이해된다. 왜냐하면 코딩 공부의 특성상 코드를 쓸 일이 많고, 수정이 빈번하게 일어나기 때문이다. 코딩도 처음 공부할 때는 노트에 일일히 개념을 적으면서 공부했다. 하지만 첫 번째 문제는 코드를 일일히 쓰는게 불편하다는 점이고, 두 번째는 수정할 때마다 지우개로 개념을 지우거나 새로운 페이지에 적어야 한다는 점이 귀찮았다. 그래서 블로그에 정리를 하기 시작했는데 노트 필기에 익숙한 사람이 블로그에 글을 써서 정리하려고 하니까 처음에는 개념이 이해도 잘 안되고 불편하기만 했는데, 어느 정도 계속 하다보니까 확실히 이게 더 편해지고 공부도 더 잘된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;갑자기 얘기가 이상한데로 빠졌지만 다시 돌아와서 무엇을 했는지 정리해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터 과학&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.02.29 - [분류 전체보기] - 컴퓨터 과학 - XML, JSON, YAML&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.06 - [분류 전체보기] - 컴퓨터 과학 - 컴퓨터의 구성(CPU, 메모리, 보조기억장치, 입출력장치)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/10&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.11 - [분류 전체보기] - 자바 - JVM(자바의 동작 과정)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.13 - [분류 전체보기] - 자바 - 코드의 구조&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/13&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.13 - [분류 전체보기] - 자바 - 자바 변수의 자료형(Data Type)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/14&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.14 - [분류 전체보기] - 자바 - 래퍼 클래스(Wrapper Class)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/16&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.15 - [분류 전체보기] - 자바 - 객체 지향 프로그래밍의 4가지 특징(추상화, 상속, 다형성, 캡슐화)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/17&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.19 - [분류 전체보기] - 자바 - 클래스(인스턴스, 필드, 메서드, 생성자)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/19&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.20 - [분류 전체보기] - 자바 - 상속(Inheritance)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/21&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.26 - [분류 전체보기] - 자바 - 추상 클래스(abstract class)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/25&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.27 - [분류 전체보기] - 자바 - 인터페이스(Interface)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/26&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.28 - [분류 전체보기] - 자바 - 추상 클래스 vs 인터페이스&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/33&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.04.05 - [분류 전체보기] - 자바 - 내부 클래스(Inner Class)&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알고리즘&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.02.28 - [분류 전체보기] - 알고리즘 - 트라이(Trie)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>이것저것</category>
      <author>진막</author>
      <guid isPermaLink="true">https://jinmak.tistory.com/35</guid>
      <comments>https://jinmak.tistory.com/35#entry35comment</comments>
      <pubDate>Mon, 29 Apr 2024 14:06:30 +0900</pubDate>
    </item>
    <item>
      <title>자바 - 내부 클래스(Inner Class)</title>
      <link>https://jinmak.tistory.com/33</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;내부 클래스 (Inner Class)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;내부 클래스 (inner class)란 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;하나의 클래스 내부에 선언된 또 다른 클래스를 의미&lt;/span&gt;한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;보통 사용자 클래스 자료형이 필요하면, 메인 클래스 외부에 선언하거나, 따로 독립적인 클래스 파일을 만들어 불러와 사용해 왔다. 내부 클래스는 기존에 사용했던 방법 대신 클래스 내부에 선언해 사용할 수 있다. 하지만 사실 내부 클래스는 내부에 정의된다는 점을 제외하고는 일반적인 클래스와 다르지 않다. 우리가 어느 클래스에 변수나 상수가 필요하다면 클래스 멤버로서 클래스 내에 선언하여 사용해 왔듯이, 클래스도 마찬가지로 변수처럼 사용해 주면 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;내부 클래스는 보통 두 클래스가 서로 긴밀한 관계에 있거나, 하나의 클래스 또는 메서드에서만 사용되는 클래스일 때 사용할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekAPoV/btsGl0TsqKl/nMXYfRT92WkkW9ktzPtAxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekAPoV/btsGl0TsqKl/nMXYfRT92WkkW9ktzPtAxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekAPoV/btsGl0TsqKl/nMXYfRT92WkkW9ktzPtAxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FekAPoV%2FbtsGl0TsqKl%2FnMXYfRT92WkkW9ktzPtAxk%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;393&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;608&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이 글에선 내부 클래스를 설명하기 위해 내부 클래스를 감싸고, 내부 클래스를 제외한 클래스를 외부 클래스라고 부르도록 하겠다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712229969240&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Creature 클래스는 내부 클래스들의 외부 클래스
class Creature {
    int life;
    
    //Animal 클래스는 Creature 클래스의 내부 클래스
    class Animal { ... }
    
    //Insect 클래스는 Creature 클래스의 내부 클래스
    class Insect { ... }
    
    public void method() {
        Animal animal = new Animal();
        Insect insect = new Insect();
        // ...
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;내부 클래스의 종류&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;내부 클래스에는 아래와 같이 총 네 가지가 있는데, 중점적으로 봐야 할 클래스는 static 클래스와 익명 클래스이다.&lt;br /&gt;나중에 배우지만 static 클래스는 디자인 패턴에서 싱글톤 패턴과 Holder 패턴에서 쓰이는 기법 중 하나이고, 익명 클래스는 자바8부터 나온 람다 표현식의 기본 골자이기 때문이다.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;인스턴스 클래스(instance class)&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;외부 클래스의 멤버변수 선언 위치에 선언하며, 외부 클래스의 인스턴스 멤버처럼 다뤄진다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적으로 선언된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;스태틱 내부 클래스(nested class)&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;외부 클래스의 멤버변수 선언 위치에 선언하며, 외부 클래스의 static 멤버처럼 다뤄진다. 다만 주의할 점은 static이라고 해서 new 생성자 초기화를 못하는 것은 아니다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;static class&lt;/span&gt;는 일반적인 static 필드 변수나 static 메서드와 달리 메모리 구조나 기능이 전혀 다르다. 중첩 클래스의 일종이다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;지역 클래스(local class)&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;외부 클래스의 메서드나 초기화블럭 안에 선언하며, 선언된 메서드 블록 영역 내부에서만 사용될 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;익명 클래스(anonymous class)&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;클래스의 선언과 객체의 생성을 동시에 하는 이름 없는 클래스이다. 주로 클래스를 일회용을 사용할 때 자주 이용된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;인스턴스 클래스(instance class)&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; 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;클래스의 멤버 변수 선언부에 위치하고 static 키워드가 없는 내부 클래스&lt;/li&gt;
&lt;li&gt;외부 클래스의 멤버로 취급되기 때문에 외부 클래스의 객체 먼저 생성한 후 내부 클래스의 객체 생성이 가능하다.&lt;/li&gt;
&lt;li&gt;인스턴스 클래스 내부에는 instance 멤버만 선언할 수 있다. (static 멤버는 선언 불가)&lt;/li&gt;
&lt;li&gt;주로 외부 클래스의 인스턴스 멤버들과 관련된 작업에 사용될 목적으로 선언된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1712230841503&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class PocketBall {
    // 인스턴스 변수
    int size = 100;
    int price = 5000;
    
    // 인스턴스 내부 클래스
    class PockeMonster {
        String name = &quot;피카츄&quot;;
        int level = 10;
        
        // static int cost = 100; ERROR! 인스턴스 내부 클래스에는 static 변수를 선언할 수 없다.
        static final int cost = 100; // final static은 상수이므로 허용
        
        public void getPockemonMember() {
            // 별다른 조치없이 외부 클래스 멤버 접근 가능
            System.out.println(size);
            System.out.println(price);   
            
            // 내부 클래스 멤버
            System.out.println(name);
            System.out.println(level);
            System.out.println(cost);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712230985656&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
    
        PocketBall ball = new PocketBall(); //먼저 외부 클래스를 인스턴스화
        //외부클래스.내부클래스 형식으로 초기화하여 사용
        //내부클래스도 외부 클래스의 멤버라고 생각하면 쉽게 이해할 수 있다
        PocketBall.PockMoster pokemon = ball.new PokeMoster(); 
        pokemon.getPokemonMember();
        
        // 위의 단계를 한 줄로 표현
        PocketBall.PokeMonster pokemon2 = new PocketBall().new PokeMonster();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;외부 클래스를 인스턴스화하면 외부 클래스의 코드가 메모리에 올라오게 되고 이때 내부 클래스의 코드도 메모리에 올라오게 된다. 이렇게 외부 클래스의 코드를 먼저 메모리에 올려줘야 내부 클래스의 인스턴스를 생성할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다만 내부 클래스는 다른 클래스에서 직접 사용하는 것보다 해당(외부) 클래스에서만 사용하는 것이 일반적이므로, 위의 메인 코드와 같이 내부 클래스의 인스턴스를 다른 클래스에서 만드는 경우는 드물다. 이렇게 할 수 있다는 것만 알아두자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;이름이 같은 외부 클래스 메서드 호출&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;만일 다음과 같이 내부 클래스에서 외부 클래스와 동일한 메서드명을 사용할 때 외부 클래스의 메서드를 호출하려면 어떻게 해야 할까?&lt;/p&gt;
&lt;pre id=&quot;code_1712231425423&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 외부 클래스
public class Main {
    
    public print(String txt) {
        System.out.println(txt);
    }
    
    // 내부 클래스
    class Sub {
        public print() {}
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;클래스가 상속관계에 있을 때는 super 예약어를 통해 부모 메서드를 호출할 수 있었다. 하지만 외부 - 내부 클래스 관계는 상속 관계가 아니기 때문에 다른 방법으로 외부 클래스의 멤버를 호출해야 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이때 정규화된 this를 사용하면 외부 클래스 인스턴스의 메서드를 호출하거나 외부 클래스 인스턴스의 참조를 가져올 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;정규화된 this란 &quot;클래스명.this&quot;의 형태로 외부 클래스의 이름을 명시하는 용법을 말한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712231695879&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Main {

    public void print(String txt) {
        System.out.println(txt);
    }
    
    class Sub {
        public void print() {
            Main.this.print(&quot;외부 클래스 메서드 호출&quot;);
            System.out.println(&quot;내부 클래스 메서드 호출&quot;);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712231771806&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void main(String[] args) {
    Main.Sub s = new Main().new Sub();
    s.print();
    /*
    외부 클래스 메서드 호출
    외부 클래스 메서드 호출
    */
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;다음에 배울 static 내부 클래스에서는 정규화된 this 문법을 사용할 수 없다.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;인스턴스 클래스 컴파일&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내부 클래스는 클래스 안의 클래스 형태이기 때문에 컴파일 형태가 조금 다르다.&lt;/li&gt;
&lt;li&gt;컴파일 시 생성되는 클래스 파일명은 &quot;[외부클래스]$[내부클래스].class&quot; 형태이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;255&quot; data-origin-height=&quot;129&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LTQ9V/btsGl3ioDXR/wItHTKREtFtDjApKCvIXa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LTQ9V/btsGl3ioDXR/wItHTKREtFtDjApKCvIXa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LTQ9V/btsGl3ioDXR/wItHTKREtFtDjApKCvIXa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLTQ9V%2FbtsGl3ioDXR%2FwItHTKREtFtDjApKCvIXa0%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;255&quot; height=&quot;129&quot; data-origin-width=&quot;255&quot; data-origin-height=&quot;129&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;스태틱 클래스 (static nested class)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;static 키워드가 붙은 내부 클래스&lt;/li&gt;
&lt;li&gt;단, 일반적인 static 필드 변수나 static 메서드와 똑같이 생각하면 안 된다.&lt;/li&gt;
&lt;li&gt;static 클래스 내부에는 instance 멤버와 static 멤버 모두 선언할 수 있다.&lt;/li&gt;
&lt;li&gt;그러나 일반적인 static 메서드와 동일하게 외부 클래스의 인스턴스 멤버에는 접근이 불가하고, 정적(static) 멤버에만 접근할 수&amp;nbsp; 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1712275826316&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class PocketBall {
    int size = 100;
    static int price = 5000;
    
    // static 내부 클래스
    static class PocketMonster {
        static String name = &quot;이상해씨&quot;;
        int level = 10;
        
        public static void getPokeMember() {
            // 외부 클래스 인스턴스 멤버 접근 불가능
            // System.out.println(size);
            
            // 외부 클래스 스태틱 멤버 접근 가능
            System.out.println(price);
            
            // 내부 클래스 멤버도 스태틱 멤버만 접근 가능
            System.out.println(name);
            // System.out.println(level);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712276064415&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        // 스태틱 내부 클래스의 인스턴스는 외부 클래스를 먼저 생성하지 않아도 된다.
        PocketBall.PokeMonster pokemon = new PocketBall.PokeMonster();
        System.out.println(pokemon.level); // 스태틱 내부 클래스도 인스턴스로는 멤버에 접근 가능
        System.out.println(PocketBall.PokeMonster.name);
        
        // 클래스. 정적내부클래스.정적메서드()
        PocketBall.PokeMonster.getPokeMember();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;static 클래스에 대한 오해&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;많은 사람들이 실수하는 오해가 static 클래스가 그 외의 static 필드 변수나 static 메서드와 같이, 'static 이니까 메모리에 한 번 올려놓고 두고두고 사용하는 거겠지?'라고 생각하는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 static 클래스는 키워드가 static이 들어갔을 뿐, 우리가 알던 static 멤버, 메서드와는 다른 녀석이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다음 코드를 보면 static 변수와 내부 인스턴스 클래스 그리고 내부 static 클래스가 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712276948998&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Main {
    // 스태틱 필드 변수
    static Integer num = new Integer(0);
    
    // 내부 인스턴스 클래스
    class InnerClass { ... }
    
    // 내부 스태틱 클래스
    static class InnerStaticClass { ... }
    
    public static void main(String[] args) {
        
        // 스태틱 필드 변수는 유일해서 서로 같다
        Integer num1 = Main.num;
        Integer num2 = Main.num;
        System.out.println(num1 == num2); // true
        
        // 생성된 내부 클래스 인스턴스는 서로 다르다
        Main.InnerClass inner1 = new Main().new InnerClass();
        Main.InnerClass inner2 = new Main().new InnerClass();
        System.out.println(inner1 == inner2); // false
        
        // 생성된 내부 스태틱 클래스 인스턴스는 서로 다르다
        Main.InnerStaticClass static1 = new InnerStaticClass();
        Main.InnerStaticClass static2 = new InnerStaticClass();
        System.out.println(static1 == static2); // false
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이들을 각각 메인 메서드에서 변수로 받아 같은지 다른지 비교해 보면, static 변수는 예상대로 메모리에서 한 번만 생성되어 num1과 num2가 참조하는 데이터가 같다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 내부 static 클래스는 일반 클래스처럼 초기화할 때마다 다른 객체가 만들어지는 것을 볼 수 있다. 위 코드에서 보았듯이 static 클래스는 static이라고 해서 메모리에 한 번만 로드되는 객체의 개념이 아닌 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 static 내부 클래스는 non-static 내부 클래스와 달리 외부 인스턴스를 먼저 선언하지 않아도 바로 내부 클래스의 인스턴스를 바로 생성할 수 있다는 차이점이 존재할 뿐이다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다만 우리가 non-static 내부 클래스 대신 static 클래스를 사용해야 하는 이유는 따로 있는데...&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;내부 클래스는 static 클래스로 선언하자&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;만일 내부 클래스를 이용하는데, 내부 클래스에서 클래스 바깥에 인스턴스를 사용할 일이 없다면 static 클래스로 선언해주어야 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;266&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DltX0/btsGmuUyqop/aSfGfeKL8lgFM0qAKWkUR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DltX0/btsGmuUyqop/aSfGfeKL8lgFM0qAKWkUR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DltX0/btsGmuUyqop/aSfGfeKL8lgFM0qAKWkUR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDltX0%2FbtsGmuUyqop%2FaSfGfeKL8lgFM0qAKWkUR1%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;266&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;266&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;왜냐하면 static이 아닌 내부 인스턴스 클래스는 외부와 연결이 되어 있어 '외부 참조'를 갖게 되어 메모리를 더 먹고, 느리며, 무엇보다 GC의 대상에서 벗어나는 문제점을 일으키기 때문이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이것은 아주 큰 문제이다 (####추가 예정####)&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;static 클래스 컴파일&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;441&quot; data-origin-height=&quot;198&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5rSOI/btsGnCEjd6y/pfGWFk5eBm6B6nCjGGJkKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5rSOI/btsGnCEjd6y/pfGWFk5eBm6B6nCjGGJkKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5rSOI/btsGnCEjd6y/pfGWFk5eBm6B6nCjGGJkKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5rSOI%2FbtsGnCEjd6y%2FpfGWFk5eBm6B6nCjGGJkKk%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;441&quot; height=&quot;198&quot; data-origin-width=&quot;441&quot; data-origin-height=&quot;198&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위의 인스턴스 내부 클래스와 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;로컬 클래스&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메서드 내부에 위치하는 클래스 (지역 변수와 같은 성질을 지님)&lt;/li&gt;
&lt;li&gt;지역 변수처럼 해당 메서드 내부에서만 한정적으로 사용된다. (해당 메서드 실행 외에는 클래스 접근 및 사용 불가)&lt;/li&gt;
&lt;li&gt;접근 제어자와 static을 붙일 수 없다. 메서드 내부에서만 사용되므로 접근을 제한할 필요가 없고, 원래 메서드 내에는 static 멤버를 선언할 수가 없기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1712278150336&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class PocketBall {
    int size = 100;
    int price = 5000;
    
    public void pocketMethod() {
        int exp = 5000;
        
        // 메서드 내에서 클래스를 선언
        class PocketMonster {
            String name = &quot;이상해씨&quot;;
            int level = 10;
            
            public void getPoketLevel() {
                System.out.println(level); // 인스턴스 변수 출력
                System.out.println(exp); // 메서드 지역 상수 출력
            }
        }
        
        // 메서드 내에서 클래스를 선언
        class PocketMonster2 {
            String name = &quot;리자몽&quot;;
            int level = 50;
        }
        
        new PocketMonster().getPoketLevel();
        System.out.println(&quot;메서드 실행 완료&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;메서드 내에서 잠시 사용하는 지역 변수 개념과 같이 지역 클래스 자료형을 사용하고 버리는 것으로 이해하면 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;메서드 내의 모든 내용은 Stack Area에 생성되었다가 메서드 종료 시 사라지게 되므로, 당연히 다른 곳에서는 접근 및 사용 자체가 불가능하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;메서드 내에서 인스턴스를 생성한 후 사용하고 메서드 종료와 함께 레퍼런스가 사라지면서 힙 메모리 영역의 실제 데이터도 나중에 GC(가비지 컬렉터)에 의해 지워지게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;로컬 클래스 지역 상수 접근&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메서드 내의 로컬 클래스에서 지역 변수에 접근해서 값을 사용하려고 할 때는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;final 지역변수&lt;/span&gt;만 사용 가능하다.&lt;/li&gt;
&lt;li&gt;변수에 final을 안 붙여도 실행이 되는 이유는, JDK1.8부터 지역 클래스에서 접근하는 지역 변수 앞에 final을 생략할 수 있기 때문이다. (컴파일러가 자동으로 붙여준다)&lt;/li&gt;
&lt;li&gt;그러나 지역 변수(상수)의 값이 바뀌는 문장이 있으면 이는 상수가 아닌 변수이니, 컴파일 에러가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xBeIc/btsGoQaKDnY/4ddUGSsLffFK3nxKlCvy8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xBeIc/btsGoQaKDnY/4ddUGSsLffFK3nxKlCvy8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xBeIc/btsGoQaKDnY/4ddUGSsLffFK3nxKlCvy8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxBeIc%2FbtsGoQaKDnY%2F4ddUGSsLffFK3nxKlCvy8k%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;790&quot; height=&quot;490&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;로컬 클래스 컴파일&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴파일 시 생성되는 클래스 파일명: &quot;외부클래스$1내부클래스.class&quot;&lt;/li&gt;
&lt;li&gt;지역 클래스는 여러 메서드 내에서 생성이 가능하니 같은 클래스명이 중복될 수 있어 앞에 숫자를 붙여 구분한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;153&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dJpo8n/btsGn0StlSj/OxCgYrZm0FreJNgVVXKp7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dJpo8n/btsGn0StlSj/OxCgYrZm0FreJNgVVXKp7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dJpo8n/btsGn0StlSj/OxCgYrZm0FreJNgVVXKp7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdJpo8n%2FbtsGn0StlSj%2FOxCgYrZm0FreJNgVVXKp7k%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;370&quot; height=&quot;153&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;153&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;익명 클래스&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;익명 클래스는 클래스 이름이 존재하지 않는 내부 클래스이다.&lt;/li&gt;
&lt;li&gt;단 하나의 객체만을 생성하는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;일회용 클래스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;클래스의 선언과 동시에 객체를 생성&lt;/li&gt;
&lt;li&gt;익명 클래스는 생성자가 존재하지 않는다.&lt;/li&gt;
&lt;li&gt;익명 클래스는 기존에 존재하는 클래스를 메서드 내에서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;일회용으로 클래스 내부 구성을 선언하여 필요한 메서드를 재정의하여 사용하는 기법&lt;/span&gt;이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1712279807488&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Anonymous {
    String amIAnonymous();
}

public class InnerClassEx implements Anonymous{
    public static void main(String[] args) {
        // Anonymous 클래스를 일회성으로 익명 클래스로 선언하여 변수 o에 저장
        Anonymous o = new Anonymous() {
            @Override
            public String amIAnonymous() {
                return &quot;아 제가 익명 클래스입니다.&quot;;
            }
        };    // 익명 클래스 뒤에는 반드시 세미콜론을 붙혀줘야 한다.

        // 익명 클래스의 객체의 오버라이딩한 메서드를 사용
        String txt = o.amIAnonymous();
        System.out.println(txt); // 아 제가 익명 클래스입니다.
    }

    @Override
    public String amIAnonymous() {
        return null;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;익명 클래스 컴파일&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;639&quot; data-origin-height=&quot;48&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dHNhRZ/btsGmVYC9eP/PexkuYFXehiKKGk4JRlg50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dHNhRZ/btsGmVYC9eP/PexkuYFXehiKKGk4JRlg50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dHNhRZ/btsGmVYC9eP/PexkuYFXehiKKGk4JRlg50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdHNhRZ%2FbtsGmVYC9eP%2FPexkuYFXehiKKGk4JRlg50%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;639&quot; height=&quot;48&quot; data-origin-width=&quot;639&quot; data-origin-height=&quot;48&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; 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;컴파일 시 생성되는 클래스 파일명 : &quot;외부클래스$1.class&quot;&lt;/li&gt;
&lt;li&gt;익명 클래스이기 때문에 클래스명은 없고 오직 숫자로만 구분한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;내부 클래스의 사용 이유&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;지금까지 네 가지의 내부 클래스를 배웠다. 그런데 정작 내부 클래스를 쓰는 이유에 대해선 알지 못한다. 마지막으로 내부 클래스를 사용하는 이유에 대해서 알아보기 전에 기억해야 할 키워드는 딱 두 가지이다. &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;간결함과 캡슐화&lt;/span&gt;&lt;/b&gt;.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;1. 클래스를 논리적으로 그룹화&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;클래스가 여러 클래스와 관계를 맺지 않고 &lt;b&gt;하나의 특정 클래스와만 관계&lt;/b&gt;를 맺는다면, 외부에 클래스를 새로 작성하는 것이 아닌 내부 클래스로 작성할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이런 경우 내부 클래스와 외부 클래스를 함께 관리하는 것이 가능해 유지보수 면에서나 코드 이해성 면에서 편리해진다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;또한 내부 클래스로 인해 새로운 클래스를 생성하지 않아도 되므로&amp;nbsp;&lt;b&gt;패키지를 간소화&lt;/b&gt;할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;코드를 예시로 들어보자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;평소대로라면 아래처럼 클래스의 바깥이나 다른 파일로 클래스를 선언해 놓고, 인스턴스화하여 사용했을 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712280616994&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Creature {
    int life;

    public void method() {
        Animal animal = new Animal(); // Animal 객체는 오로지 Creature 클래스의 메소드 내에서만 사용된다고 가정 
        // ...
    }
}

// 외부에 선언된 클래스
class Animal {

}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그런데 만일 Animal 클래스 자료형이 오로지 Creature 클래스의 메서드 내에서만 선언되어 사용된다면, Animal 클래스를 Creature 클래스 내부로 넣어줌으로써 보다 코드 자원의 이해도가 높아진다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712280673922&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Creature {
    int life;
	
    // 클래스 멤버 같이 Creature 클래스 안에다 넣어 선언한다.
    class Animal {

    }

    public void method() {
        Animal animal = new Animal(); // Animal 객체는 오로지 Creature 클래스의 메소드 내에서만 사용된다고 가정 
        // ...
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;2. 더욱 타이트한 캡슐화의 적용&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;내부 클래스에 `private` 제어자를 적용해 줌으로써, 캡슐화를 통해 클래스를 내부로 숨길 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 캡슐화를 통해 외부에서의 접근을 차단하면서도, 내부 클래스에서 외부 클래스의 멤버들을 제약 없이 쉽게 접근할 수 있어 구조적인 프로그래밍이 가능해진다. 그리고 클래스 구조를 숨김으로써 코드의 복잡성도 줄일 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712280804562&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Creature {
    private int life = 50;
	
    // private class 로, 오로지 Creature 외부 클래스에서만 접근 가능한 내부 클래스로 설정
    private class Animal {
        private String name = &quot;호랑이&quot;;

        int getOuter() {
            return life; // 외부 클래스의 private 멤버를 제약 없이 접근 가능
        }
    }

    public void method() {
        Animal animal = new Animal(); 

        // Getter 없이 내부 클래스의 private 멤버에 접근이 가능
        System.out.println(animal.name); // 호랑이

        // 내부 클래스에서 외부 클래스이 private 멤버를 출력
        System.out.println(animal.getOuter()); // 50
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;3. 가독성이 좋고 유지 관리가 쉬운 코드&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;결국은 내부 클래스를 작성하는 경우 클래스를 따로 외부에 작성하는 경우보다, 물리적으로도 논리적으로도 외부 클래스에 더 가깝게 위치하게 된다. 따라서 시각적으로 읽기가 편해질 뿐 아니라 유지보수에 있어 이점을 가지게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;한 클래스를 다른 클래스의 내부 클래스로 선언하면 두 클래스 멤버들 간에 서로 자유로이 접근할 수 있고, 외부에선 불필요한 클래스를 감춰 클래스 간의 연관관계를 따지는 것과 같은 코드의 복잡성을 줄일 수 있다는 장점이 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;요는 어차피 A 클래스 안에서만 사용하기 위한 클래스이니 굳이 연관관계를 따질 필요 없이 내부에서 선언해 직관적으로 사용하자는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; 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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4Inner-Class-%EC%9E%A5%EC%A0%90-%EC%A2%85%EB%A5%98&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://inpa.tistory.com&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712281128265&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;☕ 내부 클래스(Inner Class) 장점 &amp;amp; 종류 총정리&quot; data-og-description=&quot;내부 클래스 (Inner Class) 내부 클래스(inner class)란 하나의 클래스 내부에 선언된 또 다른 클래스를 의미한다. 보통 사용자 클래스 자료형이 필요하면, 메인 클래스 외부에 선언하거나, 따로 독립적&quot; data-og-host=&quot;inpa.tistory.com&quot; data-og-source-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4Inner-Class-%EC%9E%A5%EC%A0%90-%EC%A2%85%EB%A5%98&quot; data-og-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4Inner-Class-%EC%9E%A5%EC%A0%90-%EC%A2%85%EB%A5%98&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dx7tjW/hyVJXl3mRv/frg8NC2TFcjklDxKjkhmc1/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/wi65K/hyVJUv6TIO/Q5w3bkMuh10PkpUgnzRWJK/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/ErhIx/hyVJSSAmJ5/cJ6In1vXkaOgiAK9Rfs5P0/img.png?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4Inner-Class-%EC%9E%A5%EC%A0%90-%EC%A2%85%EB%A5%98&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EB%82%B4%EB%B6%80-%ED%81%B4%EB%9E%98%EC%8A%A4Inner-Class-%EC%9E%A5%EC%A0%90-%EC%A2%85%EB%A5%98&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dx7tjW/hyVJXl3mRv/frg8NC2TFcjklDxKjkhmc1/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/wi65K/hyVJUv6TIO/Q5w3bkMuh10PkpUgnzRWJK/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/ErhIx/hyVJSSAmJ5/cJ6In1vXkaOgiAK9Rfs5P0/img.png?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;☕ 내부 클래스(Inner Class) 장점 &amp;amp; 종류 총정리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;내부 클래스 (Inner Class) 내부 클래스(inner class)란 하나의 클래스 내부에 선언된 또 다른 클래스를 의미한다. 보통 사용자 클래스 자료형이 필요하면, 메인 클래스 외부에 선언하거나, 따로 독립적&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;inpa.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/자바</category>
      <author>진막</author>
      <guid isPermaLink="true">https://jinmak.tistory.com/33</guid>
      <comments>https://jinmak.tistory.com/33#entry33comment</comments>
      <pubDate>Fri, 5 Apr 2024 10:43:34 +0900</pubDate>
    </item>
    <item>
      <title>tobi - 독립 실행형 스프링 애플리케이션</title>
      <link>https://jinmak.tistory.com/31</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;459&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sshRT/btsGlvkqMc7/WtRsCamaoBzt33kuB01VE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sshRT/btsGlvkqMc7/WtRsCamaoBzt33kuB01VE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sshRT/btsGlvkqMc7/WtRsCamaoBzt33kuB01VE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsshRT%2FbtsGlvkqMc7%2FWtRsCamaoBzt33kuB01VE1%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;872&quot; height=&quot;459&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;459&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재까지 진행한 것 =&amp;gt; 이제 스프링 컨테이너를 사용해보겠음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1057&quot; data-origin-height=&quot;203&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxhuFC/btsGlVDbXwz/a1KTbLJ4LbMHU9bKUxH6s1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxhuFC/btsGlVDbXwz/a1KTbLJ4LbMHU9bKUxH6s1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxhuFC/btsGlVDbXwz/a1KTbLJ4LbMHU9bKUxH6s1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxhuFC%2FbtsGlVDbXwz%2Fa1KTbLJ4LbMHU9bKUxH6s1%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;1057&quot; height=&quot;203&quot; data-origin-width=&quot;1057&quot; data-origin-height=&quot;203&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;977&quot; data-origin-height=&quot;32&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MojWE/btsGkA0CNTO/K1GXcMBAxjZcjnMkZ66FfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MojWE/btsGkA0CNTO/K1GXcMBAxjZcjnMkZ66FfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MojWE/btsGkA0CNTO/K1GXcMBAxjZcjnMkZ66FfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMojWE%2FbtsGkA0CNTO%2FK1GXcMBAxjZcjnMkZ66FfK%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;977&quot; height=&quot;32&quot; data-origin-width=&quot;977&quot; data-origin-height=&quot;32&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1437&quot; data-origin-height=&quot;637&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oA7V8/btsGiSId8mH/O8WFJHaqo15v5k0nbKmITK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oA7V8/btsGiSId8mH/O8WFJHaqo15v5k0nbKmITK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oA7V8/btsGiSId8mH/O8WFJHaqo15v5k0nbKmITK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoA7V8%2FbtsGiSId8mH%2FO8WFJHaqo15v5k0nbKmITK%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;1437&quot; height=&quot;637&quot; data-origin-width=&quot;1437&quot; data-origin-height=&quot;637&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;485&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l1eiS/btsGiZN5Ad6/nFFzDFFTfle5yAWEk7Qkc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l1eiS/btsGiZN5Ad6/nFFzDFFTfle5yAWEk7Qkc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l1eiS/btsGiZN5Ad6/nFFzDFFTfle5yAWEk7Qkc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl1eiS%2FbtsGiZN5Ad6%2FnFFzDFFTfle5yAWEk7Qkc1%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;1086&quot; height=&quot;485&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;485&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;뭐가 달라짐? 이제 스프링 컨테이너를 사용할 수 있는 기본 구조를 짜놓았음. 스프링 컨테이너는 새로운 오브젝트를 계속 만들지 않고 처음에 만든 Hello Controller 오브젝트를 계속 사용함 =&amp;gt; 싱글톤 레지스트리(싱글톤 패턴을 사용하지 않고도 ㅁ마치 싱글톤 패턴을 사용하는 것처럼)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uXXba/btsGlVwqhFG/WO3Mmso5YRvzklasX7Sp31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uXXba/btsGlVwqhFG/WO3Mmso5YRvzklasX7Sp31/img.png&quot; data-alt=&quot;SimpleHelloService&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uXXba/btsGlVwqhFG/WO3Mmso5YRvzklasX7Sp31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuXXba%2FbtsGlVwqhFG%2FWO3Mmso5YRvzklasX7Sp31%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;460&quot; height=&quot;222&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;222&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;SimpleHelloService&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;277&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgktYS/btsGkATVJ2l/lIURJWe1bKdbuTBpfojZQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgktYS/btsGkATVJ2l/lIURJWe1bKdbuTBpfojZQK/img.png&quot; data-alt=&quot;HelloController&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgktYS/btsGkATVJ2l/lIURJWe1bKdbuTBpfojZQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgktYS%2FbtsGkATVJ2l%2FlIURJWe1bKdbuTBpfojZQK%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;824&quot; height=&quot;277&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;277&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;HelloController&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dependency Injection&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;249&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FoNIi/btsGiAnuoxw/gb1kZUOkqgKAgyGQuqwr91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FoNIi/btsGiAnuoxw/gb1kZUOkqgKAgyGQuqwr91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FoNIi/btsGiAnuoxw/gb1kZUOkqgKAgyGQuqwr91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFoNIi%2FbtsGiAnuoxw%2Fgb1kZUOkqgKAgyGQuqwr91%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;786&quot; height=&quot;249&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;249&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;387&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O7qNM/btsGjRa0LHI/ig4i9ESHpQKNU6U0oH1bD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O7qNM/btsGjRa0LHI/ig4i9ESHpQKNU6U0oH1bD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O7qNM/btsGjRa0LHI/ig4i9ESHpQKNU6U0oH1bD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO7qNM%2FbtsGjRa0LHI%2Fig4i9ESHpQKNU6U0oH1bD1%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;758&quot; height=&quot;387&quot; data-origin-width=&quot;758&quot; data-origin-height=&quot;387&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;429&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8iI8l/btsGjDqywrz/FUXD0nUk0uc8vB9dPmOzl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8iI8l/btsGjDqywrz/FUXD0nUk0uc8vB9dPmOzl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8iI8l/btsGjDqywrz/FUXD0nUk0uc8vB9dPmOzl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8iI8l%2FbtsGjDqywrz%2FFUXD0nUk0uc8vB9dPmOzl0%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;921&quot; height=&quot;429&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;429&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;431&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvR68Y/btsGkBebrlj/rlVykB8Eu4EpXcGqA9Cus1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvR68Y/btsGkBebrlj/rlVykB8Eu4EpXcGqA9Cus1/img.png&quot; data-alt=&quot;\&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvR68Y/btsGkBebrlj/rlVykB8Eu4EpXcGqA9Cus1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvR68Y%2FbtsGkBebrlj%2FrlVykB8Eu4EpXcGqA9Cus1%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;879&quot; height=&quot;431&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;431&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;\&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JFjQk/btsGjBsGVbQ/4rSP525XV9GsLDHK3lIsc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JFjQk/btsGjBsGVbQ/4rSP525XV9GsLDHK3lIsc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JFjQk/btsGjBsGVbQ/4rSP525XV9GsLDHK3lIsc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJFjQk%2FbtsGjBsGVbQ%2F4rSP525XV9GsLDHK3lIsc1%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;920&quot; height=&quot;426&quot; data-origin-width=&quot;920&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;523&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMVXzX/btsGjCSESM1/r8empP0LuX9OMCY7BR1FBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMVXzX/btsGjCSESM1/r8empP0LuX9OMCY7BR1FBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMVXzX/btsGjCSESM1/r8empP0LuX9OMCY7BR1FBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMVXzX%2FbtsGjCSESM1%2Fr8empP0LuX9OMCY7BR1FBK%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;959&quot; height=&quot;523&quot; data-origin-width=&quot;959&quot; data-origin-height=&quot;523&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;466&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LE6wV/btsGjmbewPF/QeJ2Ykr8JJf6afSozitHgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LE6wV/btsGjmbewPF/QeJ2Ykr8JJf6afSozitHgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LE6wV/btsGjmbewPF/QeJ2Ykr8JJf6afSozitHgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLE6wV%2FbtsGjmbewPF%2FQeJ2Ykr8JJf6afSozitHgk%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;1075&quot; height=&quot;466&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;466&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;826&quot; data-origin-height=&quot;443&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nA64Y/btsGkTFVZL4/vuohDfyBro2TF6CThTuKvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nA64Y/btsGkTFVZL4/vuohDfyBro2TF6CThTuKvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nA64Y/btsGkTFVZL4/vuohDfyBro2TF6CThTuKvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnA64Y%2FbtsGkTFVZL4%2FvuohDfyBro2TF6CThTuKvK%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;826&quot; height=&quot;443&quot; data-origin-width=&quot;826&quot; data-origin-height=&quot;443&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1090&quot; data-origin-height=&quot;193&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NY710/btsGjNGuyLA/5t4vFOmoUaxjDxPRTKK6F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NY710/btsGjNGuyLA/5t4vFOmoUaxjDxPRTKK6F0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NY710/btsGjNGuyLA/5t4vFOmoUaxjDxPRTKK6F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNY710%2FbtsGjNGuyLA%2F5t4vFOmoUaxjDxPRTKK6F0%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;1090&quot; height=&quot;193&quot; data-origin-width=&quot;1090&quot; data-origin-height=&quot;193&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KDLF6/btsGkU5U2PL/VXHxVcwtWCgpmAGgKsFqRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KDLF6/btsGkU5U2PL/VXHxVcwtWCgpmAGgKsFqRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KDLF6/btsGkU5U2PL/VXHxVcwtWCgpmAGgKsFqRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKDLF6%2FbtsGkU5U2PL%2FVXHxVcwtWCgpmAGgKsFqRK%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;1450&quot; height=&quot;490&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A00XC/btsGj06CEv4/RkkMQOshVk2GFZd0iBBBV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A00XC/btsGj06CEv4/RkkMQOshVk2GFZd0iBBBV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A00XC/btsGj06CEv4/RkkMQOshVk2GFZd0iBBBV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA00XC%2FbtsGj06CEv4%2FRkkMQOshVk2GFZd0iBBBV0%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;1138&quot; height=&quot;474&quot; data-origin-width=&quot;1138&quot; data-origin-height=&quot;474&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;787&quot; data-origin-height=&quot;511&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mlXHj/btsGmgtCxP1/DnO1ANURuTyuhL5ksoPK01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mlXHj/btsGmgtCxP1/DnO1ANURuTyuhL5ksoPK01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mlXHj/btsGmgtCxP1/DnO1ANURuTyuhL5ksoPK01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmlXHj%2FbtsGmgtCxP1%2FDnO1ANURuTyuhL5ksoPK01%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;787&quot; height=&quot;511&quot; data-origin-width=&quot;787&quot; data-origin-height=&quot;511&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;521&quot; data-origin-height=&quot;281&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NyNZf/btsGkTeRrsB/k3TTE97nWcleaZw04d6MNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NyNZf/btsGkTeRrsB/k3TTE97nWcleaZw04d6MNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NyNZf/btsGkTeRrsB/k3TTE97nWcleaZw04d6MNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNyNZf%2FbtsGkTeRrsB%2Fk3TTE97nWcleaZw04d6MNk%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;521&quot; height=&quot;281&quot; data-origin-width=&quot;521&quot; data-origin-height=&quot;281&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ce7KwZ/btsGjSnrhOt/gslfcSFK8NyuHUdByyiijk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ce7KwZ/btsGjSnrhOt/gslfcSFK8NyuHUdByyiijk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ce7KwZ/btsGjSnrhOt/gslfcSFK8NyuHUdByyiijk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fce7KwZ%2FbtsGjSnrhOt%2FgslfcSFK8NyuHUdByyiijk%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;456&quot; height=&quot;231&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;231&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;View를 찾으려고 하는데 못찾음. 기존의 방식(text-plain으로 하려면?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;250&quot; data-origin-height=&quot;179&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTviZO/btsGjnVCoh0/niwtfmnRr4Fb9DqTXOzSC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTviZO/btsGjnVCoh0/niwtfmnRr4Fb9DqTXOzSC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTviZO/btsGjnVCoh0/niwtfmnRr4Fb9DqTXOzSC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTviZO%2FbtsGjnVCoh0%2FniwtfmnRr4Fb9DqTXOzSC0%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;250&quot; height=&quot;179&quot; data-origin-width=&quot;250&quot; data-origin-height=&quot;179&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;477&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c9vhCR/btsGl0q0QnF/k9nkXbSZhJ5v9mAbriVd10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c9vhCR/btsGl0q0QnF/k9nkXbSZhJ5v9mAbriVd10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c9vhCR/btsGl0q0QnF/k9nkXbSZhJ5v9mAbriVd10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc9vhCR%2FbtsGl0q0QnF%2Fk9nkXbSZhJ5v9mAbriVd10%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;477&quot; height=&quot;252&quot; data-origin-width=&quot;477&quot; data-origin-height=&quot;252&quot;/&gt;&lt;/span&gt;&lt;/figure&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;171&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JrgRE/btsGmuyDrPw/qxvl6foiGaFrccUbaLRmXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JrgRE/btsGmuyDrPw/qxvl6foiGaFrccUbaLRmXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JrgRE/btsGmuyDrPw/qxvl6foiGaFrccUbaLRmXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJrgRE%2FbtsGmuyDrPw%2Fqxvl6foiGaFrccUbaLRmXK%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;764&quot; height=&quot;171&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;171&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아차차 public을 빼먹었다. 자바 공부한 보람이 있다. 그전에는 못 찾았을텐데... 하핫 나란 놈이란... 이것이 성장인가...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8hDus/btsGj49htne/pg6cJbo3UWwdKUKfc8lfc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8hDus/btsGj49htne/pg6cJbo3UWwdKUKfc8lfc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8hDus/btsGj49htne/pg6cJbo3UWwdKUKfc8lfc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8hDus%2FbtsGj49htne%2Fpg6cJbo3UWwdKUKfc8lfc0%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;464&quot; height=&quot;234&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;234&quot;/&gt;&lt;/span&gt;&lt;/figure&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;원인을 찾아보니 스프링부트3가 업데이트되면서 @RequestMapping 만으로 DispatcherServlet이 인식하던 기능이 더 이 상 지원되지 않고 @Controller까지 등록해야 한다. 따라서 @RequestMapping 만 있을 땐 위처럼 error가 나는 것이다.&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;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://jinmak.tistory.com/4&quot;&gt;디버깅 - -parameters&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712139412180&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;디버깅 - -parameters, 500, 매개변수 인식 오류&quot; data-og-description=&quot;디버깅 - -parameters, 500, 매개변수 인식 오류 오늘도 인강을 들으며 코딩을 했다. 처음에는 코드를 제대로 따라 쳤다고 생각했지만, 종종 빠뜨리거나 잘못 쓴 부분이 있어 오류가 났다면 요즘에는 &quot; data-og-host=&quot;jinmak.tistory.com&quot; data-og-source-url=&quot;https://jinmak.tistory.com/4&quot; data-og-url=&quot;https://jinmak.tistory.com/4&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bf2xbQ/hyVGHLj5qA/baftGg8MkVBthCrUScMtwK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Fu8ep/hyVGQg8kTR/yIyCe6Pox1Fkjk7uRFKsyK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://jinmak.tistory.com/4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jinmak.tistory.com/4&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bf2xbQ/hyVGHLj5qA/baftGg8MkVBthCrUScMtwK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/Fu8ep/hyVGQg8kTR/yIyCe6Pox1Fkjk7uRFKsyK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;디버깅 - -parameters, 500, 매개변수 인식 오류&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;디버깅 - -parameters, 500, 매개변수 인식 오류 오늘도 인강을 들으며 코딩을 했다. 처음에는 코드를 제대로 따라 쳤다고 생각했지만, 종종 빠뜨리거나 잘못 쓴 부분이 있어 오류가 났다면 요즘에는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jinmak.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 와중에 파라미터 문제가 또 도지는 바람에 찾느라 시간이 좀 걸렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;822&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K8W8U/btsGl2CuzZW/ekE7aBQO3VrlAz9CgXaWKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K8W8U/btsGl2CuzZW/ekE7aBQO3VrlAz9CgXaWKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K8W8U/btsGl2CuzZW/ekE7aBQO3VrlAz9CgXaWKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK8W8U%2FbtsGl2CuzZW%2FekE7aBQO3VrlAz9CgXaWKk%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;1212&quot; height=&quot;822&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;822&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1191&quot; data-origin-height=&quot;700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJcorj/btsGmBdwQSX/DfgUD32G0iEpKpg49PuRq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJcorj/btsGmBdwQSX/DfgUD32G0iEpKpg49PuRq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJcorj/btsGmBdwQSX/DfgUD32G0iEpKpg49PuRq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJcorj%2FbtsGmBdwQSX%2FDfgUD32G0iEpKpg49PuRq0%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;1191&quot; height=&quot;700&quot; data-origin-width=&quot;1191&quot; data-origin-height=&quot;700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1330&quot; data-origin-height=&quot;237&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpAzxl/btsGkCR4Enp/VXrcMWZrRXmYHRM4BKNBck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpAzxl/btsGkCR4Enp/VXrcMWZrRXmYHRM4BKNBck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpAzxl/btsGkCR4Enp/VXrcMWZrRXmYHRM4BKNBck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpAzxl%2FbtsGkCR4Enp%2FVXrcMWZrRXmYHRM4BKNBck%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;1330&quot; height=&quot;237&quot; data-origin-width=&quot;1330&quot; data-origin-height=&quot;237&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;709&quot; data-origin-height=&quot;85&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bveyiM/btsGkuNu6QR/sdAOm28d16Tl6nhC7edEl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bveyiM/btsGkuNu6QR/sdAOm28d16Tl6nhC7edEl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bveyiM/btsGkuNu6QR/sdAOm28d16Tl6nhC7edEl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbveyiM%2FbtsGkuNu6QR%2FsdAOm28d16Tl6nhC7edEl1%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;709&quot; height=&quot;85&quot; data-origin-width=&quot;709&quot; data-origin-height=&quot;85&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;86&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kNCLj/btsGmf9CvdC/O8TQHLC99hffQ8wkSCbCOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kNCLj/btsGmf9CvdC/O8TQHLC99hffQ8wkSCbCOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kNCLj/btsGmf9CvdC/O8TQHLC99hffQ8wkSCbCOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkNCLj%2FbtsGmf9CvdC%2FO8TQHLC99hffQ8wkSCbCOK%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;708&quot; height=&quot;86&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;86&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;391&quot; data-origin-height=&quot;68&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdEb6t/btsGj1dMAvp/epXOS4CZYkJbbXPRE59Ts1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdEb6t/btsGj1dMAvp/epXOS4CZYkJbbXPRE59Ts1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdEb6t/btsGj1dMAvp/epXOS4CZYkJbbXPRE59Ts1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdEb6t%2FbtsGj1dMAvp%2FepXOS4CZYkJbbXPRE59Ts1%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;391&quot; height=&quot;68&quot; data-origin-width=&quot;391&quot; data-origin-height=&quot;68&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;68&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bu8gV/btsGl3VGWwT/FXeVYy98KPwMC6HVbVSAYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bu8gV/btsGl3VGWwT/FXeVYy98KPwMC6HVbVSAYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bu8gV/btsGl3VGWwT/FXeVYy98KPwMC6HVbVSAYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBu8gV%2FbtsGl3VGWwT%2FFXeVYy98KPwMC6HVbVSAYk%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;688&quot; height=&quot;68&quot; data-origin-width=&quot;688&quot; data-origin-height=&quot;68&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;444&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k7RaT/btsGkTlXFCD/piEQIxxmJswTXoUiMvc1k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k7RaT/btsGkTlXFCD/piEQIxxmJswTXoUiMvc1k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k7RaT/btsGkTlXFCD/piEQIxxmJswTXoUiMvc1k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk7RaT%2FbtsGkTlXFCD%2FpiEQIxxmJswTXoUiMvc1k1%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;444&quot; height=&quot;78&quot; data-origin-width=&quot;444&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;744&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkokJm/btsGjEpJ1I2/QspOf1kgGneebXvCnogbK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkokJm/btsGjEpJ1I2/QspOf1kgGneebXvCnogbK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkokJm/btsGjEpJ1I2/QspOf1kgGneebXvCnogbK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkokJm%2FbtsGjEpJ1I2%2FQspOf1kgGneebXvCnogbK1%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;1432&quot; height=&quot;744&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;744&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;1053&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UUpaG/btsGlhAa53U/Bunyolr73SFSBJFR8nhm0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UUpaG/btsGlhAa53U/Bunyolr73SFSBJFR8nhm0K/img.png&quot; data-alt=&quot;원래 이랬었다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UUpaG/btsGlhAa53U/Bunyolr73SFSBJFR8nhm0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUUpaG%2FbtsGlhAa53U%2FBunyolr73SFSBJFR8nhm0K%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;1166&quot; height=&quot;1053&quot; data-origin-width=&quot;1166&quot; data-origin-height=&quot;1053&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;원래 이랬었다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;163&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mhS89/btsGmM6Zytf/GvOT8CbDR8PUar41xwDay0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mhS89/btsGmM6Zytf/GvOT8CbDR8PUar41xwDay0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mhS89/btsGmM6Zytf/GvOT8CbDR8PUar41xwDay0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmhS89%2FbtsGmM6Zytf%2FGvOT8CbDR8PUar41xwDay0%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;445&quot; height=&quot;163&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;163&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;719&quot; data-origin-height=&quot;73&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zwZuf/btsGjkrlsOt/7yXVC9oKR90V2AWsZAtSLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zwZuf/btsGjkrlsOt/7yXVC9oKR90V2AWsZAtSLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zwZuf/btsGjkrlsOt/7yXVC9oKR90V2AWsZAtSLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzwZuf%2FbtsGjkrlsOt%2F7yXVC9oKR90V2AWsZAtSLk%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;719&quot; height=&quot;73&quot; data-origin-width=&quot;719&quot; data-origin-height=&quot;73&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;커스텀 애노테이션을 쓰는데는 두가지 이유가 있다. (@Component Scan 강의중)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;198&quot; data-origin-height=&quot;38&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKPQxT/btsGknAREdT/z1FSHwp9lA1lWMTjOWk8BK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKPQxT/btsGknAREdT/z1FSHwp9lA1lWMTjOWk8BK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKPQxT/btsGknAREdT/z1FSHwp9lA1lWMTjOWk8BK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKPQxT%2FbtsGknAREdT%2Fz1FSHwp9lA1lWMTjOWk8BK%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;198&quot; height=&quot;38&quot; data-origin-width=&quot;198&quot; data-origin-height=&quot;38&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;195&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vaJhA/btsGj4aqGii/Hilh05uqTiDWo0MyTXvK3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vaJhA/btsGj4aqGii/Hilh05uqTiDWo0MyTXvK3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vaJhA/btsGj4aqGii/Hilh05uqTiDWo0MyTXvK3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvaJhA%2FbtsGj4aqGii%2FHilh05uqTiDWo0MyTXvK3k%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;451&quot; height=&quot;195&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;195&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKd5kX/btsGj0FROd9/KnYebbgbr7XIODB5ImvDi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKd5kX/btsGj0FROd9/KnYebbgbr7XIODB5ImvDi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKd5kX/btsGj0FROd9/KnYebbgbr7XIODB5ImvDi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKd5kX%2FbtsGj0FROd9%2FKnYebbgbr7XIODB5ImvDi0%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;1428&quot; height=&quot;314&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;314&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;787&quot; data-origin-height=&quot;489&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d1iaEO/btsGkriWRDk/A706YqiiNPhMSVlKCUK4Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d1iaEO/btsGkriWRDk/A706YqiiNPhMSVlKCUK4Kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d1iaEO/btsGkriWRDk/A706YqiiNPhMSVlKCUK4Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd1iaEO%2FbtsGkriWRDk%2FA706YqiiNPhMSVlKCUK4Kk%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;787&quot; height=&quot;489&quot; data-origin-width=&quot;787&quot; data-origin-height=&quot;489&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1303&quot; data-origin-height=&quot;787&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vRLL6/btsGleXIKKI/9bnMCrTPP9JNUdfcyxUwlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vRLL6/btsGleXIKKI/9bnMCrTPP9JNUdfcyxUwlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vRLL6/btsGleXIKKI/9bnMCrTPP9JNUdfcyxUwlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvRLL6%2FbtsGleXIKKI%2F9bnMCrTPP9JNUdfcyxUwlK%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;1303&quot; height=&quot;787&quot; data-origin-width=&quot;1303&quot; data-origin-height=&quot;787&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnMcZx/btsGknt4XgH/Q0qp9TP84A4UFPHyLIbSH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnMcZx/btsGknt4XgH/Q0qp9TP84A4UFPHyLIbSH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnMcZx/btsGknt4XgH/Q0qp9TP84A4UFPHyLIbSH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnMcZx%2FbtsGknt4XgH%2FQ0qp9TP84A4UFPHyLIbSH1%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;782&quot; height=&quot;486&quot; data-origin-width=&quot;782&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;673&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/79dzC/btsGjPdwkte/nmBDoPuWvD3XdSJ2WHSrQ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/79dzC/btsGjPdwkte/nmBDoPuWvD3XdSJ2WHSrQ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/79dzC/btsGjPdwkte/nmBDoPuWvD3XdSJ2WHSrQ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F79dzC%2FbtsGjPdwkte%2FnmBDoPuWvD3XdSJ2WHSrQ0%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;1408&quot; height=&quot;673&quot; data-origin-width=&quot;1408&quot; data-origin-height=&quot;673&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;180&quot; data-origin-height=&quot;53&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxK8jo/btsGlewF7lG/8C79h2dvtz5HAuqfhMA9xk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxK8jo/btsGlewF7lG/8C79h2dvtz5HAuqfhMA9xk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxK8jo/btsGlewF7lG/8C79h2dvtz5HAuqfhMA9xk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxK8jo%2FbtsGlewF7lG%2F8C79h2dvtz5HAuqfhMA9xk%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;180&quot; height=&quot;53&quot; data-origin-width=&quot;180&quot; data-origin-height=&quot;53&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WssVS/btsGjnuP0Aj/48osWHKf9B6vR2Ko6LASG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WssVS/btsGjnuP0Aj/48osWHKf9B6vR2Ko6LASG0/img.png&quot; data-alt=&quot;Crtl + H 로 Hierachy를 볼 수 있음&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WssVS/btsGjnuP0Aj/48osWHKf9B6vR2Ko6LASG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWssVS%2FbtsGjnuP0Aj%2F48osWHKf9B6vR2Ko6LASG0%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;488&quot; height=&quot;206&quot; data-origin-width=&quot;488&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Crtl + H 로 Hierachy를 볼 수 있음&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1061&quot; data-origin-height=&quot;62&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyEwzd/btsGl3VIaa8/yqw2AOZBJ3RZNBVd3zbaKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyEwzd/btsGl3VIaa8/yqw2AOZBJ3RZNBVd3zbaKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyEwzd/btsGl3VIaa8/yqw2AOZBJ3RZNBVd3zbaKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyEwzd%2FbtsGl3VIaa8%2Fyqw2AOZBJ3RZNBVd3zbaKk%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;1061&quot; height=&quot;62&quot; data-origin-width=&quot;1061&quot; data-origin-height=&quot;62&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/72f4R/btsGlYUBCsH/DH45jVTcWePn1kTRbVJjGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/72f4R/btsGlYUBCsH/DH45jVTcWePn1kTRbVJjGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/72f4R/btsGlYUBCsH/DH45jVTcWePn1kTRbVJjGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F72f4R%2FbtsGlYUBCsH%2FDH45jVTcWePn1kTRbVJjGk%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;978&quot; height=&quot;241&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;241&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MsXiO/btsGlXBo14C/JMNAYzGfdEfcKx2FMu6RB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MsXiO/btsGlXBo14C/JMNAYzGfdEfcKx2FMu6RB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MsXiO/btsGlXBo14C/JMNAYzGfdEfcKx2FMu6RB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMsXiO%2FbtsGlXBo14C%2FJMNAYzGfdEfcKx2FMu6RB1%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;814&quot; height=&quot;628&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lHBjV/btsGjFvrOcK/aYtXOYL99Q4kR2d8EfYAY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lHBjV/btsGjFvrOcK/aYtXOYL99Q4kR2d8EfYAY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lHBjV/btsGjFvrOcK/aYtXOYL99Q4kR2d8EfYAY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlHBjV%2FbtsGjFvrOcK%2FaYtXOYL99Q4kR2d8EfYAY0%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;1126&quot; height=&quot;598&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;61&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cT745Q/btsGjQDv8O3/KIcqj7utOSHPvL5hzKNvX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cT745Q/btsGjQDv8O3/KIcqj7utOSHPvL5hzKNvX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cT745Q/btsGjQDv8O3/KIcqj7utOSHPvL5hzKNvX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcT745Q%2FbtsGjQDv8O3%2FKIcqj7utOSHPvL5hzKNvX1%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;840&quot; height=&quot;61&quot; data-origin-width=&quot;840&quot; data-origin-height=&quot;61&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;785&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHrV4n/btsGkrpNDYb/oiYeQFrKeRLldQtgd9eol0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHrV4n/btsGkrpNDYb/oiYeQFrKeRLldQtgd9eol0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHrV4n/btsGkrpNDYb/oiYeQFrKeRLldQtgd9eol0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHrV4n%2FbtsGkrpNDYb%2FoiYeQFrKeRLldQtgd9eol0%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;1340&quot; height=&quot;785&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;785&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;추출 윈도우:Ctrl + Alt + M&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;859&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dv3eyQ/btsGj3WUg4I/ylbMUgMuXOVkEnHvHsP7g1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dv3eyQ/btsGj3WUg4I/ylbMUgMuXOVkEnHvHsP7g1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dv3eyQ/btsGj3WUg4I/ylbMUgMuXOVkEnHvHsP7g1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdv3eyQ%2FbtsGj3WUg4I%2FylbMUgMuXOVkEnHvHsP7g1%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;1324&quot; height=&quot;859&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;859&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;373&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xEKsi/btsGmvqUuNM/oUjVWd9eAqyTjJpnPFfcik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xEKsi/btsGmvqUuNM/oUjVWd9eAqyTjJpnPFfcik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xEKsi/btsGmvqUuNM/oUjVWd9eAqyTjJpnPFfcik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxEKsi%2FbtsGmvqUuNM%2FoUjVWd9eAqyTjJpnPFfcik%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;855&quot; height=&quot;373&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;373&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;736&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HltFv/btsGlwYmNkV/lKESwKKnnKpQWfSIvVPGK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HltFv/btsGlwYmNkV/lKESwKKnnKpQWfSIvVPGK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HltFv/btsGlwYmNkV/lKESwKKnnKpQWfSIvVPGK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHltFv%2FbtsGlwYmNkV%2FlKESwKKnnKpQWfSIvVPGK0%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;1044&quot; height=&quot;736&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;736&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;MySpringApplicaion 으로 빼주기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;746&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byiJBF/btsGlhfQTBF/7aLGRPPNxfWzM8oBKV4ra0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byiJBF/btsGlhfQTBF/7aLGRPPNxfWzM8oBKV4ra0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byiJBF/btsGlhfQTBF/7aLGRPPNxfWzM8oBKV4ra0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyiJBF%2FbtsGlhfQTBF%2F7aLGRPPNxfWzM8oBKV4ra0%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;813&quot; height=&quot;746&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;746&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;그러자 어디선가 본 것 같은 코드...(스프링부트 초기 코드)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;685&quot; data-origin-height=&quot;229&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvjQM7/btsGlXalmoo/WVkVh5vZYwZOBUypUBNCX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvjQM7/btsGlXalmoo/WVkVh5vZYwZOBUypUBNCX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvjQM7/btsGlXalmoo/WVkVh5vZYwZOBUypUBNCX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvjQM7%2FbtsGlXalmoo%2FWVkVh5vZYwZOBUypUBNCX0%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;685&quot; height=&quot;229&quot; data-origin-width=&quot;685&quot; data-origin-height=&quot;229&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;이제 안녕&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDAz4e/btsGmPo8qpG/kkioLdceS7RwSDy2drjv21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDAz4e/btsGmPo8qpG/kkioLdceS7RwSDy2drjv21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDAz4e/btsGmPo8qpG/kkioLdceS7RwSDy2drjv21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDAz4e%2FbtsGmPo8qpG%2FkkioLdceS7RwSDy2drjv21%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;737&quot; height=&quot;117&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;117&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;451&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkqW4m/btsGmwcgHOS/mZhjjd5Yf0NqJlfl0ddl3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkqW4m/btsGmwcgHOS/mZhjjd5Yf0NqJlfl0ddl3K/img.png&quot; data-alt=&quot;스태식이 돌아왔구나!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkqW4m/btsGmwcgHOS/mZhjjd5Yf0NqJlfl0ddl3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkqW4m%2FbtsGmwcgHOS%2FmZhjjd5Yf0NqJlfl0ddl3K%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;855&quot; height=&quot;451&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;451&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스태식이 돌아왔구나!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <author>진막</author>
      <guid isPermaLink="true">https://jinmak.tistory.com/31</guid>
      <comments>https://jinmak.tistory.com/31#entry31comment</comments>
      <pubDate>Thu, 4 Apr 2024 09:27:07 +0900</pubDate>
    </item>
    <item>
      <title>자바 - 추상 클래스 vs 인터페이스</title>
      <link>https://jinmak.tistory.com/26</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;자바&amp;nbsp;-&amp;nbsp;추상&amp;nbsp;클래스&amp;nbsp;vs&amp;nbsp;인터페이스&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;추상 클래스 vs 인터페이스 비교&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;추상 클래스와 인터페이스를 동시에 공부했다면 문득 궁금해진다. '그게 그거 아닌가?' 사실 인터페이스에 default 메서드와 static 메서드가 생기면서 인터페이스가 추상 클래스의 상위 호환이 된 느낌이 없지 않아 있지만 그래도 분명 차이점은 존재한다. 지금부터 추상 클래스와 인터페이스를 비교해 가며 무엇이 같고 무엇이 다른지 살펴보자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1349&quot; data-origin-height=&quot;685&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FSm3n/btsGavYN1kB/TIGKW3K08Tek2KnhEwnUx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FSm3n/btsGavYN1kB/TIGKW3K08Tek2KnhEwnUx0/img.png&quot; data-alt=&quot;가슴이 웅장해진다...&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FSm3n/btsGavYN1kB/TIGKW3K08Tek2KnhEwnUx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFSm3n%2FbtsGavYN1kB%2FTIGKW3K08Tek2KnhEwnUx0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;305&quot; data-origin-width=&quot;1349&quot; data-origin-height=&quot;685&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가슴이 웅장해진다...&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;추상 클래스&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;인터페이스&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span style=&quot;background-color: #efefef;&quot;&gt;사용 키워드&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;abstract&lt;/td&gt;
&lt;td&gt;interface&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;사용 가능 변수&lt;/td&gt;
&lt;td&gt;제한 없음&lt;/td&gt;
&lt;td&gt;static final (상수)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;사용 가능 접근 제어자&lt;/td&gt;
&lt;td&gt;제한 없음 (public, private, protected, default)&lt;/td&gt;
&lt;td&gt;public&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;사용 가능 메소드&lt;/td&gt;
&lt;td&gt;제한 없음&lt;/td&gt;
&lt;td&gt;abstract method, default method, static method, private method&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;상속 키워드&lt;/td&gt;
&lt;td&gt;extends&lt;/td&gt;
&lt;td&gt;implements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;다중 상속 가능 여부&lt;/td&gt;
&lt;td&gt;불가능&lt;/td&gt;
&lt;td&gt;가능 (클래스에 다중 구현, 인터페이스 끼리 다중 상속)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;공통점&lt;/td&gt;
&lt;td colspan=&quot;2&quot;&gt;1. 추상 메소드를 가지고 있어야 한다.&lt;br /&gt;&lt;br /&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;인스턴스화 할 수 없다 (&lt;/span&gt;new 생성자 사용 X)&lt;br /&gt;&lt;br /&gt;3. 인터페이스 혹은 추상 클래스를 상속받아 구현한 구현체의 인스턴스를 사용해야 한다.&lt;br /&gt;&lt;br /&gt;4. 인터페이스와 추상클래스를 구현, 상속한 클래스는 추상 메소드를 반드시 구현하여야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;추상 클래스 정리&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추상 클래스는 하위 클래스들의 공통점을 모아 추상화하여 만든 클래스&lt;/li&gt;
&lt;li&gt;추상 클래스는 다중 상속이 불가능하여&amp;nbsp;&lt;b&gt;단일 상속&lt;/b&gt;만 허용한다.&lt;/li&gt;
&lt;li&gt;추상 클래스는 추상 메서드 외에 일반 클래스와 같이&amp;nbsp;&lt;b&gt;일반적인 필드, 메서드, 생성자&lt;/b&gt;를 가질 수 있다.&lt;/li&gt;
&lt;li&gt;이러한 특징으로, 추상 클래스는&amp;nbsp;&lt;b&gt;추상화(추상 메서드)를 하면서 중복되는 클래스 멤버들을 통합 및 확장&lt;/b&gt;을 할 수 있다.&lt;/li&gt;
&lt;li&gt;같은 추상화인 인터페이스와 다른점은, 추상 클래스는&amp;nbsp;&lt;b&gt;클래스 간의 연관 관계를 구축&lt;/b&gt;하는 것에 초점을 둔다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스 정리&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내부의 모든 메서드는 `public abstract`로 정의 (default 메서드 제외)&lt;/li&gt;
&lt;li&gt;내부의 모든 필드는 `public static final` &lt;b&gt;상수&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;클래스에&amp;nbsp;&lt;b&gt;다중 구현&amp;nbsp;&lt;/b&gt;지원&lt;/li&gt;
&lt;li&gt;인터페이스 끼리는 다중 상속 지원&lt;/li&gt;
&lt;li&gt;인터페이스에도 `static`, `default`, `private`제어자를 붙여 클래스 같이 구체적인 메서드를 가질 수 있음. 따라서 하위 멤버의 중복 메서드 통합을 어느 정도 할 수는 있겠지만, 필드는 상수이기 때문에 중복 필드 통합은 불가능&lt;/li&gt;
&lt;li&gt;인터페이스는 부모 자식 관계인 상속에 얽매이지 않고, 공통 기능이 필요할때 마다 추상 메서드를&amp;nbsp; 정의해 놓고 구현(implement)하는 식으로 추상 클래스보다 자유롭게 붙였다 뗐다 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인터페이스는 클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장하기 위해 사용하는 것에 초점&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;다중 구현이 된다는 점을 이용해, 내부 멤버가 없는 빈 껍데기 인터페이스를 선언하여&amp;nbsp;&lt;b&gt;마커 인터페이스&lt;/b&gt;로서 이용 가능&lt;/li&gt;
&lt;li&gt;보통 `Verbable` 같은 형식으로 인터페이스 네이밍 규칙을 따름&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;추상 클래스 vs 인터페이스 쓰임새&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;/span&gt;인터페이스나 추상 클래스나 둘 다 똑같이 추상 메서드를 통해 상속/구현을 통한 메서드 강제 구현 규칙을 가지는 추상화 클래스이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다만 이 둘은 각각 고유한 특징을 몇 가지 가지고 있는데, 이러한 특징으로 쓰임새가 달라지게 된다. 또한 기능적인 부분뿐만 아니라 인터페이스와 추상 클래스가 내포하고 있는 논리적인 의미로서도 사용처가 나뉜다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 이 둘은 대표적으로 `다중 상속` 기능 여부의 차이가 있긴 하지만, 중요한 점은 고유 기능보다 사용 목적의 차이에 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; 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;인터페이스: `implements`라는 키워드처럼 인터페이스에 정의된 메서드를 각 클래스의 목적에 맞게 기능을 구현하는 느낌&lt;/li&gt;
&lt;li&gt;추상 클래스: `extends` 키워드를 사용해서 자신의 기능들을 하위 클래스로 확장시키는 느낌&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;409&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/24FPG/btsF87Luog2/ZWYh0vlGlKJZM8IOSIcSW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/24FPG/btsF87Luog2/ZWYh0vlGlKJZM8IOSIcSW1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/24FPG/btsF87Luog2/ZWYh0vlGlKJZM8IOSIcSW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F24FPG%2FbtsF87Luog2%2FZWYh0vlGlKJZM8IOSIcSW1%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;800&quot; height=&quot;217&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;409&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;추상클래스를 사용하는 경우&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속 받을 클래스들이 공통으로 가지는 메서드와 필드가 많아&amp;nbsp;&lt;b&gt;중복 멤버 통합&lt;/b&gt;을 할 때&lt;/li&gt;
&lt;li&gt;멤버에 public 이외의 접근자(protected, private) 선언이 필요한 경우&lt;/li&gt;
&lt;li&gt;non-static, non-final 필드 선언이 필요한 경우 (각 인스턴스에서 상태 변경을 위한 메서드가 필요한 경우)&lt;/li&gt;
&lt;li&gt;요구사항과 함께 구현 세부 정보의 일부 기능만 지정했을 때(interface의 일부만 구현한 경우)&lt;/li&gt;
&lt;li&gt;추상 클래스는 이를 상속할 각 객체들의 공통점을 찾아 추상화시켜 놓은 것으로, 상속 관계를 타고 올라갔을 때 같은 부모 클래스를 상속하며 부모 클래스가 가진 기능들을 구현해야 할 경우 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 중복 멤버 통합&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;중복되는 멤버를 통합해 주는 기능은 추상 클래스만의 기능이라기보단 상속의 기능이라 보는 것이 맞다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다만 같은 추상화 개념인 인터페이스와 차이점을 두기 위해, 상수 밖에 정의 못하는 인터페이스에서는 할 수 없는 기능이 추상 클래스 중복 멤버 통합이라고 보면 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 추상클래스의 다형성 이용 설계&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;추상 클래스의 다형성이나 인터페이스의 다형성이나 둘 다 클래스 타입을 통합한다는 취지의 기능은 똑같다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다만, 다형성을 사용하는 순서의 차이로 추상 클래스와 인터페이스의 다형성을 분리할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이 부분은 이론적인 면이 강해 이해하는 데 어려울 수 있다. 하지만 확실히 이해하면 언제 추상 클래스를 사용하고, 인터페이스를 사용할지 결정을 내리는 데 도움이 됨으로 이해하도록 노력하자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;아래의 도식을 보자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1235&quot; data-origin-height=&quot;562&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QA9MY/btsF7vfvpSr/crqnapOsl3g0d3SOjCEOF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QA9MY/btsF7vfvpSr/crqnapOsl3g0d3SOjCEOF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QA9MY/btsF7vfvpSr/crqnapOsl3g0d3SOjCEOF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQA9MY%2FbtsF7vfvpSr%2FcrqnapOsl3g0d3SOjCEOF0%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;800&quot; height=&quot;364&quot; data-origin-width=&quot;1235&quot; data-origin-height=&quot;562&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;추상 클래스는 클라이언트(ExamConsole)에서 자료형을 사용하기 전에&amp;nbsp;&lt;b&gt;미리 논리적인 클래스 상속 구조를 만들어 놓고 사용&lt;/b&gt;이 결정되는 느낌이라고 보면 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 위의 Exam 주제의 논리적인 상속 구조의 객체들을 클라이언트(ExamConsole)에서 다형성으로 통합적으로 받아 사용할 때, 필드로 추상 클래스 타입으로 선언하고 생성자에서 매개변수로 `new NewlecExam()` 혹은 `new YBMExam()` 객체로 받아와 업캐스팅으로 초기화함으로써, 다양한 Exam 자식 클래스들을 다형성으로 다룰 수 있게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711586454439&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class ExamConsole {
    Exam exam; // 상위 추상 클래스 타입으로 선언
    
    // 생성자 매개 변수로 new NewlecExam() 혹은 new YBMExam() 생성자가 들어와 필드를 초기화
    ExamConsole(Exam e) {
        this.exam = e; // 업캐스팅 초기화
    }
    
    void input() {}
    void print() {}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;정리하자면, 인터페이스나 추상 클래스나 다형성을 이용할 수 있는데, 추상 클래스를 통한 다형성을 이용할 때에는, &lt;b&gt;부모 추상 클래스와 논리적으로 관련이 있는 자식 클래스를 다룬다는 점&lt;/b&gt;에서, 클라이언트와 추상화 객체들은 &lt;b&gt;의미가 있는 관계로 묶여 있다&lt;/b&gt;고 볼 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 명확한 계층 구조 추상화&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;단순한 중복 멤버 제거를 떠나서, 클래스끼리 명확한 계층 구조가 필요할 때도 추상 클래스를 사용한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;공통된 기능 구현이 필요하거나, 공통으로 지켜야 할 규칙이 있을 때 상속을 통해 구조화하여 재정의(Overriding)을 통해 구현한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이는 기능이라기보단&amp;nbsp;&lt;b&gt;설계 원칙 이론&lt;/b&gt;에 가까운데, 아직 객체 지향의 추상화에 익숙치 않으면 인터페이스와의 차이점이 애매래 잘 와닿지 않을 수도 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;주목해야 할 부분은 추상 클래스나 인터페이스나 추상 메서드를 이용한 구현 원칙을 강제한다는 점은 같지만, 추상 클래스는 '클래스로서'&amp;nbsp;&lt;b&gt;클래스와 의미 있는 연관 관계를 구축&lt;/b&gt;할 때 라고 보면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 대용량 SMS sender를 구현하는데 여러 통신사들이 다른 통신탑(tower)을 갖고 있어서 접속하는 데 있어 각각 다른 구현이 필요하며(establish Connection With Your Tower), 공통으로 지켜야 할 규칙인 방해 금지 모드(check If Do Not Disturb Mode)도 있는 스펙일 때 먼저 추상 클래스로 공통분모를 추상화로 구현하고, 상속을 통해 여러 통신사 클래스를 확장하여 구현하는 식으로 객체 지향 설계 원칙대로 프로그램을 구성할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711586908474&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* SMS를 보내는 추상화된 코드 */
abstract class SMSSender {

    abstract public void establishConnectionWithYourTower();

    public void sendSMS() {
        establishConnectionWithYourTower();
        checkIfDoNotDisturbMode();
        // ...
        destroyConnectionWithYourTower();
    }

    abstract public void destroyConnectionWithYourTower();

    public void checkIfDoNotDisturbMode() {
        // 추상 클래스 안에서 구현
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711586915629&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* SMSSender를 통신사 클래스들이 상속 */
class SKT extends SMSSender {
    @Override
    public void establishConnectionWithYourTower() {
        // SKT 방식으로 커넥션 맺기
    }

    @Override
    public void destroyConnectionWithYourTower() {
        // SKT 방식으로 커넥션 종료
    }
}

class LG extends SMSSender {
    @Override
    public void establishConnectionWithYourTower() {
        // LG 방식으로 커넥션 맺기
    }

    @Override
    public void destroyConnectionWithYourTower() {
        // LG 방식으로 커넥션 종료
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스를 사용하는 경우&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어플리케이션의 기능을 정의해야 하지만 그 구현 방식이나 대상에 대해 추상화할 때&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서로 관련성이 없는 클래스들을 묶어 주고&lt;/b&gt; 싶을 때 (형제 관계)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다중 상속(구현)&lt;/b&gt;을 통한 추상화 설계를 해야 할 때&lt;/li&gt;
&lt;li&gt;특정 데이터 타입의 행동을 명시하고 싶은데, 어디서 그 행동이 구현되는지 신경 쓰지 않는 경우&lt;/li&gt;
&lt;li&gt;클래스와 별로도&amp;nbsp;&lt;b&gt;구현 객체가 같은 동작을 한다는 것을 보장&lt;/b&gt;하기 위해 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h5&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;자유로운 타입 묶음&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스의 가장 큰 특징은 상속에 구애 받지 않은 상속(구현)이 가능하다는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;상속(extends)은 클래스끼리 &lt;b&gt;논리적으로 타입을 묶는데&lt;/b&gt;의 의의가 있다면, 구현(implements)은 &lt;b&gt;자유로이 타입을 묶을 수 있다는 것&lt;/b&gt;에 의의가 있다. 그래서 서로 논리적이지 않고 관련이 적은 클래스끼리 필요에 의해 &lt;b&gt;형제 타입&lt;/b&gt;처럼 묶을 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다음과 같이 Creature라는 최상위 추상 클래스와 그 하위 추상 클래스인 Animal, Fish 가 있고, 각 추상 클래스를 구체적으로 의미 부여해 구현한 Parrot, Tiger, People 클래스와 Whale 클래스가 있다고 하자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2dlD4/btsGacZAGum/8bG81afsxyu59ZWs3Wqogk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2dlD4/btsGacZAGum/8bG81afsxyu59ZWs3Wqogk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2dlD4/btsGacZAGum/8bG81afsxyu59ZWs3Wqogk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2dlD4%2FbtsGacZAGum%2F8bG81afsxyu59ZWs3Wqogk%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;700&quot; height=&quot;274&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;위의 상속 관계도를 코드로 표현하면 다음과 같다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711587642802&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 추상 클래스 (조상 클래스)
abstract class Creature { }

// 추상 클래스 (부모 클래스)
abstract class Animal extends Creature { }
abstract class Fish extends Creature { }

// 자식 클래스
class Parrot extends Animal { }
class Tiger extends Animal { }
class People extends Animal { }

class Whale extends Fish { }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 상속 관계를 설정해 놓고 동작을 하는 메서드를 추가해야 하는데, 만일 수영 동작을 하는 `swimming()` 메서드를 각 자식 클래스에 추가해야 한다고 하자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이때 나중에 확장을 위해&amp;nbsp;&lt;b&gt;추상화 원칙을 따라야 한다.&amp;nbsp;&lt;/b&gt;그럼 부모나 조상 클래스에 추상 메서드를 추가해야 하는데, 수영은 고래(Whale)와 사람(People)만 할 수 있으니 이를 동시에 포함하는 Creature 추상 클래스에서 추상 메서드를 추가해야 한다. (호랑이와 앵무새는 수영을 못한다고 가정. 고래도 Fish라고 가정.)&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 Creature 추상 클래스에 추상 메서드를 추가하면, 곧 이를 상속하는 모든 자손/자식 클래스에서 반드시 메서드를 구체화해야 한다는 규칙 때문에 실제로 수영을 못하는 호랑이(Tiger)와 앵무새(Parrot) 클래스에서도 메서드를 구현해야 하는 강제성이 생긴다.&lt;/p&gt;
&lt;pre id=&quot;code_1711588008298&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 추상 클래스 (조상 클래스)
abstract class Creature { 
	abstract void swimming(); // 수영 동작을 하는 추상 메소드
}

// 추상 클래스 (부모 클래스)
abstract class Animal extends Creature { }
abstract class Fish extends Creature { }

// 자식 클래스
class Parrot extends Animal {
	void swimming() {} // 앵무새는 수영을 할수 없지만 상속 관계로 인해 강제적으로 메소드를 구현해야하는 사태가 일어난다.
}
class Tiger extends Animal {
	void swimming() {} // 호랑이는 수영을 할수 없지만 상속 관계로 인해 강제적으로 메소드를 구현해야하는 사태가 일어난다.
}
class People extends Animal {
	void swimming() {
    	// ...
    } 
}

class Whale extends Fish {
	void swimming() {
		// ...
    } 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;물론 메서드를 선언하기만 하고 빈칸으로 놔두어도 코드는 문제없이 돌아가겠지만, 이는 객체 지향 설계에 위반될 뿐만 아니라 나중에 유지보수면에서도 생산성이 떨어진다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 상속에 얽매이지 않는 인터페이스에 추상 메서드를 선언하고 이를 구현(implements)하면서&amp;nbsp;&lt;b&gt;자유로운 타입 묶음을 통해 추상화를 이루게 하는 것&lt;/b&gt;이다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;469&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwZahk/btsF65umV8X/mhKQXfQNhpB8byxxexJMjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwZahk/btsF65umV8X/mhKQXfQNhpB8byxxexJMjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwZahk/btsF65umV8X/mhKQXfQNhpB8byxxexJMjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwZahk%2FbtsF65umV8X%2FmhKQXfQNhpB8byxxexJMjk%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;700&quot; height=&quot;368&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;469&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1711588171457&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class Creature { }

abstract class Animal extends Creature { }
abstract class Fish extends Creature { }

// 수영 동작 추상 메소드를 따로 인터페이스를 만들어 넣는다.
interface Swimmable {
    void swimming();
}

class Tiger extends Animal { }
class Parrot extends Animal { }
class People extends Animal implements Swimmable{ // 인터페이스를 구현함으로써 동작이 필요한 클래스에만 따로 상속에 구애받지않고 묶음
    @Override
    public void swimming() {}
}

class Whale extends Fish implements Swimmable{ // 인터페이스를 구현함으로써 동작이 필요한 클래스에만 따로 상속에 구애받지않고 묶음
    @Override
    public void swimming() {}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이외에도, 날아다니는 동작 메서드나, 말하는 동작 메서드를 각각 인터페이스마다 분리하여 선언하고 이를 각 자식 클래스에 자유롭게 상속시킴으로써 보다 구조화된 객체 지향 설계를 추구할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;469&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GzPCj/btsF92ipL5N/BvAYOzqyPxuhWRukESKpm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GzPCj/btsF92ipL5N/BvAYOzqyPxuhWRukESKpm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GzPCj/btsF92ipL5N/BvAYOzqyPxuhWRukESKpm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGzPCj%2FbtsF92ipL5N%2FBvAYOzqyPxuhWRukESKpm0%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;700&quot; height=&quot;368&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;469&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711588242575&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class Creature { }

abstract class Animal extends Creature { }
abstract class Fish extends Creature { }

interface Flyable {
    void flying();
}

interface Talkable {
    void talking();
}

interface Swimmable {
    void swimming();
}

class Tiger extends Animal { }
class Parrot extends Animal implements Talkable{
    @Override
    public void talking() {
        
    }
}
class People extends Animal implements Talkable, Swimmable{ // 필요에 따라 적재적소에 다중으로 여러개 추가(구현)이 가능함
    @Override
    public void talking() {}

    @Override
    public void swimming() {}
}

class Whale extends Fish implements Swimmable{
    @Override
    public void swimming() {}
}&lt;/code&gt;&lt;/pre&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h5&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스 다형성 이용 설계&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이 파트는 위의 추상 클래스의 다형성 이용 설계 파트에서 이어진다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;추상 클래스는 클라이언트에서 자료형을 사용하기 전에&amp;nbsp;&lt;b&gt;미리 논리적인 클래스 상속 구조를 만들어 놓고 사용&lt;/b&gt;하는 느낌이라면, 인터페이스는 언제든 상관없이&amp;nbsp;&lt;b&gt;상황에 맞춰 필요에 따라 구현하고 자유롭게 붙였다 뗐다&lt;/b&gt;하는 느낌이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;외부 파일에 데이터를 저장하는 라이브러리를 가져와 사용한다고 가정하자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이 라이브러리 안에는 Filesave 클래스를 이용해 외부 파일로 데이터를 저장한다. 이때 Filesaver 클래스를 보면 필드 변수로 Storable 인터페이스 타입의 객체를 선언하여 `save()` 메서드에서 인터페이스 타입 객체를 이용하는 것을 볼 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;즉, Filesaver 클래스는 구체적인 클래스 타입으로 통신하는 것이 아닌&amp;nbsp;&lt;b&gt;인터페이스라는 중개타입을 이용하여 통신&lt;/b&gt;하는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1281&quot; data-origin-height=&quot;539&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5wj3K/btsF9Ji6fPi/F2Tu8veuZvHppXjGHYGkWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5wj3K/btsF9Ji6fPi/F2Tu8veuZvHppXjGHYGkWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5wj3K/btsF9Ji6fPi/F2Tu8veuZvHppXjGHYGkWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5wj3K%2FbtsF9Ji6fPi%2FF2Tu8veuZvHppXjGHYGkWK%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;700&quot; height=&quot;294&quot; data-origin-width=&quot;1281&quot; data-origin-height=&quot;539&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711589183389&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 외부 파일에 클래스 데이터를 저장 가능하도록 하는 인터페이스
interface Storable {
    // 클래스 데이터를 반환하는 메서드
    int getData();
}

// 외부 파일에 데이터를 저장하는 클래스
class FileSaver {
    Storable target; // 인터페이스를 구현한 객체를 필드로 선언
    
    // FileSaver 생성자, Storable 타입의 객체를 매개변수로 받음
    FileSaver(Storable target) {
        this.target = target; // 주어진 객체를 필드에 할당
    }
    
    // 데이터를 저장하는 메서드
    int save() {
        int data = target.getData(); // Storable 인터페이스의 메서드를 호출하여 데이터를 가져옴
        // 데이터를 저장하는 로직 구현
        // ...
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;서로 다른 클래스인 Exam, File, Rectangle 등을 FileSaver 클래스에서 파일로 저장하려면, 이들을 공통 인터페이스로 묶어 타입을 일관성 있게 정의할 수 있다. 이렇게 하면 상속 관계없이도 FileSaver 클래스의 인터페이스 타입 필드로 전달할 수 있어, 유연하게 다형성을 활용할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnViCS/btsF9yWshzE/LyzMIk3geTU0jlMD1mKKW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnViCS/btsF9yWshzE/LyzMIk3geTU0jlMD1mKKW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnViCS/btsF9yWshzE/LyzMIk3geTU0jlMD1mKKW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnViCS%2FbtsF9yWshzE%2FLyzMIk3geTU0jlMD1mKKW0%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;700&quot; height=&quot;316&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711589510871&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Exam implements Storable { // 인터페이스를 구현함으로서 클래스끼리 형제 관계를 맺음 
    int kor;
    int eng;
    int math;

    void total(){}
    void avg(){}

    // 인터페이스 통신 메소드 구현
    int getData(){
        // ...
    }
}

class File implements Storable { // 인터페이스를 구현함으로서 클래스끼리 형제 관계를 맺음 
    String src;
    
    boolean isFile(){}
    void mkDir(){}
    
    // 인터페이스 통신 메소드 구현
    int getData(){
        // ...
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;만일&amp;nbsp;&lt;b&gt;분석 라이브러리&lt;/b&gt;를 사용한다고 했을때 Analyzer 클래스에서 통신으로 사용되는 Calculateable 인터페이스 타입 객체 필드에 Exam 클래스를 전달하기 위해 역시 다중 구현이 가능하다는 점을 이용해 Caculatable 인터페이스를 implements만 하면 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1266&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cU6Dsd/btsF7Ro6Btr/UcZWVsg0sgo1CeMgaRlvg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cU6Dsd/btsF7Ro6Btr/UcZWVsg0sgo1CeMgaRlvg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cU6Dsd/btsF7Ro6Btr/UcZWVsg0sgo1CeMgaRlvg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcU6Dsd%2FbtsF7Ro6Btr%2FUcZWVsg0sgo1CeMgaRlvg1%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;700&quot; height=&quot;318&quot; data-origin-width=&quot;1266&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711589811976&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Caculatable {
    void total();
    void avg();
}

class Analyzer {
	Caculatable caculate; // Caculatable 인터페이스 타입으로 필드 선언
    
    void result() {}
    // ...
}

class Exam implements Storable, Caculatable { // 인터페이스를 구현함으로서 클래스끼리 형제 관계를 맺음
    int kor;
    int eng;
    int math;

    void total(){}
    void avg(){}
    int getData(){}
}&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;정리하자면, 인터페이스의 다형성은 부모 자식 클래스와 달리 논리적으로 관련이 없는 별개의 클래스들을 다룬다는 점에서,&amp;nbsp;&lt;b&gt;상속 관계에 얽매이지 않고 구현(implements)만 하면 자유롭게 다형성을 코드에 적용할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마커 인터페이스&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;자바의 마커 인터페이스는 일반적인 인터페이스와 동일하지만 아무 메서드도 선언하지 않은 &lt;b&gt;빈 껍데기 인터페이스&lt;/b&gt;를 말한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711590351932&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface inevitable {} // 아무 내용이 없는 빈 껍데기 인터페이스&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이는 마치 구현체에 대한 역할을 정의하는 인터페이스의 역할을 다하지 못한 것처럼 보인다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;마커 인터페이스&lt;/b&gt;는 인터페이스가 다중 상속이 가능하다는 점을 이용해 그저 표시하는 용도로 쓰는 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;아무 내용도 없어서 쓸모가 없어 보이지만, 마커 인터페이스의 역할은&amp;nbsp;&lt;b&gt;객체의 타입과 관련된 정보만을 제공해 주는&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 컴파일러와 JVM은 이 마커 인터페이스를 통해 객체에 대한 추가적인 정보를 얻을 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다음 예시 코드를 보자.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711590386538&quot; class=&quot;java&quot; style=&quot;background-color: #000000; color: #000000; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class Animal {
    public static void born(Animal a) {
        if(a instanceof Lion) {
            System.out.println(&quot;새끼를 낳았습니다.&quot;);
        } else if(a instanceof Chicken) {
            System.out.println(&quot;알을 낳았습니다.&quot;);
        } else if (a instanceof Snake) {
            System.out.println(&quot;알을 낳았습니다.&quot;);
        }
        // ...
    }
}

class Lion extends Animal { }
class Chicken extends Animal { }
class Snake extends Animal { }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 이러한 방식은 자식 클래스의 개수가 많을수록 코드가 난잡하고 길어진다는 단점이 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 아무런 내용이 없는 빈 껍데기 인터페이스를 선언하고 적절한 클래스에 implements 시킴으로써, 단순히&amp;nbsp;&lt;b&gt;타입 체크용&lt;/b&gt;으로만 사용하는 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;마커 인터페이스를 사용한 아래의 코드를 보자.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711590386541&quot; class=&quot;scala&quot; style=&quot;background-color: #000000; color: #000000; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;//새끼를 낳을 수 있다는 표식 역할을 해주는 마커 인터페이스
interface Breedable {}

class Animal {
    public static void born(Animal a) {
        if(a instanceof Breedable) {
            System.out.println(&quot;새끼를 낳았습니다.&quot;);
        } else {
            System.out.println(&quot;알을 낳았습니다.&quot;);
        }
    }
}

class Lion extends Animal implements Breedable { }
class Chiken extends Animal { }
class Snake extends Animal { }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 마커 인터페이스의 대표적인 자바 인터페이스로는 Serializabe, Cloneable 정도가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #333333; text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;인터페이스 + 추상 클래스 조합&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이처럼 각각 인터페이스와 추상 클래스의 차이점을 알기 위해 각 고유한 특징에 따른 쓰임새에 대해 알아봤지만, 사실 이 둘은 같이 조합되어서도 많이 쓰인다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;각각의 고유한 특징인&amp;nbsp;&lt;b&gt;추상 클래스의 중복 멤버 통합&lt;/b&gt;과&amp;nbsp;&lt;b&gt;인터페이스의 다중 상속&amp;nbsp;&lt;/b&gt;기능을 동시에 사용하기 위해서다. 이에 따라 둘을 같이 사용하는 여러 가지 코드 패턴들이 나왔고, 이것이&amp;nbsp;&lt;b&gt;디자인 패턴의 근간&lt;/b&gt;이 되었다고 보면 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;추상 클래스에 인터페이스 일부 구현 방법&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;추상 클래스에 인터페이스를 implements 하고, 인터페이스의 추상 메서드를 아예 구현하지 않거나, 혹은 일부만 구현하는 식으로 통합된 추상화 클래스를 만들 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711590848328&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Animal {
    void walk();
    void run();
    void breed();
}

// Animal 인터페이스를 일부만 구현하는 포유류 추상 클래스
abstract class Mammalia implements Animal {
    public void walk() { ... }
    public void run() { ... }
    // breed() 메서드는 자식 클래스에서 구체적으로 구현하도록 일부로 구현하지 않음
}
 
 // 인터페이스 + 추상 클래스를 상속하여 사용
class Lion extends Mammalia
    @Override
    public void breed() { ... }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Interface - Abstract - Concrete Class 디자인 패턴&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;객체 지향 프로그래밍을 해보면 디자인 패턴이라는 단어를 한번쯤은 들어본 적이 있을 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;디자인 패턴은 어떤 이론이라기보단&amp;nbsp;&lt;b&gt;관습에 가깝다.&lt;/b&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스는 정말 강력하지만 아쉽게도 필드는 상수만 사능하여,&amp;nbsp;&lt;b&gt;중복된 필드가 있을 경우&lt;/b&gt; 인터페이스로 해결할 수 없다는 단점이 있다. 이때는 어쩔 수 없이 추상 클래스를 사용하여야 한다. 그렇다고 추상 클래스를 남용하면 단일 상속만 되는 제한 때문에 클래스의 의존성이 커지게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 이러한 서로 간의 제약들을 극복할 방법이&amp;nbsp;&lt;b&gt;인터페이스 - 추상 클래스 - 클래스&amp;nbsp;&lt;/b&gt;구현 디자인 패턴이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 다른 개발자로부터 다음과 같은 표준화 인터페이스 코드를 전달받았다고 가정하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711591207654&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface IShape {
    void setOpacity(double opacity); //도형 투명도 지정
    void setColor(String color); // 도형 색깔 지정
    void draw(); // 도형 그리기
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;우리는 이 Shape 인터페이스에 적힌 스펙대로 도형 클래스를 설계해야 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 설계에 맞게 다음과 같이 Rectangle 과 Square 클래스를 만들고 인터페이스를 구현하여 추상 메서드를 구체화하였다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711591594371&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface IShape {
    void setOpacity(double opacity); //도형 투명도 지정
    void setColor(String color); // 도형 색깔 지정
    void draw(); // 도형 그리기
}

// 인터페이스 설계서에 따라 클래스를 구현
class Rectangle implements IShape {
    double opacity; // ! 중복
    String color; // ! 중복
    
    public void setOpacity(double opacity) { // ! 중복
        this.opacity = opacity;
    }
    public void setColor(String color) { // ! 중복
        this.color = color;
    }
    
    public void draw() {
        System.out.println(&quot;draw Rectangle with&quot;);
        System.out.println(opacity);
        System.out.println(color);
    }
}

// 인터페이스 설계서에 따라 클래스를 구현
class Square implements IShape {
    double opacity; // ! 중복
    String color; // ! 중복
    
    public void setOpacity(double opacity) { // ! 중복
        this.opacity = opacity;
    }
    public void setColor(String color) { // ! 중복
        this.color = color;
    }
    
    public void draw() {
        System.out.println(&quot;draw Square with&quot;);
        System.out.println(opacity);
        System.out.println(color);
    }
}

public class Pattern {
    public static void main(String[] args) {
        IShape[] rec = { new Rectangle(), new Square() };
        
        rec[0].setOpacity(0.7);
        rec[0].setColor(&quot;red);
        rec[0].draw();
        
        rec[1].setOpacity(0.3);
        rec[1].setColor(&quot;yellow);
        rec[1].draw();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 한 눈에 봐도 중복된 코드가 많이 보인다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스는 기본적으로 중복되는 멤버에 대해 클래스와 같이 묶어주는 역할을 못한다. 인터페이스에 선언할 수 있는 필드는 오직 상수이며, 디폴트 메서드가 있더라도 한계가 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이런 문제점을 해결할 수 있는 방법이 인터페이스(interface)와 구체 클래스(concrete class) 중간에 &lt;b&gt;추상 클래스(abstract class)를 하나 두고 공통된 부분을 모아두는 것&lt;/b&gt;이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;위의 예제에서 공통된 부분을 추상 클래스로 따로 뽑아 모으면 다음과 같아진다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711591978446&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class Shape implements IShape { // 인터페이스를 상속하는 추상 클래스
    // 중복되는 멤버들을 모아놓고
    protected double opacity;
    protected String color;
    
    public void setOpacity(double opacity) {
        this.opacity = opacity;
    }
    public void setColor(String color) {
        this.color = color;
    }
    
    // void draw(); 는 구체화 x
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 실제 구현 클래스인 Rectangle과 Square 클래스에서는 추상 클래스 Shape를 extends 하고 `draw()` 메서드 부분만 구체화해 주면 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711592056095&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Rectangle extends Shape {
    public void draw() {
        System.out.println(&quot;draw Rectangle with&quot;);
        System.out.println(opacity);
        System.out.println(color);
    }
}

class Square extends Shape {
    public void draw() {
        System.out.println(&quot;draw Rectangle with&quot;);
        System.out.println(opacity);
        System.out.println(color);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이런 식으로 자바에서 제공하는 재료들을 이용하여 각자의 위치에 맞게 여러 조합적인 코드를 짜는 것이 디자인 패턴이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다만 위의 방법은 중복 제거에 효과적이지만, 클래스 상속을 기반으로 하고 있기 때문에 다른 클래스를 상속받아야 하는 경우엔 이 패턴을 활용할 수 없다는 단점이 존재한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이런 경우에는 유명한 디자인 패턴인 Adapter 패턴을 이용하기도 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;원본 게시글&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-vs-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://inpa.tistory.com&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1711592163312&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;☕ 인터페이스 vs 추상클래스 용도 차이점 - 완벽 이해&quot; data-og-description=&quot;인터페이스 vs 추상클래스 비교 이 글을 찾아보는 독자분들은 아마도 이미 인터페이스와 추상클래스 개념을 학습한 뒤에 이 둘에 대하여 차이의 모호함 때문에 방문 했겠지만, 그래도 다시한번 &quot; data-og-host=&quot;inpa.tistory.com&quot; data-og-source-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-vs-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; data-og-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-vs-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bmDtE8/hyVDD9WnpS/03twBe7EnPodtJiGIbruaK/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/bobX7B/hyVDFmpHCS/efRbJ0uRYkkKKUxZZPydWk/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/dC1jEt/hyVDvYkRvo/ma6AcylcuFTwyjizO3lJf1/img.png?width=1235&amp;amp;height=562&amp;amp;face=0_0_1235_562&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-vs-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-vs-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bmDtE8/hyVDD9WnpS/03twBe7EnPodtJiGIbruaK/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/bobX7B/hyVDFmpHCS/efRbJ0uRYkkKKUxZZPydWk/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/dC1jEt/hyVDvYkRvo/ma6AcylcuFTwyjizO3lJf1/img.png?width=1235&amp;amp;height=562&amp;amp;face=0_0_1235_562');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;☕ 인터페이스 vs 추상클래스 용도 차이점 - 완벽 이해&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스 vs 추상클래스 비교 이 글을 찾아보는 독자분들은 아마도 이미 인터페이스와 추상클래스 개념을 학습한 뒤에 이 둘에 대하여 차이의 모호함 때문에 방문 했겠지만, 그래도 다시한번&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;inpa.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/자바</category>
      <author>진막</author>
      <guid isPermaLink="true">https://jinmak.tistory.com/26</guid>
      <comments>https://jinmak.tistory.com/26#entry26comment</comments>
      <pubDate>Thu, 28 Mar 2024 11:21:20 +0900</pubDate>
    </item>
    <item>
      <title>자바 - 인터페이스(Interface)</title>
      <link>https://jinmak.tistory.com/25</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;자바&amp;nbsp;-&amp;nbsp;인터페이스(Interface)&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그 유명한 인터페이스다. 추상 클래스를 배웠다면 다음으로 배우게 되는 것이 보통 인터페이스다. 인터페이스는 추상 클래스와 비슷한 면이 있어 혼동되는 감이 있지만, 이 기회에 인터페이스를 잘 배워두어 추상 클래스와의 차이점을 알아두는 것이 좋다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;인터페이스의 포괄적 정의&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스(interface) inter(사이) + face(얼굴)을 합성해 만든 단어로 말 그대로 어떤 사물이 맞닿아있는 면을 얘기한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스라는 용어는 꼭 자바에만 있는 것이 아니다. 위키 백과에 따르면, 인터페이스는 서로 다른 두 개의 시스템, 장치 사이에서 정보나 신호를 주고받는 경우의 접점이나 경계면이라고 한다. 즉, 사용자가 기기를 쉽게 다루기 위해 특별히 만들어 놓은 제어 장치가 되는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 정의는 그대로 자바로 옮겨져 객체의 인스턴스 메서드를 이용하는 사용자 입장에서 &lt;b&gt;&quot;그 객체의 내부 구현이 어떻든 깊이 학습할 필요없이 원하는 메서드만 호출하고 결과값만 제대로 받게 해주는 간편한 상호작용 기능이다&quot;라고&lt;/b&gt; 말할 수 있다.(추상적)&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;프로그래밍을 모르는 사람에게 인터페이스가 무엇이냐고 물어본다면, 아마 다음과 같은 GUI를 예시로 들며 말할 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1267&quot; data-origin-height=&quot;672&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt6s42/btsF7K3gHPi/GXk1hfn4CsYIbEgobkxud1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt6s42/btsF7K3gHPi/GXk1hfn4CsYIbEgobkxud1/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;nbsp;https://blog.kakaocdn.net/dn/31kPQ/btqDADnfxQT/Jw8fW7JxsmuS8NXQouyTy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt6s42/btsF7K3gHPi/GXk1hfn4CsYIbEgobkxud1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt6s42%2FbtsF7K3gHPi%2FGXk1hfn4CsYIbEgobkxud1%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;700&quot; height=&quot;371&quot; data-origin-width=&quot;1267&quot; data-origin-height=&quot;672&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;nbsp;https://blog.kakaocdn.net/dn/31kPQ/btqDADnfxQT/Jw8fW7JxsmuS8NXQouyTy0/img.png&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;이것이 인터페이스입네다...&lt;/s&gt; 이것도 인터페이스가 맞다. 이런 인터페이스는 흔히 UI(User Interface)라고 불리며 이도 결국 사용자가 프로그램을 간편하게 이용하기 위해 존재하는 인터페이스이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;사실 우리가 항상 보는 윈도우 OS의 파일 아이콘 역시 인터페이스에 속한다고 볼 수 있다. 리눅스 OS 같은 경우 터미널 명령어로 파일을 실행하고 조작해야 하지만, 윈도우에서는 GUI를 통해 컴퓨터 지식이 없는 사람도 쉽게 프로그램을 다룰 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이처럼 상호작용을 통해 사용자가 소프트웨어를 편하게 이용할 수 있게 해 주듯, 개발자가 프레임워크를 이용하여 웹서비스를 개발하는 데 있어 프레임워크의 내부 구성에 대한 학습 없이, 그저 &lt;b&gt;지원해 주는 메서드를 이용하여 간편하게 프로젝트를 개발&lt;/b&gt;할 수 있게 해주는 것이 인터페이스의 &lt;b&gt;첫 번째 역할&lt;/b&gt;이라고 할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEtWsx/btsF3F3B4ut/MfqXnZaS98WOuWmXqAE5ik/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEtWsx/btsF3F3B4ut/MfqXnZaS98WOuWmXqAE5ik/img.jpg&quot; data-alt=&quot;출처: javatutorial.net&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEtWsx/btsF3F3B4ut/MfqXnZaS98WOuWmXqAE5ik/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEtWsx%2FbtsF3F3B4ut%2FMfqXnZaS98WOuWmXqAE5ik%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;357&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: javatutorial.net&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;두 번째 인터페이스의 역할은 일종의 `스펙(Spec)`을 지정하게 하여 소프트웨어 확장에 유리하다는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;실생활로 예를 들면, 우리는 삼성 키보드든 애플 키보드든 로지텍 키보드든 &lt;b&gt;제조사에&lt;/b&gt;&amp;nbsp;&lt;b&gt;상관없이&amp;nbsp;&lt;/b&gt;컴퓨터에 연결만 하면 설치 없이 바로 이용할 수 있다. 이러한 간편함은 모두 &lt;b&gt;OS에서 미리 I/O 처리에 대해 인터페이스로 추상화&lt;/b&gt;하였기 때문에, 각 키보드 제조 회사들이 인터페이스의 구현 스펙에 따라 동작 메서드를 구현했기 때문이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; 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;pngimg.com - keyboard_PNG101855.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;866&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bk8Unw/btsF41d9n3x/mMCKiedLUO83qVhV0e3xo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bk8Unw/btsF41d9n3x/mMCKiedLUO83qVhV0e3xo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bk8Unw/btsF41d9n3x/mMCKiedLUO83qVhV0e3xo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbk8Unw%2FbtsF41d9n3x%2FmMCKiedLUO83qVhV0e3xo0%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;500&quot; height=&quot;180&quot; data-filename=&quot;pngimg.com - keyboard_PNG101855.png&quot; data-origin-width=&quot;2400&quot; data-origin-height=&quot;866&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 키보드 제조사 상관없이 우리는 간편하게 키보드를 연결만 하면 이용할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;알게 모르게 우리는 일상 생활 속에서 수많은 인터페이스의 도움을 받고 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;자바의 인터페이스&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;보통 학부생들은 인터페이스를 처음 배울 때 추상 메서드 집합이며 다중 상속이 되는 기능 정도로만 배운다. 하지만 위에서 인터페이스에 대한 친숙한 예제를 들며 소개한 이유는, 자바의 인터페이스 자체가 지닌 고유한 기능과 시스템 상호작용적인 요소로 다양한 분야에 이용될 수 있기 때문이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;상속 및 추상 메서드 강제 구현 외에도, 다양한 프레임워크에서 클래스끼리 통신하는데 자주 사용되며, 객체 지향(OOP) 프로그래밍의 전략에서 결합도(Coupling)을 낮춰 유지보수성을 늘리는 디자인 패턴으로서의 역할도 병행한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;우리가 반복되는 코드들을 줄이기 위해 for문이나 while문을 사용하듯이, 인터페이스를 사용하는&amp;nbsp; 목적은&amp;nbsp;&lt;b&gt;설계상 이점&lt;/b&gt;을 위해 사용하는 클래스라고 말할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;설계 관점에서 프로그래밍을 할 때는 전체를 볼 줄 알아야 한다. 무슨 소린지 모르겠다면 바로 인터페이스를 알아보러 가자.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;인터페이스 기본 문법&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;인터페이스 정의&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스를 작성하는 것은 추상 클래스를 작성하는 것과 같다고 봐도 된다. (인터페이스는 추상 메서드의 집합이니까)&lt;/li&gt;
&lt;li&gt;인터페이스도 필드를 선언할 수 있지만 변수가 아닌&amp;nbsp;&lt;b&gt;상수(fianl)&lt;/b&gt;로서만 정의할 수 있다.&lt;/li&gt;
&lt;li&gt;`public static final`과 `public abstract 제어자는 &lt;b&gt;생략&lt;/b&gt;이 가능하다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스에 정의된 모든 멤버에 적용되는 사항이기 때문에 편의상 생략이 가능하도록 지원한다. 생략된 제어자는 컴파일 시 컴파일러가 자동으로 추가해 준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711506235261&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface 인터페이스이름 {
    public static final 타입 상수이름 = 값;
    public abstract 타입 메서드이름(매개변수목록);
}

interface TV {
    int MAX_VOLUME = 10; // public static final 생략 가능
    int MIN_VOLUME = 10;
    
    void turnOn(); // public abstract 생략 가능
    void turnOff();
    void changeVolume(int volume);
    void changeChannel(int channel);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스 구현&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;159&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2QtoJ/btsF57dZQ5f/TYZBOQXcRUBeZDuKqQoa3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2QtoJ/btsF57dZQ5f/TYZBOQXcRUBeZDuKqQoa3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2QtoJ/btsF57dZQ5f/TYZBOQXcRUBeZDuKqQoa3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2QtoJ%2FbtsF57dZQ5f%2FTYZBOQXcRUBeZDuKqQoa3k%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;564&quot; height=&quot;159&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;159&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스도 추상 클래스처럼 그 자체로는 인스턴스를 생성할 수 없으며, 추상 클래스가 상속을 통해 완성되는 것처럼 인터페이스도 구현부를 만들어주는 클래스에서 구현(상속) 되어야 한다.&lt;/li&gt;
&lt;li&gt;해당 클래스에 인터페이스를 구현하고 싶다면, `implements` 키워드를 쓴 후에 인터페이스를 나열하면 된다.&lt;/li&gt;
&lt;li&gt;인터페이스를 상속받았다면, 자식 클래스에서 인터페이스가 포함하고 있는 추상 메서드를 구체적으로 구현한다.&lt;/li&gt;
&lt;li&gt;인터페이스의 가장 큰 특징은&amp;nbsp;&lt;b&gt;다중 구현(다중 상속)&lt;/b&gt;이 가능하다는 것이다.&lt;/li&gt;
&lt;li&gt;자식 클래스에 클래스 상속(extends)과 인터페이스 구현(implements)은 동시에 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711506675105&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Animal {
    public abstract void cry();
}

interface Pet {
    public abstract void play();
}

class Tail {
    // ...
}

class Cat extends Tail implements Animal, Pet { // 클래스와 인터페이스를 동시에 상속
    
    public void cry() {
        System.out.println(&quot;나는 냐옹이다옹!&quot;);
    }
    
    public void play() {
        System.out.println(&quot;할퀴기&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;잘 생각해 보면 인터페이스도 상속의 개념인 것 같다. 하지만 `extends` 키워드 대신 `implements`라는 '구현한다'라는 키워드를 사용하는 이유는 상속은 클래스 간의 부모 - 자식 관계를 연관시키는데 중점을 둔다면, 구현은 클래스를 확장시켜 구조를 풍부하게 만드는데 중점을 두기 때문이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스를 구현받고 추상 메서드를 구체적으로 구현할 때 접근제어자 설정에 주의해야 한다. 기본적으로 메서드를 오버라이딩(overriding) 할 때는 부모의 메서드보다 넓은 범위의 접근 제어자를 지정해야 한다는 규칙이 존재한다. 따라서 인터페이스의 추상 메서드는 기본적으로 `public abstract`가 생략된 상태이기 때문에 반드시 자식클래스의 메서드 구현부에서는 제어자를 `public`으로 설정해주어야 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스 일부 구현 (추상 클래스)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만일 클래스가 구현하는 인터페이스의 메서드 중 일부만 구현한다면 `abstract`를 붙여서 추상 클래스로 선언해야 한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;어찌 보면 당연하게 인터페이스의 추상 메서드 멤버를 그대로 상속받기 때문에, 인터페이스를 상속한 클래스에서 메서드 &lt;b&gt;구현을 하지 않으면 추상 메서드를 가진 추상 클래스가 되기 때문이다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711507173702&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Animal {
    void wald();
    void run();
    void breed();
}

// Animal 인터페이스를 일부만 구현하는 포유류 추상 클래스
abstract class Mammalia implements Animal {
    public void wald() { ... }
    public void run() { ... }
    //public void breed() 는 자식 클래스에서 구체적으로 구현하도록 일부로 구현하지 않음
}

class Lion extends Mammalia {
    @Override
    public void breed() { ... }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스가 인터페이스를 상속&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;155&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/06qbu/btsF7R2uy5C/2ZfsIgkMPcfCOFCbJbDDo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/06qbu/btsF7R2uy5C/2ZfsIgkMPcfCOFCbJbDDo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/06qbu/btsF7R2uy5C/2ZfsIgkMPcfCOFCbJbDDo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F06qbu%2FbtsF7R2uy5C%2F2ZfsIgkMPcfCOFCbJbDDo1%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;475&quot; height=&quot;155&quot; data-origin-width=&quot;475&quot; data-origin-height=&quot;155&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스끼리 상속을 통해 확장을 하듯이, 인터페이스 자체를 확장시키고 싶다면 `extends`를 통해 인터페이스를 상속하면 된다.&lt;/li&gt;
&lt;li&gt;클래스와 달리 인터페이스끼리의 상속은&amp;nbsp;&lt;b&gt;다중 상속&lt;/b&gt;이 가능하다. (메서드 구현부가 없으니 충돌 가능성이 없음)&lt;/li&gt;
&lt;li&gt;클래스의 상속과 마찬가지로 자손 인터페이스는 조상 인터페이스에 정의된 멤버를 모두 상속받는다.&lt;/li&gt;
&lt;li&gt;그러나 &lt;b&gt;필드의 경우&lt;/b&gt; 기본적으로 `static`이기 때문에 구현체를 따라가지 않게 된다. (&lt;b&gt;독립 상수)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;참고로 인터페이스에 클래스를 상속하는 행위는 불가능한데, 왜냐하면 인터페이스는 클래스와 달리 Object 클래스가 최고 조상이 아니기 때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711507964847&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Changeable {
    /* 채널을 바꾸는 기능의 메서드 */
    void change();
}

interface Powerable {
    /* 전원을 껐다 켰다 하는 기능의 메서드 */
    void power(boolean b);
}

//패널 기능과 전원 기능을 가진 인터페이스들을 하나의 인터페이스로 통합 상속
interface Contrilable extends Chanegable, Powerable {
    //인터페이스끼리 다중 상속하면 그대로 추상 멤버들을 물려 받음
}

// 클래스에 통합된 인터페이스를 그대로 상속
class MyObject implements Controlable {
    public void change() {
        System.out.println(&quot;채널을 바꾸는 기능의 메서드&quot;);
    }
    public void power(boolean b) {
        System.out.println(&quot;전원을 껐다 켰다 하는 기능의 메서드&quot;);
    }
}

public class Main {
    public static void main(String[] args) {
        //인터페이스 다형성 (인터페이스를 타입으로 취급해서 업캐스팅 가능)
        Controlable[] o = { new MyObject(), new MyObject() };
        o[0].change();
        o[0].power(true);
        
        // 각각 단일 인터페이스로도 타입으로 사용이 가능하다 (하지만 지니고 있는 추상 메서드만 사용 가능하다)
        Changeable inter1 = new Changeable();
        inter1.change();
        
        Powerable inter2 = new Powerable();
        inter2.power(true);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;인터페이스의 extends는 상속이 아니다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;인터페이스는 하나의 타입이나 규격일 뿐이지 그 자체가 하나의 객체가 되는 것이 아니다. 따라서 엄밀히 말하자면, 인터페이스 상속은 클래스의 상속처럼 부모의 속성과 동작을 물려받는 것이 아니다. 인터페이스의 상속은 &lt;b&gt;규격이나 스펙 자체 혹은 기능 자체의 선언을 물려받은 것&lt;/b&gt;이다.&lt;br /&gt;&lt;br /&gt;규격이나 스펙을 물려받아서 새로운 스펙을 만든다면 기존 여러 개의 스펙을 조합해서 하나로 묶거나 기존의 스펙을 고스란히 물려 받은 후에 다시 추가적인 기능을 가지게 하는 것이다.&lt;/blockquote&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스 상수 필드 상속 관계&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;클래스의 상속일 경우 클래스 필드 멤버끼리 상속되어 덮어 써지지만, 인터페이스의 필드들은 모두 `public static final`이기 때문에 상속을 해도 &lt;b&gt;각 필드의 멤버는 독립적으로 운용&lt;/b&gt;된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711508688778&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Iflower {
    int ex = 10; // 각각 public static final
}

interface IPlant extends Iflower {
    int ex = 20; // 각각 public static final
}

class Tulip implements IPlant {
    int ex = 30; // 그냥 인스턴스 변수
}

public class Main {
    public static void main(String[] args) {
        //클래스 타입 객체로 ex 멤버에 접근하면, 클래스 인스턴스 변수로 접근
        Tulip t = new Tulip();
        System.out.println(t.ex); // 30
        
        // 인터페이스 타입 객체로 멤버에 접근하면, 인터페이스 static 상수로 접근
        Iflower a = new Tulip();
        System.out.println(a.ex); // 10 - 좋지 않은 방법 (굳이 이렇게?)
        System.out.println(Iflower.ex); // 10 - 클래스 static 처럼 '인터페이스.멤버' 로 접근
        
        IPlant b = new Tulip();
        System.out.println(b.ex); // 20 - 좋지 않은 방법 (굳이 이렇게?)
        System.out.println(IPlant.ex); // 20 - 클래스 static 처럼 '인터페이스.멤버' 로 
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스 독립 파일&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바에서 .class 파일을 만들 수 있는 것이 꼭 클래스만 있는 것이 아니다.&lt;/li&gt;
&lt;li&gt;인터페이스 자체만으로도 클래스명으로 소스 파일을 만들 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;자바8 인터페이스 구현 메서드&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;본래 인터페이스의 메서드는 몸통(구현체)을 가질 수 없지만, java8부터&amp;nbsp;&lt;b&gt;디폴트 메서드&lt;/b&gt;와&amp;nbsp;&lt;b&gt;스태틱 메서드&lt;/b&gt;를 통해 추상 클래스처럼 &lt;b&gt;구현 메서드&lt;/b&gt;를 정의할 수 있게 되었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 이러한 점 때문에 추상 클래스와의 차이점이 거의 사라졌다고 말하기도 한다.(설 자리를 잃어가는 추상 클래스...)&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이 기능은 이전 인터페이스를 사용하여 java8의 람다 표현식 기능을 활용할 수 있도록 이전 버전과의 호환성을 위해 추가되었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Md4t6/btsF7KoO62B/YhXqQIpC9hluS8e2zKrFY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Md4t6/btsF7KoO62B/YhXqQIpC9hluS8e2zKrFY0/img.png&quot; data-alt=&quot;자바 버전 연대별 인터페이스 기능 추가 요소&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Md4t6/btsF7KoO62B/YhXqQIpC9hluS8e2zKrFY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMd4t6%2FbtsF7KoO62B%2FYhXqQIpC9hluS8e2zKrFY0%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;700&quot; height=&quot;315&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;자바 버전 연대별 인터페이스 기능 추가 요소&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;java8 버전부터 새로이 추가된 스트림이나 람다와 같은 함수형 프로그래밍을 &lt;b&gt;컬렉션(Collection) 클래스&lt;/b&gt;에서 사용하기 위해선 기존에 만들었던 인터페이스를 수정해야만 했다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그런데 만일 기존 인터페이스에 추상 메서드를 추가해버리면 이 인터페이스를 구현하고 있는 모든 구현 클래스도 변경이 필요해지기 때문에 추상 메서드 대신 &lt;b&gt;디폴트 메서드&lt;/b&gt;를 새로 추가하여 해결했다고 할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qTI87/btsF865KRus/Rq0LOrwvQUpBOITEUaKKNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qTI87/btsF865KRus/Rq0LOrwvQUpBOITEUaKKNk/img.png&quot; data-alt=&quot;Collection 인터페이스 구조도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qTI87/btsF865KRus/Rq0LOrwvQUpBOITEUaKKNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqTI87%2FbtsF865KRus%2FRq0LOrwvQUpBOITEUaKKNk%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;781&quot; height=&quot;525&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;834&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Collection 인터페이스 구조도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;default 메서드&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;디폴트 메서드 앞에 키워드 `default`를 붙이며 일반 메서드처럼 구현부가 있어야 한다.&lt;/li&gt;
&lt;li&gt;디폴트 메서드 역시 접근 제어자가 public이며 생략 가능하다.&lt;/li&gt;
&lt;li&gt;자식 클래스 (구현체)에서 default 메서드를 오버라이딩하여 재정의 가능하다.&lt;/li&gt;
&lt;li&gt;보통 인터페이스를 구현한 이후, 수정과정에서 인터페이스 모든 구현체에게 &lt;b&gt;수정 없이 광역으로 함수를 만들어주고 싶을 때&lt;/b&gt; 사용된다. (대신 모든 구현체가 원하는 값을 return하게 보장하기 위해 @implSpec 자바 doc 태그를 사용해 문서화해주어야 한다.)&lt;/li&gt;
&lt;li&gt;주의해야 할 점은 인터페이스는 Object 클래스를 상속받지 않기 때문에, Object 클래스가 제공하는 기능(equals, hasCode)은 기본 메서드로 제공받을 수 없다. 따라서 구현체가 직접 재정의를 해주어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711510136926&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Calculator {
    int plus(int i, int j);
    int multiple(int i, int j);
    
    //default로 선언함으로써 메서드를 구현할 수 있다.
    default int sub(int i, int j) {
        return i - j;
    }
}

// Calculator 인터페이스를 구현한 MyCalculator 클래스
class MyCalculator implements Calculator {
    // 추상 메서드만 구현해줌
    @Override
    public int plus(int i, int j) { return i + j; }
    @Override
    public int multiple(int i, int j) { return i * j; }
}

public class Main {
    public static void main(String[] args) {
        MyCalculator mycal = new MyCalculator();
        
        // 인터페이스 타입으로 업캐스팅
        Calculator cal = (Calculator) mycal; // 괄호 생략해도 됨
        
        //인스턴스의 인터페이스 디폴트 메서드 호출
        int value = cal.sub(5, 10);
        System.out.println(value); // -5
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스의 디폴트 메서드를 호출하기 위해선, 객체의 타입 반드시 인터페이스 타입으로 업캐스팅 해주어야 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;@implSpec 주석 문서&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;디폴트 메서드는 보통 인터페이스를 구현한 이후, 수정과정에서 인터페이스를 implements한 모든 구현체에게 수정 없이 광역으로 함수를 만들어주고 싶을 때 사용된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 A와 B 업체가 협업을 해서 어떤 인터페이스를 구현하고 있는데, 개발자가 해당 인터페이스에 기능을 추가하기 위해 추상 메서드를 추가하면, 이 인터페이스를 구현하고 있는 모든 클래스에도 수정을 가해야 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그럴 때 인터페이스에 디폴트 메서드를 추가하면, 추가된 메서드를 구현체 클래스에서 굳이 구현하지 않아도 에러 없이 사용할 수 있고, 나중에 필요하면 재정의를 통해 업그레이드된 메서드 구현도 가능해진다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;대신 모든 구현체가 원하는 값의 return을 보장해 주기 위해 @implSpec 자바 doc 태그를 사용해 문서화해주어야 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711514632582&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface IJson {
    String printJson(); // 추상 메서드
    
    /**
    *
    * @impspec
    * printJson()의 결과를 대문자 변환한다.
    */
    default void upperString() { //default 메서드
        // 구현 로직상, 추상 메서드인 printJson()의 반환 값이 정상적인 값이 될수도 있고
        // null이 되서 예외 오류가 발생할 수 있으니 @impspec 문서화를 한다.
        String text = printJson().toUpperCase();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;default 메서드 다중 상속 문제&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;클래스의 다중 상속 문제점에 대해서, 동일한 메서드명이 겹치는 경우 죽음의 다이아몬드 현상이 발생한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 다중 상속을 금지시켰더니, 이번엔 인터페이스에 디폴트 메서드라는 것이 추가되면서 인터페이스를 다중 구현할 때 클래스 다중 상속 문제와 똑같은 문제가 발생하게 되었다. 따라서 인터페이스 다중 구현에 한해저 자바는 다음과 같은 규칙을 정했다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 다중 인터페이스들 간의 디폴트 메서드 충돌&lt;/b&gt;&lt;/h5&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;똑같은 디폴트 메서드를 가진 두 인터페이스를 하나의 클래스에 구현하고 아무런 조치를 취하지 않으면&amp;nbsp;&lt;b&gt;컴파일 자체가 되지 않는다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩하여 하나로 통합하여 해결한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711515346537&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface A1 {
    public void styleA();
    
    //메서드 시그니처가 같은 디폴트 메서드
    default public void styleSame() {
        System.out.println(&quot;A1 인터페이스의 디폴트 메서드입니다. &quot;);
    }
}

interface B1 {
    public void styleB();
    
    // 메서드 시그니처가 같은 디폴트 메서드
    default public void styleSame() {
        System.out.println(&quot;B1 인터페이스의 디폴트 메서드입니다.&quot;);
    }
}

class MultiInterface implements A1, B1 {
    @Override
    public void styleA() {}
    @Override
    public void styleB() {}
    
    // 두 인터페이스 디폴트 메서드 중 A1 인터페이스의 디폴트 메서드를 오버라이딩
    default public void styleSame() {
        System.out.println(&quot;A1 인터페이스의 디폴트 메서드입니다.&quot;);
    }
}

public class Main {
    public static void main(String[] args) {
        MultiInterface m1 = new MultiInterface();
        m1.styleSame(); // &quot;A1 인터페이스의 디폴트 메서드입니다.&quot;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 인터페이스의 디폴트 메서드와 부모 클래스 메서드 간의 충돌&lt;/b&gt;&lt;/h5&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래의 상황은 자식 클래스에서 인터페이스와 부모 클래스를 동시에 extends / implement 하였을 때&lt;b&gt; 디폴트 메서드와 인스턴스 메서드 간의 충돌&lt;/b&gt;을 가정한 상황이다.&lt;/li&gt;
&lt;li&gt;이때는 &lt;b&gt;부모 클래스의 메서드가 상속되고 디폴트 메서드는 무시&lt;/b&gt;된다.&lt;/li&gt;
&lt;li&gt;만일 인터페이스 쪽의 디폴트 메서드를 사용할 필요가 있다면, 필요한 쪽의 메서드와 같은 내용으로 그냥&amp;nbsp;&lt;b&gt;오버라이딩&lt;/b&gt;하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;클래스를 상속받는 경우&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711515967922&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface A1 {
    public void styleA();
    
    // C1 클래스와 메서드 시그니처가 같은 디폴트 메서드
    default public void styleSame() {
        System.out.println(&quot;A1 인터페이스의 디폴트 메서드입니다.&quot;);
    }
}

abstract class C1 {
    // A1 인터페이스와 메서드 시그니처가 같은 인스턴스 메서드
    public void styltSame() {
        System.out.println(&quot;C1 클래스의 인스턴스 메서드입니다.&quot;);
    }
}

// 메서드 시그니처가 같은 두 추상화를 동시에 상속
class MultiClassInterface extends C1 implements A1 {
    @Override
    public void styleA() {}
}

public class Main {
    public static void main(String[] args) {
        MultiClassInterface m1 = new MultiClassInterface();
        // 클래스의 메서드 시그니처가 우선 적용
        m1.styleSame(); // &quot; C1 클래스의 인스턴스 메서드 입니다.&quot;
        
        //마찬가지로 인터페이스 타입으로 다운캐스팅해도 클래스 인스턴스 메서드로 호출됨.
        ((A1) m1).styleSame(); // &quot;C1 클래스의 인스턴스 메서드입니다.&quot;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;인터페이스를 상속받는 경우&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1711516165156&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 메서드 시그니처가 같은 두 추상화를 동시에 상속
class MultiClassInterface extends C1 implements A1 {
    @Override
    public void styleA() {}
    
    // 클래스의 인스턴스 메서드를 무시하고 인터페이스의 디폴트 메서드를 사용하기 위해 A1을 오버라이딩
    public void styleSame() {
        System.out.println(&quot; A1 인터페이스의 디폴트 메서드입니다.&quot;);
    }
}

public class Main {
    public static void main(String[] args) {
        MultiClassInterface m1 = new MultiClassInterface();
        m1.styleSame(); // &quot; A1 인터페이스의 디폴트 메서드입니다.&quot;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. default 메서드의 super&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;상위 클래스를 상속하고 상위의 메서드를 오버라이딩하여 재정의하였을 때, 만일 부모 메서드를 호출할 일이 생긴다면 `super` 예약어를 통해 부모 메서드를 호출할 수 있었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이와 같이 인터페이스도 디폴트 메서드를 구현한 클래스에서 오버라이딩 하였을 때, `super` 키워드를 통해 인터페이스의 원래의 디폴트 메서드를 호출 가능하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다만 문법이 클래스 방식과 약간 차이가 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스의 super는 다음과 같은 구성으로 호출된다. `인터페이스명.super.디폴트메서드`&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711517021918&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface IPrint {
    default void print() {
        System.out.println(&quot;인터페이스의 디폴트 메서드입니다.&quot;);
    }
}

class MyClass implements IPrint {
    @Override
    public void print() {
        IPrint.super.print(); // 인터페이스의 super 메서드를 호출
        System.out.println(&quot;인터페이스의 디폴트 메서드를 오버라이딩한 메서드입니다.&quot;);
    }
}

public class Main {
    public static void main(String[] args) {
        MyClass cls = new MyClass();
        cls.print();
    }
}

//출력 결과
//인터페이스의 디폴트 메서드입니다.
//인터페이스의 디폴트 메서드를 오버라이딩한 메서드입니다.&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;static 메서드&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인스턴스 생성과 상관없이 인터페이스 타입으로 접근해 사용할 수 있는 메서드&lt;/li&gt;
&lt;li&gt;인터페이스 전용 static 메서드라 해서 일반 클래스의 static 메서드와 다를 바가 없다.&lt;/li&gt;
&lt;li&gt;해당 타입 관련 헬퍼 또는 유틸리티 메서드를 제공할 때, 인터페이스에 스태틱 메서드로 제공하기도 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711517463068&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface  Calculator {
    public int plus(int i, int j);
    public int multiple(int i, int j);
    
    // 디폴트 메서드 
    default int sub(int i, int j) {
        return i - j;
    }
    
    // 스태틱 메서드
    public static void explain() {
        System.out.println(&quot;interface static 메서드입니다.&quot;);
    }
}

class MyCalculator implements Calculator {
    @Override
    public int plus(int i, int j) { return i + j; }
    @Override
    public int multiple(int i, int j) { return i * j; }
}

public class Main {
    public static void main(String[] args) {
        // 클래스처럼 static 메서드를 호출하면 된다.
        Calculator.explain(); // &quot;interface static 메서드입니다.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;private 메서드&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바9 버전에 추가된 메서드&lt;/li&gt;
&lt;li&gt;인터페이스에 default, static 메서드가 생긴 이후, 이러한 메서드들의&amp;nbsp;&lt;b&gt;로직을 공통화하고 재사용&lt;/b&gt;하기 위해 생긴 메서드&lt;/li&gt;
&lt;li&gt;private 메서드도 구현부를 가져야 한다.&lt;/li&gt;
&lt;li&gt;단, private 메서드는&amp;nbsp;&lt;b&gt;인터페이스 내부에서만 돌아가는 코드&lt;/b&gt;이다. (인터페이스를 구현한 클래스에서 사용하거나 재정의 할 수 없음)&lt;/li&gt;
&lt;li&gt;따라서 인터페이스 내부에서 private 메서드를 호출할 때, &lt;b&gt;default 메서드 내부에서 호출해야 하며,&lt;/b&gt; 만일 `private static` 키워드를 붙인 메서드는 static 메서드는 static 메서드에서만 호출이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;클래스에서도 private 접근제어자를 가진 메서드를 정의하였을 때, 호출 메서드에서 private 내부 메서드를 호출하여 사용하는 것처럼 인터페이스의 private 메서드도 똑같다고 생각하면 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;단, 인터페이스는 클래스가 아니기 때문에 this 예약어를 사용할 수 없다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711518589443&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;interface Calculator {
    public int plus(int i, int j);
    public int multiple(int i, int j);
    
    
    //private 메서드
    private void printf() {
        System.out.println(&quot;private 메서드는 default 내부에서만 호출이 가능합니다.&quot;);
    }
    
    // private 스태틱 메서드
    private static void printfStatic() {
        System.put.println(&quot;private static 메서드는 static 메서드 내부에서만 호출이 가능합니다.&quot;);
    }
    
    // 디폴트 메서드
    default void callPrivate() {
        printf(); // private 메서드 호출
    }
    
    // 스태틱 메서드
    static void callPrivateStatic() {
        printfStatic(); // private 스태틱 메서드 호출
    }
}

class MyCalculator implements Calculator {
    @Override
    public int plus(int i, int j) { return i + j; }
    @Override
    public int plus(int i, int j) { return i * j; }
}

public class Main {
    public static void main(String[] args) {
        // 인터페이스 디폴트 메서드를 통한 private 메서드 호출
        Calculator c = new MyCalculator(); // 인터페이스 타입으로 업캐스팅
        c.callPrivate(); // &quot;private 메서드는 default 내부에서만 호출이 가능하다.
        
        // 인터페이스 스태틱 메서드를 통한 private static 메서드 호출
        Calculator.callPrivateStatic(); // &quot;private static 메서드는 static 메서드 내부에서만 호출이 가능하다.&quot;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스의 상수는 private으로 만들 수 없다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스는 실제 객체는 아니지만 서로 간의 약속으로 사용된다. 정해진 약속을 한쪽에서 일방적으로 수정하게 되면 문제가 발생할 수 있다. 따라서 인터페이스에 선언하는 필드들은 자동으로 `public static final` 로 완벽한 상수가 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #c0d1e7;&quot;&gt;&lt;b&gt;인터페이스의 활용&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;지금까지는 인터페이스의 다양한 문법에 대해 알아보았다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 이건 그냥 인터페이스의 사용법만 알았을 뿐 인터페이스를 어떻게 쓰는지는 아직 모른다. 인터페이스는 활용할 때 비로소 빛을 바라는데, 아마 대부분의 자바 개발자는 스프링 프레임워크를 쓰려고 할 것이다. 근데 이 스프링은 인터페이스의 집합체이다. 그러니 인터페이스의 사용법을 익히고 쓰임새를 알아두는 것은 스프링을 공부하기 위한 첫걸음이 될 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;지금부터 자바에서 인터페이스를 어떻게 사용하고 그로 인해 어떤 장점을 얻을 수 있는지 알아보는 시간을 가지자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스 다형성&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;부모클래스 타입으로 자식 클래스 타입을 포함할 수 있다는 리스코프 치환의 법칙(LSP)도 인터페이스에 그대로 적용이 가능하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;클래스가 여러 개의 인터페이스를 구현하게 되면, 결과적으로 변수의 타입으로도 다양하게 쓰일 수 있다는 것을 의미하게 된다. 인터페이스 타입으로 변수를 선언하게 되면 사용하는 입장에서는 뒤에 오는 모든 객체는 간단히&amp;nbsp;&lt;b&gt;인터페이스만 구현한 객체&lt;/b&gt;이면 되기 때문에 시스템이 더욱 유연해지는 계기를 마련한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711519532128&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Keyboard { }

class Logitec_Keyboard implements Keyboard { }

class Samsung_Keyboard implements Keyboard { }

class Apple_Keyboard implements Keyboard { }

public class Main {
    public static void main(String[] args) {
        // 인터페이스 타입 배열로 여러가지 클래스들을 한번에 타입 묶음을 할 수 있다.
        Keyboard[] k = {
            new Logitec_Keyboard(),
            new Samsung_Keyboard(),
            new Apple_Keyboard()
        };
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;또한 세간에는(?)&amp;nbsp;&lt;b&gt;인터페이스를 자료형으로 쓰는 습관&lt;/b&gt;을 들이면 프로그램은 훨씬 유용해진다고 전해 내려온다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이 말의 의미는 &quot;&lt;b&gt;객체는 클래스가 아닌 인터페이스로 참조하라&quot;라는&lt;/b&gt; 의미로 볼 수 있다. 적합한 인터페이스만 있다면 매개변수뿐 아니라 반환값, 변수, 필드를 전부 인터페이스 타입으로 선언하면 좋다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체는 인터페이스를 사용해 참조하라.&lt;/li&gt;
&lt;li&gt;적당한 인터페이스가 있다면 매개변수뿐만 아니라 반환 값, 변수, 필드를 전부 인터페이스 타입으로 선언하라.&lt;/li&gt;
&lt;li&gt;객체의 실제 클래스를 사용할 상황은&amp;nbsp;&lt;b&gt;오직&lt;/b&gt; 생성자로 생성할 때뿐이다.&lt;/li&gt;
&lt;li&gt;매개변수 타입으로 클래스보다는 인터페이스를 활용하라.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 중복이 없는 집합 자료형을 사용하기 위해 LinkedHashSet 클래스를 초기화하려 할 때, 객체의 타입을 똑같이 LinkedHashSet으로 하지 말고 인터페이스인 Set 타입으로 설정하여 선언하는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711519834812&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 나쁜 예) 클래스를 바로 타입으로 사용함
LinkedHashSet&amp;lt;Object&amp;gt; s = new LinkedHashSet&amp;lt;&amp;gt;();

//좋은 예) 인터페이스를 타입으로 사용함
Set&amp;lt;Object&amp;gt; s = new LinkedHashSet&amp;lt;&amp;gt;();&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이런 식으로 코드 구현을 해놓는다면 나중에 변수가 담긴 구현 클래스를 다른 Set 자료형 클래스로 교체하고자 할 때 그저 새 클래스의 생성자를 다시 호출해주기만 하면 되어 변경이 쉬워진다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711520075306&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 본래 LinkedHashSet으로 구현했다가 사정이 생겨 TreeSet 클래스로 변경해야한다고 하면,
// 그냥 인터페이스 타입의 변수에 재할당만 하면 된다.
Set&amp;lt;Object&amp;gt; s = new LinkedHashSet&amp;lt;&amp;gt;();
s = new TreeSet&amp;lt;&amp;gt;();&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 이런식으로 인터페이스 타입으로 선언하는 습관이 꼭 좋은 점만 있는 것은 아닌데, 나쁜 예의 경우 LinkedHashSet을 HashSet으로 변환하면, LinkedHashSet과 달리 HashSet은 반복자의 순회 순서를 보장하지 않기 때문에 나중에 로직상 문제가 될 수도 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스는 변수 선언 타입 외에도 메서드의 파라미터나 메서드의 리턴 타입으로도 많이 사용된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이 역시 추상 클래스나 상속을 이용하는 것과 차이가 없지만 인터페이스는 객체의 기능을 선언하기만 하면 되기 때문에 더 확장성 있는 구조가 되고, 상속의 단점을 보완하는 방식의 설계가 가능해진다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;무엇보다 인터페이스의 다형성의 가장 큰 특징은 바로&amp;nbsp;&lt;b&gt;다중 구현을 통한 자유로운 상속 관계&lt;/b&gt;를 만들어 클래스의 다형성보다 더욱 다채롭고 유연하게 사용이 가능하다는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;클래스의 다형성은 기본적으로 클래스의 상속에 기반을 두기 때문에, 클래스 상속은 단일 상속밖에 안 되며, 클래스끼리 의미 있는 연관 관계를 가지고 있어야 해 여러모로 제약이 많다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 인터페이스는 원할 때 `implements`를 여러 개 추가하거나 빼거나 할 수 있으니 제약이 많이 사라진다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이를 이용한 예시가 바로 다음에 나올 클래스끼리 &lt;b&gt;형제 관계&lt;/b&gt;를 맺게 해 주거나 상속을 넘어선 타입 제한도 가능하게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;형제 관계를 맺어주는 인터페이스&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;기본적으로 자바의 클래스 상속 구조는 &lt;b&gt;부모 - 자식&amp;nbsp;&lt;/b&gt;관계로만 가능하게 되어 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;만일 여러 자식들끼리 의미 있는 관계를 맺고 싶다면 또 다른 부모를 두어 다시 부모 - 자식 관계를 계층형으로 만들어 주어야 한다. 그러나 자바의 클래스 상속 구조는 단일 상속만 가능하기 때문에 만일 사용하는 클래스들이 각기 다른 부모 클래스를 상속하고 있는 상황이면 위의 자료형 타입 통합을 할 수 없게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 아무 관계도 없는 클래스들에게 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어줄 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 각기 다른 부모 클래스를 상속하고 있는 Soccer 클래스와 BassGuitar 클래스를 하나의 타입으로 묶어서 사용할 필요가 있을 때, 인터페이스를 implements 함으로써 마치 Soccer와 BassGuitar 클래스를 묶은 형제 클래스 타입 IBehavior 를 만든 것과 같다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;625&quot; data-origin-height=&quot;307&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brLDGb/btsF9BEYyji/8Tk9aeU8THZ4sR5Fl6LWIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brLDGb/btsF9BEYyji/8Tk9aeU8THZ4sR5Fl6LWIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brLDGb/btsF9BEYyji/8Tk9aeU8THZ4sR5Fl6LWIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrLDGb%2FbtsF9BEYyji%2F8Tk9aeU8THZ4sR5Fl6LWIK%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;472&quot; height=&quot;232&quot; data-origin-width=&quot;625&quot; data-origin-height=&quot;307&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 형제 타입을 구성해 놓고 아래의 코드와 같이, 인터페이스를 메서드의 &lt;b&gt;매개변수 타입&lt;/b&gt;으로 받음으로써 인터페이스에 등록된 추상 메서드를 실행하면 실제 구현 클래스의 오버라이딩한 구현 메서드를 실행하게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 자유로운 인터페이스 다형성을 통해 코드 중복을 없애고 간편화를 시켜 설계상 이점을 얻을 수 있게 되는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpajh6/btsF9C5himk/Ok6SMsKd0xJZaOheKw3KN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpajh6/btsF9C5himk/Ok6SMsKd0xJZaOheKw3KN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpajh6/btsF9C5himk/Ok6SMsKd0xJZaOheKw3KN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcpajh6%2FbtsF9C5himk%2FOk6SMsKd0xJZaOheKw3KN1%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;700&quot; height=&quot;272&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;타입 접근 제한&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이외에도 인터페이스는 일종의&amp;nbsp;&lt;b&gt;접근 제한&amp;nbsp;&lt;/b&gt;역할도 할 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이는 위의 형제 관계 역할과 매우 비슷한 개념인데, 만일 똑같은 부모를 상속하고 있는 3개의 자식들 중, 2개의 자식 클래스 타입만 받을 수 있는 메서드를 구현한다고 했을 때 이용된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다형성이랍시고 부모 클래스 타입으로 파라미터를 받아버리면, 모든 자식 클래스에게 접근을 허용하기 때문에 접근에 대한 제한이 전혀 되지 않는다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;아래의 코드를 보자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711532077680&quot; class=&quot;scala&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;class GroundUnit { }

class Marine extends GroundUnit { }
class SCV extends GroundUnit { }
class Tank extends GroundUnit { }

public class Main {
    public static void main(String[] args) {
        repait(new Marine());
    } 
   
    static void repair(GroundUnit gu) {
        // 마린은 기계가 아니기 때문에 수리는 불가능하다. 하지만 상속 관계상
        // 마린 클래스 타입이 들어와 실행될 수 있는 위험성이 존재한다.
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;위처럼 테란의 지상 유닛을 만들기 위해 Marine, SCV, Tank 클래스를 만들고 이들을 공통으로 묶을 부모 클래스 GroundUnit 클래스로 상속 관계를 맺어 주었다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 `repair()` 메서드에서 중복을 줄이기 위한 다형성 기법으로 매개변수 타입을 Ground Unit 부모 클래스 타입으로 받도록 설정하였다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 잘 생각해 보면 repair 기능은 기계 유닛만 가능하여 SCV와 Tank 클래스 타입만 들어와야 하는데 생물 유닛인 Marine 클래스 타입도 상속 관계에 의해 들어올 수 있게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;개발자도 사람이고, 사람은 늘 실수를 하기 때문에 시스템적으로 접근을 하지 못하도록 처음부터 막아야 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 별도의 Machine이라는 인터페이스를 선언하고 SCV, Tank 클래스에 implements 시킨다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 3개의 자식 중 2개의 자식만 머신이라는 타입으로&amp;nbsp;&lt;b&gt;형제 타입 관계를 맺어주면서 동시에 다른 타입의 접근 제한 &lt;/b&gt;역할도 해낼 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711532548265&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Machine { } // SCV, Tank 클래스를 통합한 타입으로 이용하는 인터페이스

class GroundUnit { }

class Marine extends GroundUnit { }
class SCV extends GroundUnit implements Machine { }
class Tank extends GroundUnit implements Machine { }

public class Main {
    public static void main(String[] args) {
        repair(new Marine()); // ! Error !
    }
    
    static void repair(Machine gu) {
        // SCV와 탱크 타입만 받을 수 있도록 Machine 인터페이스로 Marine에 접근을 제한
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;메서드 접근 제한&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이밖에도&amp;nbsp;&lt;b&gt;객체에서 사용할 수 있는 메서드를 제한&lt;/b&gt;하는 효과도 있는데, 예를 들어 A, B, C라는 인터페이스를 구현한 클래스를 반환할 때 A타입으로 변환하게 되면 외부에서는 A 인터페이스의 메서드만 보이게 된다. 따라서 별도의 접근 제한을 이용하지 않고도 사용할 수 있는 메서드 접근 제한과 마찬가지로 효과를 보게 하는 방법이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이런 이유로 오히려 거꾸로 클래스에 여러 가지 메서드를 만들어 둔 다음 인터페이스로 분리하는 작업을 진행하는 경우도 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711533443530&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface PlayMovie {
    void play();
}
interface ViewImage {
    void view();
}
interface VolumeUpDown {
    void volume();
}

class MP3 implements PlayMovie, ViewImage, VolumeUpDown {
    public void play() {}
    public void view() {}
    public void volume() {}
}

public class Main {
    public static void main(String[] args) {
        PlayMovie mp3 = new MP3(); // 3개의 구현한 인터페이스 중 하나로 객체 선언
        mp3.play(); //play() 이외의 메서드는 제한된다.
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;의존성을 제거(decoupling)&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;의존성이란 객체 지향 설계에 아주 중요한 개념으로 객체가 어떻게 소통하는지 나타내는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;만일 코드 설계를 구체 클래스로 하게 되면 객체 간의 강한 의존성이 생기게 되어 만약 코드 변경이 필요하게 되면 개발자가 아주 성가시게 될 수 있다. 따라서 클래스 간의 관계를 구성할 때 그 관계를 느슨하게 하는 것이 중요하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;그래서 클래스의 관계를 상속(extends)이 아닌 구현(implements)으로 인터페이스로 확장시킨다면, 반환 타입이나 매개변수 타입으로 다른 객체와&amp;nbsp;&lt;b&gt;소통하는 구간에 인터페이스 타입으로 사용&lt;/b&gt;함으로써, 객체 간 의존성이 줄어들어 자신과 소통하는 객체의 변화에 강한 클래스를 만들 수 있게 된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzYOtk/btsGawcfCPc/RNIyrmD3NgVtqynAhhsbM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzYOtk/btsGawcfCPc/RNIyrmD3NgVtqynAhhsbM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzYOtk/btsGawcfCPc/RNIyrmD3NgVtqynAhhsbM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYOtk%2FbtsGawcfCPc%2FRNIyrmD3NgVtqynAhhsbM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;203&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;433&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이런 의존성은 과거부터 있었던 많은 Framework에서 발전해 MVC, MVVM 패턴등으로도 승화되었고 dependency injection 등의 기술로도 사용된다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스 타입으로 통신&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 다음과 같은 코드가 있다고 하자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711534019949&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class ServiceLogic {
    //ServiceLogic 클래스의 메서드는 MapStore 클래스를 사용하기 때문에, ServiceLogic은 MapStore에 의존적이다.
    public void printInt(MapStore cls) { // 지정한 클래스 타입만 받음
        int num = cls.getNum() * 2;
        System.out.println(num);
    }
}

class MapStore {
    private int num = 10;
    
    public int getNum() {
        return this.num;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;ServiceLogic 클래스의 메서드 `printInt()`를 보면 파라미터로 MapStore 클래스 타입을 받아 MapStore 클래스의 메서드를 실행해 값을 얻고 출력하는 로직으로 구성되어 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 형태를 &lt;b&gt;ServiceLogic 클래스는 MapStore 클래스에 의존적이다라고&lt;/b&gt; 말한다. 왜냐하면 MapStore 클래스가 잘못되면 ServiceLogic 클래스의 메서드는 동작하지 않을 것이기 때문이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 이러한 의존성 관계를 없애기 위해 ClubStore 인터페이스를 만들고 MapStore 클래스에 implements 하여 구현한다. 그러면 ServiceLogic 클래스에서 만일 MapStore 객체를 사용하는 게 아닌&amp;nbsp;&lt;b&gt;오직 ClubStore 인터페이스를 이용해 통신&lt;/b&gt;함으로써 클래스 간의 의존성을 없앨 수 있는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이것을&amp;nbsp;&lt;b&gt;변경에 유리한 유연한 설계&lt;/b&gt;라고도 한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;177&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bneo9S/btsF7RJb4Ig/N3teAk0UwmHGswT0NRlZwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bneo9S/btsF7RJb4Ig/N3teAk0UwmHGswT0NRlZwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bneo9S/btsF7RJb4Ig/N3teAk0UwmHGswT0NRlZwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbneo9S%2FbtsF7RJb4Ig%2FN3teAk0UwmHGswT0NRlZwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;83&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;177&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711534469145&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface ClubStore {
    // 인터페이스 타입 상태의 객체에서 메서드를 사용하기 위해선
    // 인터페이스에도 추상 메서드 형태로 넣어져 있어야 한다.
    int getNum();
}

class ServiceLogic {
    //ServiceLogic 클래스의 메서드는 ClubStore 인터페이스를 사용함으로써 클래스 간의 의존성을 없앴다.
    public void println(ClubStore cls) {
        int num = cls.getNum() * 2;
        System.out.println(num);
    }
}

class MapStore implements ClubStore{
    private int num = 10;
    
    public int getNum() {
        return this.num;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;표준화&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;개발 시간을 단축&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스를 사용하면 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제 구현에 독립적인 프로그램을 작성하는 것이 가능하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 기존의 &lt;b&gt;클래스와 클래스 간의 직접적인 관계&lt;/b&gt;를, &lt;b&gt;인터페이스를 이용해서 간접적인 관계&lt;/b&gt;로 변경하면, 한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 메서드를 호출하는 쪽에서는 선언부만 알면 되기 때문에 인터페이스만 가지고도 프로그램을 작성할 수 있으며, 동시에 다른 한쪽에서는 인터페이스를 구현하는 클래스를 작성하면 인터페이스의 구현을 기다리지 않고 작업이 가능하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;즉, A가 B클래스의 구성 완성을 기다리지 않고, 설계도인 인터페이스를 보고 동시에 개발을 함으로써 결과적으로 개발 시간을 단축시킬 수 있는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vSFyB/btsF6hIoPuH/EnsTkLXkrsCNCDQvt2ONI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vSFyB/btsF6hIoPuH/EnsTkLXkrsCNCDQvt2ONI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vSFyB/btsF6hIoPuH/EnsTkLXkrsCNCDQvt2ONI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvSFyB%2FbtsF6hIoPuH%2FEnsTkLXkrsCNCDQvt2ONI1%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;500&quot; height=&quot;344&quot; data-origin-width=&quot;690&quot; data-origin-height=&quot;475&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;사실 이는 추상 클래스 특징과 겹치는 부분이기도 한데, 인터페이스도 결국 추상화 클래스의 일종이기 때문에 가능한 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h5 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;나중에 변경이 용이함&lt;/b&gt;&lt;/h5&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;또한 프로젝트에 사용되는 기본 틀을 인터페이스로 작성한 다음 개발자들에게 인터페이스를 구현하여 프로그램을 짜도록 하면 일관되고 정형화된 프로그램의 개발이 가능하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다바의 데이터베이스 인터페이스인 JDBC가 대표적인데, 이 추상화된 인터페이스 규칙에 따라 다양한 종류의 데이터베이스를 사용하더라도 인터페이스 구현만 잘하면 동일하게 접속할 수 있는 이유이기도 하다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; 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;blob&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;445&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOhNqb/btsF914FnXB/Oa8jBKMxwJUKSWNVap1Cs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOhNqb/btsF914FnXB/Oa8jBKMxwJUKSWNVap1Cs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOhNqb/btsF914FnXB/Oa8jBKMxwJUKSWNVap1Cs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOhNqb%2FbtsF914FnXB%2FOa8jBKMxwJUKSWNVap1Cs1%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;500&quot; height=&quot;296&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;445&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 어느 자바 어플리케이션이 있고 데이터베이스를 MySQL을 사용하고 있었는데, 만약 데이터베이스를 MySQL에서 Oravle로 변경한다고 가정하자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;본래라면 자바 어플리케이션의 DB 커넥션 코드를 변경해야 하는데, 이를 자바에서는 JDBC라는 인터페이스 그룹을 통해 데이터베이스와 관계 중개를 통해 통신한다. 그래서 자바 어플리케이션 입장에선 데이터베이스 종류는 모르고 오로지 인터페이스만을 기준으로 데이터를 읽고 쓰고 작업하게 된다. 그리고 각각의 데이터베이스 제조 밴더사들은 위의 인터페이스를 구현한 구현 클래스들을 따로 만들어 자바 언어와 연결되게 지원한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 MySQL을 쓰다가 Oravle을 쓴다고 한다면, 기존에 쓰고 있는 오라클에서 제공하는 클래스 라이브러리들을 MySQL 클래스 라이브러리 파일로 바꾸고 약간 설정만 해주면 복잡한 수정 없이 변경이 완료되는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;만일 인터페이스라는 관계 중개가 없다면 하드 코딩한 것을 통째로 바꿔야 할지도 모른다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 간단하게 변경이 가능한 이유는 자바 데이터베이스 인터페이스라는 '표준화'가 있기 때문이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: justify;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마커 인터페이스&lt;/b&gt;&lt;/h4&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;자바의 마커 인터페이스는 일반적인 인터페이스와 동일하지만 사실상 아무 메서드도 선언하지 않은 빈 껍데기 인터페이스를 말한다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들면 아래와 같다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711535598171&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Untouchable {} // 아무런 내부 내용이 없는 빈 껍데기 인터페이스&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이는 마치 구현체에 대한 역할을 정의하는 인터페이스의 역할을 다하지 못한 것처럼 보인다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;마커 인터페이스&lt;/b&gt;는 인터페이스가 다중 상속이 가능하다는 점을 이용해 그저 표시하는 용도로 쓰는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;아무 내용도 없어서 쓸모가 없어 보이지만, 마커 인터페이스의 역할은&amp;nbsp;&lt;b&gt;객체의 타입과 관련된 정보만을 제공해 주는&lt;/b&gt; 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 컴파일러와 JVM은 이 마커 인터페이스를 통해 객체에 대한 추가적인 정보를 얻을 수 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;다음 예시 코드를 보자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711536046826&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Animal {
    public static void born(Animal a) {
        if(a instanceof Lion) {
            System.out.println(&quot;새끼를 낳았습니다.&quot;);
        } else if(a instanceof Chicken) {
            System.out.println(&quot;알을 낳았습니다.&quot;);
        } else if (a instanceof Snake) {
            System.out.println(&quot;알을 낳았습니다.&quot;);
        }
        // ...
    }
}

class Lion extends Animal { }
class Chicken extends Animal { }
class Snake extends Animal { }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 이러한 방식은 자식 클래스의 개수가 많을수록 코드가 난잡하고 길어진다는 단점이 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;따라서 아무런 내용이 없는 빈 껍데기 인터페이스를 선언하고 적절한 클래스에 implements 시킴으로써, 단순히&amp;nbsp;&lt;b&gt;타입 체크용&lt;/b&gt;으로만 사용하는 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;마커 인터페이스를 사용한 아래의 코드를 보자.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711536312768&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//새끼를 낳을 수 있다는 표식 역할을 해주는 마커 인터페이스
interface Breedable {}

class Animal {
    public static void born(Animal a) {
        if(a instanceof Breedable) {
            System.out.println(&quot;새끼를 낳았습니다.&quot;);
        } else {
            System.out.println(&quot;알을 낳았습니다.&quot;);
        }
    }
}

class Lion extends Animal implements Breedable { }
class Chiken extends Animal { }
class Snake extends Animal { }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 마커 인터페이스의 대표적인 자바 인터페이스로는 Serializabe, Cloneable 정도가 있다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;지금까지 interface의 사용법과 활용법을 알아보았다. 그런데 interface를 공부했다면 반드시 드는 생각이 있다. interface를 바로 배우기 전에 추상 클래스에 대해 공부했다. 추상 클래스는 자식 클래스가 부모 클래스의 메서드를 구현하는 것이고 interface도 implements 한 인터페이스를 하위 클래스에서 구현해주어야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;얼핏 보기에 용도가 그리 다르지 않은 것 같은데 과연 추상 클래스와 interface는 무슨 차이가 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;원본 게시글&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4Interface%EC%9D%98-%EC%A0%95%EC%84%9D-%ED%83%84%ED%83%84%ED%95%98%EA%B2%8C-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC#recentEntries&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://inpa.tistory.com&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1711536970158&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;☕ 인터페이스(Interface) 문법 &amp;amp; 활용 - 완벽 가이드&quot; data-og-description=&quot;인터페이스 정의 (친숙하게 설명) 객체 지향 프로그래밍의 추상화를 배우고 추상 클래스를 접해봤다면 그 다음 접해보는 것이 인터페이스(Interface) 일 것이다. 인터페이스는 간단히 말하자면 프&quot; data-og-host=&quot;inpa.tistory.com&quot; data-og-source-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4Interface%EC%9D%98-%EC%A0%95%EC%84%9D-%ED%83%84%ED%83%84%ED%95%98%EA%B2%8C-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC#recentEntries&quot; data-og-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4Interface%EC%9D%98-%EC%A0%95%EC%84%9D-%ED%83%84%ED%83%84%ED%95%98%EA%B2%8C-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ukpm7/hyVDGen112/AVnkiEfi8LPvFASMlO2uk1/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/fm3JA/hyVDF0RSrS/sUWkt60stxTZW2hsksq0bk/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/zcZMb/hyVDs1zrDx/RH4ZOeAA4VFvj8vSniKV0K/img.png?width=900&amp;amp;height=507&amp;amp;face=0_0_900_507&quot;&gt;&lt;a href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4Interface%EC%9D%98-%EC%A0%95%EC%84%9D-%ED%83%84%ED%83%84%ED%95%98%EA%B2%8C-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC#recentEntries&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4Interface%EC%9D%98-%EC%A0%95%EC%84%9D-%ED%83%84%ED%83%84%ED%95%98%EA%B2%8C-%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC#recentEntries&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ukpm7/hyVDGen112/AVnkiEfi8LPvFASMlO2uk1/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/fm3JA/hyVDF0RSrS/sUWkt60stxTZW2hsksq0bk/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/zcZMb/hyVDs1zrDx/RH4ZOeAA4VFvj8vSniKV0K/img.png?width=900&amp;amp;height=507&amp;amp;face=0_0_900_507');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;☕ 인터페이스(Interface) 문법 &amp;amp; 활용 - 완벽 가이드&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;인터페이스 정의 (친숙하게 설명) 객체 지향 프로그래밍의 추상화를 배우고 추상 클래스를 접해봤다면 그 다음 접해보는 것이 인터페이스(Interface) 일 것이다. 인터페이스는 간단히 말하자면 프&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;inpa.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/자바</category>
      <author>진막</author>
      <guid isPermaLink="true">https://jinmak.tistory.com/25</guid>
      <comments>https://jinmak.tistory.com/25#entry25comment</comments>
      <pubDate>Wed, 27 Mar 2024 20:00:44 +0900</pubDate>
    </item>
  </channel>
</rss>