상세 컨텐츠

본문 제목

구조패턴중, Proxy 패턴에 대하여..

소프트웨어공학

by amanda.hyon 2024. 9. 17. 00:13

본문

구조 패턴은 프로그램 내 자료 구조나 인터페이스 구조 등 프로그램 구조를 설계하는데 사용되는 패턴으로,,

클래스나 객체를 조합하여 더 큰 구조를 만들수 있게 해줍니다.

 

구조패턴중, Proxy 패턴은 다른 객체에 대한 접근을 제어하는 디자인 패턴입니다. 프록시는 원래 객체에 대한 대리자 역할을 하며, 원래 객체와 동일한 인터페이스를 제공하지만, 그 접근을 제한하거나 추가 작업을 수행할 수 있습니다. 이 패턴은 실제 객체에 대한 직접적인 접근을 제어하거나 성능 향상, 보안, 로깅 등의 부가 기능을 추가하고자 할 때 사용됩니다.

 

언제 Proxy 패턴을 사용할까?

  • 원래 객체의 자원 비용이 클 때(리소스가 무거운 객체): 예를 들어, 원격 서버에 있는 객체나 대용량 데이터베이스에서 데이터를 가져오는 객체에 바로 접근하는 대신, 필요한 시점에만 객체를 생성하거나 데이터에 접근할 수 있습니다.
  • 접근을 제한하고 싶을 때: 특정 객체에 대한 접근을 제한하거나 인증 과정을 추가할 수 있습니다.
  • 추가적인 작업을 처리해야 할 때: 예를 들어, 로그를 남기거나, 성능 측정을 할 때 프록시를 통해 원래 객체의 기능을 수행하면서 부가 작업을 처리할 수 있습니다.

Proxy 패턴의 구조

  1. Subject(주체) - 원래 객체와 프록시 객체가 구현해야 하는 공통 인터페이스입니다.
  2. RealSubject(실제 객체) - 프록시가 대리하는 실제 객체입니다.
  3. Proxy(프록시 객체) - 실제 객체에 대한 접근을 제어하거나, 추가 기능을 수행하는 클래스입니다.

(적용사례) 이미지 로딩, 자바코드 기준.

이미지 파일을 로드하는데 시간이 오래 걸리는 경우를 생각해 보세요. 사용자가 이미지가 필요할 때만 이미지를 로드하고, 그 외에는 이미지 로드를 지연시키는 프록시 객체를 사용할 수 있습니다.

1. Subject 인터페이스

// Subject 인터페이스: Image
interface Image {
    void display();
}

Image 인터페이스는 이미지를 출력하는 공통 메소드를 정의합니다.

2. RealSubject - 실제 이미지 클래스

// RealSubject 클래스: RealImage
class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadImageFromDisk();
    }

    private void loadImageFromDisk() {
        System.out.println("이미지 로드 중: " + filename);
    }

    @Override
    public void display() {
        System.out.println("이미지 표시: " + filename);
    }
}

RealImage 클래스는 실제로 이미지를 로드하고 출력하는 클래스입니다. 이미지를 로드하는 데 시간이 오래 걸릴 수 있기 때문에 생성자에서 파일을 로드하는 작업을 수행합니다.

3. Proxy - 프록시 이미지 클래스

// Proxy 클래스: ProxyImage
class ProxyImage implements Image {
    private RealImage realImage;
    private String filename;

    public ProxyImage(String filename) {
        this.filename = filename;
    }

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

ProxyImage 클래스는 실제 이미지 객체(RealImage)에 대한 접근을 제어합니다. 이미지가 처음 필요할 때(display() 호출 시)에만 실제로 이미지를 로드합니다.

4. 클라이언트에서 사용하기

public class Main {
    public static void main(String[] args) {
        Image image = new ProxyImage("test_image.jpg");

        // 이미지가 필요할 때만 로드됨
        System.out.println("이미지 첫 번째 표시:");
        image.display();  // 출력: 이미지 로드 중: test_image.jpg, 이미지 표시: test_image.jpg

        System.out.println("\n이미지 두 번째 표시:");
        image.display();  // 출력: 이미지 표시: test_image.jpg
    }
}

출력 

이미지 첫 번째 표시:
이미지 로드 중: test_image.jpg
이미지 표시: test_image.jpg

이미지 두 번째 표시:
이미지 표시: test_image.jpg

 

(적용사례) 데이터베이스 연결 지연 (Lazy Initialization), 파이썬 코드 기준.

1. RealSubject - 실제 데이터베이스 연결 클래스

class RealDatabase:
    def __init__(self, db_name):
        self.db_name = db_name
        self.connect_to_database()

    def connect_to_database(self):
        print(f"데이터베이스 {self.db_name}에 연결 중...")

    def execute_query(self, query):
        print(f"쿼리 실행: {query}")
        # 여기서 실제 데이터베이스에 쿼리를 실행하고 결과를 반환합니다
 

RealDatabase 클래스는 실제로 데이터베이스에 연결하고 쿼리를 실행하는 클래스입니다. 이 클래스는 생성될 때 데이터베이스에 바로 연결합니다.

2. Proxy - 데이터베이스 연결 프록시 클래스

class DatabaseProxy:
    def __init__(self, db_name):
        self.db_name = db_name
        self.real_db = None

    def execute_query(self, query):
        if self.real_db is None:
            print("프록시: 데이터베이스 연결을 지연 중입니다.")
            self.real_db = RealDatabase(self.db_name)
        self.real_db.execute_query(query)

DatabaseProxy 클래스는 실제로 데이터베이스에 바로 연결하지 않고, 쿼리를 실행할 때만 데이터베이스에 연결하는 프록시입니다. 처음으로 쿼리를 실행할 때만 RealDatabase 객체를 생성하여 데이터베이스에 연결합니다.

3. 클라이언트에서 사용하기

if __name__ == "__main__":
    db = DatabaseProxy("my_database")

    # 첫 번째 쿼리를 실행할 때만 데이터베이스에 연결됨
    print("첫 번째 쿼리:")
    db.execute_query("SELECT * FROM users")  # 출력: 프록시: 데이터베이스 연결을 지연 중입니다, 데이터베이스 my_database에 연결 중..., 쿼리 실행: SELECT * FROM users

    print("\n두 번째 쿼리:")
    db.execute_query("SELECT * FROM orders")  # 출력: 쿼리 실행: SELECT * FROM orders

출력>>

첫 번째 쿼리:
프록시: 데이터베이스 연결을 지연 중입니다.
데이터베이스 my_database에 연결 중...
쿼리 실행: SELECT * FROM users

두 번째 쿼리:
쿼리 실행: SELECT * FROM orders
  • DatabaseProxy는 지연 로딩을 통해 처음 쿼리를 실행할 때만 실제 데이터베이스에 연결합니다. 이후 쿼리 실행 시에는 바로 연결된 데이터베이스를 사용합니다.
  • 클라이언트는 프록시와 실제 데이터베이스 객체를 동일하게 사용할 수 있으며, 프록시가 중간에서 데이터베이스 연결을 지연시키는 역할을 합니다.

관련글 더보기

댓글 영역