Decorator Pattern

객체에 동적으로 새로운 책임을 추가할 수 있게 해주는 구조적 디자인 패턴
" 래퍼 (wrapper)" 개념으로 각 데코레이터는 원본 객체를 감싸면서 추가 기능을 제공한다.
여러 데코레이터를 겹겹이 쌓을 수 있으며, 각 계층은 이전 계층의 기능을 확장한다.

특징

사용사례

장점

단점

주의사항 및 고려사항

예시

Python

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
from abc import ABC, abstractmethod
from typing import List

# Component interface
class Coffee(ABC):
    """Base Coffee interface"""
    @abstractmethod
    def get_cost(self) -> float:
        pass

    @abstractmethod
    def get_ingredients(self) -> List[str]:
        pass

    @abstractmethod
    def get_description(self) -> str:
        pass

# Concrete component
class SimpleCoffee(Coffee):
    """Basic coffee implementation"""
    def get_cost(self) -> float:
        return 2.0

    def get_ingredients(self) -> List[str]:
        return ["Coffee"]

    def get_description(self) -> str:
        return "Simple coffee"

# Base decorator
class CoffeeDecorator(Coffee):
    """Base decorator class"""
    def __init__(self, coffee: Coffee):
        self._coffee = coffee

    def get_cost(self) -> float:
        return self._coffee.get_cost()

    def get_ingredients(self) -> List[str]:
        return self._coffee.get_ingredients()

    def get_description(self) -> str:
        return self._coffee.get_description()

# Concrete decorators
class MilkDecorator(CoffeeDecorator):
    """Adds milk to the coffee"""
    def get_cost(self) -> float:
        return super().get_cost() + 0.5

    def get_ingredients(self) -> List[str]:
        return super().get_ingredients() + ["Milk"]

    def get_description(self) -> str:
        return f"{super().get_description()}, with steamed milk"

class WhipDecorator(CoffeeDecorator):
    """Adds whipped cream to the coffee"""
    def get_cost(self) -> float:
        return super().get_cost() + 0.7

    def get_ingredients(self) -> List[str]:
        return super().get_ingredients() + ["Whipped Cream"]

    def get_description(self) -> str:
        return f"{super().get_description()}, topped with whipped cream"

class CaramelDecorator(CoffeeDecorator):
    """Adds caramel to the coffee"""
    def get_cost(self) -> float:
        return super().get_cost() + 0.6

    def get_ingredients(self) -> List[str]:
        return super().get_ingredients() + ["Caramel"]

    def get_description(self) -> str:
        return f"{super().get_description()}, drizzled with caramel"

class ExtraShotDecorator(CoffeeDecorator):
    """Adds an extra shot of espresso"""
    def get_cost(self) -> float:
        return super().get_cost() + 1.0

    def get_ingredients(self) -> List[str]:
        return super().get_ingredients() + ["Extra Espresso Shot"]

    def get_description(self) -> str:
        return f"{super().get_description()}, with an extra shot"

# Order management
class CoffeeOrder:
    """Manages coffee orders and provides order summary"""
    def __init__(self):
        self.coffee = None

    def create_order(self) -> None:
        """Creates a new coffee order starting with simple coffee"""
        self.coffee = SimpleCoffee()

    def add_milk(self) -> None:
        self.coffee = MilkDecorator(self.coffee)

    def add_whip(self) -> None:
        self.coffee = WhipDecorator(self.coffee)

    def add_caramel(self) -> None:
        self.coffee = CaramelDecorator(self.coffee)

    def add_extra_shot(self) -> None:
        self.coffee = ExtraShotDecorator(self.coffee)

    def get_order_summary(self) -> str:
        """Generates a summary of the current order"""
        return f"""
        Order Summary:
        Description: {self.coffee.get_description()}
        Ingredients: {', '.join(self.coffee.get_ingredients())}
        Total Cost: ${self.coffee.get_cost():f}
        """

# Usage example
if __name__ == "__main__":
    # Create a new order
    order = CoffeeOrder()
    order.create_order()

    # Customize the coffee with various additions
    order.add_milk()
    order.add_extra_shot()
    order.add_whip()
    order.add_caramel()

    # Print the order summary
    print(order.get_order_summary())

Javascript

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// Component interface
class TextProcessor {
    constructor() {
        if (this.constructor === TextProcessor) {
            throw new Error("Abstract class cannot be instantiated");
        }
    }

    process(text) {
        throw new Error("Method 'process' must be implemented");
    }
}

// Concrete component
class SimpleTextProcessor extends TextProcessor {
    process(text) {
        return text;
    }
}

// Base decorator
class TextProcessorDecorator extends TextProcessor {
    constructor(processor) {
        super();
        this._processor = processor;
    }

    process(text) {
        return this._processor.process(text);
    }
}

// Concrete decorators
class CapitalizeDecorator extends TextProcessorDecorator {
    process(text) {
        const processedText = this._processor.process(text);
        return processedText.toUpperCase();
    }
}

class TrimDecorator extends TextProcessorDecorator {
    process(text) {
        const processedText = this._processor.process(text);
        return processedText.trim();
    }
}

class HTMLEscapeDecorator extends TextProcessorDecorator {
    process(text) {
        const processedText = this._processor.process(text);
        return processedText
            .replace(/&/g, "&")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;")
            .replace(/"/g, "&quot;")
            .replace(/'/g, "&#039;");
    }
}

class MarkdownToHTMLDecorator extends TextProcessorDecorator {
    process(text) {
        const processedText = this._processor.process(text);
        return processedText
            .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
            .replace(/\*(.*?)\*/g, '<em>$1</em>')
            .replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2">$1</a>')
            .replace(/^# (.*$)/gm, '<h1>$1</h1>')
            .replace(/^## (.*$)/gm, '<h2>$1</h2>');
    }
}

class ValidationDecorator extends TextProcessorDecorator {
    constructor(processor, maxLength = 1000) {
        super(processor);
        this.maxLength = maxLength;
    }

    process(text) {
        if (!text) {
            throw new Error("Text cannot be empty");
        }
        if (text.length > this.maxLength) {
            throw new Error(`Text length exceeds maximum limit of ${this.maxLength} characters`);
        }
        return this._processor.process(text);
    }
}

// Text processing manager
class TextProcessingManager {
    constructor() {
        this.processor = new SimpleTextProcessor();
        this.history = [];
    }

    addCapitalization() {
        this.processor = new CapitalizeDecorator(this.processor);
        return this;
    }

    addTrimming() {
        this.processor = new TrimDecorator(this.processor);
        return this;
    }

    addHTMLEscaping() {
        this.processor = new HTMLEscapeDecorator(this.processor);
        return this;
    }

    addMarkdownProcessing() {
        this.processor = new MarkdownToHTMLDecorator(this.processor);
        return this;
    }

    addValidation(maxLength) {
        this.processor = new ValidationDecorator(this.processor, maxLength);
        return this;
    }

    process(text) {
        const result = this.processor.process(text);
        this.history.push({
            input: text,
            output: result,
            timestamp: new Date()
        });
        return result;
    }

    getProcessingHistory() {
        return this.history;
    }
}

// Usage example
const manager = new TextProcessingManager();

// Configure text processing chain
manager
    .addValidation(2000)
    .addTrimming()
    .addMarkdownProcessing()
    .addHTMLEscaping();

// Process some text
try {
    const input = `
    # Welcome to Text Processing
    
    This is a **bold** and *italic* text example.
    [Click here](https://example.com) to learn more.
    `;

    const result = manager.process(input);
    console.log("Processed text:");
    console.log(result);

    console.log("\nProcessing history:");
    console.log(manager.getProcessingHistory());
} catch (error) {
    console.error("Error processing text:", error.message);
}

용어 정리

용어설명

참고 및 출처


1. 주제의 분류가 적절한지에 대해 조사

Decorator Pattern(데코레이터 패턴) 은 “Computer Science and Engineering > Software Design and Architecture > Software Design Patterns > GoF > Structural Design Patterns” 분류에 정확히 해당합니다. GoF(Gang of Four) 에서 정의한 구조 (Structural) 패턴 중 하나로, 객체의 기능 확장에 특화된 패턴입니다 [1][2][20].


2. 200 자 요약

데코레이터 패턴은 기존 객체의 코드를 수정하지 않고, 런타임에 동적으로 새로운 기능을 추가할 수 있는 구조적 디자인 패턴입니다. 상속 대신 합성과 위임을 활용하며, 다양한 기능을 조합해 객체의 행동을 유연하게 확장할 수 있습니다 [1][2][3][5].


3. 250 자 개요

Decorator Pattern 은 객체에 새로운 책임이나 기능을 동적으로 추가할 수 있도록 하는 구조 패턴입니다. 기존 객체를 감싸는 래퍼 (Decorator) 객체를 통해 기능을 확장하며, 상속보다 유연하게 기능을 조합할 수 있습니다. 데코레이터와 원본 객체는 동일한 인터페이스를 구현하므로, 클라이언트는 객체가 데코레이터로 감싸졌는지 알 필요 없이 일관된 방식으로 사용할 수 있습니다. 이 패턴은 OCP(개방/폐쇄 원칙) 와 SRP(단일 책임 원칙) 를 잘 지원하며, 실무에서 로깅, 인증, 데이터 변환 등 다양한 기능 확장에 활용됩니다 [1][2][5][6][20].


핵심 개념


주요 내용 정리

패턴 이름과 분류

항목내용
패턴 이름Decorator Pattern(데코레이터 패턴)
분류GoF 구조 (Structural) 패턴

의도 (Intent)

객체에 동적으로 새로운 책임을 추가할 수 있게 하며, 기능 확장에 있어 서브클래싱보다 융통성 있는 방법을 제공한다 [1][2][5][20].


다른 이름 (Also Known As)


동기 (Motivation / Forces)


적용 가능성 (Applicability)


구조 및 아키텍처

구조 다이어그램

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
+-------------------+
|    Component      |<---------------------+
+-------------------+                      |
| +operation()      |                      |
+-------------------+                      |
      ^                                   |
      |                                   |
+-----------+     +-------------------+   |
| Concrete  |     |   Decorator       |---+
| Component |     +-------------------+
+-----------+     | - component       |
|operation()|     | +operation()      |
+-----------+     +-------------------+
                        ^
                        |
                +-------------------+
                | ConcreteDecorator |
                +-------------------+
                | +operation()      |
                +-------------------+

구성 요소 및 역할

구성 요소기능 및 역할
Component공통 인터페이스, 기능 정의
ConcreteComponent실제 기능 구현, 데코레이션 대상 객체
DecoratorComponent 인터페이스 구현, 내부에 Component 참조 (합성)
ConcreteDecoratorDecorator 상속, 구체적인 추가 기능 구현
ClientComponent 인터페이스로 객체 (데코레이터 포함) 조작

필수/선택 구성요소

구분구성 요소기능 및 특징
필수Component공통 인터페이스/추상 클래스
필수ConcreteComponent실제 기능 구현, 데코레이션 대상
필수DecoratorComponent 참조, 기능 위임 및 확장
필수ConcreteDecorator구체적인 추가 기능 구현

주요 원리 및 작동 원리

  1. Client 는 Component 인터페이스로 객체를 사용
  2. Decorator 는 Component 를 감싸고, 기능 호출을 내부 Component 에 위임
  3. ConcreteDecorator 는 위임 전후로 추가 기능을 수행
  4. 여러 Decorator 를 중첩해 다양한 기능 조합 가능

작동 원리 다이어그램

1
[Client] → [ConcreteDecoratorB] → [ConcreteDecoratorA] → [ConcreteComponent]

구현 기법

예시 코드 (Python)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Component:
    def operation(self):
        pass

class ConcreteComponent(Component):
    def operation(self):
        return "기본 기능"

class Decorator(Component):
    def __init__(self, component):
        self.component = component
    def operation(self):
        return self.component.operation()

class ConcreteDecoratorA(Decorator):
    def operation(self):
        return f"{super().operation()} + A 기능"

class ConcreteDecoratorB(Decorator):
    def operation(self):
        return f"{super().operation()} + B 기능"

# 사용 예시
obj = ConcreteDecoratorB(ConcreteDecoratorA(ConcreteComponent()))
print(obj.operation())  # 기본 기능 + A 기능 + B 기능

장점과 단점

구분항목설명
✅ 장점동적 기능 확장런타임에 객체 기능을 동적으로 확장 가능
유연성/조합성다양한 Decorator 조합으로 기능 확장
OCP/SRP 준수기존 코드 수정 없이 기능 추가, 책임 분리
코드 재사용성공통 기능/추가 기능 모듈화, 재사용 용이
⚠ 단점복잡성 증가Decorator/객체 수 증가, 구조 복잡
디버깅 어려움중첩 구조로 인해 추적/테스트 어려움
순서 의존성Decorator 적용 순서에 따라 동작 달라질 수 있음
성능 저하중첩/래핑으로 인한 호출 오버헤드 가능

도전 과제 및 해결책


분류에 따른 종류 및 유형

분류 기준종류/유형설명
적용 방식객체 데코레이터객체 (인스턴스) 단위로 기능 확장
클래스 데코레이터클래스 단위로 기능 확장 (메타프로그래밍 등)
조합 방식단일 데코레이터하나의 Decorator 만 적용
중첩 데코레이터여러 Decorator 중첩 적용

실무 적용 예시

분야적용 예시설명
로깅/모니터링Logger Decorator기존 기능에 로깅/모니터링 동적 추가
인증/보안Auth Decorator인증/권한 검사 기능 추가
데이터 변환Data Transform Decorator데이터 포맷 변환, 필터 기능 추가
Java I/OInputStream DecoratorBufferedInputStream 등 데코레이터 구조

활용 사례 (시나리오 기반)

상황 가정: 커피 주문 시스템

1
[Client] → [SyrupDecorator] → [WhippedCreamDecorator] → [SimpleCoffee]

실무에서 효과적으로 적용하기 위한 고려사항 및 주의점

항목설명권장사항
Decorator 수 관리Decorator/객체 수 증가 가능공통 Decorator 추상화, 문서화, 코드 생성 도구 활용
순서 관리Decorator 순서에 따라 동작 달라질 수 있음적용 순서 명확화, 테스트 강화
디버깅/테스트중첩 구조로 추적/테스트 어려움단위 테스트, 로깅/시각화 도구 활용
성능 관리중첩/래핑으로 인한 오버헤드 발생 가능필요 Decorator 만 적용, 불필요한 중첩 최소화

최적화하기 위한 고려사항 및 주의점

항목설명권장사항
호출 오버헤드중첩 구조로 호출 비용 증가불필요 Decorator 최소화, 직접 구현 검토
객체 생성 비용Decorator/객체 수 증가객체 풀, 싱글턴 등 활용
메모리 관리객체 수 증가로 메모리 부담GC 활용, 객체 수명 관리
테스트 자동화다양한 조합 테스트 필요자동화 테스트, Mock 활용

2025 년 기준 최신 동향

주제항목설명
함수형/메타함수/클래스 데코레이터Python 등에서 함수/클래스 데코레이터 활용 증가
마이크로서비스미들웨어/필터 체인인증/로깅 등 미들웨어 체인에 데코레이터 패턴 적용
테스트Mock Decorator테스트 자동화, Mock Decorator 활용 증가
성능데코레이터 최적화오버헤드 최소화, 코드 생성 도구 활용

주제와 관련하여 주목할 내용

주제항목설명
합성/위임상속 대체상속 대신 합성/위임으로 기능 확장
OCP/SRP개방/폐쇄, 단일 책임기능 확장과 책임 분리 실현
비교 패턴프록시/어댑터구조 유사, 목적/용도 차이
Java I/OInputStream Decorator데코레이터 패턴 대표 사례

앞으로의 전망

주제항목설명
함수형/메타함수/클래스 데코레이터언어별 데코레이터 활용 확산
마이크로서비스미들웨어/필터 체인인증/로깅 등 체인 구조 확산
테스트Mock Decorator테스트 자동화, Mock Decorator 활용 증가
성능최적화 도구데코레이터 최적화, 코드 생성 도구 활용 증가

하위 주제별 추가 학습 필요 내용

카테고리주제간략 설명
패턴 구조합성/위임상속 대신 합성/위임 구조 학습
테스트Mock Decorator테스트 자동화/Mock Decorator 설계
비교 패턴프록시/어댑터구조/목적 차이 학습
함수형함수/클래스 데코레이터Python 등 함수/클래스 데코레이터 구현법

추가 학습/알아야 할 내용

카테고리주제간략 설명
소프트웨어 아키텍처미들웨어/필터 체인데코레이터 패턴 활용 미들웨어 구조
성능데코레이터 최적화오버헤드/메모리 관리 최적화 기법
프레임워크Java I/O, Express 등프레임워크 내 데코레이터 활용법
실무 도구코드 생성 도구데코레이터 자동 생성/관리 도구 활용

용어 정리

용어설명
Component공통 인터페이스/추상 클래스, 기능 정의
ConcreteComponent실제 기능 구현 클래스, 데코레이션 대상
DecoratorComponent 구현, 내부에 Component 참조
ConcreteDecoratorDecorator 상속, 구체적인 추가 기능 구현
합성 (Composition)객체 참조 기반 구조, 상속 대신 사용
위임 (Delegation)기능 호출을 내부 객체에 위임하는 구조

참고 및 출처

What Is the Decorator Design Pattern?

Decorator 패턴은 객체의 기능을 동적으로 확장할 수 있도록 설계된 구조적 디자인 패턴입니다. 이 패턴은 상속을 사용하지 않고도 객체의 행동을 변경하거나 확장할 수 있게 해주며, 코드의 유연성과 재사용성을 높이는 데 기여합니다.


1. 주제 분류의 적절성

Decorator 패턴은 “GoF (Gang of Four)” 에서 정의한 23 가지 디자인 패턴 중 하나로, 구조적 디자인 패턴 (Structural Design Patterns) 에 속합니다. 따라서 주제 분류인 “Computer Science and Engineering > Software Design and Architecture > Software Design Patterns > GoF > Structural Design Patterns” 은 적절합니다.


2. 요약 설명 (200 자 내외)

Decorator 패턴은 객체에 새로운 기능을 동적으로 추가할 수 있게 해주는 구조적 디자인 패턴으로, 상속 없이도 객체의 행동을 확장할 수 있어 코드의 유연성과 재사용성을 높입니다.


3. 전체 개요 (250 자 내외)

Decorator 패턴은 객체의 기능을 동적으로 확장할 수 있도록 설계된 구조적 디자인 패턴입니다. 이 패턴은 상속을 사용하지 않고도 객체의 행동을 변경하거나 확장할 수 있게 해주며, 코드의 유연성과 재사용성을 높이는 데 기여합니다. Decorator 패턴은 기본 객체를 래핑하는 데코레이터 객체를 통해 추가 기능을 부여하며, 이러한 구조는 다양한 기능의 조합을 가능하게 합니다.


4. 핵심 개념


5. 주요 원리 및 작동 원리

Decorator 패턴은 기본 객체를 데코레이터 객체로 감싸는 구조를 통해 기능을 확장합니다. 각 데코레이터는 동일한 인터페이스를 구현하여, 클라이언트는 데코레이터와 기본 객체를 동일하게 취급할 수 있습니다. 이러한 구조는 기능의 조합과 확장을 유연하게 만들어 줍니다.(GeeksforGeeks)


6. 구조 및 아키텍처

구성 요소

다이어그램

다음은 Decorator 패턴의 구조를 나타낸 UML 다이어그램입니다:

Decorator Pattern UML Diagram


7. 구현 기법

Decorator 패턴은 다양한 언어에서 구현할 수 있으며, 각 언어의 특성에 따라 구현 방식이 다를 수 있습니다. 예를 들어, Python 에서는 함수 데코레이터를 사용하여 기능을 확장할 수 있고, Java 에서는 인터페이스와 클래스를 활용하여 구현할 수 있습니다.


8. 장점과 단점

구분항목설명
✅ 장점유연성객체의 기능을 동적으로 확장할 수 있어 유연한 설계가 가능합니다.
재사용성기능을 모듈화하여 다양한 조합으로 재사용할 수 있습니다.
⚠ 단점복잡성 증가데코레이터의 중첩이 많아지면 구조가 복잡해질 수 있습니다.
디버깅 어려움여러 데코레이터가 중첩되면 디버깅이 어려울 수 있습니다.

9. 도전 과제


10. 분류에 따른 종류 및 유형

Decorator 패턴은 기능의 추가 방식에 따라 다양한 유형으로 분류될 수 있습니다.

유형설명
기능 확장 데코레이터기존 기능에 새로운 기능을 추가하는 데코레이터
기능 변경 데코레이터기존 기능의 동작을 변경하는 데코레이터
기능 제거 데코레이터기존 기능을 제거하거나 무력화하는 데코레이터

11. 실무 적용 예시

Decorator 패턴은 다양한 실무 환경에서 활용될 수 있습니다.

분야예시
GUI 개발스크롤바, 테두리 등 다양한 UI 요소를 동적으로 추가
로깅 시스템로그 메시지에 시간, 레벨 등의 정보를 동적으로 추가
데이터 처리데이터에 필터링, 변환 등의 기능을 동적으로 적용

12. 활용 사례

예를 들어, 커피 주문 시스템에서 기본 커피에 우유, 시럽, 휘핑크림 등을 동적으로 추가하는 경우 Decorator 패턴을 활용할 수 있습니다. 각 추가 요소는 데코레이터로 구현되어, 다양한 조합의 커피를 유연하게 생성할 수 있습니다.


13. 실무에서 효과적으로 적용하기 위한 고려사항 및 주의할 점

고려사항설명권장사항
데코레이터의 책임 분리각 데코레이터는 하나의 책임만 가지도록 설계단일 책임 원칙 (SRP) 을 준수
데코레이터의 순서 관리데코레이터의 적용 순서에 따라 결과가 달라질 수 있음적용 순서를 명확히 정의
중복 기능 방지여러 데코레이터에서 동일한 기능을 중복 구현하지 않도록 주의기능의 중복 여부를 검토

14. 성능을 최적화하기 위한 고려사항 및 주의할 점

고려사항설명권장사항
데코레이터의 수 제한과도한 데코레이터의 중첩은 성능 저하를 초래할 수 있음필요한 최소한의 데코레이터만 사용
캐싱 활용반복되는 연산 결과를 캐싱하여 성능 향상적절한 캐싱 전략 수립
지연 초기화필요한 시점에 데코레이터를 초기화하여 리소스 절약Lazy Initialization 기법 활용

15. 용어 정리

용어설명
Component기본 인터페이스 또는 추상 클래스
ConcreteComponent기본 기능을 구현한 클래스
DecoratorComponent 인터페이스를 구현하고, Component 객체를 포함하는 추상 클래스
ConcreteDecoratorDecorator 를 상속하여 추가 기능을 구현한 클래스

16. 참고 및 출처


물론입니다. 아래는 “16. 참고 및 출처 " 이후 이어지는 내용입니다.


17. 2025 년 기준 최신 동향

주제항목설명
데코레이터 패턴함수형 언어와의 통합JavaScript, Python 등의 함수형 기능과 결합되어 데코레이터가 함수나 클래스의 메타정보 처리에 활용됨
마이크로서비스미들웨어 기반 데코레이터인증, 로깅, 모니터링 기능을 서비스 간에 공통 적용하기 위한 데코레이터 아키텍처 도입
클라우드 네이티브정책 기반 컴포넌트 구성Kubernetes 오퍼레이터/CRD(사용자 정의 리소스) 처리에 데코레이터 유사 구조 활용
AOP (관점 지향 프로그래밍)데코레이터 패턴 대체AOP 프레임워크 (Spring AOP 등) 가 데코레이터 역할을 동적으로 수행하며 확장성 확보

18. 주제와 관련하여 주목할 내용

주제항목설명
데코레이터와 AOP책임 분리AOP 는 런타임 시점에서 공통 관심사를 분리하지만 데코레이터는 정적인 조합 구조로 모듈화
데코레이터와 프록시구조적 유사성프록시는 접근 제어, 데코레이터는 기능 확장에 초점을 둠. 구조는 유사하지만 목적이 다름
데코레이터와 전략 패턴기능 구성 방식전략 패턴은 알고리즘 교체, 데코레이터는 기능 누적 방식으로 차별화됨

19. 앞으로의 전망

주제항목설명
디자인 패턴선언적/구성 기반 개발데코레이터는 선언적 기능 조합을 위한 구성 도구로 더 많이 활용될 것으로 예측
프론트엔드 아키텍처UI 구성 요소 데코레이션React, Vue 등의 컴포넌트 기반 UI 에서 데코레이터 유사 구조를 통한 상태/스타일 조합 확산
백엔드 미들웨어인터셉터 기반 확장Express.js, NestJS 등에서 요청 - 응답 흐름을 확장하는 데 데코레이터 구조 활용 강화

20. 하위 주제 및 학습 항목 정리

카테고리주제설명
디자인 패턴AOP vs 데코레이터코드 확장 방식과 적용 시점의 차이점에 대한 이해 필요
코드 품질단일 책임 원칙데코레이터가 여러 책임을 동시에 가질 경우 복잡도 증가
테스트 전략데코레이터 테스트데코레이터가 추가된 객체에 대한 단위 테스트 작성 기법
프레임워크 활용NestJS 데코레이터메타프로그래밍 기반 데코레이터 정의 및 활용 실습

21. 관련 분야와 함께 학습할 내용

카테고리주제설명
객체지향 설계Open-Closed Principle데코레이터는 기존 코드를 수정하지 않고 확장 가능한 구조를 제공함
클린 아키텍처계층 간 데코레이터 사용인터페이스 - 어댑터 계층에서 데코레이터를 통해 공통 로직 적용 가능
함수형 프로그래밍고차 함수 (HOF)함수형 언어에서 데코레이터는 고차 함수 개념과 연결됨
프레임워크 디자인플러그인 시스템데코레이터는 플러그인 기반의 시스템 아키텍처에서 유용하게 활용됨

용어 정리

용어설명
데코레이터 (Decorator)객체의 기능을 동적으로 확장할 수 있도록 설계된 구조적 디자인 패턴
Component데코레이터가 감싸는 기본 객체 또는 인터페이스
ConcreteComponent실제 기능을 구현한 기본 객체
ConcreteDecorator기능을 확장한 데코레이터 클래스
AOP (Aspect-Oriented Programming)공통 관심사를 모듈화하여 핵심 비즈니스 로직과 분리하는 프로그래밍 패러다임
프록시 (Proxy) 패턴객체에 대한 접근을 제어하는 구조적 패턴으로 데코레이터와 구조적으로 유사

참고 및 출처


이후 원하시는 비교 예시 (예: Decorator vs Composite vs Proxy 등), 실무 코드 작성, 프레임워크 적용 사례 (NestJS, Spring 등) 등도 계속해서 정리해드릴 수 있습니다. 필요하신 항목 알려주세요.

아래는 Decorator vs Composite vs Proxy 패턴에 대한 실무 중심 비교표와 함께 각 패턴의 구조, 목적, 사용 시점 차이점 등을 정리한 내용입니다.


✅ 디자인 패턴 비교: Decorator vs Composite vs Proxy

항목Decorator (데코레이터)Composite (컴포지트)Proxy (프록시)
🔍 목적객체의 기능을 동적으로 확장객체의 계층 구조 표현 및 일관된 방식으로 처리객체 접근 제어 또는 지연 초기화
🧩 구조적 핵심객체를 래핑(wrapping)하여 새로운 기능 추가트리 구조 구성(Leaf/Composite)실제 객체에 대한 인터페이스를 동일하게 유지
🧪 사용 조건런타임 중 기능 확장이 필요할 때계층적 구조를 동일한 방식으로 처리할 때접근 제어, 로깅, 캐싱, 원격 호출 등이 필요할 때
🔄 동적 기능 변경가능 (조합 순서에 따라 변화)불가 (계층 구조 고정적)제한적 (기능 위임 중심)
🧱 클래스 수 증가많아짐 (데코레이터마다 클래스 필요)중간 수준 (Leaf/Composite 구분)적음 (프록시와 실제 객체 1:1)
🔐 대표 사용 사례스트림 처리 (Java I/O), 인증, 캐싱폴더-파일 트리 구조, UI 컴포넌트Virtual Proxy, Remote Proxy, Protection Proxy
🔁 조합/중첩중첩 가능 (계속 감싸기)자식들을 포함하는 구조중첩보단 단일 위임 중심
🧠 대표 원칙 기반개방-폐쇄 원칙(OCP), 책임 연쇄전체-부분 계층 구조대리 제어(Surrogate Control)

📌 사용 시점에 따른 판단 가이드

조건추천 패턴
기능을 확장하면서 객체를 감싸고 싶은 경우Decorator
여러 객체들을 동일한 방식으로 반복 처리하고 싶은 경우Composite
실제 객체를 감추고, 접근을 통제하고 싶은 경우Proxy

🎯 패턴 구조 다이어그램 비교

🔧 Decorator

1
2
3
Component
ConcreteComponent <── Decorator ──> ConcreteDecoratorA/B

🌲 Composite

1
2
3
4
5
Component
 ├── Leaf
 └── Composite
       ├── Leaf
       └── Composite (재귀 가능)

🛡 Proxy

1
Client → Proxy → RealSubject

🛠 실무 적용 예시

패턴실무 활용 예시
DecoratorNestJS나 Flask에서 인증, 로깅 기능을 @데코레이터로 확장
CompositeReact/Angular UI 컴포넌트 구조, 폴더-파일 관리 시스템
ProxySpring AOP, JPA Lazy Loading, gRPC Stub Wrapper

필요하시면 위의 패턴들을 조합한 복합 구조 예시나, Spring / NestJS / Django 기반 프레임워크 적용 사례도 제공해드릴 수 있습니다.

데코레이터 패턴 (Decorator Pattern)에 대해 포괄적으로 조사하고 분석해드리겠습니다.

이제 데코레이터 패턴에 대한 포괄적인 내용을 정리하겠습니다.

데코레이터 패턴 (Decorator Pattern) 조사 보고서

1. 주제 분류 검증

제시된 분류 **“Computer Science and Engineering” > “Software Design and Architecture” > “Software Design Patterns” > “GoF” > “Structural Design Patterns”**는 적절합니다. 데코레이터 패턴은 GoF(Gang of Four)의 23가지 디자인 패턴 중 하나이며, 구조적 패턴(Structural Pattern)으로 분류됩니다.

2. 요약 설명 (200자 내외)

데코레이터 패턴은 기존 객체의 구조를 변경하지 않고 런타임에 동적으로 새로운 기능을 추가할 수 있는 구조적 디자인 패턴입니다. 래퍼 객체를 사용하여 객체를 감싸고 동일한 인터페이스를 유지하면서 추가 책임을 부여하며, 상속 대신 컴포지션을 활용하여 유연성을 제공합니다.

3. 전체 개요 (250자 내외)

데코레이터 패턴은 객체지향 설계에서 개방-폐쇄 원칙을 준수하며 기존 코드의 수정 없이 기능을 확장할 수 있게 해주는 강력한 패턴입니다. 상속의 경직성을 극복하고 런타임에 동적으로 기능을 조합할 수 있어 높은 유연성을 제공합니다. Java I/O 스트림, GUI 컴포넌트, 스트리밍 서비스의 기능 추가 등 다양한 실무 영역에서 활용되며, 특히 다중 기능 조합이 필요한 시나리오에서 효과적입니다.

4. 핵심 개념

기본 개념

심화 개념


제1부: 패턴의 기본 이해

배경

데코레이터 패턴은 상속의 한계를 극복하기 위해 개발되었습니다. 상속은 컴파일 타임에 행위가 결정되어 런타임에 유연한 기능 조합이 어려운 반면, 데코레이터 패턴은 런타임에 동적으로 기능을 추가하거나 제거할 수 있습니다.

목적 및 필요성

주요 기능 및 역할

  1. 기능 래핑: 기존 객체를 새로운 기능으로 감싸기
  2. 투명한 인터페이스: 클라이언트가 데코레이터 사용을 인지하지 못함
  3. 동적 조합: 런타임에 기능들을 자유롭게 조합
  4. 책임 분산: 각 데코레이터가 특정 책임만 담당

특징

핵심 원칙

  1. 개방-폐쇄 원칙 (Open-Closed Principle): 확장에는 열려있고 수정에는 닫힘
  2. 단일 책임 원칙 (Single Responsibility Principle): 각 데코레이터가 하나의 책임만 담당
  3. 컴포지션 우선 원칙: 상속보다 컴포지션 활용
  4. 인터페이스 분리 원칙: 클라이언트가 사용하지 않는 인터페이스에 의존하지 않음

주요 원리 및 작동 원리

데코레이터 패턴의 작동 원리는 다음과 같습니다:

  1. Component 인터페이스 정의: 공통 인터페이스 설정
  2. ConcreteComponent 구현: 기본 기능을 가진 구체적 구현체
  3. Decorator 추상 클래스: Component 인터페이스를 구현하고 Component 참조 보유
  4. ConcreteDecorator 구현: 구체적인 추가 기능을 구현
  5. 클라이언트 사용: 필요한 데코레이터들을 조합하여 사용
1
2
Client -> ConcreteDecorator1 -> ConcreteDecorator2 -> ConcreteComponent
           (기능1 추가)        (기능2 추가)         (기본 기능)

제2부: 구조 및 아키텍처

구조 및 아키텍처

데코레이터 패턴은 4가지 핵심 구성요소로 이루어져 있습니다:

필수 구성요소

구성요소기능역할특징
Component공통 인터페이스 정의데코레이터와 구체 컴포넌트의 공통 인터페이스 제공추상 클래스 또는 인터페이스
ConcreteComponent기본 기능 구현데코레이션될 기본 객체의 구현체Component 인터페이스를 구현
Decorator데코레이터 기반 클래스Component 참조를 보유하고 위임 기능 제공추상 클래스로 구현
ConcreteDecorator구체적 기능 추가실제 추가 기능을 구현하는 구체적 데코레이터Decorator를 상속하여 구현

UML 클래스 다이어그램 구조

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
┌─────────────────┐
│   <<interface>> │
│    Component    │
│                 │
│ + operation()   │
└─────────────────┘
    ┌────┴────┐
    │         │
┌───────────────┐ ┌─────────────────┐
│ConcreteCompo- │ │   Decorator     │◇────────┐
│nent           │ │                 │         │
│               │ │ - component:    │         │
│+ operation()  │ │   Component     │         │
└───────────────┘ │                 │         │
                  │ + operation()   │         │
                  └─────────────────┘         │
                           △                  │
                           │                  │
                  ┌────────────────┐          │
                  │ConcreteDecora- │          │
                  │tor             │          │
                  │                │          │
                  │+ operation()   │──────────┘
                  │+ addBehavior() │
                  └────────────────┘

구성 요소별 상세 기능

1. Component (컴포넌트 인터페이스)

2. ConcreteComponent (구체 컴포넌트)

3. Decorator (데코레이터 추상 클래스)

4. ConcreteDecorator (구체적 데코레이터)


제3부: 구현 및 활용

구현 기법

1. 기본 구현 기법

정의: Component 인터페이스를 기반으로 한 표준 데코레이터 구현 구성: 인터페이스 정의 → 기본 구현체 → 추상 데코레이터 → 구체적 데코레이터 목적: 런타임에 객체의 기능을 동적으로 확장 실제 예시:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Component 인터페이스
interface Coffee {
    String getDescription();
    double getCost();
}

// ConcreteComponent
class BasicCoffee implements Coffee {
    public String getDescription() { return "Basic Coffee"; }
    public double getCost() { return 2.0; }
}

// Decorator
abstract class CoffeeDecorator implements Coffee {
    protected Coffee coffee;
    public CoffeeDecorator(Coffee coffee) { this.coffee = coffee; }
}

// ConcreteDecorator
class MilkDecorator extends CoffeeDecorator {
    public MilkDecorator(Coffee coffee) { super(coffee); }
    public String getDescription() { return coffee.getDescription() + ", Milk"; }
    public double getCost() { return coffee.getCost() + 0.5; }
}

2. 함수형 데코레이터 기법

정의: 함수형 프로그래밍 개념을 활용한 데코레이터 구현 구성: 고차 함수를 활용하여 기능을 동적으로 조합 목적: 더 간결하고 유연한 기능 조합 실제 예시:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
def timing_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f"실행 시간: {time.time() - start}")
        return result
    return wrapper

@timing_decorator
def slow_function():
    time.sleep(1)
    return "완료"

3. 의존성 주입 기반 데코레이터

정의: 의존성 주입 컨테이너를 활용한 데코레이터 등록 및 관리 구성: IoC 컨테이너에서 데코레이터 체인 자동 구성 목적: 데코레이터의 생명주기 관리 및 자동 와이어링 실제 예시: Spring Framework의 AOP, .NET의 Scrutor 라이브러리

장점과 단점

구분항목설명
✅ 장점런타임 유연성컴파일 타임이 아닌 런타임에 동적으로 기능 조합 가능
개방-폐쇄 원칙 준수기존 코드 수정 없이 새로운 기능 확장 가능
기능 조합성여러 데코레이터를 자유롭게 조합하여 다양한 기능 조합 구현
단일 책임 원칙각 데코레이터가 하나의 특정 기능만 담당
메모리 효율성상속 계층보다 메모리 효율적인 객체 구성
⚠ 단점복잡성 증가많은 데코레이터 사용 시 코드 복잡도 급증
디버깅 어려움중첩된 데코레이터로 인한 호출 체인 추적 困難
성능 오버헤드메서드 위임으로 인한 성능 저하
순서 의존성데코레이터 적용 순서에 따른 결과 차이
클래스 개수 증가각 기능별로 별도 데코레이터 클래스 필요

도전 과제

1. 데코레이터 순서 의존성

문제: 데코레이터 적용 순서에 따라 결과가 달라지는 문제 해결책:

2. 성능 오버헤드

문제: 여러 데코레이터 중첩으로 인한 성능 저하 해결책:

3. 디버깅 복잡성

문제: 중첩된 데코레이터로 인한 디버깅 어려움 해결책:

분류에 따른 종류 및 유형

분류 기준유형설명예시
적용 시점정적 데코레이터컴파일 타임에 결정되는 데코레이터Java Annotation
동적 데코레이터런타임에 동적으로 적용되는 데코레이터Proxy 기반 데코레이터
기능 범위행위 데코레이터객체의 행동을 변경하는 데코레이터로깅, 캐싱 데코레이터
상태 데코레이터객체의 상태를 확장하는 데코레이터속성 추가 데코레이터
구현 방식상속 기반클래스 상속을 활용한 데코레이터전통적인 GoF 패턴
컴포지션 기반객체 합성을 활용한 데코레이터현대적 구현 방식
함수형함수를 활용한 데코레이터Python 데코레이터

실무 적용 예시

도메인적용 사례기본 컴포넌트데코레이터 예시
I/O 처리Java I/O StreamFileInputStreamBufferedInputStream, GZIPInputStream
웹 서비스HTTP 요청 처리BasicHttpHandlerAuthenticationDecorator, LoggingDecorator
GUI 개발윈도우 컴포넌트BasicWindowScrollBarDecorator, BorderDecorator
게임 개발캐릭터 아이템BasicWeaponDamageBoostDecorator, SpeedDecorator
데이터베이스연결 관리BasicConnectionPooledConnectionDecorator, CachingDecorator
메시징알림 시스템EmailNotifierSMSDecorator, SlackDecorator

제4부: 고급 주제 및 최신 동향

활용 사례

시나리오: 스트리밍 서비스의 비디오 처리 시스템

상황: 대규모 비디오 스트리밍 플랫폼에서 사용자별 맞춤 비디오 처리가 필요한 상황

시스템 구성:

1
2
3
4
5
VideoProcessor (기본 컴포넌트)
├── SubtitleDecorator (자막 추가)
├── QualityEnhancer (화질 향상)
├── CompressionDecorator (압축 처리)
└── AnalyticsDecorator (시청 분석)

시스템 구성 다이어그램:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
[Client Request] 
[AnalyticsDecorator] ← 시청 데이터 수집
[CompressionDecorator] ← 대역폭에 따른 압축
[QualityEnhancer] ← AI 기반 화질 향상
[SubtitleDecorator] ← 언어별 자막 추가
[VideoProcessor] ← 기본 비디오 처리
[Processed Video Stream]

Workflow:

  1. 요청 수신: 클라이언트가 비디오 스트리밍 요청
  2. 분석 시작: AnalyticsDecorator가 시청 패턴 분석 시작
  3. 압축 적용: 사용자 네트워크 환경에 따른 압축 레벨 결정
  4. 화질 향상: AI 알고리즘을 통한 실시간 화질 개선
  5. 자막 처리: 사용자 언어 설정에 따른 자막 오버레이
  6. 기본 처리: 핵심 비디오 디코딩 및 스트리밍 준비
  7. 결과 전송: 최종 처리된 비디오 스트림 전송

데코레이터별 역할:

실무에서 효과적으로 적용하기 위한 고려사항 및 주의할 점

구분고려사항권장사항
설계 단계인터페이스 안정성 확보변경 가능성이 낮은 핵심 인터페이스 설계
성능 관리데코레이터 체인 깊이 제한최대 5단계 이내로 제한하고 성능 모니터링
테스트 전략각 데코레이터별 단위 테스트독립적 테스트와 조합 테스트 병행
문서화데코레이터 사용 가이드 작성적용 순서와 호환성 매트릭스 제공
예외 처리데코레이터별 예외 전파 규칙일관된 예외 처리 체계 구축
메모리 관리데코레이터 생명주기 관리적절한 가비지 컬렉션과 리소스 해제

최적화하기 위한 고려사항 및 주의할 점

구분최적화 방안권장사항
캐싱 전략결과 캐싱 및 메모이제이션자주 사용되는 데코레이터 조합 결과 캐싱
지연 로딩필요시점에만 데코레이터 활성화Lazy Initialization 패턴 적용
객체 풀링데코레이터 객체 재사용자주 사용되는 데코레이터 객체 풀 관리
프로파일링성능 병목 지점 식별데코레이터별 실행 시간 측정 및 분석
비동기 처리독립적 데코레이터 병렬 실행CompletableFuture 등을 활용한 비동기 처리
메모리 최적화불필요한 데코레이터 정리생명주기 관리 및 WeakReference 활용

GoF 패턴 상세 정보

패턴 이름과 분류

의도 (Intent)

객체에 추가적인 책임을 동적으로 부여합니다. 데코레이터는 기능 확장을 위한 서브클래싱의 유연한 대안을 제공합니다.

다른 이름 (Also Known As)

동기 (Motivation / Forces)

적용 가능성 (Applicability)

구조 (Structure)

앞서 제시한 UML 다이어그램 참조

참여자 (Participants)

협력 (Collaboration)

데코레이터는 Component에 요청을 전달하고, 전달 전후에 추가 작업을 수행할 수 있습니다.

결과 (Consequences)

장점:

단점:

구현 (Implementation)

샘플 코드 (Sample Code)

앞서 제시한 커피 주문 시스템 예제 참조

알려진 사용 (Known Uses)

2025년 기준 최신 동향

주제항목설명
마이크로서비스서비스 메시 데코레이터Envoy Proxy를 활용한 서비스 간 통신 장식
클라우드 네이티브컨테이너 데코레이터Kubernetes Sidecar 패턴을 통한 기능 확장
AI/ML 통합지능형 데코레이터머신러닝 기반 동적 기능 적용
함수형 프로그래밍고차 함수 활용함수형 언어에서의 데코레이터 패턴 구현
리액티브 시스템스트림 데코레이터반응형 프로그래밍에서의 데이터 스트림 장식

주제와 관련하여 주목할 내용

주제항목설명
AOP 통합관점 지향 프로그래밍Spring AOP와 같은 프레임워크에서의 데코레이터 활용
동적 프록시런타임 코드 생성Castle DynamicProxy, CGLib 등을 활용한 동적 데코레이터 생성
함수형 데코레이터고차 함수 패턴Python, JavaScript 등에서의 함수형 데코레이터 구현
의존성 주입IoC 컨테이너 통합Scrutor, Autofac 등을 통한 데코레이터 자동 등록
성능 모니터링관찰 가능성OpenTelemetry와 같은 도구를 통한 데코레이터 성능 추적

앞으로의 전망

주제항목설명
서버리스 컴퓨팅FaaS 데코레이터AWS Lambda, Azure Functions에서의 함수 장식 패턴
엣지 컴퓨팅분산 데코레이터CDN과 엣지 서버에서의 콘텐츠 변환 및 최적화
블록체인스마트 컨트랙트 데코레이터블록체인 애플리케이션에서의 트랜잭션 장식
양자 컴퓨팅양자 회로 데코레이터양자 알고리즘에서의 회로 변환 패턴
메타버스가상 객체 데코레이터3D 가상 환경에서의 객체 기능 확장

추가 학습 주제 (하위 주제)

카테고리주제설명
관련 패턴Proxy Pattern데코레이터와 프록시의 차이점 및 조합 방법
관련 패턴Composite Pattern데코레이터와 컴포지트의 구조적 유사성
관련 패턴Chain of Responsibility데코레이터 체인과 책임 연쇄의 비교
구현 기법Dynamic Proxy런타임 프록시 생성을 통한 동적 데코레이터
성능 최적화Flyweight Integration데코레이터와 플라이웨이트 패턴의 결합

추가 학습 관련 분야

카테고리주제설명
소프트웨어 아키텍처Microservices Architecture마이크로서비스에서의 데코레이터 활용
함수형 프로그래밍Higher-Order Functions함수형 언어에서의 데코레이터 구현
관점 지향 프로그래밍Aspect-Oriented ProgrammingAOP에서의 횡단 관심사 분리
리액티브 프로그래밍Reactive Streams반응형 시스템에서의 스트림 데코레이션
클라우드 컴퓨팅Serverless Computing서버리스 환경에서의 함수 데코레이션

기타 사항

최신 프레임워크와의 통합

모던 개발 도구 지원

실무 적용 체크리스트

  1. 인터페이스 설계: 변경 가능성이 낮은 안정된 인터페이스 정의
  2. 성능 고려: 데코레이터 체인의 깊이와 성능 영향 분석
  3. 테스트 전략: 단위 테스트와 통합 테스트의 균형
  4. 문서화: 데코레이터 조합 규칙과 사용 가이드 작성
  5. 모니터링: 운영 환경에서의 데코레이터 성능 추적

용어 정리

용어설명
컴포지션 (Composition)객체 간의 “has-a” 관계를 통해 기능을 구성하는 방식
위임 (Delegation)한 객체가 다른 객체에게 작업을 전달하는 메커니즘
투명성 (Transparency)클라이언트가 데코레이터 사용을 인지하지 못하는 특성
재귀적 컴포지션 (Recursive Composition)데코레이터를 중첩하여 다층 구조를 만드는 방식
횡단 관심사 (Cross-cutting Concerns)여러 모듈에 걸쳐 나타나는 공통 기능 (로깅, 보안 등)
사이드카 패턴 (Sidecar Pattern)주 애플리케이션 옆에 보조 컨테이너를 배치하는 패턴
프록시 체인 (Proxy Chain)여러 프록시 객체가 연결된 구조
메소드 인터셉션 (Method Interception)메소드 호출을 가로채어 추가 로직을 실행하는 기법

참고 및 출처