패스잇

CS 기초

디자인 패턴 면접 질문

싱글톤, 팩토리, 전략, 옵저버, 데코레이터 — 디자인 패턴 면접은 패턴 이름을 넘어 "어떤 문제를 풀기 위한 것인가"를 묻습니다. 각 패턴의 의도와 트레이드오프를 모범답안으로 정리했습니다.

총 21문제 · 기초 7 · 중급 7 · 심화 7 · 모범답안 포함

디자인 패턴 면접 질문 — 기초

Q1 기초

소프트웨어 개발에서 디자인 패턴(Design Pattern)이 무엇인지 설명하고, 이를 사용하는 주된 목적은 무엇인가요?

힌트 · 디자인 패턴은 특정 문제에 대한 검증된 해결책을 템플릿화한 것이며, 재사용성, 유지보수성, 확장성 향상이 주 목적입니다.

디자인 패턴은 소프트웨어 개발에서 반복적으로 발생하는 문제에 대한 검증된 해결책을 템플릿 형태로 제공하는 것입니다. 일종의 설계 아이디어 모음이라고 생각하시면 됩니다.

전체 모범답안 펼치기

디자인 패턴은 소프트웨어 개발에서 반복적으로 발생하는 문제에 대한 검증된 해결책을 템플릿 형태로 제공하는 것입니다. 일종의 설계 아이디어 모음이라고 생각하시면 됩니다.

디자인 패턴을 사용하는 주된 목적은 코드의 재사용성을 높이고, 유지보수를 용이하게 하며, 시스템의 확장성을 향상시키는 데 있습니다. 또한, 객체 지향 설계 원칙을 준수하여 코드의 결합도를 낮추고 응집도를 높이는 데에도 도움이 됩니다.

예를 들어, 객체 생성 과정을 캡슐화하는 팩토리 패턴을 사용하면 객체 생성 로직 변경 시 다른 코드에 미치는 영향을 최소화할 수 있습니다.

#재사용성#유지보수성#확장성#결합도 감소#객체지향 설계

이 질문 단독 페이지 →

Q2 기초

싱글톤(Singleton) 패턴은 어떤 상황에서 사용하기 적합하며, 이 패턴을 구현할 때 주의해야 할 점은 무엇인가요?

힌트 · 싱글톤은 전역적으로 단 하나의 인스턴스만 존재해야 할 때 사용합니다. 멀티스레드 환경에서의 동기화 문제와 의존성 주입의 어려움을 고려해야 합니다.

싱글톤 패턴은 애플리케이션 내에서 특정 클래스의 인스턴스가 오직 하나만 존재해야 하고, 어디서든 그 인스턴스에 접근할 수 있도록 해야 할 때 유용합니다. 예를 들어, 환경 설정 정보 관리, 로깅, 데이터베이스 연결…

전체 모범답안 펼치기

싱글톤 패턴은 애플리케이션 내에서 특정 클래스의 인스턴스가 오직 하나만 존재해야 하고, 어디서든 그 인스턴스에 접근할 수 있도록 해야 할 때 유용합니다. 예를 들어, 환경 설정 정보 관리, 로깅, 데이터베이스 연결 풀 관리 등에 활용될 수 있습니다.

구현 시 가장 중요한 점은 멀티스레드 환경에서의 동시성 문제입니다. 여러 스레드가 동시에 싱글톤 인스턴스를 생성하려고 시도할 경우, 의도치 않게 여러 개의 인스턴스가 생성될 수 있습니다. 이를 방지하기 위해 synchronized 키워드를 사용하거나, 이른 초기화(eager initialization) 방식을 사용하여 스레드 안전성을 확보해야 합니다.

또 다른 주의점은 싱글톤이 전역 상태를 가지게 되면서 다른 클래스와의 결합도가 높아질 수 있다는 점입니다. 이는 테스트를 어렵게 만들고, 코드의 유연성을 떨어뜨릴 수 있습니다. 따라서 싱글톤 사용을 최소화하고, 의존성 주입 등의 다른 디자인 패턴을 고려하는 것이 좋습니다.

#단일 인스턴스#전역 접근점#상태 유지#동시성 문제#지연 초기화

이 질문 단독 페이지 →

Q3 기초

팩토리 메서드(Factory Method) 패턴은 언제 사용하며, 이 패턴을 적용했을 때 얻을 수 있는 장점은 무엇인가요?

힌트 · 객체 생성 로직을 서브클래스에 위임하여 결합도를 낮추고, 새로운 객체 타입 추가 시 기존 코드를 수정하지 않도록 합니다. OCP를 준수하는 데 도움이 됩니다.

팩토리 메서드 패턴은 객체 생성 로직을 직접 수행하는 대신, 서브클래스에서 객체 생성을 담당하도록 위임할 때 사용합니다.

전체 모범답안 펼치기

팩토리 메서드 패턴은 객체 생성 로직을 직접 수행하는 대신, 서브클래스에서 객체 생성을 담당하도록 위임할 때 사용합니다.

이 패턴을 적용하면 객체 생성과 사용 코드가 분리되어 결합도가 낮아집니다. 따라서 새로운 객체 타입을 추가하더라도 기존 코드를 수정할 필요 없이, 새로운 서브클래스만 추가하면 됩니다. 이는 OCP(개방-폐쇄 원칙)를 준수하는 데 도움이 됩니다.

예를 들어, 다양한 데이터베이스 연결 객체를 생성해야 할 때, 각 데이터베이스 종류에 따라 팩토리 메서드를 구현한 서브클래스를 만들 수 있습니다. 이렇게 하면 데이터베이스 종류가 추가되어도 기존 코드를 변경하지 않고 확장할 수 있습니다.

#객체 생성#결합도 감소#유연성#확장성#OCP (개방-폐쇄 원칙)

이 질문 단독 페이지 →

Q4 기초

추상 팩토리(Abstract Factory) 패턴은 팩토리 메서드 패턴과 어떻게 다르며, 어떤 종류의 문제를 해결하는 데 효과적인가요?

힌트 · 추상 팩토리는 관련 있는 객체들의 '군(family)'을 묶어서 생성할 때 사용하며, 팩토리 메서드는 단일 객체 생성을 담당하는 반면, 추상 팩토리는 여러 팩토리를 묶는 상위 개념입니다.

추상 팩토리 패턴과 팩토리 메서드 패턴의 가장 큰 차이점은 '생성하는 객체의 범위'입니다. 팩토리 메서드는 단일 종류의 객체를 생성하는 데 집중하는 반면, 추상 팩토리는 '관련 있는 객체들의 집합', 즉 제품군을 생…

전체 모범답안 펼치기

추상 팩토리 패턴과 팩토리 메서드 패턴의 가장 큰 차이점은 '생성하는 객체의 범위'입니다. 팩토리 메서드는 단일 종류의 객체를 생성하는 데 집중하는 반면, 추상 팩토리는 '관련 있는 객체들의 집합', 즉 제품군을 생성하는 데 사용됩니다.

추상 팩토리는 여러 팩토리 메서드를 묶어놓은 상위 개념이라고 볼 수 있습니다. 예를 들어, GUI 애플리케이션에서 Windows 테마와 macOS 테마를 각각 지원해야 할 때, 추상 팩토리를 사용하면 버튼, 창, 스크롤바 등 각 테마에 맞는 관련 객체들을 일관성 있게 생성할 수 있습니다.

이 패턴은 특정 제품군에 대한 클라이언트 코드를 해당 구현체로부터 분리하여, 시스템이 여러 제품군을 쉽게 전환하거나 새로운 제품군을 추가할 수 있도록 할 때 매우 효과적입니다. 즉, 구현의 독립성을 높이고 유연성을 확보하는 데 강점이 있습니다.

#객체 생성#관련 객체#인터페이스#구현 분리#제품군

이 질문 단독 페이지 →

Q5 기초

빌더(Builder) 패턴은 복잡한 객체를 생성할 때 어떤 이점을 제공하며, 일반적인 생성자(Constructor) 방식과 비교했을 때의 차이점은 무엇인가요?

힌트 · 빌더 패턴은 복잡한 객체의 생성 과정을 여러 단계로 나누어 가독성을 높이고, 필수 인자와 선택 인자의 조합이 많을 때 유용합니다. 생성자 오버로딩의 단점을 보완합니다.

빌더 패턴은 복잡한 객체를 생성할 때 유용합니다. 특히 필수 인자와 선택적 인자가 많아 생성자 오버로딩이 복잡해지는 경우에 효과적입니다.

전체 모범답안 펼치기

빌더 패턴은 복잡한 객체를 생성할 때 유용합니다. 특히 필수 인자와 선택적 인자가 많아 생성자 오버로딩이 복잡해지는 경우에 효과적입니다.

일반적인 생성자 방식은 객체 생성 시 모든 인자를 한 번에 전달해야 하지만, 빌더 패턴은 단계별로 필요한 인자만 설정하고 최종적으로 객체를 생성할 수 있습니다. 이를 통해 코드 가독성을 높이고, 객체의 불변성을 유지하기 용이합니다.

예를 들어, 자동차 객체를 생성할 때 엔진, 타이어, 색상 등 다양한 옵션을 빌더를 통해 설정하고, 필요한 옵션만 선택적으로 설정하여 자동차 객체를 만들 수 있습니다. 이렇게 하면 생성자 오버로딩으로 인한 복잡성을 줄이고 유연하게 객체를 생성할 수 있습니다.

#불변객체#가변성#단계별_생성#유연성#가독성

이 질문 단독 페이지 →

Q6 기초

스트래티지(Strategy) 패턴은 다양한 알고리즘을 유연하게 교체해야 할 때 어떻게 활용될 수 있는지 설명해주세요.

힌트 · 알고리즘 군을 정의하고 각각을 캡슐화하여 서로 교환 가능하게 만듭니다. 런타임에 클라이언트가 특정 알고리즘을 선택하여 사용할 수 있도록 합니다.

스트래티지 패턴은 여러 알고리즘을 상황에 따라 유연하게 바꿔 써야 할 때 유용합니다. 핵심은 알고리즘들을 각각 독립적인 클래스로 캡슐화하고, 이 클래스들이 동일한 인터페이스를 구현하도록 하는 겁니다.

전체 모범답안 펼치기

스트래티지 패턴은 여러 알고리즘을 상황에 따라 유연하게 바꿔 써야 할 때 유용합니다. 핵심은 알고리즘들을 각각 독립적인 클래스로 캡슐화하고, 이 클래스들이 동일한 인터페이스를 구현하도록 하는 겁니다.

예를 들어, 이미지 압축 프로그램을 만든다고 가정해 볼게요. 압축 방식에는 JPEG, PNG, GIF 등 여러 가지가 있을 수 있습니다. 스트래티지 패턴을 사용하면 각 압축 알고리즘을 별도의 클래스로 만들고, 압축 방식을 선택하는 코드를 런타임에 결정할 수 있습니다.

클라이언트는 구체적인 알고리즘 대신 인터페이스를 통해 압축 기능을 사용하므로, 새로운 압축 알고리즘이 추가되거나 기존 알고리즘이 변경되어도 클라이언트 코드를 수정할 필요가 없어집니다. 이렇게 알고리즘을 캡슐화하고 교체 가능하게 만들어서 코드의 유연성과 확장성을 높일 수 있습니다.

#알고리즘 교체#캡슐화#Context#인터페이스#유연성

이 질문 단독 페이지 →

Q7 기초

옵저버(Observer) 패턴은 객체 간의 일대다 의존성을 어떻게 관리하며, 주로 어떤 시스템에서 효과적으로 사용될 수 있나요?

힌트 · 주체(Subject)의 상태 변화를 관찰자(Observer)들에게 자동으로 알리는 방식으로, 느슨한 결합을 통해 상태 변화에 따른 업데이트를 효율적으로 처리합니다. UI 이벤트, 분산 시스템 알림 등에 활용됩니다.

옵저버 패턴은 주체(Subject) 객체의 상태 변화를 여러 관찰자(Observer) 객체들에게 자동으로 알리는 방식으로 일대다 의존성을 관리합니다. 주체는 관찰자 목록을 유지하며, 상태가 변경될 때마다 등록된 모든…

전체 모범답안 펼치기

옵저버 패턴은 주체(Subject) 객체의 상태 변화를 여러 관찰자(Observer) 객체들에게 자동으로 알리는 방식으로 일대다 의존성을 관리합니다. 주체는 관찰자 목록을 유지하며, 상태가 변경될 때마다 등록된 모든 관찰자에게 이를 통지합니다. 관찰자들은 이 통지를 받아 자신의 상태를 업데이트하거나 필요한 작업을 수행합니다.

이 패턴은 주체와 관찰자 간의 느슨한 결합을 제공하여, 주체의 변경이 관찰자들에게 직접적인 영향을 주지 않으면서도 상태 변화에 효율적으로 대응할 수 있게 합니다.

주로 이벤트 기반 시스템에서 효과적으로 사용됩니다. 예를 들어, 사용자 인터페이스(UI)에서 버튼 클릭이나 데이터 변경과 같은 이벤트가 발생했을 때, 해당 이벤트를 구독하는 여러 컴포넌트들에게 알림을 보내 업데이트하는 경우에 유용합니다. 또한, 분산 시스템에서 특정 서비스의 상태 변화를 여러 다른 서비스에 알리거나, 실시간 데이터 스트림을 처리하는 시스템 등에서도 널리 활용됩니다.

#일대다 의존성#주체(Subject)#관찰자(Observer)#상태 변화#이벤트 기반 시스템

이 질문 단독 페이지 →

읽기만으론 부족합니다 — 직접 말해보세요

패스잇 앱에서 디자인 패턴 질문에 직접 답하면 AI가 1:1로 답변을 코칭합니다.

디자인 패턴 면접 질문 — 중급

Q8 중급

실무에서 Singleton 패턴을 사용할 때 발생할 수 있는 문제점(예: 테스트 용이성, 멀티스레딩 환경)과 이를 해결하기 위한 방법에 대해 설명해 주세요.

힌트 · 전역 상태 관리, 의존성 주입(DI), Double-Checked Locking 또는 Enum을 통한 구현을 고려해야 합니다.

Singleton 패턴은 전역적으로 유일한 인스턴스를 제공하여 편리하지만, 몇 가지 문제점을 야기할 수 있습니다.

전체 모범답안 펼치기

Singleton 패턴은 전역적으로 유일한 인스턴스를 제공하여 편리하지만, 몇 가지 문제점을 야기할 수 있습니다.

첫째, 전역 상태를 가지므로 테스트 격리가 어렵습니다. 각 테스트가 독립적으로 실행되어야 하는데, Singleton 인스턴스의 상태가 공유되면 예상치 못한 테스트 실패가 발생할 수 있습니다. 이를 해결하기 위해 인터페이스를 통해 Singleton 인스턴스에 접근하고, 테스트 시에는 Mock 객체를 주입하여 의존성을 분리할 수 있습니다.

둘째, 멀티스레딩 환경에서 동기화 문제가 발생할 수 있습니다. 여러 스레드가 동시에 Singleton 인스턴스를 생성하려고 하면, 인스턴스가 여러 개 생성될 위험이 있습니다. 이를 해결하기 위해 Double-Checked Locking이나 Enum을 사용하여 스레드 안전하게 Singleton을 구현할 수 있습니다. 예를 들어, private static volatile Singleton instance; 와 같이 volatile 키워드를 사용하여 instance 변수의 가시성을 확보하고, synchronized 블록을 통해 동기화를 제어할 수 있습니다.

#전역_상태#테스트_격리#멀티스레딩#동기화#DI(의존성_주입)

이 질문 단독 페이지 →

Q9 중급

Factory Method 패턴과 Abstract Factory 패턴은 모두 객체 생성을 추상화하지만, 목적과 적용 방식에 차이가 있습니다. 두 패턴의 주요 차이점을 설명하고, 각각 어떤 상황에 더 적합한지 구체적인 예시를 들어 비교해 주세요.

힌트 · Factory Method는 단일 제품 계층을, Abstract Factory는 여러 제품군을 생성하는 데 초점을 맞춥니다.

Factory Method와 Abstract Factory 패턴은 모두 객체 생성 로직을 캡슐화하여 클라이언트 코드로부터 분리하는 역할을 합니다.

전체 모범답안 펼치기

Factory Method와 Abstract Factory 패턴은 모두 객체 생성 로직을 캡슐화하여 클라이언트 코드로부터 분리하는 역할을 합니다.

Factory Method는 객체 생성 책임을 서브클래스에게 위임하여, 팩토리 클래스를 상속받은 서브클래스에서 어떤 객체를 생성할지 결정합니다. 이는 단일 제품 계층 구조에서 유연성을 확보할 때 유용합니다. 예를 들어, Button 인터페이스를 정의하고, WindowsButton, MacOSButton 클래스가 이를 구현할 때, 운영체제에 따라 다른 버튼 객체를 생성하는 팩토리를 만들 수 있습니다.

반면, Abstract Factory는 서로 관련 있는 객체들의 군(Family)을 생성하는 인터페이스를 제공합니다. 이는 여러 제품군을 일관성 있게 생성해야 할 때 적합합니다. 예를 들어, GUI 애플리케이션에서 Button, TextField 등의 UI 컴포넌트들을 Windows 스타일과 MacOS 스타일로 제공해야 할 때, 각 스타일별 팩토리를 만들어 사용할 수 있습니다.

핵심적인 차이는 Factory Method는 단일 객체 생성에 집중하고, Abstract Factory는 관련 객체들의 집합을 생성한다는 점입니다.

#생성 책임 위임#객체 군(Family) 생성#구현 분리#확장성#유연성

이 질문 단독 페이지 →

Q10 중급

시스템의 특정 동작 방식을 런타임에 유연하게 변경해야 하는 요구사항이 있을 때, Strategy 패턴을 어떻게 적용할 수 있는지 설명하고, 이 패턴이 가져다주는 장점과 단점을 함께 설명해 주세요.

힌트 · 알고리즘군을 캡슐화하고 교환 가능하게 만듭니다. Context와 Strategy 인터페이스의 역할을 중심으로 설명하세요.

시스템의 특정 동작 방식을 런타임에 유연하게 변경해야 할 때, Strategy 패턴을 적용하면 매우 효과적입니다. 이 패턴은 알고리즘군을 캡슐화하고, 이들을 서로 바꿔 사용할 수 있도록 합니다.

전체 모범답안 펼치기

시스템의 특정 동작 방식을 런타임에 유연하게 변경해야 할 때, Strategy 패턴을 적용하면 매우 효과적입니다. 이 패턴은 알고리즘군을 캡슐화하고, 이들을 서로 바꿔 사용할 수 있도록 합니다.

핵심은 두 가지 구성 요소입니다. 첫째, Context는 변경될 동작을 수행하는 객체이며, 실제 알고리즘은 직접 구현하지 않고 Strategy 인터페이스를 통해 위임합니다. 둘째, Strategy 인터페이스는 모든 구체적인 알고리즘이 구현해야 하는 공통 메서드를 정의합니다. 그리고 각 구체적인 Strategy 클래스는 특정 알고리즘을 구현합니다.

Context는 런타임에 어떤 Strategy 객체를 사용할지 결정하고, 해당 Strategy 객체의 메서드를 호출하여 동작을 수행합니다. 이를 통해 클라이언트는 Context 객체의 내부 구현을 알 필요 없이, 원하는 알고리즘을 선택하여 적용할 수 있습니다.

Strategy 패턴의 가장 큰 장점은 **OCP(개방-폐쇄 원칙)**를 잘 만족시킨다는 점입니다. 새로운 알고리즘을 추가하거나 기존 알고리즘을 수정할 때, 기존 Context 코드나 다른 Strategy 클래스를 변경할 필요 없이 새로운 Strategy 클래스만 추가하면 됩니다. 이는 런타임 유연성을 극대화하며, 코드의 확장성과 유지보수성을 크게 향상시킵니다.

하지만 단점도 있습니다. Strategy 패턴을 적용하기 위해 인터페이스와 여러 구체 클래스를 생성해야 하므로, 클래스 수가 늘어나 코드 복잡성이 증가할 수 있습니다. 또한, 클라이언트가 어떤 Strategy를 선택해야 할지 알아야 하므로, 클라이언트 코드에 대한 이해가 필요할 수 있습니다.

#알고리즘 교체#Context#캡슐화#OCP (개방-폐쇄 원칙)#런타임 유연성

이 질문 단독 페이지 →

Q11 중급

비동기적으로 발생하는 이벤트에 대해 여러 컴포넌트가 독립적으로 반응해야 하는 상황에서 Observer 패턴을 적용할 수 있습니다. 이 패턴의 동작 원리를 설명하고, Push 모델과 Pull 모델의 차이점 및 각각의 장단점을 비교해 주세요.

힌트 · Subject와 Observer 간의 느슨한 결합을 통해 상태 변화를 통지합니다. 데이터 전달 방식에 따라 Push/Pull 모델로 나뉩니다.

Observer 패턴은 특정 객체(Subject)의 상태 변화를 감지하고, 이에 관심 있는 다른 객체들(Observers)에게 자동으로 알림을 보내는 디자인 패턴입니다. Subject는 Observer 목록을 관리하…

전체 모범답안 펼치기

Observer 패턴은 특정 객체(Subject)의 상태 변화를 감지하고, 이에 관심 있는 다른 객체들(Observers)에게 자동으로 알림을 보내는 디자인 패턴입니다. Subject는 Observer 목록을 관리하고, 상태가 변경될 때마다 각 Observer에게 업데이트를 통지합니다. 이를 통해 Subject와 Observer 간의 느슨한 결합(Loose Coupling)을 유지할 수 있습니다.

Push 모델에서는 Subject가 상태 변화와 함께 변경된 데이터를 Observer에게 직접 전달합니다. 장점은 Observer가 필요한 데이터를 즉시 받을 수 있다는 것이지만, 단점은 Subject가 모든 Observer에게 필요한 데이터를 미리 알아야 하고, 불필요한 데이터까지 전달할 수 있다는 점입니다.

Pull 모델에서는 Subject는 상태가 변경되었다는 사실만 알리고, Observer가 필요한 데이터를 Subject로부터 직접 가져옵니다. 장점은 Observer가 필요한 데이터만 요청할 수 있어 효율적이지만, 단점은 Observer가 Subject에 대한 의존성이 높아지고, 데이터를 가져오는 추가적인 과정이 필요하다는 점입니다.

#Subject#Observer#Push 모델#Pull 모델#Loose Coupling

이 질문 단독 페이지 →

Q12 중급

기존 객체의 기능을 변경하지 않고 동적으로 새로운 기능을 추가해야 할 때 Decorator 패턴을 활용할 수 있습니다. 상속 대신 Decorator 패턴을 사용하는 이유와, 언제 이 패턴을 적용하는 것이 효과적인지 설명해 주세요.

힌트 · 상속의 단점(클래스 폭발)을 회피하며, 객체의 기능을 동적으로 조합하여 확장할 수 있습니다.

Decorator 패턴은 기존 객체의 기능을 수정 없이 동적으로 확장할 때 유용합니다. 상속 대신 이 패턴을 사용하는 이유는 상속의 단점인 '클래스 폭발'을 피할 수 있기 때문입니다. 다양한 기능 조합을 상속으로 구…

전체 모범답안 펼치기

Decorator 패턴은 기존 객체의 기능을 수정 없이 동적으로 확장할 때 유용합니다. 상속 대신 이 패턴을 사용하는 이유는 상속의 단점인 '클래스 폭발'을 피할 수 있기 때문입니다. 다양한 기능 조합을 상속으로 구현하면 너무 많은 하위 클래스가 생길 수 있습니다.

Decorator 패턴은 객체 결합을 통해 기능을 추가하므로, 런타임에 유연하게 기능을 조합할 수 있습니다. 예를 들어, 커피 객체에 우유, 설탕, 시럽 등의 데코레이터를 추가하여 다양한 커피를 만들 수 있습니다.

이 패턴은 객체에 새로운 책임을 동적으로 할당해야 할 때, 그리고 객체의 핵심 로직 변경 없이 부가 기능을 추가해야 할 때 효과적입니다.

#객체 결합#유연성#상속의 단점#동적 기능 추가#책임 할당

이 질문 단독 페이지 →

Q13 중급

Adapter 패턴과 Facade 패턴은 모두 기존 시스템이나 라이브러리와의 상호작용을 돕는 구조 패턴입니다. 두 패턴의 목적과 사용 시점을 비교하여 설명하고, 각각의 실질적인 적용 사례를 들어주세요.

힌트 · Adapter는 호환되지 않는 인터페이스를 맞추고, Facade는 복잡한 서브시스템에 대한 단순화된 인터페이스를 제공합니다.

Adapter 패턴과 Facade 패턴은 둘 다 기존 시스템과의 연동을 돕지만, 목적과 사용 시점이 다릅니다.

전체 모범답안 펼치기

Adapter 패턴과 Facade 패턴은 둘 다 기존 시스템과의 연동을 돕지만, 목적과 사용 시점이 다릅니다.

Adapter 패턴은 주로 호환되지 않는 인터페이스를 가진 클래스들을 함께 작동하도록 변환하는 데 사용됩니다. 마치 전압 변환기처럼, 기존의 인터페이스를 클라이언트가 기대하는 다른 인터페이스로 바꿔주는 역할을 합니다. 예를 들어, 레거시 시스템의 API가 최신 라이브러리의 요구사항과 맞지 않을 때 Adapter를 사용하여 인터페이스를 맞춰줄 수 있습니다.

Facade 패턴은 복잡한 서브시스템에 대해 단순화된 통합 인터페이스를 제공하는 데 중점을 둡니다. 여러 개의 클래스로 구성된 복잡한 라이브러리나 프레임워크를 사용할 때, Facade는 클라이언트가 이 서브시스템의 복잡성을 알 필요 없이 간단한 메서드 호출로 기능을 사용할 수 있게 해줍니다. 예를 들어, 데이터베이스 연결, 쿼리 실행, 결과 처리 등 여러 단계가 필요한 데이터 접근 로직을 Facade로 묶어 클라이언트에게는 간단한 getData() 메서드만 노출할 수 있습니다.

요약하자면, Adapter는 '인터페이스 변환'에, Facade는 '복잡성 은닉 및 단순화된 인터페이스 제공'에 초점을 맞춘다고 볼 수 있습니다.

#인터페이스 변환#단일 인터페이스 제공#기존 시스템 통합#복잡성 은닉#클라이언트 단순화

이 질문 단독 페이지 →

Q14 중급

Proxy 패턴은 실제 객체에 대한 접근을 제어하거나 기능을 추가할 목적으로 사용됩니다. Proxy 패턴의 동작 원리를 설명하고, Virtual Proxy, Remote Proxy, Protective Proxy의 차이점을 구체적인 예시와 함께 설명해 주세요.

힌트 · Proxy는 실제 객체를 대신하는 대리자 역할을 합니다. 각 프록시 유형은 목적에 따라 실제 객체에 대한 접근을 다르게 제어합니다.

Proxy 패턴은 실제 객체에 대한 접근을 제어하거나 부가 기능을 제공하기 위해 중간에 대리자(Proxy)를 두는 디자인 패턴입니다. 클라이언트는 Proxy를 통해 실제 객체에 접근하며, Proxy는 접근 제어, 로…

전체 모범답안 펼치기

Proxy 패턴은 실제 객체에 대한 접근을 제어하거나 부가 기능을 제공하기 위해 중간에 대리자(Proxy)를 두는 디자인 패턴입니다. 클라이언트는 Proxy를 통해 실제 객체에 접근하며, Proxy는 접근 제어, 로깅, 캐싱 등의 역할을 수행할 수 있습니다.

Virtual Proxy는 실제 객체의 생성을 지연시키는 데 사용됩니다. 예를 들어, 큰 이미지 파일을 로딩할 때, Virtual Proxy는 이미지 로딩이 완료될 때까지 placeholder 이미지를 보여주다가 로딩이 완료되면 실제 이미지를 보여줍니다.

Remote Proxy는 서로 다른 주소 공간에 존재하는 객체에 대한 접근을 제공합니다. 예를 들어, 클라이언트가 서버에 있는 객체를 사용해야 할 때, Remote Proxy는 네트워크 통신을 처리하여 클라이언트가 마치 로컬 객체를 사용하는 것처럼 보이게 합니다.

Protective Proxy는 실제 객체에 대한 접근 권한을 제어합니다. 예를 들어, 특정 사용자에게만 접근 권한이 있는 객체에 대해, Protective Proxy는 사용자의 권한을 확인하고 권한이 있는 경우에만 실제 객체에 접근을 허용합니다.

#대리자#접근 제어#Virtual Proxy#Remote Proxy#Protective Proxy

이 질문 단독 페이지 →

디자인 패턴 면접 질문 — 심화

Q15 심화

Decorator 패턴과 Proxy 패턴은 구조적으로 유사해 보이지만, 목적과 적용 방식에서 명확한 차이가 있습니다. 복잡한 시스템에서 특정 객체에 대한 횡단 관심사(cross-cutting concerns)를 적용하거나 접근 제어를 구현해야 할 때, 두 패턴 중 어떤 것을 선택해야 하며, 각각의 성능 및 유지보수 측면에서의 장단점은 무엇인지 구체적인 시나리오를 들어 설명해주세요.

힌트 · Decorator는 기능 확장, Proxy는 접근 제어 및 부가 기능 제공에 중점을 둡니다. 성능 및 유지보수 측면에서 런타임 오버헤드, 코드 복잡성, 그리고 책임 분리를 고려해야 합니다.

Decorator와 Proxy는 구조는 비슷하지만 목적이 다릅니다.

전체 모범답안 펼치기

Decorator와 Proxy는 구조는 비슷하지만 목적이 다릅니다.

Decorator는 기존 객체의 기능을 런타임에 동적으로 확장할 때 사용합니다. 예를 들어, 로깅이나 트랜잭션 관리 같은 횡단 관심사를 여러 객체에 공통적으로 적용하고 싶을 때, 각 객체에 Decorator를 감싸서 기능을 추가할 수 있습니다. 장점은 코드 중복 없이 기능을 재사용하고, 객체 간의 결합도를 낮춰 유지보수성이 좋다는 것입니다. 단점은 객체 생성이 많아져 런타임 오버헤드가 발생할 수 있다는 점입니다.

Proxy는 객체에 대한 접근을 제어하거나, 객체 생성 및 접근 전에 부가적인 작업을 수행할 때 사용합니다. 예를 들어, 원격 객체에 접근하거나, 민감한 데이터에 대한 접근 권한을 확인하는 경우에 Proxy를 사용할 수 있습니다. 장점은 원본 객체와 클라이언트 사이에 투명하게 작동하며, 접근 제어 로직을 분리하여 핵심 로직에 집중할 수 있다는 것입니다. 단점은 Proxy 객체가 추가되어 복잡성이 증가하고, 경우에 따라 성능 저하가 발생할 수 있습니다.

따라서 횡단 관심사를 기능 확장 관점에서 적용하려면 Decorator를, 접근 제어 또는 부가 기능 제공 관점에서는 Proxy를 선택하는 것이 좋습니다.

#횡단 관심사#데코레이터#프록시#책임 할당#유지보수성

이 질문 단독 페이지 →

Q16 심화

이벤트 기반 아키텍처에서 Observer 패턴과 Publish-Subscribe 패턴은 모두 느슨한 결합을 통해 객체 간의 통신을 구현하는 데 사용됩니다. 하지만 이 둘은 아키텍처적 차이와 확장성, 그리고 구현 복잡성에서 중요한 차이를 가집니다. 대규모 분산 시스템에서 이 두 패턴 중 어느 것을 선택해야 하며, 그 선택이 시스템의 확장성, 성능, 그리고 장애 허용성에 어떤 영향을 미치는지 심층적으로 비교 설명해주세요.

힌트 · Observer는 발행자와 구독자가 직접 통신하지만, Publish-Subscribe는 중간 브로커를 통해 통신합니다. 대규모 시스템에서는 중간 브로커의 유무가 확장성과 장애 허용성에 큰 영향을 미칩니다.

이벤트 기반 아키텍처에서 Observer 패턴과 PublishSubscribe 패턴은 느슨한 결합을 제공하지만, 대규모 분산 시스템에서는 PublishSubscribe 패턴이 훨씬 유리합니다.

전체 모범답안 펼치기

이벤트 기반 아키텍처에서 Observer 패턴과 Publish-Subscribe 패턴은 느슨한 결합을 제공하지만, 대규모 분산 시스템에서는 Publish-Subscribe 패턴이 훨씬 유리합니다.

Observer 패턴은 발행자와 구독자가 직접 연결되어 있어, 발행자가 변경될 때 모든 구독자에게 즉시 알림이 전달됩니다. 이는 시스템 규모가 커지면 발행자와 구독자 간의 의존성이 높아져 확장성과 유지보수성이 떨어집니다. 또한, 발행자가 실패하면 구독자에게도 영향을 미칠 수 있어 장애 허용성이 낮습니다.

반면, Publish-Subscribe 패턴은 메시지 브로커(예: Kafka, RabbitMQ)를 통해 발행자와 구독자를 분리합니다. 발행자는 메시지를 브로커에 발행하고, 구독자는 관심 있는 토픽을 구독하여 메시지를 비동기적으로 수신합니다. 이 중간 브로커 덕분에 발행자와 구독자는 서로를 알 필요가 없어 결합도가 매우 낮습니다.

이러한 구조는 다음과 같은 이점을 제공합니다.

  • 확장성: 발행자와 구독자를 독립적으로 확장할 수 있습니다. 새로운 구독자를 추가하거나 기존 구독자를 늘려도 발행자에게 영향을 주지 않으며, 발행자 또한 독립적으로 확장 가능합니다. 메시지 브로커 자체도 클러스터링을 통해 확장성을 확보할 수 있습니다.
  • 성능: 비동기 통신을 통해 발행자는 메시지를 발행하고 즉시 다른 작업을 수행할 수 있습니다. 구독자 역시 자신의 속도에 맞춰 메시지를 처리하므로 전체 시스템의 처리량이 향상됩니다.
  • 장애 허용성: 메시지 브로커는 메시지를 큐에 저장하므로, 발행자나 구독자 중 하나가 일시적으로 실패하더라도 데이터 손실 없이 메시지를 전달할 수 있습니다. 브로커 자체의 고가용성 구성으로 시스템 전체의 안정성을 높일 수 있습니다.

따라서 대규모 분산 시스템에서는 Publish-Subscribe 패턴이 시스템의 유연성, 확장성, 그리고 안정성을 극대화하는 데 필수적입니다.

#Publish-Subscribe#메시지 큐#비동기#확장성#결합도

이 질문 단독 페이지 →

Q17 심화

Singleton 패턴은 전역적으로 유일한 인스턴스를 보장하는 데 유용하지만, 테스트 용이성 저해, 다중 스레드 환경에서의 문제, 그리고 과도한 사용 시 의존성 주입을 어렵게 만드는 등 여러 단점이 지적됩니다. 이러한 Singleton 패턴의 문제점을 극복하고, 테스트 용이성과 유연성을 높이면서도 전역적인 유일성을 보장해야 하는 상황에서 Dependency Injection (DI) 또는 Monostate 패턴과 같은 대안을 어떻게 적용할 수 있는지 구체적인 코드 설계 관점에서 설명해주세요.

힌트 · Singleton은 전역 상태를 만들고 테스트 격리를 어렵게 합니다. DI는 의존성을 외부에서 주입하여 테스트 용이성을 높이며, Monostate는 상태를 공유하되 인스턴스는 여러 개 생성하여 유연성을 제공합니다.

Singleton 패턴의 문제점을 극복하고 전역적인 유일성을 보장하면서도 테스트 용이성을 확보하기 위해 DI 컨테이너와 인터페이스를 활용할 수 있습니다.

전체 모범답안 펼치기

Singleton 패턴의 문제점을 극복하고 전역적인 유일성을 보장하면서도 테스트 용이성을 확보하기 위해 DI 컨테이너와 인터페이스를 활용할 수 있습니다.

예를 들어, 설정 관리자 클래스를 싱글톤으로 구현하는 대신, 설정 관리자 인터페이스를 정의하고 실제 구현체를 DI 컨테이너에 등록합니다. 필요한 곳에서는 인터페이스를 통해 설정 관리자를 주입받아 사용합니다. 이렇게 하면 실제 구현체를 Mock 객체로 쉽게 대체하여 유닛 테스트를 수행할 수 있습니다.

Monostate 패턴은 상태를 공유하는 여러 인스턴스를 생성하여 싱글톤의 전역 상태 문제를 완화합니다. 모든 인스턴스가 동일한 내부 상태를 공유하므로, 싱글톤과 유사한 효과를 내면서도 각 인스턴스를 독립적으로 테스트할 수 있습니다. 하지만 Monostate 패턴은 상태 공유에 대한 명확한 인지가 필요하며, 예상치 못한 부작용을 초래할 수 있으므로 주의해서 사용해야 합니다.

#Dependency Injection#인터페이스#테스트 용이성#유닛 테스트#Monostate 패턴

이 질문 단독 페이지 →

Q18 심화

오래된 레거시 시스템은 종종 'God Object'나 'Feature Envy'와 같은 안티 패턴으로 인해 유지보수가 어렵고 확장성이 떨어집니다. 이러한 레거시 코드베이스를 점진적으로 리팩토링하여 디자인 패턴을 적용하고자 할 때, 어떤 전략과 패턴을 사용하여 기존 기능을 손상시키지 않으면서 코드 품질을 향상시킬 수 있을지 구체적인 단계와 적용 가능한 패턴(예: Strategy, Facade, Adapter)을 제시하여 설명해주세요.

힌트 · 점진적 리팩토링은 기존 기능을 보호하면서 작은 단위로 개선하는 것입니다. Facade로 복잡한 서브시스템을 감싸고, Strategy로 변하는 부분을 분리하며, Adapter로 호환되지 않는 인터페이스를 연결하는 방법을 고려할 수 있습니다.

레거시 시스템 리팩토링은 조심스럽게 접근해야 합니다. 먼저, '스트랭글러 패턴'을 적용하여 기존 시스템을 점진적으로 대체하는 방식을 고려합니다. 새로운 기능은 새로운 아키텍처로 개발하고, 기존 기능은 리팩토링을 통해…

전체 모범답안 펼치기

레거시 시스템 리팩토링은 조심스럽게 접근해야 합니다. 먼저, '스트랭글러 패턴'을 적용하여 기존 시스템을 점진적으로 대체하는 방식을 고려합니다. 새로운 기능은 새로운 아키텍처로 개발하고, 기존 기능은 리팩토링을 통해 점진적으로 옮겨가는 것이죠.

리팩토링 시에는 '테스트 주도 개발(TDD)'을 적극 활용하여 기존 기능이 변경 후에도 정상적으로 작동하는지 확인합니다. 'Facade' 패턴을 사용하여 복잡한 레거시 시스템의 인터페이스를 단순화하고, 'Strategy' 패턴으로 알고리즘을 캡슐화하여 변경에 유연하게 대처할 수 있도록 합니다. 또한, 'Adapter' 패턴을 사용하여 새로운 인터페이스와 기존 인터페이스 간의 호환성을 확보합니다.

예를 들어, 결제 시스템의 복잡한 로직을 Facade로 감싸고, 다양한 결제 방식을 Strategy 패턴으로 구현하여 새로운 결제 방식 추가에 용이하도록 만들 수 있습니다.

#스트랭글러 패턴#테스트 주도 개발 (TDD)#추상화#Facade 패턴#Adapter 패턴

이 질문 단독 페이지 →

Q19 심화

디자인 패턴은 코드의 구조와 유지보수성을 향상시키지만, 일부 패턴은 잘못 적용되거나 특정 상황에서 성능 오버헤드를 유발할 수 있습니다. 예를 들어, Chain of Responsibility, Decorator, Visitor 패턴 등은 런타임 시 추가적인 객체 생성이나 메서드 호출로 인해 성능 저하를 일으킬 가능성이 있습니다. 이러한 패턴들이 성능에 미칠 수 있는 부정적인 영향을 분석하고, 성능 최적화를 고려하여 패턴을 설계하거나 대안을 선택하는 방법에 대해 설명해주세요.

힌트 · 패턴 적용 시 발생하는 추가적인 객체 생성, 가상 메서드 호출, 참조 추적 등의 오버헤드를 고려해야 합니다. 캐싱, 지연 초기화, 또는 더 직접적인 구현으로 성능을 최적화할 수 있습니다.

네, 디자인 패턴의 성능 영향과 최적화 방안에 대해 말씀드리겠습니다.

전체 모범답안 펼치기

네, 디자인 패턴의 성능 영향과 최적화 방안에 대해 말씀드리겠습니다.

Chain of Responsibility, Decorator, Visitor 패턴 등은 유연성과 확장성을 제공하지만, 말씀하신 대로 런타임 시 객체 생성이나 메서드 호출이 늘어나 성능 오버헤드를 유발할 수 있습니다. 예를 들어, Decorator 패턴은 여러 데코레이터를 중첩할 때마다 새로운 객체를 생성하고, 각 데코레이터의 메서드를 순차적으로 호출하게 됩니다.

이러한 성능 저하를 방지하기 위해 몇 가지 접근 방식을 고려할 수 있습니다. 첫째, 패턴 적용 전에 해당 패턴이 정말 필요한지, 그리고 성능에 미칠 영향을 충분히 분석해야 합니다. 둘째, 패턴을 적용하더라도 성능 최적화를 고려해야 합니다. 예를 들어, 객체 생성이 빈번하다면 팩토리 패턴을 활용하여 객체 생성을 중앙 집중화하고 재사용성을 높일 수 있습니다. 또한, 반복적인 계산 결과는 캐싱하여 불필요한 연산을 줄일 수 있습니다.

만약 패턴 적용으로 인한 오버헤드가 크다면, 전략 패턴과 같이 더 직접적이고 간단한 구현을 대안으로 고려할 수도 있습니다. 핵심은 유연성과 성능 사이의 균형을 맞추는 것입니다.

#객체 생성 비용#메서드 호출 오버헤드#캐싱#팩토리 패턴#전략 패턴

이 질문 단독 페이지 →

Q20 심화

마이크로서비스 아키텍처는 분산 시스템의 복잡성을 관리하기 위해 다양한 디자인 패턴을 활용합니다. 마이크로서비스 환경에서 Service Discovery, Circuit Breaker, Saga, API Gateway와 같은 패턴들이 각각 어떤 문제점을 해결하고, 전체 시스템의 견고성, 확장성, 그리고 장애 허용성에 어떻게 기여하는지 구체적인 시나리오와 함께 설명해주세요.

힌트 · Service Discovery는 서비스 위치를 찾고, Circuit Breaker는 실패 전파를 방지하며, Saga는 분산 트랜잭션을 관리하고, API Gateway는 진입점을 통합합니다. 이들은 마이크로서비스의 복잡성을 줄이고 안정성을 높이는 데 핵심적인 역할을 합니다.

마이크로서비스 환경에서 복잡성을 관리하고 시스템 안정성을 높이기 위해 다양한 디자인 패턴이 활용됩니다.

전체 모범답안 펼치기

마이크로서비스 환경에서 복잡성을 관리하고 시스템 안정성을 높이기 위해 다양한 디자인 패턴이 활용됩니다.

Service Discovery는 동적으로 변화하는 서비스 인스턴스의 위치를 자동으로 찾아 서비스 간 통신을 가능하게 합니다. 예를 들어, 사용자 요청이 들어왔을 때 주문 서비스는 Service Discovery를 통해 현재 활성화된 결제 서비스 인스턴스의 주소를 알아내 통신합니다. 이는 서비스의 확장성과 가용성을 높여줍니다.

Circuit Breaker는 특정 서비스에 장애가 발생했을 때, 해당 서비스로의 요청을 차단하여 실패가 다른 서비스로 전파되는 것을 막습니다. 예를 들어, 결제 서비스가 응답하지 않으면 Circuit Breaker가 작동하여 더 이상 결제 서비스로 요청을 보내지 않고 즉시 실패 응답을 반환합니다. 이는 시스템 전체의 장애를 방지하고 복구 시간을 단축하는 데 기여합니다.

Saga는 여러 마이크로서비스에 걸쳐 있는 복잡한 비즈니스 트랜잭션을 관리합니다. 각 마이크로서비스는 자체 트랜잭션을 수행하고, 실패 시에는 이전 단계의 트랜잭션을 보상하는 방식으로 전체 트랜잭션의 일관성을 유지합니다. 예를 들어, 주문 생성 시 결제, 재고 확인, 배송지 설정 등 여러 서비스가 관여하는데, Saga 패턴을 통해 각 단계가 성공하거나 실패 시 롤백을 처리하여 데이터 불일치를 방지합니다.

API Gateway는 모든 클라이언트 요청의 단일 진입점 역할을 합니다. 인증, 로깅, 라우팅, 응답 변환 등의 기능을 중앙에서 처리하여 각 마이크로서비스는 비즈니스 로직에만 집중할 수 있게 합니다. 예를 들어, 모바일 앱에서 상품 목록을 조회하는 요청이 오면 API Gateway는 해당 요청을 상품 서비스로 라우팅하고, 필요한 경우 사용자 인증 정보도 함께 전달합니다. 이는 클라이언트의 복잡성을 줄이고 시스템의 보안 및 관리 효율성을 높입니다.

이 패턴들은 상호 보완적으로 작용하여 마이크로서비스 환경의 견고성, 확장성, 그리고 장애 허용성을 크게 향상시킵니다.

#Service Discovery#Circuit Breaker#Saga#API Gateway#분산 트랜잭션

이 질문 단독 페이지 →

Q21 심화

고도로 동시성(concurrent)이 요구되는 시스템을 설계할 때, 전통적인 디자인 패턴만으로는 충분하지 않거나 오히려 복잡성을 증가시킬 수 있습니다. 이러한 환경에서 Producer-Consumer, Reactor, Actor 모델과 같은 동시성 패턴(Concurrency Patterns)이 어떻게 스레드 안전성, 자원 관리, 그리고 성능 최적화를 달성하는 데 기여하는지 설명하고, 이들 패턴을 적용할 때 주의해야 할 점과 잠재적인 문제점(예: 데드락, 라이브락)에 대해 논의해주세요.

힌트 · 동시성 패턴은 공유 자원 접근 제어, 작업 분배, 비동기 통신 등을 통해 스레드 안전성과 성능을 높입니다. 데드락, 라이브락, 경합 조건 등을 피하기 위한 적절한 동기화 메커니즘과 설계가 중요합니다.

고성능 동시성 시스템 설계 시, 전통적인 패턴은 스레드 간 복잡한 상호작용을 관리하기 어렵습니다. ProducerConsumer 패턴은 생산자와 소비자 간의 데이터 흐름을 큐로 분리하여 스레드 안전성과 자원 관리를…

전체 모범답안 펼치기

고성능 동시성 시스템 설계 시, 전통적인 패턴은 스레드 간 복잡한 상호작용을 관리하기 어렵습니다. Producer-Consumer 패턴은 생산자와 소비자 간의 데이터 흐름을 큐로 분리하여 스레드 안전성과 자원 관리를 효율화합니다. Reactor 패턴은 단일 스레드 또는 소수 스레드로 다수의 I/O 이벤트를 비동기적으로 처리하여 컨텍스트 스위칭 오버헤드를 줄이고 성능을 높입니다. Actor 모델은 독립적인 Actor들이 메시지 전달로만 통신하며 상태를 캡슐화하여 스레드 안전성을 확보하고 확장성을 용이하게 합니다.

이러한 패턴 적용 시, 데드락이나 라이브락 같은 문제는 주의해야 합니다. 예를 들어, Producer-Consumer에서 큐가 가득 찼을 때 생산자가 무한정 대기하거나, Actor 모델에서 메시지 순환으로 인해 Actor들이 응답하지 않는 상황이 발생할 수 있습니다. 이를 방지하기 위해 적절한 타임아웃 메커니즘, 메시지 우선순위 지정, 그리고 명확한 통신 프로토콜 설계가 필수적입니다. 또한, 과도한 동기화는 성능 저하를 야기할 수 있으므로, 공유 자원 접근을 최소화하고 비동기 통신을 적극 활용하는 것이 중요합니다.

#스레드 안전성#자원 경쟁#데드락#라이브락#컨텍스트 스위칭

이 질문 단독 페이지 →

함께 보면 좋은 CS 기초 면접 질문

← 전체 면접 질문 카테고리 보기

보유한 디자인 패턴 질문은 이게 전부가 아닙니다

패스잇 앱에는 직무별 면접 질문 수천 개와 모범답안이 담겨 있습니다. AI 모의면접으로 직접 답하고, 약점을 분석받아 보세요.