개발블로그

[디자인 패턴] 디자인 패턴이란? 반복되는 설계 문제를 해결하는 방법 본문

STUDY/CS

[디자인 패턴] 디자인 패턴이란? 반복되는 설계 문제를 해결하는 방법

devmel 2026. 9. 3. 17:51
Contents 접기
 

개념

 

개념

소프트웨어 설계에서 자주 반복되는 문제와 그 해결 방식을 정리한 것

 

단, 디자인 패턴은 완성된 코드는 아니다. 

패턴을 그대로 복사해서 붙여 넣는 코드 조각이 아니라, 특정 상황에서 코드를 어떤 구조로 나눌지에 대한 설계 아이디어에 가까움

 

주로 반복되는 설계 문제

반복되는 설계 문제 예시 상황 연결되는 패턴
여러 방식 중 하나를 선택해야 함 카드 결제, 포인트 결제, 쿠폰 결제 중 하나를 선택 전략 패턴
객체 생성 조건이 복잡함 회원 등급에 따라 다른 할인 정책 객체 생성 팩토리 패턴
하나만 존재해야 하는 객체가 있음 설정 관리 객체, 애플리케이션 전역 상태 관리 싱글톤 패턴
서로 맞지 않는 인터페이스를 연결해야 함 외부 결제 API 응답 형식을 내부 결제 코드에 맞춰 사용 어댑터 패턴
상태 변화가 여러 곳에 전달되어야 함 주문 상태가 변경되면 알림, 재고, 배송 시스템에 반영 옵저버 패턴
기존 기능에 부가 기능을 덧붙여야 함 결제 처리 전후로 로깅, 권한 확인, 캐싱 추가 데코레이터 패턴
객체 구조가 복잡한데 같은 방식으로 다뤄야 함 폴더와 파일을 같은 방식으로 탐색 컴포지트 패턴
작업 요청을 나중에 실행하거나 기록해야 함 버튼 클릭, 주문 취소 요청, 작업 큐 처리 커맨드 패턴

 

 

객체지향과 디자인 패턴의 관계 

관점 설명
넓은 의미의 디자인 패턴 소프트웨어 설계 전반에서 반복되는 문제 해결 방식
좁은 의미의 디자인 패턴 객체지향 설계에서 자주 사용되는 구조
GoF 디자인 패턴 대표적인 객체지향 디자인 패턴 모음

 

역할

역할 설명
설계 경험의 재사용 반복되는 문제에 대해 이미 알려진 해결 구조를 참고할 수 있다.
공통 언어 제공 복잡한 설계 구조를 패턴 이름으로 빠르게 공유할 수 있다.
변경 지점 분리 바뀔 가능성이 높은 부분과 유지되는 부분을 나누는 데 도움을 준다.

ex) 결제 방식
변하지 않는 부분 : 주문을 생성하고 결제를 요청하는 흐름
변할 수 있는 부분 : 카드 결제, 포인트 결제, 쿠폰 결제 같은 결제 방식

 


 

자주 사용되는 디자인 패턴

 

패턴 해결하려는 문제 핵심 아이디어
전략 패턴 여러 방식 중 하나를 선택해야 한다. 실행할 방식을 객체로 분리하고 필요할 때 교체한다.

ex) 결제 방식이 카드, 포인트, 쿠폰처럼 여러 개라면 각 방식을 별도의 객체로 분리 할 수 있음
=> 결제 흐름은 유지하면서 결제 방식만 교체할 수 있다. 
변하지 않는 부분 : 결제를 진행하는 흐름
변하는 부분 : 카드 결제, 포인트 결제, 쿠폰 결제
팩토리 패턴 객체 생성 조건이 복잡하다. 객체 생성 책임을 별도의 역할로 분리한다.

ex) 회원 등급에 따라 다른 할인 정책 객체를 만들어야 하면
=> 객체를 사용하는 코드가 생성 조건을 모두 알 필요는 없다. 
생성책임을 별도의 팩토리로 분리하면 사용하는 쪽은 필요한 객체를 받아서 사용하면 됨
변하지 않는 부분 : 할인 정책을 사용한다
변하는 부분 : 어떤 할인 정책 객체를 만들기 결정한다
싱글톤 패턴 하나만 존재해야 하는 객체가 필요하다. 하나의 인스턴스만 사용하도록 제한한다.

ex) 설정 정보나 공용 자원 관리 객체처럼 여러 개 만들어지면 문제가 되는 경우가 있음
=> 하나의 인스턴스만 사용하도록 제한
어댑터 패턴 서로 맞지 않는 인터페이스를 연결해야 한다. 기존 인터페이스를 원하는 형태로 변환한다.

ex) 외부 결제 API가 내부 코드와 다른 형식의 메서드나 응답을 제공할 수 있음
=> 이때 어댑터를 두면, 기존 내부 코드를 크게 바꾸지 않고 외부 API를 연결할 수 있음
옵저버 패턴 상태 변화가 여러 객체에 전달되어야 한다. 변화가 발생하면 관련 객체들에게 알린다.

ex) 주문 상태가 결제 완료로 바뀌면 알림발송, 재고 차감, 배송 준비 같은 작업이 이어질 수 있음
=> 이런 상태 변화가 발생했을 때, 관련 객체들에게 알리는 구조를 만듦 
데코레이터 패턴 기존 기능에 부가 기능을 덧붙여야 한다. 기존 객체를 감싸서 기능을 추가한다.

ex) 기존 결제 처리 로직에 로깅, 권한 확인, 캐싱 같은 기능을 추가해야 할 수 있음
=> 기본 기능 + 권한 확인 추가 + 로깅 추가 + 캐싱 추가 

 

 


 

주의점

 

모든 코드에 패턴을 적용해야 하는 것은 아님. 

패턴을 먼저 정해놓고 코드를 끼워 맞추면 오히려 구조가 복잡해질 수 있다. 

ex) 간단한 조건문으로 충분한 문제에 전략 패턴을 적용하거나, 단순한 객체 생성에 팩토리 패턴을 적용하면 클래스만 불필요하게 늘어날 수 있음 

 

주의점

주의점 설명
패턴을 먼저 고르지 않기 문제를 이해하기 전에 패턴부터 적용하면 과한 설계가 될 수 있다.
이름보다 의도 이해하기 패턴 이름을 외우는 것보다 어떤 문제를 해결하는지 아는 것이 중요하다.
단순한 문제에 과하게 적용하지 않기 작은 코드에는 단순한 함수나 조건문이 더 적합할 수 있다.
언어와 환경 고려하기 언어가 제공하는 기능에 따라 같은 패턴도 더 단순하게 표현될 수 있다.

 

유용한 질문

질문 의미
지금 해결하려는 문제는 무엇인가? 패턴보다 문제를 먼저 확인한다.
이 문제가 반복적으로 나타나는가? 일회성 문제에 과한 구조를 만들지 않는다.
변경 가능성이 높은 부분은 어디인가? 바뀌는 부분과 유지되는 부분을 구분한다.
패턴을 적용하면 코드가 더 이해하기 쉬워지는가? 구조가 늘어나는 만큼 가독성이 좋아지는지 확인한다.
더 단순한 방법은 없는가? 함수, 조건문, 언어 기능으로 충분한지 검토한다.