Proxy

์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ

img.png

์—ฌ๊ธฐ์— ๋กœ๊ทธ ์ถ”์ ์šฉ ํ”„๋ก์‹œ๋ฅผ ์ถ”์ ํ•˜๋ฉด ์ด๋ ‡๊ฒŒ ๋œ๋‹ค.

img_1.png
img_2.png

๊ฐ๊ฐ ์ธํ„ฐํŽ˜์ด์Šค์— ๋งž๋Š” ํ”„๋ก์‹œ ๊ตฌํ˜„์ฒด๋ฅผ ์ถ”๊ฐ€ํ•œ ๋‹ค์Œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์‹คํ–‰ ์‹œ์ ์— ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์˜์กด ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

@RequiredArgsConstructor
public class OrderRepositoryInterfaceProxy implements OrderRepositoryV1 {

    private final OrderRepositoryV1 target;//์‹ค์ œ ๊ฐ์ฒด
    private final LogTrace logTrace;

    @Override
    public void save(String itemId) {
        TraceStatus status = null;
        try {
            status = logTrace.begin("OrderRepository.save()");

            target.save(itemId);
            logTrace.end(status);
        } catch (Exception e) {
            logTrace.exception(status, e);
            throw e;
        }
    }
}

@RequiredArgsConstructor
public class OrderServiceInterfaceProxy implements OrderServiceV1 {

    private final OrderServiceV1 target;//์‹ค์ œ ๊ฐ์ฒด
    private final LogTrace logTrace;

    @Override
    public void orderItem(String itemId) {
        TraceStatus status = null;
        try {
            status = logTrace.begin("OrderService.orderItem()");

            target.orderItem(itemId);
            logTrace.end(status);
        } catch (Exception e) {
            logTrace.exception(status, e);
            throw e;
        }
    }
}

@RequiredArgsConstructor
public class OrderControllerInterfaceProxy implements OrderControllerV1 {

    private final OrderControllerV1 target;//์‹ค์ œ ๊ฐ์ฒด
    private final LogTrace logTrace;

    @Override
    public String request(String itemId) {
        TraceStatus status = null;
        try {
            status = logTrace.begin("OrderController.request()");

            String result = target.request(itemId);
            logTrace.end(status);
            return result;
        } catch (Exception e) {
            logTrace.exception(status, e);
            throw e;
        }
    }

    @Override
    public String noLog() {
        return target.noLog();
    }
}
@Configuration
public class InterfaceProxyConfig {

    @Bean
    public OrderControllerV1 orderController(LogTrace logTrace) {
        OrderControllerV1Impl controllerImpl = new OrderControllerV1Impl(orderService(logTrace));

        return new OrderControllerInterfaceProxy(controllerImpl, logTrace);//ํ”„๋ก์‹œ ๋นˆ ๋“ฑ๋ก
    }

    @Bean
    public OrderServiceV1 orderService(LogTrace logTrace) {
        OrderServiceV1Impl serviceImpl = new OrderServiceV1Impl(orderRepository(logTrace));

        return new OrderServiceInterfaceProxy(serviceImpl, logTrace);//ํ”„๋ก์‹œ ๋นˆ ๋“ฑ๋ก
    }

    @Bean
    public OrderRepositoryV1 orderRepository(LogTrace logTrace) {
        OrderRepositoryV1Impl repositoryImpl = new OrderRepositoryV1Impl();

        return new OrderRepositoryInterfaceProxy(repositoryImpl, logTrace);//ํ”„๋ก์‹œ ๋นˆ ๋“ฑ๋ก
    }
}

@Import(InterfaceProxyConfig.class)
@SpringBootApplication(scanBasePackages = "hello.proxy.app.v3")
public class ProxyApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProxyApplication.class, args);
    }

    @Bean
    public LogTrace logTrace() {
        return new ThreadLocalLogTrace();
    }
}
  • ์‹ค์ œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜์ง€ ์•Š๊ณ  ํ”„๋ก์‹œ๋ฅผ ์‹ค์ œ ์Šคํ”„๋ง ๋นˆ ๋Œ€์‹  ๋“ฑ๋กํ•œ๋‹ค.

  • ํ”„๋ก์‹œ๋Š” ๋‚ด๋ถ€์— ์‹ค์ œ ๊ฐ์ฒด(ํƒ€๊ฒŸ)๋ฅผ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋‹ค.

img_3.png
img_4.png
  • ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์‹ค์ œ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ  ๊ด€๋ฆฌํ•œ๋‹ค.

  • ์‹ค์ œ ๊ฐ์ฒด๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์™€๋Š” ์ƒ๊ด€์ด ์—†๊ณ  ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด์„œ ์ฐธ์กฐ๋  ๋ฟ์ด๋‹ค.

๊ตฌ์ฒด ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ

@RequiredArgsConstructor
public class OrderRepositoryConcreteProxy extends OrderRepositoryV2 {

    private final OrderRepositoryV2 target;
    private final LogTrace logTrace;

    @Override
    public void save(String itemId) {
        TraceStatus status = null;
        try {
            status = logTrace.begin("OrderRepository.save()");

            target.save(itemId);
            logTrace.end(status);
        } catch (Exception e) {
            logTrace.exception(status, e);
            throw e;
        }
    }
}

public class OrderServiceConcreteProxy extends OrderServiceV2 {

    private final OrderServiceV2 target;
    private final LogTrace logTrace;

    public OrderServiceConcreteProxy(OrderServiceV2 target, LogTrace logTrace) {
        super(null);//๋ถ€๋ชจ์˜ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•จ.
        this.target = target;
        this.logTrace = logTrace;
    }

    @Override
    public void orderItem(String itemId) {
        TraceStatus status = null;
        try {
            status = logTrace.begin("OrderService.orderItem()");

            target.orderItem(itemId);
            logTrace.end(status);
        } catch (Exception e) {
            logTrace.exception(status, e);
            throw e;
        }
    }
}

public class OrderControllerConcreteProxy extends OrderControllerV2 {

    private final OrderControllerV2 target;
    private LogTrace logTrace;

    public OrderControllerConcreteProxy(OrderControllerV2 target, LogTrace logTrace) {
        super(null);//๋ถ€๋ชจ์˜ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•จ.
        this.target = target;
        this.logTrace = logTrace;
    }

    @Override
    public String request(String itemId) {
        TraceStatus status = null;
        try {
            status = logTrace.begin("OrderController.request()");

            String result = target.request(itemId);
            logTrace.end(status);
            return result;
        } catch (Exception e) {
            logTrace.exception(status, e);
            throw e;
        }
    }

    @Override
    public String noLog() {
        return target.noLog();
    }
}
@Configuration
public class ConcreteProxyConfig {

    @Bean
    public OrderControllerV2 orderControllerV2(LogTrace logTrace) {
        OrderControllerV2 controllerImpl = new OrderControllerV2(orderServiceV2(logTrace));
        return new OrderControllerConcreteProxy(controllerImpl, logTrace);
    }

    @Bean
    public OrderServiceV2 orderServiceV2(LogTrace logTrace) {
        OrderServiceV2 serviceImpl = new OrderServiceV2(orderRepositoryV2(logTrace));
        return new OrderServiceConcreteProxy(serviceImpl, logTrace);
    }

    @Bean
    public OrderRepositoryV2 orderRepositoryV2(LogTrace logTrace) {
        OrderRepositoryV2 repositoryImpl = new OrderRepositoryV2();
        return new OrderRepositoryConcreteProxy(repositoryImpl, logTrace);
    }
}

@Import(ConcreteProxyConfig.class)
@SpringBootApplication(scanBasePackages = "hello.proxy.app.v3")
public class ProxyApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProxyApplication.class, args);
    }

    @Bean
    public LogTrace logTrace() {
        return new ThreadLocalLogTrace();
    }
}

์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ์™€ ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ

  • ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์—†์–ด๋„ ํด๋ž˜์Šค ๊ธฐ๋ฐ˜์œผ๋กœ ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ๋Š” ์ƒ์†์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ช‡ ๊ฐ€์ง€ ๋‹จ์ ์ด ์žˆ๋‹ค.

  • ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

  • ํด๋ž˜์Šค์— finalํ‚ค์›Œ๋“œ๊ฐ€ ๋ถ™์œผ๋ฉด ์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ๋ฉ”์„œ๋“œ์— finalํ‚ค์›Œ๋“œ๊ฐ€ ๋ถ™์œผ๋ฉด ์˜ค๋ฒ„๋ผ์ด๋“œ์„ ํ•  ์ˆ˜ ์—†๋‹ค.

๋Œ€์ฒด์ ์œผ๋กœ ํด๋ž˜์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ๋ณด๋‹ค๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜์˜ ํ”„๋ก์‹œ๊ฐ€ ๋” ์ข‹๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜์˜ ํ”„๋ก์‹œ๋Š” ์ƒ์†์ด๋ผ๋Š” ์ œ์•ฝ์—์„œ ์ž์œ ๋กญ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ์˜ ๋‹จ์ ์€ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์—†๋‹ค๋ฉด ์ธํ„ฐํŽ˜์ด์Šค ๊ธฐ๋ฐ˜ ํ”„๋ก์‹œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค.

์ด๋ก ์ ์œผ๋กœ๋Š” ๋ชจ๋“  ๊ฐ์ฒด์— ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋„์ž…ํ•ด์„œ ์—ญํ• ๊ณผ ๊ตฌํ˜„์„ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์—ญํ• ๊ณผ ๊ตฌํ˜„์„ ๋‚˜๋ˆ„์–ด์„œ ๊ตฌํ˜„์ฒด๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋„์ž…ํ•˜๋Š” ๊ฒƒ์€ ๊ตฌํ˜„์„ ๋ณ€๊ฒฝํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์„ ๋•Œ ํšจ๊ณผ์ ์ธ๋ฐ ๊ตฌํ˜„์„ ๋ณ€๊ฒฝํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๊ฑฐ์˜ ์—†๋Š” ์ฝ”๋“œ์— ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ์‹ค์šฉ์ ์ด์ง€ ์•Š๋‹ค.

์ด๋Ÿฐ ๊ณณ์—๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ ์šฉํ•˜๊ธฐ ๋ณด๋‹ค ๊ตฌ์ฒด ํด๋ž˜์Šค๋ฅผ ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ์ˆ˜๋„ ์žˆ๋‹ค.

ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  ๋กœ๊ทธ ์ถ”์ ๊ธฐ๋ผ๋Š” ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋ฌธ์ œ๋Š” ํ”„๋ก์‹œ ํด๋ž˜์Šค๋ฅผ ๋„ˆ๋ฌด ๋งŽ์ด ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

ํ”„๋ก์‹œ ํด๋ž˜์Šค๊ฐ€ ํ•˜๋Š” ๋กœ์ง์€ ๋Œ€์ƒ ํด๋ž˜์Šค๋งŒ ๋‹ค๋ฅผ ๋ฟ ๋ชจ๋‘ ๋˜‘๊ฐ™๋‹ค. ํ”„๋ก์‹œ ํด๋ž˜์Šค๋ฅผ ํ•˜๋‚˜๋งŒ ๋งŒ๋“ค์–ด์„œ ๋ชจ๋“  ๊ณณ์— ์ ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์—†์„๊นŒ?

๋™์  ํ”„๋ก์‹œ ๊ธฐ์ˆ ์ด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์ค€๋‹ค.

Last updated