diff --git a/study/design-pattern/catalogs/proxy/example.png b/study/design-pattern/catalogs/proxy/example.png new file mode 100644 index 0000000..eec2833 Binary files /dev/null and b/study/design-pattern/catalogs/proxy/example.png differ diff --git a/study/design-pattern/catalogs/proxy/index.md b/study/design-pattern/catalogs/proxy/index.md new file mode 100644 index 0000000..2df06b2 --- /dev/null +++ b/study/design-pattern/catalogs/proxy/index.md @@ -0,0 +1,132 @@ +# Proxy + +a.k.a. **๋Œ€๋ฆฌ์ž(Surrogate)** + +## **๐Ÿ’กย ์ฑ…์—์„œ ์„ค๋ช…ํ•˜๋Š” ์˜๋„** + +๋‹ค๋ฅธ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•œ ๋Œ€๋ฆฌ์ž(surrogate) ๋˜๋Š” ์ž๋ฆฌ์ฑ„์›€์ž(placeholder) ์—ญํ• ์„ ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋‘ก๋‹ˆ๋‹ค. + +## **๐Ÿงย ์šฐ๋ฆฌ ์ƒํ™ฉ์— ๋งž๊ฒŒ ํ’€์–ด ์“ด ๋™๊ธฐ** + +์˜ˆ๋ฅผ ๋“ค์–ด ์ง€๋„ ์œ„์— ์ˆ˜์ฒœ ๊ฐœ์˜ ๋งˆ์ปค๋ฅผ ํ‘œ์‹œํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ด…์‹œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋งˆ์ปค๋ฅผ ๊ทธ๋ฆฌ๋Š” ๊ณผ์ •์€ ๋ณต์žกํ•ด์„œ ๋งŽ์€ ์ž์›์„ ํ•„์š”๋กœ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. + +๊ทธ๋Ÿฐ๋ฐ ์‚ฌ์šฉ์ž๋Š” ๋‚ด๋ถ€์ ์ธ ์‚ฌ์ •์€ ๋ชจ๋ฅด๋ฉฐ, ์ง€๋„ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋น ๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๊ธธ ๊ธฐ๋Œ€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ์ง€๋„๋ฅผ ํ™•๋Œ€ํ–ˆ๋‹ค๋ฉด ์ˆ˜์ฒœ๊ฐœ์˜ ๋งˆ์ปค๋ฅผ ํ•œ๋ฒˆ์— ๊ทธ๋ฆฌ์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. + +์ด๋ ‡๊ฒŒ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ๊ด€๋ฆฌํ•˜๊ธฐ๊ฐ€ ๊นŒ๋‹ค๋กœ์šด ๊ฐ์ฒด๋กœ ์ธํ•ด, ๊ผญ ํ•„์š”ํ•  ๋•Œ๋งŒ ์ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ค‘์š”ํ•œ ๊ฒƒ์€ ์ด๋ฏธ์ง€๊ฐ€ ํ•„์š”ํ•  ๋•Œ๋งŒ ์ƒ์„ฑ๋œ๋‹ค๋Š” ์‚ฌ์‹ค์ด ์™ธ๋ถ€์— ๋“œ๋Ÿฌ๋‚ด์„  ์•ˆ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ง€๋„ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ด€์ ์—์„œ ๊ตฌํ˜„์„ ๋ณต์žกํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์„œ๋„ ์•ˆ๋ฉ๋‹ˆ๋‹ค. + +ํ•ด๊ฒฐ์ฑ…์€ ๋งˆ์ปค์˜ ๋Œ€์—ญ์„ ๋งก์€ **๋งˆ์ปค** **ํ”„๋ก์‹œ**๋ผ๋Š” ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. **๋งˆ์ปค ํ”„๋ก์‹œ**๋Š” ๋งˆ์ปค์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๊ณ , ํ•„์š”ํ•  ๋•Œ ๋งˆ์ปค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค. + +![Example](./example.png) + +Proxy๋Š” RealSubject์ฒ˜๋Ÿผ ํ–‰๋™ํ•˜๋ฉฐ ํ•„์š”ํ•  ๋•Œ RealSubject์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. + +## **๐Ÿ› ย ํ™œ์šฉ์„ฑ: ์ด๋Ÿด ๋•Œ ์”๋‹ˆ๋‹ค** + +- ์›๊ฒฉ์ง€ ํ”„๋ก์‹œ(remote proxy): ์„œ๋กœ ๋‹ค๋ฅธ ์ฃผ์†Œ ๊ณต๊ฐ„์— ์กด์žฌํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋Œ€ํ‘œ ๊ฐ์ฒด๋กœ, ๋กœ์ปฌ ํ™˜๊ฒฝ์— ์œ„์น˜ํ•ฉ๋‹ˆ๋‹ค. +- ๊ฐ€์ƒ ํ”„๋ก์‹œ(virtual proxy): ์š”์ฒญ์ด ์žˆ์„ ๋•Œ๋งŒ ํ•„์š”ํ•œ ๊ณ ๋น„์šฉ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. (**๋™๊ธฐ์—์„œ ์„ค๋ช…ํ•œ ์˜ˆ์‹œ์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.)** +- ๋ณดํ˜ธ์šฉ ํ”„๋ก์‹œ(protection proxy): ์›๋ž˜ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์‹ค์ œ ์ ‘๊ทผ์„ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ์ฒด๋ณ„๋กœ ์ ‘๊ทผ ์ œ์–ด ๊ถŒํ•œ์ด ๋‹ค๋ฅผ ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +- ์Šค๋งˆํŠธ ์ฐธ์กฐ์ž(smart reference): ์›์‹œ ํฌ์ธํ„ฐ์˜ ๋Œ€์ฒด์šฉ ๊ฐ์ฒด๋กœ, ์‹ค์ œ ๊ฐ์ฒด์— ์ ‘๊ทผ์ด ์ผ์–ด๋‚  ๋•Œ ์ถ”๊ฐ€์ ์ธ ํ–‰๋™์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. + 1. ์‹ค์ œ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ฐธ์กฐ ํšŸ์ˆ˜๋ฅผ ์ €์žฅํ•˜๋‹ค๊ฐ€ ๋”๋Š” ์ฐธ์กฐ๊ฐ€ ์—†์„ ๋•Œ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ์ž๋™์œผ๋กœ ์—†์•ฑ๋‹ˆ๋‹ค. (aka. ์Šค๋งˆํŠธ ํฌ์ธํ„ฐ) + 2. ๋งจ ์ฒ˜์Œ ์ฐธ์กฐ๋˜๋Š” ์‹œ์ ์— ์˜์†์  ์ €์žฅ์†Œ์˜ ๊ฐ์ฒด๋ฅผ ๋ฉ”๋ชจ๋ฆฌ๋กœ ์˜ฎ๊น๋‹ˆ๋‹ค. + 3. ์‹ค์ œ ๊ฐ์ฒด์— ์ ‘๊ทผํ•˜๊ธฐ ์ „์—, ๋‹ค๋ฅธ ๊ฐ์ฒด๊ฐ€ ๊ทธ๊ฒƒ์„ ๋ณ€๊ฒฝํ•˜์ง€ ๋ชปํ•˜๋„๋ก ์‹ค์ œ ๊ฐ์ฒด์— ์ž ๊ธˆ์„ ๊ฒ๋‹ˆ๋‹ค. + +## **๐ŸŽย ๊ฒฐ๊ณผ** + +ํ”„๋ก์‹œ ํŒจํ„ด์€ ์–ด๋–ค ๊ฐ์ฒด์— ์ ‘๊ทผํ•  ๋•Œ ์ถ”๊ฐ€์ ์ธ **๊ฐ„์ ‘ํ™” ํ†ต๋กœ**๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ์ถ”๊ฐ€๋œ ๊ฐ„์ ‘ํ™” ํ†ต๋กœ๋Š” **ํ”„๋ก์‹œ์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ**์„œ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์“ฐ์ž„์ƒˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +1. ์›๊ฒฉ์ง€ ํ”„๋ก์‹œ๋Š” ๊ฐ์ฒด๊ฐ€ ๋‹ค๋ฅธ ์ฃผ์†Œ ๊ณต๊ฐ„์— ์กด์žฌํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์ˆจ๊ธธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +2. ๊ฐ€์ƒ ํ”„๋ก์‹œ๋Š” ์š”๊ตฌ์— ๋”ฐ๋ผ ๊ฐ์ฒ˜๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋“ฑ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +3. ๋ณดํ˜ธ์šฉ ํ”„๋ก์‹œ ๋ฐ ์Šค๋งˆํŠธ ์ฐธ์กฐ์ž๋Š” ๊ฐ์ฒด๊ฐ€ ์ ‘๊ทผํ•  ๋•Œ๋งˆ๋‹ค ์ถ”๊ฐ€ ๊ด€๋ฆฌ๋ฅผ ์ฑ…์ž„์ง‘๋‹ˆ๋‹ค. ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๊ฒƒ์ธ์ง€ ์‚ญ์ œํ•  ๊ฒƒ์ธ์ง€๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค. + +## **๐Ÿ—บย ๊ตฌํ˜„ ๋ฐฉ๋ฒ•** + +๋™๊ธฐ์—์„œ ์˜ˆ์‹œ๋กœ ๋“  ์ง€๋„ ์œ„์˜ ๋งˆ์ปค๋ฅผ ๊ทธ๋ฆฌ๋Š” ์ผ€์ด์Šค๋ฅผ ํ”„๋ก์‹œ๋กœ ๊ตฌํ˜„ํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. + +์šฐ์„  ์ง€๋„ ์ƒ์˜ ๊ทธ๋ž˜ํ”ฝ ๊ฐ์ฒด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” `Graphic` ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. + +```tsx +abstract class Graphic { + abstarct public draw(latLng: LatLng): void; +} +``` + +๋‹ค์Œ์œผ๋กœ `Graphic` ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” `Marker` ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. + +```tsx +class Marker extends Graphic { + constructor(id: string) { + // id๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งˆ์ปค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + } + + public draw(latLng: LatLng) { + // ์ธ์ž๋กœ ์ „๋‹ฌ๋œ ์ขŒํ‘œ์— ๋งˆ์ปค๋ฅผ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค. + } +} +``` + +`MarkerProxy` ํด๋ž˜์Šค๋„ ์—ญ์‹œ `Graphic` ๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. `MarkerProxy` ๋Š” `Marker` ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜๋กœ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  `Marker` ๊ฐ์ฒด๊ฐ€ ์ด๋ฏธ ์ƒ์„ฑ๋˜์—ˆ๋‹ค๋ฉด ๊ทธ๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์•„๋‹ˆ๋ผ๋ฉด ์ƒˆ๋กœ ์ƒ์„ฑํ•œ ํ›„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ `getMarker` ๋ฉ”์„œ๋“œ๋„ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. + +```tsx +class MarkerProxy extends Graphic { + private id: string; + private marker: Marker; + + constructor(id: string) { this.id = id; } + + public getMarker() { + if (!this.marker) { + this.marker = new Marker(this.id); + } + + return this.marker; + } + + public draw(latLng: LatLng) { + this.getMarker().draw(latLng); + } +} +``` + +`Graphic`, `MarkerProxy` , `Marker`๋Š” `Map` ํด๋ž˜์Šค์—์„œ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด์ œ ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ํ•ด๋‹นํ•˜๋Š” `Map` ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค. + +```tsx +class MeshMap { + private markers: Graphic[] = []; + + public insert(graphic: Graphic) { + // ๊ทธ๋ž˜ํ”ฝ ์š”์†Œ๋ฅผ ์ง€๋„์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. + this.markers.push(graphic) + } + + public changeZoom() { + // ๋งŒ์•ฝ zoom์ด ๋ณ€๊ฒฝ๋˜๋ฉด ์ง€๋„์— ์ถ”๊ฐ€๋˜์—ˆ๋˜ ๊ทธ๋ž˜ํ”ฝ ์š”์†Œ์˜ draw๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. + /** + * this.markers.forEach(m => m.draw(latLng)); + */ + } +} + +const map = new MeshMap(); +map.insert(new MarkerProxy("์ฒซ ๋ฒˆ์งธ ๋งˆ์ปค")); +``` + +## **๐Ÿ”™ย ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•œ ์˜ˆ์‹œ (๋˜๋Š” ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ–ˆ๋‹ค๋ฉด...)** + +ES6์—์„œ ์†Œ๊ฐœ๋œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ Proxy๋Š” ์ด๋ฆ„๋งŒ ๋ด๋„ ์•Œ๊ฒ ์ง€๋งŒ, ํ”„๋ก์‹œ ํŒจํ„ด๊ณผ ๊ด€๋ จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ Proxy ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +### ํ”„๋ก์‹œ ํŒจํ„ด์œผ๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ + +- ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์ œ์–ด**(๋ณดํ˜ธ์šฉ ํ”„๋ก์‹œ)** +- ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ ‘๊ทผ์ด ์ผ์–ด๋‚˜๋ฉด ์ถ”๊ฐ€์ ์ธ ๋™์ž‘์„ ์ˆ˜ํ–‰**(์Šค๋งˆํŠธ ์ฐธ์กฐ์ž)** +- ... ๋“ฑ๋“ฑ + +### ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ Proxy + +- ํƒ€๊ฒŸ ๊ฐ์ฒด(์›๋ณธ ๊ฐ์ฒด)์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ๊ฐ€๋กœ์ฑ„๊ณ , ์ถ”๊ฐ€์ ์ธ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. +- MobX์—์„œ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ Proxy๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„๋œ ๊ธฐ๋Šฅ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค. (ex. observable) + +## ์ฐธ๊ณ  + +- [Proxy Wikipedia](https://en.wikipedia.org/wiki/Proxy_pattern) +- [MDN Proxy](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Proxy) +- [The Amazing Power of JavaScript Proxies](https://levelup.gitconnected.com/the-amazing-power-of-javascript-proxies-aa27c6d06bcb) \ No newline at end of file