Proxy ํŒจํ„ด์€ ๋ญ˜๊นŒ? ์„œ๋ฒ„์—์„œ ๋“ค์—ˆ๋˜ ๊ฒƒ ๊ฐ™์€๋ฐ, ํŒจํ„ด์œผ๋กœ๋Š” ์–ด๋–ค ์˜๋ฏธ๊ฐ€ ์žˆ๋Š”์ง€ ์•Œ์•„๋ณด์ž.

Proxy

  • ์˜ˆ์ „์— ์˜๋ฏธ์žˆ์—ˆ๋˜ ๋ฐฉ๋ฒ•
  • ์˜คํžˆ๋ ค ํด๋ž˜์Šค๊ฐ€ ๋ช…๋ฐฑํ•˜์ง€ ์•Š๊ฒŒ ๋ณด์ด๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์–ด ์กฐ์‹ฌํ•ด์•ผ ํ•จ

Proxy๋ž€?

  • ์›น ๋ธŒ๋ผ์šฐ์ € ์„ค์ •์— ํ”„๋ก์‹œ ์„œ๋ฒ„๋ผ๋Š” ๊ฒƒ์ด ์žˆ์Œ
  • ์‹ค์ œ ์›น ์‚ฌ์ดํŠธ ์„œ๋ฒ„์™€ ์‚ฌ์šฉ์ž ์‚ฌ์ด์— ์žˆ๋Š” ์ค‘๊ฐ„ ์„œ๋ฒ„๋ฅผ ๋งํ•จ
  • ์ธํ„ฐ๋„ท ์ƒ์˜ ์บ์‹œ ๋ฉ”๋ชจ๋ฆฌ

Proxy Pattern

  • Proxy ์„œ๋ฒ„๊ฐ€ ํ•˜๋ ค๋Š” ๊ฒƒ๊ณผ ๋น„์Šทํ•จ
  • ํด๋ž˜์Šค์—์„œ ์–ด๋–ค ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๋Š”๊ฒŒ ์• ๋งคํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.
    • ๋ฐ์ดํ„ฐ๊ฐ€ ๋„ˆ๋ฌด ์ปค์„œ ๋ฏธ๋ฆฌ ์ฝ์–ด๋‘๋ฉด ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ๋ถ€์กฑํ•จ
    • ๊ฐœ์ฒด ์ƒ์„ฑ์‹œ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์‹œ๊ฐ„์ด ๊ฝค ๊ฑธ๋ฆผ
    • ๊ฐœ์ฒด๋Š” ๋งŒ๋“ค์—ˆ์œผ๋‚˜ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์Œ
    • ์ด๋Ÿฐ ๊ฒƒ๋“ค์„ ๊ฐ’๋น„์‹ผ ๋ฆฌ์†Œ์Šค๋ผ๊ณ  ํ•จ
  • ๋ชฉํ‘œ: โ€œ๋‹น์žฅ์€ ํ•„์š” ์—†์ง€๋งŒ, ํ•„์š”ํ•˜๊ฒŒ ๋  ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•˜์—ฌ ์–ธ์ œ๋“  ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์ž.โ€
  • ์ฒ˜์Œ ํ™”๋ฉด๊ฐ™์€ ๊ฒƒ์„ ๋กœ๋“œํ•œ๋‹ค๊ณ  ํ•  ๋•Œ, ๋ฆฌ์†Œ์Šค๋Š” ํŒŒ์ผ ๊ฒฝ๋กœ๋งŒ ๊ธฐ์–ต
  • ์‹ค์ œ๋กœ ํ™”๋ฉด์— ๋ณด์—ฌ์งˆ ํ•„์š”๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ ๋กœ๋“œ
  • ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์ •๋ณด๋Š” ์ €์žฅํ•ด๋‘š(์บ์‹ฑ)

์˜ˆ์‹œ: Image data

  • ์ด๋ฏธ์ง€๋Š” ์šฉ๋Ÿ‰์ด ํฌ๊ณ 
  • ์ €์žฅ ์žฅ์น˜์—์„œ ์ฝ์–ด์™€์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณดํ†ต ๋กœ๋”ฉํ•˜๋Š”๋ฐ ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค. (๋ณ‘๋ชฉ ํ˜„์ƒ ๋ฐœ์ƒ)
  • ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋ก์‹œ ํŒจํ„ด์„ ์ ์šฉํ•˜๊ธฐ ์ ํ•ฉํ•˜๋‹ค.

Proxy ์ ์šฉ X

public final class Image {
    private ImageData image;
 
    // ์ƒ์„ฑ์‹œ ์ด๋ฏธ์ง€๋ฅผ ๋กœ๋“œ
    public Image(String filePath) {
        this.image = ImageLoader.getInstance().load(filePath);
    }
 
    public void draw(Canvas canvas, float x, float y) {
        canvas.draw(this.image, x, y)
    }
}
  • filepath๋ฅผ ๋ฐ›์ž๋งˆ์ž ๋ฌด์กฐ๊ฑด ๋””์Šคํฌ์—์„œ ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์˜ด
  • ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋ฌด์กฐ๊ฑด ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐ„๋„ ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค.
  • ์–ธ์ œ๋‚˜ ๋ฌธ์ œ์ ์€ ์•„๋‹ˆ๋‹ค. ๋งŒ์•ฝ 500๊ฐœ ์ด๋ฏธ์ง€๋ฅผ ๋ชจ๋‘ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด ํฐ ๋ฌธ์ œ๋Š” ์•„๋‹ ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹ค๋งŒ, ์‚ฌ์šฉ ์—ฌ๋ถ€๊ฐ€ ํ™•๋ฅ ์ ์œผ๋กœ ๋‚ฎ๋‹ค๋ฉด ๊ตณ์ด ๋กœ๋“œํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋กœ๋“œํ•˜๋Š” ๋‚ญ๋น„๋ฅผ ๋ฒ”ํ•  ์ˆ˜ ์žˆ๋‹ค.

Proxy ์ ์šฉ O

public final class Image {
    private String filePath;
    private ImageData image;
 
    public Image(String filePath) {
        this.filePath = filePath;
    }
 
    public void draw(Canvas canvas, float x, float y) {
        if (this.image == null) {
            this.image = ImageLoader.getInstance().load(this.filePath);
        }
 
        canvas.draw(this.image, x, y);
    }
}
  • ๊ฐœ์ฒด ์ƒ์„ฑ์‹œ์—๋Š” ์•„๋ฌด ๋ฐ์ดํ„ฐ๋„ ์ฝ์ง€ ์•Š์Œ
  • ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์‹œ์ ์— ์บ์‹œ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ณ  ๋กœ๋“œ๋ฅผ ๊ฒฐ์ •
  • ์ด๋ ‡๊ฒŒ ํ•„์š”ํ•œ ์‹œ์ ์— ๋Šฆ์— ์ฝ์–ด์˜ค๋Š” ๋ฐฉ์‹์„ **์ง€์—ฐ(๊ฒŒ์œผ๋ฅธ) ๋กœ๋”ฉ(lazy loading)**์ด๋ผ ํ•จ
    • ์ด ๋ฐ˜๋Œ€๋Š” ์ฆ‰์‹œ((๋กœ๋”ฉํ•˜๊ณ ์‹ถ์–ด์„œ) ์•ˆ๋‹ฌ์ด ๋‚œ) ๋กœ๋”ฉ(eagar loading)

์ฆ‰์‹œ ๋กœ๋”ฉ vs. ์ง€์—ฐ ๋กœ๋”ฉ

  • ์œ„์—์„œ๋Š” ๋‘๊ฐ€์ง€ ๋น„๊ต๋ฅผ ํ–ˆ๋Š”๋ฐ, ์‚ฌ์‹ค ์บ์‹ฑ ์—ฌ๋ถ€๊นŒ์ง€ ์ ์šฉํ•œ๋‹ค๋ฉด 3๊ฐ€์ง€ ๋ถ„๋ฅ˜๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.
์ฆ‰์‹œ ๋กœ๋”ฉ์ง€์—ฐ ๋กœ๋”ฉ + ์บ์‹œ X์ง€์—ฐ ๋กœ๋”ฉ + ์บ์‹œ
(ํ”„๋ก์‹œ ํŒจํ„ด)
์ตœ์‹  ๋ฐ์ดํ„ฐXOโ–ณ
๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ตœ๋Œ€์ตœ์†Œ์ค‘๊ฐ„ (์‚ฌ์šฉํ•œ ๊ฒƒ์— ๋Œ€ํ•ด ์บ์‹ฑ์œผ๋กœ ๋“ค๊ณ  ์žˆ์Œ)
์‹คํ–‰ ์†๋„ ๋ณ‘๋ชฉ์ ์ƒ์„ฑ ์‹œ์ ์‚ฌ์šฉํ•  ๋•Œ ๋งˆ๋‹ค์•Œ๊ธฐ ์–ด๋ ค์›€ (์ฒ˜์Œ ์‚ฌ์šฉํ•œ ์‹œ์ ์— ๋ฐœ์ƒ)
  • ํ”„๋ก์‹œ ํŒจํ„ด์˜ ๊ฒฝ์šฐ ๋ช…ํ™•ํ•˜์ง€ ์•Š๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

์š”์ฆ˜ ์„ธ์ƒ์—์„œ์˜ ํ”„๋ก์‹œ ํŒจํ„ด

  • ๋ฉ”๋ชจ๋ฆฌ๋Ÿ‰์ด ๋งŽ๋‹ค.
    • ํ•œ ๋ฒˆ์— ๋กœ๋”ฉํ•ด๋†”๋„ ํฐ ๋ฌธ์ œ๋Š” ์•„๋‹ˆ๋‹ค.
  • ํ•œ ๋ฒˆ์— ๊ทธ๋ฆฌ๋Š” ์ด๋ฏธ์ง€ ์ˆ˜๊ฐ€ ๋งŽ์ง€ ์•Š๋‹ค๋ฉด?
    • ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๋””์Šคํฌ์—์„œ ์ฝ์ž.
    • ์ถฉ๋ถ„ํžˆ ๋นจ๋ผ์กŒ๋‹ค.
    • SSD๋ฉด ๋” ๋น ๋ฅด๋‹ค.
  • ์ธํ„ฐ๋„ท์—์„œ ๋กœ๋”ฉํ•œ๋‹ค๋ฉด?
    • ๋””์Šคํฌ๋ณด๋‹ค ๋” ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค.
    • ๊ทธ ๋™์•ˆ ํ”„๋กœ๊ทธ๋žจ์ด ๋ฉˆ์ถฐ์žˆ์„ ์ˆ˜๋Š” ์—†๋‹ค.

ํ”„๋ก์‹œ ํŒจํ„ด + ์บก์Šํ™”์˜ ๋ฌธ์ œ

  • ์บก์Šํ™”๋Š” ์ž˜ ํ•ด๋‘š
  • ํด๋ผ์ด์–ธํŠธ๋Š” ์‚ฌ์šฉ๋งŒ ํ•˜๋ฉด ๊ฒฐ๊ตญ ์ด๋ฏธ์ง€๊ฐ€ ๋กœ๋“œ๋˜์–ด ๋ฐ˜ํ™˜๋จ
  • ํ•˜์ง€๋งŒ.. ์–ธ์ œ ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ๋Š๋ ค์ง€๋Š”์ง€ ์•Œ ์ˆ˜ ์—†๋‹ค.
  • ์œ„์—์„œ ๋ณด์•˜๋“ฏ์ด ํ”„๋ก์‹œ ํŒจํ„ด์„ ์‚ฌ์šฉํ•œ ๊ฒฝ์šฐ ๋ช…ํ™•ํ•˜์ง€ ์•Š๋‹ค๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ๋Œ€๋ฌธ์ด๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ ์ž…์žฅ์—์„œ ํ•ด๋‹น ํด๋ž™์Šค๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์—,
  • ๊ฐ ๋ฐฉ์‹์— ๋Œ€ํ•ด ์ œ์–ด๊ถŒ์„ ํด๋ผ์ด์–ธํŠธ ์ชฝ์œผ๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ๊ฒƒ์ด ๋ณด๋‹ค ์˜ณ๋‹ค.
  • ๊ฒฐ๊ตญ ๊ณ ๊ฐ์˜ ๊ธฐ์ค€์œผ๋กœ ํ”„๋กœ๋•ํŠธ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์˜ณ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ํ”„๋ก์‹œ ํŒจํ„ด์˜ ํ˜„๋Œ€ํ™” ์˜ˆ

public final class Image {
    private String filePath;
    private ImageData image;
 
    public Image(String filePath) { 
        this.filePath = filePath;
    }
 
    public boolean isLoaded() {
        return this.image != null;
    }
 
    public void load() {
        if (this.image == null) {
            this.image = ImageLoader.getInstance().load(this.filePath);
        }
    }
 
    public void unload() {
        this.image = null;
    }
 
    public void draw(Canvas canvas, float x, float y) {
        canvas.draw(this.image, x, y);
    }
}
  • ์ƒ์„ฑ ์‹œ์—๋Š” filePath๋งŒ ๋ฐ›๋Š”๋‹ค.
  • ๋ฐ”๊นฅ์œผ๋กœ ์ด๋ฏธ์ง€ ๋กœ๋“œ ์—ฌ๋ถ€(isLoaded())๋ฅผ ํŒŒ์•… ํ•  ์ˆ˜ ์žˆ๊ฒŒ ์—ด์–ด์ค€๋‹ค.
  • ์ง์ ‘์ ์œผ๋กœ load() ํ•จ์ˆ˜๋ฅผ ์—ด์–ด์ฃผ์–ด ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
  • ์บ์‹œ๊ฐ€ ์ƒํ•  ๊ฒƒ์„ ๋Œ€๋น„ํ•˜์—ฌ unload() ํ•จ์ˆ˜๋„ ์ œ๊ณตํ•œ๋‹ค.
  • draw() ํ•จ์ˆ˜์˜ ๊ฒฝ์šฐ image๊ฐ€ ์žˆ๋‹ค๋Š” ์ „์ œํ•˜์— ์ž‘๋™ํ•œ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ™”๋ฉด์— ๋ฆฌ์†Œ์Šค ํŒŒ์ผ์„ ๋ช‡๊ฐœ ๋กœ๋“œํ–ˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋„ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋‹ค!
    • ์›๋ž˜๋Š” ๋กœ๋“œ ์—ฌ๋ถ€๋ฅผ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ƒฅ ๋ฒ™์ฐŒ๊ณ  ๊ธฐ๋‹ค๋ ค์•ผ ํ•œ๋‹ค.
    • ๊ทธ๋Ÿผ ๊ฐ•์ข…ํ•ด๋ฒ„๋ฆฌ๊ณ  ๊ทธ ์•ฑ ์•ˆ์“ฐ๊ฒ ์ง€

์ง€์—ฐ ๋กœ๋”ฉ ์ฃผ์˜์‚ฌํ•ญ

  • ํ•„์š”ํ•œ ๊ณณ์— ์ž˜ ์„ ํƒํ•˜์—ฌ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.
  • UX๋„ ๊ณ ๋ คํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ
  • ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ํ”„๋ก์‹œ ํŒจํ„ด์˜ ์ž…์ง€๊ฐ€ ์ข€ ์• ๋งคํ•ด์ง
    • ํด๋ผ์ด์–ธํŠธ ์ชฝ์œผ๋กœ ์ œ์–ด์—ฌ๋ถ€๋ฅผ ๋…ธ์ถœํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์บก์Šํ™”๊ฐ€ ์ข€ ๊นจ์ง
      • ๊ฒฐ๊ตญ ๋‚ด๋ถ€๊ฐ€ ์–ด๋–ป๊ฒŒ ๋„๋Š”์ง€ ๋…ธ์ถœํ•˜๋Š” ์…ˆ
  • ์ฆ‰, ๋ถ€์ˆ˜์ ์ธ ์š”์†Œ(์‹œ๊ฐ„, UX ๋“ฑ)์„ ๊ณ ๋ ค ํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์บก์Šํ™”๊ฐ€ ๊นจ์ง์—๋„ ์—ด์–ด๋‘๋Š” ๊ฒƒ์ด ์ข‹์€ ๋ฐฉ์•ˆ์ผ ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹จ์ˆœํžˆ ์บก์Šํ™”๋ฅผ ์œ„ํ•ด ๋ฐ–์—์„œ ๋™์ž‘์„ ๋ช…ํ™•ํžˆ ์•Œ์•„์•ผ ํ•จ์—๋„ ์ˆจ๊ธฐ๋Š” ๊ฒƒ์€ ๊ฐœ๋…์— ํ•จ๋ชฐ๋˜์–ด ์ค‘์š”ํ•œ ๊ฒƒ์„ ๋†“์น˜๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ฒ”ํ•  ์ˆ˜ ์žˆ๋‹ค.

Reference