<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>티끌모아 태산</title>
    <link>https://qababa.tistory.com/</link>
    <description>안녕하세요, 꾸준히 성장하기를 원하는 성실한 개발자입니다.</description>
    <language>ko</language>
    <pubDate>Sun, 12 Jul 2026 17:20:06 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>goldpig</managingEditor>
    <image>
      <title>티끌모아 태산</title>
      <url>https://tistory1.daumcdn.net/tistory/4938153/attach/1f389e146f5d4e79b95b8d7b2b77880c</url>
      <link>https://qababa.tistory.com</link>
    </image>
    <item>
      <title>Spring Boot</title>
      <link>https://qababa.tistory.com/359</link>
      <description>&lt;h4 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;1537&quot; data-origin-height=&quot;728&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0AIOX/btsHL5rSMzW/IntKUgt086ZREk5xNIBKL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0AIOX/btsHL5rSMzW/IntKUgt086ZREk5xNIBKL0/img.png&quot; data-alt=&quot;https://start.spring.io/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0AIOX/btsHL5rSMzW/IntKUgt086ZREk5xNIBKL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0AIOX%2FbtsHL5rSMzW%2FIntKUgt086ZREk5xNIBKL0%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;1537&quot; height=&quot;728&quot; data-origin-width=&quot;1537&quot; data-origin-height=&quot;728&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://start.spring.io/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 스프링부트 프로젝트를 만들 때, 위 사이트에서 설정을 하고 다운받아 IDE에서 Open을 통해 실행하게 된다. 스프링부트란&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt; 자바 웹 프로그램을 더욱 쉽고 빠르게 만들기 위한 도구&lt;/b&gt;&lt;/span&gt;이다. 새로운 기술이라기 보다는 스프링 프레임워크를 개선한 것이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;개발 환경 설정 간소화&lt;/b&gt;: &lt;b&gt;&lt;u&gt;외부라이브러리를 최적화해 제공&lt;/u&gt;&lt;/b&gt;하기 때문에 사용자가 직접 연동할 필요가 없다. (스프링은 버전에 따라 동작하는 외부 라이브러리를 일일 찾아 연동해야 한다.)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;웹 애플리케이션 서버 내장&lt;/b&gt;: 스프링 부트는 웹 애플리케이션 서버(WAS: Web Application Server)인 톰캣을 가지고 있다. 따라서 &lt;u&gt;&lt;b&gt;웹 서비스를 jar 파일로 간편하게 배포&lt;/b&gt;&lt;/u&gt;할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;스프링 부트 개발 환경 설정&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;JDK(Java Development Kit,&lt;b&gt; 자바 개발 도구&lt;/b&gt;) 설치하기&lt;/li&gt;
&lt;li&gt;IDE(이클립스 or 인텔리제이) 설치하기. IDE는 &lt;b&gt;개발 생산성을 높여주는 도구&lt;/b&gt; 역할&lt;/li&gt;
&lt;li&gt;스프링 부트 프로젝트 만들기 (스프링 부트 3 버전은 JDK 17이상만 지원한다.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6eHu6/btsHLvEC9Nf/1QQCfdqaXsCKAd8wpq1H8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6eHu6/btsHLvEC9Nf/1QQCfdqaXsCKAd8wpq1H8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6eHu6/btsHLvEC9Nf/1QQCfdqaXsCKAd8wpq1H8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6eHu6%2FbtsHLvEC9Nf%2F1QQCfdqaXsCKAd8wpq1H8k%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;554&quot; height=&quot;184&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;184&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;774&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bymNox/btsHMudTrkB/lJ1TMtFIfSArm9Zo3bOQEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bymNox/btsHMudTrkB/lJ1TMtFIfSArm9Zo3bOQEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bymNox/btsHMudTrkB/lJ1TMtFIfSArm9Zo3bOQEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbymNox%2FbtsHMudTrkB%2FlJ1TMtFIfSArm9Zo3bOQEK%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;774&quot; height=&quot;380&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;380&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;b&gt;H2 Database&lt;/b&gt;: 자료를 저장하기 위한 데이터베이스&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Mustache&lt;/b&gt;: 화면을 만들기 위해 필요한 도구&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Spring Data JPA&lt;/b&gt;: 데이터베이스를 좀 더 편리하게 다루게 해주는 도구&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;트러블 슈팅&lt;/h4&gt;
&lt;pre id=&quot;code_1717398259694&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;A problem occurred configuring root project 'toy'.
&amp;gt; Could not resolve all artifacts for configuration ':classpath'.
   &amp;gt; Could not resolve org.springframework.boot:spring-boot-gradle-plugin:3.3.0.
     Required by:
         project : &amp;gt; org.springframework.boot:org.springframework.boot.gradle.plugin:3.3.0
      &amp;gt; No matching variant of org.springframework.boot:spring-boot-gradle-plugin:3.3.0 was found. The consumer was configured to find a library for use during runtime, compatible with Java 11, packaged as a jar, and its dependencies declared externally, as well as attribute 'org.gradle.plugin.api-version' with value '8.7' but:
          - Variant 'apiElements' declares a library, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares a component for use during compile-time, compatible with Java 17 and the consumer needed a component for use during runtime, compatible with Java 11
              - Other compatible attribute:
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.7')
          - Variant 'javadocElements' declares a component for use during runtime, and its dependencies declared externally:
              - Incompatible because this component declares documentation and the consumer needed a library
              - Other compatible attributes:
                  - Doesn't say anything about its elements (required them packaged as a jar)
                  - Doesn't say anything about its target Java version (required compatibility with Java 11)
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.7')
          - Variant 'mavenOptionalApiElements' declares a library, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares a component for use during compile-time, compatible with Java 17 and the consumer needed a component for use during runtime, compatible with Java 11
              - Other compatible attribute:
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.7')
          - Variant 'mavenOptionalRuntimeElements' declares a library for use during runtime, packaged as a jar, and its dependencies declared externally:
              - Incompatible because this component declares a component, compatible with Java 17 and the consumer needed a component, compatible with Java 11
              - Other compatible attribute:
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.7')
          - Variant 'modernGradleRuntimeElements' declares a library for use during runtime, packaged as a jar, and its dependencies declared externally, as well as attribute 'org.gradle.plugin.api-version' with value '8.7':
              - Incompatible because this component declares a component, compatible with Java 17 and the consumer needed a component, compatible with Java 11
          - Variant 'runtimeElements' declares a library for use during runtime, packaged as a jar, and its dependencies declared externally, as well as attribute 'org.gradle.plugin.api-version' with value '7.5':
              - Incompatible because this component declares a component, compatible with Java 17 and the consumer needed a component, compatible with Java 11
          - Variant 'sourcesElements' declares a component for use during runtime, and its dependencies declared externally:
              - Incompatible because this component declares documentation and the consumer needed a library
              - Other compatible attributes:
                  - Doesn't say anything about its elements (required them packaged as a jar)
                  - Doesn't say anything about its target Java version (required compatibility with Java 11)
                  - Doesn't say anything about org.gradle.plugin.api-version (required '8.7')

* Try:
&amp;gt; Review the variant matching algorithm at https://docs.gradle.org/8.7/userguide/variant_attributes.html#sec:abm_algorithm.
&amp;gt; No matching variant errors are explained in more detail at https://docs.gradle.org/8.7/userguide/variant_model.html#sub:variant-no-match.
&amp;gt; Run with --stacktrace option to get the stack trace.
&amp;gt; Run with --info or --debug option to get more log output.
&amp;gt; Run with --scan to get full insights.
&amp;gt; Get more help at https://help.gradle.org.
BUILD FAILED in 99ms&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 부트 프로젝트를 다운받아 빌드하는 과정에서 오류가 발생했다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;오류 원인&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 부트 버전 3이상부터는 JDK가 17이상이어야 한다. 처음 인텔리제이스에는 아래와 같이 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;버전이 잘못 초기화 되어있는 것&lt;/b&gt;&lt;/span&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;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xOkDl/btsHNcw2CBV/QzYMB89XYTOfPQ96e4sSY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xOkDl/btsHNcw2CBV/QzYMB89XYTOfPQ96e4sSY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xOkDl/btsHNcw2CBV/QzYMB89XYTOfPQ96e4sSY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxOkDl%2FbtsHNcw2CBV%2FQzYMB89XYTOfPQ96e4sSY1%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;360&quot; data-origin-width=&quot;978&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 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;606&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1Tf6D/btsHLGsvKYw/5EXZTN8KjpWongIGn96GI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1Tf6D/btsHLGsvKYw/5EXZTN8KjpWongIGn96GI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1Tf6D/btsHLGsvKYw/5EXZTN8KjpWongIGn96GI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1Tf6D%2FbtsHLGsvKYw%2F5EXZTN8KjpWongIGn96GI0%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;606&quot; height=&quot;132&quot; data-origin-width=&quot;606&quot; data-origin-height=&quot;132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;Grade JVM을 수정&lt;/b&gt;&lt;/span&gt;한 후 빌드를 실행하면 성공적으로 빌드가 됨을 확인할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;971&quot; data-origin-height=&quot;121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQPEFJ/btsHNDVeSbh/tDksZKoEeDVseov2v0cyH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQPEFJ/btsHNDVeSbh/tDksZKoEeDVseov2v0cyH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQPEFJ/btsHNDVeSbh/tDksZKoEeDVseov2v0cyH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQPEFJ%2FbtsHNDVeSbh%2FtDksZKoEeDVseov2v0cyH1%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;971&quot; height=&quot;121&quot; data-origin-width=&quot;971&quot; data-origin-height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/스프링</category>
      <author>goldpig</author>
      <guid isPermaLink="true">https://qababa.tistory.com/359</guid>
      <comments>https://qababa.tistory.com/359#entry359comment</comments>
      <pubDate>Mon, 3 Jun 2024 16:58:36 +0900</pubDate>
    </item>
    <item>
      <title>CI/CD를 왜 배우는 걸까?</title>
      <link>https://qababa.tistory.com/358</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅CI/CD란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CI/CD란 Continuous &lt;b&gt;Integration&lt;/b&gt;, Continuous &lt;b&gt;Deployment&lt;/b&gt;라는 의미를 갖고 있다. 쉽게 말해 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;CI/CD는 테스트(Test), 통합(Merge), 배포 (Deploy)의 과정을 자동화하는 걸&lt;/b&gt;&lt;/span&gt; 의미한다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;CI/CD를 왜 배울까?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어, 서버를 AWS EC2에 배포하고 운영하다보면 코드 수정 혹은 새로운 기능을 추가하는 일이 많아진다. 그러면 새로운 기능에 대한 코드를 작성한 후 Commit을 한다. 그런 뒤 브런치에 Merge를 하고 배포를 한다. 배포를 할 때, 직접 수동으로 컴퓨터 서버 (ex. AWS EC2)에 접속해서 새로운 코드를 다운받아 실행시켜야한다.&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;b&gt;새로운 기능 추가 또는 코드의 수정이 일어날 때마다 반복하기란 &lt;u&gt;너무 귀찮은 일&lt;/u&gt;&lt;/b&gt;이다. 그래서 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;이런 반복적인 과정을 자동화 시키기 위해서 CI/CD를 배우는 것&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CI/CD 과정은 일반적으로 다음과 같은 과정으로 일어난다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ExgTS/btsHLEHsRTY/OZSGESVz4shskTPptKULMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ExgTS/btsHLEHsRTY/OZSGESVz4shskTPptKULMK/img.png&quot; data-alt=&quot;출처 :&amp;amp;nbsp; https://www.performetriks.com/post/load-test-in-a-cicd-environment&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ExgTS/btsHLEHsRTY/OZSGESVz4shskTPptKULMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FExgTS%2FbtsHLEHsRTY%2FOZSGESVz4shskTPptKULMK%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;747&quot; height=&quot;184&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;184&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 :&amp;nbsp; https://www.performetriks.com/post/load-test-in-a-cicd-environment&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 기능을 개발하고 완료해서 Commit을 찍으면 빌드가 되게 셋팅된다. 빌드가 완료되면 작성한 테스트 코드를 실행시킨다. ( 테스트 코드를 작성하지 않은 서비스에서는 이 과정을 생략하기도 한다. ) 그런 뒤 테스트가 통과되면 서버 컴퓨터에 최신 코드가 배포된다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅CI/CD를 구축할 때 사용할 Github Actions&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CI/CD를 구축할 때 사용하는 툴은 여러가지가 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Github Actions - 별도의 서버 구축 필요 없음&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Jenkins - 별도의 서버 구축 필요&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Circle CI&lt;/li&gt;
&lt;li&gt;Travis CI&amp;nbsp;&lt;/li&gt;
&lt;li&gt;등등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 중에서 현업에서&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt; 많이 사용하면서, 무료로 사용할 수 있고, 빌드용 서버가 따로 필요없는&lt;/b&gt;&lt;/span&gt; Github Actions를 활용해서 CI/CD를 구축할 수 있다. 실제 현업에서는 Github Actions 뿐만 아니라 Jenkins도 많이 활용한다. 둘 중 무엇을 사용해도 CI/CD 구성을 전부 할 수 있다. 그러므로 &lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;0&quot;&gt;&lt;u&gt;&lt;b&gt;Github Actions를 사용할 지, Jenkins를 사용할 지는 장단점을 비교해서 상황에 맞게 선택&lt;/b&gt;&lt;/u&gt;하면 된다. 개인적으로 &lt;b&gt;추천하는 툴은 Github Actions&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Jenkins의 &lt;u&gt;&lt;b&gt;단점은 별도의 서버를 구축해야 한다는 점&lt;/b&gt;&lt;/u&gt;이다. 하지만 Github Actions는 &lt;b&gt;빌드용 서버 구축 없이 Github에 내장되어 있는 Github Actions 기능을 사용&lt;/b&gt;할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Github Actions는 비용적인 측면도 유리하고 셋팅하는 데 시간도 적게 걸린다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Github Actions를 활용한 전체적인 CI/CD 흐름&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Github Actions를 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;로직을 실행시킬 수 있는 일종의 컴퓨터&lt;/b&gt;&lt;/span&gt;라고 생각하면 된다. 그렇기 때문에 CI/CD과정에서 Github Actions는 &quot;빌드, 테스트, 배포&quot;에 대한 로직을 실행시키는 역할을 하게 된다. CI/CD의 구성은 다양하지만 일반적으로 아래의 흐름을 같는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;139&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EsYqS/btsHKPCM9Zd/Np3j9bIeRjMm9tQjZBPkuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EsYqS/btsHKPCM9Zd/Np3j9bIeRjMm9tQjZBPkuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EsYqS/btsHKPCM9Zd/Np3j9bIeRjMm9tQjZBPkuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEsYqS%2FbtsHKPCM9Zd%2FNp3j9bIeRjMm9tQjZBPkuK%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;757&quot; height=&quot;139&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;139&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;코드 작성 후 Commit&lt;/li&gt;
&lt;li&gt;Github에 push&lt;/li&gt;
&lt;li&gt;Push를 감지해서 Github Actions에 작성한 로직이 실행된다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;빌드(Buid)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;테스트(Test)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서버로 배포(Deploy)&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;서버에서 배포된 최신 코드로 서버를 재실행&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>백엔드/DevOps</category>
      <author>goldpig</author>
      <guid isPermaLink="true">https://qababa.tistory.com/358</guid>
      <comments>https://qababa.tistory.com/358#entry358comment</comments>
      <pubDate>Sun, 2 Jun 2024 23:38:05 +0900</pubDate>
    </item>
    <item>
      <title>백엔드 CI/CD에 필요한 AWS 지식</title>
      <link>https://qababa.tistory.com/357</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅배포란(Deployment)?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포란 내가&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt; 만든 서비스를 다른 사용자들이 인터넷을 통해서 사용할 수 있게 만드는 것&lt;/b&gt;&lt;/span&gt;을 의미한다. 쉽게 말해 우리가 만든 웹 페이지나 서버를 다른 사람들이 사용하려면 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;인터넷 상에 배포&lt;/b&gt;&lt;/span&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;655&quot; data-origin-height=&quot;321&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Syd7d/btsHMx1ZgGr/8ftBt9h9qPtc3f4Yi2kEUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Syd7d/btsHMx1ZgGr/8ftBt9h9qPtc3f4Yi2kEUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Syd7d/btsHMx1ZgGr/8ftBt9h9qPtc3f4Yi2kEUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSyd7d%2FbtsHMx1ZgGr%2F8ftBt9h9qPtc3f4Yi2kEUK%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;655&quot; height=&quot;321&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;321&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 자신의 컴퓨터에서 개발을 할 때는 '&lt;b&gt;localhost&lt;/b&gt;' 라는 주소로 테스트도하고 개발을 한다. 하지만 이 localhost는 다른 컴퓨터에서 접근이 불가능한 주소다. 그렇기 때문에 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;배포를 하게되면 고유의 IP주소나 도메인 주소를 부여받게되고, 다른 컴퓨터에서 그 주소로 접속할 수 있게 된다&lt;/b&gt;&lt;/span&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 어떤 서비스를 완성했으면, 그것을 다른 사용자들이 사용할 수 있도록 배포를 해줘야한다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅EC2(Elastic Compute Cloud)란 무엇인가?&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2란 쉽게 말해 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;컴퓨터를 빌려서 원격으로 접속해 사용하는 서비스&lt;/b&gt;&lt;/span&gt;다. 쉽게 말해 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;하나의 컴퓨터&lt;/b&gt;&lt;/span&gt;를 의미한다. 그렇다면 EC2를 왜 배울까? 배포를 하기 위해서는 컴퓨터가 필요한데, 내 컴퓨터를 활용할 수 있다. 하지만 내 컴퓨터로 서버를 배포하게 되면&lt;b&gt;&lt;u&gt; 24시간 동안 컴퓨터를 켜&lt;/u&gt;&lt;/b&gt;놔야한다. 또한 인터넷을 통해 내 컴퓨터에 접근할 수 있게 만들다보니 &lt;b&gt;보안상의 위험&lt;/b&gt;이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제점을 해결하기 위해서 내 컴퓨터를 사용하지 않고, &lt;b&gt;AWS EC2라는 컴퓨터를 빌려서 해결&lt;/b&gt;할 수 있다. 이 외에도 AWS EC2는 여러가지 부가 기능(로깅, 오토스케일링, 로드밸런싱 등)을 많을 갖고 있다. 실제 현업에서도 서버를 배포할 때 AWS EC2를 많이 활용한다.&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;u&gt;&lt;b&gt;백엔드 서버를 배포해야 할 때면 EC2에 서버를 배포해서 사용&lt;/b&gt;&lt;/u&gt;한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;프론트엔드 웹 페이지를 배포할 때는 AWS EC2를 활용할 수 있지만 &lt;u&gt;&lt;b&gt;vercel, netlify 또는 AWS S3&lt;/b&gt;&lt;/u&gt;를 사용해서 주로 배포한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;IP와 Port의 개념&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IP란 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;host에 대한 식별자로, 네트워크 상에서 특정 컴퓨터를 가리키는 주소&lt;/b&gt;&lt;/span&gt;다. Port란 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;한 컴퓨터 내에서 실행되고 있는 특정 프로그램의 주소&lt;/b&gt;&lt;/span&gt;를 의미한다. 예를 들어, 외부에서 특정 컴퓨터 내부에 있는 Spring Boot라는 서버에 통신을 하고 싶다고 가정하자. 하지만 외부에서 IP주소만 알아서는 실행되고 있는 여러 프로그램 중 어떤 프로그램과 통신을 해야 할 지 알 수가 없다. 그래서 &lt;b&gt;특정 서버와 통신을 할 때는 &lt;u&gt;IP 주소&lt;/u&gt;와 서버가 실행되고 있는 &lt;u&gt;포트 번호&lt;/u&gt;&lt;/b&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;b&gt;22번 (SSH, Secure Shell Protocol):&lt;/b&gt; 원격 접속을 위한 포트 번호. EC2 인스턴스에 연결할 때, 22번 포트를 사용한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;80번 (HTTP):&lt;/b&gt; HTTP로 통신을 할 때 사용한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;442 (HTTPS):&lt;/b&gt; HTTPS로 통신을 할 때 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 포트 번호는 일반적으로 정해져 있는 규약이지 반드시 지켜야하는 것은 아니다. 예를 들어, 특정 서버와 HTTP 통신을 할 때 80번 포트를 쓰지 않고 3000번 포트나 8080번 포트를 써도 상관 없다.&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/DevOps</category>
      <author>goldpig</author>
      <guid isPermaLink="true">https://qababa.tistory.com/357</guid>
      <comments>https://qababa.tistory.com/357#entry357comment</comments>
      <pubDate>Sun, 2 Jun 2024 23:05:26 +0900</pubDate>
    </item>
    <item>
      <title>⭐다형성과 설계</title>
      <link>https://qababa.tistory.com/356</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;객체 지향 프로그래밍&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체지향 프로그래밍은 컴퓨터 프로그램을 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;객체들의 모임&lt;/b&gt;&lt;/span&gt;으로 보는 것이다. 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있다. (&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;협력&lt;/b&gt;&lt;/span&gt;) 그리고 프로그램을 &lt;b&gt;유연하고 변경 용이&lt;/b&gt;하게 만든다. 즉, 레고 블록 조립하듯이 개발을 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;다형성(Polymorphism)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 지향 프로그래밍의 가장 핵심적인 특징은 &lt;b&gt;다형성&lt;/b&gt;이다. 다형은 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;역할과 구현을 분리&lt;/b&gt;&lt;/span&gt;시킨다. 아래 그림과 &lt;u&gt;&lt;b&gt;자동차의 역할과 자동차의 구현을 분리&lt;/b&gt;&lt;/u&gt;시킨다. 다형성의 본질은 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경&lt;/b&gt;&lt;/span&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;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beKkYc/btsHKNLBITq/Om19K5mKIyOISu7XrkLjR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beKkYc/btsHKNLBITq/Om19K5mKIyOISu7XrkLjR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beKkYc/btsHKNLBITq/Om19K5mKIyOISu7XrkLjR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeKkYc%2FbtsHKNLBITq%2FOm19K5mKIyOISu7XrkLjR0%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;336&quot; data-origin-width=&quot;708&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 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;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;클라이언트(운전자)는 역할(인터페이스)만 알면 된다&lt;/b&gt;&lt;/span&gt;. 즉, 인터페이스를 구현하는 K3, 아반떼, 테슬라 모델3의 세부적인 &lt;b&gt;내부 구조를 몰라도&lt;/b&gt; 된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;클라이언트는 구현 대상의 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;내부 구조가 변경되어도 영향을 받지 않는다&lt;/b&gt;&lt;/span&gt;. K3, 아반떼 등의 내부 구조가 바뀌어도 영향X&lt;/li&gt;
&lt;li&gt;클라이언트는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;구현 대상 자체를 변경해도 영향을 받지 않는다&lt;/b&gt;&lt;/span&gt;. 즉, 자동차가 K3이든, 아반떼로 바뀌든 운전자에게는 영향을 주지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 지향 프로그래밍의 핵심은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다형성&lt;/b&gt;&lt;/span&gt;이다. 디자인 패턴 대부분은 다형성을 활용하는 것이다. 스프링의 핵심인 제어의 역전(IoC), 의존관계 주입(DI)도 결국 다형성을 활용하는 것이다. 그리고 프레임워크인 &lt;b&gt;스프링을 활용하면 레고 블럭 조립하듯이 구현을 편리하게 변경할 수 있다&lt;/b&gt;.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;역할과 구현 예제&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다형성을 활용하면 역할과 구현을 분리해서, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;클라이언트 코드의 변경 없이 구현 객체를 변경&lt;/b&gt;&lt;/span&gt;할 수 있다. 다음 관계에서 &lt;b&gt;Driver가 클라이언트&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;805&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ekzAfB/btsHLVveyyb/BvowWk6axjVjgjQbx1GjPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ekzAfB/btsHLVveyyb/BvowWk6axjVjgjQbx1GjPK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ekzAfB/btsHLVveyyb/BvowWk6axjVjgjQbx1GjPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FekzAfB%2FbtsHLVveyyb%2FBvowWk6axjVjgjQbx1GjPK%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;805&quot; height=&quot;370&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;370&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;운전자(Driver)는 &lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Car의 역할에만 의존한다. 구현인 K3, Model3 자동차에 의존하지 않는다&lt;/span&gt;&lt;/b&gt;.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Driver 클래스는 Car car 멤버변수를 갖는다. 따라서 Car 인터페이스를 참조한다.&lt;/li&gt;
&lt;li&gt;인터페이스를 구현한 K3Car, Model3Car에 의존하지 않고, Car 인터페이스에만 의존한다.&lt;/li&gt;
&lt;li&gt;의존은 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;클래스 의존 관계&lt;/b&gt;&lt;/span&gt;를 뜻한다. 즉 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;클래스 상에서 어떤 클래스를 알고 있는가&lt;/b&gt;&lt;/span&gt;를 뜻한다. Driver 클래스 코드를 보면 Car 인터페이스만 사용하는 것을 알 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Car는 자동차의 역할이고 인터페이스다. K3Car, Model3Car 클래스가 인터페이스를 구현한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1717308941269&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Driver {
    private Car car; // 멤버변수

    public void setCar(Car car) {
        System.out.println(&quot;자동차를 설정합니다. &quot; + car);
        this.car = car;
    }

    public void drive(){
        System.out.println(&quot;자동차를 운전합니다.&quot;);
        car.startEngine();
        car.pressAccelerator();
        car.offEngine();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Driver는 멤버 변수로 Car car를 갖는다. setCar(Car car)를 통해 &lt;u&gt;멤버 변수에 자동차를 설정&lt;/u&gt;한다. 외부에서 누군가 이 메서드를 호출해주어야 Driver는 새로운 자동차를 참조하거나 변경할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;drive() 메서드는 Car 인터페이스가 제공하는 기능들을 통해 자동차를 운전한다.&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;800&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLdg1a/btsHLD9vmf1/J2K0iCyZz8DaPIvYRHdbK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLdg1a/btsHLD9vmf1/J2K0iCyZz8DaPIvYRHdbK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLdg1a/btsHLD9vmf1/J2K0iCyZz8DaPIvYRHdbK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLdg1a%2FbtsHLD9vmf1%2FJ2K0iCyZz8DaPIvYRHdbK0%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;296&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;296&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;driver.setCar(k3Car)를 호출해서 Driver의 Car car 필드가 &lt;b&gt;K3Car의 인스턴스를 참조&lt;/b&gt;하도록 한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;driver.drive()를 호출하면 x001을 참조한다. &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;car 필드가 Car 타입이므로 Car 타입을 찾아서 실행하지만 메서드 오버라이딩에 의해 K3Car의 기능이 호출&lt;/b&gt;&lt;/span&gt;된다.&amp;nbsp;&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;798&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q1QB1/btsHKS0qOSG/VkWzgsy0B5JjffTPo0rHRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q1QB1/btsHKS0qOSG/VkWzgsy0B5JjffTPo0rHRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q1QB1/btsHKS0qOSG/VkWzgsy0B5JjffTPo0rHRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ1QB1%2FbtsHKS0qOSG%2FVkWzgsy0B5JjffTPo0rHRK%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;546&quot; data-origin-width=&quot;798&quot; data-origin-height=&quot;546&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;Model3Car를 생성한다.&lt;/li&gt;
&lt;li&gt;driver.setCar(model3Car)를 호출해서 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;Driver의 Car car 필드가 Model3Car의 인스턴스를 참조&lt;/b&gt;&lt;/span&gt;하도록 변경한다.&lt;/li&gt;
&lt;li&gt;driver.drive()를 호출하면 x002을 참조한다. car 필드가 Car 타입이므로 Car 타입을 찾아서 실행하지만 메서드 오버라이딩에 의해 Model3Car의 기능이 호출된다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⭐OCP(Open-Closed Principle) 원칙&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 객체 지향 설계 원칙 중 하나는 &lt;b&gt;OCP 원칙&lt;/b&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;b&gt;Open for extension&lt;/b&gt;: 새로운 기능의 추가나 변경 사항이 생겼을 때, &lt;u&gt;기존 코드는 확장&lt;/u&gt;할 수 있어야 한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Closed for modification&lt;/b&gt;: 기존의 코드는 &lt;u&gt;수정되지 않아야 한다&lt;/u&gt;.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 말이 좀 헷갈릴 수 있는데, 기존 코드 확장은 &lt;b&gt;인터페이스나 인터페이스를 구현하는 코드를 추가하거나 변경하는 것&lt;/b&gt;이고 기존 코드를 수정하지 않아야 한다는 것은 &lt;b&gt;클라이언트 코드를 변경하지 않는다는 뜻&lt;/b&gt;이다. 다시 말해, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;클라이언트 코드를 변경하지 않고 서버의 구현 기능을 유연하게 변경하는 것&lt;/b&gt;&lt;/span&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;803&quot; data-origin-height=&quot;353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o02VE/btsHLWOvAmq/jRKAmTk2QWLLsKKqRizt9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o02VE/btsHLWOvAmq/jRKAmTk2QWLLsKKqRizt9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o02VE/btsHLWOvAmq/jRKAmTk2QWLLsKKqRizt9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo02VE%2FbtsHLWOvAmq%2FjRKAmTk2QWLLsKKqRizt9k%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;803&quot; height=&quot;353&quot; data-origin-width=&quot;803&quot; data-origin-height=&quot;353&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트인 Driver는 인터페이스인 Car에만 의존하고 인터페이스를 구현하는 K3Car, Model3Car, NewCar에 대해서는 알지 못한다. 그렇기 때문에 새로운 차량을 추가해도 Driver의 코드는 전혀 변경하지 않는다. 차량의 종류는 계속 늘어나도 이는 마찬가지다. 즉, 기능을 확장해도 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;main()&lt;/b&gt;&lt;/span&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;b&gt;확장에 열려있다는 뜻&lt;/b&gt;: Car 인터페이스를 사용해서 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;새로운 차량을 자유롭게 추가하거나 변경&lt;/b&gt;&lt;/span&gt;할 수 있다. 그리고 Car 인터페이스를 사용하는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;클라이언트 코드인 Driver도 Car 인터페이스를 통해 새롭게 추가된 차량을 자유롭게 호출&lt;/b&gt;&lt;/span&gt;할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드 수정은 닫혀 있다는 뜻&lt;/b&gt;: 새로운 차를 추가하게 되면 기능이 추가되기 때문에 기존 코드의 수정을 불가피하다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;하지만 클라이언트 코드의 수정은 일어나지 않는다&lt;/b&gt;&lt;/span&gt;.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;변하지 않는 부분&lt;/b&gt;: 클라이언트 코드는 변하지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;변하는 부분&lt;/b&gt;: main()과 같이 새로운 차를 생성하고 Driver에게 필요한 차를 전달해주는 역할은 당연히 코드 수정이 필요하다. &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;main()은 전체 프로그램을 설정하고 조율하는 역할&lt;/b&gt;&lt;/span&gt;을 한다. 이런 부분은 OCP를 지켜도 변경이 필요하다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국, Car를 사용하는 클라이언트 코드인 Driver 코드의 변경 없이 새로운 차량을 확장할 수 있다. &lt;b&gt;다형성을 활용하고 역할과 구현을 잘 분리한 덕분에 새로운 차량을 추가해도 대부분의 핵심 코드들을 그대로 유지할 수 있게 된다&lt;/b&gt;.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;전략 패턴(Strategy Pattern)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디자인 패턴 중 가장 중요한 패턴은 전략 패턴이다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;전략 패턴은 알고리즘을 클라이언트 코드의 변경 없이 쉽게 교체&lt;/b&gt;&lt;/span&gt;할 수 있다. 위 코드처럼 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;Car인 인터페이스가 바로 전략을 정의하는 인터페이스&lt;/b&gt;&lt;/span&gt;가 되고, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;각각의 차량이 전략의 구체적인 구현&lt;/b&gt;&lt;/span&gt;이 된다. 그리고 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;전략을 클라이언트 코드(Driver)의 변경 없이 손쉽게 교체&lt;/b&gt;&lt;/span&gt;할 수 있다.&amp;nbsp;&lt;/p&gt;</description>
      <category>백엔드/JAVA</category>
      <author>goldpig</author>
      <guid isPermaLink="true">https://qababa.tistory.com/356</guid>
      <comments>https://qababa.tistory.com/356#entry356comment</comments>
      <pubDate>Sun, 2 Jun 2024 15:45:47 +0900</pubDate>
    </item>
    <item>
      <title>다형성2</title>
      <link>https://qababa.tistory.com/355</link>
      <description>&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;806&quot; data-origin-height=&quot;174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bd3ACe/btsHKaNWRrs/kfVVGKkspW6w7cLBXP2Px1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bd3ACe/btsHKaNWRrs/kfVVGKkspW6w7cLBXP2Px1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bd3ACe/btsHKaNWRrs/kfVVGKkspW6w7cLBXP2Px1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbd3ACe%2FbtsHKaNWRrs%2FkfVVGKkspW6w7cLBXP2Px1%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;806&quot; height=&quot;174&quot; data-origin-width=&quot;806&quot; data-origin-height=&quot;174&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 객체들이 있고, sound() 함수를 정의했다고 하자. &lt;u&gt;&lt;b&gt;이때, 개, 고양이, 소 말고 다른 동물을 추가하면 어떻게 될까?&lt;/b&gt;&lt;/u&gt; 새로운 클래스를 만들고 sound() 함수를 정의해야한다. 하지만 그렇게 될경우 &lt;u&gt;&lt;b&gt;중복되는 부분이 존재&lt;/b&gt;&lt;/u&gt;하게 된다. 그러면 중복되는 부분을 어떻게 제거할 수 있을까? 메서드 또는 배열? 안된다. 개, 고양이, 소 모두의&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt; 타&lt;/span&gt;입이 서로 다르기 때문에&lt;/b&gt;&lt;/span&gt; 중복되는 부분을 제거할 수 없다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;Dog, Cat, Caw가 모두 같은 타입을 사용할 수 있다면 메서드와 배열을 활용해서 코드의 중복을 제거할 수 있다는 것&lt;/b&gt;&lt;/span&gt;이다. ❗다형성의 핵심인 &lt;b&gt;다형적 참조와 메서드 오버라이딩&lt;/b&gt;을 활용하면 Dog, Cat, Caw가 모두 같은 타입을 사용하고, 각자 자신의 메서드도 호출할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;다형성 활용1&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;866&quot; data-origin-height=&quot;539&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eo1WXo/btsHKKHQ3y0/KU4fScuRYnI3Hnh0riVQj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eo1WXo/btsHKKHQ3y0/KU4fScuRYnI3Hnh0riVQj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eo1WXo/btsHKKHQ3y0/KU4fScuRYnI3Hnh0riVQj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feo1WXo%2FbtsHKKHQ3y0%2FKU4fScuRYnI3Hnh0riVQj1%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;627&quot; height=&quot;390&quot; data-origin-width=&quot;866&quot; data-origin-height=&quot;539&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다형성을 활용하기 위해 Animal(동물) 부모 클래스를 만들고 sound() 메서드를 정의한다. 그리고 이 메서드는 자식 클래스에서 오버라이딩 된다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1717210597790&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        Dog dog = new Dog();
        Cat cat = new Cat();
        Caw caw = new Caw();

        soundAnimal(dog);
        soundAnimal(cat);
        soundAnimal(caw);
        }
    private static void soundAnimal(Animal animal){
        System.out.println(&quot;동물소리 테스트 시작&quot;);
        animal.sound();
        System.out.println(&quot;동물소리 테스트 종류&quot;);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;243&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caa1G8/btsHLfgpIZX/ep6uGY5KPq2THDJcVHAgA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caa1G8/btsHLfgpIZX/ep6uGY5KPq2THDJcVHAgA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caa1G8/btsHLfgpIZX/ep6uGY5KPq2THDJcVHAgA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcaa1G8%2FbtsHLfgpIZX%2Fep6uGY5KPq2THDJcVHAgA0%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;774&quot; height=&quot;243&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;243&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;예를들어, soundAnimal(dog)를 호출하면 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;soundAnimal (Animal animal)에 Dog 인스턴스가 전달&lt;/span&gt;된다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Animal animal = dog로 이해하면 되고, 부모는 자식을 담을 수 있다&lt;/span&gt;. Animal은 dog의 부모다.&lt;/li&gt;
&lt;li&gt;그러면 메서드 안에서 animal.sound() 메서드가 호출 된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;animal 변수의 타입은 Animal 이므로 Dog 인스턴스에 있는 Animal 클래스 부분을 찾아서 sound() 메서드를 실행한다. 그런데 하위 클래스인 Dog에서 sound() 메서드를 오버라이딩 했다. 따라서 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;오버라이딩한 메서드가 우선권&lt;/span&gt;을 갖는다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⭐핵심은 Animal animal 코드이다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다형적 참조&lt;/b&gt;&lt;/span&gt;로 인해 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;animal 변수는 자식인 Dog, Cat, Caw의 인스턴스를 참조&lt;/span&gt;할 수 있다. (부모는 자식을 담을 수 있다.) 또한 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;메서드 오버라이딩&lt;/b&gt;&lt;/span&gt;으로 인해 animal.sound()를 호출해도&lt;span style=&quot;background-color: #dddddd;&quot;&gt; Dog.sound, Cat.sound, Caw.sound()와 같이 각 인스턴스의 메서드를 호출&lt;/span&gt;할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;추상 클래스1&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스를 설계도에 비유한다면, 추상 클래스는 미완성 설계도에 비유할 수 있다. 따라서 실체인 인스턴스가 존재하지 않는다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;추상클래스는 상속을 통해 자식 클래스에 의해서만 완성될 수 있다&lt;/b&gt;&lt;/span&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;u&gt;상속을 목적&lt;/u&gt;으로 사용&lt;/li&gt;
&lt;li&gt;&lt;u&gt;부모 클래스 역할&lt;/u&gt;을 담당&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1717213837492&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class AbstractAnimal {...}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추상 클래스를 생성할 때, 추상이라는 의미의 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;abstract&lt;/b&gt;&lt;/span&gt; 키워드를 붙여 준다.&lt;/li&gt;
&lt;li&gt;추상 클래스는 new AbstractAnimal()와 같이 &lt;u&gt;&lt;b&gt;직접 인스턴스를 생성하지 못한다&lt;/b&gt;&lt;/u&gt;.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1717214258312&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 추상클래스 생성 불가
AbstractAnimal animal = new AbstractAnimal();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;추상 메서드 -&amp;gt; 미완성 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드는 선언부와 구현부(몸통)로 구성되어 있다. 이때, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;선언부만 작성하고 구현부는 작성되지 않은 채로 남겨둔 것이 추상메서드&lt;/b&gt;&lt;/span&gt;이다. 이는 부모 클래스를 상속 받는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;자식 클래스가 반드시 오버라이딩 해야하는 메서드&lt;/b&gt;&lt;/span&gt;이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1717213972648&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public abstract void sound();&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추상 메서드는 선언할 때, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;abstract&lt;/b&gt;&lt;/span&gt; 키워드를 붙여주면 된다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;❗추상 메서드가 하나라도 있는 클래스는 추상 클래스로 선언해야 한다&lt;/b&gt;&lt;/span&gt;. -&amp;gt; 그렇지 않으면 컴파일 오류 발생한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;❗추상 메서드는 상속 받는 자식 클래스가 반드시 오버라이딩 해서 사용해야 한다&lt;/b&gt;&lt;/span&gt;.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p 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;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;부모(Animal) 인스턴스를 생성할 문제를 근본적으로 방지&lt;/b&gt;&lt;/span&gt;해준다.&lt;/li&gt;
&lt;li&gt;추상 메서드 덕분에 새로운 동물의 자식 클래스를 만들 때, 실수로 sound()를 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;오버라이딩 하지 않을 문제를 근본적으로 방지&lt;/b&gt;&lt;/span&gt;해준다.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;추상 클래스2&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;순수 추상 클래스: 모든 메서드가 추상 메서드인 추상 클래스&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHtX7C/btsHMcQKfUc/S7sczBQoedXv3BAspTMXK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHtX7C/btsHMcQKfUc/S7sczBQoedXv3BAspTMXK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHtX7C/btsHMcQKfUc/S7sczBQoedXv3BAspTMXK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHtX7C%2FbtsHMcQKfUc%2FS7sczBQoedXv3BAspTMXK0%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;837&quot; height=&quot;522&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;522&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AbstractAnimal의 모든 기능을 자식 클래스에서 오버라이딩 해야한다. 대상 타입을 찾을 때는 호출자의 타입을 기준으로 선택한다. 처음 호출자의 타입으로 선택 후 오버라이딩을 호출한다.&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;242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SNj7Y/btsHLrgLuKz/2Bpkuk0B4LcTafKkcbiIbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SNj7Y/btsHLrgLuKz/2Bpkuk0B4LcTafKkcbiIbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SNj7Y/btsHLrgLuKz/2Bpkuk0B4LcTafKkcbiIbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSNj7Y%2FbtsHLrgLuKz%2F2Bpkuk0B4LcTafKkcbiIbk%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;242&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;242&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 메서드가 추상 메서드인 순수 추상 클래스는 코드를 실행할 바디 부분이 없다.&lt;/p&gt;
&lt;pre id=&quot;code_1717216781583&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public abstract class AbstractAnimal {
    public abstract void sound();
    public abstract void move();
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;인스턴스를 생성할 수 없다&lt;/b&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;한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;상속하는 클래스는 모든 메서드를 구현&lt;/b&gt;해야 한다. 이러한 특징은 상속받는 &lt;u&gt;&lt;b&gt;자식 클래스 입장에서 어떤 규격을 지켜서 구현해야 하는 것처럼 느껴&lt;/b&gt;&lt;/u&gt;진다. 이것은 일반적으로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터페이스&lt;/b&gt;&lt;/span&gt;와 같이 느껴진다. 이런 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;순수 추상 클래스 개념은 프로그래밍에서 매우 자주사용되고, 이를 편리하게 사용할 수 있도록 인터페이스라는 개념을 제공&lt;/b&gt;&lt;/span&gt;한다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자바는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;순수 추상클래스를 더 편리하게 사용&lt;/span&gt;할 수 있는 인터페이스 개념을 제공한다.&lt;span style=&quot;color: #ee2323;&quot;&gt; interface&lt;/span&gt; 키워드 사용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1717219106784&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 순수 추상 클래스
public interface interfaceAnimal {
    void sound(); // public abstract 생략
    void move(); // public abstract 생략
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스는 순수 추상 클래스와 같다. 여기에 약간의 편의 기능이 추가된 것 뿐이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;인터페이스의 메서드는 모두&lt;b&gt; public, abstract &lt;/b&gt;&lt;/span&gt;이다.&lt;/li&gt;
&lt;li&gt;메서드에 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;public abstract 를 생략&lt;/span&gt;할 수 있다. 참고로 생략을 권장한다.&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_1717219556903&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public interface InterfaceAnimal {
    public static final double MY_PI = 3.14;
   }
   
public interface InterfaceAnimal {
    double MY_PI = 3.14; // public static final  생략가능
   }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스에서 멤버 변수는&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt; public, static, final&lt;/span&gt; &lt;/b&gt;이 모두 포함되어 있다고 간주하고 생략 가능하다. &lt;u&gt;&lt;b&gt;final은 변수의 값을 한번 설정하면 바꿀 수 없다는 뜻&lt;/b&gt;&lt;/u&gt;이다.&amp;nbsp;&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;839&quot; data-origin-height=&quot;514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/whZjz/btsHKlon8hf/Ev2stAKeFjsQt5B8PiK07k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/whZjz/btsHKlon8hf/Ev2stAKeFjsQt5B8PiK07k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/whZjz/btsHKlon8hf/Ev2stAKeFjsQt5B8PiK07k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwhZjz%2FbtsHKlon8hf%2FEv2stAKeFjsQt5B8PiK07k%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;839&quot; height=&quot;514&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;514&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스는&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt; class 대신에 interface&lt;/b&gt;&lt;/span&gt; 키워드를 사용한다. 그리고 인터페이스를 상속받을 때는 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;extends 대신에 implements&lt;/b&gt;&lt;/span&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;834&quot; data-origin-height=&quot;244&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PyQzw/btsHLuLd1pY/wyyrZ57AKIn9e2AtbdBZYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PyQzw/btsHLuLd1pY/wyyrZ57AKIn9e2AtbdBZYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PyQzw/btsHLuLd1pY/wyyrZ57AKIn9e2AtbdBZYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPyQzw%2FbtsHLuLd1pY%2FwyyrZ57AKIn9e2AtbdBZYk%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;834&quot; height=&quot;244&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;244&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;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: #9feec3;&quot;&gt;&lt;b&gt; 클래스, 추상 클래스, 인터페이스는 프로그램 코드, 메모리 구조상 모두 똑같다&lt;/b&gt;&lt;/span&gt;. .class로 다 이뤄진다. 인터페이스를 작성할 때도 .java에 인터페이스를 정의한다. 그렇기 때문에 인터페이스는 추상 클래스와 비슷하다고 생각하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;상속 vs 구현&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 클래스의 기능을 자식 클래스가 상속 받을 때, 클래스는 상속 받는다고 표현하지만 부모 인터페이스의 기능을 자식이 상속 받을 때는 인터페이스를 구현한다고 표현한다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;상속은 부모의 기능을 물려받는 것&lt;/b&gt;&lt;/span&gt;이 목적이다. 하지만 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;인터페이스는 모든 메서드가 추상 메서드 이기때문에 물려받을 기능이 없고 오히려 인터페이스에 정의한 모든 메서드를 자식이 오버라이딩해서 기능을 구현&lt;/b&gt;&lt;/span&gt;해야 한다. 따라서 인터페이스는 상속 대신 구현이라고 표현한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;인터페이스를 사용해야하는 이유 -&amp;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;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;제약&lt;/b&gt;&lt;/span&gt;: 인터페이스를 만드는 이유는 인터페이스를 구현하는 곳에서 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;인터페이스의 메서드를 반드시 구현하라는 규약(제약)&lt;/b&gt;&lt;/span&gt;을 주는 것이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다중 구현&lt;/b&gt;&lt;/span&gt;: &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;자바에서 클래스 상속은 부모를 하나만 지정할 수 있다. 반면에 인터페이스는 부모를 여러명 두는 다중 상속이 가능&lt;/b&gt;&lt;/span&gt;하다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 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;764&quot; data-origin-height=&quot;481&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKaktS/btsHKTLxkNM/FT0Vk1RtcpGeiZppDzfu61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKaktS/btsHKTLxkNM/FT0Vk1RtcpGeiZppDzfu61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKaktS/btsHKTLxkNM/FT0Vk1RtcpGeiZppDzfu61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKaktS%2FbtsHKTLxkNM%2FFT0Vk1RtcpGeiZppDzfu61%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;481&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;481&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바는 다중 상속을 지원하지 않는다. &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;AirplaneCar입장에서 move()를 호출할 때, 어떤 부모의 move()를 사용해야할지&lt;/b&gt;&lt;/span&gt; 애매한 문제가 발생하는데 이를 '&lt;u&gt;&lt;b&gt;다이아몬드&lt;/b&gt;&lt;/u&gt;' 문제라고한다. 그리고 다중 상속을 사용하면 클래스 계층 구조가 매우 복잡해 질 수 있다. 그렇기 때문에&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;&amp;nbsp;자바는 클래스의 다중 상속을 허용하지 않는다. 대신 인터페이스의 다중 구현을 허용&lt;/b&gt;&lt;/span&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;853&quot; data-origin-height=&quot;527&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTckcc/btsHLt6MkV0/kvs9GUk7HoRrApZlKvbuqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTckcc/btsHLt6MkV0/kvs9GUk7HoRrApZlKvbuqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTckcc/btsHLt6MkV0/kvs9GUk7HoRrApZlKvbuqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTckcc%2FbtsHLt6MkV0%2Fkvs9GUk7HoRrApZlKvbuqK%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;853&quot; height=&quot;527&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;527&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스 자신은 구현을 갖지 않는다. 대신 인터페이스를 구현하는 곳에서 해당 기능을 모두 구현해야 한다. 여기서 &lt;u&gt;&lt;b&gt;interfaceA, interfaceB는 같은 이름의 methodCommon()를 제공하지만 이것의 기능은 Child가 구현&lt;/b&gt;&lt;/u&gt;한다. 그리고 오버라이딩에 의해 Child에 있는 methodCommon()이 호출된다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;결과적으로 어떤 부모의 methodCommon()을 선택하는 것이 아니라 그냥 인터페이스를 구현한 Child에 있는 methodCommon()이 사용&lt;/b&gt;&lt;/span&gt;된다. 이러한 이유로 다이아몬드 문제가 발생하지 않는다.&lt;/p&gt;
&lt;pre id=&quot;code_1717227984317&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        interfaceA a = new Child(); // 부모는 자식을 담을 수 있다.
        a.methodA();
        a.methodCommon();
    
        interfaceB b = new Child();
        b.methodB();
        b.methodCommon();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8Bgil/btsHLgNgBNf/5NPYjzNb5INmlBvKV5r9d0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8Bgil/btsHLgNgBNf/5NPYjzNb5INmlBvKV5r9d0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8Bgil/btsHLgNgBNf/5NPYjzNb5INmlBvKV5r9d0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8Bgil%2FbtsHLgNgBNf%2F5NPYjzNb5INmlBvKV5r9d0%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;828&quot; height=&quot;294&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;a.method()Common()을 호출하면 먼저 &lt;b&gt;x001&lt;/b&gt; Child 인스턴스를 찾는다.&lt;/li&gt;
&lt;li&gt;변수 a가 InterfaceA 타입이므로 해당 타입에서&lt;b&gt; methodCommon()&lt;/b&gt;을 찾는다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;methodCommon()은 하위 타입인 Child에서 오버라이딩 되어 있다. 따라서 Child의 methodCommon()이 호출된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3jc6t/btsHKmHFDBx/xnxI3vTl97kHyP6DuNyfY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3jc6t/btsHKmHFDBx/xnxI3vTl97kHyP6DuNyfY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3jc6t/btsHKmHFDBx/xnxI3vTl97kHyP6DuNyfY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3jc6t%2FbtsHKmHFDBx%2FxnxI3vTl97kHyP6DuNyfY0%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;836&quot; height=&quot;317&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;317&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;b.method()Common()을 호출하면 먼저&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;x002&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Child 인스턴스를 찾는다.&lt;/li&gt;
&lt;li&gt;변수 b가 InterfaceB 타입이므로 해당 타입에서&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;methodCommon()&lt;/b&gt;을 찾는다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;methodCommon()은 하위 타입인 Child에서 오버라이딩 되어 있다. 따라서 Child의 methodCommon()이 호출된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;클래스와 인터페이스 활용&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;클래스 상속과 인터페이스 구현을 함께 사용해보자&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;435&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZInG7/btsHKb0wWXB/2PkfNkvacMceRpxdOABga1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZInG7/btsHKb0wWXB/2PkfNkvacMceRpxdOABga1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZInG7/btsHKb0wWXB/2PkfNkvacMceRpxdOABga1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZInG7%2FbtsHKb0wWXB%2F2PkfNkvacMceRpxdOABga1%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;862&quot; height=&quot;435&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;435&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;AbstractAnimal은 &lt;b&gt;추상 클래스&lt;/b&gt;다. -&amp;gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;상속 목적&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Fly는 &lt;b&gt;인터페이스&lt;/b&gt;이다. -&amp;gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;구현 목적&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Bird, Chicken은 날 수 있는 동물이다. fly() 메서드를 구현해야한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1717230294767&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Bird extends AbstractAnimal implements Fly&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;span style=&quot;background-color: #dddddd;&quot;&gt;extends&lt;/span&gt;를 통한 상속은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;하나만&lt;/b&gt;&lt;/span&gt; 할 수 있고,&lt;span style=&quot;background-color: #dddddd;&quot;&gt; implements&lt;/span&gt;를 통한 인터페이스는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다중 구현&lt;/b&gt;&lt;/span&gt;할 수 있기 때문에 둘이 함께 나온 경우 extends가 먼저 나와야 한다.&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;825&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNbiAk/btsHJU5LkVi/Ftkeye1kCTbFSnRN17kgg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNbiAk/btsHJU5LkVi/Ftkeye1kCTbFSnRN17kgg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNbiAk/btsHJU5LkVi/Ftkeye1kCTbFSnRN17kgg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNbiAk%2FbtsHJU5LkVi%2FFtkeye1kCTbFSnRN17kgg0%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;825&quot; height=&quot;250&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;250&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;animal.sound()를 호출하면 참조 대상인 x001 Bird 인스턴스를 찾는다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;호출한 animal 변수는 AbstractAnimal 타입이다. 따라서 AbstractAnimal.sound()를 찾는다. 해당 메서드는 오버라이딩 되었기 때문에 Bird.sound()가 호출된다.&amp;nbsp;&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;838&quot; data-origin-height=&quot;311&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ISQ6k/btsHLsfKny7/h6HfVPTah8ZG1jamGLj3M1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ISQ6k/btsHLsfKny7/h6HfVPTah8ZG1jamGLj3M1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ISQ6k/btsHLsfKny7/h6HfVPTah8ZG1jamGLj3M1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FISQ6k%2FbtsHLsfKny7%2Fh6HfVPTah8ZG1jamGLj3M1%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;838&quot; height=&quot;311&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;311&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;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;fly.fly()를 호출하면 참조 대상인 x001 Bird 인스턴스&lt;/b&gt;&lt;/span&gt;를 찾는다.&lt;/li&gt;
&lt;li&gt;호출한 fly 변수는 Fly 타입이다. 따라서 Fly.fly()를 찾는다. 해당 메서드는 Bird.fly()에 오버라이딩 되어 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Bird.fly()가 호출된다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>백엔드/JAVA</category>
      <author>goldpig</author>
      <guid isPermaLink="true">https://qababa.tistory.com/355</guid>
      <comments>https://qababa.tistory.com/355#entry355comment</comments>
      <pubDate>Sat, 1 Jun 2024 17:30:30 +0900</pubDate>
    </item>
    <item>
      <title>10. 다형성(1)</title>
      <link>https://qababa.tistory.com/354</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 개발자가 되기 위해서는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다형성에 대한 이해가 필수&lt;/b&gt;&lt;/span&gt;다. 다형성(Polymorphism)은 말 그대로 &quot;다양한 형태&quot;, &quot;여러 형태&quot;를 뜻한다. 보통 하나의 객체는 하나의 타입으로 고정된다. 그런데 다형성을 사용하게 되면 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;하나의 객체가 여러 타입으로 사용&lt;/b&gt;&lt;/span&gt;될 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다형성을 이해하기 위해서는 &lt;b&gt;다형적 참조&lt;/b&gt;와 &lt;b&gt;메서드 오버라이딩&lt;/b&gt;이라는 핵심 이론을 알아야 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;다형적 참조&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다형적 참조의 핵심은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;부모는 자식을 품을 수 있다&lt;/b&gt;&lt;/span&gt;는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex1) &lt;b&gt;부모 타입의 변수가 부모 인스턴스 참조&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Parent -&amp;gt; Parent: parent.ParentMethod()&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;806&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cafFth/btsHJT6trUD/w1ihpKKFbjWHwSY4vnIw60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cafFth/btsHJT6trUD/w1ihpKKFbjWHwSY4vnIw60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cafFth/btsHJT6trUD/w1ihpKKFbjWHwSY4vnIw60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcafFth%2FbtsHJT6trUD%2Fw1ihpKKFbjWHwSY4vnIw60%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;806&quot; height=&quot;227&quot; data-origin-width=&quot;806&quot; data-origin-height=&quot;227&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;li&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Parent parent = new Parent();&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Parent 인스턴스를 만들었다. &lt;span style=&quot;background-color: #dddddd;&quot;&gt;부모 타입인 Parent를 생성했기 때문에 메모리 상에 Parent만 생성&lt;/span&gt;된다. (자식은 생성되지 않는다.)&lt;/li&gt;
&lt;li&gt;생성된 참조값을 Parent 타입의 변수인 parent에 담아 둔다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;parent.parentMethod()를 호출하면 인스터스의 Parent 클래스에 있는 parentMethod()가 호출된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex2) &lt;b&gt;자식 타입의 변수가 자식 인스턴스 참조&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Child -&amp;gt; Child: child.childMethod()&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;231&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ca8jxN/btsHLEfwKrD/PqpRc3oiCVEeKOeOrPuMv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ca8jxN/btsHLEfwKrD/PqpRc3oiCVEeKOeOrPuMv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ca8jxN/btsHLEfwKrD/PqpRc3oiCVEeKOeOrPuMv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fca8jxN%2FbtsHLEfwKrD%2FPqpRc3oiCVEeKOeOrPuMv0%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;797&quot; height=&quot;231&quot; data-origin-width=&quot;797&quot; data-origin-height=&quot;231&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;li&gt;Child child = new Child();&lt;/li&gt;
&lt;li&gt;Child 인스턴스를 만들었다. 이 경우 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;자식 타입인 Child를 생성했기 때문에 메모리 상에 Child와 Parent가 모두 생성&lt;/span&gt;된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;생성된 참조값을 Child 타입의 뱐수인 child에 담아 둔다.&lt;/li&gt;
&lt;li&gt;child.childMethod()를 호출하면 인스턴스의 Child 클래스에 있는 childMethod()가 호출된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⭐ex3) 다형적 참조: &lt;b&gt;부모 타입의 변수가 자식 인스턴스 참조&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Parent -&amp;gt; Child: poly.parentMethod()&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ewq7nR/btsHJWvoftb/0AVCuvM6ezfjaSiciYYaV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ewq7nR/btsHJWvoftb/0AVCuvM6ezfjaSiciYYaV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ewq7nR/btsHJWvoftb/0AVCuvM6ezfjaSiciYYaV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fewq7nR%2FbtsHJWvoftb%2F0AVCuvM6ezfjaSiciYYaV0%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;815&quot; height=&quot;232&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;232&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;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;부모 타입의 변수가 자식 인스턴스를 참조&lt;/b&gt;&lt;/span&gt;한다.&lt;/li&gt;
&lt;li&gt;Parent poly = new Child();&lt;/li&gt;
&lt;li&gt;Child 인스턴스를 만들었다. 이 경우 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;자식 타입인 Child를 생성했기 때문에 메모리 상에 Child와 Parent가 모두 생성&lt;/span&gt;된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;생성된 참조값을 Parent 타입인 poly에 담아 둔다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⭐&lt;b&gt;부모는 자식을 담을 수 있다&lt;/b&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;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;반대로 자식 타입은 부모 타입을 담을 수 없다&lt;/b&gt;&lt;/span&gt;.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Parent poly = new Child() 는 가능하다. 반대로 Child child1 = new Parent()는 컴파일 오류! 이처럼 Parent 타입은 자신은 물론이고, 자식 타입까지 참조할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;Parent poly = new Parent(), Parent poly = new Child(), Parent poly = new Grandsom()&lt;/span&gt; (Child 하위에 손자가 있다면 가능)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;자바에서 부모 타입은 자신은 물론이고, 자신을 기준으로 모든 자식 타입을 참조&lt;/b&gt;&lt;/span&gt;할 수 있다. 이것이 바로 다양한 형태를 참조할 수 있다고 해서 다형적 참조라고 한다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;다형적 참조와 인스턴스 실행&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다형적 참조의 한계&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Parent -&amp;gt; Child: poly.childMethod()&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwqOx1/btsHLrHvLQV/NmaE1LKhT05sdN59yU0Ka0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwqOx1/btsHLrHvLQV/NmaE1LKhT05sdN59yU0Ka0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwqOx1/btsHLrHvLQV/NmaE1LKhT05sdN59yU0Ka0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwqOx1%2FbtsHLrHvLQV%2FNmaE1LKhT05sdN59yU0Ka0%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;815&quot; height=&quot;240&quot; data-origin-width=&quot;815&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Parent poly = new Child() 처럼 자식 인스턴스를 참조하고 있는 상황에서 poly가 자식 타입인 Child에 있는 childMethod()를 호출하면 어떻게 될까? &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;부모 타입의 참조변수로 자식 인스턴스를 참조할 수 있다. 하지만 자식의 기능은 호출할 수 없다&lt;/b&gt;&lt;/span&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;poly.childMethod()를 실행하면 &lt;u&gt;참조값을 통해 인스턴스를 찾는다&lt;/u&gt;.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;인스턴스 안에서 실행할 타입을 찾아야 한다. 이때, 호출자 타입을 기준으로 선택한다. 그러므로 Parent 클래스부터 시작해서 필요한 기능을 찾는다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;상속 관계는 부모 방향으로 찾아 올라갈 수 있지만 자식 방향으로 찾아 내려갈 수 는 없다&lt;/b&gt;&lt;/span&gt;.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Parent는 부모 타입이고 상위에 부모가 없다. 그러므로 childMethod()를 찾을 수 없으므로 컴파일 오류가 발생한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 어떻게 childMethod를 호출할 수 있을까? 정답은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;캐스팅&lt;/b&gt;&lt;/span&gt;! 캐스팅이란 특정 타입으로 변경하는 것이다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;다형성과 캐스팅&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다운캐스팅&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;315&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dRbQuQ/btsHJwqn2lV/IZW1Hu4ZV95j64LCl5Omik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dRbQuQ/btsHJwqn2lV/IZW1Hu4ZV95j64LCl5Omik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dRbQuQ/btsHJwqn2lV/IZW1Hu4ZV95j64LCl5Omik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdRbQuQ%2FbtsHJwqn2lV%2FIZW1Hu4ZV95j64LCl5Omik%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;796&quot; height=&quot;315&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;315&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1717158911024&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Child child = (Child) poly // Parent poly&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(타입) 처럼 괄호와 그 사이에 타입을 지정하면 &lt;u&gt;&lt;b&gt;참조 대상을 특정 타입으로 변경&lt;/b&gt;&lt;/u&gt;할 수 있다. 위에서 말했듯이 부모는 자식을 담을 수 있지만 자식은 부모를 담을 수 없다. 이때, 다운캐스팅이라는 기능을 활용해서 &lt;b&gt;부모 타입을 잠깐 자식 타입으로 변경&lt;/b&gt;하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;poly&lt;/b&gt;는 &lt;b&gt;Parent&lt;/b&gt; 타입니다. 이 타입을 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;(Child)&lt;/span&gt;를 사용해서 &lt;u&gt;&lt;b&gt;일시적으로 자식 타입인 Child 타입으로 변경&lt;/b&gt;&lt;/u&gt;한다. 그리고 나서 Child child에 대입한다.&amp;nbsp;&lt;/p&gt;
&lt;p 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;Child child = (Child) poly // 다운캐스팅을 통해 부모타입을 자식 타입으로 변환한 다음에 대입 시도&lt;/li&gt;
&lt;li&gt;Child child = (Child) x001 // 이때, poly 자체를 변경하는 것이 아니라 참조값을 꺼내서 읽은 다음 자식 타입으로 지정&lt;/li&gt;
&lt;li&gt;Child child = x001 // 최종결과&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;❗캐스팅을 한다고해서 Parent poly의 타입이 변하는 것은 아니다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;해당 참조값을 꺼내고 꺼낸 참조값이 Child 타입이 되는 것&lt;/b&gt;&lt;/span&gt;이다. 따라서 poly의 타입은 Parent로 기존과 동일하다.&amp;nbsp;&lt;/p&gt;
&lt;h4 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;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1717160145249&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        // 다운캐스팅(부모 타입 -&amp;gt; 자식 타입)
        Child child = (Child)poly; // x001
        child.childMethod();

        //일시적 다운캐스팅 -&amp;gt; 해당 메서드를 호출하는 순간만 다운캐스팅
        ((Child) poly).childMethod();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;811&quot; data-origin-height=&quot;285&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7LuUR/btsHLszLKVe/WVgx2Oo4ilUSkLoFpCKfa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7LuUR/btsHLszLKVe/WVgx2Oo4ilUSkLoFpCKfa1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7LuUR/btsHLszLKVe/WVgx2Oo4ilUSkLoFpCKfa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7LuUR%2FbtsHLszLKVe%2FWVgx2Oo4ilUSkLoFpCKfa1%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;811&quot; height=&quot;285&quot; data-origin-width=&quot;811&quot; data-origin-height=&quot;285&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때도 poly가 Child 타입으로 바뀌는 것은 아니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1717160234565&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;((Child) poly).childMethod(); // 다운캐스팅을 통해 부모타입을 자식 타입으로 변환 후 기능 호출
((Child) x001).childMethod(); // 참조값을 읽은 다음 자식 타입으로 다운캐스팅&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 일시적 다운 캐스팅을 사용하면 별도의 변수 없이 인스턴스의 자식 타입의 기능을 사용할 수 있다. 반대로 &lt;b&gt;업캐스팅은 현재 타입을 부모 타입으로 변경하는 것&lt;/b&gt;이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1717160326556&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;     Parent parent1 = (Parent) child; // 업캐스팅은 생략 가능, 생략 권장
     Parent parent2 = child; // 업캐스팅 생략, 자바가 알아서 해준다.

     parent1.parentMethod();
     parent2.parentMethod();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항상 부모는 자식을 담을 수 있다. 사실 이때, 자식도 부모로 타입 변환이 필요한데 이는 자바에서 자동으로 변환해 준다. 따라서 (Parent) 부분이 생략이 가능하다.&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;b&gt;업캐스팅은 생략할 수 있다. 다운캐스팅은 생략할 수 없다. 참고로 업캐스팅은 매우 자주 사용하기 때문에 생략을 권장한다&lt;/b&gt;. 다시말하지만 부모는 자식을 담을 수 있다. 하지만 반대는 안된다. (꼭 필요하다면 다운캐스팅을 해야한다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 다운캐스팅은 왜 개발자가 직접 명시적으로 캐스팅을 해야할까?&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;다운캐스팅과 주의점&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1717162213639&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        Parent parent1 = new Child();
        Child child1 = (Child) parent1;
        child1.childMethod(); // 문제 없음

        Parent parent2 = new Parent();
        Child child2 = (Child) parent2; // 런타임 오류 - ClassCastException
        child2.childMethod(); // 실행 불가&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운캐스팅은 잘못하면 심각한 &lt;b&gt;런타임 오류&lt;/b&gt;가 발생할 수 있다. *&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;런타임 오류&lt;/b&gt;&lt;/span&gt;는 말 그대로&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt; 프로그램이 실행되고 있는 시점에서 발생하는 오류&lt;/b&gt;&lt;/span&gt;다. 런타임 오류는 매우 안좋은 오류다 왜냐하면 보통 고객이 해당 프로그램일 실행하는 도중에 발생하기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;다운 캐스팅이 가능한 경우&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;808&quot; data-origin-height=&quot;367&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bucWU1/btsHLXsw2hO/uk2fHstfNfZHvRKSv9LnyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bucWU1/btsHLXsw2hO/uk2fHstfNfZHvRKSv9LnyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bucWU1/btsHLXsw2hO/uk2fHstfNfZHvRKSv9LnyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbucWU1%2FbtsHLXsw2hO%2Fuk2fHstfNfZHvRKSv9LnyK%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;808&quot; height=&quot;367&quot; data-origin-width=&quot;808&quot; data-origin-height=&quot;367&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;parent1의 경우 다운캐스팅을 해도 문제가 되지 않는다. 하지만 아래 경우는 다운캐스팅이 불가능 하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;359&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KlknA/btsHLOia2a8/HoKR2EhPRqRrmPlTF5VO31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KlknA/btsHLOia2a8/HoKR2EhPRqRrmPlTF5VO31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KlknA/btsHLOia2a8/HoKR2EhPRqRrmPlTF5VO31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKlknA%2FbtsHLOia2a8%2FHoKR2EhPRqRrmPlTF5VO31%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;816&quot; height=&quot;359&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;359&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;parent2를 Child 타입으로 다운캐스팅한다. 하지만 parent2는 Parent로 생성되었다. 따라서 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;메모리 상에 Child 자체가 존재하지 않는다&lt;/b&gt;&lt;/span&gt;. 즉, Child 자체를 사용할 수 없다. 자바에서는 사용할 수 없는 타입으로 다운캐스팅을 하는 경우에 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;ClassCastException&lt;/b&gt;&lt;/span&gt; 이라는 예외를 발생시킨다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;업캐스팅이 안전하고 다운캐스팅이 위험한 이유&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업캐스팅은 다운캐스팅과 다르게 이런 문제가 발생하지 않는다. 왜냐하면 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;객체를 생성하면 해당 타입의 상위 부모 타입은 모두 생성&lt;/b&gt;&lt;/span&gt;된다. 따라서 위로만 타입을 변경하는 &lt;u&gt;&lt;b&gt;업캐스팅은 메모리 상에 인스턴스가 모두 존재&lt;/b&gt;&lt;/u&gt;하기 때문에 안전하다. 반면에 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;다운 캐스팅은 존재하지 않는 하위 타입으로 캐스팅하는 문제&lt;/b&gt;&lt;/span&gt;가 발생할 수 있다. 왜냐하면 객체를 생성하면 부모 타입은 모두 함께 생성되지만 &lt;u&gt;&lt;b&gt;자식 타입은 생성되지 않는다&lt;/b&gt;&lt;/u&gt;. 그렇기 때문에 이런 문제를 인지하고 사용해야 한다는 의미로 명시적으로 캐스팅 해줘야 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;491&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n1SdV/btsHLGR6nhZ/95tc625h6KqvpuoRi3XRgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n1SdV/btsHLGR6nhZ/95tc625h6KqvpuoRi3XRgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n1SdV/btsHLGR6nhZ/95tc625h6KqvpuoRi3XRgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn1SdV%2FbtsHLGR6nhZ%2F95tc625h6KqvpuoRi3XRgk%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;807&quot; height=&quot;491&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;491&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 A, B, C는 상속 관계다. 그러므로 new C()로 인스턴스를 생성하면 &lt;b&gt;메모리 상에 즉, 인스턴스 내부에 자신과 부모인 A,B,C가 모두 생성&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;789&quot; data-origin-height=&quot;488&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d1r25C/btsHLDVmBdZ/luUmkccbKc0t6hDbtunAg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d1r25C/btsHLDVmBdZ/luUmkccbKc0t6hDbtunAg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d1r25C/btsHLDVmBdZ/luUmkccbKc0t6hDbtunAg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd1r25C%2FbtsHLDVmBdZ%2FluUmkccbKc0t6hDbtunAg0%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;789&quot; height=&quot;488&quot; data-origin-width=&quot;789&quot; data-origin-height=&quot;488&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 new B()를 하게 되면 인스턴스 내부에 자기 자신인 B와 부모인 A만 생성된다. 즉 &lt;b&gt;C는 B 인스턴스 내부에 존재하지 않기 때문에 C로 다운 캐스팅을 하게 되면 오류가 발생&lt;/b&gt;한다. 왜냐하면 C 자체는 존재하지 않기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A a = new B() :&lt;b&gt; A로 업케스팅&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;B b = new B() : &lt;b&gt;자신과 같은 타입&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;C c = new B() : &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;하위 타입은 대입할 수 없음, 컴파일 오류&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;C c = (C) new B() : &lt;b&gt;하위 타입으로 강제 다운캐스팅, 하지만 B 인스턴스에 C와 관련된 부분이 없으므로 잘못된 캐스팅&lt;/b&gt;, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;ClassCastException&lt;/b&gt;&lt;/span&gt;&amp;nbsp;런타임 오류 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;컴파일 오류 vs 런타임 오류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;컴파일 오류&lt;/b&gt;는 변수명 오타, 잘못된 클래스 이름 사용 등 자바 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;프로그램을 실행하기 전에 발생하는 오류&lt;/b&gt;&lt;/span&gt;다. 이런 오류는 IDE에서 즉시 확인할 수 있기 때문에 안전하고 좋은 오류다. 반면에 &lt;b&gt;런타임 오류&lt;/b&gt;는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;프로그램이 실행되는 도중에 발생하는 오류&lt;/b&gt;&lt;/span&gt;로 좋은 않은 오류다. 왜냐하면 고객이 사용하는 도중에 오류가 발생하기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;instanceof&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다형성에서 참조형 변수가 참조하는 대상이 다양하기 때문에 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;어떤 인스턴스를 참조하고 있는지 확인&lt;/b&gt;&lt;/span&gt;할 필요가 있다. 이때, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;instanceof&lt;/b&gt;&lt;/span&gt; 키워드를 사용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1717164547592&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Parent parent1 = new Parent();
Parent parent2 = new Child();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Parent는 자신과 같은 Parent의 인스턴스도 참조할 수 있고, 자식 타입인 Child의 인스턴스도 참조할 수 있다. 이때, parent1, parent2 변수가 참조하는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;인스턴스의 타입을 확인하고 싶다면 instanceof 키워드&lt;/b&gt;&lt;/span&gt;를 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1717164725164&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	Parent parent1 = new Parent();
        System.out.println(&quot;parent1 호출&quot;);
        call(parent1);
        Parent parent2 = new Child();
        System.out.println(&quot;parent2 호출&quot;);
        call(parent2);
    }

    	private static void call(Parent parent){

        parent.parentMethod();
        // parent가 Child 인스턴스 인 경우 childMethod() 실행
        if (parent instanceof Child){
            System.out.println(&quot;Child 인스턴스 맞음&quot;);
            ((Child) parent).childMethod();
        }

    }&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;자바 16 - Pattern Matching for instanceof&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 16부터는 instanceof를 사용하면서 동시에 변수를 선언할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1717164955439&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private static void call(Parent parent){

        parent.parentMethod();
        // Child 인스턴스 인 경우 childMethod() 실행
        if (parent instanceof Child child){
            System.out.println(&quot;Child 인스턴스 맞음&quot;);
            // 생략 가능
            //Child child = (Child) parent;
            child.childMethod();
        }

    }&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;다형성과 메서드 오버라이딩&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드 오버라이딩의 핵심은 &quot;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;오버라이딩 된 메서드가 항상 우선권을 가진다.&lt;/b&gt;&lt;/span&gt;&quot; 메서드 오버라이딩의 진짜 힘은 다형성과 함께 사용할 때다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1717166841710&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;        // 부모 변수가 자식 인스턴스를 참조(다형적 참조)
        Parent poly = new Child();
        System.out.println(&quot;Parent -&amp;gt; Child&quot;);
        System.out.println(&quot;value = &quot; + poly.value); // 변수는 오버라이딩 x
        poly.method(); // 메서드는 오버라이딩!&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6xqqJ/btsHKkpfwWa/OvqyKEIGpcELJW169md2YK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6xqqJ/btsHKkpfwWa/OvqyKEIGpcELJW169md2YK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6xqqJ/btsHKkpfwWa/OvqyKEIGpcELJW169md2YK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6xqqJ%2FbtsHKkpfwWa%2FOvqyKEIGpcELJW169md2YK%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;838&quot; height=&quot;308&quot; data-origin-width=&quot;838&quot; data-origin-height=&quot;308&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;poly 변수는 Parent 타입이다. 따라서 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;poly.value, poly.method()&lt;/span&gt;를 호출하면 인스턴스의 Parent 타입에서 기능을 찾아 실행한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;poly.value: Parent 타입에 있는 value 값을 읽는다. 즉, &lt;u&gt;변수(필드)는 오버라이딩 x&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;⭐poly.method(): Parent 타입에 있는 method()가 아니라 하위 타입으로 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;오버라이딩 된 Child.method()를 호출&lt;/b&gt;&lt;/span&gt;한다. 따라서 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;오버라이딩 된 메서드가 항상 우선권&lt;/b&gt;&lt;/span&gt;을 갖는다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 자식에서도 오버라이딩 하고 손자에서도 같은 메서드를 오버라이딩을 하는 경우 손자의 오버라이딩 메서드가 우선권을 갖는다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;즉, 더 하위 자식의 오버라이딩 된 메서드가 우선권을 갖는 것&lt;/b&gt;&lt;/span&gt;이다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;다형적 참조&lt;/b&gt;&lt;/span&gt;: 하나의 변수 타입으로 다양한 자식 인스턴스를 참조할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;메서드 오버라이딩&lt;/b&gt;&lt;/span&gt;: 기존 기능을 하위 타입에서 새로운 기능으로 재정의&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>백엔드/JAVA</category>
      <author>goldpig</author>
      <guid isPermaLink="true">https://qababa.tistory.com/354</guid>
      <comments>https://qababa.tistory.com/354#entry354comment</comments>
      <pubDate>Fri, 31 May 2024 23:53:55 +0900</pubDate>
    </item>
    <item>
      <title>9. 상속</title>
      <link>https://qababa.tistory.com/353</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;상속이란 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;기존 클래스를 재사용하여 새로운 클래스를 작성는 것&lt;/b&gt;&lt;/span&gt;이다. 상속은 &lt;b&gt;코드의 재사용성&lt;/b&gt;을 높이고 &lt;b&gt;코드의 중복을 제거&lt;/b&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;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;extends&lt;/b&gt;&lt;/span&gt; 키워드를 사용하고 &lt;b&gt;extends 대상은 하나만 선택&lt;/b&gt;할 수 있다.&amp;nbsp;&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;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;623&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lj3eP/btsHINEho53/BWkXHOq5IdTunmRxPfaeqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lj3eP/btsHINEho53/BWkXHOq5IdTunmRxPfaeqk/img.png&quot; data-alt=&quot;Car는 부모클래스이고 ElectricCar와 GasCar는 자손클래스이다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lj3eP/btsHINEho53/BWkXHOq5IdTunmRxPfaeqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flj3eP%2FbtsHINEho53%2FBWkXHOq5IdTunmRxPfaeqk%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;508&quot; height=&quot;378&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;623&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Car는 부모클래스이고 ElectricCar와 GasCar는 자손클래스이다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속은 부모의 기능을 자식이 물려받는 것이다. 따라서 자식은 부모의 기능을 물려 받아서 사용하고 있다. &lt;b&gt;&lt;u&gt;하지만 부모 클래스는 자식 클래스에 접근할 수 없다&lt;/u&gt;&lt;/b&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;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;자바는 다중 상속을 지원하지 않는다&lt;/b&gt;&lt;/span&gt;. 따라서 &lt;span style=&quot;color: #333333;&quot;&gt;extends 대상은 하나만 선택&lt;/span&gt;할 수 있다. 즉, 부모는 여러개의 자식을 가질 수 있지만 자식은 하나의 부모만 선택할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;생성자와 초기화 블럭은 상속되지 않는다. 오직 부모 클래스의 필드와 메서드만 상속된다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;⭐상속과 메모리 구조&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1717066758822&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ElectricCar electricCar = new ElectricCar();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new ElectricCar()를 호출하면 &lt;b&gt;ElectricCar 뿐만 아니라 상속 관계에 있는 Car까지 포함해서 인스턴스가 생성&lt;/b&gt;된다. 참조값은&lt;b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt; x001&lt;/span&gt;&lt;/b&gt;로 하나이지만 실제로 그 안에는 Car, ElectricCar 라는 두 가지 클래스 정보가 공존한다.&amp;nbsp;&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;802&quot; data-origin-height=&quot;253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dA9qzi/btsHI8aaPK5/4SfdVUAJUgt1ivRO0FyO5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dA9qzi/btsHI8aaPK5/4SfdVUAJUgt1ivRO0FyO5K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dA9qzi/btsHI8aaPK5/4SfdVUAJUgt1ivRO0FyO5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdA9qzi%2FbtsHI8aaPK5%2F4SfdVUAJUgt1ivRO0FyO5K%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;704&quot; height=&quot;222&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;253&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;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;상속 관계의 객체를 생성하면 그 내부에는 부모와 자식이 모두 생성&lt;/b&gt;&lt;/span&gt;된다.&lt;/li&gt;
&lt;li&gt;상속 관계의 객체를 호출할 때, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;호출자의 타입을 기준으로 대상 타입&lt;/b&gt;&lt;/span&gt;을 찾는다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;현재 타입에서 기능을 찾지 못했다면 상위 부모 타입으로 기능을 찾아서 호출&lt;/b&gt;&lt;/span&gt;한다. 최상위 클래스에서 기능을 찾지 못하면 컴파일 오류가 발생한다.&amp;nbsp;&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;813&quot; data-origin-height=&quot;255&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BxOFD/btsHIOwqYiT/I6OTVKAxx7ueCh7y2TCK8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BxOFD/btsHIOwqYiT/I6OTVKAxx7ueCh7y2TCK8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BxOFD/btsHIOwqYiT/I6OTVKAxx7ueCh7y2TCK8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBxOFD%2FbtsHIOwqYiT%2FI6OTVKAxx7ueCh7y2TCK8K%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;255&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;255&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;800&quot; data-origin-height=&quot;253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HP9eX/btsHIJvckqd/MZ5EKG1DYLAl1mnZ2MNfIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HP9eX/btsHIJvckqd/MZ5EKG1DYLAl1mnZ2MNfIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HP9eX/btsHIJvckqd/MZ5EKG1DYLAl1mnZ2MNfIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHP9eX%2FbtsHIJvckqd%2FMZ5EKG1DYLAl1mnZ2MNfIK%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;253&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;253&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 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;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;오버라이딩&lt;/b&gt;&lt;/span&gt;: &lt;b&gt;부모 클래스로부터 물려받은 메서드의 내용(기능)을 자식 클래스에서 재정하는 것&lt;/b&gt;이다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;조건&lt;/b&gt;&lt;/span&gt;: 1. &lt;b&gt;메서드의 이름&lt;/b&gt;이 같아야 한다 2. &lt;b&gt;매개변수&lt;/b&gt;가 같아야 한다 3. &lt;b&gt;반환 타입&lt;/b&gt;이 같아야 한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;@Override&lt;/b&gt; 애노테이션 활용한다. 필수는 아니지만 &lt;b&gt;코드의 명확성&lt;/b&gt;을 위해 붙여주는 것이 좋다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오버로딩&lt;/b&gt;은 &lt;u&gt;&lt;b&gt;메서드의 이름은 같지만 매개변수가 다른 메서드를 여러 개 정의하는 것&lt;/b&gt;&lt;/u&gt;이다. (기존에 없는 새로운 메서드를 정의하는 것이다.) 반면 오버라이딩은 상속받은 메서드의 내용을 변경하는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;h4 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;b&gt;private&lt;/b&gt;: 모든 외부 호출을 막는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;default&lt;/b&gt;: 같은 패키지 안에서 호출을 허용한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;protected&lt;/b&gt;: 같은 패키지 안에서 호출을 허용한다. 하지만 &lt;u&gt;&lt;b&gt;상속관계일 경우 패키지가 달라도 호출을 허용&lt;/b&gt;&lt;/u&gt;한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;public&lt;/b&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;402&quot; data-origin-height=&quot;33&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PmyLm/btsHIZR1UfA/TIVZoLgfTaUn42rVnGK6p0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PmyLm/btsHIZR1UfA/TIVZoLgfTaUn42rVnGK6p0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PmyLm/btsHIZR1UfA/TIVZoLgfTaUn42rVnGK6p0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPmyLm%2FbtsHIZR1UfA%2FTIVZoLgfTaUn42rVnGK6p0%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;402&quot; height=&quot;33&quot; data-origin-width=&quot;402&quot; data-origin-height=&quot;33&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;super - 부모 참조&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;super는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;자손 클래스에서 부모 클래스의 멤버를 참조하는데 사용되는 참조 변수&lt;/b&gt;&lt;/span&gt;이다. 즉, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;supe&lt;/b&gt;&lt;b&gt;r&lt;/b&gt;&lt;/span&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;u&gt;&lt;b&gt;중복 정의되어 서로 구별해야하는 경우&lt;/b&gt;&lt;/u&gt;에만 super를 사용하는 것이 좋다.&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;617&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coPSrL/btsHHTSSjVZ/uGfkUEEOpwZE3dOF69lys1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coPSrL/btsHHTSSjVZ/uGfkUEEOpwZE3dOF69lys1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coPSrL/btsHHTSSjVZ/uGfkUEEOpwZE3dOF69lys1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoPSrL%2FbtsHHTSSjVZ%2FuGfkUEEOpwZE3dOF69lys1%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;430&quot; height=&quot;459&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;658&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;831&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgPIwP/btsHI7CoE37/GGtEBp8pQyXQrStizY1xqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgPIwP/btsHI7CoE37/GGtEBp8pQyXQrStizY1xqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgPIwP/btsHI7CoE37/GGtEBp8pQyXQrStizY1xqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgPIwP%2FbtsHI7CoE37%2FGGtEBp8pQyXQrStizY1xqk%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;831&quot; height=&quot;304&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;super() - 조상 클래스의 생성자&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속 관계의 인스턴스를 생성하면 결국 &lt;b&gt;메모리 내부에는 자식과 부모 클래스가 모두&lt;/b&gt; 만들어진다. Child를 만들면 부모인 Parent까지 함께 만들어지는 것이다. &lt;u&gt;&lt;b&gt;따라서 각각의 생성자도 모두 호출되&lt;/b&gt;&lt;/u&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;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;상속 관계를 사용하면 자식 클래스의 생성자에서 부모 클래스의 생성자를 반드시 호출&lt;/b&gt;&lt;/span&gt;해야한다. (&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;규칙&lt;/b&gt;&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1717382877255&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class ClassB extends ClassA {
    public ClassB(int a){
        super(); // 부모 클래스의 기본 생성자 생략 가능
        System.out.println(&quot;ClassB 생성자 a=&quot; + a);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;부모 생성자를 호출할 때는 &lt;b&gt;super()&lt;/b&gt;를 사용하면 된다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;this()&lt;/b&gt;&lt;/span&gt;는 같은 클래스의 다른 생성자를 호출할 때 사용하지만,&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; super()&lt;/b&gt;&lt;/span&gt;는 조상 클래스의 생성자를 호출할 때 사용한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Object클래스를 제외한 모든 클래스의 생성자 첫 줄에 생성자 this(), 또는 super()를 호출해야한다. 그렇지 않으면 컴파일러가 자동적으로 'super();'를 생성자의 첫 줄에 삽입한다&lt;/b&gt;. 하지만 만약 생성자가 정의되어 있으면, 기본생성자를 자동으로 생성해주지 않는다.&lt;/p&gt;
&lt;pre id=&quot;code_1717383099528&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class ClassC extends ClassB{
    public ClassC(){
        super(10,20); // 수퍼를 직접 정의해야한다.
        System.out.println(&quot;ClassC 생성자&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;클래스와 메서드에 사용되는 final&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;b&gt;final&lt;/b&gt;: &lt;b&gt;상속 끝&lt;/b&gt; 즉, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;final로 선언된 클래스는 확장 될 수 없다&lt;/b&gt;&lt;/span&gt;. 따라서 다른 클래스가 final로 선언된 클래스를 상속받을 수 없다.&lt;/li&gt;
&lt;li&gt;메서드에 &lt;b&gt;final&lt;/b&gt;: &lt;b&gt;오버라이딩 끝&lt;/b&gt; 즉, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;final로 선언된 메서드는 오버라이드 될 수 없다&lt;/b&gt;&lt;/span&gt;. 상속받은 서브 클래스에서 이 메서드를 변경할 수 없다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>백엔드/JAVA</category>
      <author>goldpig</author>
      <guid isPermaLink="true">https://qababa.tistory.com/353</guid>
      <comments>https://qababa.tistory.com/353#entry353comment</comments>
      <pubDate>Thu, 30 May 2024 20:18:00 +0900</pubDate>
    </item>
    <item>
      <title>H-index</title>
      <link>https://qababa.tistory.com/352</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 설명&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;H-Index는 과학자의 생산성과 영향력을 나타내는 지표입니다. 어느 과학자의 H-Index를 나타내는 값인 h를 구하려고 합니다. 위키백과에 따르면, H-Index는 다음과 같이 구합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;어떤 과학자가 발표한 논문&lt;span&gt;&amp;nbsp;&lt;/span&gt;n편 중,&lt;span&gt;&amp;nbsp;&lt;/span&gt;h번 이상 인용된 논문이&lt;span&gt;&amp;nbsp;&lt;/span&gt;h편 이상이고 나머지 논문이 h번 이하 인용되었다면&lt;span&gt;&amp;nbsp;&lt;/span&gt;h의 최댓값이 이 과학자의 H-Index입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;어떤 과학자가 발표한 논문의 인용 횟수를 담은 배열 citations가 매개변수로 주어질 때, 이 과학자의 H-Index를 return 하도록 solution 함수를 작성해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제한사항&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;과학자가 발표한 논문의 수는 1편 이상 1,000편 이하입니다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;논문별 인용 횟수는 0회 이상 10,000회 이하입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입출력 예&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;233&quot; data-origin-height=&quot;89&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FxfZc/btsHGki22XT/JfJNxMMwhKPWqXgcglkwdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FxfZc/btsHGki22XT/JfJNxMMwhKPWqXgcglkwdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FxfZc/btsHGki22XT/JfJNxMMwhKPWqXgcglkwdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFxfZc%2FbtsHGki22XT%2FJfJNxMMwhKPWqXgcglkwdK%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;233&quot; height=&quot;89&quot; data-origin-width=&quot;233&quot; data-origin-height=&quot;89&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 style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;이 과학자가 발표한 논문의 수는 5편이고, 그중 3편의 논문은 3회 이상 인용되었습니다. 그리고 나머지 2편의 논문은 3회 이하 인용되었기 때문에 이 과학자의 H-Index는 3입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 아이디어&lt;/h3&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;H-Index란 문제에 명시되어 있는 것처럼 &lt;u&gt;&lt;b&gt;논문 n편 중, h번 이상 인용된 논문이 h편 이상&lt;/b&gt;&lt;/u&gt;이고 나머지 논문이 h번 이하 인용되었다면 h의 최댓값이 과학자의 H-Index이다. &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;각 논문의 인용된 횟수를 차례대로 보기 위해 내림차순으로 정렬&lt;/b&gt;&lt;/span&gt;한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;index&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;0 (1)&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;1 (2)&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;2 (3)&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;3 (4)&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;4 (5)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;citations&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;6&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 16.6667%; text-align: center;&quot;&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;여기서 각 index는&lt;b&gt; i번 이상 이용된 논문의 개수&lt;/b&gt;를 나타낸다. citations의 값이 index보다 크다면 계속해서 개수를 세어준다. 하지만 만약 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;citations의 값이 index보다 작거나 같아진다면 더 이상 i번 이상 인용된 논문이 없다는 뜻이므로 i의 값을 리턴&lt;/b&gt;&lt;/span&gt;해준다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;❗ 주의할 점은 만약 [5,5,5] 처럼 인용횟수가 모두 같은 요소가 여러개 있거나 혹은 [100] 처럼 논문이 1개 밖에 없다면 citations의 길이를 리턴해주면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 구현&lt;/h3&gt;
&lt;pre id=&quot;code_1717042091858&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(citations):
    #answer = 0
    citations.sort(reverse=True)
    for i in range(len(citations)):
        # i번 이상 인용된 논문이 더 이상 없다면
        if i &amp;gt;= citations[i]:
            return i
        
    return len(citations) # 인용횟수가 모두 같을 때 ex [5,5,5]&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래머스/Level 2</category>
      <author>goldpig</author>
      <guid isPermaLink="true">https://qababa.tistory.com/352</guid>
      <comments>https://qababa.tistory.com/352#entry352comment</comments>
      <pubDate>Thu, 30 May 2024 13:08:10 +0900</pubDate>
    </item>
    <item>
      <title>n^2 배열 자르기</title>
      <link>https://qababa.tistory.com/351</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 설명&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;정수&lt;span&gt;&amp;nbsp;&lt;/span&gt;n,&lt;span&gt;&amp;nbsp;&lt;/span&gt;left,&lt;span&gt;&amp;nbsp;&lt;/span&gt;right가 주어집니다. 다음 과정을 거쳐서 1차원 배열을 만들고자 합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;n행&lt;span&gt;&amp;nbsp;&lt;/span&gt;n열 크기의 비어있는 2차원 배열을 만듭니다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;i = 1, 2, 3, ..., n에 대해서, 다음 과정을 반복합니다.
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;1행 1열부터&lt;span&gt;&amp;nbsp;&lt;/span&gt;i행&lt;span&gt;&amp;nbsp;&lt;/span&gt;i열까지의 영역 내의 모든 빈 칸을 숫자&lt;span&gt;&amp;nbsp;&lt;/span&gt;i로 채웁니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;1행, 2행, ...,&lt;span&gt;&amp;nbsp;&lt;/span&gt;n행을 잘라내어 모두 이어붙인 새로운 1차원 배열을 만듭니다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;새로운 1차원 배열을&lt;span&gt;&amp;nbsp;&lt;/span&gt;arr이라 할 때,&lt;span&gt;&amp;nbsp;&lt;/span&gt;arr[left],&lt;span&gt;&amp;nbsp;&lt;/span&gt;arr[left+1], ...,&lt;span&gt;&amp;nbsp;&lt;/span&gt;arr[right]만 남기고 나머지는 지웁니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;정수&lt;span&gt;&amp;nbsp;&lt;/span&gt;n,&lt;span&gt;&amp;nbsp;&lt;/span&gt;left,&lt;span&gt;&amp;nbsp;&lt;/span&gt;right가 매개변수로 주어집니다. 주어진 과정대로 만들어진 1차원 배열을 return 하도록 solution 함수를 완성해주세요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;❗제한사항&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;1 &amp;le;&lt;span&gt;&amp;nbsp;&lt;/span&gt;n&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;le; 107&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;0 &amp;le;&lt;span&gt;&amp;nbsp;&lt;/span&gt;left&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;le;&lt;span&gt;&amp;nbsp;&lt;/span&gt;right&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt; n2&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;right&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;left&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;lt; 105&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;854&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNj6hm/btsHIeH6f1D/kFzVY0PbHslVhy798VLOT1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNj6hm/btsHIeH6f1D/kFzVY0PbHslVhy798VLOT1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNj6hm/btsHIeH6f1D/kFzVY0PbHslVhy798VLOT1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bNj6hm/btsHIeH6f1D/kFzVY0PbHslVhy798VLOT1/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;658&quot; height=&quot;370&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 아이디어&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시에서 1,2,3이 들어있는 곳의 규칙을 살펴보면, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;(0,0)은 1이고 인덱스에 1이 하나라도 들어가면 2 그리고 인덱스에 2가 하나라도 들어가면 3이 된다&lt;/b&gt;&lt;/span&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2차원 배열을 1차원 배열로 만들어서 살펴보면 다음과 같다.&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;157&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cG1slM/btsHIwoio42/5VdKB7VMMScbNUP77JKXK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cG1slM/btsHIwoio42/5VdKB7VMMScbNUP77JKXK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cG1slM/btsHIwoio42/5VdKB7VMMScbNUP77JKXK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcG1slM%2FbtsHIwoio42%2F5VdKB7VMMScbNUP77JKXK0%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;157&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;157&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;544&quot; data-origin-height=&quot;53&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dWWvvt/btsHHICUAS1/dVqX9rcsYTxmor2HMvYK80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dWWvvt/btsHHICUAS1/dVqX9rcsYTxmor2HMvYK80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dWWvvt/btsHHICUAS1/dVqX9rcsYTxmor2HMvYK80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdWWvvt%2FbtsHHICUAS1%2FdVqX9rcsYTxmor2HMvYK80%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;544&quot; height=&quot;53&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;53&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스 8을 살펴보면,&lt;b&gt; 8 (8 // 3, 8 % 3) 즉 (몫, 나머지)&lt;/b&gt;로 확인할 수 있다. 그리고 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;몫과 나머지 중 큰 값을 구하고 거기 1을 더하면 원하는 값&lt;/b&gt;&lt;/span&gt;을 얻을 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 구현&lt;/h3&gt;
&lt;pre id=&quot;code_1717039891474&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def solution(n, left, right):
    answer = []
    for i in range(left, right+1):
        a = i // n # 몫
        b = i % n # 나머지
        # 둘 중 더 큰값을 구하고 1을 더하면 원하는 값을 구할 수 있다.
        answer.append(max(a,b)+1)
    return answer&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래머스/Level 2</category>
      <author>goldpig</author>
      <guid isPermaLink="true">https://qababa.tistory.com/351</guid>
      <comments>https://qababa.tistory.com/351#entry351comment</comments>
      <pubDate>Thu, 30 May 2024 12:31:27 +0900</pubDate>
    </item>
    <item>
      <title>할인 행사</title>
      <link>https://qababa.tistory.com/350</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 설명&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;XYZ 마트는 일정한 금액을 지불하면 10일 동안 회원 자격을 부여합니다. XYZ 마트에서는 회원을 대상으로 매일 한 가지 제품을 할인하는 행사를 합니다. 할인하는 제품은 하루에 하나씩만 구매할 수 있습니다. 알뜰한 정현이는 자신이 원하는 제품과 수량이 할인하는 날짜와 10일 연속으로 일치할 경우에 맞춰서 회원가입을 하려 합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어, 정현이가 원하는 제품이 바나나 3개, 사과 2개, 쌀 2개, 돼지고기 2개, 냄비 1개이며, XYZ 마트에서 14일간 회원을 대상으로 할인하는 제품이 날짜 순서대로 치킨, 사과, 사과, 바나나, 쌀, 사과, 돼지고기, 바나나, 돼지고기, 쌀, 냄비, 바나나, 사과, 바나나인 경우에 대해 알아봅시다. 첫째 날부터 열흘 간에는 냄비가 할인하지 않기 때문에 첫째 날에는 회원가입을 하지 않습니다. 둘째 날부터 열흘 간에는 바나나를 원하는 만큼 할인구매할 수 없기 때문에 둘째 날에도 회원가입을 하지 않습니다. 셋째 날, 넷째 날, 다섯째 날부터 각각 열흘은 원하는 제품과 수량이 일치하기 때문에 셋 중 하루에 회원가입을 하려 합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;정현이가 원하는 제품을 나타내는 문자열 배열&lt;span&gt;&amp;nbsp;&lt;/span&gt;want와 정현이가 원하는 제품의 수량을 나타내는 정수 배열&lt;span&gt;&amp;nbsp;&lt;/span&gt;number, XYZ 마트에서 할인하는 제품을 나타내는 문자열 배열&lt;span&gt;&amp;nbsp;&lt;/span&gt;discount가 주어졌을 때, 회원등록시 정현이가 원하는 제품을 모두 할인 받을 수 있는 회원등록 날짜의 총 일수를 return 하는 solution 함수를 완성하시오. 가능한 날이 없으면 0을 return 합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;❗제한사항&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #263747; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;1 &amp;le;&lt;span&gt;&amp;nbsp;&lt;/span&gt;want의 길이 =&lt;span&gt;&amp;nbsp;&lt;/span&gt;number의 길이 &amp;le; 10
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;1 &amp;le;&lt;span&gt;&amp;nbsp;&lt;/span&gt;number의 원소 &amp;le; 10&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;number[i]는&lt;span&gt;&amp;nbsp;&lt;/span&gt;want[i]의 수량을 의미하며,&lt;span&gt;&amp;nbsp;&lt;/span&gt;number의 원소의 합은 10입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;10 &amp;le;&lt;span&gt;&amp;nbsp;&lt;/span&gt;discount의 길이 &amp;le; 100,000&lt;/li&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;want와&lt;span&gt;&amp;nbsp;&lt;/span&gt;discount의 원소들은 알파벳 소문자로 이루어진 문자열입니다.
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: inherit; color: #000000;&quot;&gt;1 &amp;le;&lt;span&gt;&amp;nbsp;&lt;/span&gt;want의 원소의 길이,&lt;span&gt;&amp;nbsp;&lt;/span&gt;discount의 원소의 길이 &amp;le; 12&lt;/li&gt;
&lt;/ul&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;1280&quot; data-origin-height=&quot;430&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djvddm/btsHCRaanYQ/1GKCerbdNczO5GwvlIkBck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djvddm/btsHCRaanYQ/1GKCerbdNczO5GwvlIkBck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djvddm/btsHCRaanYQ/1GKCerbdNczO5GwvlIkBck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdjvddm%2FbtsHCRaanYQ%2F1GKCerbdNczO5GwvlIkBck%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;1280&quot; height=&quot;430&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;430&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 아이디어&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Counter&lt;/li&gt;
&lt;li&gt;zip()&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*zip() 함수는 파이썬 내장 함수로, 여러 개의 반복 가능한 객체를 인자로 받아서 동일한 인덱스의 요소를 튜플 형태로 묶여주는 역할을 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 구현&lt;/h3&gt;
&lt;pre id=&quot;code_1716960064147&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from collections import Counter
def solution(want, number, discount):
    answer = 0
    dic = {}
    for w,n in zip(want, number):
        dic[w] = n
    # print(dic), {'banana': 3, 'apple': 2, 'rice': 2, 'pork': 2, 'pot': 1}
    
    # discount에서 총 10개의 상품을 꺼내는 반복문 실행
    # 이 범위는 슬라이딩 윈도우 방식으로 10개의 연속된 상품을 검사하기 위해 설정됨 
    for i in range(len(discount) - 9):
        c = Counter(discount[i:i+10])
        '''
        print(c)
        Counter({'apple': 3, 'banana': 2, 'rice': 2, 'pork': 2, 'chicken': 1})
        Counter({'apple': 3, 'banana': 2, 'rice': 2, 'pork': 2, 'pot': 1})
        Counter({'banana': 3, 'apple': 2, 'rice': 2, 'pork': 2, 'pot': 1})
        Counter({'banana': 3, 'rice': 2, 'apple': 2, 'pork': 2, 'pot': 1})
        Counter({'banana': 3, 'rice': 2, 'apple': 2, 'pork': 2, 'pot': 1})
        '''
        if c == dic:
            answer += 1
    return answer&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;</description>
      <category>프로그래머스/Level 2</category>
      <author>goldpig</author>
      <guid isPermaLink="true">https://qababa.tistory.com/350</guid>
      <comments>https://qababa.tistory.com/350#entry350comment</comments>
      <pubDate>Wed, 29 May 2024 14:24:41 +0900</pubDate>
    </item>
  </channel>
</rss>