자바생
article thumbnail
Published 2022. 11. 1. 00:24
Template Callback Pattern Design Pattern
728x90

콜백 정의

위키에서는 콜백을 다른 코드의 인수로서 넘겨주는 실행 가능한 코드라고 합니다. 콜백을 넘겨받는 코드는 이 콜백을 필요에 따라 즉시 실행할 수도 있고, 아니면 나중에 실행할 수도 있습니다. Java에서는 이러한 콜백 코드를 전달할 때 람다나 익명 내부 클래스 형태로 넘겨줍니다.

 

템플릿 콜백 ? 템플릿 메서드 ?

 

템플릿 메서드

단일 상속만이 가능한 자바 언어에서 템플릿 메서드를 사용하는데 한계가 있습니다. 자식 클래스 입장에서는 부모 클래스의 기능을 전혀 사용하지 않고, 자식 클래스가 부모 클래스와 컴파일 시점에 강하게 결합됩니다. 이러한 단점을 해결하기 위해서 상속의 단점을 제거하고 interface를 사용하는 전략 패턴을 DI에 주로 사용합니다.

 

템플릿 콜백

DI에서 전략 패턴을 주로 사용하는데, 전략을 익명 내부 클래스나 람다로 정의하여 파라미터로 전달하여 전략 패턴보다 더욱 유연하게 사용하는 것을 템플릿 콜백 패턴이라고 합니다. 스프링은 템플릿 콜백 패턴을 DI 에 적극 활용하고 있습니다.

전략 패턴과 템플릿 콜백 패턴이 비슷하지만 어떤 차이가 있는지 코드로 보겠습니다.

 

전략 패턴

 

Strategy

public interface Strategy {
    void action();
}

 

Context

public class Context {

    private final Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void execute() {
        System.out.println("행동 시작");

        strategy.action();

        System.out.println("행동 끝");
    }
}

Context를 생성할 때 Strategy를 주입받아서 execute를 실행할 때 전략을 사용합니다.

이러한 방식이기 때문에 선 조립 후 실행 이라고 합니다.

또한, 한번 주입된 strategy가 있기 때문에 strategy가 바뀌지 않으면 execute만 하면 됩니다.

 

Strategy Test

public class StrategyTest {

    @Test
    void strategy() {
        Strategy strategy = null;
        Context context = null;

        strategy = new RunStrategy();
        context = new Context(strategy);
        context.execute();
        System.out.println();

        strategy = new FlyStrategy();
        context = new Context(strategy);
        context.execute();
    }

    static class RunStrategy implements Strategy {
        @Override
        public void action() {
            System.out.println("뛴다");
        }
    }

    static class FlyStrategy implements Strategy {
        @Override
        public void action() {
            System.out.println("난다");
        }
    }
}

내부 클래스에 Strategy를 구현하고 있는 2개의 구체 클래스가 있습니다.

Context에 Strategy를 먼저 주입해놓은 다음에 Context에서 Strategy를 실행하게 됩니다.

이러한 방식을 선 조립, 후 실행이라고 하는데, 스프링으로 애플리케이션을 개발할 때 애플리케이션 로딩 시점에 의존관계 주입을 통해 필요한 의존관계를 모두 맺어두고 난 다음에 실제 요청을 처리하는 것과 같은 원리입니다.

 

단점

하지만 먼저 조립하고 사용하는 선 조립 후 실행 방식으로 유연성이 떨어집니다.

그래서 더욱 유연하게 사용할 수 있는 템플릿 콜백 패턴이 있습니다.

 

템플릿 콜백 패턴

 

Callback

public interface Callback {
    void action();
}

 

CallbackTemplate

public class CallbackTemplate {

    public void execute(Callback callback) {
        System.out.println("행동 시작");

        callback.action();

        System.out.println("행동 끝");
    }
}

 

Callback Test

public class CallbackTest {

    @Test
    void callbackTest() {
        CallbackTemplate callbackTemplate = new CallbackTemplate();

        callbackTemplate.execute(() -> System.out.println("뛴다"));
        System.out.println();
        callbackTemplate.execute(() -> System.out.println("난다"));
    }
}

이 방법을 사용하게 되면 선 조립 후 실행하는 방식이 아니라 Context를 실행할 때마다 전략을 인수로 전달합니다.(이렇게 인수로 넘기는 실행 가능한 코드를 ‘콜백’이라고 합니다.)

그래서 전략 패턴은 런타임 시점에 전략이 결정되지만 템플릿 콜백 패턴은 클라이언트(Test)가callbackTemplate(context)를 실행하는 시점에 원하는 Strategy를 전달할 수 있기 때문에 template이 실행되는 시점에 전략이 결정됩니다. 또한, 하나의 callbackTemplate을 통해 여러 전략을 인수로 전달하여 유연하게 실행할 수 있습니다.

즉, 전략 패턴에서 ‘템플릿’, ‘콜백’ 부분이 강조된 패턴을 템플릿 콜백 패턴이라고 합니다.

스프링에서는 JdbcTemplate, RestTemplate, TransationTemplate 등 XXXTemplate은 템플릿 콜백 패턴으로 만들어져있다고 합니다.

 

정리

템플릿 콜백 패턴은 GOF 패턴은 아니지만 스프링에서 자주 적용되는 디자인 패턴 중 하나입니다.

템플릿 콜백 패턴은 전략 패턴과 매우 유사하지만 전략을 파라미터로 콜백 형태로 전달하여 클라이언트가 직접 실행하는 것이 아닌 context 뒤에서 실행됩니다.

그래서 일반적인 전략 패턴을 사용할 때 선 조립 후 실행 방식이 아닌 client를 실행할 때 strategy를 넘겨 더욱 유연하게 사용할 수 있습니다.

 

REFERENCES

영한님 Spring 고급편

728x90

'Design Pattern' 카테고리의 다른 글

Decorator Pattern  (0) 2022.11.06
Singleton Pattern  (0) 2022.03.17
Command Pattern  (0) 2022.03.15
State Pattern  (0) 2022.03.12
Strategy Pattern  (0) 2022.03.04
profile

자바생

@자바생

틀린 부분이 있다면 댓글 부탁드립니다~😀

검색 태그