==👨‍💻 디자인 패턴 핵심 요약==

개발자의 필독서 디자인 패턴 완벽 가이드북

소프트웨어 개발은 건축과 비슷하다. 튼튼하고 효율적인 건물을 짓기 위해 건축가가 설계 도면을 그리는 것처럼, 개발자도 견고하고 확장 가능한 소프트웨어를 만들기 위해 설계를 한다. 하지만 이 과정에서 개발자들이 반복적으로 마주치는 문제들이 있다. 예를 들어, 객체를 어떻게 만들고 관리해야 메모리를 효율적으로 사용할 수 있을까? 혹은 서로 다른 객체들을 어떻게 연결해야 유연하게 작동할까?

이러한 고민에 대한 오랜 시간 축적된 해답이 바로 **디자인 패턴(Design Pattern)**이다. 디자인 패턴은 특정 상황에서 발생하는 일반적인 문제에 대한 해결책을 정형화된 형태로 정리한 것이다. 이는 단순한 코드 조각이 아니라, 설계에 대한 ‘사고 방식’을 제공하여 개발자에게 유용한 길잡이가 된다.

1. 디자인 패턴 왜 만들어졌는가

디자인 패턴의 역사는 1990년대로 거슬러 올라간다. 당시 객체 지향 프로그래밍이 확산되면서 개발자들은 복잡한 시스템을 설계하고 구축하는 데 많은 어려움을 겪었다. 이들의 공통된 고민은 “어떻게 하면 재사용 가능한 소프트웨어를 만들 수 있을까?”였다.

이때 에리히 감마(Erich Gamma), 리처드 헬름(Richard Helm), 랄프 존슨(Ralph Johnson), 존 블리시데스(John Vlissides) 네 명의 저자가 **GoF(Gang of Four)**라는 이름으로 불리며 **『Design Patterns: Elements of Reusable Object-Oriented Software』**라는 기념비적인 책을 출간한다. 이 책은 23가지 디자인 패턴을 소개하며 소프트웨어 설계의 새로운 패러다임을 제시했다. 이들은 건축 분야의 ‘패턴 언어’ 개념을 소프트웨어에 적용해, 반복되는 문제와 그에 대한 해결책을 체계적으로 분류하고 명명했다.

디자인 패턴이 중요한 이유를 크게 두 가지로 요약할 수 있다.

  • 재사용 가능한 검증된 설계: 디자인 패턴은 이미 수많은 개발자들이 동일한 문제에 대해 고민하고 해결하며 검증해 온 결과물이다. 새로운 문제에 직면했을 때 처음부터 모든 것을 설계하는 대신, 적절한 디자인 패턴을 적용하면 시간을 절약하고 잠재적인 버그나 설계 결함을 줄일 수 있다.

  • 개발자 간의 의사소통 효율 증진: 디자인 패턴은 개발자들 사이의 공통 언어 역할을 한다. “이 부분은 싱글톤 패턴을 적용했습니다”라고 말하는 순간, 상대방은 코드를 깊이 들여다보지 않아도 이 객체가 전체 시스템에서 단 하나만 존재하며 공유된다는 것을 즉시 이해한다. 이는 코드 리뷰나 협업 시 불필요한 설명을 줄여 의사소통 비용을 크게 낮춘다.

2. 디자인 패턴의 세 가지 분류 체계

디자인 패턴은 그 목적에 따라 크게 세 가지 그룹으로 나뉜다. 이 분류는 문제를 해결하는 ‘방식’을 기준으로 한다.

생성 패턴 (Creational Patterns)

객체 생성 방식과 관련된 패턴. 객체 생성 과정을 추상화하거나 캡슐화하여 시스템의 유연성을 높인다. 새로운 객체를 만들 때 직접 new 키워드를 사용하기보다, 특정 패턴을 통해 객체 생성을 위임함으로써 결합도를 낮추는 데 중점을 둔다.

  • 팩토리 메서드(Factory Method): 객체 생성을 서브클래스에 위임하여 유연성을 확보

  • 싱글톤(Singleton): 전체 시스템에서 단 하나의 객체만 존재하도록 보장

  • 추상 팩토리(Abstract Factory): 서로 관련 있는 객체들의 집합을 생성하는 인터페이스 제공

  • 빌더(Builder): 복잡한 객체 생성 과정을 단계별로 분리

  • 프로토타입(Prototype): 기존 객체를 복제하여 새로운 객체 생성

구조 패턴 (Structural Patterns)

클래스나 객체들을 조합하여 더 큰 구조를 만드는 패턴. 서로 다른 인터페이스를 가진 클래스들을 조합하거나, 복잡한 시스템의 구조를 단순화하는 데 사용한다.

  • 어댑터(Adapter): 호환되지 않는 인터페이스를 호환 가능하도록 변환

  • 프록시(Proxy): 특정 객체에 대한 접근을 제어하는 대리자 역할

  • 데코레이터(Decorator): 객체에 동적으로 새로운 기능을 추가

  • 퍼사드(Facade): 복잡한 서브시스템을 단순한 인터페이스로 묶음

  • 컴포지트(Composite): 객체들을 트리 구조로 구성하여 전체-부분 관계 표현

행동 패턴 (Behavioral Patterns)

객체 간의 상호작용과 관련된 패턴. 객체들이 어떻게 소통하고 책임을 분배하는지를 정의한다. 이를 통해 객체 간의 결합도를 낮추고 유연성을 높인다.

  • 템플릿 메서드(Template Method): 알고리즘의 뼈대를 정의하고, 세부 단계를 서브클래스에 위임

  • 옵저버(Observer): 한 객체의 상태 변화가 다른 객체에 자동으로 통보되도록 함

  • 커맨드(Command): 요청을 객체로 캡슐화하여 매개변수화하거나, 로깅, 실행 취소 기능 추가

  • 전략(Strategy): 알고리즘을 여러 클래스로 분리하여 교체 가능하게 함

  • 스테이트(State): 객체의 내부 상태에 따라 행동을 변경

3. 주요 디자인 패턴 심층 분석

이제 면접이나 실무에서 가장 자주 등장하는 4가지 핵심 디자인 패턴을 심층적으로 살펴보겠다.

1) 싱글톤 패턴 (Singleton Pattern)

핵심: 오직 한 개의 인스턴스만 존재하도록 보장하는 패턴.

싱글톤 패턴은 애플리케이션 내에서 단 하나의 객체만 생성하여 공유하는 방식이다. 이는 메모리 자원을 절약하고, 객체 간에 상태를 공유해야 하는 경우에 유용하다. 마치 대한민국이라는 시스템에 대통령이 한 명만 존재하는 것과 같다.

왜 필요한가: 데이터베이스 연결 객체나 스레드 풀처럼 시스템 전체에서 공통으로 사용되는 자원은 여러 개를 만들 필요가 없다. 여러 개의 인스턴스가 생성되면 불필요한 메모리 낭비가 발생하고, 데이터의 일관성을 보장하기 어려워진다. 예를 들어, DB 커넥션 객체를 사용할 때마다 생성하고 해제하면 부하가 크고 비효율적이다. 싱글톤 패턴을 사용하면 하나의 커넥션 객체를 미리 만들어두고 필요할 때마다 가져다 씀으로써 자원 낭비를 막는다.

구현 방법 (세 가지 주요 방식):

  • 이른 초기화 (Eager Initialization): 애플리케이션이 시작될 때 미리 인스턴스를 생성한다.

    public class Singleton {
        private static final Singleton instance = new Singleton();
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            return instance;
        }
    }
    

    장점은 구현이 매우 간단하고 스레드에 안전하다는 점. 단점은 인스턴스가 사용되지 않더라도 메모리에 상주한다는 것이다.

  • 게으른 초기화 (Lazy Initialization): 인스턴스가 필요한 시점에 생성한다.

    public class Singleton {
        private static Singleton instance;
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    장점은 필요한 시점에만 객체를 생성하므로 메모리를 효율적으로 사용한다는 점이다. 하지만 멀티스레드 환경에서 동시에 getInstance()를 호출하면 여러 인스턴스가 생성될 수 있는 치명적인 문제가 발생한다.

  • 스레드 안전한 게으른 초기화 (Thread-safe Lazy Initialization):: 멀티스레드 환경에서 안전하게 게으른 초기화를 구현한다. synchronized 키워드를 사용하거나, 이중 확인 잠금(Double-Checked Locking) 기법을 사용한다.

    public class Singleton {
        private static volatile Singleton instance; // volatile 키워드 사용
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized (Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    이중 확인 잠금은 synchronized 블록의 성능 저하를 최소화하면서 스레드 안전성을 확보하는 방법이다.

2) 팩토리 메서드 패턴 (Factory Method Pattern)

핵심: 객체를 생성하는 책임을 서브클래스에 위임하여 생성 코드를 추상화하는 패턴.

객체를 직접 new 키워드로 생성하는 대신, 객체 생성을 위한 **인터페이스(팩토리 메서드)**를 정의하고, 구체적인 객체 생성은 팩토리를 상속받은 서브클래스에서 담당한다.

왜 필요한가: 특정 객체(예: 건물)를 생성하는 과정이 복잡하고, 생성해야 하는 객체의 종류가 여러 가지(예: 아시아 스타일 건물, 유럽 스타일 건물)일 때 유용하다. 코드가 특정 객체에 직접적으로 의존하는 것을 막아 결합도를 낮추고 코드를 유연하게 만든다. 이를 통해 **개방/폐쇄 원칙(OCP, Open/Closed Principle)**을 준수할 수 있다. 새로운 종류의 객체가 추가되더라도 기존 코드를 수정할 필요 없이, 팩토리 인터페이스를 상속받는 새로운 클래스만 추가하면 된다.

건설사 비유: ‘건설사’라는 인터페이스가 있고, 이 인터페이스를 구현하는 ‘유럽 건설사’와 ‘아시아 건설사’ 클래스가 있다고 가정하자. 두 클래스는 모두 건물짓기()라는 메서드를 가지고 있지만, 실제 내부 구현은 다르다. 이 경우, 클라이언트(건물 짓기를 요청하는 쪽)는 특정 건설사를 직접 생성하는 대신, 건설사라는 인터페이스만 바라보고 건물짓기() 메서드를 호출한다. 실제 어떤 건설사가 사용될지는 별도의 설정(DI)을 통해 결정되므로, 유럽 건설사를 아시아 건설사로 변경해도 클라이언트 코드는 수정할 필요가 없다.

구조:

  • Product (제품): 생성될 객체의 공통 인터페이스 (예: 건물)

  • ConcreteProduct (구체적 제품): Product를 구현한 실제 객체 (예: 유럽 건물, 아시아 건물)

  • Creator (생성자): 팩토리 메서드를 선언하는 추상 클래스나 인터페이스 (예: 건설사)

  • ConcreteCreator (구체적 생성자): 팩토리 메서드를 오버라이드하여 ConcreteProduct 객체를 생성 (예: 유럽 건설사, 아시아 건설사)

역할설명건설사 비유
Product생성될 객체의 공통 인터페이스건물 인터페이스
ConcreteProduct실제 생성되는 객체유럽 건물, 아시아 건물
Creator팩토리 메서드를 정의건설사 인터페이스
ConcreteCreator제품을 생성하는 구체적인 팩토리 클래스유럽 건설사, 아시아 건설사

3) 어댑터 패턴 (Adapter Pattern)

핵심: 호환되지 않는 인터페이스를 가진 객체들을 함께 사용 가능하게 만드는 패턴.

서로 다른 두 개의 인터페이스를 연결하는 ‘어댑터’ 역할을 한다. 마치 한국에서 가져온 전자제품을 미국에서 사용하기 위해 플러그 모양을 바꿔주는 변환 어댑터와 같다.

왜 필요한가: 이미 잘 동작하는 외부 라이브러리나 레거시 시스템이 있지만, 우리 시스템의 인터페이스와 맞지 않을 때 사용한다. 직접 코드를 수정할 수 없거나 수정하기 번거로운 외부 코드를 우리 시스템에 맞게 변환해준다. 이를 통해 기존 코드를 재사용하면서도 시스템의 유연성을 유지한다.

건설사 비유: 우리 시스템은 건물짓기()라는 메서드를 가진 건설사 인터페이스만 인식한다고 가정하자. 그런데 외부 라이브러리인 ‘유럽 건축사’는 build() 메서드를, ‘아시아 건설사’는 make() 메서드를 사용한다. 이 두 라이브러리를 우리 시스템에 통합하려면 어떻게 해야 할까?

이때 어댑터가 필요하다.

  1. 유럽어댑터건설사 인터페이스를 구현하고, 내부적으로 유럽 건축사build() 메서드를 호출하도록 건물짓기()를 구현한다.

  2. 아시아어댑터도 마찬가지로 아시아 건설사make() 메서드를 호출하도록 구현한다.

이제 우리 시스템은 유럽어댑터아시아어댑터를 사용하기만 하면 외부 라이브러리의 기능을 동일한 인터페이스로 사용할 수 있게 된다.

구조:

  • Target (목표): 클라이언트가 사용하는 인터페이스 (예: 건설사)

  • Adaptee (적응 대상): 호환되지 않는 기존의 인터페이스 (예: 유럽 건축사, 아시아 건설사)

  • Adapter (어댑터): Target 인터페이스를 구현하고 Adaptee를 활용하여 기능을 수행 (예: 유럽 어댑터, 아시아 어댑터)

어댑터 패턴은 클래스 상속을 사용하는 클래스 어댑터와 객체 구성을 사용하는 객체 어댑터로 나눌 수 있다. 일반적으로 객체 어댑터가 더 유연하고 널리 사용된다.

4) 템플릿 메서드 패턴 (Template Method Pattern)

핵심: 알고리즘의 뼈대(템플릿)를 부모 클래스에 정의하고, 구체적인 세부 단계는 자식 클래스에서 구현하게 하는 패턴.

마치 요리 레시피처럼, **준비 -> 요리 -> 서빙**이라는 전체적인 흐름은 정해져 있지만, 각 단계의 구체적인 방법은 요리사에 따라 달라지는 것과 같다.

왜 필요한가: 여러 객체에 공통적으로 적용되는 알고리즘이 있지만, 그 과정의 일부 단계만 달라지는 경우에 코드 중복을 줄이고 유연성을 확보한다. 부모 클래스에서 변하지 않는 부분을 고정하고, 변하는 부분만 추상 메서드로 정의하여 자식 클래스에 구현을 강제한다. 이를 통해 부모는 자식에게 어떤 절차를 따라야 하는지 알려주고, 자식은 자신의 방식으로 그 절차를 완성하는 **‘제어의 역전(Inversion of Control)‘**이 일어난다.

건설사 비유: ‘건물’이라는 추상 클래스가 있고, 준비()세우기()라는 추상 메서드, 그리고 건물짓기()라는 템플릿 메서드를 가진다고 가정하자.

  • 건물짓기() 메서드에는 준비()를 호출하고 이어서 세우기()를 호출하는 순서가 정해져 있다.

  • 유럽 건물아시아 건물 클래스는 이 건물 클래스를 상속받아, 각각의 스타일에 맞는 준비()세우기() 메서드를 구현한다.

이렇게 되면 전체적인 건물 짓기 과정은 변하지 않으면서, 세부적인 준비 및 세우기 방식만 다르게 구현할 수 있다. 새로운 스타일의 건물이 추가되더라도, 건물 클래스를 상속받는 새로운 클래스만 만들면 되므로 기존 코드를 수정할 필요가 없다.

구조:

  • AbstractClass (추상 클래스): 알고리즘의 뼈대(템플릿 메서드)를 정의하고, 추상 메서드(Hook Method)를 포함한다. (예: 건물)

  • ConcreteClass (구체적 클래스): AbstractClass를 상속받아 추상 메서드를 구현한다. (예: 유럽 건물, 아시아 건물)

자바에서의 예시: 자바의 AbstractList 클래스는 add, remove, get 등의 공통 기능을 정의하면서도, get(int index)와 같은 추상 메서드는 구체적인 구현(예: ArrayList는 배열 기반, LinkedList는 연결 리스트 기반)을 서브클래스에 위임하는 방식으로 템플릿 메서드 패턴을 활용한다.

4. 디자인 패턴의 한계와 비판

디자인 패턴은 만능 해결책이 아니다. 무분별한 사용은 오히려 코드를 복잡하게 만들고 과도한 추상화로 인해 가독성을 해칠 수 있다.

  • 복잡성 증가: 패턴을 적용하는 과정에서 불필요한 클래스와 인터페이스가 추가될 수 있다. 이는 프로젝트의 규모가 작거나 단순한 문제에 대해 오버엔지니어링(Over-engineering)을 초래할 수 있다.

  • 실수와 오용의 가능성: 특정 패턴의 장점만 보고 단점을 고려하지 않거나, 상황에 맞지 않는 패턴을 적용하면 오히려 유지보수가 더 어려워진다.

  • 은탄환이 아니다: 디자인 패턴은 단순히 ‘도구’일 뿐이다. 좋은 설계를 위해서는 문제의 본질을 이해하고, 패턴을 올바르게 선택하며, 자신의 코드에 맞게 변형하여 적용하는 능력이 필요하다.

결론적으로, 디자인 패턴은 맹목적으로 외워야 할 지식이 아니라, 반복적인 문제를 해결하기 위한 ‘설계의 지혜’다. 이 핸드북을 통해 각 패턴의 근본적인 목적과 구조를 이해하고, 실제 프로젝트에서 어떤 문제에 직면했을 때 어떤 패턴을 고려해야 할지 판단하는 능력을 기르길 바란다.

더 나아가 각 패턴의 세부 구현 방식이나 다른 패턴들과의 조합에 대해 궁금하다면, 언제든지 물어봐 달라.

1. ❓ 디자인 패턴이란?

1.1. ⚙️ 정의

  • 소프트웨어 개발 과정에서 ==반복적으로 발생하는 문제==에 대한 _검증된 설계 노하우_를 패턴화
  • ==코드 스타일==을 통일하고, 의사소통을 효율화
  • _오랜 시간 검증_된 구조로 설계 시간 단축

1.2. 🧩 종류

  • 생성 패턴: 객체 생성 방식 정의
  • 구조 패턴: 복잡한 시스템 구조 설계
  • 행동 패턴: 메소드 호출 및 알고리즘 설계

2. 🔣 싱글톤 패턴

2.1. 💡 정의

  • ==인스턴스== ==오직 1개만 생성하는 패턴==
  • 메모리 낭비 방지, 전역 객체처럼 사용

2.2. 🛠️ 활용 예시

  • ==스프링 컨테이너==: 객체 관리 시 싱글톤 패턴 사용
  • ==DB 커넥션==: 연결 객체 재사용
  • ==쓰레드 풀==: 쓰레드 생성 비용 절감

2.3. 🧱 생성 방법

  • 이름 초기화 방식
  • 게으른 초기화 방식
  • Holder에 의한 초기화 방식

3. 🏭 팩토리 메소드 패턴

3.1. 🏗️ 정의

  • 객체 생성을 전담하는 ==팩토리 객체==를 사용하는 패턴
  • 객체 생성을 캡슐화하여 결합도 감소

3.2. 🧩 구성 요소

  • ==Creator==: 객체 생성 인터페이스 정의
  • ==ConcreteCreator==: 실제 객체 생성
  • ==Product==: 생성될 객체의 인터페이스 정의

4. 🔌 어댑터 패턴

4.1. 🔄 정의

  • 호환되지 않는 인터페이스를 ==어댑터==를 통해 호환시키는 패턴
  • 기존 코드를 수정 없이 새로운 인터페이스에 적용

4.2. 🧩 활용 예시

  • 외부 라이브러리 통합 시 인터페이스 불일치 해결

5. 🧩 템플릿 메소드 패턴

5.1. 뼈대(템플릿)를 상속하고 확장하는 패턴

  • ==상속==을 통해 부모 클래스의 기능 확장
  • 전체적인 흐름은 고정하고, 일부 단계만 자식 클래스에서 구현

5.2. ⚙️ 활용 예시

  • Java ==AbstractMap 클래스: 맵의 공통 기능을 구현하고, HashMap== ==TreeMap==에서 개별 자료구조에 맞게 구현
graph LR
    A[AbstractMap] --> B(HashMap)
    A --> C(TreeMap)
    style A fill:\#f9f,stroke:#333,stroke-width:2px

대본

[음악] 4 안녕하세요 정보입니다 오늘은 디자인 패턴 시간인데요 디자인 패턴은 어 조금 개념이 어려워요 그래서 5 저와 함께 5가지 질문을 쉽게 이해 하시고 이제 시작을 하면 좀더 수월하게 하실 수 있을 것 같아요 그럼 디자인했던 시작해볼게요 4 오전 첫번째로 디자인 패턴 이에요 디자인 패턴은 디자인 패턴이 뭔지 혹시 면 거니 디자인 패턴이 뭐예요 라고 물어보면 은 우리가 이렇게 대답을 할 수 있다는 거죠 그럼 디자인 패턴 레드 에서는 보면은 디자인 패턴을 즉 과학 5 소프트웨어 개발 과정 해서 뭘 이즈 개발자 선배들이 이렇게 해서 이제 똑같은 여러분 저를 이제 개발 해 왔을 거 아니에요 근데 그 때마다 지어 울어 문제들 이렇게 발생해요 그만 할 쓰는 문제들을 어떻게 해결할 지 그 설계 노하우들을 패턴으로 정해 라구요 그래서 이런 식의 문제가 될 때는 이런 배 컸으면 쉽게 해결할 수 있고 이런식의 문제가 발생했어요 이런 식으로 해결할 수 있다 이런식으로 이런걸 패턴으로 정리 1개 djm 패터닝 그래서 디자인 패턴을 쓰면 크게 두 가지 장점이 있어요 첫번째는 이제 꽃 이 스타일이 비슷해 코드 스타일 비드 왜냐하면 빛 하나의 패턴은 이제 비슷한 포르 유형을 쓰거든요 이렇게 어떤 좋은점이 있냐면 의사소통을 효율적으로 할 수가 있어요 그러니까 보통 제 개발자들이 좀 어려운 게 남은 코드를 읽는 게 생각보다 앉아 어려워요 여기서 익고 늘 왜 썼는지 이해가 잘 안 된단 말이에요 이제 그 코드 리뷰를 할때 그런데 이제 디자인 배짱 을 사용하며 넣고 이 코드의 그렇게 쭉 그 형태가 나오니까 다음엔 어떤 코드가 나오게 떠나 이런 식으로 짐작이 될 수가 있고 그런 의사 소니가 빨라지기 되겠죠 다음은 두 번째는 이제 검증이 되었다는 거에요 그러니까 내가 새롭게 만드려면 은 이게 검증되어 있지 않는거 기 때문에 그 어떤 버그가 발생할 수도 있잖아요 근데 디자인 패턴을 사용하면 은 이미 문제를 겪었던 사람이 그걸 어 쏠 어서 그게 오랜시간 또 검증된 구조이기 때문에 좀 더 빠른게 이제 시간을 아낄 수가 꼭 시간을 아껴서 빠르게 설 을 찍고 개발할 수가 있죠 이런 식의 두 가지 장점이 있구요 그래서 디자인 패턴은 크게 3가지 패턴이 세다 지름 그 로 나뉜 이래요 첫번째는 생성 편이에요 생성 패턴은 이제 개체를 어떻게 생성 알지 그러니까 이런 경우에는 이런 방법을 생 상황 효율적이고 처럼 없는 이런 마음으로 한번 훌쩍 이렇게 개체를 생성하는 생성 패턴 있구요 두번째는 구조 패턴이 있어요 부조 패턴은 어떤 복잡한 상황에서 구조를 이런식으로 하면 은 이제 효과적으로 한샘몰 사용할 수 있다라는 걸 알았다는 게 구조 캐던 이구요 마지막으로 행동할 짱이에요 행동 패턴은 어떤 매수 드에 쏘리 와 관련된 했더니 이젠 도배 턱이 어떤 때는 어떤 메소드를 어떤 식으로 메소드를 사용하면 효과적으로 알 수가 있다 라는것을 된거죠 그래서 그렇게 세 가지 생성 소주 행동 패턴이 인데요 한번 같이 어떻게 되어 있는 볼게요 네 지금 보시면 이렇게 3가지 생성 패턴 생성 후 주행 필통에 힘 빔 패턴 인데요 뭐 많죠 그중에 이제 가장 자주 물어보고 유명 하면 더 많 한번 알아볼게요 이번 시간에는 자 우선 5 이번 시간에 어떤걸 할 거냐 며 는 우선 팩토리 메소드 패턴 싱글턴 패턴 어댑터 패턴 왜 템플 임해서 그때 이렇게 답 네 가지를 알 거에요 네 그래서 이렇게 4가지를 한번 알아볼게요 자 그러면 정리하자면 은 왠 조건이 디자인했던 뭐예요 라고 물어보면 저는 이렇게 나빠져 있어요 디자인 패턴은 과거 소프트웨어 개발 과정에서 발견한 설계도 어를 패턴으로 정리한 것입니다 그래서 범용적인 코드 스타일로 있어서 또 효율적으로 할 수 있구요 그리고 이미 검증된 구조이므로 세계를 빠르게 할 수 있습니다 목적에 따라서 생성 패턴 구조 팩 행복 패턴 으로 나누어지게 됩니다 라고 말하겠어요 그럼 다음 싱글톤 패턴 으로 넘어 갈게요 신갈동 패턴을 인스턴트를 오직 1개만 생성하는 패턴 이에요 자 이게 무슨 말이냐면 a 라는 클래스가 있고 c 라는 클래스가 있고 c 라는 클래스가 있어요 근데 여기서 모두 d 라는 클래스를 필요해 그에게 가까이 이렇게 가져갔어 야 되거든요 자 이런거 코너 어떤 식으로 구성된 여는 여기서 d 는 ud 에서 생성 되고요 여기도 뒤는 이후 이렇게 생성 되고요 여기도 마찬가지 이렇게 생성해 되겠죠 이렇게 되면 어떻게 만드냐 왜 왜냐면은 자 11 라 2 3 섹스가 살리라 했죠 그러니까 지금 메모리에는 개 같은 개체가 신세가 있어요 객체가 살 길이라 사용되고 있는 거에요 만약에 이것들이다 다른 정보 아니면 다른 상어 팩 가지고 있으며 는 이렇게 세 개의 개체를 사용하는 요건 증 없지만 이게 모두 같은 것을 바라보면서 같은 사업회 있다 며 이렇게 문제가 되죠 이렇게 나오미가 되고 있으니까요 그래서 이런 식으로 1개만 생성한 있는 패턴이 식물 똥배 따라 사용하면 어떻게 되냐면 이렇게 각각 쓰는 게 아니고요 뒤 미리 전체 전염병처럼 어디를 하나 만들어 봐요 그 여기서 이렇게 갖다 쓰고 이제 갖다 쓰고 말고 쓰고 빨고 쓴거 말고 이런 식으로 1 이렇게 인스턴스 오직 1개만 생성한 패턴이 싱글톤 패턴 이에요 자 이거 어디서 많이 들어보셨죠 이게 어디서 사용 되냐면 스프링 컨테이너에 서희 컨테이너에서 객체들 관리 하잖아요 이것들이다 기본적으로 이 싱글톤 패턴 으로 사용되고 있어요 그래서 인스 1개만 생성하면 패턴이 싱글톤 매턴 이고 스프링에서 잘 사용되고 있다 라고 자신들이 고요 그리고 이 또 다른 곳을 많이 사용되는 절 두가지를 설명드릴께요 첫 번째는 db 커넥션 이에요 db 커넥션이 뭐냐면 우리 잡아 나눴다는 곳에서 이제 데이터베이스 연결을 할 때 어제 비애를 사용하지 않는다면 어떤 식으로 연기 됐냐 며 는 커넥션 객체를 하나 만들어서 3 데이터베이스와 동시에 했어요 여기서 커넥션 입체감 안 되거든요 근데 이게 어떤 은혜라 있냐면 우리가 db 를 계속 연결하고 유지하고 있지 않잖아요 역률 했다 또 않고 연결 다 끊고 하는데 이 때 마다 커넥션 객체를 계속 만들고 사용을 하면 은 이제 낭비가 되고 다시 문제가 될 수 있겠죠 그렇기 때문에 미리 커넥션 객체를 하나 만들어 줘서 이거를 각자 생산이 아니라 이 때 마다 가져가 쓰는 거에요 그래서 이렇게 db 커넥션 이제 사용될 수도 있구요 두번째는 쓰레드 풀이 에요 스레드 풀 이 뭐냐면 우선 출에 대해서 설명드리면 풀 2 1 개념은 또 수영장을 듯하네요 그래서 술은 미리 여러개를 만들어서 그때마다 사용하고 반납하고 사용하고 반납하고 하는 개념이 풀이 잠 쓰레드 풀은 뭐냐면은 이렇게 여기 안에 쓰레드가 여러개 있겠죠 이걸 왜 사용을 안하면 은 쓰레드를 생성하는 데는 오래 걸려요 시간이 오래 걸리는 말이에요 그러니까 3를 그때가 어떤 작업에서 새로 쓰는 를 생성하려면 너무 오래 걸리니까 미디 만들어 놓고 사용을 하는 거예요 우리 이전 예시에 유튜브 예시를 하더라도 줘 유튜브는 이렇게 시 링이 계속되는 쓰레드가 하나 있고 여기 좋아요 를 누르면 은 이 서버에 보내는 쓸 때는 하나 있다고 첨부 많이 쓰잖아요 이때 많이 우리가 생활하고 있는데 좋아 룰을 눌렀어요 그럼 이때 새로운 쓰레드가 이제 애정 받게 돼야 되는데 뭐 그때 샌들을 생성을 하게 되면 좋아요와 관계로 능 기계 되잖아요 그렇기 때문에 미리 생성해 던 쓰레드 해서 이걸 여기 할당하고 여기 삶을 하고 강남 한계 쓰이는 뿌리의 그래서 쓰레드 풀이 라는 객체가 이제 또 필요할 거 아니야 이렇게 쓰레드 l 후 를 만들어서 관리하는 내가 이 좋아요 를 누르면 어떤 일이 발생 해야 되냐면 은 었을 때 풀을 가져와서 거기서 술들을 1 앞에 와야 되는데 이 쓴소리 그때마다 생성되면 베일 비효율적이고 의미 없잖아요 그렇기 때문에 식물 또 로 패턴으로 미리 있어 에도 불안 생성해서 그 이렇게 쓰 멀티스레드 다른 쓰레드가 필요할 때마다 가져다가 이제 사용 오라고 달라고 하는 거죠 이런식으로 크게 db 커넥션이 낫을 f 에서 사용해 되구요 신갈동 패턴을 생성하는 방법 그니까 이런 인스턴스를 1 인스턴스 를 1개만 생성하는 방법이 크게 세 졸 가 있어요 첫번째는 이름 초기화 방식 이 두 번째는 게으른 초기화 광 칙 마지막은 폴더 에 의한 초기에 방식 되거든요 이거는 한번 내용을 찾아 보시고 쭉 읽어보세요 그래서 어떤 개념이지만 이제 알고 아야 2시면 됩니다 자 그래 정리를 하자면 어 레노버의 싱글톤 패턴 이 뭐냐고 물어보면 은 뭐 저희 이렇게 대답했어요 싱글톤 패턴은 인스턴스를 오직 한 개만 생성하는 베타 입니다 et 예를 들면 db 커넥션이 너스 렌트 풀 객체를 사용할 때 사용합니다 만드는 방법으로는 일은 쪼개 방 시에 교회는 좀 양식들이 홍도 이러한 초기의 방식이 있습니다 고대 다 빠지면 되겠습니다 다음은 팩토리 패턴 인데요 팩토리 블 또는 개체를 직접 3 삼성 하지 않고 개체를 생성하는 팩토리 객체 팩토리 개체를 사용하는 패턴이라 패턴 이에요 자 예를 들면 은 내가 어 어떤 건 설사 클래스를 가지고 있다고 쳤어요 건설사에서 이제 건물 짓기 라는 메소드를 실행을 하면 어떻게 이 건물이 생성된다 고쳐 볼게요 근데 이게 건물 이 처음에 이렇게 잘 동작 했거든요 근데 이게 yo 2 이제 명령에 떨어졌어요 이 건물을 어 건물을 아시아 스타일의 건물과 유럽 스타일의 건물을 만들어요 그러면 이제 여기서는 여기 로서는 아시아 스타일 건물로 바꾸고 이것을 아시아 건설사로 해요 그리고 여기서는 어유 니 일어 건설 따로 새로운 클래스를 만드는 거죠 그리고 여기서는 유럽 건물을 짓는 거죠 이렇게 되면 어떤 문제가 발생해 괜 여 면 뭐 내가 이런 건설 사흘 이제 가져와서 이제 내가 함수에서 사용할 거 아니에요 내가 예를 들면 은 어 유럽권 설사를 지금 승리로 꿈을 만들기 위해서 유럽 업무를 별로 꽃물 안 변수는 1호 건설사에서 짓기 라는 메소드를 통해서 1호 건물을 가져간다고 차우 볼게요 그러면은 이유로 없거든 사에서 1억 봄을 가져오게 되죠 근데 만약에 코드가 수정 해야 되요 아까 그 움직이 받게 돼요 이런 건설 딸을 아시아 업무를 바쁘게 써요 여기 아시아로 바꿔 줘야 되고 여기가 아시아로 봤구요 그쵸 자 그럼 어떤 문제 바뀐 생각 생기냐 하면 이렇게 기존의 이르러 건설사로 사용되었던 부분이 모두 아시아로 바뀌어야 되는 거잖아요 그러면은 이것들을 찾아서 다 여기를 아시아 로 바꿔줘야 4 아시아 샤샤 작품의 2기 조금 있으면 괜찮은데 여러 개 있으면 은 너무 오래 걸리고 또 여기서 사람이다 보니까 실수 할 수 있는 가능성이 있잖아요 그렇기 때문에 사용하는 게 뭐냐면 우리 스프링에서 배웠던 어 디펜더는 c 인젝션 이에요 이 펜더 시 인젝션 해서 미리 건설 싸는 건설사는 아시아 다 이런식으로 이런 식을 영구 연결 공개를 치며 는 이렇게 건설 따로 사용되는 것은 모두 아시아 가도록 하게 되요 이게 키핑 너 cdi 이거든요 그러니까 유럽을 놓지 말고 건설사 라는 것을 사용해서 이렇게 각각 갔다 이제 건설사를 사용하는 부분이 모두 이 아시아 들어왔네요 그러니까 이 아시야 이 건설사 라는 도 인터페이스가 필요하잖아요 그래서 여기에 건 설사 라는 인터페이스 로 이렇게 값싸게 클래스를 이제 반 되는 거죠 그럼 내는 나는 건설사 라는 인터페이스가 가지고도 이제 여러개의 가까이 예 건설사 라는 인터페이스를 가지고 도 이제 코드를 작성할 수 있고 그 di 를 통해서 쉽게 변경을 해도 밴 5초 그럴 때 이제 추가적인 코드를 수정하지 않아도 되구요 그래서 이렇게 되면 이제 이게 결을 낮춰주는 효과가 있어요 결어 또 나는 거는 따른 코드의 이제 의존 아오 변화 할 할 수 있는걸 어렵게 만드는게 결합 되거든요 그래서 이렇게 결합도 를 낮춰 주게 되구요 어 2 여기서 이제 만 말하는 이제 개체들은 이 주체들이 되겠고 개체를 생성하는 팩토리 들은 이렇게 아시아 건 털사 유럽권 살짝 안되겠죠 그걸 가까 찍는 방법은 이 아시아 건 젖산은 아시아 느낌대로 1호 뻔 설사는 이유로 건설사 대로 이루어 지고 가까이 이 객체를 만드는 것이 구현이 되겟죠 자기 가시나요 자 그럼 팩토리 메소드를 정리를 해볼게요 만약에 원조 까미 팩토리 메소드가 뭐예요 라고 볼 없는 저는 객체를 직접 생성하지 않고 객체를 생성하는 팩토리 빛을 만 사용하는 패턴입니다 작품 점으로는 직접 갱 채를 직접 객체를 생성하는 것을 막아줘서 결합도 를 낮춰주는 효과가 있습니다 라고 배가 겠어요 자 이렇게 이해 되시나요 조금 복잡하죠 머를 떠 래도 한번 돌려 보면서 다시 한번 이해를 해 버려 도록 하세요 자 그러면은 잠깐 제 팩토링 메소드가 어떤 식으로 구성이 되어 있는지 알아볼게요 이 계 획 털이 메소드의 정의의 있네요 흐 통해서 등 아까 우리가 봤던 크리에이터는 건설 싸 우 였구요 이거 콘크리트 구조의 이터 구체적인 크리에이터 라는 거죠 이것은 뭘까요 유럽권 설사 어 그리고 아시아 설사가 되겠죠 그 이거는 이제 건물이 되겠구요 그래서 크리에이터 에서 바로 건물내 생성하는 게 아니라 콘크리트 크리스털을 사용해서 여기서 프로덕트 를 만들어 내는 거에요 그런데 왜 사용하려면 이 각각의 건물 만드는 방법이 다르게 사용될 수 있기 때문에 그래서 여기서 이렇게 만드는 거에요 여기는 인터페이스로 입에 쏘 들을 어떤 식으로 메소드를 만들어야 된다 이렇게 강제 만 해 놓았고 이 주체적인 메소드가 생 수행되는 그 코드들은 2 콘크리트 크리에이터 에서 정의가 되게 되겠죠 네 그래서 이렇게 팩토리 메소드를 알아 봤구요 내가 어댑터 패턴 께요 어뎁터 끝은 은어 데이터를 사용해서 호환되지 않는 인터페이스를 보완하도록 가능 자 이게 무슨 말일까요 모든 말이냐면 은 자 우리 가까이로 뻔 설사 위로 건설 쌀을 사용하고 아시아 번 설사를 사용 한다고 했잖아요 그래서 이건 얼 싸 이걸 받아서 이렇게 사용을 한다고 했잖아요 근데 이렇게 하려고 하다보니까 이미 외부의 유로 번 설사를 만들어 놓고 코드가 있는 거에요 그러면 우리는 그냥 그것을 가져다 쓰면 되는 거죠 그래서 외국 라이브러리를 사용할 거에요 근데 또 까 보니까 외부 라이 몰래 유로 껀 설사와 아시아 번 싹 각각 외무 라이브를 가지고 왔는데 영이는 빌트 라는 메소드로 건물을 짓고 여기는 메이크 라는 메소드로 건물을 짓네요 그런데 건설사 에서는 이 하나의 메소드를 통해서 이 비결 다 관리하고 싶은데 5 입힐 트와 매스 크를 사용을 하는 거죠 그러면 여기에서 빌트 를 사용하자 니 까 아시아를 사용할 수도 없고 메이크 사용 하자니 여기를 사용할 수 없는 거에요 이렇게 두개가 호환되지 않는 경우에는 어떻게 하냐면 이 가운데 에다가 가운데 새로운 어뎁터를 만들게요 입니다 어댑터 그래서 어댑터 를 사용해서 건설사에서 이유로 얹어 싸 를 사용할 때는 이 빌드를 사용하고 2 이 아시아 번 쌀 사용할 때는 이 메 이 크 를 사용하는 거죠 그러면은 이 어댑터 어떻게 되냐면 은 어 그게 유럽 어댑터가 있고 어 돼 그리고 아시아 어댑터가 있겠죠 그래서 여기에서는 어 여기에서는 어두 라는 메소드를 실행을 하면 은 유럽 건설 싸이의 빌트 를 실행하게 만들고 그리고 여기서도 주라고 하면 은 아시아의 메이 글을 만들어 라고 이렇게 정리를 하죠 으 건설사 에서는 어댑터의 2 라는 메소드를 실행을 만하면 은 2556 유 러브 일 경우에는 이 비트를 사용되고 아시아의 경우에는 케이크를 사용하게 되죠 자 그래서 여기 또 di 에다가 어댑터는 유럽으로 아더가 아니면 아시아로 하더라 아시아라이 연결 조금만 정의를 하면은 이어 데 터라 인터페이스를 상속받는 이 유럽과 아시아가 자동으로 결정되고 그럼 거기서 는 외부 라이브러리를 사용 쉽게 사용할 수 있게 되죠 이런식으로 호환되지 않는 인터페이스를 호 안에서 사용하는 도로 1회당 2 어딜 더 패턴이 어디 이해가 가시나요 자 그럼 정리하자면 어댑터 패자는 어댑터 를 사용해서 호환되지 않는 인터페이스를 보완하도록 하는 패턴 이에요 향후 의 인터페이스가 바뀐 올해도 병 논의 내용이 이 어뎁터 안에 이 어댑터 안에 특히 여기 구현해 주는 것 여기에서 캡슐이 병원 뱀으로 수정할 필요가 없습니다 라고 대답을 하겠어요 자 그럼 넘어갈게요 다음은 캠 빨리 패턴 이에요 템플릿 패턴이 뭐냐면 샘플링 패턴은 이제 상속을 통해서 부모의 기능을 확장할 때 사용하는 방법이에요 자 형장 할 때 확장할 때 사용하는 방법인데요 작가라 비슷한 예시를 괴롭게 요 또 건설사 얘긴데요 유로 건 설사 바 있구요 그리고 아시아 건설사가 있다 고쳐 볼게요 근데 유럽과 아시아 늘 전체적인 프로세스는 또 컸거든요 그래서 어 준비 란 계와 어 그리고 세우기를 단계 라 똑같이 또 가 되어야 주민이 세우기 근데 각각의 유럽 스타일의 준비하는 법과 아시아의 준비한 밥이 다 다르고요 여기도 세운 마음이 달라요 근데 공통적인 것은 어 건물 짓기 라는걸 사용하면 은 준비를 한 다음에 세우기 하는것은 똑같아요 아시아 도 마찬가지로 빚기 와서는 준비 세우기 이런식으로 프로세스가 프로세스는 이제 동일한데 각각 2 3부 과정이 다른 뭐예요 지금 이런 어떻게 해야 면은 이 공통된 기능들이 지금 2번 세워지고 있잖아요 자의 일없는 이렇게 개발자들에게 코드가 중복되는 걸 안 좋아하거든요 이런 어떤 문제가 않냐며 는 유럽 아시아 아프리카 새로 생기면 어떻게 되어 아마 지키는 똑같은 프로세스의 이루어지면 똑같이 그거를 좀 정리를 해줘야 되죠 근데 많이 실수 알면은 또 여기서 문제가 또 발생할 수 있고 버그가 또 하나 생길 수 있구요 그렇기 때문에 이렇게 최대의 코드를 줄이는 걸 좋아해요 1월 어떻게 하냐며 는 e 클래스 와 이 클래스 는 이제 부모 클래스를 하나 만드는 부모 클래스를 만들어서 어 건물 이라는 클래스를 만들고 어 준비와 세우기 라는 것은 너네 상속받은 애들이 알아서 구현해 근데 나는 집기 이라는 프로세스는 정의를 해 두겠어 너는 이걸 꼭 따라 에 따라야 돼요 어차피 다르고 있으니까 준비와 세우기 라는 프로세스를 따를 거야 그러면 어떻게 되면 이 밑에서 기존의 유럽과 아시아에서 10길 했던게 여기가 위미 없어지게 되죠 얘기를 어이가 없어 지게 되고 j 위에서 선언을 하게 됐고 이 유럽과 아시아는 가까 준비한 방법 세우는 방법과 1 즉 다르게 정리를 하면 되는 거죠 이렇게 상황 풀 통해서 부모 클래스의 기념 이 준비와 세우기를 이 확장할 때 사용하는 방법이 템플릿 메소드 라는 패터닝 2 자 이제 5 어디에서 많이 사용되며 자 말에서 1 특히 많이 사용되는 것이 엑스트렉 탭 이에요 매미 라는 것은 어떤 길을 통해서 배율을 얻는 자료 구조가 맵 이잖아요 그래서 이거를 크게 활용하는 것이 이걸 구현된 것이 패 심을 미 있구요 그리고 트림 앱이 있어요 자 헬시 맵은 그해 c 자료구조 를 사용해서 매번 불어난 거구요 트릭 메우는 그 이신 탐색 들을 사용해서 앱을 구해야 할 거에요 여기 위에 어 x 틸트 대위 라는 어이 추상 클래스가 있거든요 여기에서는 이 해쉬 맵과 트림 ma 공통적인 부분을 구현을 해 줘요 근데 싱 아까 트리 맵이 자리 구조가 달라서 이제 코드가 변경되는 부분을 영이 안에서 부연 해줬구요 그래 이 교회에서 es 트렉 트 맵이 이 템플릿 메소드 패턴 의 가장 대표적인 2 웰본 되면은 뭐 자료 구도에서 해시 타의 매매에서 개시 라는 메소드가 있죠 게시 라는 메소드를 어떤 키 값에 있는 밸류를 가져오는 것이 이제 계시잖아요 이게 슨 제 실행했을 때 그 자료 구조의 들어가서 그 값을 꺼내 오는데 햇수로 와 트리를 각각 모직 이 다를 거 아니에요 그렇기 때문에 이 개성 여기서 각각 구현을 해 주는 거죠 그치만 전체적인 이 공통적인 맵 이어서 갖고 있는 공통적인 부분은 얘 유튜브 앱에서 가 어구를 해준다 라고 이해하시면 되겠어요 자 정리하자면 면접관이 캠페인 메소드 패턴 이 뭐예요 라고 물어보면 저는 맥 캠벨 웨스트 패턴은 상속을 통해서 그 부모 클래스의 기능을 확장할 때 사용하는 2번입니다 부모 플러스에서 변하지 않는 기능을 쯤 해두고 뭐 자식 클래스에서 확장한 기능을 구현하게 됩니다 자바에서는 추상 클래스를 사용해서 뿐 양악 하는데요 대표적으로 x title 있습니다 lsl 맵은 s 트랩 에서 공통된 기능을 정리하고 이상석 빠는 해시 맵이나 트리 면에서 가 깔려 자리 구조에 맞게 개인 메소드를 다르게 들어가게 됩니다 라고 대답했어요 4 이렇게 어택 매수호가 지 알아 봤구요 어요 그렇게 이렇게 5가지 디자인 패턴 질문들 알아봤어요 디자인 패턴은 어 쪼끔 이해하기가 처음엔 힘들어요 그래서 이렇게 가장 많이 나온 급여 까지 질문들은 이제 빠삭하게 이렇게 준비를 해서 개 답을 할 준비를 해주시면 되요 너무 많이 나오지도 않지만 엄 연접 에서 전후 안나오는 질문도 아니거든요 그렇기 때문에 이렇게까지 준비해주시면 되겠습니다 그럼 오늘은 여기서 마칠께요 안녕