ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Core - 프록시 패턴(예제 프로젝트)
    FrameWork/Spring&Spring-boot 2024. 3. 8. 11:02

    프록시패턴 - 예제 프로젝트

    다양한 상황에서 프록시 사용법을 이해하기 위해 다음과 같은 기준으로 기본 예제 프로젝트를 만들어보자

     

    예제는 크게 3가지 상황으로 만든다.

    • v1 - 인터페이스와 구현 클래스 - 스프링 빈으로 수동 등록
    • v2 - 인터페이스 없는 구체 클래스 - 스프링 빈으로 수동 등록
    • v3 - 컴포넌트 스캔으로 스프링 빈 자동 등록

    실무에서는 스프링 빈으로 등록할 클래스는 인터페이스가 있는 경우도 있고 없는 경우도 있다. 그리고 스프링 빈을 수동으로 직접 등록 하는 경우도 있고, 컴포넌트 스캔으로 자동으로 등록하는 경우도 있다. 이러한 다양한 케이스에 프록시를 어떻게 적용하는지 알아보기 위해 다양한 예제를 준비해보자.


    예제 프로젝트 만들기 v1

    v1 - 인터페이스와 구현 클래스 - 스프링 빈으로 수동 등록

    지금까지 보았던 Controller, Service, Repository에 인터페이스를 도입하고, 스프링 빈으로 수동 등록해보자.

     

    OrderRepositoryV1

    public interface OrderRepositoryV1 {
        void save(String itemId);
    }

     

     

    OrderServiceV1

    public interface OrderServiceV1 {
        void orderItem(String itemId);
    }

     

     

    OrderControllerV1

    @RequestMapping
    @ResponseBody
    public interface OrdersControllerV1 {
    
        @GetMapping("/v1/order")
        String createOrder(@RequestParam("itemId") String itemId);
    
        @GetMapping("/v1/no-log")
        String noLog();
    }

     

    • @RequestMapping : 스프링 MVC는 @RestController 또는 @RequestMapping 에노테이션이 타입이 있어야 스프링 컨트롤러로 인식한다. 그리고 스프링 컨트롤러로 인식해야, HTTP URL이 매핑되고 동작한다. 이 애노테이션은 인터페이스에 사용해도 된다.
    • @ResponseBody : HTTP 메시지 컨버터를 사용해서 응답한다. 이 애노테이션은 인터페이스에 사용해도 된다.
    • 코드를 보면 createOrder(), noLog() 두 가지 메서드가 있다. createOrder()는 LogTrace를 적용할 대상이고, noLog()는 단순히 LogTrace를 적용하지 않을 대상이다.

    @RequestParam("itemId") 같은 어노테이션은 클래스 레벨에서는 생략해도 크게 문제가 없지만 인터페이스의 경우는 제대로 명시해 주는 것이 좋다 그렇게 하지 않을 경우 컴파일 시점에 인식이 안돼는 문제가 발생할 수 있다. 

     

     

    SpringProxyApplication - 코드 추가

    @Import(AppV1Config.class)
    @SpringBootApplication
    public class SpringProxyApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringProxyApplication.class, args);
        }
    
    }

     

    • @Import(AppV1Config.class) : 클래스를 스프링 빈으로 등록한다. 여기서는 AppV1Config.class를 스프링 빈으로 등록한다. 일반적으로 @Configuration 같은 설정 파일을 등록할 때 사용하지만, 아무 빈이나 수동 등록할 때도 사용할 수 있다. 스프링 빈을 등록할 때 사용할 수 있다.
      • AppV1Config 클래스 자체가 스프링 빈으로 등록되 되야 해당 클래스 하위에 @Bean 어노테이션으로 등록한 빈들도 스프링 빈으로 등록이 된다.
    • @SpringBootApplication(scanBasePackages = "hello.proxy.app") : @ComponentSacn의 기능과 같다 컴포넌트 스캔을 시작할 위치를 지정한다. 이 값을 설정하면 해당 패키지와 그 하위 패키지를 컴포넌트 스캔한다. 이 값을 사용하지 않으면 SpringProxyApplication이 있는 패키지와 그 하위 패키지를 스캔한다. 참고로 v3에서 지금 설정한 컴포넌트 스캔 기능을 사용한다.

     

    ❗주의
    앞으로는 @Configuration을 사용한 수동 빈 등록 설정을 com.core.springproxy.config 위치에 두고 점진적으로 변경할 예정이다. 지금은 AppV1config.class를 @Import를 사용해서 설정하지만 이후에 다른 것을 설정할 예정이다.

    @Configuration은 내부에 @Component 애노테이션을 포함하고 있어서 컴포넌트 스캔의 대상이 된다. 따라서 컴포넌트 스캔에 의해 hello.proxy.config 위치 설정 파일들이 스프링 빈으로 자동 등록 되지 않도록 컴포넌트 스캔의 시작 위치를 "com.core.springproxy.app" 으로 설정해야 한다.

     


    예제 프로젝트 만들기 v2

    v2 - 인터페이스 없는 구체 클래스 - 스프링 빈으로 수동 등록 

    이번에는 인터페이스가 없는 Controller, Service, Repository를 스프링 빈으로 수동 등록해보자

     

    OrderContorllerV2

    package com.core.springproxy.app.v2;
    
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.*;
    
    @Slf4j
    @RestController
    @ResponseBody
    public class OrderControllerV2 {
    
        private final OrderServiceV2 orderService;
    
        public OrderControllerV2(OrderServiceV2 orderService) {
            this.orderService = orderService;
        }
    
        @GetMapping("/v2/order")
        String createOrder(@RequestParam("itemId") String itemId){
            orderService.orderItem(itemId);
            return "ok";
        }
    
        @GetMapping("/v1/no-log")
        String noLog(){
            return "ok";
        }
    
    }
    

     


    예제 프로젝트 만들기 v3

    v3 - 컴포넌트 스캔으로 스프링 빈 자동 등록

    이번에는 컴포넌트 스캔으로 스프링 빈을 자동 등록해보자.

     

    @Slf4j
    @RestController
    @ResponseBody
    public class OrderControllerV3 {
    
        private final OrderServiceV3 orderService;
    
        public OrderControllerV3(OrderServiceV3 orderService) {
            this.orderService = orderService;
        }
    
        @GetMapping("/v3/order")
        String createOrder(@RequestParam("itemId") String itemId){
            orderService.orderItem(itemId);
            return "ok";
        }
    
        @GetMapping("/v3/no-log")
        String noLog(){
            return "ok";
        }
    
    }

     

    ProxyApplication 에서 @SpringBootApplication(scanBasePackage = "com.core.springproxy")를 사용했고, 각각 @RestController, @Service, @Repository 애노테이션을 가지고 있기 때문에 컴포넌트 스캔 대상이 된다.  

     

     

    [출처 - 스프링 핵심원리-고급편, 저 김영한]

    https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B3%A0%EA%B8%89%ED%8E%B8

     

    스프링 핵심 원리 - 고급편 강의 - 인프런

    스프링의 핵심 원리와 고급 기술들을 깊이있게 학습하고, 스프링을 자신있게 사용할 수 있습니다., 핵심 디자인 패턴, 쓰레드 로컬, 스프링 AOP스프링의 3가지 핵심 고급 개념 이해하기 📢 수강

    www.inflearn.com

     

    댓글

Designed by Tistory.