괴발개발 성장기

Study/디자인패턴

[디자인패턴] 프록시 패턴(Proxy Pattern)

지니유 2023. 8. 28. 14:06
반응형

프록시 패턴(Proxy Pattern)

  • 어떤 객체의 대리자 역할을 하는 객체를 통해 해당 객체의 기능을 간접적으로 사용하는 디자인 패턴
  • 원래 사용하려는 객체를 직접 사용하지 않고 대리인을 통해서 쓰는 패턴

클라이언트로 첫 요청을 받으면 프록시 받는 것이다. 예를 들으면 사장을 만나기 위해서는 비서를 거쳐서 가는 것과 비슷한 개념이다.

 

# 장점

- 기존 코드는 수정하지 않고 새로운 기능을 추가한다 => 개방폐쇄의 원칙
- 기존 코드의 기능만 유지할 수 있다.
- 보안을 강화시킬 수 있다.
- 초기화 지연을 시킬 수 있다. => 최초로 사용할 때 만든다.
- 캐싱하여 성능을 향상
- 특정 권한이나 조건에 맞는 경우 객체에 접근할 수 있다.

 

# 단점

- 코드의 복잡성이 증가한다.

 

# 예시

가상 프록시를 사용하여 이미지 로딩을 지연시키는 상황

 

이미지를 받을 때 마다 이미지 이름을 출력해보자.

// 인터페이스 정의 => Image 인터페이스는 Display() 메서드를 가지고 있다.
type Image interface {
	Display()
}

// RealImage는 실제 이미지를 나타내는 구조체
type RealImage struct {
	filename string
}

func NewRealImage(filename string) *RealImage {
	fmt.Println("Loading image:", filename)
	return &RealImage{filename: filename}
}

func (r *RealImage) Display() {
	fmt.Println("Displaying image:", r.filename)
}

프록시를 만들어보자

// ProxyImage는 이미지 로딩을 지연시키는 프록시 구조체
type ProxyImage struct {
	realImage *RealImage
	filename  string
}

func NewProxyImage(filename string) *ProxyImage {
	return &ProxyImage{filename: filename}
}

// ProxyImage의 Display() 메서드에서는 실제 이미지가 로딩되기 전에는 realImage가 초기화되지 않습니다.
func (p *ProxyImage) Display() {
	if p.realImage == nil { 
    // 이미지가 실제로 필요한 순간에 realImage를 생성하고 로딩하여 실제 이미지를 보여줍니다.
		p.realImage = NewRealImage(p.filename)
	}
	p.realImage.Display() // 실제 이미지를 표시
}

 

메인에서 실행해보자

func main() {
		var image Image = NewProxyImage("example.jpg")

		// 이미지 로딩이 필요한 시점에서 실제 이미지가 로딩됨
		image.Display()

		// 이미지 로딩이 필요 없으므로 실제 이미지는 로딩되지 않음
		image.Display()
 }

처음에 Display() 호출 될 때 realImage가 없기 때문에 p.realImage = NewRealImage(p.filename) 실제 이미지 객체를 생성한다.

그리고 p.realImage.Display()를 호출하여 실제 이미지를 표시한다.

 

다시 Display() 호출하면 ProxyImage에서 이미 이미지가 로딩되어있음을 알고  바로 p.realImage.Display() 호출한다.

그럼 다시 실제 이미지를 표시하지 않고 이미지가 이미 로딩되었음을 알려준다.

 

 

# 참고 이슈

https://github.com/YooGenie/go-study/issues/78

 

프록시 패턴 · Issue #78 · YooGenie/go-study

 

github.com

 

 

 

반응형