SpringBootProject

SpringBoot: 템플릿 메소드 패턴

dding-shark 2025. 7. 11. 12:38
728x90

템플릿 메소드 패턴


1. 문제 상황

  • 기존 동시성문제를 해결한 로그 추적/출력 기를 적용하려면, 수많은 서비스, 리포지토리, 컨트롤러의 코드를 수정해야할 필요가 있었다.
  • 하지만, 코드 구조상
    class Sample{
    public void smapleMethod(){
        try{
            //  로그 시작부 

            //      핵심 로직

            //  로그 마침
        }catch (Exception e){
            throw new IlligalStateException(e)
        }


    }
}

이렇게 핵심 로직을 try-catch 문으로 감싸져있는 구조이고, try catch 가 없더라도, 시작부와 마침부 사이에 핵심로직이 들어가있어,
로직을 분리하기가 쉽지가 않은 상황이 있다.

  • 정리 :
    • 문제 1. 로그 추적기를 도입함에 있어 수정해야하는 코드들이 너무 많다,
    • 문제 2. 로그 추적기를 분리 시키기가 쉽지 않다.

2. SOL(가설)

  • 변하는 부분(핵심 로직) 과 변하지 않는 부분 (부가 로직) 이 있는 중에 변하지 않는 부분을 추상 클래스로 만들어,
    변하는 부분을 구현체에서 구현하게 하면 위에서 발생한 문제들 중 문제2 를 부분적으로 해결 할 수 있는 모듈을 구성하는 아이디어가 생겼고,

이를 템플릿 메서드 패턴이라고 한다.


3. 아이디어 다이어그램

이런 식으로 해결을 하는 흐름이다, 그림에서 보이는 것과 같이, 도형이라는 변하지 않는 무언가들을 추상 클래스로 만들고,

각 구현체(삼각형, 사각형, 원)은 각 클래스마다 변하는 특성을 구현하여 사용하는 구조로 이루어져 있다.

  • (여기서 필자는 상속... 에대한 강력한 반발..? 이 있기에.... 흠.... 하긴 했다.. 하지만,,, 강사님의 흐름에 몸을 맡겨 보기로 해본다.)

4. 구현

@Slf4j
public abstract class Figure {

    public void area()
    {

        log.info(" 이것은 도형 입니다.");
        log.inof("도형에 대한 설명을 시작하겠습니다.");
        //비즈니스 로직 실행
        call();
        log.info("도형에 대한 설명이 끝났습니다.");

    }
    protected  abstract  void call();
}



public class Circle extends  Figure{

    @Override
    call(){
        log.info("이 도형은 원 입니다.");
    }
}

public class Triangle extends  Figure{
    @Override
    call()
    {
        log.info("이 도형은 삼각형 입니다.");
    }
}

이런식으로 각 도형에 맞게 오버라이딩 하여, area()를 호출하면,
로그가 순서대로 각 클래스에 맞게 찍힐 것이다.

사용시엔

class TemplateMethodExcuteSample {

    public void smaple(){
        Firgure circle = new Circle();
        firgure.area();
        Firgure triangle = new Triangle();
        firgure.area();
    }
}

기본적으로 이렇게 실행 시키면 되는데,,, 신기한거 좀 발견한걸 적어보자면... 원 설명 로직을 실행 할때랑 삼각형 로직을 수행할때랑 실행시간의 차이가 난다.
(시간을 찍어보면 한... 5ms..?) 왜 이런 상황이 벌어지냐면... 핫스팟 JIT 컴파일의 최적화 처리를 해준것 + 초기 준비 단계의 로딩시간 등등이 있는데... 그래서 위아래 바꿔서 실해해도 아래꺼가 좀더 빠르다 뭐 잡다한 이야기었다.

new Circle new Triangle 이런것도 사실 좀 불편하다... 이런 구조에선 저렁 방식이 좀더 어울리지만.. 추상객체이니만큼 익명 클래스를 만들어버리면

    class TemplateMthodEcxuteSample2{
        Firgure circle = new Firgure(){
            @Override
            call()
            {
                log.info("이 도형은 원입니다.");
            }
        }

        circle.area();
    }

해도 결과는 똑같이 나오는데, 오버라이드할 메소드가 많으면 많을수록 어마어마한 코드길이가 되기때문에 상황에 맞게 쓰도록하자.


문제점.. (강사님의 능력을 의심하는게 아니라, 본 해결책의 문제분석이다. )

  • 하지만... 마직 문제 1이 남았고, 상속은 항상 강력한 결합을 가져오기에 되도록 상속을 피하라고 배웠지만... 뭐... 모르겠다....
  • 일단 필자는... 전략 패턴.. 데코레이트... 등등이 떠오르긴 하는데... 뒤에 설명을 해주신다고 하신다.
728x90