[북스터디]자바 기술 면접 빈출 질문(3) 8가지 디자인 패턴 질문

Wang_Seok_Hyeon·2023년 9월 29일
0
post-thumbnail

Intro

디자인 패턴은 GoF로 대표되는 OOP 개발의 주요한 사용 방식 중 하나로, 다양한 문제를 해결하는 방식으로 많이 사용되어져 온 것이 굳어지고 소개되고 이론을 가지며 생겨난 것입니다.
생성, 구조, 행동패턴으로 크게 세 개로 분류되며 총 23가지를 가지고 있다고 알려져 있습니다.

여기에 대해서 자세히 모든 것을 다루지는 않지만, 이 책에서도 몇 가지 질문과 그에 대한 답변이 정리되어 있어 이를 소개하고자 합니다.

1. 데커레이터 패턴에 적합한 객체지향 프로그래밍 개념은 무엇인가?

데커레이터 디자인 패턴에 적합한 객체지향 프로그래밍 개념은 구성입니다. 이 객체지향 프로그래밍 개념을 통해 데커레이터 디자인 패턴은 기존 클래스를 수정하지 않고도 새로운 기능을 제공합니다.

2. 싱글턴 패턴은 언제 사용해야 하는가?

싱글턴(singleton) 디자인 패턴은 클래스의 애플리케이션 레벨(전역) 인스턴스가 하나만 필요할 때 사용하면 매우 적합합니다. 다만, 싱글턴은 클래스 간 결합을 증가시키고 개발, 테스트 및 디버깅 중에 병목 현상을 발생시킬 수 있으므로 사용에 주의가 필요합니다.
유명한 도서인 이펙티브 자바(3판)에서 언급했듯이 자바 열거형(ENUM)을 사용하는 것이 이 패턴을 구현하는 가장 좋은 방법입니다. 로거(logger), java.lang.Runtime 등과 같은 전역 환경 설정, 하드웨어 접근, 데이터베이스 연결 등을 위해 싱글턴 패턴을 사용하는 것이 일반적인 시나리오입니다.

3. 전략 패턴과 상태 패턴의 차이점은 무엇인가?

상태(state) 디자인 패턴은 상태에 따라 특정 작업을 수행하도록 설계되었습니다. 이 패턴은 클래스를 변경하지 않는 환경에서 서로 다른 상태의 특정 동작을 나타냅니다. 반면에 전략(strategy) 디자인 패턴은 코드를 수정하지 않고 여러 알고리즘을 전환하여 사용하기 위한 패턴입니다. 클라이언트는 구성과 런타임 위임(delegation)을 통해 알고리즘을 전환합니다. 또한 상태 패턴에서는 각 상태를 다른 상태로 연결하며 흐름이 생성되기 때문에 상태 전이 순서가 명확하지만, 전략 패턴에서는 클라이언트가 원하는 알고리즘을 순서와 상관없이 선택할 수 있습니다. 예를 들어 상태 패턴은 클라이언트에 패키지를 보내는 상태를 정의할 수 있습니다. 패키지는 순서가 정해진 상태에서 시작하여 클라이언트가 패키지를 받는 마지막 상태에 도달할 때까지 계속해서 연결된 상태를 통과합니다. 반면에 전략 패턴은 각 상태를 달성하기 위한 서로 다른 전략을 정의합니다. 예를 들어 패키지를 배달하는 여러 가지 전략이 있을 수 있습니다.

4. 프록시 패턴과 데커레이터 패턴의 차이점은 무엇인가?

프록시(proxy) 디자인 패턴은 무언가에 대한 접근 제어 게이트웨이를 제공하는 데 유용합니다. 일반적으로 이 패턴은 실제 객체를 대신할 대리 객체를 생성합니다. 실제 객체에 대한 각 요청은 대리 객체를 통과해야 하며, 대리 객체는 이를 실제 객체로 전달할 방법과 시점을 결정합니다. 데커레이터 디자인 패턴은 객체를 생성하지 않으며 런타임에 기존 객체를 새로운 기능으로 장식할 뿐입니다. 대리 객체를 생성하지 않으며 런타임에 기존 객체를 새로운 기능으로 장식할 뿐입니다. 대리 객체를 연쇄적으로 사용하는 것은 권장되지 않지만, 특정 순서로 데커레이터를 연쇄적으로 사용하는 것은 데커레이터 패턴을 올바르게 사용하는 방법입니다. 예를 들어 프록시 패턴은 인터넷의 프록시 서버를 나타낼 수 있으며 데커레이터 패턴은 프록시 서버를 서로 다른 사용자 지정 설정으로 장식할 수 있습니다.

5. 퍼사드 패턴과 데커레이터 패턴의 차이점은 무엇인가?

데커레이터 디자인 패턴은 객체에 새로운 기능을 추가하거나 객체를 장식한다는 의미이지만, 퍼사드(facade) 디자인 패턴은 객체에 새로운 기능을 전혀 추가하지 않습니다. 퍼사드 패턴은 시스템의 복잡성을 숨기고 기존 기능만 표면에 내세워 클라이언트에게 노출되는 친근한 얼굴 뒤에서 기능을 호출합니다. 퍼사드 패턴은 복잡한 작업을 수행하기 위해 개별 구성요소를 호출하는 간단한 인터페이스를 노출할 수 있습니다. 예를 들어 데커레이터 패턴은 엔진, 기어박스 등으로 뼈대를 장식하여 자동차를 만드는 데 사용할 수 있고, 퍼사드 패턴은 자동차 생성 과정의 세부 사항을 아는 산업용 로봇에 명령을 내릴 수 잇는 간단한 인터페이스를 노출하여 자동차를 만드는 복잡성을 숨길 수 있습니다.

6. 템플릿 메서드 패턴과 전략 패턴의 주요 차이점은 무엇인가?

템플릿 메서드(Template method) 패턴과 전략 패턴은 도메인별 알고리즘 집합을 객체로 캡슐화하지만 동이랗ㄴ 방법을 사용하지는 않습니다. 주요 차이점은 전략 패턴은 요구사항을 기반으로 서로 다른 전략 또는 알고리즘 중에 사용할 알고리즘을 런타임에 결정하지만, 템플릿 메서드 패턴은 고정된 뼈대, 즉 사전에 정의된 일련의 단계에 따라 구현된 알고리즘대로 동작한다는 사실입니다. 일부 단계는 고정되어 잇는 반면에 나머지 단계는 다른 용도로 수정할 수 잇습니다. 예를 들어 전략 패턴은 신용카드 또는 페이팔(Paypal)과 같은 서로 다른 지불 전략 사이에서 어떤 전략을 사용할 것인지 결정할 수 잇으며, 템플릿 메서드 패턴은 특정 전략으로 지불하기 위해 사전에 정의된 단계의 순서를 설명할 수 잇습니다. 예를 들어 페이팔로 지불하려면 고정된 일련의 단계가 필요합니다.

7. 빌더 패턴과 팩토리 패턴의 주요 차이점은 무엇인가?

팩토리(factory) 패턴은 단일 메서드호출로 객체를 생성합니다. 이때 필요한 모든 매개변수를 전달해야 하며 팩토리는 일반적으로 생성자를 호출하여 객체를 반환할 것입니다. 반면에 빌더(builder)패턴은 매개변수의 조합을 형성할 수 있는 setter 메서드의 연쇄작용을 통해 복잡한 객체를 구성할 수 있도록 설계되었ㅅ브니다. 연쇄작용의 끝에서 빌더 메서드는 매개변수 목록이 설정되었음을 알리는 build 메서드를 노출하며 이 시점에 객체를 구축할 수 있ㅅ브니다. 즉, 팩토리 패턴은 생성자의 래퍼(wrapper) 역할을 하는 반면, 빌더 패턴은 훨씬 세분화되어 생성자에게 전달할 수 있는 모든 매개변수의 래퍼 역할을 합니다.
빌더를 통해 가능한 모든 매개변수 조합을 다 노출하는 점층적(telescopic) 생성자 패턴을 피할 수 있습니다. 예를 들어 Book(책) 객체가 있다고 하겠습니다. 책은 저자, 제목, ISBN, 형식과 같은 고정 매개변수의 조합으로 특징이 만들어집니다. 책을 만들 때는 대부분의 경우 매개변수의 개수가 바뀌지 않으므로 팩토리 패턴이 적합할 것입니다. 하지만 Server 객체는 어떨까요? 서버는 매개변수가 엄청나게 많은 복잡한 객체이므로 빌더 패턴이 훨씬 더 적절하거나, 두 가지 패턴을 조합하여 내부적으로 빌더에 의존하는 팩토리 패턴이 적합할 것입니다.

8. 어댑터 패턴과 브리지 패턴의 주요 차이점은 무엇인가?

어댑터(adapter) 패턴은 타사의 코드와 같이 수정할 수 없는 기존 코드와 새로운 시스템 또는 인터페이스 사이의 호환성을 제공하려고 노력합니다. 반면에 브리지(bridge) 패턴은 사전에 구현되며 엄청난 수의 클래스 작성을 피하고자 구현에서 추상화를 분리하는 것을 의미합니다. 따라서 어댑터 패턴은 설계 후에 각 항목 사이의 호환성을 제공하고자 노력하고, 브리지 패턴은 추상화와 구현이 독립적으로 변경될 수 있도록 사전 구축됩니다.(어댑터의 첫 글자 A가 이후를 뜻하는 after에서, 브리지의 첫 글자 B가 이전을 뜻하는 Before에서 따온 것으로 생각하면 기억하기 좋습니다.)
어댑터 패턴은 독립적으로 작동하지만 호환이 되는 입력 및 출력값이 없어 서로 소통할 수 없는 두 시스템 사이에서 중간자 역할을 합니다. 반면에 브리지 패턴은 직교하는 클래스 계층을 통해 문제를 해결할 수 잇지만, 확장성 문제와 제한된 확장으로 인해 어려움을 겪습니다. 예를 들어 ReadJsonRequest(JSON 요청 읽기)와 ReadXmlRequest(XML 요청 읽기)라는 두 가지 클래스가 있다고 가정하겠습니다. 각 클래스는 D1, D2와 D3와 같은 서로 다른 장치로부터 요청을 읽어 들일 수 잇으며 D2는 JSON 요청만, D3는 XML 요청만 제공합니다. 어댑터 패턴을 통해 JSON과 XML을 서로 변환할 수 잇으며 두 클래스는 세 가지 장치 모두와 통신할 수 있습니다. 반면에 브리지 패턴을 사용하면 ReadXmlRequestD1, ReadXmlRequestD2, ReadXmlRequestD3, ReadJsonRequestD1, ReadJsonRequestD2, ReadJsonRequestD3 등과 같은 많은 클래스를 생성하는 것을 방지할 수 있습니다.

Outro

이로써 챕터 6의 주요 질문들 정리가 끝났습니다. 이외에도 다양한 상황의 다양한 질문이 있기 때문에 면접 시리즈를 따로 빼도 좋지 않을까 생각이 듭니다.

추가적으로 디자인패턴에 관한 추천 학습사이트 소개와
풍성한 한가위 기원하며 앞으로 챕터7, 챕터8 등등 더 많은 책의 내용을 소개 정리할 수 있도록 하겠습니다.

디자인 패턴 학습 추천 사이트

profile
하루 하루 즐겁게

0개의 댓글