1. 디자인 패턴이란?

디자인 패턴은 소프트웨어 설계 시 반복적으로 등장하는 문제를 해결하기 위한 일종의 '템플릿'이다. Java Spring에서는 프레임워크 특성상 구조적인 패턴(예: MVC)이나 생성/행위 패턴을 많이 활용한다.

실제로 Spring 기반 프로젝트를 개발하다 보면, 작은 규모의 서비스라도 다양한 디자인 패턴이 유기적으로 사용되는 것을 볼 수 있습니다. 각 컴포넌트가 자신의 책임에 집중하고, 변화에 유연하게 대응할 수 있도록 설계하는 과정에서 자연스럽게 전략(Strategy), 프록시(Proxy), 빌더(Builder) 등 다수의 패턴이 녹아들게 됩니다.

2. 시기별 디자인 패턴 사용 경향

시기 특징 주로 사용된 패턴
Spring Framework 2.x XML 기반 설정, DI/IoC 초창기 Singleton, Factory, Proxy, Template Method
Spring 3.x ~ 4.x Java Config 전환, AOP 정착 Strategy, Decorator, Observer, Command
Spring Boot Auto-configuration, Starter 기반 설정 최소화 Builder, Adapter, Chain of Responsibility, Specification

3. 주요 디자인 패턴 정리 및 실무 예제

 

Singleton 패턴

  • 정의: 인스턴스를 하나만 생성해 공유
  • Spring 적용: 기본 Bean scope가 Singleton
  • 대표 클래스: Spring의 모든 @Component, @Service, @Repository
  • UML (Text 기반):
+----------------+
|   Singleton    |
+----------------+
| - instance     |
+----------------+
| + getInstance()|
+----------------+
  • 실무 예제:
@Service
public class NotificationService {
    public void send(String message) {
        System.out.println("Sending message: " + message);
    }
}

Factory 패턴

  • 정의: 객체 생성 로직을 캡슐화
  • Spring 적용: BeanFactory, FactoryBean
  • 대표 클래스: LocalSessionFactoryBean, SqlSessionFactoryBean
  • UML (Text 기반):
      +-------------+
      |   Product   |
      +-------------+
         ^       ^
         |       |
+---------------------+
|ConcreteProductA/B   |
+---------------------+
         ^
         |
+---------------------+
|   ProductFactory    |
| +createProduct()    |
+---------------------+
  • 실무 예제:
public class AnimalFactory {
    public static Animal createAnimal(String type) {
        return switch (type) {
            case "dog" -> new Dog();
            case "cat" -> new Cat();
            default -> throw new IllegalArgumentException("Unknown type");
        };
    }
}

Proxy 패턴

  • 정의: 대리 객체를 통해 원래 객체 제어
  • Spring 적용: AOP (Aspect Oriented Programming)
  • 대표 클래스: ProxyFactoryBean, @Transactional
  • UML (Text 기반):
     +---------+
     | Subject |
     +---------+
        ^   ^
        |   |
+--------------+  +--------+
| RealSubject  |  | Proxy  |
+--------------+  +--------+
                     |
                     v
              +-------------+
              | RealSubject |
              +-------------+
  • 실무 예제:
@Aspect
@Component
public class LoggingAspect {
    @Before("execution(* com.example.service.*.*(..))")
    public void logBefore() {
        System.out.println("메서드 실행 전 로그 출력");
    }
}

Template Method 패턴

  • 정의: 알고리즘 골격을 정의하고, 일부 단계는 서브클래스에서 구현
  • Spring 적용: JdbcTemplate, RestTemplate
  • 대표 클래스: JdbcTemplate, AbstractController
  • UML (Text 기반):
+------------------+
|  AbstractClass   |
+------------------+
| +templateMethod()|
| +primitiveOp1()  |
| +primitiveOp2()  |
+------------------+
          ^
          |
+------------------+
|  ConcreteClass   |
+------------------+
| +primitiveOp1()  |
| +primitiveOp2()  |
+------------------+
  • 실무 예제:
public abstract class AbstractTask {
    public void execute() {
        start();
        process();
        end();
    }
    protected abstract void process();
    private void start() { System.out.println("Start"); }
    private void end() { System.out.println("End"); }
}

Strategy 패턴

  • 정의: 알고리즘을 클래스로 분리해 캡슐화
  • Spring 적용: AuthenticationProvider, ViewResolver
  • 대표 클래스: HandlerMethodArgumentResolver
  • UML (Text 기반):
     +------------+
     |  Strategy  |
     +------------+
        ^     ^
        |     |
+-------------------+
|ConcreteStrategies |
+-------------------+
        ^
        |
   +-----------+
   |  Context   |
   +-----------+
   | -strategy |
   | +execute()|
   +-----------+
  • 실무 예제:
public interface PaymentStrategy {
    void pay(int amount);
}

public class CreditCardPayment implements PaymentStrategy {
    public void pay(int amount) {
        System.out.println("Paid " + amount + " using credit card.");
    }
}


Builder 패턴

  • 정의: 복잡한 객체 생성을 단계별로 처리
  • Spring 적용: ResponseEntity.builder(), Lombok @Builder
  • 대표 클래스: ResponseEntity, User.builder()
  • UML (Text 기반):
+-----------+       +-----------+
|  Director | ----> |  Builder  |
+-----------+       +-----------+
                         ^
                         |
                +------------------+
                | ConcreteBuilder  |
                +------------------+
                         |
                         v
                    +---------+
                    | Product |
                    +---------+
  • 실무 예제:
@Builder
public class User {
    private String name;
    private int age;
}

Adapter 패턴

  • 정의: 인터페이스 호환을 위한 중간 계층
  • Spring 적용: HandlerAdapter, MessageConverter
  • 대표 클래스: HttpMessageConverter, HandlerAdapter
  • UML (Text 기반):
     +--------+
     | Target |
     +--------+
         ^
         |
     +--------+
     | Adapter|
     +--------+
         |
         v
     +--------+
     | Adaptee|
     +--------+
  • 실무 예제:
public interface MediaPlayer {
    void play(String fileName);
}

public class AudioPlayer implements MediaPlayer {
    public void play(String fileName) {
        System.out.println("Playing " + fileName);
    }
}

Specification 패턴

  • 정의: 조건을 조합해 쿼리 작성
  • Spring 적용: JpaSpecificationExecutor
  • 대표 클래스: Specification<T>
  • UML (Text 기반):
      +------------------+
      |  Specification   |
      +------------------+
      | +isSatisfiedBy() |
      | +and(), or(), not()|
      +------------------+
               ^
               |
   +----------------------------+
   |   ConcreteSpecification   |
   +----------------------------+
  • 실무 예제:
Specification<User> hasName(String name) = (root, query, cb) -> cb.equal(root.get("name"), name);

4. 목적별 디자인 패턴 추천 가이드

Spring 프로젝트에서 상황에 따라 어떤 디자인 패턴을 적용하면 좋을지 정리하면 다음과 같습니다:

목적/상황 추천 패턴 설명
JPA 동적 쿼리 처리 Specification 조건 조합 및 유연한 쿼리 생성을 위해 적합
다양한 외부 시스템 연계 Adapter, Template Method 연계 대상별로 추상화하여 유연하게 연동 가능
복잡한 객체 생성 Builder DTO나 Response 객체를 생성할 때 단계적 설정이 가능
비즈니스 로직 알고리즘 분리 Strategy 정책, 계산 방식, 인증처리 등 알고리즘 선택에 유리
횡단 관심사 처리 Proxy 트랜잭션, 로깅, 인증/인가 등 AOP 기반 처리
템플릿 제공 후 확장 유도 Template Method API 호출, DB 연동 등 공통 로직 제공 후 커스터마이징 허용
서로 다른 구현 통합 필요 Adapter 외부 API, 레거시 시스템 등을 일관된 인터페이스로 변환

이 표를 바탕으로 실무 상황에 맞는 패턴을 선택하면 아키텍처의 유연성과 유지보수성이 크게 향상됩니다

'Back-End > Java & Spring' 카테고리의 다른 글

Factory 패턴 개념  (0) 2025.05.11
싱글톤 패턴 개념& Spring Bean Scope  (0) 2025.05.11
Java GC 로그 해석과 튜닝 전략 정리  (0) 2025.05.10
Java GC 알고리즘 정리  (0) 2025.05.10
CORS 오류 해결하기(Spring)  (0) 2025.03.02

+ Recent posts