ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자주 사용되는 디자인 패턴에 대해 알아보자 (springboot)
    Server/Spring Boot 2025. 4. 28. 17:44
    728x90
    반응형

    Spring Boot 개발에서 꼭 알아야 할 디자인 패턴

    1. 싱글턴 패턴 (Singleton Pattern)

    싱글턴 패턴은 객체를 하나만 생성하여 모든 클라이언트가 동일한 인스턴스를 공유하도록 하는 패턴입니다. Spring에서는 주로 @Service, @Component, @Repository 등의 어노테이션을 사용하여 빈을 생성할 때 싱글턴을 기본으로 사용합니다.

    import org.springframework.stereotype.Service;
    
    @Service
    public class SingletonService {
    
        private static SingletonService instance;
    
        private SingletonService() {}
    
        public static SingletonService getInstance() {
            if (instance == null) {
                instance = new SingletonService();
            }
            return instance;
        }
    
        public String getMessage() {
            return "싱글턴 패턴 예제!";
        }
    }

    설명: SingletonService 클래스는 getInstance() 메서드를 통해 객체를 한 번만 생성하고, 그 후에는 동일한 인스턴스를 반환합니다.

    2. 전략 패턴 (Strategy Pattern)

    전략 패턴은 알고리즘을 클래스화하여 각각의 전략을 교환 가능하게 만드는 패턴입니다. Spring에서는 비즈니스 로직을 다양한 전략 객체로 나누어 사용하는 경우가 많습니다.

    // 전략 인터페이스
    public interface PaymentStrategy {
        void pay();
    }
    
    // 콘크리트 전략 1
    public class CreditCardPayment implements PaymentStrategy {
        @Override
        public void pay() {
            System.out.println("신용카드로 결제");
        }
    }
    
    // 콘크리트 전략 2
    public class PaypalPayment implements PaymentStrategy {
        @Override
        public void pay() {
            System.out.println("PayPal로 결제");
        }
    }
    
    // Context
    public class PaymentService {
    
        private PaymentStrategy paymentStrategy;
    
        public PaymentService(PaymentStrategy paymentStrategy) {
            this.paymentStrategy = paymentStrategy;
        }
    
        public void executePayment() {
            paymentStrategy.pay();
    }

    설명: PaymentService 클래스는 PaymentStrategy 인터페이스를 통해 결제 방법을 선택할 수 있게 하며, 필요에 따라 결제 전략을 변경할 수 있습니다.

    3. 팩토리 패턴 (Factory Pattern)

    팩토리 패턴은 객체를 생성하는 인터페이스를 제공하고, 구체적인 클래스의 인스턴스는 서브클래스에서 결정하도록 하는 패턴입니다. Spring에서는 빈을 자동으로 생성할 때 팩토리 메서드 방식이 많이 사용됩니다.

    // 팩토리 인터페이스
    public interface Vehicle {
        void drive();
    }
    
    // 콘크리트 제품 1
    public class Car implements Vehicle {
        @Override
        public void drive() {
            System.out.println("자동차를 운전");
        }
    }
    
    // 콘크리트 제품 2
    public class Bike implements Vehicle {
        @Override
        public void drive() {
            System.out.println("자전거를 타기");
        }
    }
    
    // 팩토리 클래스
    public class VehicleFactory {
    
        public Vehicle createVehicle(String type) {
            if ("car".equalsIgnoreCase(type)) {
                return new Car();
            } else if ("bike".equalsIgnoreCase(type)) {
                return new Bike();
            }
            return null;
        }
    }

    설명: VehicleFactory 클래스는 createVehicle() 메서드를 통해 조건에 맞는 객체를 생성하여 반환합니다.

    4. 옵저버 패턴 (Observer Pattern)

    옵저버 패턴은 한 객체의 상태 변화가 있을 때, 그것을 의존하고 있는 객체들에게 자동으로 알리는 패턴입니다. Spring에서는 ApplicationEventPublisher를 활용하여 이벤트 리스너 패턴을 구현할 때 사용됩니다.

    import org.springframework.context.ApplicationEventPublisher;
    import org.springframework.context.ApplicationEventPublisherAware;
    import org.springframework.stereotype.Component;
    
    @Component
    public class UserService implements ApplicationEventPublisherAware {
    
        private ApplicationEventPublisher publisher;
    
        @Override
        public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
            this.publisher = publisher;
        }
    
        public void createUser(String username) {
            System.out.println("사용자 생성: " + username);
            publisher.publishEvent(new UserCreatedEvent(this, username));
        }
    }
    
    public class UserCreatedEvent extends ApplicationEvent {
    
        private String username;
    
        public UserCreatedEvent(Object source, String username) {
            super(source);
            this.username = username;
        }
    
        public String getUsername() {
            return username;
        }
    }
    
    @Component
    public class UserCreatedEventListener {
    
        @EventListener
        public void onUserCreated(UserCreatedEvent event) {
            System.out.println("새로운 사용자 생성됨: " + event.getUsername());
        }
    }

    설명: UserService는 새로운 사용자가 생성될 때 UserCreatedEvent 이벤트를 발행하고, UserCreatedEventListener는 이를 구독하여 알림을 받습니다.

    5. 데코레이터 패턴 (Decorator Pattern)

    데코레이터 패턴은 객체에 새로운 기능을 동적으로 추가할 수 있는 패턴입니다. Spring에서는 주로 AOP(Aspect-Oriented Programming)에서 사용되며, 메서드 실행 전후에 추가적인 작업을 할 때 사용됩니다.

    public interface Coffee {
        double cost();
    }
    
    public class SimpleCoffee implements Coffee {
        @Override
        public double cost() {
            return 5.0;
        }
    }
    
    public class MilkDecorator implements Coffee {
    
        private Coffee decoratedCoffee;
    
        public MilkDecorator(Coffee coffee) {
            this.decoratedCoffee = coffee;
        }
    
        @Override
        public double cost() {
            return decoratedCoffee.cost() + 1.5;
        }
    }
    
    public class SugarDecorator implements Coffee {
    
        private Coffee decoratedCoffee;
    
        public SugarDecorator(Coffee coffee) {
            this.decoratedCoffee = coffee;
        }
    
        @Override
        public double cost() {
            return decoratedCoffee.cost() + 0.5;
        }
    }

    설명: SimpleCoffee 객체에 MilkDecorator와 SugarDecorator를 추가하여 커피의 비용을 동적으로 변경할 수 있습니다.

    결론

    위에서 소개한 디자인 패턴들은 Spring Boot 애플리케이션에서 자주 사용되는 패턴들이며, 이를 통해 코드의 재사용성, 유지보수성 및 확장성을 높일 수 있습니다.

    728x90
    반응형

    댓글

Designed by Tistory.