ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스프링과 디자인 패턴
    공부방 2023. 8. 27. 20:26

    디자인 패턴

    소프트웨어 디자인 패턴(software design pattern)은 소프트웨어 공학의 소프트웨어 디자인에서 특정 문맥에서 공통적으로 발생하는 문제에 대해 재사용 가능한 해결책이다.

     

    디자인 패턴은 시스템을 디자인 할 때 공통된 문제들을 해결하는데에 쓰이는 형식화 된 관행이라고 볼 수 있다. 

    '스프링 입문을 위한 자바 객체 지향의 원리와 이해' 라는 책에서 소개된 디자인 패턴중 일부를 살펴 보고 이 패턴들이 스프링에서 어떤식으로 사용 되는지 살펴보자

     

    어댑터 패턴

    먼저 어댑터 패턴이 적용되지 않은 두 클래스를 보자

    public class ServiceA{
    	void runServiceA(){
        	System.out.println("ServiceA");
        }
    }
    
    public class ServiceB{
    	void runServiceB(){
        	System.out.println("ServiceB");
        }
    }

    이 두 클래스를 사용하는 곳에서는 runServiceA 와 runServiceB라는 서로 다른 함수를 호출 해야 한다. 위 코드를 어댑터 패턴을 적용해 개선을 해보면 

    public class AdapterServiceA{
    	ServiceA sa = new ServiceA();
        
        void runService(){
        	sa.runServiceA();
        }
    }
    
    public class AdapterServiceB{
    	ServiceB sb = new ServiceB();
        
        void runService(){
        	sb.runServiceB();
        }
    }

    이런식으로 어댑터 클래스를 새로 두어 실제 사용할때는 같은 이름의 함수를 호출하면 된다. 이처럼, 어댑터 패턴은

    "호출당하는 쪽의 메서드를 호출하는 쪽의 코드에 대응하도록 중간에 변환기를 통해 호출하는 패턴" 이라 할 수 있다. 

     

    스프링에서 어댑터 패턴이 사용되는곳은 대표적으로 HandlerAdapter 가 있다. 

    HanderAdapter 중 하나인 SimpleControllerHandlerAdapter를 예시로 보자. handle 이라는 method가 있는데 DispatcerServelet에서는 이 method를 호출하여 handler를 작동시킨다. 이 HandlerAdapter를 구현한 다른 클래스들도 각자에 맞게 handle 함수를 구현하고 호출하는곳에서는 동일하게 handle 을 호출하는 형식이다. 

     

    프록시 패턴

    먼저 프록시 패턴을 적용하지 않은 코드를 보자

    public class Service {
    	public String runSomething(){
       		return "Hello";
        }
    }

    위 클래스를 사용하는곳에서는 Service의 인스턴스를 만들고 runSomething 메소드를 호출할 것이다. 이를 프록시 패턴을 적용하여 수정해 보자.

    public interface IService{
    	String runSomething();
    }
    
    public class Service implements IService{
    	public STring runSomething(){
        	return "Hello";
        }
    }
    
    public class Proxy implements IService{
    	IService service;
        
        public String runSomething() {
        	serive = new Service();
            return service.runSomething();
        }
    }

    위처럼 수정된 코드에서는 Service 의 인스턴스를 생성하는것이 아닌 Proxy의 인스턴스를 생성하고 runSomething 메소드를 호출하면 Service의 runSomething 결과를 마찬가지로 받을 수 있다.

    이게 무슨 차이가 있나 싶겠지만, 이런식으로 Proxy를 통해 대신 호출하게 되면 Proxy의 runSomething에 별도의 제어 흐름을 추가할 수 있다. Service 의 runSomething 전후에 자신이 원하는 로직을 넣을 수 있게되었다. 

    프록시 패턴을 정리하면 "제어 흐름을 조정하기 위한 목적으로 중간에 대리자를 두는 패턴" 이라 할 수 있다. 

     

    스프링에서 프록시 패턴이 적용된 대표적인 부분은 스프링의 AOP 기능이다. 

    스프링 AOP란, Aspect Oriented Programming의 약자이다. 위 그림처럼 여러 클래스에 흩어져있는 관점들을 하나로 모아 처리하는 것이다. 

    대표적인 예로, 스프링에서 @Transactional 는 AOP 방식으로 처리된다. 실제 비즈니스 로직 외에 트랜잭션 시작 등의 전처리와 커밋, 롤백등의 후처리등을 프록시 패턴으로 처리한다. 

     

    싱글톤 패턴

    싱글톤 패턴은 클래스의 인스턴스를 하나만 만들어 사용하는 패턴이다. 

     

    public class Singleton {
    	static Singleton singletonObject;
        
        private Singleton(){};
        
        public static Singleton getInstance(){
        	if(singletonObject == null){
            	singletonObject = new Singleton();
            }
            
            return singletonObject;
        }
    }

    위는 싱글톤 패턴의 예시이다. 물론 아주 좋은 싱글톤 생성 방식은 아니다. 자세한 싱글톤에 대한 설명은 다음을 참조한다.

    2023.08.27 - [JAVA] - Singleton 구현 기법

     

    Singleton 구현 기법

     

    devchive.tistory.com

    이처럼, 싱글톤 패턴을 사용하면 항상 하나의 인스턴스만 생성하여 사용된다. 

     

    스프링에서의 싱글톤 패턴으로는 다음과 같은 부분을 볼 수 있다. 

    DefaultBootstrapContext의 getInstance 함수이다. 현재 Scope 이 싱글톤이면 this.instances에 인스턴스를 하나 할당하고 계속 같은 인스턴스를 반환하는것을 볼 수 있다.

     

    코드로 찾아본 예시는 위와 같지만, 스프링에서 제일 유명한 싱글톤 패턴은 싱글톤 컨테이너이다. 스프링에서는 생성된 Bean을 싱글톤 패턴으로 관리하여 단 하나의 인스턴스만 갖고있는다. 이를 컨테이너가 필요한 곳에 주입하는 방식으로 사용된다. 

    '공부방' 카테고리의 다른 글

    HTTPS 통신 과정  (0) 2023.11.15
    OSI 7계층과 TCP/IP 4계층  (0) 2023.11.07
    Session과 Token  (0) 2023.10.20
    부동소수점 표현 방식 [IEEE 754]  (0) 2023.08.31
    CAP Theorem  (0) 2023.08.06
Designed by Tistory.