[Spring] 스프링에서 사용되는 디자인 패턴들

2024. 10. 25. 23:36·Programming/Spring,JPA

 

디자인 패턴이란?

반복적으로 일어나는 문제들을 어떻게 풀어나갈 것인가에 대한 일종의 솔루션이다. 프로그램을 작성하다보면 프로그래머들은 비슷비슷한 상황에 직면하게 되는데, 그러한 상황에서 해결할 수 있는 솔루션이라고 생각하면 된다.


어댑터 패턴

✔️ 어댑터 패턴이란?

호환되지 않는 인터페이스를 가진 객체들이 협업할 수 있도록 하는 디자인 패턴으로,

호출 당하는 쪽의 메서드를 호출하는 쪽의 코드에 대응하도록 중간에 변환기를 통해 호출하는 패턴.

 

 

✔️실생활에서의 어댑터

우린 이미 실생화에서 어댑터를 사용하고 있다. 나는 아이폰 충전기를 가지고 있는데, C타입의 기기를 충전하기 위해선 어탭터를 이용하여 충전할 수 있다.

 

 

✔️ 구현 방법

구현 방법은 위 그림과 같다. 어댑터는 한 객체의 인터페이스를 구현하고 다른 객체를 래핑한다.

 

코드로 이해를 해보자.

public interface IphoneCharger {
    String chargeIphone();
}

public class ThunderboltCharger implements IphoneCharger{
    @Override
    public String chargeIphone() {
        return "charge Iphone using thunderbolt";
    }
}
public class UsbCharger {
    public String chargeGalaxy() {
        return "charge Galaxy using USB-C";
    }
}
public class ThunderboltToUsbAdapter implements IphoneCharger{
    UsbCharger usbCharger;

    public ThunderboltToUsbAdapter(UsbCharger usbCharger) {
        this.usbCharger = usbCharger;
    }

    @Override
    public String chargeIphone() {
        return usbCharger.chargeGalaxy() + "(using adapter)";
    }
}
public class Client {
    public static void main(String[] args) {
        ThunderboltCharger thunderboltCharger = new ThunderboltCharger();
        UsbCharger usbCharger = new UsbCharger();

        System.out.println(thunderboltCharger.chargeIphone());
        System.out.println(usbCharger.chargeGalaxy());

        System.out.println("=====================");

        IphoneCharger thunderboltToUsbAdapter = new ThunderboltToUsbAdapter(usbCharger);
        System.out.println(thunderboltToUsbAdapter.chargeIphone());
    }
}

 

 

📌 Spring의 어댑터 패턴 : HandlerAdapter

 

스프링이 동작할때 핸들러 어댑터라는것이 사용된다. 이름부터 대놓고 어댑터이다. 간단한 동작과정을 살펴보자.

 

Spring MVC 동작 과정

  1. 클라이언트는 uri 형식으로 웹 서비스에 요청을 보낸다
  2. DispatchServlet이 핸들러 매핑을 동작 시킨다(해당 요청을 매핑할 컨트롤러가 있는지 찾는 과정).
  3. 매핑할 핸들러를 가져오면 핸들러를 실행시키기 위해 핸들러 어탭터를 가져온다.
  4. 핸들러 어탭터 실행하면 실제 컨트롤러의 핸들러가 실행 

 

 

그렇다면 핸들러 어댑터가 왜 필요할까? 그 이유는 다양한 형태의 컨트롤러가 존재하기 때문이다.

 

//1. Controller 인터페이스를 구현하기

@Component("/springmvc/old-controller")
public class OldController implements Controller {
.
.
.
}
 

//2. HttpRequestHandler 인터페이스를 구현하기

@Component("/springmvc/request-handler")
public class MyHttpRequestHandler implements HttpRequestHandler {
.
.
.
}
 

//3. 어노테이션 기반

@Controller
@RequestMapping("/api/members")
public class InterestController {
.
.
.
}

 

이렇게 다양한 방식이 존재하는데, 어댑터 패턴을 구현했기에 컨트롤러의 종류가 다르더라도 그에 맞는 어댑터만 사용한다면 적용이 가능하다.

 

 

DispatcherServlet에는 getHandlerAdpater 메서드가 존재한다. 어댑터들을 반복문으로 돌리며 알맞는 핸들러를 찾는 과정을 진행한다.

supports 메서드는 핸들러 인스턴스를 받아서 핸들러 아답터가 지원할 수 있는지 확인한다.

 


 

프록시 패턴

✔️ 프록시 패턴이란?

 

제어 흐름을 조정하기 위한 목적으로 중간에 대리자를 두는 패턴으로, 원래 객체에 대한 접근을 제한한다.

요청이 객체에 전달되기 전 후에 무언가를 수행할 수 있다.

 

 

✔️ 프록시 객체 사용 이유

 

객체에 대한 접근제어 및 부가 기능 추가 등을 이유로 사용한다.

 

프록시 클래스에는 서비스 객체를 가리키는 참조 필드가 있다. 프록시가 요청의 처리를 완료하면, 그 후 처리된 요청을 서비스 객체에 전달한다.

클라이언트는 프록시 클래스를 호출하여 서비스 객체의 비즈니스 로직을 사용할 수 있다.

 

 

 

 

예를 들어, 데이터베이스를 접근하기 앞서 필요한 A 로직이 있다고 가정하자. 모든 클라이언트 코드에 이 로직을 구현하면 코드의 중복을 초래한다.

 

 

 

이럴때 프록시 패턴을 사용한다. 클라이언트가 프록시 객체를 호출하면, 프록시 객체에서 A로직을 실행하고 데이터베이스에 접근하게 된다.

 

 

📌  Spring의 프록시 패턴 : @Transactional

 

 

@Transactional 어노테이션을 적용하지 않았을 경우의 Flow Chart

 

: Controller → Service → Repository 의 흐름으로, 우리가 설계한 그대로 메소드를 호출

 

 

@Transactional 어노테이션을 적용했을 경우의 Flow Chart

 

: Controller와 Service 레이어 사이에 Proxy 객체가 추가되어 Service 레이어를 대리 호출하고 있는 모습

 


싱글톤 패턴

✔️ 싱글톤 패턴이란?

클래스의 인스턴스, 즉 객체를 하나만 만들어서 사용하는 패턴. 인스턴스에 대한 전역 접근 지점을 제공한다.

 

 

✔️ 구현 방법

- new를 실행할 수 없도록 생성자에 private 접근 제어자

- 유일한 단일 객체를 반환할 수 있는 정적 메서드

- 유일한 단일 객체를 참조할 정적 참조 변수

public class Singleton {
	static Singleton sigletonObject;
	
	private Singleton() {}; // private 생성자

	public staitc Singleton getInstance() {
		if (singletonObject == null) {
			singletonObject = new Singleton();
		}
		return sigletonObejct;
	}
}

 

 

📌 스프링의 싱글톤 패턴

스프링은 스프링 컨테이너에 의해 싱글톤 패턴이 구현된다. 특정 클래스에 대해 @Bean이 정의되면, 스프링 컨테이너는 그 클래스에 대해 딱 한개의 인스턴스를 만든다. Bean이 호출될때마다 스프링은 생성된 공유 인스턴스를 리턴 시킨다.

 


 

템플릿 메서드 패턴

 

✔️템플릿 메서드 패턴이란?

 

상위클래스의 견본 메서드에서 하위 클래스가 오버라이딩한 메서드를 호출하는 패턴.

부모 클래스에서 알고리즘 골격을 정의한다. 해당 알고리즘의 구조를 변경하지 않고 자식 클래스들이 알고리즘의 틀정 단계들을 오버라이드 할 수 있도록 하는 행동.

 

 

✔️ 예시

 

문서들을 분석하는 데이터 마이닝 앱을 개발하고 있다고 가정하자. 앱은 Doc, CSV, PDF와 같은 당야한 형식의 문세들에서 일관된 형식으로 데이터를 추출한다.그리하여 데이터 형식을 처리하는 코드를 클래스별로 다르게 구현하였는데, 중복 코드가 많이 포함되어있는것을 발견했다.

 

알고리즘 구조는 그대로 두되, 중복 코드를 제거하는 방법이 필요할때 사용할 수 있는데 템플릿 메서드 패턴이다.

 

 

 

 

 

📌  Spring에서의 템플릿 메서드

 

Spring의 DispatcherServlet에서 템플릿 메서드 패턴이 사용되고 있다.

 

 

 

 

 

 

DispatcherServlet은 FrameworkServlet을 상속받고 있다.

 

 

DispatcherServlet에는 오버라이드된 doService()가 존재한다는 것을 미리 알아두자.

 

 

다시 부모 클래스인 FrameworkServlet으로 가보자. processRequest()를 살펴볼건데, 여기에서 doSerivce()를 호출한다.

 

 

FrameworkServlet에서 doService를 살펴보니, 이에 대한 구현은 하위클래스에게 위임하고 있다.

하위클래스인 DispatcherServlet에서 doService()를 구체화하고 있다. DispatcherServlet에서 processRequest를 호출하면 FrameworkServlet의 로직을 따르다, doService 호출 부분에서는 DispatcherServlet에서 구현한 로직을 타게 된다.

'Programming > Spring,JPA' 카테고리의 다른 글

[Spring] 예외 처리에만 국한되지 않는 @ControllerAdvice  (0) 2024.10.26
[Spring] 단일 행이 반환될때는 queryForObject가 항상 정답일까?  (0) 2024.10.26
[Spring] 스프링 삼각형(IoC/DI, AOP, PSA)  (1) 2024.10.25
[JPA] 영속성 컨텍스트(Persistence Context) 내부 구조 살펴보기  (1) 2024.10.25
[JPA] Hibernate 내부 동작을 알고 계신가요?(save 안티패턴 고찰)  (3) 2024.09.05
'Programming/Spring,JPA' 카테고리의 다른 글
  • [Spring] 예외 처리에만 국한되지 않는 @ControllerAdvice
  • [Spring] 단일 행이 반환될때는 queryForObject가 항상 정답일까?
  • [Spring] 스프링 삼각형(IoC/DI, AOP, PSA)
  • [JPA] 영속성 컨텍스트(Persistence Context) 내부 구조 살펴보기
우니wooni
우니wooni
  • 우니wooni
    woonDev
    우니wooni
  • 전체
    오늘
    어제
    • 전체
      • Programming
        • Java,Back-end
        • Spring,JPA
        • OS
        • Network
        • 기술 면접 대비
      • Books
        • MySQL 8.0
      • Side Project
        • Study Together
      • Life
        • 회고
        • 일상 이야기
  • 블로그 메뉴

    • 홈
    • GitHub
  • 링크

    • GitHub
  • 공지사항

  • 인기 글

  • 태그

    영속성 컨텍스트
    Pessimistic lock
    동시성
    익명 클래스
    비동기
    이벤트 기반 구조
    비관적 락
    Optimistic Lock
    Spring
    Persistence Context
    JPA
    디자인 패턴
    event-driven architecture
    낙관적 락
    Java
    레디스
    hibernate
    스프링
    추상화
    동시성 제어
    람다
    redis
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
우니wooni
[Spring] 스프링에서 사용되는 디자인 패턴들
상단으로

티스토리툴바