브리지는 큰 클래스 또는 밀접하게 관련된 클래스들의 집합을 두 개의 개별 계층구조(추상화 및 구현)로 나눈 후 각각 독립적으로 개발할 수 있도록 하는 구조 디자인 패턴입니다.
문제
추상화? 구현? 어렵게 들리시나요? 진정하세요. 그리고 간단한 예시를 한번 살펴봅시다.
Circle(원) 및 Square(직사각형)라는 한 쌍의 자식 클래스들이 있는 기하학적 Shape(모양) 클래스가 있다고 가정해 봅시다. 이 클래스 계층 구조를 확장하여 색상을 도입하기 위해 Red(빨간색) 및 Blue(파란색) 모양들의 자식 클래스들을 만들 계획입니다. 그러나 이미 두 개의 자식 클래스가 있으므로 BlueCircle(파란색 원) 및 RedSquare(빨간색 직사각형)와 같은 네 가지의 클래스 조합을 만들어야 합니다.
새로운 모양 유형들과 색상 유형들을 추가할 때마다 계층 구조는 기하급수적으로 성장합니다. 예를 들어, 삼각형 모양을 추가하려면 각 색상별로 하나씩 두 개의 자식 클래스들을 도입해야 합니다. 그리고 그 후에 또 새 색상을 추가하려면 각 모양 유형별로 하나씩 세 개의 자식 클래스를 만들어야 합니다. 유형들이 많아지면 많아질수록 코드는 점점 복잡해집니다.
해결책
이 문제는 모양과 색상의 두 가지 독립적인 차원에서 모양 클래스들을 확장하려고 하기 때문에 발생합니다. 이것은 클래스 상속과 관련된 매우 일반적인 문제입니다.
브리지 패턴은 상속에서 객체 합성으로 전환하여 이 문제를 해결하려고 시도합니다. 이것이 의미하는 바는 차원 중 하나를 별도의 클래스 계층구조로 추출하여 원래 클래스들이 한 클래스 내에서 모든 상태와 행동들을 갖는 대신 새 계층구조의 객체를 참조하도록 한다는 것입니다.

이 접근 방식을 따르면, 색상 관련 코드를 Red 및 Blue라는 두 개의 자식 클래스들이 있는 자체 클래스로 추출할 수 있습니다. 그런 다음 Shape 클래스는 색상 객체들 중 하나를 가리키는 참조 필드를 받습니다. 이제 모양은 연결된 색상 객체에 모든 색상 관련 작업을 위임할 수 있습니다. 이 참조는 Shape 및 Color 클래스들 사이의 브리지(다리) 역할을 할 것입니다. 이제부터 새 색상들을 추가할 때 모양 계층구조를 변경할 필요가 없으며 그 반대의 경우도 마찬가지입니다.
추상화와 구현
GoF의 디자인 패턴 은 브리지 패턴 정의의 일부로 추상화 및 구현이라는 용어들을 소개합니다. 저는 위 용어들이 너무 학문적이라 그로 인해 패턴이 실제보다 더 복잡하게 들린다고 생각합니다. 그러면 GoF의 책의 난해한 용어들 뒤에 숨겨진 의미를 모양과 색상이 있는 간단한 예를 통해 해독해 보겠습니다.
추상화(인터페이스라고도 함)는 일부 개체(entity)에 대한 상위 수준의 제어 레이어입니다. 이 레이어는 자체적으로 실제 작업을 수행해서는 안 되며, 작업들을 구현 레이어(플랫폼이라고도 함)에 위임해야 합니다.
참고로 지금 우리가 이야기하는 것은 당신이 선호하는 프로그래밍 언어의 인터페이스들이나 추상 클래스들이 아닙니다. 이것들은 같은 것이 아닙니다.
실제 앱을 예로 들면 추상화는 그래픽 사용자 인터페이스이며 구현은 그래픽 사용자 인터페이스 레이어가 사용자와 상호작용하여 그 결과로 호출하는 배경 운영 체제 코드(API)입니다.
일반적으로 이러한 앱은 두 가지 독립적인 방향으로 확장할 수 있습니다.
- 다른 여러 가지의 그래픽 사용자 인터페이스를 가진다 (예: 일반 고객 또는 관리자용으로 맞춘 인터페이스들).
- 여러 다른 API들을 지원한다 (예: 맥, 리눅스 및 윈도우에서 앱을 실행할 수 있는 API들).
최악의 경우 이 앱은 수백 개의 조건문들이 코드 전체에 다양한 API와 다양한 유형의 그래픽 사용자 인터페이스들을 연결한 거대한 스파게티 코드 그릇처럼 형성됩니다.
전체를 잘 이해해야 하므로 모놀리식 코드베이스는 간단한 변경을 하는 것조차 매우 어렵습니다. 반면에 잘 정의된 작은 모듈들을 변경하는 것이 훨씬 쉽습니다.
당신은 특정 인터페이스-플랫폼 조합들과 관련된 코드를 별도의 클래스들로 추출하여 이 복잡함에 질서를 부여할 수 있으나, 곧 이러한 클래스들이 많이 있다는 것을 알게 될 것입니다. 새로운 그래픽 사용자 인터페이스를 추가하거나 다른 API를 지원하려면 점점 더 많은 클래스를 생성해야 하므로 클래스 계층구조는 기하급수적으로 성장할 것입니다.
브리지 패턴으로 이 문제를 해결해 봅시다. 브리지 패턴은 클래스들을 두 개의 계층구조로 분리하라고 제안합니다:
- 추상화: 앱의 그래픽 사용자 인터페이스 레이어.
- 구현: 운영 체제의 API.
추상화 객체는 앱의 드러나는 모습을 제어하고 연결된 구현 객체에 실제 작업들을 위임합니다. 서로 다른 구현들은 공통 인터페이스를 따르는 한 상호 호환이 가능하며, 이에 따라 같은 그래픽 사용자 인터페이스는 리눅스와 윈도우에 동시에 작동할 수 있습니다.
따라서 당신은 API 관련 클래스들을 건드리지 않고 그래픽 사용자 인터페이스 클래스들을 변경할 수 있습니다. 그리고 다른 운영 체제에 대한 지원을 추가하려면 구현 계층구조 내에 자식 클래스를 생성하기만 하면 됩니다.
'스터디 > 디자인패턴' 카테고리의 다른 글
[design-pattern] 어댑터 패턴의 이해(Adapter Pattern) (0) | 2022.12.18 |
---|---|
[design-pattern][디자인패턴]추상 팩토리 패턴(Abstract Factory Pattern)이란? (0) | 2022.11.28 |
[design-pattern][디자인패턴] 프로토타입 패턴(Prototype Pattern)이란? (0) | 2022.11.28 |
[design-pattern][디자인패턴]빌더 패턴(Builder Pattern)이란? (0) | 2022.11.28 |