JPA 프록시에 사용하는 ByteBuddy

2024. 9. 14. 23:37개발/Spring

Lazy Loading(지연 로딩)을 하게 되면 연관 관계에 있는 엔터티 객체는 엔터티 객체를 상속받은 프록시 객체로 채워넣고 나중에 실제로 사용할 때 초기화 한다. 이 때 사용되는 프록시 라이브러리가 ByteBuddy이다. 이 프록시 객체를 Jackson에서 직렬화하려고 할 때 type 관련 에러가 발생하므로 연관 관계가 있는 엔터티를 RequestBody로 받는 것은 지양하자. ByteBuddyInterceptor 클래스의 경우 hibernate에서 제공하는 것으로 보인다.

import org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor;

ByteBuddy란?

컴파일러의 도움 없이 런타임에 자바 클래스를 생성 또는 수정하는 라이브러리이다.

ByteBuddy를 사용한 예제

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;

public class ByteBuddyInterceptorExample {
    
    public static class TargetClass {
        public String sayHello(String name) {
            return "Hello, " + name;
        }
    }

    public static class Interceptor {
        public static String intercept(String name) {
            return "Intercepted! Hello, " + name;
        }
    }

    public static void main(String[] args) throws Exception {
        TargetClass target = new ByteBuddy()
            .subclass(TargetClass.class)
            .method(ElementMatchers.named("sayHello"))
            .intercept(MethodDelegation.to(Interceptor.class))
            .make()
            .load(TargetClass.class.getClassLoader())
            .getLoaded()
            .newInstance();
        
        System.out.println(target.sayHello("Byte Buddy"));  // Output: Intercepted! Hello, Byte Buddy
    }
}

ChatGPT에 의하면 Mockito 라이브러리도 동적으로 Mock 객체를 사용할 때 ByteBuddy를 이용한다고 한다.