BE/Java

[Java] 프록시

baek-dev 2024. 12. 22. 14:59

대리인이나 중개자를 뜻하며, 소프트웨어에서는 다른 객체에 대한 접근을 제어하거나 대체 역할을 하는 객체를 말한다

쉽게말해, 원래 객체에 접근하기 전에 중간에 끼어드는 객체


프록시의 필요성

1. 추가 작업 수행

  • 원래 객체를 호출하기 전후에 부가 작업을 수행해야 할때
  • 예: 로깅, 인증, 캐싱, 지연 로딩 등

2. 원래 객체 보호

  • 원래 객체에 대한 접근을 제한하거나 제어
  • 예: 보안 관련 작업

3. 성능 최적화

  • 실제 객체의 생성이나 초기화를 나중으로 미루는 경우 (지연 로딩)

4. 구조적 유연성

  • 객체 교체나 확장성을 높이기 위해 중간 계층을 추가

프록시의 종류

1. 정적 프록시 (Static Proxy)

  • 컴파일 시점에 프록시 객체를 작성
  • 원래 객체와 동일한 인터페이스를 구현
  • 코드가 고정적이고, 클래스별로 프록시를 별도로 작성해야함
interface Service {
    void performTask();
}

class RealService implements Service {
    @Override
    public void performTask() {
        System.out.println("Real Service is performing the task.");
    }
}

class StaticProxy implements Service {
    private RealService realService;

    public StaticProxy(RealService realService) {
        this.realService = realService;
    }

    @Override
    public void performTask() {
        System.out.println("Proxy: Pre-processing before the task.");
        realService.performTask();
        System.out.println("Proxy: Post-processing after the task.");
    }
}

public class Main {
    public static void main(String[] args) {
        RealService realService = new RealService();
        StaticProxy proxy = new StaticProxy(realService);
        proxy.performTask();
    }
}

 

출력:

Proxy: Pre-processing before the task.
Real Service is performing the task.
Proxy: Post-processing after the task.

 

 

2. 동적 프록시 (Dynamic Proxy)

  • 런타임에 프록시 객체를 생성
  • 자바의 java.lang.reflect.Proxy 클래스와 InvocatonHandler 인터페이스를 사용
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface Service {
    void performTask();
}

class RealService implements Service {
    @Override
    public void performTask() {
        System.out.println("Real Service is performing the task.");
    }
}

class DynamicProxyHandler implements InvocationHandler {
    private Object target;

    public DynamicProxyHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Proxy: Pre-processing before the task.");
        Object result = method.invoke(target, args);
        System.out.println("Proxy: Post-processing after the task.");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        RealService realService = new RealService();

        Service proxy = (Service) Proxy.newProxyInstance(
            realService.getClass().getClassLoader(),
            realService.getClass().getInterfaces(),
            new DynamicProxyHandler(realService)
        );

        proxy.performTask();
    }
}

 

출력:

Proxy: Pre-processing before the task.
Real Service is performing the task.
Proxy: Post-processing after the task.

 

 

3. 프레임워크 기반 프록시

  • 스프링 프록시 : 스프링은 AOP (Aspect-Oriented Programming) 에서 프록시를 적극적으로 사용
    • JDK 동적 프록시 : 인터페이스를 구현한 객체를 프록시로 생성
    • CGLIB : 클래스의 서브클래스를 동적으로 생성하여 프록시를 생성

예제: 스프링 AOP에서의 프록시

  • @Transactional 또는 @Aspect같은 기능은 프록시로 구현된다
@Service
public class MyService {
    @Transactional
    public void performTask() {
        System.out.println("Performing task in a transactional context.");
    }
}
  • 여기서 @Transactional은 프록시를 통해 트랜잭션 처리가 추가된다

프록시의 주요 속성과 메서드

1. 속성

  • target : 프록시가 대리하는 원래 객체
  • method : 프록시 객체에서 호출된 메서드
  • arguments : 메서드 호출시 전달된 매개변수

 

2. 주요 동작

  • 메서드 호출 전/후 로직 삽입
  • 원래 객체의 메서드 실행을 위임
  • 동적으로 원래 객체를 교체 가능

프록시의 장 단점

장점

1. 원래 객체의 변경 없이 부가 기능 추가 가능

2. 코드의 재사용성과 유지보수성이 높아짐

3. 지연로딩, 로깅, 보안, 캐싱 등 다양한 용도로 활용 가능

 

단점

1. 정적 프록시는 클래스별로 프록시를 작성해야 하므로 코드가 중복될 수 있음

2. 동적 프록시는 성능 오버헤드가 발생할 수 있음

3. 복잡도가 증가하여 디버깅이 어려워질 수 있음


정리

1. 프록시란?

  • 원래 객체를 대신하여 중간에서 작업을 수행하거나, 원래 객체에 대한 접근을 제어하는 객체

2. 종류

  • 정적 프록시 : 미리 작성된 프록시 클래스
  • 동적 프록시 : 런타임에 생성

3. 사용 사례

  • 로깅, 인증, 트랜잭션 관리, 지연 로딩 등

4. 스프링에서의 활용

  • AOP, @Transactional 등에서 프록시를 사용

 

 

 

 

 

출처 : ChatGPT

'BE > Java' 카테고리의 다른 글

[Java] @IdClass  (0) 2024.12.31
[Java] @Builder, @ToString, @EqualsAndHashCode, @Singular  (0) 2024.12.23
[Java] 쓰레드  (0) 2024.12.22
[Java] StringBuffer, StringBuilder  (1) 2024.12.19
[Java] 영속성  (0) 2024.12.16