<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>H.Dev Log</title>
    <link>https://hlxecz.tistory.com/</link>
    <description>1인분 개발자가 되고 싶은 개발 기록</description>
    <language>ko</language>
    <pubDate>Thu, 18 Jun 2026 23:25:13 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>hlxecz</managingEditor>
    <image>
      <title>H.Dev Log</title>
      <url>https://tistory1.daumcdn.net/tistory/8427700/attach/6cfda989d676451189df63c65b7e8a66</url>
      <link>https://hlxecz.tistory.com</link>
    </image>
    <item>
      <title>[OOP] GoF(Gang of Four) 디자인 패턴 장점 과 종류 !!</title>
      <link>https://hlxecz.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOLID 랑 이것 저것 찾아보다가 디자인 패턴은 어떤 것 들이 있을까 해서 찾아봤습니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부 할게 너무너무 많은 것 일단 종류만 먼저 정리해 볼게요 !!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; color: #333; line-height: 1.6;&quot;&gt;
&lt;div style=&quot;background-color: #f8f9fa; border: 1px solid #e9ecef; border-radius: 8px; padding: 20px; margin-bottom: 30px;&quot;&gt;
&lt;h2 style=&quot;margin-top: 0; color: #495057; border-bottom: 2px solid #adb5bd; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;b&gt;디자인 패턴(Design Pattern)&lt;/b&gt;이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 중 발생하는 반복적인 문제들에 대한 해결책으로, 많은 개발자가 인정한 &lt;b&gt;모범 사례(Best Practice)&lt;/b&gt;입니다. 객체 지향 4대 특성과 SOLID 원칙을 기반으로 합니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #495057; margin-top: 20px;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp; 디자인 패턴의 &lt;b&gt;장점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; padding-left: 20px;&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; 모듈화가 용이하여 변경 시 해당 부분만 수정 가능&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;/div&gt;
&lt;h3 style=&quot;color: #495057;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;gof.png&quot; data-origin-width=&quot;777&quot; data-origin-height=&quot;574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be4ZKU/dJMcafZHkHy/ixdj8dlwqfK8LkGkpta1J1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be4ZKU/dJMcafZHkHy/ixdj8dlwqfK8LkGkpta1J1/img.png&quot; data-alt=&quot;디자인 패턴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be4ZKU/dJMcafZHkHy/ixdj8dlwqfK8LkGkpta1J1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe4ZKU%2FdJMcafZHkHy%2Fixdj8dlwqfK8LkGkpta1J1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;782&quot; height=&quot;578&quot; data-filename=&quot;gof.png&quot; data-origin-width=&quot;777&quot; data-origin-height=&quot;574&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;디자인 패턴&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;h3 style=&quot;color: #495057;&quot; data-ke-size=&quot;size23&quot;&gt;  객체 지향과 디자인 패턴의 비유&lt;/h3&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin-bottom: 30px; border: 1px solid #dee2e6;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #e9ecef; text-align: center;&quot;&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #dee2e6;&quot;&gt;프로그래밍 개념&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #dee2e6;&quot;&gt;요리 비유&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #dee2e6;&quot;&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #dee2e6; text-align: center; font-weight: bold;&quot;&gt;객체 지향 4대 원칙&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #dee2e6; text-align: center;&quot;&gt;요리 도구&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #dee2e6;&quot;&gt;캡슐화, 상속, 추상화, 다형성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #dee2e6; text-align: center; font-weight: bold;&quot;&gt;설계 원칙 (SOLID)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #dee2e6; text-align: center;&quot;&gt;도구 사용법&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #dee2e6;&quot;&gt;도구를 올바르게 다루는 방법&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f1f3f5;&quot;&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #dee2e6; text-align: center; font-weight: bold; color: #d6336c;&quot;&gt;디자인 패턴&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #dee2e6; text-align: center; font-weight: bold; color: #d6336c;&quot;&gt;레시피&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #dee2e6;&quot;&gt;표준화된 문제 해결 방법&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 style=&quot;color: #495057; border-bottom: 2px solid #adb5bd; padding-bottom: 10px; margin-top: 40px;&quot; data-ke-size=&quot;size26&quot;&gt;GoF의 23가지 디자인 패턴&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #495057; color: #fff; padding: 10px; border-radius: 5px; margin-bottom: 0;&quot; data-ke-size=&quot;size23&quot;&gt;1. 생성 패턴 (Creational Pattern)&lt;/h3&gt;
&lt;p style=&quot;font-size: 0.9em; color: #666; margin-bottom: 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 0.9em; color: #666; margin-bottom: 10px;&quot; data-ke-size=&quot;size16&quot;&gt;객체 생성에 관련된 패턴으로, 객체의 생성과 조합을 캡슐화해 특정 객체가 생성되거나 변경되어도 프로그램 구조에 영향을 크게 받지 않도록 유연성을 제공합니다.&lt;/p&gt;
&lt;p style=&quot;font-size: 0.9em; color: #666; margin-bottom: 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin-bottom: 30px; font-size: 0.95em; height: 235px;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody style=&quot;border-top: 2px solid #495057;&quot;&gt;
&lt;tr style=&quot;height: 47px;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold; width: 25%; height: 47px;&quot;&gt;Singleton&lt;br /&gt;(싱글톤)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; height: 47px;&quot;&gt;하나의 인스턴스만 생성되도록 보장하고, 어디서든 접근 가능하게 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 47px;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold; height: 47px;&quot;&gt;Factory Method&lt;br /&gt;(팩토리 메서드)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; height: 47px;&quot;&gt;객체 생성을 서브 클래스로 미루어 어떤 클래스의 인스턴스를 생성할지 결정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 47px;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold; height: 47px;&quot;&gt;Abstract Factory&lt;br /&gt;(추상 팩토리)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; height: 47px;&quot;&gt;관련된 객체들의 집합을 생성하는 인터페이스를 제공하여 구체적인 생성을 추상화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 47px;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold; height: 47px;&quot;&gt;Builder&lt;br /&gt;(빌더)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; height: 47px;&quot;&gt;복잡한 객체의 생성 과정을 단순화하여 단계적으로 생성 및 조립&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 47px;&quot;&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold; height: 47px;&quot;&gt;Prototype&lt;br /&gt;(프로토타입)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; height: 47px;&quot;&gt;기존 객체를 복제(Clone)하여 새로운 객체를 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #495057; color: #fff; padding: 10px; border-radius: 5px; margin-bottom: 0;&quot; data-ke-size=&quot;size23&quot;&gt;2. 구조 패턴 (Structural Pattern)&lt;/h3&gt;
&lt;p style=&quot;font-size: 0.9em; color: #666; margin-bottom: 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 0.9em; color: #666; margin-bottom: 10px;&quot; data-ke-size=&quot;size16&quot;&gt;클래스나 객체를 조합해 더 큰 구조를 만드는 패턴입니다.&lt;/p&gt;
&lt;p style=&quot;font-size: 0.9em; color: #666; margin-bottom: 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin-bottom: 30px; font-size: 0.95em;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody style=&quot;border-top: 2px solid #495057;&quot;&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold; width: 25%;&quot;&gt;Adapter&lt;br /&gt;(어댑터)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;호환되지 않는 인터페이스를 가진 클래스들을 함께 사용할 수 있도록 래퍼(Wrapper) 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Bridge&lt;br /&gt;(브릿지)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;추상화와 구현을 분리하여 각각 독립적으로 확장 가능하게 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Composite&lt;br /&gt;(컴포지트)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;개별 객체와 복합 객체를 동일하게 다루며 트리 구조를 구성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Decorator&lt;br /&gt;(데코레이터)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;객체에 동적으로 새로운 기능을 추가하여 확장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Facade&lt;br /&gt;(퍼사드)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;복잡한 서브시스템을 쉽게 사용할 수 있도록 단순한 통합 인터페이스 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Flyweight&lt;br /&gt;(플라이웨이트)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;대량의 작은 객체들을 공유하여 메모리 사용 최적화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Proxy&lt;br /&gt;(프록시)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;다른 객체에 대한 대리자를 제공하여 접근 제어, 지연 로딩 등을 수행&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #495057; color: #fff; padding: 10px; border-radius: 5px; margin-bottom: 0;&quot; data-ke-size=&quot;size23&quot;&gt;3. 행위 패턴 (Behavioral Pattern)&lt;/h3&gt;
&lt;p style=&quot;font-size: 0.9em; color: #666; margin-bottom: 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 0.9em; color: #666; margin-bottom: 10px;&quot; data-ke-size=&quot;size16&quot;&gt;객체나 클래스 사이의 알고리즘이나 책임 분배에 관련된 패턴입니다.&lt;/p&gt;
&lt;p style=&quot;font-size: 0.9em; color: #666; margin-bottom: 10px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; margin-bottom: 30px; font-size: 0.95em;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody style=&quot;border-top: 2px solid #495057;&quot;&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold; width: 25%;&quot;&gt;Observer&lt;br /&gt;(옵저버)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;상태 변경 시 의존하는 다른 객체들에게 자동으로 알림&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Strategy&lt;br /&gt;(전략)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;알고리즘을 정의하고 캡슐화하여 실행 중에 교체 가능하게 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Command&lt;br /&gt;(커맨드)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;요청을 객체로 캡슐화하여 큐 저장, 로깅, 실행 취소 등을 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;State&lt;br /&gt;(상태)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;객체의 내부 상태에 따라 스스로 행동을 변경하도록 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Chain of Responsibility&lt;br /&gt;(책임 연쇄)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;요청을 처리하는 객체들을 체인으로 연결하여 처리할 때까지 넘김&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Visitor&lt;br /&gt;(방문자)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;객체 구조를 변경하지 않고 새로운 연산을 수행할 수 있게 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Interpreter&lt;br /&gt;(인터프리터)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;언어의 문법을 정의하고 해석기를 제공하여 문제 해결&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Memento&lt;br /&gt;(메멘토)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;객체의 내부 상태를 저장해 두었다가 나중에 복원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Mediator&lt;br /&gt;(중재자)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;객체 간의 복잡한 통신을 캡슐화하여 결합도를 낮춤&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Template Method&lt;br /&gt;(템플릿 메서드)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;알고리즘의 골격은 상위 클래스에, 구체적 단계는 하위 클래스에 구현&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6; background-color: #f8f9fa; font-weight: bold;&quot;&gt;Iterator&lt;br /&gt;(이터레이터)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border-bottom: 1px solid #dee2e6;&quot;&gt;내부 구조를 노출하지 않고 컬렉션의 요소에 순차적으로 접근&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;갑자기 또 궁금해진 GoF 저만,, 영어 약자 나오면 궁금해지는거 아니겠죠 아래에다가 정리해볼게요 !&lt;/p&gt;
&lt;div style=&quot;font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; color: #333; line-height: 1.6; margin-top: 50px;&quot;&gt;
&lt;div style=&quot;background-color: #f8f9fa; border-left: 5px solid #495057; padding: 20px; border-radius: 4px;&quot;&gt;
&lt;h3 style=&quot;margin-top: 0; color: #212529; font-size: 1.1em; border-bottom: 1px solid #dee2e6; padding-bottom: 10px;&quot; data-ke-size=&quot;size23&quot;&gt;디자인 패턴의 기원: GoF(Gang of Four)&lt;/h3&gt;
&lt;p style=&quot;margin-bottom: 10px; font-size: 0.95em;&quot; data-ke-size=&quot;size16&quot;&gt;우리가 학습하는 디자인 패턴의 표준은 1994년 출간된 책 &lt;b&gt;《Design Patterns: Elements of Reusable Object-Oriented Software》&lt;/b&gt;에서 정립되었습니다.&lt;/p&gt;
&lt;p style=&quot;margin-bottom: 10px; font-size: 0.95em;&quot; data-ke-size=&quot;size16&quot;&gt;이 책은 소프트웨어 설계의 공통된 문제에 대한 해법과 작명법을 제안하였으며, 공동 저자인 &lt;b&gt;에리히 감마(Erich Gamma), 리처드 헬름(Richard Helm), 랄프 존슨(Ralph Johnson), 존 블리시데스(John Vlissides)&lt;/b&gt; 네 명을 가리켜 이 분야의 &lt;b&gt;'4인방(Gang of Four, GoF)'&lt;/b&gt;이라 부릅니다.&lt;/p&gt;
&lt;ul style=&quot;margin-bottom: 0; font-size: 0.9em; color: #555; background-color: #e9ecef; padding: 10px 10px 10px 30px; border-radius: 4px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;책의 전반부는 패턴의 정의를, 후반부는 실용적인 23가지 패턴을 다룸&lt;/li&gt;
&lt;li&gt;예제 코드는 객체지향 언어인 C++과 스몰토크(Smalltalk)로 작성됨&lt;/li&gt;
&lt;li&gt;한국어판은 피어슨 에듀케이션 코리아를 통해 출판됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: right; margin-top: 15px; font-size: 0.85em; color: #868e96;&quot;&gt;&lt;span style=&quot;color: #888888; font-size: 0.8em; letter-spacing: 0px;&quot;&gt;참고 및 출처: &lt;/span&gt;&lt;a style=&quot;color: #666; text-decoration: none;&quot; href=&quot;https://ittrue.tistory.com/550&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;IT is True:티스토리&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Knowledge/디자인 패턴</category>
      <category>GOF</category>
      <category>디자인 패턴</category>
      <author>hlxecz</author>
      <guid isPermaLink="true">https://hlxecz.tistory.com/17</guid>
      <comments>https://hlxecz.tistory.com/17#entry17comment</comments>
      <pubDate>Mon, 26 Jan 2026 19:03:55 +0900</pubDate>
    </item>
    <item>
      <title>[OOP] 객체 지향 설계의 5가지 원칙 - S.O.L.I.D</title>
      <link>https://hlxecz.tistory.com/16</link>
      <description>&lt;div style=&quot;background-color: #f6f8fa; border: 1px solid #d0d7de; border-radius: 6px; padding: 12px 15px; margin-bottom: 20px; font-size: 0.9em; display: flex; align-items: center; font-family: 'Apple SD Gothic Neo', sans-serif;&quot;&gt;&lt;span style=&quot;margin-right: 10px; font-size: 1.2em;&quot;&gt; &lt;/span&gt;
&lt;div&gt;&lt;span style=&quot;color: #57606a; font-weight: bold;&quot;&gt;Design Pattern:&lt;/span&gt;&lt;span style=&quot;color: #0969da; font-weight: bold; margin-left: 5px;&quot;&gt;SOILD&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #57606a; font-weight: bold;&quot;&gt;Problem Source:&lt;/span&gt; &lt;a style=&quot;color: #0969da; text-decoration: none; font-weight: bold; margin-left: 5px;&quot; href=&quot;https://github.com/Hlxecz/Sw_Pilot_Java/blob/main/Chapter_4/Step4/src/Rule01/SOILD.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; GitHub - Sw_Pilot_Java (Chapter 4 / Step 4) &lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;contents_style&quot; style=&quot;font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; line-height: 1.7; color: #333;&quot;&gt;
&lt;h2 style=&quot;border-bottom: 1px solid #ddd; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;SOLID 원칙이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체지향 설계 5대 원칙으로, &lt;b&gt;유지보수성과 확장성을 높이고 코드의 복잡도를 줄이기 위한 핵심 설계 지침&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SOLID 원칙은 특정 언어나 프레임워크에 종속되지 않는, &quot;변화에 유연하고 유지보수하기 쉬운 코드&quot;를 만들기 위한 기본 철학입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;srp&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. SRP: 단일 책임 원칙 (Single Responsibility Principle)&lt;/b&gt;&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;795&quot; data-origin-height=&quot;603&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YjPKs/dJMcafFtNic/aigHQXY0hYWGhqenzJ99t1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YjPKs/dJMcafFtNic/aigHQXY0hYWGhqenzJ99t1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YjPKs/dJMcafFtNic/aigHQXY0hYWGhqenzJ99t1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYjPKs%2FdJMcafFtNic%2FaigHQXY0hYWGhqenzJ99t1%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;427&quot; height=&quot;324&quot; data-origin-width=&quot;795&quot; data-origin-height=&quot;603&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&quot;한 클래스는 하나의 책임(기능)만 가져야 한다.&quot;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 클래스에 여러 책임이 섞여 있으면, 한 기능의 변경이 다른 기능에 연쇄적인 영향을 줄 수 있습니다. 책임을 명확히 분리하면 변경의 파급효과를 줄이고 유지보수성이 높아집니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #e8f5e9; padding: 15px; border-radius: 8px; margin: 15px 0;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: #2e7d32;&quot;&gt;  Tip:&lt;/span&gt;&lt;br /&gt;청소기는 청소만 잘하면 됩니다. 화분에 물 주고 드라이 기능까지 넣으면 하나만 고장 나도 전체를 못 쓰게 되죠. &lt;b&gt;하나의 클래스는 한 가지 책임만 지게 하세요!&lt;/b&gt;&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 간단한 예시&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// 보고서 생성 책임
public class ReportGenerator {
    public String generate() {
        return &quot;Report 내용&quot;;
    }
}

// 보고서 출력 책임 (분리됨)
public class ReportPrinter {
    public void print(String report) {
        System.out.println(report);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;ocp&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. OCP: 개방-폐쇄 원칙 (Open/Closed Principle)&lt;/b&gt;&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;643&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjdApg/dJMcaia9mU4/DnUK8k8g9pEoikdTSiRKx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjdApg/dJMcaia9mU4/DnUK8k8g9pEoikdTSiRKx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjdApg/dJMcaia9mU4/DnUK8k8g9pEoikdTSiRKx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjdApg%2FdJMcaia9mU4%2FDnUK8k8g9pEoikdTSiRKx1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;445&quot; height=&quot;312&quot; data-origin-width=&quot;916&quot; data-origin-height=&quot;643&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&quot;클래스는 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 한다.&quot;&lt;/b&gt;&lt;/blockquote&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;div style=&quot;background-color: #e8f5e9; padding: 15px; border-radius: 8px; margin: 15px 0;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: #2e7d32;&quot;&gt;  Tip:&lt;/span&gt;&lt;br /&gt;역할(인터페이스)과 구현(클래스)을 분리하세요. 기존 코드는 건드리지 말고, 새로운 클래스를 추가(상속/구현)하는 방식으로 기능을 확장하세요.&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 간단한 예시&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;interface Payment {
    void pay();
}

// 새로운 결제 수단이 추가되어도 Payment 인터페이스만 구현하면 됨
class CardPayment implements Payment {
    public void pay() {
        System.out.println(&quot;카드 결제 진행&quot;);
    }
}

class OrderService {
    private Payment payment;
    
    // 생성자 주입을 통해 유연하게 변경 가능
    public OrderService(Payment payment) {
        this.payment = payment;
    }
    
    public void checkout() {
        payment.pay(); // 기존 코드는 수정할 필요 없음
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;lsp&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. LSP: 리스코프 치환 원칙 (Liskov Substitution Principle)&lt;/b&gt;&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1083&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIU7u2/dJMcajgK13E/mbCTiqka9FSm5ImK2exLkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIU7u2/dJMcajgK13E/mbCTiqka9FSm5ImK2exLkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIU7u2/dJMcajgK13E/mbCTiqka9FSm5ImK2exLkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIU7u2%2FdJMcajgK13E%2FmbCTiqka9FSm5ImK2exLkK%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;546&quot; height=&quot;348&quot; data-origin-width=&quot;1083&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&quot;자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 한다.&quot;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다형성을 활용할 때, 부모 클래스 타입으로 선언된 변수에 자식 객체를 대입해도 프로그램이 원래 의도대로 동작해야 한다는 원칙입니다. 즉, 자식 클래스는 부모의 규약을 철저히 지켜야 합니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #e8f5e9; padding: 15px; border-radius: 8px; margin: 15px 0;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: #2e7d32;&quot;&gt;  Tip:&lt;/span&gt;&lt;br /&gt;자바의 Collection 프레임워크가 대표적인 예입니다. &lt;code&gt;LinkedList&lt;/code&gt;에서 &lt;code&gt;HashSet&lt;/code&gt;으로 구현체를 바꿔도 &lt;code&gt;.add()&lt;/code&gt; 동작은 논리적으로 문제없이 작동해야 합니다.&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 간단한 예시&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// 부모 타입 Collection
Collection&amp;lt;String&amp;gt; myData = new LinkedList&amp;lt;&amp;gt;();
myData.add(&quot;apple&quot;);

// 자식 클래스를 HashSet으로 교체해도 add() 동작은 보장됨 -&amp;gt; LSP 만족
myData = new HashSet&amp;lt;&amp;gt;();
myData.add(&quot;banana&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;isp&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. ISP: 인터페이스 분리 원칙 (Interface Segregation Principle)&lt;/b&gt;&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;688&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzNn1P/dJMcadOmDg7/3K4KGs7so5Onp5GBkEaS6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzNn1P/dJMcadOmDg7/3K4KGs7so5Onp5GBkEaS6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzNn1P/dJMcadOmDg7/3K4KGs7so5Onp5GBkEaS6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdzNn1P%2FdJMcadOmDg7%2F3K4KGs7so5Onp5GBkEaS6K%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;663&quot; height=&quot;356&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;688&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&quot;인터페이스는 작게 나눠서, 구현체가 필요한 기능만 구현하게 하자.&quot;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;범용적인 큰 인터페이스 하나보다는, 구체적인 여러 개의 인터페이스가 낫습니다. 구현하는 클래스가 자신이 사용하지 않는 기능까지 억지로 구현하지 않도록 해야 합니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #e8f5e9; padding: 15px; border-radius: 8px; margin: 15px 0;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: #2e7d32;&quot;&gt;  Tip:&lt;/span&gt;&lt;br /&gt;인터페이스는 다중 상속(구현)이 가능합니다. 기능별로 잘게 쪼개서 필요한 것만 골라 구현하도록 설계하세요.&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 간단한 예시&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// 기능별로 인터페이스 분리
interface Printer {
    void print();
}

interface Fax {
    void fax();
}

// 팩스 기능이 없는 프린터는 Printer만 구현하면 됨 (불필요한 fax() 구현 강제 X)
class BasicPrinter implements Printer {
    public void print() {
        System.out.println(&quot;프린트 출력 중&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;dip&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. DIP: 의존 역전 원칙 (Dependency Inversion Principle)&lt;/b&gt;&lt;/h2&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w1LuO/dJMcagxBeCF/wRSswsGRffgtstEtk9PwZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w1LuO/dJMcagxBeCF/wRSswsGRffgtstEtk9PwZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w1LuO/dJMcagxBeCF/wRSswsGRffgtstEtk9PwZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw1LuO%2FdJMcagxBeCF%2FwRSswsGRffgtstEtk9PwZk%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;745&quot; height=&quot;311&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;534&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&quot;구현 클래스에 의존하지 말고, 추상화(인터페이스)에 의존해야 한다.&quot;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변하기 쉬운 것(구현체)보다는 변하지 않는 것(인터페이스, 추상 클래스)에 의존해야 유지보수가 쉬워집니다. 이를 위해 보통 &lt;b&gt;의존성 주입(DI)&lt;/b&gt;을 활용합니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #e8f5e9; padding: 15px; border-radius: 8px; margin: 15px 0;&quot;&gt;&lt;span style=&quot;font-weight: bold; color: #2e7d32;&quot;&gt;  Tip:&lt;/span&gt;&lt;br /&gt;&quot;저장한다&quot;는 역할(인터페이스)에 의존해야지, &quot;MySQL에 저장한다&quot;는 구체적인 사실에 의존하면 나중에 오라클로 DB를 바꿀 때 코드를 다 뜯어고쳐야 합니다.&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 간단한 예시&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// 추상화에 의존
interface Database {
    void save(String data);
}

class MySQLDatabase implements Database {
    public void save(String data) {
        System.out.println(&quot;MySQL에 저장: &quot; + data);
    }
}

class DataService {
    private Database db; // 구체적인 MySQLDatabase가 아닌 인터페이스에 의존
    
    public DataService(Database db) {
        this.db = db;
    }
    
    public void store(String input) {
        db.save(input);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;summary&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무리 요약&lt;/b&gt;&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: center; width: 15%;&quot;&gt;원칙&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: center;&quot;&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;SRP&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;하나의 클래스는 &lt;b&gt;하나의 책임&lt;/b&gt;만 가져야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;OCP&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;확장에는 &lt;b&gt;열려&lt;/b&gt; 있고, 수정에는 &lt;b&gt;닫혀&lt;/b&gt; 있어야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;LSP&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;자식 클래스는 &lt;b&gt;부모 클래스를 대체&lt;/b&gt;해도 문제없어야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;ISP&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;필요한 기능만 가진 &lt;b&gt;인터페이스로 분리&lt;/b&gt;해야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;DIP&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;구현체가 아닌, &lt;b&gt;추상화(인터페이스)에 의존&lt;/b&gt;해야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #f6f8fa; padding: 20px; border-radius: 8px; border: 1px solid #d0d7de; margin-top: 30px;&quot;&gt;
&lt;p style=&quot;margin: 0; font-weight: bold; color: #555; margin-bottom: 8px;&quot; data-ke-size=&quot;size16&quot;&gt;  Reference &amp;amp; Source&lt;/p&gt;
&lt;div style=&quot;margin-top: 15px; padding: 12px; background-color: #ffffff; border-radius: 6px; border: 1px solid #e1e4e8;&quot;&gt;  &lt;a style=&quot;text-decoration: none; color: #0969da; font-weight: bold; font-size: 0.95em;&quot; href=&quot;https://inpa.tistory.com/entry/OOP-%F0%9F%92%A0-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%84%A4%EA%B3%84%EC%9D%98-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%B9%99-SOLID&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; [Inpa Dev  &amp;zwj; ] solid&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;margin-top: 15px; padding: 12px; background-color: #ffffff; border-radius: 6px; border: 1px solid #e1e4e8;&quot;&gt;  &lt;a style=&quot;text-decoration: none; color: #0969da; font-weight: bold; font-size: 0.95em;&quot; href=&quot;https://medium.com/@learnstuff.io/single-responsibility-principle-ad3ae3e264bb&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; SRP&lt;/a&gt;&lt;/div&gt;
&lt;div style=&quot;margin-top: 15px; padding: 12px; background-color: #ffffff; border-radius: 6px; border: 1px solid #e1e4e8;&quot;&gt;  &lt;a style=&quot;text-decoration: none; color: #0969da; font-weight: bold; font-size: 0.95em;&quot; href=&quot;  https://www.linkedin.com/pulse/interface-segregation-principle-mamata-raote-she-her-/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; ISP &lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Knowledge/디자인 패턴</category>
      <category>Solid</category>
      <author>hlxecz</author>
      <guid isPermaLink="true">https://hlxecz.tistory.com/16</guid>
      <comments>https://hlxecz.tistory.com/16#entry16comment</comments>
      <pubDate>Mon, 26 Jan 2026 18:39:08 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] 인터페이스 vs 추상클래스 차이점 정리</title>
      <link>https://hlxecz.tistory.com/15</link>
      <description>&lt;div class=&quot;contents_style&quot; style=&quot;font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; line-height: 1.7; color: #333;&quot;&gt;
&lt;h2 style=&quot;border-left: 5px solid #293a55; padding-left: 12px; margin: 30px 0 20px 0; color: #333;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 한눈에 보는 비교 &lt;span style=&quot;color: #888888; text-align: start;&quot;&gt;(Interface vs abstract)&lt;/span&gt; &lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스와 추상 클래스, 막상 비교하려면 헷갈리는 두 개념의 문법적 차이를 표로 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border-top: 2px solid #545454; border-bottom: 1px solid #ddd; font-size: 0.95em;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f5f5f5; border-bottom: 1px solid #ccc;&quot;&gt;
&lt;th style=&quot;padding: 15px 10px; text-align: left; width: 20%; color: #333; font-weight: bold;&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;padding: 15px 10px; text-align: left; width: 40%; color: #333; font-weight: bold; border-left: 1px solid #e0e0e0;&quot;&gt;추상 클래스&lt;/th&gt;
&lt;th style=&quot;padding: 15px 10px; text-align: left; width: 40%; color: #333; font-weight: bold; border-left: 1px solid #e0e0e0;&quot;&gt;인터페이스&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr style=&quot;border-bottom: 1px solid #eee;&quot;&gt;
&lt;td style=&quot;padding: 12px 10px; font-weight: bold; color: #555;&quot;&gt;사용 키워드&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0;&quot;&gt;&lt;code&gt;abstract&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0;&quot;&gt;&lt;code&gt;interface&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;border-bottom: 1px solid #eee;&quot;&gt;
&lt;td style=&quot;padding: 12px 10px; font-weight: bold; color: #555;&quot;&gt;사용 가능 변수&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0;&quot;&gt;제한 없음&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0;&quot;&gt;&lt;span style=&quot;color: #e91e63;&quot;&gt;static final (상수)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;border-bottom: 1px solid #eee;&quot;&gt;
&lt;td style=&quot;padding: 12px 10px; font-weight: bold; color: #555;&quot;&gt;접근 제어자&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0;&quot;&gt;제한 없음&lt;br /&gt;&lt;span style=&quot;font-size: 0.85em; color: #888;&quot;&gt;(public, private, protected, default)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0;&quot;&gt;&lt;code&gt;public&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;border-bottom: 1px solid #eee;&quot;&gt;
&lt;td style=&quot;padding: 12px 10px; font-weight: bold; color: #555;&quot;&gt;사용 가능 메서드&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0;&quot;&gt;제한 없음&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0;&quot;&gt;abstract, default, static, private&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;border-bottom: 1px solid #eee;&quot;&gt;
&lt;td style=&quot;padding: 12px 10px; font-weight: bold; color: #555;&quot;&gt;상속 키워드&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0;&quot;&gt;&lt;code&gt;extends&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0;&quot;&gt;&lt;code&gt;implements&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;border-bottom: 2px solid #ccc;&quot;&gt;
&lt;td style=&quot;padding: 12px 10px; font-weight: bold; color: #555;&quot;&gt;다중 상속 여부&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0; color: #d32f2f;&quot;&gt;&lt;b&gt;불가능&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 12px 10px; border-left: 1px solid #f0f0f0; color: #2e7d32;&quot;&gt;&lt;b&gt;가능&lt;br /&gt;&lt;span style=&quot;color: #888888; text-align: start;&quot;&gt;클래스에 다중구현, 인터페이스 끼리 다중 상속&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f9f9f9;&quot;&gt;
&lt;td style=&quot;padding: 15px 10px; font-weight: bold; color: #555; vertical-align: top;&quot;&gt;공통점&lt;/td&gt;
&lt;td style=&quot;padding: 15px 10px; border-left: 1px solid #e0e0e0; line-height: 1.8; color: #444;&quot; colspan=&quot;2&quot;&gt;1. 추상 메서드를 가지고 있어야 한다.&lt;br /&gt;2. 인스턴스화 할 수 없다. (&lt;code&gt;new&lt;/code&gt; 생성자 사용 불가)&lt;br /&gt;3. 구현체(자식 클래스)의 인스턴스를 사용해야 한다.&lt;br /&gt;4. 상속/구현 받은 클래스는 &lt;b&gt;추상 메서드를 반드시 구현(Override)&lt;/b&gt; 해야 한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;&lt;/div&gt;
&lt;h2 style=&quot;border-left: 5px solid #293a55; padding-left: 12px; margin: 30px 0 20px 0; color: #333;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 인터페이스 (Interface)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스는 구현 객체가 &lt;b&gt;&quot;같은 동작을 한다&quot;&lt;/b&gt;는 것을 보장하기 위한 &lt;b&gt;설계도&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속 관계에 얽매이지 않고 자유롭게 기능을 장착할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 특징&lt;/h3&gt;
&lt;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;span style=&quot;color: #ee2323;&quot;&gt;&lt;code&gt;public abstract&lt;/code&gt;&lt;/span&gt;입니다. (Java 8부터 default/static 메서드 가능)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상수만 허용:&lt;/b&gt; 일반 변수는 가질 수 없으며, 모든 필드는 &lt;code&gt;public static final&lt;/code&gt; 상수입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다중 구현 가능:&lt;/b&gt; 클래스는 여러 인터페이스를 동시에 구현(implements)할 수 있어 유연합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;행위 중심 (Can-do):&lt;/b&gt; &quot;무엇을 할 수 있는가&quot;에 초점을 둡니다. 보통 &lt;code&gt;~able&lt;/code&gt;로 네이밍합니다. (예: &lt;code&gt;Runnable&lt;/code&gt;, &lt;code&gt;Serializable&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;간단 예시&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// '날 수 있는' 기능 정의
interface Flyable {
    void fly(); // public abstract 생략 가능
}

// '수영할 수 있는' 기능 정의
interface Swimmable {
    void swim();
}

// 오리는 날 수도 있고, 수영할 수도 있음 (다중 구현)
class Duck implements Flyable, Swimmable {
    @Override
    public void fly() { System.out.println(&quot;오리가 날아갑니다.&quot;); }
    
    @Override
    public void swim() { System.out.println(&quot;오리가 수영합니다.&quot;); }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;abstract-class&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 추상 클래스 (Abstract Class)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상 클래스는 하위 클래스들의 &lt;b&gt;&quot;공통점을 모아둔 미완성 클래스&quot;&lt;/b&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;&lt;b&gt;단일 상속:&lt;/b&gt; 일반 클래스와 마찬가지로 하나만 상속(extends)받을 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;일반 멤버 보유:&lt;/b&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;족보 중심 (Is-a):&lt;/b&gt; &quot;무엇인가&quot;에 초점을 둡니다. 서로 연관된 클래스들의 뼈대 역할을 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;간단 예시&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// 동물이라는 공통 분모 (미완성 설계도)
abstract class Animal {
    String name; // 상태(변수)를 가질 수 있음

    // 공통 기능 (일반 메서드)
    void eat() { System.out.println(&quot;밥을 먹습니다.&quot;); }

    // 자식마다 다른 기능 (추상 메서드)
    abstract void sound(); 
}

class Dog extends Animal {
    @Override
    void sound() { System.out.println(&quot;멍멍!&quot;); }
}

class Cat extends Animal {
    @Override
    void sound() { System.out.println(&quot;야옹!&quot;); }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;section5&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 그래서 언제, 무엇을 써야 할까?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이론적인 차이점은 알겠지만, 막상 코드를 짤 때 &quot;지금 뭘 써야 하지?&quot; 고민될 때가 많습니다. 상황별 선택 가이드를 제시합니다.&lt;/p&gt;
&lt;div style=&quot;display: flex; gap: 20px; margin-bottom: 20px;&quot;&gt;
&lt;div style=&quot;flex: 1; background-color: #fff3e0; padding: 15px; border-radius: 8px; border: 1px solid #ffe0b2;&quot;&gt;
&lt;h3 style=&quot;margin-top: 0; color: #ef6c00;&quot; data-ke-size=&quot;size23&quot;&gt; ️ 추상 클래스 (Abstract Class)&lt;/h3&gt;
&lt;ul style=&quot;padding-left: 20px; margin-bottom: 0; line-height: 1.6;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&quot;IS-A&quot; 관계일 때:&lt;/b&gt; &quot;강아지는 동물이다&quot;, &quot;자동차는 탈것이다&quot;처럼 명확한 계층 구조가 필요할 때.&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;code&gt;public&lt;/code&gt; 이외에 &lt;code&gt;protected&lt;/code&gt;나 &lt;code&gt;private&lt;/code&gt; 멤버가 필요할 때.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div style=&quot;flex: 1; background-color: #e3f2fd; padding: 15px; border-radius: 8px; border: 1px solid #bbdefb;&quot;&gt;
&lt;h3 style=&quot;margin-top: 0; color: #1565c0;&quot; data-ke-size=&quot;size23&quot;&gt; ️ 인터페이스 (Interface)&lt;/h3&gt;
&lt;ul style=&quot;padding-left: 20px; margin-bottom: 0; line-height: 1.6;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&quot;CAN-DO&quot; 관계일 때:&lt;/b&gt; &quot;날 수 있다(Flyable)&quot;, &quot;저장할 수 있다(Saveable)&quot;처럼 기능을 장착해주고 싶을 때.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서로 다른 조상을 가질 때:&lt;/b&gt; 상속 계보와 상관없이 공통 기능을 부여하고 싶을 때. (예: &lt;code&gt;Bird&lt;/code&gt;와 &lt;code&gt;Airplane&lt;/code&gt;은 다르지만 둘 다 &lt;code&gt;Flyable&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다중 구현이 필요할 때:&lt;/b&gt; 하나의 클래스가 여러 가지 역할을 수행해야 할 때.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section6&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. 실전 패턴: 인터페이스와 추상 클래스의 조합 (Mixin)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 실무에서는 이 둘을 &lt;b&gt;함께 사용하는 경우&lt;/b&gt;가 많습니다. 인터페이스의 &quot;유연함(다중 상속)&quot;과 추상 클래스의 &quot;편리함(중복 제거)&quot;을 모두 챙기는 강력한 설계 패턴입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시: 게임 캐릭터 만들기 (Game Character)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임의 모든 캐릭터는 공격(Attack)하고 이동(Move)할 수 있어야 합니다. (인터페이스 역할)&lt;br /&gt;하지만, 모든 캐릭터는 체력(HP)과 레벨(Level)이라는 공통 속성을 가집니다. (추상 클래스 역할)&lt;/p&gt;
&lt;h4 style=&quot;color: #666;&quot; data-ke-size=&quot;size20&quot;&gt;Step 1. 인터페이스로 설계도(기능) 정의&lt;/h4&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;interface Attackable {
    void attack(); // 모든 캐릭터는 공격해야 함 (강제성)
}

interface Movable {
    void move(); // 모든 캐릭터는 움직여야 함
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #666;&quot; data-ke-size=&quot;size20&quot;&gt;Step 2. 추상 클래스로 공통 멤버(뼈대) 구현&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스에는 변수(상태)를 담을 수 없으니, 추상 클래스를 중간에 둬서 공통 변수를 관리합니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// 인터페이스를 구현(implements)하면서, 공통 기능은 미리 만들어두는 추상 클래스
abstract class GameCharacter implements Attackable, Movable {
    // 1. 공통 필드 (중복 제거)
    protected int hp;
    protected int level;

    // 2. 공통 메서드 (중복 제거)
    public void levelUp() {
        this.level++;
        System.out.println(&quot;레벨 업! 현재 레벨: &quot; + this.level);
    }
    
    // attack()과 move()는 자식마다 다르므로 추상 메서드로 남겨둠 (구현 강제)
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #666;&quot; data-ke-size=&quot;size20&quot;&gt;Step 3. 실제 클래스 구현 (단순화)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 실제 캐릭터 클래스들은 &lt;code&gt;hp&lt;/code&gt;, &lt;code&gt;level&lt;/code&gt; 변수를 일일이 선언할 필요 없이, 핵심 로직에만 집중하면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; &gt;&lt;code&gt;class Warrior extends GameCharacter {
    @Override
    public void attack() {
        System.out.println(&quot;칼로 공격합니다!&quot;);
    }
    @Override
    public void move() {
        System.out.println(&quot;뛰어서 이동합니다.&quot;);
    }
}

class Wizard extends GameCharacter {
    @Override
    public void attack() {
        System.out.println(&quot;마법 불꽃 발사!&quot;);
    }
    @Override
    public void move() {
        System.out.println(&quot;텔레포트로 이동합니다.&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;div style=&quot;background-color: #f9f9f9; padding: 20px; border-radius: 10px; border: 1px solid #ddd; margin-top: 20px;&quot;&gt;
&lt;h2 id=&quot;section7&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;7. 결론: 다형성(Polymorphism)의 중요성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 인터페이스와 추상 클래스를 조합해서 복잡하게 설계한 진짜 이유는 바로 &lt;b&gt;&quot;다형성을 200% 활용하기 위해서&quot;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 우리는 전사(Warrior)든 마법사(Wizard)든 상관없이, 모두 &lt;b&gt;&lt;code&gt;GameCharacter&lt;/code&gt;&lt;/b&gt;라는 하나의 타입으로 묶어서 관리할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다형성 활용 코드 예시&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class GameMain {
    public static void main(String[] args) {
        // 1. 다형성: 서로 다른 객체를 '부모 타입'으로 묶음
        List&amp;lt;GameCharacter&amp;gt; party = new ArrayList&amp;lt;&amp;gt;();
        party.add(new Warrior());
        party.add(new Wizard());

        // 2. 일괄 처리: 구체적인 타입(전사인지 마법사인지)을 몰라도 됨
        for (GameCharacter character : party) {
            character.move();   // 공통 기능 (추상 클래스에서 상속)
            character.attack(); // 개별 기능 (오버라이딩된 메서드 실행)
            // 전사는 &quot;칼 공격&quot;, 마법사는 &quot;마법 공격&quot;이 자동으로 나감!
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;margin-top: 0; color: #2e7d32;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&amp;nbsp; 이 패턴(Interface + Abstract)의 장점 요약&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: none; padding-left: 5px; line-height: 2.0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;- &lt;b&gt;설계의 표준화 (Interface):&lt;/b&gt; &quot;모든 캐릭터는 반드시 공격해야 한다&quot;는 규칙을 강제하여, 개발자가 실수로 기능을 누락하는 것을 방지합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt; &lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 코드 중복 제거 (Abstract Class):&lt;/b&gt; 체력(HP), 레벨(Level) 처럼 모든 캐릭터가 갖는 공통 코드를 부모 클래스 한곳에서만 관리하면 되므로 유지보수가 매우 쉬워집니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt; &lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 확장성 (Polymorphism):&lt;/b&gt; 나중에 &lt;code&gt;Archer(궁수)&lt;/code&gt; 클래스가 추가되어도, 기존의 &lt;code&gt;GameMain&lt;/code&gt; 코드는 한 줄도 수정할 필요가 없습니다. 그냥 리스트에 추가만 하면 됩니다. (OCP 원칙 준수)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;자바의 꽃은 객체지향이고, 객체지향의 완성은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;다형성&lt;/b&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;입니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;인터페이스로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&quot;큰 그림(설계)&quot;&lt;/b&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;을 그리고, 추상 클래스로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&quot;공통 분모(구현)&quot;&lt;/b&gt;&lt;span style=&quot;background-color: #f9f9f9; color: #333333; text-align: start;&quot;&gt;를 묶어주는 이 패턴을 익혀두면, 좋을 것 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;div style=&quot;background-color: #f6f8fa; padding: 20px; border-radius: 8px; border: 1px solid #d0d7de; margin-top: 30px;&quot;&gt;
&lt;p style=&quot;margin: 0; font-weight: bold; color: #555; margin-bottom: 8px;&quot; data-ke-size=&quot;size16&quot;&gt;  Reference &amp;amp; Source&lt;/p&gt;
&lt;p style=&quot;margin: 0; font-size: 0.95em; line-height: 1.6; color: #333;&quot; data-ke-size=&quot;size16&quot;&gt;이 포스팅은 &lt;b&gt;&quot;요즘 공부 도와주는 갓 인파&quot;&lt;/b&gt;님의 블로그 내용을 바탕으로 정리했습니다.&lt;br /&gt;더 깊이 있는 내용과 예제는 아래 원문에서 확인하실 수 있습니다.&lt;/p&gt;
&lt;div style=&quot;margin-top: 15px; padding: 12px; background-color: #ffffff; border-radius: 6px; border: 1px solid #e1e4e8;&quot;&gt;  &lt;a style=&quot;text-decoration: none; color: #0969da; font-weight: bold; font-size: 0.95em;&quot; href=&quot;https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-vs-%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; [Inpa Dev  &amp;zwj; ] 자바 인터페이스 vs 추상클래스 차이점 완벽 이해하기 &lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Language/Java</category>
      <category>Abstract</category>
      <category>Interface</category>
      <category>인터페이스 vs 추상클래스</category>
      <author>hlxecz</author>
      <guid isPermaLink="true">https://hlxecz.tistory.com/15</guid>
      <comments>https://hlxecz.tistory.com/15#entry15comment</comments>
      <pubDate>Wed, 7 Jan 2026 15:10:26 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] Stack 구현 &amp;amp; Stack Class의 문제점 (feat. Deque)</title>
      <link>https://hlxecz.tistory.com/13</link>
      <description>&lt;div style=&quot;background-color: #f6f8fa; border: 1px solid #d0d7de; border-radius: 6px; padding: 12px 15px; margin-bottom: 20px; font-size: 0.9em; display: flex; align-items: center; font-family: 'Apple SD Gothic Neo', sans-serif;&quot;&gt;&lt;span style=&quot;margin-right: 10px; font-size: 1.2em;&quot;&gt; &lt;/span&gt;
&lt;div&gt;&lt;span style=&quot;color: #57606a; font-weight: bold;&quot;&gt;Java Collection:&lt;/span&gt; &lt;span style=&quot;color: #0969da; font-weight: bold; margin-left: 5px;&quot;&gt;Stack &amp;amp; Deque&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #57606a; font-weight: bold;&quot;&gt;Problem Source:&lt;/span&gt; &lt;a style=&quot;color: #0969da; text-decoration: none; font-weight: bold; margin-left: 5px;&quot; href=&quot;https://github.com/Hlxecz/Sw_Pilot_Java/tree/main/Chapter_2/Step2/src&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; GitHub - Sw_Pilot_Java (Chapter 2 / Step 2 - 3) &lt;/a&gt;
&lt;div style=&quot;color: #57606a; font-size: 0.85em; margin-top: 2px;&quot;&gt;LIFO 구조인 스택의 개념과 사용법, 그리고 현대적인 대체제인 Deque를 알아봅니다.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;contents_style&quot; style=&quot;font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; line-height: 1.7; color: #333;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택(Stack)은 '쌓다', '더미'라는 뜻을 가지고 있습니다. 식당에 쌓여 있는 접시 더미나, 총기의 탄창을 떠올리면 이해하기 쉽습니다.&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;LIFO(Last In First Out, 후입선출)&lt;/b&gt; 구조를 가지고 있으며, 이는 먼저 들어간 데이터가 먼저 나오는 Queue(FIFO)와 정반대되는 개념입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;329&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dB01hO/dJMcabCLPwU/7uKBtrmtlL65NOoRGDLUCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dB01hO/dJMcabCLPwU/7uKBtrmtlL65NOoRGDLUCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dB01hO/dJMcabCLPwU/7uKBtrmtlL65NOoRGDLUCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdB01hO%2FdJMcabCLPwU%2F7uKBtrmtlL65NOoRGDLUCk%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;618&quot; height=&quot;329&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;329&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;section1&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 스택(Stack)의 구조와 특징&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;LIFO 구조:&lt;/b&gt; 나중에 넣은(Push) 데이터가 먼저 나옵니다(Pop).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;활용 예시:&lt;/b&gt; 웹 브라우저 뒤로 가기, 편집기 실행 취소(Undo/Redo), 수식의 괄호 검사, JVM의 Stack 메모리 영역 등.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Java 특징:&lt;/b&gt; &lt;code&gt;java.util.Stack&lt;/code&gt; 클래스는 &lt;code&gt;Vector&lt;/code&gt; 클래스를 상속받아 구현되었으므로 &lt;b&gt;Thread-Safe&lt;/b&gt;하다는 특징이 있습니다.&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;215&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beQLXv/dJMcagRB2GK/kGUQXUWul7TC9tecPAkiSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beQLXv/dJMcagRB2GK/kGUQXUWul7TC9tecPAkiSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beQLXv/dJMcagRB2GK/kGUQXUWul7TC9tecPAkiSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeQLXv%2FdJMcagRB2GK%2FkGUQXUWul7TC9tecPAkiSk%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;462&quot; height=&quot;215&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;215&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section2&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Stack 클래스 주요 메서드&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서 스택을 다룰 때 주로 사용하는 메서드들입니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;메서드&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;설명&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;반환값&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center; color: #2196f3;&quot;&gt;push(item)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;스택의 맨 위에 객체를 저장합니다.&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;저장된 객체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center; color: #ff9800;&quot;&gt;pop()&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;맨 위의 객체를 &lt;b&gt;꺼내서 반환&lt;/b&gt;합니다. (제거됨)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;꺼낸 객체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;peek()&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;맨 위의 객체를 &lt;b&gt;확인만&lt;/b&gt; 합니다. (제거 안 됨)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;맨 위 객체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;empty()&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;스택이 비어있는지 확인합니다.&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;boolean&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;search(o)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;객체의 위치를 반환합니다. (1부터 시작)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;인덱스 (없으면 -1)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 실전 사용 예제&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;기본적인 Push와 Pop&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 넣고(push) 꺼내는(pop) 가장 기초적인 동작입니다. 꺼내면 데이터는 스택에서 사라집니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;Stack&amp;lt;Integer&amp;gt; stack = new Stack&amp;lt;&amp;gt;();

// 1. 요소 추가 (Push)
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println(stack); // [1, 2, 3]

// 2. 요소 꺼내기 (Pop - LIFO)
System.out.println(stack.pop()); // 3 (가장 마지막에 넣은 것)
System.out.println(stack.pop()); // 2
System.out.println(stack); // [1] (꺼낸 값은 사라짐)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;최상단 값 확인하기 (Peek)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;peek()&lt;/code&gt;은 데이터를 꺼내지 않고 &lt;b&gt;&quot;다음에 나올 값이 뭔지 확인만&quot;&lt;/b&gt; 하고 싶을 때 사용합니다. 데이터가 제거되지 않습니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;Stack&amp;lt;String&amp;gt; stack = new Stack&amp;lt;&amp;gt;();
stack.push(&quot;Apple&quot;);
stack.push(&quot;Banana&quot;);
stack.push(&quot;Cherry&quot;);

// 맨 위 값 확인 (제거 X)
System.out.println(&quot;Top Element: &quot; + stack.peek()); // Cherry
System.out.println(&quot;Stack Size: &quot; + stack.size());  // 3 (사이즈 유지됨)

// 값을 꺼냄 (제거 O)
System.out.println(&quot;Pop Element: &quot; + stack.pop());  // Cherry
System.out.println(&quot;Stack Size: &quot; + stack.size());  // 2&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;위치 검색 (search) 주의사항&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;search()&lt;/code&gt; 메서드는 배열의 인덱스(0부터 시작)와 다르게, &lt;b&gt;맨 위에서부터 몇 번째에 있는지(1부터 시작)&lt;/b&gt;를 반환합니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;Stack&amp;lt;String&amp;gt; stack = new Stack&amp;lt;&amp;gt;();
stack.push(&quot;HI&quot;);
stack.push(&quot;HELLO&quot;);
stack.push(&quot;EARTH&quot;);

// &quot;EARTH&quot;는 맨 위에 있으므로 1 반환
System.out.println(stack.search(&quot;EARTH&quot;)); // 1 

// &quot;HI&quot;는 세 번째로 꺼내지므로 3 반환
System.out.println(stack.search(&quot;HI&quot;));    // 3&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section4&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. Stack 클래스는 Deprecated 되었습니다!&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론부터 말하자면, 실무에서 &lt;code&gt;java.util.Stack&lt;/code&gt; 클래스는 &lt;b&gt;사용을 지양&lt;/b&gt;해야 합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djZusV/dJMcafLWjRV/FoMuWlkSAsvaZyJCXIySck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djZusV/dJMcafLWjRV/FoMuWlkSAsvaZyJCXIySck/img.png&quot; data-alt=&quot;Stack 클래스는 Vector 클래스를 상속하도록 설계 되어 있음&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djZusV/dJMcafLWjRV/FoMuWlkSAsvaZyJCXIySck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjZusV%2FdJMcafLWjRV%2FFoMuWlkSAsvaZyJCXIySck%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;353&quot; height=&quot;362&quot; data-origin-width=&quot;282&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Stack 클래스는 Vector 클래스를 상속하도록 설계 되어 있음&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;div style=&quot;background-color: #ffebee; padding: 15px; border-left: 5px solid #f44336; margin: 15px 0; border-radius: 0 5px 5px 0;&quot;&gt;&lt;b&gt;⚠️ 이유 1: Vector 상속의 문제점&lt;/b&gt;&lt;br /&gt;Stack은 &lt;code&gt;Vector&lt;/code&gt;를 상속받았습니다. Vector는 중간에 데이터를 삽입할 수 있는 &lt;code&gt;add(index, val)&lt;/code&gt; 메서드를 가지고 있는데, 이를 Stack도 그대로 물려받았습니다.&lt;br /&gt;&lt;b&gt;&quot;맨 위에서만 넣고 빼야 한다&quot;&lt;/b&gt;는 스택의 원칙이 깨질 위험이 있습니다.&lt;/div&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;Stack&amp;lt;String&amp;gt; stack = new Stack&amp;lt;&amp;gt;();
stack.push(&quot;One&quot;);
stack.push(&quot;Two&quot;);

// 스택의 원칙 위배! (중간에 강제 삽입 가능)
stack.add(0, &quot;Bug&quot;); 

// pop() 결과가 예상과 달라질 수 있음
System.out.println(stack.pop()); // &quot;Two&quot; (Bug가 아님)&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;code&gt;Vector&lt;/code&gt;의 모든 메서드가 &lt;code&gt;synchronized&lt;/code&gt; 처리되어 있어, 싱글 스레드 환경에서도 불필요한 성능 저하가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section5&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 권장되는 해결책: Deque (ArrayDeque)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 공식 문서에서도 Stack 대신 &lt;b&gt;Deque(덱)&lt;/b&gt; 인터페이스의 구현체인 &lt;code&gt;ArrayDeque&lt;/code&gt;를 사용할 것을 권장합니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;279&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Iruiy/dJMcagxi9XA/f2Y6qTU9j4H5MkKveT3Wt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Iruiy/dJMcagxi9XA/f2Y6qTU9j4H5MkKveT3Wt0/img.png&quot; data-alt=&quot;JAVA 공식 문서&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Iruiy/dJMcagxi9XA/f2Y6qTU9j4H5MkKveT3Wt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIruiy%2FdJMcagxi9XA%2Ff2Y6qTU9j4H5MkKveT3Wt0%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;713&quot; height=&quot;279&quot; data-origin-width=&quot;713&quot; data-origin-height=&quot;279&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;JAVA 공식 문서&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Deque는 양쪽 끝에서 데이터를 넣고 뺄 수 있어, &lt;b&gt;스택(LIFO)&lt;/b&gt;과 &lt;b&gt;큐(FIFO)&lt;/b&gt;의 기능을 모두 완벽하게 수행할 수 있습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;193&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpqFGG/dJMcadgeL2c/FmKJeFgeQWJs3cu8zdcSs0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpqFGG/dJMcadgeL2c/FmKJeFgeQWJs3cu8zdcSs0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpqFGG/dJMcadgeL2c/FmKJeFgeQWJs3cu8zdcSs0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpqFGG%2FdJMcadgeL2c%2FFmKJeFgeQWJs3cu8zdcSs0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;193&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;193&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Stack 처럼 사용하기 (LIFO)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;push()&lt;/code&gt;와 &lt;code&gt;pop()&lt;/code&gt; 메서드를 사용하면 스택과 동일하게 동작합니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;/* Stack 처럼 사용하기 */
Deque&amp;lt;String&amp;gt; stack = new ArrayDeque&amp;lt;&amp;gt;();

// 담기 (Push)
stack.push(&quot;a&quot;);
stack.push(&quot;b&quot;);
stack.push(&quot;c&quot;);
stack.push(&quot;d&quot;);
stack.push(&quot;e&quot;);

System.out.println(stack); // [e, d, c, b, a] (Last In First Out)

// 꺼내기 (Pop)
System.out.println(stack.pop()); // e
System.out.println(stack.pop()); // d
System.out.println(stack); // [c, b, a]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Queue 처럼 사용하기 (FIFO)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;offer()&lt;/code&gt;와 &lt;code&gt;poll()&lt;/code&gt; 메서드를 사용하면 큐와 동일하게 동작합니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; style=&quot;background: #282c34; color: #abb2bf; padding: 20px; border-radius: 8px;&quot;&gt;&lt;code&gt;/* Queue 처럼 사용하기 */
Deque&amp;lt;String&amp;gt; queue = new ArrayDeque&amp;lt;&amp;gt;();

// 담기 (Offer)
queue.offer(&quot;a&quot;);
queue.offer(&quot;b&quot;);
queue.offer(&quot;c&quot;);
queue.offer(&quot;d&quot;);
queue.offer(&quot;e&quot;);

System.out.println(queue); // [a, b, c, d, e] (First In First Out)

// 꺼내기 (Poll)
System.out.println(queue.poll()); // a
System.out.println(queue.poll()); // b
System.out.println(queue); // [c, d, e]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #e8f5e9; padding: 20px; border-radius: 10px; border: 1px solid #c8e6c9; margin: 20px 0;&quot;&gt;1. &lt;b&gt;Stack&lt;/b&gt;은 LIFO(후입선출) 구조이다.&lt;br /&gt;2. 기존 &lt;code&gt;java.util.Stack&lt;/code&gt;은 낡은 &lt;code&gt;Vector&lt;/code&gt;를 상속받아 설계 결함이 있다.&lt;br /&gt;3. 따라서 스택이 필요할 때는 &lt;b&gt;&lt;code&gt;Deque&amp;lt;T&amp;gt; stack = new ArrayDeque&amp;lt;&amp;gt;();&lt;/code&gt;&lt;/b&gt;를 쓰자!&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;div style=&quot;background-color: #f5f5f5; padding: 15px; border-radius: 5px; color: #666; font-size: 0.85em; margin-top: 30px;&quot;&gt;
&lt;p style=&quot;margin: 0; font-weight: bold;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;References &amp;amp; Sources&lt;/p&gt;
&lt;ul style=&quot;padding-left: 20px; margin-top: 5px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #666; text-decoration: none;&quot; href=&quot;https://inpa.tistory.com/entry/JCF-%F0%9F%A7%B1-Stack-%EA%B5%AC%EC%A1%B0-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%A0%95%EB%A6%AC#thankYou&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Inpa Dev  &amp;zwj; :티스토리 - 자바 Stack 구조 및 사용법 정리&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;color: #666; text-decoration: none;&quot; href=&quot;https://www.programiz.com/dsa/stack&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Programiz - Stack Data Structure&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Language/Java</category>
      <category>Java</category>
      <category>Stack</category>
      <author>hlxecz</author>
      <guid isPermaLink="true">https://hlxecz.tistory.com/13</guid>
      <comments>https://hlxecz.tistory.com/13#entry13comment</comments>
      <pubDate>Fri, 19 Dec 2025 18:33:26 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] Collection Framework &amp;amp; Collections Class _ Part 1</title>
      <link>https://hlxecz.tistory.com/12</link>
      <description>&lt;div style=&quot;background-color: #f6f8fa; border: 1px solid #d0d7de; border-radius: 6px; padding: 12px 15px; margin-bottom: 20px; font-size: 0.9em; display: flex; align-items: center;&quot;&gt;&lt;span style=&quot;margin-right: 10px; font-size: 1.2em;&quot;&gt; ️&lt;/span&gt;
&lt;div&gt;&lt;span style=&quot;color: #57606a; font-weight: bold;&quot;&gt;Java Concept:&lt;/span&gt; &lt;span style=&quot;color: #0969da; font-weight: bold; margin-left: 5px;&quot;&gt;Collection Framework &amp;amp; Collections Class _ Part 1&lt;/span&gt;
&lt;div style=&quot;color: #57606a; font-size: 0.85em; margin-top: 2px;&quot;&gt;자바의 자료구조(Collection) 전체 구조와 인터페이스 종류에 대해 정리해 보겠습니다&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;contents_style&quot; style=&quot;font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; line-height: 1.7; color: #333;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바를 공부하다 보면 &lt;code&gt;Collection&lt;/code&gt;과 &lt;code&gt;Collections&lt;/code&gt;라는 비슷하게 생긴 두 단어를 마주하게 됩니다. 's' 하나 차이인데 역할은 완전히 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #e6f5ff; color: #333333; text-align: start;&quot;&gt;Collection&lt;/span&gt; 는 데이터를 담는 &lt;b&gt;그릇(Framework)&lt;/b&gt;이고, &lt;span style=&quot;background-color: #e6f5ff; color: #333333; text-align: start;&quot;&gt;Collections&lt;/span&gt; 는 그 그릇을 요리하는 &lt;b&gt;도구(Utility)&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 자바의 자료구조 전체 지도인 &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;컬렉션 프레임워크&lt;/span&gt;를 먼저 훑어보고, 다음 장에 이를 효율적으로 다루기 위한 &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;Collections 클래스의 기능&lt;/span&gt;들을 정리해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;section1&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 자바 컬렉션 프레임워크 (Collection Framework)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컬렉션 프레임워크란 &lt;b&gt;&quot;다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 클래스의 집합&quot;&lt;/b&gt;을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 자료구조(Data Structure)와 알고리즘을 자바 클래스로 구현해 놓은 것입니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;collections_1.png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1463&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpKrHM/dJMcagKPqYT/EwEfVbM0nMhLgCqrlj3joK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpKrHM/dJMcagKPqYT/EwEfVbM0nMhLgCqrlj3joK/img.png&quot; data-alt=&quot;https://commons.wikimedia.org&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpKrHM/dJMcagKPqYT/EwEfVbM0nMhLgCqrlj3joK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdpKrHM%2FdJMcagKPqYT%2FEwEfVbM0nMhLgCqrlj3joK%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;2560&quot; height=&quot;1463&quot; data-filename=&quot;collections_1.png&quot; data-origin-width=&quot;2560&quot; data-origin-height=&quot;1463&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://commons.wikimedia.org&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;figure style=&quot;text-align: center; margin: 30px 0;&quot;&gt;
&lt;figcaption style=&quot;color: #888; font-size: 0.9em;&quot;&gt;▲ Java Collections Framework 계층 구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Collection Framework &lt;/b&gt;주요 인터페이스 특징&lt;/h2&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center; width: 20%;&quot;&gt;인터페이스&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;특징&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;구현 클래스&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;List&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;순서가 &lt;b&gt;있음&lt;/b&gt;, 중복 &lt;b&gt;허용&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;ArrayList, LinkedList, Stack, Vector&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;Set&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;순서가 &lt;b&gt;없음&lt;/b&gt;, 중복 &lt;b&gt;불가&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;HashSet, TreeSet, LinkedHashSet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;Map&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;Key-Value 쌍, Key 중복 불가, 순서 없음&lt;br /&gt;&lt;span style=&quot;font-size: 0.9em; color: #888;&quot;&gt;(Collection 인터페이스 상속 아님)&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;HashMap, TreeMap, LinkedHashMap, Properties&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;Queue&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;선입선출(FIFO) 구조&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;LinkedList, PriorityQueue&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section2&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. List 인터페이스 (순서 O, 중복 O)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;줄 서기&quot;&lt;/b&gt;와 같습니다. 데이터가 들어온 순서대로 저장되며, 똑같은 데이터가 또 들어와도 상관없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스(방 번호)를 이용해 데이터를 관리합니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;클래스&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;내부 구조&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;장점 (속도)&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;단점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;ArrayList&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;동적 배열 (Object[])&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #2e7d32;&quot;&gt;조회(Get) 빠름&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #c62828;&quot;&gt;중간 삽입/삭제 느림&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;LinkedList&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;노드 연결 (Node&amp;lt;E&amp;gt;)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #2e7d32;&quot;&gt;중간 삽입/삭제 빠름&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #c62828;&quot;&gt;조회(Get) 느림&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;Vector&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;동적 배열 + 동기화&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;멀티스레드 안전(Safe)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #c62828;&quot;&gt;무겁고 느림 (Legacy)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;- 상세 설명&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ArrayList:&lt;/b&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;데이터를 순차적으로 추가/조회&lt;/span&gt;할 때 성능이 가장 좋습니다. 하지만 중간에 요소를 끼워 넣으려면 뒤에 있는 데이터들을 전부 한 칸씩 밀어야 해서 느립니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LinkedList:&lt;/b&gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;앞뒤 요소의 주소&lt;/span&gt;만 알고 연결된 구조입니다. 중간에 데이터를 넣을 때 주소만 바꿔주면 되므로 빠릅니다. 하지만 5번째 데이터를 찾으려면 처음부터 하나씩 건너가야 해서 조회는 느립니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Vector:&lt;/b&gt; ArrayList의 옛날 버전입니다. &lt;b&gt;&lt;code&gt;synchronized&lt;/code&gt;&lt;/b&gt;가 걸려있어 성능이 떨어지므로, 동기화가 필요하면 &lt;code&gt;Collections.synchronizedList()&lt;/code&gt;를 쓰는 게 낫습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; style=&quot;background: #282c34; color: #abb2bf; padding: 20px; border-radius: 8px;&quot;&gt;&lt;code&gt;List&amp;lt;String&amp;gt; list = new ArrayList&amp;lt;&amp;gt;();
list.add(&quot;Java&quot;);
list.add(&quot;Java&quot;); // 중복 가능
list.add(1, &quot;Spring&quot;); // 중간 삽입 (이 경우 LinkedList가 더 유리할 수 있음)

System.out.println(list); // [Java, Spring, Java]&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. Set 인터페이스 (순서 X, 중복 X)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;주머니&quot;&lt;/b&gt;와 같습니다. 순서가 뒤죽박죽이며, 똑같은 구슬을 두 개 넣을 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;중복 제거&lt;/b&gt;&lt;/span&gt;가 필요할 때 핵심적으로 사용됩니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;클래스&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;내부 구조&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;정렬/순서&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;특징&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;HashSet&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;Hash Table&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #c62828;&quot;&gt;순서 없음 (Random)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;가장 빠름, 일반적인 Set&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;LinkedHashSet&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;Hash Table + LinkedList&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #2e7d32;&quot;&gt;입력 순서 보장&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;순서가 중요한 경우 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;TreeSet&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;Red-Black Tree&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #2196f3;&quot;&gt;오름차순 정렬&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;범위 검색, 정렬된 데이터 필요 시&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;- 상세 설명&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HashSet:&lt;/b&gt; &lt;code&gt;hashCode()&lt;/code&gt;와 &lt;code&gt;equals()&lt;/code&gt;를 이용해 &lt;span style=&quot;color: #ee2323;&quot;&gt;중복을 걸러&lt;/span&gt;냅니다. 순서를 보장하지 않으므로, &quot;데이터가 들어있는지 확인(contains)&quot;하는 용도로 가장 빠르고 좋습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LinkedHashSet:&lt;/b&gt; HashSet에 순서 기억 기능을 추가한 것입니다. 데이터가 들어온 순서대로 출력하고 싶을 때 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TreeSet:&lt;/b&gt; 이진 탐색 트리 구조로 데이터를 저장하면서 &lt;b&gt;자동으로 정렬(Sorting)&lt;/b&gt;합니다. HashSet보다는 느리지만, &quot;가나다순 출력&quot;이나 &quot;특정 범위 검색&quot;에 유리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; style=&quot;background: #282c34; color: #abb2bf; padding: 20px; border-radius: 8px;&quot;&gt;&lt;code&gt;Set&amp;lt;String&amp;gt; set = new HashSet&amp;lt;&amp;gt;();
set.add(&quot;Java&quot;);
set.add(&quot;Java&quot;); // 중복 발생 -&amp;gt; 저장 안 됨 (false 반환)
set.add(&quot;Android&quot;);
set.add(&quot;Spring&quot;);

System.out.println(set); 
// 출력 결과 예시: [Spring, Java, Android] (순서 보장 안 됨)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section4&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. Queue 인터페이스 (선입선출 대기열)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;놀이공원 줄 서기&quot;&lt;/b&gt;와 같습니다. 먼저 들어온 데이터가 먼저 나가는 &lt;b&gt;FIFO(First In First Out)&lt;/b&gt; 구조입니다. 순서가 있지만, 중간에 새치기(삽입)는 불가능합니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;클래스&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;내부 구조&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;특징&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;활용&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;LinkedList&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;Node 연결&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #2e7d32;&quot;&gt;큐의 표준 구현체&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;일반적인 큐 작업&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;PriorityQueue&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;Heap (이진 트리)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #2196f3;&quot;&gt;우선순위 정렬&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;작업 스케줄링 (중요도 순)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;ArrayDeque&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;가변 배열 (Circular)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;양쪽 끝 접근 가능&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;스택/큐 대용 (성능 우수)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;- 상세 설명&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;LinkedList:&lt;/b&gt; List 인터페이스도 구현하고 Queue 인터페이스도 구현했습니다. 큐로 사용할 때는 &lt;code&gt;offer(넣기)&lt;/code&gt;, &lt;code&gt;poll(꺼내기)&lt;/code&gt; 메서드를 주로 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PriorityQueue:&lt;/b&gt; 들어온 순서와 상관없이 &lt;b&gt;&quot;우선순위가 높은 데이터&quot;&lt;/b&gt;가 먼저 나갑니다. 기본적으로는 숫자가 낮은 것이 우선이며, 생성자에 기준을 설정할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ArrayDeque:&lt;/b&gt; 큐(Queue)와 스택(Stack)의 기능을 모두 합친 덱(Deque)의 구현체입니다. 성능이 매우 좋아 실무에서 Stack 대신 많이 쓰입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; style=&quot;background: #282c34; color: #abb2bf; padding: 20px; border-radius: 8px;&quot;&gt;&lt;code&gt;Queue&amp;lt;String&amp;gt; queue = new LinkedList&amp;lt;&amp;gt;();
queue.offer(&quot;첫번째&quot;);
queue.offer(&quot;두번째&quot;);
queue.offer(&quot;세번째&quot;);

System.out.println(queue.poll()); // &quot;첫번째&quot; (가장 먼저 들어간 것)
System.out.println(queue); // [&quot;두번째&quot;, &quot;세번째&quot;]&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section5&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. Map 인터페이스 (키와 값의 쌍)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Map&lt;/code&gt;은 엄밀히 말해 &lt;code&gt;Collection&lt;/code&gt; 인터페이스의 자식은 아닙니다. 하지만 프레임워크의 중요한 한 축입니다. &lt;b&gt;Key(키)&lt;/b&gt;와 &lt;b&gt;Value(값)&lt;/b&gt;의 쌍으로 데이터를 관리합니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;구현 클래스&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;Key 특징&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;정렬&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;Null 허용&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;HashMap&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;중복 불가&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;순서 없음&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #2e7d32;&quot;&gt;Key 1개, Value 다수 허용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;LinkedHashMap&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;중복 불가&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;입력 순서 보장&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;허용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;TreeMap&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;중복 불가&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;Key 기준 오름차순&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #c62828;&quot;&gt;Key Null 불가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; text-align: center;&quot;&gt;Hashtable&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;중복 불가&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;순서 없음&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #c62828;&quot;&gt;Key/Value 둘 다 Null 불가&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;- 상세 설명&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HashMap:&lt;/b&gt; 가장 널리 쓰입니다. Key의 중복은 허용하지 않고, Value의 중복은 허용합니다. 순서를 보장하지 않지만 검색 속도가 매우 빠릅니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TreeMap:&lt;/b&gt; Key를 기준으로 자동 정렬됩니다. 정렬된 순서대로 조회하거나 범위 검색이 필요할 때 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hashtable:&lt;/b&gt; HashMap의 구버전(Legacy)입니다. 동기화(Synchronized)가 되어 있어 멀티스레드 환경에서 안전하지만 느립니다. 최근에는 &lt;code&gt;ConcurrentHashMap&lt;/code&gt;을 더 권장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; style=&quot;background: #282c34; color: #abb2bf; padding: 20px; border-radius: 8px;&quot;&gt;&lt;code&gt;Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
map.put(&quot;사과&quot;, 1000);
map.put(&quot;바나나&quot;, 2000);
map.put(&quot;사과&quot;, 1500); // Key 중복! -&amp;gt; 기존 값(1000)이 덮어씌워짐

System.out.println(map.get(&quot;사과&quot;)); // 1500&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section6&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. &lt;span style=&quot;background-color: #f6f8fa; color: #0969da; text-align: start;&quot;&gt;Collection Framework&amp;nbsp; &lt;/span&gt;핵심 요약&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background-color: #e8f5e9; padding: 20px; border-radius: 10px; border: 1px solid #c8e6c9; margin: 20px 0;&quot;&gt;
&lt;ul style=&quot;list-style-type: none; padding-left: 5px; line-height: 2.0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;순서&lt;/b&gt;가 중요하고 &lt;b&gt;중복&lt;/b&gt; 데이터도 저장해야 한다면? &lt;br /&gt;  &lt;span style=&quot;background-color: #fff; padding: 2px 6px; border-radius: 4px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;List (ArrayList)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;중복을 제거&lt;/b&gt;해야 하고, 존재 여부(Contains) 확인이 중요하다면? &lt;br /&gt;  &lt;span style=&quot;background-color: #fff; padding: 2px 6px; border-radius: 4px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;Set (HashSet)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터를 순서대로(선입선출)&lt;/b&gt; 처리해야 한다면? &lt;br /&gt;  &lt;span style=&quot;background-color: #fff; padding: 2px 6px; border-radius: 4px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;Queue (LinkedList)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ID, 사번&lt;/b&gt;처럼 고유한 키(Key)로 데이터를 빠르게 찾아야 한다면? &lt;br /&gt;  &lt;span style=&quot;background-color: #fff; padding: 2px 6px; border-radius: 4px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;Map (HashMap)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Tip _ 인터페이스 기반 코딩&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수를 선언할 때는 구체적인 클래스(ArrayList)보다는 &lt;b&gt;인터페이스(List)&lt;/b&gt;를 사용하는 습관을 들이는 것이 좋습니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #f1f8e9; padding: 15px; border-left: 5px solid #8bc34a; margin: 10px 0; border-radius: 0 5px 5px 0;&quot;&gt;
&lt;p style=&quot;margin: 0;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #d9534f;&quot;&gt;❌ Bad:&lt;/span&gt; &lt;code&gt;ArrayList&amp;lt;String&amp;gt; list = new ArrayList&amp;lt;&amp;gt;();&lt;/code&gt;&lt;br /&gt;&lt;span style=&quot;color: #2e7d32;&quot;&gt;&lt;b&gt;⭕ Good:&lt;/b&gt;&lt;/span&gt; &lt;code&gt;List&amp;lt;String&amp;gt; list = new ArrayList&amp;lt;&amp;gt;();&lt;/code&gt;&lt;/p&gt;
&lt;p style=&quot;margin-top: 10px; font-size: 0.9em; color: #666;&quot; data-ke-size=&quot;size16&quot;&gt;  이렇게 해야 나중에 &lt;code&gt;new LinkedList&amp;lt;&amp;gt;()&lt;/code&gt;로 구현체를 바꿔도 나머지 코드를 수정할 필요가 없어집니다. (유연성 증가)&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;Collection Framework 에 대해 정리를 해보았고 !!&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;다음으로는&amp;nbsp; &lt;span style=&quot;background-color: #fff5b1; color: #333333; text-align: start;&quot;&gt;Collections 클래스&lt;/span&gt; 에 대해 어떤 메서드들과 기능들이 있는지 정리해 보겠습니다 ~!&lt;/p&gt;</description>
      <category>Language/Java</category>
      <category>Collection</category>
      <category>collections</category>
      <category>인터페이스</category>
      <author>hlxecz</author>
      <guid isPermaLink="true">https://hlxecz.tistory.com/12</guid>
      <comments>https://hlxecz.tistory.com/12#entry12comment</comments>
      <pubDate>Tue, 16 Dec 2025 14:23:27 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] Getter/Setter 이중성 &amp;amp; 문제점 Refactoring</title>
      <link>https://hlxecz.tistory.com/8</link>
      <description>&lt;div style=&quot;background-color: #f6f8fa; border: 1px solid #d0d7de; border-radius: 6px; padding: 12px 15px; margin-bottom: 20px; font-size: 0.9em; display: flex; align-items: center; font-family: 'Apple SD Gothic Neo', sans-serif;&quot;&gt;&lt;span style=&quot;margin-right: 10px; font-size: 1.2em;&quot;&gt;☕&lt;/span&gt;
&lt;div&gt;&lt;span style=&quot;color: #57606a; font-weight: bold;&quot;&gt;Java Study:&lt;/span&gt; &lt;span style=&quot;color: #0969da; font-weight: bold; margin-left: 5px;&quot;&gt;Refactoring Getter/Setter&lt;/span&gt;
&lt;div style=&quot;color: #57606a; font-size: 0.85em; margin-top: 2px;&quot;&gt;이 포스팅은 Getter/Setter의 남용을 막고, 객체지향적인 설계를 하는 방법을 정리한 글입니다.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;contents_style&quot; style=&quot;font-family: 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif; line-height: 1.7; color: #333;&quot;&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;Getter&lt;/b&gt;와 &lt;b&gt;Setter&lt;/b&gt;를 생성하곤 합니다. IDE가 단축키 한 번이면 만들어주니 너무나 자연스럽죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;b&gt;&quot;이게 정말 객체지향적인가?&quot;&lt;/b&gt;라는 의문을 가져본 적 있으신가요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 값을 넣고 빼기만 한다면 그건 객체가 아니라 데이터 주머니에 불과할지도 모릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 무분별한 Getter/Setter 사용이 왜 문제인지, 그리고 이를 해결하기 위한 &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;진짜 객체지향 설계 방법(Rich Domain Model, VO 등)&lt;/span&gt;에 대해 정리해보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;section1&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Getter/Setter의 이중성과 문제점&lt;/b&gt;&lt;/h2&gt;
&lt;h3 style=&quot;color: #d9534f;&quot; data-ke-size=&quot;size23&quot;&gt;빈약한 도메인 모델 (Anemic Domain Model)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 '정보 은닉'을 위해 필드를 &lt;code&gt;private&lt;/code&gt;으로 막습니다. 그런데 바로 &lt;code&gt;public&lt;/code&gt; Getter/Setter를 열어버린다면? 사실상 정보 은닉은 깨진 것과 다름없습니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// ❌ 상태와 행위가 분리된 절차지향적 코드
public class Order {
    private int totalAmount;
    // 단순히 값만 꺼내주고 넣어주는 역할
    public int getTotalAmount() { return totalAmount; }
    public void setTotalAmount(int amount) { this.totalAmount = amount; }
}

// 서비스 로직 (객체의 데이터를 꺼내서 외부에서 처리함)
public void discount(Order order) {
    int amount = order.getTotalAmount();
    if (amount &amp;gt; 10000) {
        order.setTotalAmount(amount - 1000);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 되면 객체는 자신의 데이터에 대한 통제권을 잃고, 단순히 &lt;b&gt;데이터 보관소(주머니)&lt;/b&gt; 역할만 하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것을 &lt;b&gt;빈약한 도메인 모델&lt;/b&gt;이라고 합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section2&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 해결책 - 묻지 말고 시켜라 (Tell, Don't Ask)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체지향의 핵심은 &lt;b&gt;데이터와 그 데이터를 조작하는 행위(로직)를 한곳에 묶는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 달라고(Ask) 하지 말고, 원하는 작업을 하라고 시켜야(Tell) 합니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #009688;&quot; data-ke-size=&quot;size23&quot;&gt;풍부한 도메인 모델 (Rich Domain Model)&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// ✅ 스스로의 상태를 관리하는 객체
public class Order {
    private int totalAmount;

    // 객체가 스스로 판단하고 상태를 변경함
    public void applyDiscount() {
        if (this.totalAmount &amp;gt; 10000) {
            this.totalAmount -= 1000;
        }
    }
}

// 서비스 로직
public void process(Order order) {
    order.applyDiscount(); // &quot;할인해!&quot; 라고 명령만 하면 됨
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 외부에서는 &lt;code&gt;Order&lt;/code&gt;의 내부 구현을 몰라도 됩니다. 변경 사항이 생겨도 &lt;code&gt;Order&lt;/code&gt; 객체 내부만 수정하면 되므로 유지보수성이 대폭 향상됩니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 더 나은 설계 1: Value Object (VO)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;int&lt;/code&gt;, &lt;code&gt;long&lt;/code&gt; 같은 원시 타입은 값이 무엇을 의미하는지, 유효한 값인지 스스로 증명하지 못합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 &lt;b&gt;값을 감싸는 객체(VO)&lt;/b&gt;를 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #e8f5e9; padding: 15px; border-radius: 8px; margin-bottom: 15px;&quot;&gt;
&lt;p style=&quot;margin: 0; color: #2e7d32; font-weight: bold;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;Value Object의 특징&lt;/p&gt;
&lt;ul style=&quot;padding-left: 20px; margin-bottom: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;불변성 (Immutable):&lt;/b&gt; 생성 후 값이 변하지 않음 (Setter 없음).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유효성 검증:&lt;/b&gt; 생성자에서 값의 유효성을 체크함 (예: 금액은 음수 불가).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;동등성:&lt;/b&gt; 값이 같으면 같은 객체로 취급 (equals &amp;amp; hashCode 재정의).&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class Money {
    private final int amount; // 불변

    public Money(int amount) {
        if (amount &amp;lt; 0) {
            throw new IllegalArgumentException(&quot;돈은 음수가 될 수 없습니다.&quot;);
        }
        this.amount = amount;
    }

    public Money plus(Money other) {
        return new Money(this.amount + other.amount); // 새로운 객체 반환
    }
}&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;code&gt;int price = -1000;&lt;/code&gt; 같은 끔찍한 실수를 원천 차단할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section4&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 더 나은 설계 2: Aggregate Root와 캡슐화&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체들이 복잡하게 얽혀 있을 때, 외부에서 내부의 작은 객체들을 마음대로 조작하게 두면 안 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Aggregate Root(대표 객체)&lt;/b&gt;를 통해서만 내부에 접근하도록 제약해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;잘못된 설계 vs 올바른 설계&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 10px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;방식&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;문제점/장점&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center; color: #d9534f; font-weight: bold;&quot;&gt;Bad&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;&lt;code&gt;order.getItems().add(item);&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;주문(Order) 몰래 아이템을 추가함. 총액 계산 누락 등 버그 발생 위험.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center; color: #2e7d32; font-weight: bold;&quot;&gt;Good&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;&lt;code&gt;order.addItem(item);&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;주문 객체가 아이템 추가와 동시에 총액 갱신 등 규칙을 수행함.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section5&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 결론: 객체를 객체답게 쓰는 법&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background-color: #f9f9f9; padding: 20px; border-radius: 10px; border: 1px solid #ddd;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc; margin-bottom: 0; line-height: 1.8;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Getter/Setter는 최소한으로:&lt;/b&gt; 무조건 만들지 말고, 꼭 필요한 경우(DTO, 조회용)에만 만들자.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상태 변경은 명확하게:&lt;/b&gt; &lt;code&gt;setStatus(&quot;CANCEL&quot;)&lt;/code&gt; 대신 &lt;code&gt;cancelOrder()&lt;/code&gt; 처럼 의도가 드러나는 메서드를 사용하자.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;검증은 생성 시점에:&lt;/b&gt; 생성자에서 유효성을 검사하여, 태어날 때부터 온전한 객체(VO)만 존재하게 하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #f1f8e9; padding: 15px; border-left: 5px solid #8bc34a; margin: 10px 0; border-radius: 0 5px 5px 0;&quot;&gt;&lt;b&gt;핵심 요약:&lt;/b&gt;&lt;br /&gt;&quot;값을 꺼내서(Get) 내가 계산하고 다시 넣지(Set) 말자.&quot;&lt;br /&gt;&lt;b&gt;&quot;객체에게 계산하라고 시키고(Tell), 결과만 받아오자.&quot;&lt;/b&gt;&lt;br /&gt;이것이 객체지향 프로그래밍의 시작입니다.&lt;/div&gt;
&lt;/div&gt;</description>
      <category>Language/Java</category>
      <category>getter</category>
      <category>Java</category>
      <category>setter</category>
      <category>문제점</category>
      <category>생각정리</category>
      <author>hlxecz</author>
      <guid isPermaLink="true">https://hlxecz.tistory.com/8</guid>
      <comments>https://hlxecz.tistory.com/8#entry8comment</comments>
      <pubDate>Fri, 12 Dec 2025 19:37:43 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] 접근제한자 &amp;amp; 캡슐화</title>
      <link>https://hlxecz.tistory.com/7</link>
      <description>&lt;div style=&quot;background-color: #f6f8fa; border: 1px solid #d0d7de; border-radius: 6px; padding: 12px 15px; margin-bottom: 20px; font-size: 0.9em; display: flex; align-items: center;&quot;&gt;&lt;span style=&quot;margin-right: 10px; font-size: 1.2em;&quot;&gt; &lt;/span&gt;
&lt;div&gt;&lt;span style=&quot;color: #57606a; font-weight: bold;&quot;&gt;Java Concept:&lt;/span&gt; &lt;span style=&quot;color: #0969da; font-weight: bold; margin-left: 5px;&quot;&gt;Access Modifier &amp;amp; Encapsulation&lt;/span&gt;
&lt;div style=&quot;color: #57606a; font-size: 0.85em; margin-top: 2px;&quot;&gt;접근제한자와 캡슐화, 그리고 더 나은 설계를 위한 메서드 활용법을 다룹니다.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 프로그래밍을 하다 보면 &lt;code&gt;public&lt;/code&gt;, &lt;code&gt;private&lt;/code&gt; 같은 단어들을 매일 마주하게 됩니다. 처음에는 &quot;그냥 다 &lt;code&gt;public&lt;/code&gt;으로 하면 편하지 않나?&quot;라고 생각할 수 있습니다.&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;접근제한자(Access Modifier)&lt;/b&gt;야말로 객체 지향의 핵심인 &lt;b&gt;보안과 무결성&lt;/b&gt;을 지키는 문지기 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 접근제한자의 종류와 범위부터, Getter/Setter의 장단점, 그리고 &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;최근 실무에서 Getter/Setter 대신 선호하는 &quot;의미 있는 메서드 설계&quot;&lt;/span&gt;까지 완벽하게 정리해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 접근제한자 완벽 정리 (Scope)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접근 제한자는 &lt;b&gt;&quot;누구까지 들어오게 해줄 것인가?&quot;&lt;/b&gt;를 결정하는 문지기입니다. 자바에는 4가지 등급의 보안 레벨이 있습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: center;&quot;&gt;접근제한자&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: center;&quot;&gt;내 클래스&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: center;&quot;&gt;같은 패키지&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: center;&quot;&gt;상속받은 자식&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: center;&quot;&gt;외부 전체&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #2196f3; text-align: center;&quot;&gt;public&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;⭕&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;⭕&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;⭕&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;⭕&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #ff9800; text-align: center;&quot;&gt;protected&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;⭕&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;⭕&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;⭕&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center; color: #ccc;&quot;&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #9c27b0; text-align: center;&quot;&gt;default (생략)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;⭕&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;⭕&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center; color: #ccc;&quot;&gt;❌&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center; color: #ccc;&quot;&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #f44336; text-align: center;&quot;&gt;private&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center;&quot;&gt;⭕&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center; color: #ccc;&quot;&gt;❌&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center; color: #ccc;&quot;&gt;❌&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; text-align: center; color: #ccc;&quot;&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Tip:&lt;/b&gt; 실무에서는 대부분 &lt;b&gt;private&lt;/b&gt;(변수)과 &lt;b&gt;public&lt;/b&gt;(메서드)을 주로 사용하며, 상속 관계 설계를 위해 &lt;b&gt;protected&lt;/b&gt;를 종종 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 캡슐화와 Getter/Setter의 기본&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;캡슐화(Encapsulation)란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체의 &lt;b&gt;중요한 데이터(필드)&lt;/b&gt;를 외부에서 마음대로 건드리지 못하게 꽁꽁 숨기는(private) 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 안전하게 접근할 수 있는 통로(public 메서드)만 열어둡니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 사용법 (Java Beans 패턴)&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class Organism {
    // 1. 데이터는 private으로 숨김 (정보 은닉)
    private String name;
    private int age;

    // 2. Getter: 읽기 전용 통로
    public String getName() {
        return name;
    }

    // 3. Setter: 쓰기 전용 통로 (검증 로직 포함 가능)
    public void setAge(int age) {
        if (age &amp;lt; 0) {
            System.out.println(&quot;나이는 음수가 될 수 없습니다.&quot;);
            return;
        }
        this.age = age;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. Getter/Setter의 장단점 분석&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;그냥 변수를 public으로 풀면 편한데 왜 귀찮게 Getter/Setter를 쓸까요?&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;display: flex; gap: 20px; margin-bottom: 20px;&quot;&gt;
&lt;div style=&quot;flex: 1; background-color: #e8f5e9; padding: 15px; border-radius: 8px;&quot;&gt;
&lt;p style=&quot;margin: 0 0 10px 0; color: #2e7d32; font-weight: bold;&quot; data-ke-size=&quot;size16&quot;&gt;✅ 장점 (Pros)&lt;/p&gt;
&lt;ul style=&quot;padding-left: 20px; margin-bottom: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;무결성 보장:&lt;/b&gt; &lt;code&gt;setAge(-5)&lt;/code&gt;처럼 말이 안 되는 데이터 입력을 &lt;code&gt;if&lt;/code&gt;문으로 막을 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;접근 제어:&lt;/b&gt; Getter만 만들면 &lt;b&gt;읽기 전용(Read-only)&lt;/b&gt; 필드로 만들 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유지보수:&lt;/b&gt; 내부 변수명이 바뀌어도, 메서드 이름은 그대로 유지하여 외부 코드 수정을 막을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div style=&quot;flex: 1; background-color: #ffebee; padding: 15px; border-radius: 8px;&quot;&gt;
&lt;p style=&quot;margin: 0 0 10px 0; color: #c62828; font-weight: bold;&quot; data-ke-size=&quot;size16&quot;&gt;❌ 단점 (Cons)&lt;/p&gt;
&lt;ul style=&quot;padding-left: 20px; margin-bottom: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;캡슐화 위반 위험:&lt;/b&gt; 무분별한 Setter 남발은 사실상 public 변수와 다를 바 없습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체 수동성:&lt;/b&gt; 객체가 스스로 일을 처리하지 않고, 외부에서 값을 꺼내서(Get) 처리하고 다시 넣는(Set) 절차 지향적인 코드가 되기 쉽습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 실무 트렌드: 의미 있는 메서드 설계&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에는 &lt;b&gt;&quot;단순한 Setter 대신, 행위를 나타내는 메서드를 만들어라&quot;&lt;/b&gt;라는 원칙이 강조되고 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;BAD -&lt;/span&gt;&amp;nbsp;단순 Setter 사용&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;Order order = new Order();
order.setStatus(&quot;SHIPPED&quot;); // &quot;상태를 바꾼다&quot;는 단순한 데이터 변경&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 '왜' 상태가 바뀌는지, 배송이 시작되면 '무엇'을 더 해야 하는지(예: 알림 발송) 알기 어렵습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #009688;&quot;&gt;GOOD - &lt;/span&gt;비즈니스 용어 사용&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class Order {
    private String status;

    // 의미 있는 이름을 가진 메서드 (Setter 대체)
    public void startShipping() {
        if (this.status.equals(&quot;PAYMENT_COMPLETED&quot;)) {
            this.status = &quot;SHIPPED&quot;;
            sendNotification(); // 관련된 로직도 함께 처리 가능!
        }
    }
}

// 사용처
order.startShipping(); // &quot;배송을 시작해라!&quot; (의도가 명확함)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 코드만 읽어도 &lt;b&gt;&quot;아, 지금 배송 처리를 하는구나&quot;&lt;/b&gt;라고 명확하게 의도를 파악할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 요약 및 결론&lt;/b&gt;&lt;/h2&gt;
&lt;div style=&quot;background-color: #f9f9f9; padding: 20px; border-radius: 10px; border: 1px solid #ddd;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc; margin-bottom: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;접근제한자:&lt;/b&gt; &lt;code&gt;private&lt;/code&gt;(나만) &amp;lt; &lt;code&gt;default&lt;/code&gt; &amp;lt; &lt;code&gt;protected&lt;/code&gt; &amp;lt; &lt;code&gt;public&lt;/code&gt;(모두)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캡슐화:&lt;/b&gt; 데이터는 &lt;code&gt;private&lt;/code&gt;으로 숨기고, 필요한 경우에만 메서드로 열어주자.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Getter/Setter:&lt;/b&gt; 데이터 무결성을 위해 필요하지만, 무분별한 사용은 지양하자.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Tip:&lt;/b&gt; 단순히 값을 넣는 &lt;code&gt;setXxx()&lt;/code&gt;보다는 &lt;code&gt;cancelOrder()&lt;/code&gt;, &lt;code&gt;updateUserInfo()&lt;/code&gt; 처럼 &lt;b&gt;의도가 드러나는 이름&lt;/b&gt;을 짓자!&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #f1f8e9; padding: 15px; border-left: 5px solid #8bc34a; margin: 10px 0; border-radius: 0 5px 5px 0;&quot;&gt;&lt;b&gt;  마무리:&lt;/b&gt;&lt;br /&gt;좋은 객체는 자신의 데이터를 남에게 그냥 보여주지 않고(Getter), 외부에서 시키는 대로 그냥 값을 바꾸지 않습니다(Setter).&lt;br /&gt;&lt;b&gt;&quot;스스로 데이터를 관리하고 행동하는 객체&quot;&lt;/b&gt;를 만드는 것이 OOP의 핵심입니다.&lt;/div&gt;</description>
      <category>Language/Java</category>
      <category>Java</category>
      <category>캡슐화</category>
      <author>hlxecz</author>
      <guid isPermaLink="true">https://hlxecz.tistory.com/7</guid>
      <comments>https://hlxecz.tistory.com/7#entry7comment</comments>
      <pubDate>Fri, 12 Dec 2025 18:21:33 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] 객체 지향 프로그래밍 4대 원칙</title>
      <link>https://hlxecz.tistory.com/6</link>
      <description>&lt;div style=&quot;background-color: #f6f8fa; border: 1px solid #d0d7de; border-radius: 6px; padding: 12px 15px; margin-bottom: 20px; font-size: 0.9em; display: flex; align-items: center; font-family: 'Apple SD Gothic Neo', sans-serif;&quot;&gt;&lt;span style=&quot;margin-right: 10px; font-size: 1.2em;&quot;&gt;☕&lt;/span&gt;
&lt;div&gt;&lt;span style=&quot;color: #57606a; font-weight: bold;&quot;&gt;Java Concept:&lt;/span&gt; &lt;span style=&quot;color: #0969da; font-weight: bold; margin-left: 5px;&quot;&gt;OOP 4 Principles &amp;amp; Methods&lt;/span&gt;
&lt;div style=&quot;color: #57606a; font-size: 0.85em; margin-top: 2px;&quot;&gt;이 포스팅은 객체 지향의 4대 원칙과 관련 문법, 사용 이유를 정리한 글입니다.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바(Java)를 공부하다 보면 숨 쉬듯이 듣게 되는 단어가 있습니다. 바로 &lt;b&gt;객체 지향 프로그래밍(OOP, Object-Oriented Programming)&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;그냥 클래스 만들고 객체 생성하면 되는 거 아냐?&quot;라고 생각하기 쉽지만, 실무에서 유지보수하기 좋은 코드를 짜기 위해서는 OOP의 &lt;b&gt;4가지 핵심 원칙&lt;/b&gt;을 제대로 이해하고 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;캡슐화, 상속, 다형성, 추상화&lt;/span&gt;가 도대체 &lt;b&gt;왜 필요하며&lt;/b&gt;, 자바에서 이를 구현하기 위해 &lt;b&gt;어떤 키워드와 메서드&lt;/b&gt;를 사용하는지 완벽하게 파헤쳐 보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;section1&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;캡슐화 (Encapsulation)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캡슐화는 &lt;b&gt;데이터(변수)와 그 데이터를 처리하는 코드(메서드)를 하나로 묶고, 외부로부터 보호하는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #2196f3;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;왜 사용하는가? (Why)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;데이터 보호 (Data Integrity):&lt;/b&gt; 외부에서 변수에 직접 접근해 엉뚱한 값(예: 나이에 -5살)을 넣는 것을 방지합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유지보수성:&lt;/b&gt; 내부 구현이 바뀌어도 외부에서는 메서드 이름만 알면 되므로 영향이 적습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #666;&quot; data-ke-size=&quot;size23&quot;&gt;핵심 키워드 및 메서드&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 10px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;접근제어자&lt;/td&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;&lt;code&gt;private&lt;/code&gt;(나만), &lt;code&gt;default(같은 패키지)&lt;/code&gt;, &lt;code&gt;protected(상속)&lt;/code&gt;, &lt;code&gt;public&lt;/code&gt;(모두)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;Getter / Setter&lt;/td&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;데이터를 읽고(Get), 검증 후 저장(Set)하는 메서드&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;public class BankAccount {
    private int balance; // 1. private으로 잠금

    // 2. Setter 메서드로 검증 로직 추가
    public void setBalance(int amount) {
        if (amount &amp;lt; 0) {
            System.out.println(&quot;유효하지 않은 금액입니다.&quot;);
            return;
        }
        this.balance = amount;
    }

    // 3. Getter 메서드로 읽기 권한 제공
    public int getBalance() {
        return this.balance;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section2&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;상속 (Inheritance)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속은 &lt;b&gt;부모 클래스의 속성과 기능을 자식 클래스가 물려받아 확장하는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #2196f3;&quot; data-ke-size=&quot;size23&quot;&gt;왜 사용하는가? (Why)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;코드 재사용 (Reusability):&lt;/b&gt; 똑같은 코드를 여러 번 짤 필요 없이 부모의 것을 가져다 씁니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;계층 구조 형성:&lt;/b&gt; 사물 간의 관계(IS-A)를 명확하게 표현하여 체계적인 설계가 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #666;&quot; data-ke-size=&quot;size23&quot;&gt;핵심 키워드 및 메서드&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 10px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;extends&lt;/td&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;클래스를 상속받을 때 사용하는 키워드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;super() / super.&lt;/td&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;부모의 생성자를 호출하거나, 부모의 변수/메서드에 접근할 때 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;class Car { // 부모
    void drive() { System.out.println(&quot;운전합니다.&quot;); }
}

class SuperCar extends Car { // 자식 (extends 사용)
    void booster() {
        super.drive(); // 부모의 drive() 메서드 호출
        System.out.println(&quot;부스터 가동!&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;다형성 (Polymorphism)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다형성은 &lt;b&gt;&quot;하나의 객체나 메서드가 여러 가지 다른 형태를 가질 수 있는 성질&quot;&lt;/b&gt;입니다. OOP의 꽃이라고 불립니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #2196f3;&quot; data-ke-size=&quot;size23&quot;&gt;왜 사용하는가? (Why)&lt;/h3&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; 서로 다른 객체들을 하나의 타입(부모)으로 묶어서 관리할 수 있습니다. (예: `List list = new ArrayList()`)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #666;&quot; data-ke-size=&quot;size23&quot;&gt;핵심 키워드 및 메서드&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 10px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;Overriding&lt;/td&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;부모의 메서드를 자식 입맛에 맞게 &lt;b&gt;재정의(덮어쓰기)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;Overloading&lt;/td&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;같은 이름의 메서드를 매개변수만 다르게 하여 &lt;b&gt;여러 개 정의&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;instanceof&lt;/td&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;객체가 특정 클래스의 인스턴스인지 확인하는 연산자&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;class Animal {
    void speak() { System.out.println(&quot;소리를 냅니다&quot;); }
}

class Dog extends Animal {
    @Override // 오버라이딩
    void speak() { System.out.println(&quot;멍멍!&quot;); }
    
    // 오버로딩 (같은 이름, 다른 매개변수)
    void speak(String mood) { System.out.println(mood + &quot; 멍멍!&quot;); }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section4&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;추상화 (Abstraction)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상화는 &lt;b&gt;불필요한 세부 정보는 숨기고, 중요한 공통 기능(본질)만 추출하여 정의하는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #2196f3;&quot; data-ke-size=&quot;size23&quot;&gt;왜 사용하는가? (Why)&lt;/h3&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; 개발자들에게 &quot;이 기능은 반드시 구현해야 해!&quot;라고 강제성을 부여하여 일관된 설계를 유도합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;복잡도 감소:&lt;/b&gt; 구체적인 동작 방법(How)은 몰라도, 무슨 역할(What)을 하는지만 알면 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #666;&quot; data-ke-size=&quot;size23&quot;&gt;핵심 키워드 및 메서드&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 10px 0;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;abstract&lt;/td&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;추상 클래스나 추상 메서드를 선언할 때 사용 (미완성 설계도)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;interface&lt;/td&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;구현체가 없는 100% 껍데기, 다중 상속 가능 (설계 표준)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;implements&lt;/td&gt;
&lt;td style=&quot;padding: 8px; border: 1px solid #ddd;&quot;&gt;인터페이스를 구현할 때 사용하는 키워드&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// 추상화: &quot;그림을 그린다&quot;는 기능만 정의 (껍데기)
interface Shape {
    void draw(); // abstract method
}

// 구체화: 실제 어떻게 그릴지는 구현 클래스가 담당
class Circle implements Shape {
    @Override
    public void draw() { System.out.println(&quot;원을 그립니다.&quot;); }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section5&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;OOP를 사용하는 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 객체 지향 프로그래밍의 4대 원칙을 한눈에 정리해 봅시다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0; font-size: 0.95em;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;원칙&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;핵심 키워드&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;사용 이유 (Benefit)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #2196f3;&quot;&gt;캡슐화&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;private, Getter/Setter&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;데이터 보호 및 무결성 유지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #009688;&quot;&gt;상속&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;extends, super&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;코드 중복 제거, 재사용성 향상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #ff9800;&quot;&gt;다형성&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;Overriding, Overloading&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;유연한 확장, 변경 최소화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #9c27b0;&quot;&gt;추상화&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;interface, abstract&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;복잡도 감소, 설계 표준 제시&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;section6&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;객체 지향의 장점&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 지향 프로그래밍(OOP)을 도입했을 때 얻을 수 있는 강력한 이점들을 정리해 보았습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0; font-size: 0.95em;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left; width: 30%;&quot;&gt;장점&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #2196f3;&quot;&gt;  유지보수 용이&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;하나의 객체 또는 클래스 단위로 수정이 가능하여, 전체 시스템의 안정성을 유지하기 쉽습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #009688;&quot;&gt;♻️ 재사용성 증가&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;잘 설계된 클래스와 객체는 다른 프로젝트나 다양한 상황에서 쉽게 재활용할 수 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #ff9800;&quot;&gt;  확장성 우수&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;기능 추가 시 기존 코드를 건드리지 않고, 새로운 객체만 추가하면 되어 확장이 유연합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #9c27b0;&quot;&gt;  현실 세계 모델링&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;사람, 동물, 식물 등 실체를 코드로 자연스럽게 표현(매핑)할 수 있어 설계가 직관적입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #e91e63;&quot;&gt;  코드 가독성 향상&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;객체와 클래스 중심으로 역할이 명확하게 분리되어 있어, 코드를 읽고 이해하기가 쉬워집니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #f1f8e9; padding: 15px; border-left: 5px solid #8bc34a; margin: 10px 0; border-radius: 0 5px 5px 0;&quot;&gt;&lt;b&gt;  결론:&lt;/b&gt;&lt;br /&gt;OOP는 단순히 코드를 짜는 문법이 아니라, &lt;b&gt;&quot;유지보수하기 쉽고 유연한 소프트웨어&quot;&lt;/b&gt;를 만들기 위한 철학입니다.&lt;br /&gt;이 핵심 원칙과 장점들을 마음속에 새기고 코딩한다면, 여러분의 코드는 훨씬 더 견고해질 것입니다.&lt;/div&gt;</description>
      <category>Language/Java</category>
      <category>Java</category>
      <category>OOP</category>
      <author>hlxecz</author>
      <guid isPermaLink="true">https://hlxecz.tistory.com/6</guid>
      <comments>https://hlxecz.tistory.com/6#entry6comment</comments>
      <pubDate>Fri, 12 Dec 2025 17:42:10 +0900</pubDate>
    </item>
    <item>
      <title>Big-O, 왜 상수는 무시할까? (feat. &amp;Omega;, &amp;Theta; 표기법 정리)_Part 2</title>
      <link>https://hlxecz.tistory.com/5</link>
      <description>&lt;div style=&quot;background-color: #e3f2fd; padding: 10px 15px; border-radius: 6px; margin-bottom: 20px; font-size: 0.9em; color: #0d47a1;&quot;&gt;  &lt;b&gt;시리즈 알림:&lt;/b&gt; 이 글은 &lt;u&gt;시간 복잡도 심화편(Part 2)&lt;/u&gt;입니다. &lt;br /&gt;기초적인 O(n) vs O(n&amp;sup2;) 실전 예제는 &lt;a href=&quot;https://hlxecz.tistory.com/4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Part 1 (이전 글)&lt;/a&gt;을 참고해주세요.&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 포스팅에서 우리는 시간 복잡도를 통해 코드의 효율성을 판단하는 법을 배웠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 공부를 하다 보면 두 가지 의문이 생깁니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&quot;왜 &lt;code&gt;2n&lt;/code&gt;이나 &lt;code&gt;100n&lt;/code&gt;이나 똑같이 &lt;b&gt;O(n)&lt;/b&gt;이라고 퉁치는 걸까?&quot;&lt;br /&gt;&quot;Big-O 말고 오메가(&amp;Omega;), 세타(&amp;Theta;)는 대체 뭘까?&quot;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 개발자 면접이나 전공 수업에서 깊이 있게 다루는 &lt;b&gt;시간 복잡도의 수학적 원리&lt;/b&gt;를 아주 쉽게 풀어서 정리해 보겠습니다.&lt;/p&gt;
&lt;h2 id=&quot;section1&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;1. 왜 상수(Constant)는 생략하는가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 흔히 &lt;code&gt;O(2n)&lt;/code&gt;을 &lt;b&gt;O(n)&lt;/b&gt;으로, &lt;code&gt;O(n&amp;sup2; + 100)&lt;/code&gt;을 &lt;b&gt;O(n&amp;sup2;)&lt;/b&gt;으로 표기합니다. 2배나 차이가 나는데 왜 무시하는 걸까요?&lt;/p&gt;
&lt;h3 style=&quot;color: #d9534f;&quot; data-ke-size=&quot;size23&quot;&gt;핵심: &quot;정확한 시간&quot;이 아니라 &quot;성장 패턴&quot;이 중요하다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Big-O는 &quot;몇 초가 걸리냐&quot;를 재는 것이 아니라, &lt;b&gt;&quot;입력 크기(n)가 무한대로 커질 때, 연산량이 어떤 그래프 모양으로 증가하는가&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;를 보는 지표이기 때문입니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #f1f8e9; padding: 15px; border-radius: 5px; margin: 15px 0;&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예시 비교:&lt;/b&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;O(n):&lt;/b&gt; n=1,000일 때 &amp;rarr; 1,000번 연산&lt;/li&gt;
&lt;li&gt;&lt;b&gt;O(2n):&lt;/b&gt; n=1,000일 때 &amp;rarr; 2,000번 연산&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;margin-top: 10px;&quot; data-ke-size=&quot;size16&quot;&gt;물론 2배 차이가 나지만, &lt;b&gt;n이 커질수록 &quot;정비례해서 늘어난다(선형 증가)&quot;는 패턴은 동일&lt;/b&gt;합니다. 그래프의 기울기만 다를 뿐, 모양은 직선으로 똑같죠.&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생략 규칙 정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 영향력이 큰 항(Dominant Term)만 남기고 나머지는 과감히 버립니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0; font-size: 0.95em;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;규칙&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;예시&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;결과 (Big-O)&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;이유&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;&lt;b&gt;상수 곱 무시&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;2n, 100n&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #2196f3;&quot;&gt;O(n)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;단순히 기울기 차이일 뿐, 패턴 동일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;&lt;b&gt;낮은 차수 무시&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;n&amp;sup2; + n + 1&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #2196f3;&quot;&gt;O(n&amp;sup2;)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;n이 커지면 n&amp;sup2;이 압도적으로 주도함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;&lt;b&gt;로그보다 n 우선&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;n + log n&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #2196f3;&quot;&gt;O(n)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;log n의 증가 속도는 매우 느림&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;&lt;b&gt;상수만 존재&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;100번 수행&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold; color: #2196f3;&quot;&gt;O(1)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;입력 크기와 무관하게 고정됨&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section2&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;2. Big-O (O): 상한선&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 가장 흔하게 쓰는 표기법입니다. 알고리즘 성능의 &lt;b&gt;&quot;최악의 상황&quot;&lt;/b&gt; 혹은 &lt;b&gt;&quot;아무리 느려도 이것보단 안 느리다(상한)&quot;&lt;/b&gt;는 것을 보장합니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #fff3e0; padding: 20px; border: 1px solid #ffe0b2; border-radius: 8px;&quot;&gt;
&lt;h4 style=&quot;margin-top: 0; color: #ef6c00;&quot; data-ke-size=&quot;size20&quot;&gt;수학적 정의&lt;/h4&gt;
&lt;p style=&quot;font-family: 'Times New Roman', serif; font-size: 1.1em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;f(n) &amp;le; C &amp;middot; g(n)&lt;/i&gt;&lt;br /&gt;&lt;span style=&quot;font-size: 0.8em; color: #666;&quot;&gt;(for sufficiently large n)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;의미:&lt;/b&gt; &lt;i&gt;f(n)&lt;/i&gt;의 증가 속도가 &lt;i&gt;g(n)&lt;/i&gt;보다 빨라지지 않는다. (위에서 눌러주는 상한선)&lt;/p&gt;
&lt;/div&gt;
&lt;p style=&quot;margin-top: 15px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;margin-top: 15px;&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 &lt;code&gt;f(n) = n&amp;sup2; + n + 1&lt;/code&gt; 이라는 알고리즘이 있을 때, n이 충분히 크다면 &lt;code&gt;C &amp;middot; n&amp;sup2;&lt;/code&gt;보다 항상 작거나 같습니다.&lt;br /&gt;따라서 이 알고리즘은 &lt;span style=&quot;background-color: #eee; padding: 2px 5px; border-radius: 3px;&quot;&gt;f(n) &amp;isin; O(n&amp;sup2;)&lt;/span&gt; 이라고 할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;margin-top: 15px;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;3. Big-&amp;Omega;, Big-&amp;Theta;: 다른 형제들&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Big-O만 있는 게 아닙니다. 상황에 따라 하한선이나 정확한 구간을 표현해야 할 때도 있습니다.&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;Big-&amp;Omega; (오메가): 하한선 (최소 성장 속도)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;아무리 빨라도 이것보단 빠를 수 없다&quot;는 &lt;b&gt;최소한의 연산량&lt;/b&gt;을 의미합니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #fff3e0; padding: 20px; border: 1px solid #ffe0b2; border-radius: 8px;&quot;&gt;
&lt;p style=&quot;font-family: 'Times New Roman', serif;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;f(n) &amp;ge; c &amp;middot; g(n)&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;의미:&lt;/b&gt; &lt;i&gt;f(n)&lt;/i&gt;의 증가 속도가 &lt;i&gt;g(n)&lt;/i&gt;보다 느리지 않다. (아래에서 받쳐주는 하한)&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예: &lt;code&gt;n&amp;sup2; + n + 1&lt;/code&gt;은 아무리 작아도 &lt;code&gt;n&amp;sup2;&lt;/code&gt; 보다는 큽니다. &amp;rarr; &lt;span style=&quot;background-color: #eee; padding: 2px 5px; border-radius: 3px;&quot;&gt;f(n) &amp;isin; &amp;Omega;(n&amp;sup2;)&lt;/span&gt;&lt;span style=&quot;background-color: #eee; padding: 2px 5px; border-radius: 3px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Big-&amp;Theta; (세타): 딱 맞는 성장 속도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상한(O)과 하한(&amp;Omega;)이 같을 때, 즉 &lt;b&gt;&quot;딱 이 정도 속도로 성장한다&quot;&lt;/b&gt;고 정확하게 말할 때 사용합니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #fff3e0; padding: 20px; border: 1px solid #ffe0b2; border-radius: 8px;&quot;&gt;
&lt;p style=&quot;font-family: 'Times New Roman', serif;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;f(n) &amp;isin; O(g(n)) AND f(n) &amp;isin; &amp;Omega;(g(n))&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;의미:&lt;/b&gt; &lt;i&gt;f(n)&lt;/i&gt;과 &lt;i&gt;g(n)&lt;/i&gt;이 같은 차수로 성장한다. (샌드위치처럼 딱 맞음)&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예: &lt;code&gt;n&amp;sup2; + n + 1&lt;/code&gt;은 n&amp;sup2;의 상한도 만족하고 하한도 만족하므로 &amp;rarr; &lt;span style=&quot;background-color: #eee; padding: 2px 5px; border-radius: 3px;&quot;&gt;f(n) &amp;isin; &amp;Theta;(n&amp;sup2;)&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section4&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;4. 요약&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 알고리즘 문제 풀이(코딩 테스트)에서는 &lt;b&gt;Big-O(최악의 경우)&lt;/b&gt;만 고려하면 됩니다. 내가 짠 코드가 최악의 상황에서도 제한 시간 내에 통과하는지가 중요하기 때문입니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #f9f9f9; padding: 20px; border-radius: 10px; border: 1px solid #ddd;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc; margin-bottom: 0;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;O(2n) &amp;rarr; O(n):&lt;/b&gt; 성장 패턴(기울기)이 선형으로 같기 때문에 상수는 무시한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Big-O (O):&lt;/b&gt; &quot;최악의 경우엔 이 정도야&quot; (상한선)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Big-&amp;Omega; (&amp;Omega;):&lt;/b&gt; &quot;최소한 이만큼은 걸려&quot; (하한선)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Big-&amp;Theta; (&amp;Theta;):&lt;/b&gt; &quot;정확히 이 정도 차수야&quot; (평균/정확)&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 누군가 &quot;왜 상수를 떼고 말하나요?&quot;라고 묻는다면, &lt;b&gt;&quot;입력 데이터가 무한대로 커질 때의 성장 패턴을 보기 위함입니다!&quot;&lt;/b&gt;라고 멋지게 대답해 보세요.&lt;/p&gt;</description>
      <category>TEST/Testing</category>
      <category>BIG-O</category>
      <category>시간복잡도</category>
      <author>hlxecz</author>
      <guid isPermaLink="true">https://hlxecz.tistory.com/5</guid>
      <comments>https://hlxecz.tistory.com/5#entry5comment</comments>
      <pubDate>Mon, 8 Dec 2025 18:28:26 +0900</pubDate>
    </item>
    <item>
      <title>내 코드가 느린 이유? 시간 복잡도(Time Complexity)와 Big-O 정리_Part 1</title>
      <link>https://hlxecz.tistory.com/4</link>
      <description>&lt;div style=&quot;background-color: #f6f8fa; border: 1px solid #d0d7de; border-radius: 6px; padding: 12px 15px; margin-bottom: 20px; font-size: 0.9em; display: flex; align-items: center;&quot;&gt;&lt;span style=&quot;margin-right: 10px; font-size: 1.2em;&quot;&gt; &lt;/span&gt;
&lt;div&gt;&lt;span style=&quot;color: #57606a; font-weight: bold;&quot;&gt;Problem Source:&lt;/span&gt; &lt;a style=&quot;color: #0969da; text-decoration: none; font-weight: bold; margin-left: 5px;&quot; href=&quot;https://github.com/Hlxecz/Sw_Pilot_Java/tree/main/Chapter_2/Step2/src&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; GitHub - Sw_Pilot_Java (Chapter 2 / Step 2 - 3) &lt;/a&gt;
&lt;div style=&quot;color: #57606a; font-size: 0.85em; margin-top: 2px;&quot;&gt;이 포스팅은 해당 리포지토리의 문제에 대한 분석 및 풀이 과정을 담고 있습니다.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알고리즘 문제를 풀거나 실무에서 대용량 데이터를 다루다 보면, 기능은 완벽한데 &lt;b&gt;&quot;시간 초과&quot;&lt;/b&gt;가 뜨거나 시스템이 버벅이는 경우를 마주합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 우리가 가장 먼저 점검해야 할 것이 바로 &lt;b&gt;시간 복잡도(Time Complexity)&lt;/b&gt;입니다. 오늘은 제가 공부한 내용을 바탕으로, &lt;span style=&quot;background-color: #fff5b1;&quot;&gt;O(n&amp;sup2;)의 늪에서 빠져나와 O(n)으로 최적화하는 과정&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;section1&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 시간 복잡도란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 복잡도는 &lt;b&gt;알고리즘이 입력 크기(Input Size)에 따라 얼마나 많은 연산을 수행하는지&lt;/b&gt;를 나타내는 지표입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 &quot;몇 초 걸린다&quot;가 아니라, 수학적으로 실행 시간의 변화 추이를 표현하는 것이죠.&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;최악의 시간(Worst Case):&lt;/b&gt; 빅오(Big-O) 표기법의 기준이 되며, 가장 오래 걸릴 때를 가정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;필요성:&lt;/b&gt; 효율적인 알고리즘 선택, 성능 개선 포인트 파악, 대규모 데이터 처리 가능 여부 판단&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section2&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Big-O 표기법 총정리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Big-O 표기법은 데이터 입력 크기(&lt;code&gt;n&lt;/code&gt;)가 무한대로 커질 때, 연산 횟수가 어떻게 증가하는지 &lt;b&gt;상한선&lt;/b&gt;을 나타냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 표는 &lt;b&gt;빠른 순서(위)에서 느린 순서(아래)&lt;/b&gt;로 정렬되어 있습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0; font-size: 0.95em;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;표현&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;속도 / 이름&lt;/th&gt;
&lt;th style=&quot;padding: 12px; border: 1px solid #ddd; text-align: left;&quot;&gt;대표 예시&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #2196f3; font-weight: bold;&quot;&gt;O(1)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;상수 시간 (Fastest)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;Stack의 Push/Pop, 배열 인덱스 접근&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #2196f3; font-weight: bold;&quot;&gt;O(log n)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;로그 시간&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;이진 탐색 (Binary Search)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #009688; font-weight: bold;&quot;&gt;O(n)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;선형 시간&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;for문 1번 순회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #ff9800; font-weight: bold;&quot;&gt;O(n log n)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;선형 로그 시간&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;퀵 정렬(Quick), 병합 정렬(Merge)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #fff8f8;&quot;&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #f44336; font-weight: bold;&quot;&gt;O(n^2)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;이차 시간&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;이중 for문, 삽입/거품 정렬&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #ffebee;&quot;&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #c62828; font-weight: bold;&quot;&gt;O(2^n)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;지수 시간 (Exponential)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;피보나치 수열(재귀), 부분집합 구하기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #ffcdd2;&quot;&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: #b71c1c; font-weight: bold;&quot;&gt;O(n!)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;팩토리얼 시간 (Slowest)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;외판원 순회 문제(TSP), 모든 순열 구하기&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div style=&quot;background-color: #f1f8e9; padding: 15px; border-left: 5px solid #8bc34a; margin: 10px 0; border-radius: 0 5px 5px 0;&quot;&gt;&lt;b&gt;  성능 순서 요약:&lt;/b&gt;&lt;br /&gt;O(1) &amp;lt; O(log n) &amp;lt; O(n) &amp;lt; O(n log n) &amp;lt; &lt;span style=&quot;color: red;&quot;&gt;O(n&amp;sup2;) &amp;lt; O(2^n) &amp;lt; O(n!)&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;오른쪽으로 갈수록(아래로 갈수록) 실행 시간이 기하급수적으로 늘어나므로, &lt;br /&gt;데이터가 많을 때는 &lt;b&gt;O(n&amp;sup2;) 이상&lt;/b&gt;의 알고리즘은 피하는 것이 좋습니다.&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddf0Iu/dJMcacVUKQl/oTE9h3vsrrFku3DVjIeYJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddf0Iu/dJMcacVUKQl/oTE9h3vsrrFku3DVjIeYJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddf0Iu/dJMcacVUKQl/oTE9h3vsrrFku3DVjIeYJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fddf0Iu%2FdJMcacVUKQl%2FoTE9h3vsrrFku3DVjIeYJK%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;846&quot; height=&quot;570&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;570&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;figure style=&quot;text-align: center; margin: 30px 0;&quot;&gt;
&lt;figcaption style=&quot;color: #888; font-size: 0.9em;&quot;&gt;▲ Big-O Complexity Chart (입력 크기에 따른 시간 증가량)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;section3&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. Case Study 01: 중복 없는 숫자 찾기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 케이스는 &lt;b&gt;&quot;리스트에서 딱 한 번만 등장하는 숫자를 찾는 상황&quot;&lt;/b&gt;입니다. 여기서 초보자들이 가장 많이 하는 실수가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #d9534f;&quot; data-ke-size=&quot;size23&quot;&gt;내가 작성한 문제의 코드 (O(n&amp;sup2;))&lt;/h3&gt;
&lt;pre class=&quot;java&quot; style=&quot;background: #282c34; color: #abb2bf; padding: 20px; border-radius: 8px;&quot;&gt;&lt;code&gt;for (int val : list) {
&amp;nbsp; &amp;nbsp; // 리스트 전체를 돌면서 val의 개수를 센다
&amp;nbsp; &amp;nbsp; if (Collections.frequency(list, val) == 1) {&amp;nbsp;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; System.out.println(val);
&amp;nbsp; &amp;nbsp; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;병목 분석&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Collections.frequency(list, val)&lt;/code&gt; 메서드는 마법처럼 숫자를 세주는 게 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부적으로 &lt;b&gt;리스트 전체를 처음부터 끝까지 순회(O(n))&lt;/b&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;code&gt;for&lt;/code&gt;문: &lt;b&gt;n회&lt;/b&gt; 반복&lt;/li&gt;
&lt;li&gt;안쪽 &lt;code&gt;frequency&lt;/code&gt;: &lt;b&gt;n회&lt;/b&gt; 탐색&lt;/li&gt;
&lt;li&gt;&lt;b&gt;총 시간 복잡도:&lt;/b&gt; n &amp;times; n = &lt;span style=&quot;color: red; font-weight: bold;&quot;&gt;O(n&amp;sup2;)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 10만 개라면, 100억 번의 연산을 하게 되어 프로그램이 멈출 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #2196f3;&quot; data-ke-size=&quot;size23&quot;&gt;최적화: HashMap 사용 (O(n))&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하기 위해 &lt;b&gt;HashMap&lt;/b&gt;을 사용하여 데이터를 미리 세어둡니다(Preprocessing).&lt;/p&gt;
&lt;pre class=&quot;java&quot; style=&quot;background: #282c34; color: #abb2bf; padding: 20px; border-radius: 8px;&quot;&gt;&lt;code&gt;// 1. O(n): 리스트를 한 번만 돌면서 개수를 맵에 저장
Map&amp;lt;Integer, Integer&amp;gt; countMap = new HashMap&amp;lt;&amp;gt;();
for (int val : list) {
&amp;nbsp; &amp;nbsp; countMap.put(val, countMap.getOrDefault(val, 0) + 1);
}

// 2. O(n): 맵을 확인하며 1번만 등장한 값 찾기
// (Map의 조회는 평균적으로 O(1)입니다)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 루프가 중첩되지 않고 분리되어 &lt;b&gt;O(n) + O(n) = O(2n)&lt;/b&gt;, 즉 &lt;b&gt;O(n)&lt;/b&gt;으로 획기적인 성능 향상이 일어납니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section4&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. Case Study 02: 회문(Palindrome) 판별기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 케이스는 &lt;b&gt;&quot;문장을 단어별로 쪼개고, 회문이면 출력, 아니면 뒤집어서 출력&quot;&lt;/b&gt;하는 로직입니다.&lt;/p&gt;
&lt;h3 style=&quot;color: #d9534f;&quot; data-ke-size=&quot;size23&quot;&gt;내가 작성한 코드 (O(n))&lt;/h3&gt;
&lt;pre class=&quot;java&quot; style=&quot;background: #282c34; color: #abb2bf; padding: 20px; border-radius: 8px;&quot;&gt;&lt;code&gt;// 문장을 단어별로 쪼갬
for (int i = sens.length - 1; i &amp;gt;= 0; i--) {
&amp;nbsp; &amp;nbsp; // 각 단어(word)의 앞뒤를 비교 (회문 검사)
&amp;nbsp; &amp;nbsp; for (int e = 0; e &amp;lt; word.length() / 2; e++) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (word.charAt(e) != word.charAt(word.length() - 1 - e)) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // ...
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;복잡도 분석 (이건 병목이 아님)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;얼핏 보면 &lt;code&gt;for&lt;/code&gt;문 안에 &lt;code&gt;for&lt;/code&gt;문이 있어 &lt;b&gt;O(n&amp;sup2;)&lt;/b&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;n:&lt;/b&gt; 단어의 개수&lt;/li&gt;
&lt;li&gt;&lt;b&gt;k:&lt;/b&gt; 각 단어의 평균 길이&lt;/li&gt;
&lt;li&gt;&lt;b&gt;N:&lt;/b&gt; 전체 문자열의 길이 (n &amp;times; k)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 모든 단어의 모든 글자를 한 번씩만 확인합니다. 즉, 전체 연산 횟수는 전체 글자 수(N)와 비례합니다.&lt;/p&gt;
&lt;div style=&quot;background-color: #e8f4fd; padding: 15px; border-left: 5px solid #2196f3; margin: 10px 0; border-radius: 0 5px 5px 0;&quot;&gt;&lt;b&gt;  결론:&lt;/b&gt; O(nk) = &lt;b&gt;O(N)&lt;/b&gt; (전체 문자 수 기준 선형 시간)&lt;br /&gt;입력 길이가 최대 10⁶이라도, O(N)은 충분히 효율적이므로 굳이 최적화할 필요가 없습니다.&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;section5&quot; style=&quot;border-left: 5px solid #2196f3; padding-left: 10px; margin-top: 50px;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 병목 현상 및 최적화 방안 요약&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘 분석한 내용을 표로 정리해 보았습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; border: 1px solid #ddd; margin: 20px 0; font-size: 0.95em;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;background-color: #f2f2f2;&quot;&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;병목 원인&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;기존 시간 복잡도&lt;/th&gt;
&lt;th style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;개선 후&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;Case 01&lt;br /&gt;(숫자 찾기)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;Collections.frequency에 의한&lt;br /&gt;중복 순회 발생&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: red;&quot;&gt;&lt;b&gt;O(n&amp;sup2;)&lt;/b&gt;&lt;br /&gt;(매우 느림)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: green;&quot;&gt;&lt;b&gt;O(n)&lt;/b&gt;&lt;br /&gt;(HashMap 사용)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; font-weight: bold;&quot;&gt;Case 02&lt;br /&gt;(회문 판별)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;없음 (구조적으로 효율적)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd; color: green;&quot;&gt;&lt;b&gt;O(N)&lt;/b&gt;&lt;br /&gt;(전체 문자 수)&lt;/td&gt;
&lt;td style=&quot;padding: 10px; border: 1px solid #ddd;&quot;&gt;변경 불필요&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 복잡도 분석은 &lt;b&gt;&quot;내 코드가 왜 느린지&quot;&lt;/b&gt;를 찾아내는 가장 중요한 핵심 이론입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Case 01처럼 &lt;b&gt;숨겨진 루프(frequency)&lt;/b&gt;를 찾아내 O(n)으로 만드는 것이 최적화의 핵심이고, Case 02처럼 &lt;b&gt;구조적으로 이미 최적화된 코드&lt;/b&gt;를 구별해내는 안목 또한 중요한 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #f5f5f5; padding: 15px; border-radius: 5px; color: #666; font-size: 0.9em;&quot;&gt;&amp;nbsp; &lt;b&gt;참고 자료&lt;/b&gt;&lt;br /&gt;- &lt;a style=&quot;color: #666; text-decoration: underline;&quot; href=&quot;https://www.bigocheatsheet.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Big-O Cheat Sheet&lt;/a&gt;&lt;br /&gt;- &lt;a style=&quot;color: #666; text-decoration: underline;&quot; href=&quot;https://visualgo.net/en&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;VisuAlgo&lt;/a&gt;&lt;br /&gt;- &lt;a style=&quot;color: #666; text-decoration: underline;&quot; href=&quot;https://www.geeksforgeeks.org/collections-frequency-java/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GeeksforGeeks (Collections.frequency)&lt;/a&gt;&lt;/div&gt;</description>
      <category>TEST/Testing</category>
      <category>문제풀이</category>
      <category>빅오표기법</category>
      <category>시간복잡도</category>
      <category>피드백</category>
      <author>hlxecz</author>
      <guid isPermaLink="true">https://hlxecz.tistory.com/4</guid>
      <comments>https://hlxecz.tistory.com/4#entry4comment</comments>
      <pubDate>Mon, 8 Dec 2025 17:30:51 +0900</pubDate>
    </item>
  </channel>
</rss>