핵심 인사이트 (3줄 요약)

  1. 본질: 데코레이터 (Decorator)와 프록시 (Proxy)는 모두 동일 인터페이스로 원본 객체를 감싸는 래퍼 구조를 쓰지만, 데코레이터는 책임 추가가 목적이고 프록시는 접근 통제가 목적이다.
  2. 가치: 두 패턴을 구조가 아니라 의도로 구분할 수 있어야 기능 확장, 보안, 캐시, 지연 로딩, 원격 호출 같은 요구사항에 맞는 설계를 선택할 수 있다.
  3. 판단 포인트: 클라이언트가 어떤 래퍼를 적용할지 직접 조합하면 데코레이터에 가깝고, 클라이언트가 원본처럼 쓰는 사이 중간에서 제어가 개입하면 프록시에 가깝다.

Ⅰ. 개요 및 필요성

데코레이터와 프록시는 GoF (Gang of Four) 구조 패턴에서 가장 자주 혼동되는 쌍이다. 둘 다 Subject 인터페이스를 구현하고, 내부에 실제 객체를 참조하며, 호출을 위임한다. 클래스 다이어그램만 보면 거의 같은 모양이어서 "둘이 뭐가 다른가"라는 질문이 자연스럽게 나온다.

하지만 설계에서 중요한 것은 모양이 아니라 시스템이 그 래핑을 왜 도입했는가이다. 기능을 덧붙이려는가, 아니면 접근 시점을 감시·지연·보호하려는가에 따라 유지보수 방식과 테스트 포인트가 달라진다. 이 차이를 모르면 캐싱, 인증, 로깅, 압축, 지연 로딩 같은 실무 구현을 패턴 이름만 바꿔 부르는 수준에서 멈추게 된다.

┌────────────────────────────────────────────────────────────────────┐
│            같은 외형, 다른 질문: "무엇을 위해 감쌌는가?"          │
├────────────────────────────────────────────────────────────────────┤
│ Client ─▶ Wrapper ─▶ Real Object                                  │
│                                                                    │
│ If goal = add behavior      -> Decorator                           │
│ If goal = control access    -> Proxy                               │
│                                                                    │
│ Same shape, different intent, different design consequence         │
└────────────────────────────────────────────────────────────────────┘

즉 두 패턴의 경계는 코드 문법이 아니라 책임 배치에 있다. 데코레이터는 원본 기능을 유지한 채 부가 기능을 쌓는 쪽에 초점이 있고, 프록시는 원본에 도달하기 전 단계에서 접근 조건을 조절하는 쪽에 초점이 있다.

  • 📢 섹션 요약 비유: 같은 포장지라도 선물을 꾸미기 위한 리본이면 데코레이터이고, 택배를 열기 전에 확인하는 봉인 스티커면 프록시다. 겉모양보다 목적이 다르다.

Ⅱ. 아키텍처 및 핵심 원리

데코레이터의 핵심은 동일 인터페이스를 유지한 채 기능을 계층적으로 추가하는 것이다. 각 데코레이터는 Component 인터페이스를 구현하면서 내부에 또 다른 Component를 들고, 호출 전후에 부가 작업을 붙인다. 이 구조는 여러 기능을 순서대로 조합할 수 있어 상속 폭발을 줄인다.

반면 프록시는 실제 객체에 대한 대리자다. 요청을 바로 전달하지 않고, 권한 확인·원격 연결·캐시 조회·지연 생성 같은 제어 로직을 먼저 수행한다. 클라이언트는 프록시를 특별한 객체로 의식하지 않고, 실제 객체처럼 사용한다는 점이 중요하다.

┌───────────────────────────────┐    ┌───────────────────────────────┐
│ Decorator call path           │    │ Proxy call path               │
├───────────────────────────────┤    ├───────────────────────────────┤
│ Client                        │    │ Client                        │
│   │                           │    │   │                           │
│   ▼                           │    │   ▼                           │
│ LoggingDecorator              │    │ AccessProxy                   │
│   │                           │    │   │ check auth / cache / lazy  │
│   ▼                           │    │   ▼                           │
│ CompressionDecorator          │    │ RealService                   │
│   │                           │    │                               │
│   ▼                           │    │ Transparent to client         │
│ FileStream                    │    └───────────────────────────────┘
│ Explicit stacking by client   │
└───────────────────────────────┘
항목데코레이터 (Decorator)프록시 (Proxy)
핵심 의도책임·기능 추가접근 제어·대리 수행
클라이언트 인지보통 직접 조합함대개 투명하게 사용함
중첩 패턴여러 겹 조합 빈번보통 한 단계 제어가 많음
대표 사례Java I/O (Input/Output), 미들웨어 체인AOP (Aspect-Oriented Programming) 트랜잭션, 지연 로딩, 원격 프록시
설계 위험순서 의존성 증가실제 객체 생명주기 은닉

이 표에서 중요한 것은 "같은 인터페이스 유지"라는 공통점보다, 시스템 책임이 어디에 놓이는가이다. 데코레이터는 기능의 수평 확장에 강하고, 프록시는 보안·성능·분산 환경 제어처럼 원본 접근 조건을 관리하는 데 강하다.

  • 📢 섹션 요약 비유: 데코레이터는 옷 위에 코트와 머플러를 겹쳐 입는 것이고, 프록시는 건물 입구의 출입 게이트다. 하나는 꾸미고 보강하고, 다른 하나는 들어갈 수 있는지 먼저 판단한다.

Ⅲ. 비교 및 연결

패턴 경계를 더 분명히 하려면 데코레이터와 프록시를 유사 패턴과 함께 봐야 한다. 어댑터 (Adapter)는 인터페이스를 바꾸고, 퍼사드 (Facade)는 복잡한 하위 시스템을 단순화하며, 데코레이터와 프록시는 인터페이스를 유지한 채 객체 주변에서 역할을 수행한다. 즉 데코레이터와 프록시는 "같은 계약을 유지하면서 무엇을 바꾸는가"의 문제다.

패턴인터페이스 변화주목적실무 연결
Decorator동일 유지기능 추가로깅, 압축, 포맷 변환, 미들웨어
Proxy동일 유지접근 통제인증, 캐시, 지연 로딩, 원격 호출
Adapter변환호환성 확보레거시 API 연동
Facade새 인터페이스 제공복잡도 감춤서브시스템 진입점 단순화

또한 프록시는 AOP (Aspect-Oriented Programming)와 자연스럽게 이어진다. 트랜잭션, 보안, 로깅 같은 횡단 관심사 (Cross-Cutting Concern)를 원본 코드 밖에서 끼워 넣기 때문이다. 반대로 데코레이터는 함수형 파이프라인이나 HTTP 미들웨어처럼 "기능을 층층이 조합"하는 구조와 친하다. 구조는 닮았지만 시스템 전체에서 맡는 역할의 결이 다르다.

  • 📢 섹션 요약 비유: 어댑터는 플러그 모양을 바꾸는 변환기이고, 퍼사드는 복잡한 기계를 대신 조작해 주는 리모컨이다. 데코레이터와 프록시는 둘 다 원래 기계를 그대로 두지만, 하나는 기능을 덧붙이고 다른 하나는 접근을 관리한다.

Ⅳ. 실무 적용 및 기술사 판단

실무에서 데코레이터와 프록시를 구분하는 가장 좋은 질문은 "클라이언트가 래핑 사실을 알아야 하는가"이다. 예를 들어 BufferedInputStream(new FileInputStream(...))은 개발자가 직접 버퍼링 기능을 선택하므로 데코레이터다. 반면 Spring의 @Transactional은 호출자가 프록시를 의식하지 않아도 트랜잭션 경계가 자동 적용되므로 프록시다.

대표 적용 시나리오

  1. 데코레이터: HTTP (Hypertext Transfer Protocol) 응답에 압축·암호화·로깅을 순서대로 붙이는 미들웨어 체인
  2. 프록시: 권한 체크 후에만 실제 서비스 메서드를 호출하는 보안 프록시
  3. 프록시: 대용량 엔티티를 첫 접근 시점에만 불러오는 지연 로딩 (Lazy Loading)
  4. 데코레이터: 결제 모듈에 추적 ID 부여, 포맷 변환, 재시도 기능을 계층적으로 부착

기술사 판단 체크리스트

  • 기능을 조합 가능한 레이어로 쌓아야 하는가?
  • 원본 객체 접근 전 검증, 캐싱, 원격 연결, 생성 지연이 필요한가?
  • 클라이언트가 어떤 부가 기능이 적용됐는지 알아야 하는가?
  • 래퍼 순서가 결과를 바꾸는가, 아니면 단일 관문 역할만 하면 되는가?

안티패턴

  • 단순 접근 통제를 데코레이터로 구현해 클라이언트가 불필요하게 래퍼를 알아야 하는 경우

  • 기능 추가 요구를 프록시로 억지 구현해 책임 이름은 프록시인데 실제로는 장식 객체가 되어 버리는 경우

  • 여러 데코레이터 순서를 명확히 정의하지 않아 압축 후 암호화와 암호화 후 압축이 뒤섞이는 경우

  • 📢 섹션 요약 비유: 손님이 직접 토핑을 골라 피자를 쌓으면 데코레이터이고, 입구에서 예약자만 들여보내는 안내 데스크면 프록시다. 선택권이 손님 쪽에 있느냐, 통제권이 입구 쪽에 있느냐가 핵심이다.


Ⅴ. 기대효과 및 결론

데코레이터를 올바르게 쓰면 상속 없이 기능 조합이 가능해지고, 프록시를 올바르게 쓰면 핵심 비즈니스 로직을 건드리지 않고 보안·성능·분산 제어를 삽입할 수 있다. 두 패턴 모두 OCP (Open-Closed Principle, 개방-폐쇄 원칙)를 실천하는 데 유용하지만, 그 가치는 서로 다른 종류의 변경을 흡수한다는 데 있다. 데코레이터는 기능 변화를, 프록시는 접근 정책 변화를 흡수한다.

한계도 분명하다. 데코레이터는 계층이 많아질수록 호출 흐름이 복잡해지고, 프록시는 실제 호출 주체가 숨겨져 디버깅이 어려워질 수 있다. 따라서 이 둘을 기억할 때는 "같은 모양"이 아니라 "같은 인터페이스를 유지한 채 무엇을 바꾸려는가"라는 질문으로 정리하는 것이 가장 정확하다.

  • 📢 섹션 요약 비유: 데코레이터는 기존 가방에 주머니를 더 다는 방식이고, 프록시는 가방 보관소의 출입 관리인이다. 둘 다 가방 자체는 바꾸지 않지만, 하나는 기능을 늘리고 다른 하나는 접근을 통제한다.

📌 관련 개념 맵

개념연결 포인트
구조 패턴 (Structural Pattern)두 패턴이 속한 GoF 패턴 분류
OCP (Open-Closed Principle)기존 객체 수정 없이 기능 추가 또는 제어 삽입
AOP (Aspect-Oriented Programming)프록시를 활용한 횡단 관심사 분리
Middleware데코레이터식 기능 체인의 대표 구현
Lazy Loading프록시가 실체 생성을 지연하는 대표 사례

📈 관련 키워드 및 발전 흐름도

객체 래핑 (Object Wrapping)
        │
        ▼
동일 인터페이스 유지
        │
        ├──────────────▶ Decorator: responsibility extension
        │
        └──────────────▶ Proxy: access mediation
                               │
                               ▼
AOP · Lazy Loading · Remote Proxy · Middleware

이 흐름은 래핑 구조가 "기능 추가"와 "접근 제어"라는 두 갈래로 분기되고, 이후 프레임워크 수준 구현으로 확장되는 과정을 보여준다.

👶 어린이를 위한 3줄 비유 설명

  1. 데코레이터는 기본 장난감 자동차에 스티커, 불빛, 날개를 하나씩 붙이는 거예요.
  2. 프록시는 장난감 보관함 앞에서 "이건 지금 꺼내도 되는지" 확인해 주는 문지기예요.
  3. 둘 다 자동차를 직접 바꾸지는 않지만, 하나는 더 멋지게 만들고 다른 하나는 사용을 관리해요.