본문 바로가기
Backend/Spring

CGLIB 프록시

by unknownomad 2025. 3. 1.

 

JDK 동적 프록시 vs CGLIB

✔ Spring에서 @Transactional, @Cacheable 같은 AOP 기능을 적용할 때 JDK 동적 프록시와 CGLIB 프록시를 사용함

✔ Spring Boot 2.0부터 JDK 동적 프록시가 기본값으로 변경되었으며, 그 이유와 차이를 정리


CGLIB 프록시

✔ CGLIB(Code Generation Library) 프록시는 바이트코드를 조작하여 클래스 기반으로 프록시 객체를 생성하는 기술

✔ Spring에서는 AOP(Aspect-Oriented Programming)와 프록시 패턴에서 사용됨

CGLIB 프록시 개념

✔ JDK 동적 프록시와 차이점

  • JDK 동적 프록시: 인터페이스 기반 → 인터페이스가 필요함
  • CGLIB 프록시: 클래스 기반 → 인터페이스 없이도 프록시 생성 가능

✔ CGLIB 동작 방식

  • 원본 클래스를 상속하여 서브 클래스를 생성하고, 메서드를 오버라이딩하여 프록시 기능을 적용
  • MethodInterceptor를 사용하여 메서드 실행 전후 로직을 제어

Spring에서의 CGLIB 프록시 활용

✅ AOP (Aspect-Oriented Programming)

✔ @Transactional, @Cacheable 등의 Spring AOP 기능을 사용할 때 프록시 객체를 자동 생성

✔ Spring이 프록시를 만들 때 인터페이스가 없으면 CGLIB을 사용

JDK 동적 프록시 vs CGLIB

  • 인터페이스 존재 여부에 따라 Spring이 자동으로 선택
  • 인터페이스 있으면 JDK 동적 프록시, 없으면 CGLIB 프록시 사용
  • Spring Boot 2.0부터 CGLIB은 기본적으로 사용하지 않음 (proxyTargetClass = true 설정 시 사용 가능)

Q1. Spring Boot 2.0부터 CGLIB이 기본이 아닌 이유?

✔ JDK 동적 프록시 성능이 개선되었고, 유지보수성이 높아졌기 때문

✔ CGLIB은 final 클래스나 final 메서드에서 동작하지 않는 한계가 있음

✔ Spring Boot 2.0부터 JDK 동적 프록시가 기본값, 필요하면 CGLIB을 강제 사용 가능

Q2. CGLIB과 JDK 동적 프록시 중 무엇을 써야 할까?

✔ 가능하면 JDK 동적 프록시를 사용 → 성능과 유지보수성이 더 좋음

✔ 만약 클래스 기반으로 프록시를 만들어야 한다면 CGLIB 사용 가능

 


✅ @Transactional과 CGLIB

 @Transactional이 붙은 클래스나 메서드는 Spring이 프록시를 생성하여 트랜잭션을 관리함

인터페이스 없이 클래스만 있을 경우 CGLIB 프록시를 사용

@Transactional이 private 메서드에서 동작하지 않는 이유?

✔ CGLIB 프록시는 메서드를 오버라이딩하는 방식 → private 메서드는 상속되지 않으므로 프록시 적용 불가


CGLIB 프록시의 단점

CGLIB 단점

✔ 바이트코드 조작이 필요하므로 JDK 동적 프록시보다 성능이 다소 느림

✔ final 클래스 또는 final 메서드는 상속할 수 없어서 CGLIB 프록시 적용 불가

CGLIB을 사용하지 못하는 경우는?

✔ final 클래스 또는 final 메서드가 있는 경우

✔ proxyTargetClass = true를 설정하지 않으면 인터페이스 기반 JDK 프록시가 기본 적용됨


결론

✔ Spring에서 프록시 기반 AOP를 사용할 때 JDK 동적 프록시와 CGLIB 프록시를 선택함

✔ 인터페이스 있으면 JDK 동적 프록시, 없으면 CGLIB 프록시 사용

✔ CGLIB은 클래스를 상속하여 프록시 객체를 생성 → final 메서드는 프록시 적용 불가

✔ @Transactional, @Cacheable 같은 AOP 기능에서 자동으로 CGLIB을 사용할 수도 있음

✔ Spring Boot 2.0부터 JDK 동적 프록시가 기본값, 필요하면 proxyTargetClass = true 설정 가능

댓글