TIL/Spring & Spring Batch

์Šคํ”„๋ง ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ

JoJobum 2023. 5. 24.
๐Ÿ’ก ํ”„๋ก์‹œ(Proxy) ๋ž€?
ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‹ค์ œ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๋Œ€์ƒ์ธ์–‘ ์š”์ฒญ์„ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ์—ญํ• .
ํ”„๋ก์‹œ์—๊ฒŒ ์š”์ฒญ์„ ๋„˜๊ฒจ๋ฐ›์•„ ์ตœ์ข… ์ฒ˜๋ฆฌํ•˜๋Š” ์˜ค๋ธŒ์ ํŠธ๋Š” ํƒ€๊นƒ(Target).
ํƒ€๊นƒ๊ณผ ํ”„๋ก์‹œ์ธ์ง€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์—†์–ด์•ผ ํ•˜๊ธฐ์— ๋‘˜์€ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™•์žฅํ•ด์•ผ ํ•จ.

 

ํ”„๋ก์‹œ๋Š” ์‚ฌ์šฉ ๋ชฉ์ ์— ๋”ฐ๋ผ 2๊ฐ€์ง€๋กœ ๋‚˜๋‰จ

  • ๋ถ€๊ฐ€์ ์ธ ๊ธฐ๋Šฅ ๋ถ€์—ฌ ⇒ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด
  • ์ ‘๊ทผ ์ œ์–ด ⇒ ํ”„๋ก์‹œ ํŒจํ„ด 

 

ํ”„๋ก์‹œ ํŒจํ„ด

๊ฐ์ฒด ์ƒ์„ฑ์€ ๋น„์šฉ ⇒ ์ตœ์†Œํ•œ, ํ•„์š” ์‹œ์ ๊นŒ์ง€ ๋ฏธ๋ฃจ๋Š”๊ฒŒ ์ข‹์Œ

  • ํƒ€๊นƒ์— ๋Œ€ํ•œ ์ ‘๊ทผ๊ถŒํ•œ ์ œ์–ด ๊ฐ€๋Šฅ
  • ์บ์‹ฑ

 

ํ”„๋ก์‹œ์˜ ๋‹จ์ 

  • ํ”„๋ก์‹œ๊ฐ€ ๋ฉค๋ฒ„๋ณ€์ˆ˜๋กœ ํƒ€๊นƒ ์˜ค๋ธŒ์ ํŠธ ๊ฐ€์ง€๊ธฐ์— ํƒ€๊นƒ ์˜ค๋ธŒ์ ํŠธ์— ์ข…์†์ 
  • ๋˜‘๊ฐ™์€ ๊ธฐ๋Šฅ ์ˆ˜ํ–‰ํ•˜๋Š” ํ”„๋ก์‹œ๋ผ๋„ ์—ฌ๋Ÿฌ ํƒ€๊นƒ์— ์ ์šฉํ•˜๋ ค๋ฉด ํƒ€๊นƒ์˜ ๊ฐฏ์ˆ˜ ๋งŒํผ ํ”„๋ก์‹œ ์ƒ์„ฑํ•ด์•ผ ํ•˜๊ธฐ์— ์ฝ”๋“œ ์ค‘๋ณต ๋ฐœ์ƒ
  • ํ”„๋ก์‹œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฉ”์†Œ๋“œ์—๋„ ํƒ€๊นƒ์œผ๋กœ ์œ„์ž„ํ•˜๋Š” ๋ฉ”์†Œ๋“œ ์ž‘์„ฑํ•ด์•ผ ํ•จ

⇒ ๋ฆฌํ”Œ๋ ‰์…˜ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋ก์‹œ๋ฅผ ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•ด์„œ ํ•ด๊ฒฐํ•ด๋ณด์ž!

 

๋‹ค์ด๋‚ด๋ฏน ํ”„๋ก์‹œ

์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ ๋ฌด๋กœ ํฌ๊ฒŒ ๋ถ„๋ฅ˜๋จ

  • ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ ⇒ JDK ๋™์  ํ”„๋ก์‹œ
  • ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ ⇒ CGLIB

 

JDK ๋™์  ํ”„๋ก์‹œ

๊ตฌํ˜„ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ”„๋ก์‹œ ์ƒ์„ฑ

reflect์˜ invocationHandler๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ

Object proxy = Proxy.newProxyInstance(ClassLoader       // ํด๋ž˜์Šค๋กœ๋”
                                    , Class<?>[]        // ํƒ€๊นƒ์˜ ์ธํ„ฐํŽ˜์ด์Šค
                                    , InvocationHandler // ํƒ€๊นƒ์˜ ์ •๋ณด๊ฐ€ ํฌํ•จ๋œ Handler
              										  );

Proxy ๊ฐ์ฒด ์ƒ์„ฑ๋˜๋Š” ๊ณผ์ •

  1. ProxyFactory๊ฐ€ ํƒ€๊นƒ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†ํ•œ Proxy ๊ฐ์ฒด ์ƒ์„ฑ
  2. proxy ๊ฐ์ฒด์— invocation Handler๋ฅผ ํฌํ•จ์‹œ์ผœ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜
public class TestInvocationHandler implements InvocationHandler {

    private TargetInterface target; //ํƒ€๊นƒ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ์œ ์ง€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    public TestInvocationHandler(TargetInterface target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        log.info("ํ”„๋ก์‹œ ๋ถ€๊ฐ€๊ธฐ๋Šฅ ์‹œ์ž‘");  //์—ฌ๊ธฐ์— ๋ถ€๊ฐ€๊ธฐ๋Šฅ ๋กœ์ง์„ ์ถ”๊ฐ€
        Object result = method.invoke(target, args);  //์‹ค์ œ ํƒ€๊นƒ ์˜ค๋ธŒ์ ํŠธ๋กœ ์š”์ฒญ์„ ์œ„์ž„ํ•ฉ๋‹ˆ๋‹ค.
        log.info("ํ”„๋ก์‹œ ๋ถ€๊ฐ€๊ธฐ๋Šฅ ์ข…๋ฃŒ");  //์—ฌ๊ธฐ์— ๋ถ€๊ฐ€๊ธฐ๋Šฅ ๋กœ์ง์„ ์ถ”๊ฐ€

        return result;
    }
}
@Test
void testInvocationHandler(){
    TargetInterface target = new TargetImpl();
    TestInvocationHandler invocationHandler = new TestInvocationHandler(target);

    //ํ”„๋ก์‹œ ์ƒ์„ฑ
    TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(TargetInterface.class.getClassLoader(), new Class[]{TargetInterface.class}, invocationHandler);

    //ํ”„๋ก์‹œ ์‹คํ–‰
    proxy.run();
    log.info("proxy = {}", proxy.getClass());

}

์ƒˆ๋กœ์šด ํƒ€๊นƒ์— ๊ธฐ์กด์˜ ํ”„๋ก์‹œ๋ฅผ ์ ์šฉํ•˜๋ ค๋ฉด ์ƒˆ๋กœ์šด ํƒ€๊นƒ์˜ ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ผ์น˜ํ•˜๋Š” ํ”„๋ก์‹œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋Š” ๋ถ€๋ถ„์„ InvocationHandler๋ฅผ ์‚ฌ์šฉํ•ด ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•ด ํ•ด๊ฒฐ

 

CGLIB

CGLIB์€ ๋ฐ”์ดํŠธ ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•˜์—ฌ ๋™์ ์œผ๋กœ ํด๋ž˜์Šค ์ƒ์„ฑํ•ด์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

Enhancer enhancer = new Enhancer();
         enhancer.setSuperclass(MemberService.class); // ํƒ€๊นƒ ํด๋ž˜์Šค
         enhancer.setCallback(MethodInterceptor);     // Handler
Object proxy = enhancer.create(); // Proxy ์ƒ์„ฑ

์ธํ„ฐํŽ˜์ด์Šค ์—†์ด concrete ํด๋ž˜์Šค๋งŒ ์กด์žฌํ•ด๋„ ํ”„๋ก์‹œ ์ƒ์„ฑ ๊ฐ€๋Šฅ

CGLIB์€ MethodIntercepter ํ†ตํ•ด ๊ตฌํ˜„๋จ, InvocationHandler์™€ ๋งค์šฐ ์œ ์‚ฌ

์„ฑ๋Šฅ์ ์œผ๋กœ CGLIB์ด ์ข‹์Œ

CGLB์€ ํƒ€๊นƒ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณต ๋ฐ›์•„ ๋ฐ”์ดํŠธ ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•ด์„œ Proxy๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ดํ›„ ํ˜ธ์ถœ์‹œ์—๋Š” ์กฐ์ž‘๋œ ๋ฐ”์ดํŠธ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์ ์œผ๋กœ ์ข‹๋‹ค.

ํ•˜์ง€๋งŒ ์ดˆ๊ธฐ Spring์—์„œ๋Š” JDK ๋ฐฉ์‹์„ ์‚ฌ์šฉํ–ˆ์—ˆ์Œ

  • net.sf.cglib.proxy.Enhancer ์˜์กด์„ฑ ์ถ”๊ฐ€
  • default ์ƒ์„ฑ์ž
  • ํƒ€๊นƒ์˜ ์ƒ์„ฑ์ž ๋‘ ๋ฒˆ ํ˜ธ์ถœ

๊ฐ™์€ ๋ฌธ์ œ์ ์ด CGLIB์— ์กด์žฌํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—

But, ๋Œ€๋ถ€๋ถ„ ๊ฐœ์„ ๋˜์–ด ํ˜„์žฌ ์Šคํ”„๋ง์˜ ๋‹ค์ด๋‚˜๋ฏน ํ”„๋ก์‹œ๋Š” CGLIB์œผ๋กœ ๊ตฌํ˜„๋จ

 

์Šคํ”„๋ง AOP์˜ Proxy ๋™์ž‘

๋Ÿฐํƒ€์ž„ ์œ„๋น™(Runtime Weaving)

  1. Spring AOP๋Š” ํ˜ธ์ถœ ์‹œ์ ์— IoC ์ปจํ…Œ์ด๋„ˆ์— ์˜ํ•ด Proxy Bean์„ ์ƒ์„ฑ
    1. ์ธํ„ฐํŽ˜์ด์Šค ์œ ๋ฌด์— ๋”ฐ๋ผ ๋ฐฉ์‹ ์„ ํƒ(JDK / CGLIB)
  2. ๋™์ ์œผ๋กœ ์ƒ์„ฑ๋œ Proxy Bean์€ ํƒ€๊นƒ์˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ์‹œ์ ์— ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ๋ฉ”์†Œ๋“œ๋ฅผ ํŒ๋‹จ ๋ฐ ์ฃผ์ž…

 

๋‹ค์ด๋‚˜๋ฏน ํ”„๋ก์‹œ์˜ ๋‹จ์ 

  • ์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ ๋ฌด์— ๋”ฐ๋ผ JDK ๋™์  ํ”„๋ก์‹œ, CGLIB์œผ๋กœ ๊ฐ๊ฐ ๊ตฌํ˜„ํ•ด์•ผ ํ–ˆ์Œ
  • ๋‹ค์ด๋‚˜๋ฏน ํ”„๋ก์‹œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” InvocationHandler์™€ MethodInterceptor์— ํƒ€๊นƒ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์กด์žฌํ•ด์•ผ ํ•จ

 

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ๋ž€?

๋‹ค์ด๋‚˜๋ฏน ํ”„๋ก์‹œ์˜ ๋‹จ์ ๋“ค์„ ํ•ด๊ฒฐํ•˜๊ณ ์ž ์œ„์˜ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ ๋ฌด์— ๋”ฐ๋ผ ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” ํŒฉํ† ๋ฆฌ

์ฆ‰, ๊ธฐ์กด ๋‹ค์ด๋‚˜๋ฏน ํ”„๋ก์‹œ์— ํŒฉํ† ๋ฆฌ ํŒจํ„ด ์ ์šฉ

 

 

Advidsor, Advice

๐Ÿ’ก Advisor = Advice + Pointcut

Advice: ํƒ€๊นƒ ์˜ค๋ธŒ์ ํŠธ์— ์ ์šฉํ•  ๋ถ€๊ฐ€๊ธฐ๋Šฅ์„ ๋‹ด์€ ์˜ค๋ธŒ์ ํŠธ

Pointcut: ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ์„ ์ ์šฉํ•  ๋Œ€์ƒ์ธ์ง€ ํŒ๋ณ„ํ•˜๋Š” ํ•„ํ„ฐ๋ง ๋กœ์ง

 

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ์˜ ๋‹จ์ 

  • ํ”„๋ก์‹œ๋ฅผ ์ ์šฉํ•  ์Šคํ”„๋ง Bean์˜ ๊ฐฏ์ˆ˜๋งŒํผ ํ”„๋ก์‹œ๋ฅผ ์ƒ์„ฑํ•ด์„œ Bean์œผ๋กœ ๋“ฑ๋กํ•ด์ฃผ์–ด์•ผ ํ•จ
  • ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์œผ๋กœ ๋“ฑ๋ก๋œ ์Šคํ”„๋ง Bean์—๋Š” ์ ์šฉ ๋ถˆ๊ฐ€๋Šฅ

 

๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ(Bean Post Processor)

ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋‹จ์ ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋นˆ์„ ๋“ฑ๋กํ•˜๊ธฐ ์ „์— ์›ํ•˜๋Š”๋Œ€๋กœ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋Š” **๋นˆ ํ›„์ฒ˜๋ฆฌ๊ธฐ(Bean Post Processor)**๋ฅผ ์‚ฌ์šฉ

์ฐธ๊ณ 

[Spring] ํ”„๋ก์‹œ์™€ ๋””์ž์ธํŒจํ„ด (tistory.com)

[Spring] ๋‹ค์ด๋‚ด๋ฏน ํ”„๋ก์‹œ(DynamicProxy) (tistory.com)`

[Spring] ํ”„๋ก์‹œ ํŒฉํ† ๋ฆฌ(ProxyFactory) (tistory.com)

JDK Dynamic Proxy์™€ CGLIB์˜ ์ฐจ์ด์ ์€ ๋ฌด์—‡์ผ๊นŒ? | Moon`s Development Blog (gmoon92.github.io)

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€