@Transactional 구현 - 목차
2021.12.02 - [Java/@Transaction 구현] - 1. 배경설명, 구현 동기 및 목표
2021.12.02 - [Java/@Transaction 구현] - 2. Aspect Oriented Programming
2021.12.02 - [Java/@Transaction 구현] - 3. Proxy 패턴 (현재 글)
2021.12.02 - [Java/@Transaction 구현] - 4. JDK Dynamic Proxy
2021.12.02 - [Java/@Transaction 구현] - 5. 애너테이션 적용
앞서 Cell을 핵심기능과 부가기능으로 나눠서 살펴봤다. 부가기능을 모듈화하고 핵심기능의 전, 후에 실행하거나, 부가기능 내에서 핵심기능을 수행할 수 있다. 핵심기능을 변경하지 않고 어떻게 부가기능을 추가할 수 있을까?
프록시 패턴을 이용하면 목표를 달성할 수 있다. 프록시 패턴에 대해 알아본다.
프록시 패턴
프록시 패턴은 요청을 처리하는 객체에 대한 접근을 제어하는 용도로 사용한다. 대변인에 해당하는 객체를 제공하는 패턴이다.

일반적으로 요청이 발생하면, 객체의 메서드를 호출해 요청을 처리한다.

프록시 패턴은 처리하는 객체의 앞에서 요청을 먼저 받아서 적절한 부가기능을 제공한 후, 원래 객체의 메소드를 호출한다.
프록시 패턴의 주요 기능
접근제어
- 권한에 따른 접근 차단
- 캐싱
- 원본데이터에서 가져온 값을 프록시 객체에서 저장하고 있다가 요청이 들어오면 프록시에 저장된 값을 반환한다.
- 성능상의 이점을 얻을 수 있다.
- 지연로딩
- 프로그램이 실행될 때, 처음부터 모든 객체를 만들지 않고 "요청이 들어오면" 실제 객체를 만들어 요청을 처리한다.
부가기능 추가
- 원래 요청에 응답하는 객체에 기능을 더해 부가기능을 수행한다.
- 요청 값이나, 응답 값을 중간에 변형한다.
- 실행 시간을 측정해서 추가 로그를 남긴다.
프록시 패턴 UML

ProxyCell 클래스와 RealCell 클래스 모두 Cell 인터페이스를 구현한다.

Node객체는 ProxyCell객체를 주입받고, ProxyCell 객체는 RealCell 객체를 주입받는다.
Node에서 Cell 인터페이스를 이용해 메소드를 실행하면, RealCell의 메소드를 바로 호출하지 않고, 대리자인 ProxyCell의 메소드를 호출한다. 그리고 ProxyCell 객체에 설정한 부가기능을 수행하고, RealCell 객체를 호출해 핵심기능을 수행한다.
Code
Node.java
public class Node {
private final Cell cell;
public Node(Cell cell) {
this.cell = cell;
}
public void execute () {
cell.canEdit();
cell.getValue();
cell.setValue("test");
}
}
ProxyCell.java
public class ProxyCell implements Cell {
private final Cell realCell;
public ProxyCell(Cell realCell) {
this.realCell = realCell;
}
@Override
public boolean canEdit() {
System.out.println("=== Authentication ===");
return realCell.canEdit();
}
@Override
public Object getValue() {
System.out.println("=== Authentication ===");
return realCell.getValue();
}
@Override
public void setValue(Object value) {
System.out.println("=== Authentication ===");
System.out.println("=== Transaction in ===");
realCell.setValue(value);
System.out.println("=== Transaction out ===");
}
}
생성자에서 realCell 을 주입받는다. 각 메서드에서 부가기능을 수행하고, realCell 의 동일한 이름의 메서드를 수행한다.
RealCell.java
public class RealCell implements Cell {
@Override
public boolean canEdit() {
System.out.println("real canEdit\n");
return false;
}
@Override
public Object getValue() {
System.out.println("real getValue()\n");
return null;
}
@Override
public void setValue(Object value) {
System.out.println("real setValue() : " + value);
}
}
RealCell 클래스에는 핵심 기능만 남긴다.
NodeTest.java
class NodeTest {
@Test
void proxyTest (){
Cell realCell = new RealCell();
Cell proxyCell = new ProxyCell(realCell);
Node node = new Node(proxyCell);
node.execute();;
}
}
의존성을 위와 같이 주입하고 실행하면, 부가기능과 핵심기능을 모두 실행할 수 있다. 그림으로 나타내면 다음과 같다.

부가기능을 ProxyCell 로 옮기면, RealCell에는 핵심기능만 남길 수 있다.
위와 같이 개발자가 직접 프록시 클래스를 구현할 수 있다. 그러나 JDK Dynamic Proxy 라이브러리를 이용하면, 프록시 클래스를 직접 작성하지 않고, 동적으로 프록시 클래스를 만들 수 있다.
'Java > @Transaction 구현' 카테고리의 다른 글
5. 애너테이션 적용 (0) | 2021.12.02 |
---|---|
4. JDK Dynamic Proxy (0) | 2021.12.02 |
2. Aspect Oriented Programming (0) | 2021.12.02 |
1. 배경설명, 구현 동기 및 목표 (0) | 2021.12.02 |