템플릿 콜백 패턴(스프링)를 이해해 보자.

Choizz·2023년 1월 27일
0

디자인 패턴

목록 보기
3/8
post-thumbnail

이 전에 전략 패턴에 대해서 포스팅한 적이 있다.

전략 패턴은 실행 전에 먼저 조립을 해두고 실행을 한다. 그리고 중간에 필요한 특성을 바꿀 때는 setter를 사용해서 중간에 전략을 바꿀 수 있다. 하지만 싱글톤 방식에서 사용할 때는 동시성 문제가 발생할 가능성이 있다.

반대로, 실행 시점에 전략을 선택하는 방법이 있는데, 그것이 바로 템플릿 콜백 패턴이다. 스프링 내부에서 이런 방식을 많이 사용하기 때문에, 스프링 안에서만 이렇게 부른다고 한다(RestTemplate, JdbcTemplate 등등).

콜백이란,
다른 코드의 인수로 넘겨주는 실행 가능한 코드를 말한다. 즉, 코드가 호출(call)이 되고, 뒤(back, after)에서 실행이 되는 것이다.

콜백이라는 의미가 이해하기 애매하지만, 파라미터로 넘어온 객체에게 로직 수행을 위임한다고 이해를 하면 될 것 같다.
그렇다면 콜백 패턴을 사용했을 경우와 아닌 경우를 비교하며 살펴보자.


그냥 전략 패턴

  • 설정한 상황은 버튼을 누르면 영화 티켓이 할인이 되는데, 할인 전략은 조조 할인,심야 할인이다.
  • Button 클래스의 코드를 살펴보면
    - 싱글톤 패턴을 사용한다.
    - 인자로 DiscountType을 받고 필드로 저장한 뒤, 그것을 사용한다.
public class Button {

	private DiscountType discountType;
	private static Button newInstance = new Button();

	private Button(){}


	public static Button getInstance(DiscountType discountType){
		newInstance.discountType = discountType;
		return newInstance;
	}

	public void click() {
		System.out.println("할인이 적용됩니다.");
	    discountType.discount(PriceConst.MOVIE_PRICE);
		System.out.println("결제를 시도해 주세요");
	}
}
  • 아래 코드는 전략 패턴을 사용했다. 이것은 실행 전에 미리 할인 전략을 조립을 한 후 조립된 것을 가져다가 쓰면 된다.
  • 조조 할인의 경우 button1을 사용하면 되고, 심야 할인은 button2를 사용하면 된다.
public class Main {

	public static void main(String[] args) {
		Button button1 = Button.getInstance(new MorningDiscountType()); //조조 할인
		button1.click();
		Button button2 = Button.getInstance(new NightDiscountType());/심야 할인
		button2.click();
	}
}

//결과
할인이 적용됩니다.
조조 할인입니다. 1000원 할인되어 11000원 입니다.
결제를 시도해 주세요
============
할인이 적용됩니다.
심야 할인이 적용됩니다. 2000원 할인되어 10000원 입니다.
결제를 시도해 주세요

단점

  • 그런데 만약 할인 정책이 바뀌어 조조 할인이 없어지고 통신사 할인이 생겨서 button1을 클릭했을 때, 통신사 할인으로 바꿔야 하는 상황이 생겼다.
  • button1은 실행 시점 부터 조조 할인을 적용시켰다. 이것을 바꾸려면 setter함수를 사용해 바꿀 수 있다.
  • 만약 Button 객체가 싱글톤 패턴이 적용되어 생성되었기 때문에, setter 메서드로 필드를 변경 시 동시성 문제가 발생할 가능성이 있다(스프링은 싱글톤을 사용).

템플릿 콜백 패턴 적용

  • 템플릿 콜백 패턴은 미리 전략을 주입하는 하고 실행하는 것이 아니라 실행 시에 전략을 주입한다.
  • click() 메서드를 실행할 경우에 할인 전략이 적용되는 것이다.
public class ButtonCallBack {

	private static ButtonCallBack newInstance = new ButtonCallBack();

	private ButtonCallBack(){}


	public static ButtonCallBack getInstance(){
		return newInstance;
	}

	public void click( DiscountType discountType) { //파라미터로 콜백 코드 전달.
		System.out.println("할인이 적용됩니다.");
	    discountType.discount(PriceConst.MOVIE_PRICE);
		System.out.println("결제를 시도해 주세요");
	}
}
  • 이렇게 파라미터를 callback으로 전달하게 되면, 싱글톤 패턴에서 필드를 사용하지 않기 때문에 동시성 문제에서 자유롭다.
  • 그리고 실행 시점에 할인 전략을 선택을 할 수 있다. 미리 실행 전에 button 객체에 할인 전략을 조립해 놓으면 실행 후에는 그 전략만 사용해야 했다.
public class Main {
	public static void main(String[] args) {
		ButtonCallBack button = ButtonCallBack.getInstance();
		button.click(new MorningDiscountType()); //실행 시점에 전략 설정
		button.click(new NightDiscountType());
	}
    
//결과
할인이 적용됩니다.
조조 할인입니다. 1000원 할인되어 11000원 입니다.
결제를 시도해 주세요
============
할인이 적용됩니다.
심야 할인이 적용됩니다. 2000원 할인되어 10000원 입니다.
결제를 시도해 주세요

단점

  • 실행 시점에 일일이 할인 전략을 지정해 주어야한다.

템플릿 콜백 패턴은 어느 경우에??

템플릿

  • 템플릿이라는 것은 변하지 않는 부분을 의미한다. 이 예에서는
할인이 적용됩니다.
...
결제를 시도해 주세요

이 부분이 할인 전략에도 변하지 않는 부분이다.

콜백

  • 변하는 부분은 할인 전략에 따라 실행되는 로직이다. 이 할인을 적용시키는 것이 callback 코드이다.
조조 할인입니다. 1000원 할인되어 11000원 입니다.
심야 할인이 적용됩니다. 2000원 할인되어 10000원 입니다.

즉, 변하지 않는 부분과 변하는 부분을 분리하고, 변하지 않는 부분을 템플릿으로서 공통으로 사용하는 것이다.


button.click(new MorningDiscountType());
button.click(new NightDiscountType());

....
        
	public void click( DiscountType discountType) {
		System.out.println("할인이 적용됩니다."); //변하지 않는 부분
	    discountType.discount(PriceConst.MOVIE_PRICE); //변하는 부분.
		System.out.println("결제를 시도해 주세요");////변하지 않는 부분
	}

람다식 사용

  • 콜백 패턴의 경우 보통 람다식을 사용하여 표현한다.
  • 이때 인터페이스가 정의한 메서드가 하나여야 한다.
public interface DiscountType {

    public void discount(int originPrice);
}

...


public class Main {
	public static void main(String[] args) {

		ButtonCallBack button = ButtonCallBack.getInstance();
		button.click(originPrice -> {
			int totalPrice = 0;
			totalPrice = originPrice - PriceConst.MORNING_DISCOUNT;
			System.out.println("조조 할인입니다. " + PriceConst.MORNING_DISCOUNT +"원 할인되어 " + totalPrice +"원 입니다.");
		});
	}
}

//결과
할인이 적용됩니다.
조조 할인입니다. 1000원 할인되어 11000원 입니다.
결제를 시도해 주세요

정리

전략 패턴과 템플릿 콜백 패턴은 각각 장단점이 존재하지만,
실행 시점에 유연하게 전략을 적용하라면 템플릿 콜백 패턴을 사용하는 것이 좋다.


Refernence

profile
집중

0개의 댓글