๊นจ์•Œ ๊ฐœ๋… ๐Ÿ“‘/๊ธฐํƒ€

SOLID ์›์น™

interfacer_han 2025. 12. 1. 19:27

#1 ํ”„๋กœ๊ทธ๋žจ์˜ ์šด๋ช…๊ณผ ์„ค๊ณ„

์ธ๊ฐ„์˜ ์šด๋ช…์€ ๋ช…ํ™•ํ•˜๋‹ค. ํŠน์ด์ ์ด ์˜ค์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฐ€์ •ํ•˜์—, ์ธ๊ฐ„์€ ์–ธ์  ๊ฐ„ ๋ฐ˜๋“œ์‹œ ์ฃฝ๋Š”๋‹ค. ํ”„๋กœ๊ทธ๋žจ์˜ ์šด๋ช…๋„ ๋ช…ํ™•ํ•˜๋‹ค. ํ•œ ๋ฒˆ ๊ฐœ๋ฐœ๋œ ํ”„๋กœ๊ทธ๋žจ์€, ๋ฏธ๋ž˜์— ๋ฐ˜๋“œ์‹œ ๋ณ€๊ฒฝ(์œ ์ง€๋ณด์ˆ˜)๋œ๋‹ค.

 

'์šด๋ช…'์„ ๊ณ ๋ คํ•˜๋ฉด ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ '์ข‹์€ ์„ค๊ณ„'๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๋– ์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋‹ค. ๋ฐ”๋กœ, ๋ณ€๊ฒฝ์— ๊ฐ•ํ•œ ์„ค๊ณ„(๊ตฌ์กฐ)๋‹ค. ์•„๋ž˜์— ์žˆ๋Š” ๋ง์€ ๋‹ค ๊ฐ™์€ ๋ง์ด๋‹ค.

 

๋ณ€๊ฒฝ์— ๊ฐ•ํ•œ ์„ค๊ณ„(๊ตฌ์กฐ)
= ์ƒˆ๋กœ์šด ์š”๊ตฌ์‚ฌํ•ญ์ด๋‚˜ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์žˆ์„ ๋•Œ, ๋ฐ”๊ฟ”์•ผ ํ•˜๋Š” ์ฝ”๋“œ์˜ ๋ฒ”์œ„๊ฐ€ ์ข์€ ๊ตฌ์กฐ
= ๋ณ€๊ฒฝ์— ์œ ์—ฐํ•˜๊ฒŒ ๋Œ€์ฒ˜๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ
= ํ™•์žฅ์„ฑ์ด ๋†’์€ ๊ตฌ์กฐ

 

#2 SOLID ์›์น™

#2-1 Whatใ†Why

#1์—์„œ ๋งํ•œ '๋ณ€๊ฒฝ์— ๊ฐ•ํ•œ' ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๊ณ ์•ˆ๋œ 5๊ฐ€์ง€ ํŒจํ„ด(์›์น™)์ด๋‹ค. S,O, L, I, D์˜ ๊ฐ ์•ŒํŒŒ๋ฒณ์ด ํŒจํ„ด ํ•˜๋‚˜์— ๋Œ€์‘ํ•œ๋‹ค. 

 

#2-2 ์ด๋ชจ์ €๋ชจ

  • ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๋‹จ๊ณจ ๋ฉด์ ‘ ์งˆ๋ฌธ ์ค‘ ํ•˜๋‚˜๋‹ค.
  • ํ˜„๋Œ€์˜ ๋งŽ์€ ๋””์ž์ธ ํŒจํ„ด์ด SOLID ์„ค๊ณ„ ์›์น™์— ๋”ฐ๋ผ์„œ ๋งŒ๋“ค์–ด์กŒ๋‹ค. (SOLID๊ฐ€ ๊ทผ๊ฐ„).
  • ๋ˆˆ์— ๋„๋Š” ์ฒ ์ž๋กœ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด S → O → L → I → D ์ˆœ์œผ๋กœ ๋ฐฐ์—ด๋˜์—ˆ์„ ๋ฟ, 5์›์น™ ๊ฐ„ ์šฐ์„ ์ˆœ์œ„๋Š” ์—†๋‹ค.
  • 5๊ฐ€์ง€ ์›์น™๋“ค์€ ์„œ๋กœ ์™„์ „ํžˆ ๋…๋ฆฝ๋œ ๊ฐœ๋ณ„์ ์ธ ๊ฐœ๋…์ด ์•„๋‹ˆ๋ผ ๊ฐœ๋…์ ์œผ๋กœ ์—ฐ๊ด€๋˜์–ด ์žˆ๋‹ค. ์›์น™๋ผ๋ฆฌ ์„œ๋กœ์„œ๋กœ ์ด์šฉํ•˜๊ธฐ๋„ ํ•˜๊ณ  ์ผ๋ถ€ ๊ฒฝ์šฐ์—์„  ํฌํ•จ ๊ด€๊ณ„๋ฅผ ์ด๋ฃฐ ์ˆ˜ ์žˆ๋‹ค.
  • ์ฝ”๋“œ์— ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค๋ฉด ์–ต์ง€๋กœ ์ง€ํ‚ค์ง€ ์•Š์•„๋„ ๋œ๋‹ค. ๋˜ S, O, L, I, D ์ „๋ถ€๊ฐ€ ์•„๋‹ˆ๋ผ ์ผ๋ถ€๋งŒ ์ง€์ผœ๋„ ๋œ๋‹ค. (ํ˜•์‹๋ณด๋‹จ ๊ธฐ๋Šฅ!).

 

#3 [S] ๋‹จ์ผ ์ฑ…์ž„ ์›์น™

Single Responsibility Principle, SRP

 

#3-1 What

ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋Š” ํ•˜๋‚˜์˜ '์ฑ…์ž„'๋งŒ์„ ์ง€๋…€์•ผ ํ•œ๋‹ค.

* ์ฑ…์ž„(Responsibility): ์กด์žฌ ์˜์˜ (์—ญํ• , ๊ธฐ๋Šฅ ๋“ฑ)

๋งŒ์•ฝ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค์— ๊ธฐ๋Šฅ(์ฑ…์ž„)์ด ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ๋‹ค๋ฉด, ๊ธฐ๋Šฅ ๋ณ€๊ฒฝ(์ˆ˜์ •)์ด ์ผ์–ด๋‚ฌ์„ ๋•Œ ์ˆ˜์ •ํ•ด์•ผ ํ•  ์ฝ”๋“œ๊ฐ€ ๋งŽ์•„์ง„๋‹ค. ๋‚ด๊ฐ€ ์„ค๊ณ„ํ•œ ํด๋ž˜์Šค๊ฐ€ ๋งŒ์•ฝ ๋ฏธ๋ž˜์— ๋ณ€๊ฒฝ๋œ๋‹ค๋ฉด, ๊ทธ ์ด์œ ๋Š” ํ•œ ๊ฐ€์ง€ ์ข…๋ฅ˜์˜ '์ฑ…์ž„(Responsibility)' ๋•Œ๋ฌธ์ด์–ด์•ผ ํ•œ๋‹ค.

 

#3-2 'Ripple Effect'๋ž€

UI ๋””์ž์ธ์—์„œ๋Š”, (๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋“ฑ ๋•Œ์˜) ์‹œ๊ฐ์  ๋ฌผ๊ฒฐ(Ripple) ํšจ๊ณผ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋Š” ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” ์ฝ”๋“œ ๋ณ€๊ฒฝ ์‹œ ์˜ˆ๊ธฐ์น˜ ์•Š๊ฒŒ ๋ฐœ์ƒํ•˜๋Š” ์ฝ”๋“œ์˜ ์—ฐ์‡„์ ์ธ ์˜ํ–ฅ(ํŒŒ๊ธ‰ ํšจ๊ณผ)์„ ์˜๋ฏธํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” Ripple Effect๋ฅผ ํ›„์ž์˜ ์˜๋ฏธ๋กœ ์‚ฌ์šฉํ•œ๋‹ค.

 

#3-3 ์˜ˆ์‹œใ†๊ธฐ๋Œ€ ํšจ๊ณผ

SRP๋ฅผ ์ง€ํ‚ค์ง€ ์•Š์€ ์˜ˆ์‹œ

๊ธฐ๋Šฅ(์ฑ…์ž„)์„ ์—ฌ๋Ÿฌ ๊ฐœ ๊ฐ€์ง„ ํด๋ž˜์Šค A๊ฐ€ ์žˆ์„ ๋•Œ,
A์˜ ํŠน์ • ๊ธฐ๋Šฅ์„ ๋ณ€๊ฒฝํ•˜๋ฉด
→ ์—ฐ๊ด€๋œ ํด๋ž˜์Šค B ์ˆ˜์ •
→ ์—ฐ๊ด€๋œ ํด๋ž˜์Šค C ์ˆ˜์ •
→ ์—ฐ๊ด€๋œ ํด๋ž˜์Šค D ์ˆ˜์ •

Ripple Effect๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์‹œ๋‹ค. ์œ„์˜ ์˜ˆ์‹œ์—์„œ ๋” ๋‚˜์•„๊ฐ€ ๋งŒ์•ฝ D์˜ ์ˆ˜์ • ์‚ฌํ•ญ์ด A์—๊ฒŒ Ripple Effect๋ฅผ ์ผ์œผํ‚จ๋‹ค๋ฉด, Ripple Effect๊ฐ€ A์—์„œ ์‹œ์ž‘ํ•ด์„œ A๋กœ ๋Œ์•„์˜ค๋Š” ์ˆœํ™˜ ํ˜•ํƒœ๊ฐ€ ๋˜๊ณ  ๋งŒ๋‹ค. ํ˜ผ๋ˆ ๊ทธ ์ž์ฒด๋‹ค. ๋งŒ์•ฝ SRP๋ฅผ ์ค€์ˆ˜ํ–ˆ๋‹ค๋ฉด ์ฝ”๋“œ ๋ณ€๊ฒฝ์ด ํ•˜๋‚˜์˜ ํด๋ž˜์Šค ๋‚ด๋ถ€๋กœ ํ•œ์ •๋˜์—ˆ์„ ๊ฒƒ์ด๋‹ค (= Ripple Effect๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์•˜์„ ๊ฒƒ์ด๋‹ค).

 

๊ธฐ๋Œ€ ํšจ๊ณผ

SRP ํŒจํ„ด์„ ์ค€์ˆ˜ํ•˜์—ฌ, Ripple Effect๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

#4 [O] ๊ฐœ๋ฐฉ ํ์‡„ ์›์น™

Open Closed Principle, OCP

 

#4-1 What

(์ธํ„ฐํŽ˜์ด์Šค๋‚˜) ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ, ๊ธฐ์กด ์ฝ”๋“œ(๋ถ€๋ชจ ํด๋ž˜์Šค)๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์•ผ ํ•œ๋‹ค.

์ด๋ฅผ ๋‹ฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด์„œ, ๋ถ€๋ชจ ํด๋ž˜์Šค์—๋Š” '์ตœ์†Œํ•œ์˜ ์ถ”์ƒํ™”(#4-2) ์ฝ”๋“œ'๋งŒ์„ ๋‚จ๊ธฐ๊ณ  ๋‚˜๋จธ์ง€๋Š” ์ œ๊ฑฐํ•ด์•ผ ํ•œ๋‹ค.

 

#4-2 '์ถ”์ƒ'์ด๋ž€

  • ํ‘œ์ค€๊ตญ์–ด๋Œ€์‚ฌ์ „: ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์‚ฌ๋ฌผ์ด๋‚˜ ๊ฐœ๋…์—์„œ ๊ณตํ†ต๋˜๋Š” ํŠน์„ฑ์ด๋‚˜ ์†์„ฑ ๋”ฐ์œ„๋ฅผ ์ถ”์ถœํ•˜์—ฌ ํŒŒ์•…ํ•˜๋Š” ์ž‘์šฉ (๋งํฌ)
  • ๊ทธ๋ž˜๋”” ๋ถ€์น˜(Grady Booch): ๋‹ค๋ฅธ ๋ชจ๋“  ์ข…๋ฅ˜์˜ ๊ฐ์ฒด๋กœ๋ถ€ํ„ฐ ์‹๋ณ„๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์˜ ๋ณธ์งˆ์ ์ธ ํŠน์ง•

์—ฌ๊ธฐ์—์„  '์ถ”์ƒ'์„ ๋ฌ˜์‚ฌํ•  ๋•Œ ์ผ๋ฐ˜์ ์œผ๋กœ ํ†ต์šฉ๋˜๋Š” ์„ค๋ช…์„, #4-4์—์„  '์ถ”์ƒ'์˜ ๋ณธ์งˆ์ ์ธ ์„ค๋ช…์„ ๋‹ค๋ฃฌ๋‹ค. ์ถ”์ƒ์€ '๊ณตํ†ต๋œ ๊ฒƒ'์ด๋ผ๊ณ  ์„ค๋ช…๋˜๋Š” ๊ฒŒ ์ผ๋ฐ˜์ ์ด๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๋ฆผ 'ํšŒ์ƒ‰ ๋‚˜๋ฌด'์— ์žˆ๋Š” ๋ฌผ์ฒด๋ฅผ '๋‚˜๋ฌด'๋ผ๊ณ  ์ธ์‹ํ•˜๋Š” ์ด์œ ๋Š”, ๊ทธ ๊ทธ๋ฆผ์—์„œ ํ˜„์‹ค์˜ ๋‚˜๋ฌด๋“ค์ด ๊ณตํ†ต์œผ๋กœ ์ง€๋‹ˆ๋Š” ํŠน์„ฑ์„ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

#4-3 ์˜ˆ์‹œใ†๊ธฐ๋Œ€ ํšจ๊ณผ

OCP๋ฅผ ์ง€ํ‚ค์ง€ ์•Š์€ ์˜ˆ์‹œ

open class Animal {
    // ์ƒˆ๋กœ์šด ๋™๋ฌผ(์˜ˆ: Fox)์„ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ์ด when ๋ฌธ์„ ๋ฐ˜๋“œ์‹œ ์ˆ˜์ •ํ•ด์•ผ ํ•จ → OCP ์œ„๋ฐ˜
    fun speak(animal: Animal): String {
        return when (animal) {
            is Dog -> "์™ˆ"
            is Cat -> "๋ƒฅ"
            else -> "..."
        }
    }
}

class Dog : Animal()

class Cat : Animal()

์œ„์˜ ์ฝ”๋“œ๋ฅผ #4-2์— ์žˆ๋Š” '์ถ”์ƒ' ๊ฐœ๋…์œผ๋กœ ์„ค๋ช…ํ•˜์ž๋ฉด, ๋™๋ฌผ๋“ค์€ ๊ณตํ†ต์œผ๋กœ ์†Œ๋ฆฌ๋ฅผ ๋‚ธ๋‹ค(Speak)๋Š” ํŠน์„ฑ์„ ์ฝ”๋“œ(Animal.speak())๋กœ ์˜ฎ๊ธด ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ์ถ”์ƒ์„ ์ตœ์†Œํ™”ํ•˜์ง€ ์•Š์•˜๋‹ค. ๋‹ค์‹œ ๋งํ•ด, speak() ๋ถ€๋ถ„์˜ ์ฝ”๋“œ๊ฐ€ ๊ณผ๋„ํ•˜๊ฒŒ ๋งŽ๋‹ค. ๊ทธ๋ž˜์„œ Animal์ด๋ผ๋Š” ๋ถ€๋ชจ๋ฅผ ๋”ฐ๋ฅด๋Š” Cat, Dog ํด๋ž˜์Šค์˜ speak() ๋ฉ”์†Œ๋“œ ๊ตฌํ˜„์„ ์œ„ํ•ด์„ , '๊ธฐ์กด ์ฝ”๋“œ(์—ฌ๊ธฐ์„  Animal์˜ ์ฝ”๋“œ)๋ฅผ ๊ณ ์ณ์•ผ ํ•˜๋Š”' ์ƒํ™ฉ์ด ๋˜์–ด๋ฒ„๋ ธ๋‹ค.

 

OCP๋ฅผ ์ง€ํ‚จ ์˜ˆ์‹œ

// ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด OCP ์ค€์ˆ˜ํ•˜๊ฒŒ ๋งŒ๋“ฆ
open class Animal {
    open fun speak(): String = "..."
}

class Dog : Animal() {
    override fun speak() = "์™ˆ"
}

class Cat : Animal() {
    override fun speak() = "๋ƒฅ"
}

---

// ์ด๋ ‡๊ฒŒ Animal์„ interface๋กœ ๋‘๋Š” ๋ฐฉ์‹์˜ ์ˆ˜์ •๋„ ์ข‹๋‹ค
interface Animal {
    fun speak(): String
}

class Dog : Animal {
    override fun speak() = "์™ˆ"
}

class Cat : Animal {
    override fun speak() = "๋ƒฅ"
}

๋ฐ˜๋ฉด speak()์„ '์ตœ์†Œํ™”๋œ ์ถ”์ƒ ์ฝ”๋“œ'๋กœ ๋ฐ”๊พธ๋ฉด ์–ด๋–จ๊นŒ? ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ๋ฐ”๊พธ์ง€ ์•Š๊ณ ๋„ Cat, Dog ๋“ฑ์„ ์„ ์–ธ ๊ฐ€๋Šฅํ•  ๋งŒํผ speak()์„ ๊ฒฝ๋Ÿ‰ํ™”ํ–ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์œ„์˜ ์ฝ”๋“œ๋Š” OCP๋ฅผ ์ง€ํ‚จ ์ฝ”๋“œ๊ฐ€ ๋œ๋‹ค.

 

๊ธฐ๋Œ€ ํšจ๊ณผ
OCP ํŒจํ„ด์„ ์ค€์ˆ˜ํ•˜์—ฌ, ๊ธฐ์กด ์ฝ”๋“œ ์ˆ˜์ • ์—†์ด ์†์‰ฝ๊ฒŒ ๊ธฐ๋Šฅ ํ™•์žฅ์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

 

#4-4 ์ง„์งœ '์ถ”์ƒ'

๋ณธ์งˆ(What) ์ฐพ๊ธฐ

์ถ”์ƒ = ๊ตฌ์กฐ = ์ •์ฑ…
(์ถ”์ƒํ™” = ๊ตฌ์กฐํ™” = ์ •์ฑ…ํ™”)

#4-2์—์„  '์ถ”์ƒ'์„ ๋ฌ˜์‚ฌํ•  ๋•Œ ํ†ต์šฉ๋˜๋Š” ์„ค๋ช…์„ ๋‹ค๋ค˜์ง€๋งŒ, ์—ฌ๊ธฐ์—์„  '์ถ”์ƒ'์˜ ๋ณธ์งˆ์ ์ธ ์„ค๋ช…์„ ๋‹ค๋ฃฌ๋‹ค. ์‚ฌ์‹ค ์ถ”์ƒ์ด๋ž€, ๊ทธ๋ƒฅ '๊ตฌ์กฐ'์— ๋ถˆ๊ณผํ•˜๋‹ค. #4-2์—์„œ ์–ธ๊ธ‰ํ–ˆ๋˜ '๊ณตํ†ต'์ด๋ผ๋Š” ํ‚ค์›Œ๋“œ๋„ ์—ฌ๊ธฐ์—” ์—†๋‹ค. ๋‘ ๊ธ€์ž '๊ตฌ'์™€ '์กฐ'๊ฐ€ ์„ค๋ช…์˜ ์ „๋ถ€๋‹ค. ๋‚˜๋Š” ์ถ”์ƒ์ด ๊ทธ์ € '๊ตฌ์กฐ'์˜ ํ˜„ํ•™์  ํ‘œํ˜„์— ๋ถˆ๊ณผํ•˜๋‹ค๊ณ  ๊ฐํžˆ ์ฃผ์žฅํ•ด ๋ณธ๋‹ค. ์•„๋ž˜๋Š” ์‚ฌ๋žŒ์„ '์ถ”์ƒํ™”ํ•œ' ๊ทธ๋ฆผ 2๊ฐœ์— ๋Œ€ํ•œ ๋น„๊ต๋‹ค.

 

์–ด์งธ์„œ ์กธ๋ผ๋งจ์€ ํŒ”๊ณผ ๋‹ค๋ฆฌ๊ฐ€ ์žˆ๋Š”๋ฐ, ํ™”์žฅ์‹ค ํ‘œ์ง€ํŒ ์‚ฌ๋žŒ์—๊ฒ ์—†๋Š”๊ฐ€? ์ผ๋ฐ˜์ ์ธ ์‚ฌ๋žŒ์€ ๋ˆ„๊ตฌ๋‚˜ ๊ณตํ†ต์œผ๋กœ ๊ฐ€์ง€๋Š” ๊ฒŒ ์•„๋‹Œ๊ฐ€? ์ด ๋ฐ˜๋ก€๋ฅผ ํ†ตํ•ด ์ถ”์ƒ์ด๋ž€ (๋””์ž์ด๋„ˆ๊ฐ€ ์ž„์˜๋กœ ์ •ํ•œ) '๊ตฌ์กฐ'๋ฅผ ์–ด๋ ต๊ฒŒ ํ‘œํ˜„ํ•œ ๋‹จ์–ด์ผ ๋ฟ์ด์ง€, '๊ณตํ†ต'์„ ๋“ค๋จน์ด๋ฉฐ ์„ค๋ช…ํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ๊ฐœ๋…์ž„์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์™œ ๊ทธ๋Ÿฐ ์„ค๋ช…์ด ๋‚˜์˜ค๊ฒŒ ๋˜์—ˆ์„๊นŒ? ๊ทธ๊ฒƒ์€ ๋ฐ”๋กœ What๊ณผ How๋ฅผ ํ˜ผ๋™ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

์ถ”์ƒ์€ ๋ฌด์—‡(What, ๋ณธ์งˆ)์ธ๊ฐ€? → ๊ตฌ์กฐ
์ถ”์ƒ์„ ์–ด๋–ป๊ฒŒ(How, ๋ฐฉ๋ฒ•) ํ•ด์•ผ ์ž˜ ๋ฝ‘์•„๋‚ด๋Š”๊ฐ€? → ๊ณตํ†ต์ ์„ ์ฐพ์•„์„œ

์ด๋ ‡๋“ฏ, What์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด์•ผ ํ•˜๋Š”๋ฐ How์— ๋Œ€ํ•œ ์„ค๋ช…์„ ํ•ด๋ฒ„๋ฆฐ ๊ฒƒ์ด๋‹ค. ๋ฌผ๋ก  ์ผ๋ฐ˜์ ์œผ๋กœ ํ†ต์šฉ๋˜๋Š” ์„ค๋ช…์—์„œ, ์ถ”์ƒ์„ '๊ตฌ์กฐ'๋ผ๊ณ  ํ•  ์ˆ˜ ์—†๋Š” ๋…ธ๋ฆ‡์ธ ๊ฒƒ๋„ ์ธ์ •ํ•œ๋‹ค. ๋„ˆ๋ฌด ์งง์•„์„œ ๋ฌด์„ฑ์˜ํ•˜๊ฒŒ ๋ณด์ผ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐ˜๋ฌธํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

 

์กธ๋ผ๋งจ๊ณผ ํ™”์žฅ์‹ค ํ‘œ์ง€ํŒ ์‚ฌ๋žŒ ๋ชจ๋‘ '์‚ฌ๋žŒ'์ด๋ผ๋ฉด ๊ณตํ†ต์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” '๋จธ๋ฆฌ'๋ฅผ ๋™๊ทธ๋ผ๋ฏธ๋กœ ํ‘œํ˜„ํ–ˆ๋Š”๋ฐ, ๋ฐ˜๋ก€๋ž์‹œ๊ณ  ์ œ์‹œํ•œ ์˜ˆ์‹œ๋งˆ์ €๋„ ๊ฒฐ๊ตญ ๊ณตํ†ต์˜ ๊ฐœ๋…์ด ๋“ค์–ด๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹Œ๊ฐ€?

๊ทธ๋ ‡๋‹ค๋ฉด ์‚ฌ๋žŒ ๋จธ๋ฆฌ๋ฅผ ๋„ค๋ชจ๋กœ ํ‘œํ˜„ํ•˜๋Š” ์ถ”์ƒ์€ ์–ด๋–ค๊ฐ€? ์•„๋‹ˆ๋ฉด ์•„์˜ˆ ๋จธ๋ฆฌ๋ถ€ํ„ฐ ๋ฐœ๋๊นŒ์ง€๋ฅผ ํ†ต์งธ๋กœ ํ•˜๋‚˜์˜ ์ (.)์œผ๋กœ ํ‘œ์‹œํ•  ์ˆ˜๋„ ์žˆ๊ณ , ํŠน์ •ํ•œ ์ˆซ์ž๋กœ ํ‘œ์‹œํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์–ด๋–ค ํ˜•ํƒœ๋“  ๊ทธ๊ฑด ๋””์ž์ด๋„ˆ์˜ ๋งˆ์Œ์ด๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์ถ”์ƒ์„ '์ž˜' ํ•˜๊ธฐ ์œ„ํ•ด์„œ '๊ณตํ†ต'์ ์„ ์ž˜ ๋ฝ‘์•„๋‚ด์•ผ ํ•˜๋Š” ๊ฑด ๋งž์ง€๋งŒ, ์•ž์„œ ๋งํ–ˆ๋“ฏ ๊ทธ๊ฑด ์ถ”์ƒ์˜ How์ง€ What์ด ์•„๋‹ˆ๋‹ค.

 

์ข‹์€ ๋ฐฉ๋ฒ•(How)

์ง€๊ธˆ๊นŒ์ง€ ์ผ๋ฐ˜์ ์œผ๋กœ ํ†ต์šฉ๋˜๋Š” ์ถ”์ƒ์˜ ์ •์˜์—์„œ ๋ณธ์งˆ(What)๊ณผ ๋ฐฉ๋ฒ•(How)์„ ๋ถ„๋ฆฌํ–ˆ๋‹ค๋ฉด, ์ง€๊ธˆ๋ถ€ํ„ด ๋ถ„๋ฆฌ๋œ ๋ถ€๋ถ„ ์ค‘ How๋ฅผ ์ง‘์ค‘์ ์œผ๋กœ ๊ณต๋žตํ•ด๋ณธ๋‹ค. ๋‹ค์‹œ ๋งํ•ด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ์ถ”์ƒํ™”๋ฅผ ์ž˜ํ• ์ง€์— ๋Œ€ํ•œ ์„ค๋ช…์ด๋‹ค. ์ข‹์€ ์ถ”์ƒ์€ 2๊ฐ€์ง€ ์š”์†Œ์˜ ์ค„๋‹ค๋ฆฌ๊ธฐ์—์„œ ๋‚˜์˜ค๋Š”๋ฐ, ๊ทธ ์š”์†Œ๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

1. ์œ ์—ฐํ•จ (๊ณตํ†ต์ ์„ ์ข๊ฒŒ ์žก์Œ = "xxx ์ค‘ ์ผ๋ถ€๋งŒ์ด ๊ทธ๋ž˜")
2. ๊ฐ€๋…์„ฑ (๊ณตํ†ต์ ์„ ๋„“๊ฒŒ ์žก์Œ = "xxx๋Š” ๋‹ค ๋˜‘๊ฐ™์•„")

์ด ์š”์†Œ์™€ ํ•จ๊ป˜ #4-3์˜ ์˜ˆ์‹œ๋ฅผ ๋‹ค์‹œ ๋ณด์ž. Animal์€ ์†Œ๋ฆฌ๋ฅผ ๋‚ด๋Š” ๊ณตํ†ต์ ์ด ์žˆ๋‹ค๊ณ  ํ–ˆ์ง€๋งŒ, ์ •๋ง๋กœ ๊ทธ๋Ÿด๊นŒ?

 

class Shell : Animal() { // ์กฐ๊ฐœ
    override fun speak() = "???" // ๋…ผ๋ฆฌ์  ์—๋Ÿฌ
}

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

 

open class Animal

open class SpeakableAnimal : Animal() {
    open fun speak(): String = "..."
}

class Dog : SpeakableAnimal() {
    override fun speak() = "์™ˆ"
}

class Cat : SpeakableAnimal() {
    override fun speak() = "๋ƒฅ"
}

class Shell : Animal() // ์กฐ๊ฐœ

๋ชจ๋“  Animal์ด speak()์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•˜๋Š” ๋Œ€์‹ , ๋” ์ข์€ ๋ฒ”์œ„์ธ SpeakableAnimal๋งŒ์ด speak()์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค. ์ฆ‰, ๊ณตํ†ต์ ์˜ ๋ฒ”์œ„๋ฅผ ์ค„์˜€๋‹ค. ๊ณตํ†ต์ ์„ ์ค„์ด๋ฉด ์œ ์—ฐ์„ฑ์ด ์ƒ๊ธฐ์ง€๋งŒ, ๊ณตํ†ต์ ์„ ์ค„์ธ ๋งŒํผ ์ƒ๊ธด ์ฐจ์ด์ ์— ๊ด€ํ•ด ๊ธฐ์ˆ ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ์–‘์ด ๋Š˜์–ด๋‚˜์„œ ๊ฐ€๋…์„ฑ์€ ๋–จ์–ด์ง„๋‹ค.

 

๋ชจ๋“  ๋™๋ฌผ์€ ์šธ์Œ์†Œ๋ฆฌ๋ฅผ ๋‚ธ๋‹ค → ์ผ๋ถ€ ๋™๋ฌผ๋งŒ์ด ์šธ์Œ์†Œ๋ฆฌ๋ฅผ ๋‚ธ๋‹ค

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

 

#4-5 TMI

#4-4์—์„œ ๋งํ•œ ์กธ๋ผ๋งจ์„ ๋‹ค์‹œ ๋ณด์ž. ์™œ (ํ™”์žฅ์‹ค ํ‘œ์ง€ํŒ ์‚ฌ๋žŒ๊ณผ ๋‹ฌ๋ฆฌ) ์กธ๋ผ๋งจ์€ ์‚ฌ์ง€๊ฐ€ ๋ฉ€์ฉกํ• ๊นŒ? ์กธ๋ผ๋งจ์€ ์ฃผ๋กœ ๊ต๊ณผ์„œ ๊ตฌ์„ ๋‚™์„œ์— ๋‚˜์˜ค๋Š” ๋“ฑ์žฅ์ธ๋ฌผ์ด๊ณ , ๋””์ž์ด๋„ˆ๋Š” ์‹ญ์ค‘ํŒ”๊ตฌ ์ˆ˜์—… ์‹œ๊ฐ„์ด ์ง€๋ฃจํ•ด์„œ ๋‚™์„œ ์ค‘์ธ ์ดˆ๋“ฑํ•™์ƒ์ด๋‹ค. ๊ทธ๋Ÿฐ ์ดˆ๋“ฑํ•™์ƒ๋“ค์˜ 99%๋Š” ์กธ๋ผ๋งจ๋“ค๋ผ๋ฆฌ ์‹ธ์šฐ๋Š” ๋ชจ์Šต์„ ๊ทธ๋ฆด ํ…๋ฐ, ์‹ธ์›€ ๋ฌ˜์‚ฌ๋ฅผ ์œ„ํ•ด ํŒ”๊ณผ ๋‹ค๋ฆฌ์˜ ์กด์žฌ๋Š” ํ•„์ˆ˜์ ์ด๋‹ค. 

 

์กธ๋ผ๋งจ์—๊ฒŒ ๊ฐ•์ œ๋กœ ์œ ์—ฐํ•จ์„ ๋ถ€์—ฌํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ? ์กธ๋ผ๋งจ์˜ ๋ชธํ†ต์€ ์ผ์ง์„ ์ด๋‹ค. ์—ฌ๊ธฐ์„œ ์ผ์ง์„  ๋Œ€์‹  ํ™”์žฅ์‹ค ํ‘œ์ง€ํŒ ์‚ฌ๋žŒ์ฒ˜๋Ÿผ '๊ฑฐ๋Œ€ํ•œ ๋ชธํ†ต'์„ ๊ทธ๋ ค ๋„ฃ๊ฒŒ ๊ฐ•์ œํ•ด ๋ณด๋Š” ๊ฒƒ์ด๋‹ค. ์ดˆ๋“ฑํ•™์ƒ์˜ ๋ฐ˜์‘์€ ์•„๋งˆ ์ด๋Ÿด ํ…Œ๋‹ค: "๊ทธ๋ƒฅ ์กธ๋ผ๋งจ๋ผ๋ฆฌ ์‹ธ์šฐ๋Š” ๊ฒƒ๋งŒ ๊ทธ๋ฆฌ๊ณ  ์‹ถ์€๋ฐ, ๊ท€์ฐฎ๊ฒŒ ๋ชธํ†ต๋„ ๊ทธ๋ ค ๋„ฃ์–ด์•ผ ํ•ด? ์ฐจ๋ผ๋ฆฌ ์ˆ˜์—…์„ ๋“ฃ๊ณ  ๋ง์ง€!". ์กธ๋ผ๋งจ์€ ๋” ๊ฑด๋“ค์ผ ํ•„์š” ์—†๋Š” ์ตœ์†Œํ•œ์˜ ์ถ”์ƒ์ด๋‹ˆ๊นŒ.

 

ํ•œํŽธ, ํ™”์žฅ์‹ค ํ‘œ์ง€ํŒ ์‚ฌ๋žŒ์€ ์‹ธ์šธ ์ผ์ด ์—†๋‹ค. ๊ฐ„ํ˜น ํ™”์žฅ์‹ค ํ‘œ์ง€ํŒ์—์„œ ํŒ”๊ณผ ๋‹ค๋ฆฌ๋ฅผ ๋ฌ˜์‚ฌํ•˜๋Š” ๋•Œ๋„ ์žˆ์œผ๋‚˜, ๊ทธ๋Ÿฐ ์ƒํ™ฉ์—๋„ ํŒ”๊ณผ ๋‹ค๋ฆฌ๋Š” ์–ด์ฐจํ”ผ ์•„๋ฌด๋Ÿฐ ๋™์ž‘๋„ ์˜๋ฏธ๋„ ์—†๋‹ค. ๋˜ ํ™”์žฅ์‹ค ํ‘œ์ง€ํŒ ์‚ฌ๋žŒ๋“ค์€ ๋ชธํ†ต์ด ๋ฐ˜๋“œ์‹œ ์ผ์ž๊ฐ€ ์•„๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ผ์ง์„ ์ด๋ผ๋ฉด ๋‚จ์ž ํ™”์žฅ์‹ค์ธ์ง€ ์—ฌ์ž ํ™”์žฅ์‹ค์ธ์ง€์˜ ํ‘œ์‹œ๋ฅผ ์œ„ํ•œ ์ƒ‰์„ ์ฑ„์›Œ ๋„ฃ์„ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ํ™”์žฅ์‹ค ํ‘œ์ง€ํŒ ๋˜ํ•œ ์„ธ์›”์ด ํ๋ฅด๋ฉฐ ์ •ํ˜•ํ™”๋œ ์ตœ์†Œํ•œ์˜ ์ถ”์ƒ์ด๋‹ค.

 

#5 [L] ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™

Liskov Substitution Principle, LSP

 

#5-1 What

ํ•˜์œ„ ํƒ€์ž…์€ ์ƒ์œ„ ํƒ€์ž…์œผ๋กœ ๋Œ€์ฒดํ• (์น˜ํ™˜) ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ƒ์†๋ฐ›์€ ์ž์‹ ํด๋ž˜์Šค๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์ฒ˜๋Ÿผ ๋‹ค๋ค„๋„ ๋…ผ๋ฆฌ์ ์œผ๋กœ(='๊ธฐ๋Šฅ'์ ์œผ๋กœ) ๋˜‘๊ฐ™์ด ๋™์ž‘ํ•ด์•ผ ํ•œ๋‹ค. ๊ตฌํ˜„์ฒด(์ž์‹)๋ฅผ ๋ฐ”๊ฟ”๋„ ์ฝ”๋“œ์˜ ์˜๋ฏธ(๋ฉ”์†Œ๋“œ๋ณ„๋กœ ์ง€๋‹ˆ๋Š” ๋™์ž‘์˜ ์ถ”์ƒ์ ์ธ ๊ธฐ๋Œ€)๊ฐ€ ๊นจ์ง€์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค๋Š” ๋ง์ด๋‹ค.

 

#5-2 '์บ์ŠคํŒ…'์ด๋ž€

ํ•œ ํƒ€์ž…์„ ๋‹ค๋ฅธ ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ. ๊ฐ์ฒด์ง€ํ–ฅ์—์„œ๋Š” ์ฃผ๋กœ ์ƒ์† ๊ด€๊ณ„์—์„œ ์‚ฌ์šฉ๋จ. ์ฆ‰, ๋ถ€๋ชจ ํด๋ž˜์Šค ↔ ์ž์‹ ํด๋ž˜์Šค ๊ฐ„์˜ ํ˜• ๋ณ€ํ™˜์„ ์˜๋ฏธํ•œ๋‹ค.

 

์—…์บ์ŠคํŒ…

val dog = Dog()
// "as" ์—†์ด ์—…์บ์ŠคํŒ… (์•”์‹œ์ )
val animal: Animal = dog
animal.sound()

์ž์‹ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด(์ธ์Šคํ„ด์Šค)๋ฅผ ๋ถ€๋ชจ ํด๋ž˜์Šค ํƒ€์ž…์œผ๋กœ ํ˜• ๋ณ€ํ™˜ํ•˜๋Š” ํ–‰์œ„. ํ•ญ์ƒ ์•ˆ์ „ํ•˜๋ฉฐ ์ž๋™์œผ๋กœ(= ์•”์‹œ์ ์œผ๋กœ) ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋‹ค์šด์บ์ŠคํŒ…

val animal: Animal = Cat()
// ๋‹ค์šด์บ์ŠคํŒ… (๋ช…์‹œ์ ). "as"์—์„œ,
// ClassCastException ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ ์žˆ์Œ
val dog = animal as Dog   
dog.bark()

๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด(์ธ์Šคํ„ด์Šค)๋ฅผ ์ž์‹ ํด๋ž˜์Šค ํƒ€์ž…์œผ๋กœ ํ˜• ๋ณ€ํ™˜ํ•˜๋Š” ํ–‰์œ„. ์•ˆ์ „์ด ๋ณด์žฅ๋˜์ง€ ์•Š์œผ๋ฉฐ ๋ช…์‹œ์  ์บ์ŠคํŒ…์ด ํ•„์š”ํ•˜๋‹ค.

 

#5-3 ์˜๋ฌธ์ ?

์ž์‹์€ ๋ถ€๋ชจ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋“œํ•ด์„œ ๋งŒ๋“ค์–ด์ง€๋ฏ€๋กœ, ์—…์บ์ŠคํŒ…์ด ๋ฌด์กฐ๊ฑด ๊ฐ€๋Šฅ(์•ˆ์ „)ํ•˜๋‹ค. ์ฆ‰, ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™์€ ์•Œ์•„์„œ ์ง€์ผœ์ง€๋Š” ๊ฒŒ ์•„๋‹Œ๊ฐ€?

์•„๋‹ˆ๋‹ค. ํ•ต์‹ฌ์€ ์—…์บ์ŠคํŒ…์ด ์•„๋‹ˆ๋ผ '๊ธฐ๋Šฅ'์ด๋‹ค

 

open class Bird {
    open fun fly() { println("๋‚ ์•„์š”") }
}

class Ostrich : Bird() {
    // ์ž์‹์ด ๋ถ€๋ชจ์˜ '๊ธฐ๋Šฅ'(๋น„ํ–‰) ์ˆ˜ํ–‰ ๋ถˆ๊ฐ€
    override fun fly() { 
        throw UnsupportedOperationException(
            "ํƒ€์กฐ๋Š” ๋ชป ๋‚ ์•„์š”"
        )
    }
}

๋ถ€๋ชจ(Bird) ์ชฝ์—์„œ fly() ๋ฉ”์†Œ๋“œ๋ฅผ ์ •์˜ํ•จ์œผ๋กœ์จ ("์ƒˆ๋Š” ๋‚  ์ˆ˜ ์žˆ๋‹ค"๋ผ๋Š”) '๊ธฐ๋Šฅ'์„ ๋ณด์žฅํ–ˆ๋Š”๋ฐ, ์ž์‹(Ostrich)์ด ๊ทธ ๋ณด์žฅ์„ ๊นจ๋ฒ„๋ ธ๋‹ค. ์ฆ‰, Ostrich๋Š” LSP๋ฅผ ์œ„๋ฐ˜ํ–ˆ๋‹ค. ํ˜น์€ ์ด๋Ÿฐ ์ƒํ™ฉ์„ ๋งŒ๋“  ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ LSP๋ฅผ ์œ„๋ฐ˜ํ–ˆ๋‹ค.

 

#5-4 ์˜ˆ์‹œใ†๊ธฐ๋Œ€ ํšจ๊ณผ

LSP๋ฅผ ์ง€ํ‚จ ์˜ˆ์‹œ

์ž๋ฐ”์˜ LinkedList, ArrayList, HashSet ๋“ฑ์€ ๋ชจ๋‘ Collection ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ ์ž๋ฃŒํ˜•์„ Collection ํƒ€์ž…์œผ๋กœ์„œ ๋‹ค๋ฃจ๋”๋ผ๋„ (= ์—…์บ์ŠคํŒ…), Collection.add() ๋‚˜ Collection.contains() ๊ฐ™์€ ๋ฉ”์„œ๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ(= ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๊ธฐ๋Œ€ํ•˜๋Š” ๋…ผ๋ฆฌ์  '๊ธฐ๋Šฅ'์— ๋งž๊ฒŒ) ๋™์ž‘ํ•˜๋ฏ€๋กœ LSP๋ฅผ ์ง€ํ‚จ ์‚ฌ๋ก€๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

LSP๋ฅผ ์ง€ํ‚ค์ง€ ์•Š์€ ์˜ˆ์‹œ

๋ฐ˜๋ฉด ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๊ฐ€ ๋‚˜์ง€ ์•Š๋Š”๋Œ€๋„ add(), contains() ๋“ฑ์˜ ๋™์ž‘์ด ๋…ผ๋ฆฌ์ ์œผ๋กœ ์ด์ƒํ•˜๋‹ค๋ฉด, ๊ทธ๊ฒƒ์€ LSP๋ฅผ ์œ„๋ฐ˜ํ•œ ๊ฒƒ์ด๋‹ค.

 

๊ธฐ๋Œ€ ํšจ๊ณผ

LSP ํŒจํ„ด์„ ์ค€์ˆ˜ํ•˜์—ฌ, ๊ฐ์ฒด์˜ ๊ตฌ์ฒด์ ์ธ(= ๋‹คํ˜•์ ์ธ) ๊ตฌํ˜„์— ์˜์กดํ•˜์ง€ ์•Š๊ฒŒ ๋งŒ๋“ ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ์ฒด ๊ต์ฒด๋ฅผ ์ž์œ ๋กœ์ด ๋งŒ๋“ ๋‹ค. (๋‹คํ˜•์„ฑPolymorphism ↑).

 

#6 [I] ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™

Interface Segregation Principle, ISP

 

#6-1 What

ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•„์š” ์—†๋Š” ๊ธฐ๋Šฅ์— ์˜์กด(implement)ํ•˜์ง€ ์•Š๊ฒŒ, ์˜์กดํ•  ์ธํ„ฐํŽ˜์ด์Šคใ†ํด๋ž˜์Šค ๊ตฌ์กฐ๋ฅผ ์ž˜ ๋‚˜๋ˆ  ์„ค๊ณ„ํ•œ๋‹ค.

* ํด๋ผ์ด์–ธํŠธ(Client): ์ธํ„ฐํŽ˜์ด์Šค๋‚˜ ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ๊ธฐ๋Šฅ์„ ๋Œ์–ด๋‹ค ์“ฐ๋Š” ํด๋ž˜์Šค (์ •ํ™•ํ•œ ๋น„์œ ๋Š” ์•„๋‹ˆ์ง€๋งŒ, ํด๋ž˜์Šค ๊ณ„์˜ getter ๋А๋‚Œ)

๊ฐ์ฒด๋Š” ์˜ค์ง ์ž์‹ ์ด ํ•„์š”ํ•œ '์ถ”์ƒ'(#4-2, #4-4)์—๋งŒ ์˜์กดํ•ด์•ผ ํ•œ๋‹ค. ์ถ”์ƒํ™”๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ์ธํ„ฐํŽ˜์ด์Šค์ด๋ฏ€๋กœ, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž˜ ๋ถ„๋ฆฌํ•˜๋ฉด ISP๊ฐ€ ์ง€์ผœ์งˆ ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์„œ "์ž˜ ๋ถ„๋ฆฌํ•œ๋‹ค"๋ผ๋Š” ๊ฒƒ์˜ ์˜๋ฏธ๋Š” ๊ทธ์ € ์กฐ๊ทธ๋งฃ๊ฒŒ ๋‚˜๋ˆ„๋ฉด OK๋ผ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, '์ถ”์ƒ'(#4-2, #4-4)์— ๋งž๊ฒŒ ์ž˜ ๋‚˜๋ˆ„๋ผ๋Š” ์–˜๊ธฐ๋‹ค.

 

#6-2 ์šฉ์–ด ์ •๋ฆฌ

ํด๋ž˜์Šค: ๊ตฌ์ฒด์ ์ธ ๊ธฐ๋Šฅ ๊ตฌํ˜„
์ธํ„ฐํŽ˜์ด์Šค: ๊ตฌํ˜„ ์—†์ด ๊ธฐ๋Šฅใ†ํ˜•์‹๋งŒ์„ ์ •์˜
ํด๋ผ์ด์–ธํŠธ: ํด๋ž˜์Šค / ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ฃผ์ฒด์ธ ๊ฐ์ฒด

 

#6-3 ์˜ˆ์‹œใ†๊ธฐ๋Œ€ ํšจ๊ณผ

ISP๋ฅผ ์ง€ํ‚จ ์˜ˆ์‹œ

Kiosk๊ฐ€ LotteriaOrderSystem ๋ฐ LotteriaBurgerMenu ๋Œ€์‹  OrderSystem ๋ฐ BurgerMenu์— ์˜์กดํ•˜๋Š” ์ด์œ ๋Š” DIP ์›์น™์„ ์ง€ํ‚ค๊ธฐ ์œ„ํ•จ์ด๋‹ค. ๋งŒ์•ฝ Kiosk๊ฐ€ BurgerMenu๊ฐ€ ์•„๋‹Œ FastfoodMenu๋ฅผ ์ƒ์†๋ฐ›๋Š” ๊ตฌ์กฐ์˜€๋‹ค๋ฉด(= ์˜์กดํ•œ๋‹ค๋ฉด = implement ํ•œ๋‹ค๋ฉด) ํ”ผ์ž ๋ฉ”๋‰ด์— ๋Œ€ํ•ด์„œ "์ฃผ๋ฌธํ•  ์ˆ˜ ์—†๋Š” ๋ฉ”๋‰ด์ž…๋‹ˆ๋‹ค."๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ผ์ผ์ด ๊ท€์ฐฎ๊ฒŒ ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ–ˆ์„ ๊ฒƒ์ด๋‹ค.

 

๊ธฐ๋Œ€ ํšจ๊ณผ

ISP ํŒจํ„ด์„ ์ค€์ˆ˜ํ•˜์—ฌ, ์˜๋ฏธ ์—†๋Š” ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€ ์•Š๊ฒŒ ๋งŒ๋“œ๋Š” ๊ตฌ์กฐ๋ฅผ ํ˜•์„ฑํ•œ๋‹ค.

 

#6-4 ํฌํ•จ ๊ด€๊ณ„ ์ •๋ฆฌ

"ISP๋ฅผ ์ง€ํ‚ค๋ฉด SRP๊ฐ€ ๋”ฐ๋ผ์˜จ๋‹ค." → โ–ณ

ํ•ญ์ƒ ๊ทธ๋ ‡์ง„ ์•Š์ง€๋งŒ, ๋Œ€์ฒด๋กœ ๋งž๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ž‘์œผ๋ฉด, ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” ํด๋ž˜์Šค๊ฐ€ ๊ตฌํ˜„ํ•  ๊ธฐ๋Šฅ๋„ ์ž‘์„ ํ™•๋ฅ ์ด ๋†’๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋‹น์—ฐํžˆ '์ฑ…์ž„์ด ํ•œ ๊ฐ€์ง€์ผ ํ™•๋ฅ '๋„ ๋†’์•„์ง„๋‹ค. ์•„๋ž˜๋Š” 'ํ•ญ์ƒ ๊ทธ๋ ‡์ง€ ์•Š์€' ์ด์œ ๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ๋‹ค (๋ฐ˜๋ก€).

 

class FileManager : Readable, Writable {
    override fun read(): String {
        ...
    }
    override fun write(data: String) {
        ...
    }
}

'ํด๋ผ์ด์–ธํŠธ'๋กœ์„œ์˜ FileManager๋Š” ์ž์‹ ์ด ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฉ”์„œ๋“œ์— ์˜์กดํ•˜์ง€ ์•Š๋Š”๋‹ค (ISP ์ค€์ˆ˜). ํ•˜์ง€๋งŒ, 'ํด๋ž˜์Šค'๋กœ์„œ์˜ FileManager๋Š” (๊ด€์ ์— ๋”ฐ๋ผ 'ํŒŒ์ผ ๊ด€๋ฆฌ'๋ผ๋Š” ๋‹จ์ผ ์ฑ…์ž„์œผ๋กœ ๋ณผ ์ˆ˜๋„ ์žˆ๊ธด ํ•˜์ง€๋งŒ) 'ํŒŒ์ผ ์ฝ๊ธฐ'์™€ 'ํŒŒ์ผ ์“ฐ๊ธฐ'๋ผ๋Š” 2๊ฐ€์ง€ ์ฑ…์ž„์„ ๋ณด์œ ํ•œ๋‹ค. ์ด ๊ด€์ ์—์„œ๋Š” ํด๋ž˜์Šค์˜ ์ž ์žฌ์  ์—…๋ฐ์ดํŠธ ์ด์œ ๊ฐ€, "ํŒŒ์ผ ์ฝ๊ธฐ ๋กœ์ง์„ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ"์™€ "ํŒŒ์ผ ์“ฐ๊ธฐ ๋กœ์ง์„ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์žˆ์„ ๋•Œ"์˜ 2์ข…๋ฅ˜์ด๋ฏ€๋กœ SRP๋ฅผ ์œ„๋ฐ˜ํ•˜๊ฒŒ ๋œ๋‹ค.

 

"SRP๋ฅผ ์ง€ํ‚ค๋ฉด ISP๊ฐ€ ๋”ฐ๋ผ์˜จ๋‹ค." → โœ•

interface Board {
    fun write()
    fun read()
    fun update()
    fun delete()
}

์œ„์˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ง€๋‹Œ ๊ธฐ๋Šฅ์„, '๊ฒŒ์‹œ๊ธ€ ์ด์šฉ'์ด๋ผ๋Š” '๋‹จ์ผ ์ฑ…์ž„'์œผ๋กœ ๋ณด๊ธฐ๋กœ ๊ฐ€์ •(์•ฝ์†)ํ•˜๊ณ  ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ฝ์–ด๋ณด์ž.

 

class AdminUser : Board {
    override fun write() {
        println("๊ด€๋ฆฌ์ž๊ฐ€ ๊ธ€์„ ์”€.")
    }
    override fun read() {
        println("๊ด€๋ฆฌ์ž๊ฐ€ ๊ธ€์„ ์ฝ์Œ.")
    }
    override fun update() {
        println("๊ด€๋ฆฌ์ž๊ฐ€ ๊ธ€์„ ์ˆ˜์ •ํ•จ.")
    }
    override fun delete() {
        println("๊ด€๋ฆฌ์ž๊ฐ€ ๊ธ€์„ ์‚ญ์ œํ•จ.")
    }
}

class NormalUser : Board {
    override fun write() {
        println("์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๊ฐ€ ๊ธ€์„ ์”€.")
    }
    override fun read() {
        println("์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๊ฐ€ ๊ธ€์„ ์ฝ์Œ.")
    }
    override fun update() {
        println(
            "์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๊ฐ€ ๊ธ€์„ ์ˆ˜์ •ํ•จ."
        )
    }

    // ํ•„์š”์—†๋Š” ๊ตฌํ˜„์„ ๊ฐ•์š”๋‹นํ•จ (ISP ์œ„๋ฐ˜)
    override fun delete() {
        throw UnsupportedOperationException(
            "์ผ๋ฐ˜ ์‚ฌ์šฉ์ž๋Š” ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ ๋ถˆ๊ฐ€."
        )
    }
}

NormalUser.delete()๋Š” ๋ช…์ œ์— ๋Œ€ํ•œ ๋ฐ˜๋ก€๋‹ค.

 

#7 [D] ์˜์กด ์—ญ์ „ ์›์น™

Dependency Inversion Principle, DIP

 

#7-1 ๋ถ€์ •ํ™•ํ•œ ์„ค๋ช…

์–ด๋–ค ํด๋ž˜์Šค์— ์˜์กด(์ฐธ์กฐ)ํ•˜๋Š” ๋Œ€์‹ , ๊ทธ ํด๋ž˜์Šค์˜ ๊ฐ€๋Šฅํ•œ ๋†’์€ ๋ถ€๋ชจ(ํด๋ž˜์Šค, ์ธํ„ฐํŽ˜์ด์Šค)์— ์˜์กด(์ฐธ์กฐ)ํ•œ๋‹ค.

๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„  ์ž์‹ ์ชฝ์œผ๋กœ ๊ฐˆ์ˆ˜๋ก '๊ตฌํ˜„'์ด ๊ฐ•ํ•ด์ง€๊ณ , ๋ถ€๋ชจ ์ชฝ์œผ๋กœ ๊ฐˆ์ˆ˜๋ก '์ถ”์ƒํ™”'๊ฐ€ ๊ฐ•ํ•ด์ง€๋Š” ๊ตฌ์กฐ๊ฐ€ ์ž์—ฐํžˆ ํ˜•์„ฑ๋œ๋‹ค. ์ด๋•Œ ๋˜๋„๋ก ๋‚ด๊ฐ€ ๋‹ค๋ฃจ๋Š” ๊ฐ์ฒด๊ฐ€ ์ž์‹ ์ชฝ๋ณด๋‹ค๋Š” ๋ถ€๋ชจ ์ชฝ์— ์˜์กดํ•˜๊ฒŒ ๋งŒ๋“ค์–ด๋ผ. ๋‹ค์‹œ ๋งํ•ด, ๊ตฌํ˜„๋ณด๋‹จ ์ถ”์ƒํ™”์— ์˜์กดํ•˜๊ฒŒ ๋งŒ๋“ค์–ด๋ผ. ๋น„์œ ํ•˜์ž๋ฉด, '์˜์กด์˜ ์—…์บ์ŠคํŒ…(#5-2)'์„ ํ•˜๋ผ๋Š” ๋ง์ด๋‹ค. ์˜์กด ๊ด€๊ณ„๋ฅผ ๋งบ์„ ๋•Œ ๋ณ€ํ™”ํ•˜๊ธฐ ์‰ฌ์šด ๊ฒƒ ๋˜๋Š” ์ž์ฃผ ๋ณ€ํ™”ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š”, ๋ณ€ํ™”ํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒƒ ๊ฑฐ์˜ ๋ณ€ํ™”๊ฐ€ ์—†๋Š” ๊ฒƒ์— ์˜์กดํ•˜๋ผ๋Š” ๊ฒƒ์ด๊ธฐ๋„ ํ•˜๋‹ค.

 

์œ„์˜ ์„ค๋ช…์€ ์ดํ•ด ๋‚œ์ด๋„ ์ธก๋ฉด์—์„œ, ๊ทธ๋ฆฌ๊ณ  'DIP๊ฐ€ ๋Œ€์ถฉ ์–ด๋–ค ๋А๋‚Œ์ธ์ง€' ํŒŒ์•…ํ•˜๊ธฐ์—๋Š” ์ข‹๋‹ค. ํ•˜์ง€๋งŒ (๋‚ด๊ฐ€ ์“ด ๊ฑฐ์ง€๋งŒ) DIP๋ฅผ ๋ถ€์ •ํ™•ํ•˜๊ฒŒ ์™œ๊ณกํ•œ ์„ค๋ช…์ด๋‹ค. #7-3์—์„œ ์ด์–ด์„œ ์„ค๋ช…ํ•œ๋‹ค.

 

#7-2 '์—ญ์ „'์˜ ์˜๋ฏธ

์˜›๋‚  ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ •์„: ๊ณ ์ˆ˜์ค€ ๋กœ์ง์ด ์ €์ˆ˜์ค€ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ํ˜ธ์ถœ(์˜์กด)ํ•˜๋Š” ๊ฒŒ ์ž์—ฐ(์ง๊ด€)์Šค๋Ÿฝ๋‹ค

๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋„์ž… ํ›„ ์ •์„: ์ €์ˆ˜์ค€ ๊ตฌํ˜„์ด ๊ณ ์ˆ˜์ค€์˜ ์ถ”์ƒ ์ •์ฑ…์„ ๋”ฐ๋ฅด๋Š”(์˜์กดํ•˜๋Š”) ๊ฒŒ (์œ ์ง€๋ณด์ˆ˜ ์ƒ) ํŽธํ•˜๋‹ค

[์ƒ์œ„ ๋ชจ๋“ˆ → ํ•˜์œ„ ๋ชจ๋“ˆ]์—์„œ [ํ•˜์œ„ ๋ชจ๋“ˆ → ์ƒ์œ„ ๋ชจ๋“ˆ]๋กœ ์˜์กด ๋ฐฉํ–ฅ์˜ ์ •์„(ํŒจ๋Ÿฌ๋‹ค์ž„)์ด ์—ญ์ „๋๋‹ค๋Š” ์˜๋ฏธ๋‹ค. ์ด์–ด์ง€๋Š” #7-3์—์„œ '์—ญ์ „'์˜ ๋” ์ง๊ด€์ ์ธ ์˜๋ฏธ๋ฅผ '๋ณด์—ฌ'์ฃผ๊ฒ ๋‹ค.

 

#7-3 What (์ •ํ™•ํ•œ ์„ค๋ช…)

#7-1์˜ ์„ค๋ช…์ด ๋ถ€์ •ํ™•ํ•œ ์ด์œ ๋ฅผ ๋‚˜์—ดํ•ด ๋ณด๊ฒ ๋‹ค.

 

"๋ถ€๋ชจ์— ์˜์กดํ•˜๋ผ." → โœ•

ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ '๋ถ€๋ชจ'๋Š” ์›๋ž˜ '์ƒ์† ๊ด€๊ณ„'์—์„œ์˜ ์ƒ์œ„ ํด๋ž˜์Šค๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์•„๋ž˜๋Š” DIP์˜ ์›๋ฌธ์ด๋‹ค.

A. High-level modules should not import anything from low-level modules. Both should depend on abstractions (e.g., interfaces).
B. Abstractions should not depend on details. Details (concrete implementations) should depend on abstractions.

DIP์˜ ์›๋ฌธ์—์„  ์ถ”์ƒ(= ๊ตฌ์กฐ = ์ •์ฑ… = ์ธํ„ฐํŽ˜์ด์Šค)์— ์˜์กดํ•˜๋ผ๊ณ  ํ–ˆ๋‹ค. ์ด๋ฅผ '๋ถ€๋ชจ'๋ผ๊ณ  ๋ถˆ๋Ÿฌ์„  ์•ˆ ๋œ๋‹ค. ๋ฌผ๋ก  ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„  (์ƒ์† ๊ด€๊ณ„์—์„œ) ์ž์‹ ์ชฝ์œผ๋กœ ๊ฐˆ์ˆ˜๋ก '๊ตฌํ˜„'์ด ๊ฐ•ํ•ด์ง€๊ณ , ๋ถ€๋ชจ ์ชฝ์œผ๋กœ ๊ฐˆ์ˆ˜๋ก '์ถ”์ƒํ™”'๊ฐ€ ๊ฐ•ํ•ด์ง€๋Š” ๊ตฌ์กฐ๊ฐ€ ์ž์—ฐํžˆ ํ˜•์„ฑ๋œ๋‹ค. ๋•Œ๋ฌธ์— ๊ทธ๋ ‡๊ฒŒ ๋ถ€๋ฅผ๋งŒํ•œ ๊ฒฝํ–ฅ์„ฑ ์ž์ฒด๋Š” ์กด์žฌํ•œ๋‹ค. ๊ทธ๋ ‡๋‹ค, ๊ทธ์ € '๊ฒฝํ–ฅ์„ฑ'์— ๋ถˆ๊ณผํ•œ ๊ฒƒ์ด๋‹ค.

 

"๋ถ€๋ชจ(์ธํ„ฐํŽ˜์ด์Šค)" → โœ•

์–ด๋–ค ์ธํ„ฐํŽ˜์ด์Šค A๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค B๊ฐ€ ์žˆ์„ ๋•Œ, A๋ฅผ B์˜ '๋ถ€๋ชจ'๋ผ๊ฑฐ๋‚˜ ๋ฐ˜๋Œ€๋กœ B๋ฅผ A์˜ '์ž์‹'์ด๋ผ๊ณ  ๋ถ€๋ฅผ ์ˆ˜๋Š” ์—†๋‹ค. ์•„๋ž˜์˜ ์šฉ์–ด ์ •๋ฆฌ๋ฅผ ๋ณด์ž.

์„œ๋ธŒํƒ€์ดํ•‘(subtyping): B๊ฐ€ A๋ฅผ ๊ตฌํ˜„ํ•˜๊ฑฐ๋‚˜ ํ™•์žฅํ•˜์—ฌ, "A๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š” ์œ„์น˜(where A is expected)"์— B๋ฅผ ๋‘ฌ๋„ ์•ˆ์ „ํ•˜๊ฒŒ ๋Œ€์ฒด(substitute)๋˜๋Š” ๊ด€๊ณ„๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ (B๋ฅผ A์˜ subtype์œผ๋กœ ๋งŒ๋“œ๋Š” ํ–‰์œ„).

์ƒ์†(inheritance): ๊ตฌํ˜„(implementation)์„ ๋ฌผ๋ ค๋ฐ›์œผ๋ฉฐ ์„œ๋ธŒํƒ€์ดํ•‘ํ•˜๋Š” ๊ฒƒ.

์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„(implementation of interface): ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์„œ๋ธŒํƒ€์ดํ•‘ํ•˜๋Š” ๊ฒƒ. ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ฐ€์ง„ ๊ตฌํ˜„(implementation)์ด ์—†์–ด, ์„œ๋ธŒํƒ€์ดํ•‘ ์‹œ ๊ตฌํ˜„์„ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์•ผ๋งŒ ํ•˜๋ฏ€๋กœ ์ƒ์†์ด ์•„๋‹˜.

* ๊ทธ๋ ‡๋‹ค๋ฉด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์„œ๋ธŒํƒ€์ดํ•‘ํ•ด ์ƒˆ๋กœ์šด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฑด ๋ญ๋ผ๊ณ  ๋ถ€๋ฅผ๊นŒ? ๋ฐ”๋กœ, '์ธํ„ฐํŽ˜์ด์Šค ํ™•์žฅ(interface extension)'์ด๋ผ ๋ถ€๋ฅธ๋‹ค. ํ•˜์ง€๋งŒ ์œ„ํ‚ค๋ฐฑ๊ณผ์— ๋”ฐ๋ฅด๋ฉด ์ผ๋ถ€์—์„  '์ธํ„ฐํŽ˜์ด์Šค ์ƒ์†(interface inheritance)'์ด๋ผ๋Š” ํ‘œํ˜„๋„ ์“ด๋‹ค๊ณ  ํ•œ๋‹ค. ํ›„์ž์˜ ๊ฒฝ์šฐ์—ฌ๋„, inheritance๋ผ๋Š” ๋‹จ์–ด ์•ž์— interface๋ผ๋Š” ๋‹จ์–ด๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ํฌ๊ฒŒ ํ—ท๊ฐˆ๋ฆด ์—ผ๋ ค๋Š” ์—†์„ ๊ฒƒ์ด๋‹ค. 

๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„๋Š” ์ƒ์† ๊ด€๊ณ„๋ฅผ ์˜๋ฏธํ•˜๋Š”๋ฐ, ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ƒ์† ๊ด€๊ณ„๊ฐ€ ์•„๋‹ˆ๋ผ์„œ '๋ถ€๋ชจ'๊ฐ€ ๋  ์ˆ˜ ์—†๋‹ค.

 

"๊ฐ€๋Šฅํ•œ ๋†’์€ ๋ถ€๋ชจ์ •์ฑ…์— ์˜์กดํ•˜๋ผ." → โœ•

'๋ถ€๋ชจ'๋ผ๋Š” ๋ง์€ ์•ž์„œ ํ‹€๋ฆฐ ์ด์œ ๋ฅผ ์„ค๋ช…ํ–ˆ์œผ๋‹ˆ, "๊ฐ€๋Šฅํ•œ ๋†’์€ ๋ถ€๋ชจ์— ์˜์กดํ•˜๋ผ"๋ผ๋Š” ํ‘œํ˜„์„ "๊ฐ€๋Šฅํ•œ ๋†’์€ ์ •์ฑ…์— ์˜์กดํ•˜๋ผ"๋กœ ๊ณ ์ณค๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๋ ‡๊ฒŒ ๊ณ ์ณ๋„ ํ‹€๋ฆฐ ํ‘œํ˜„์ด๋‹ค. ์™œ๋ƒํ•˜๋ฉด '๋†’์€'์ด๋ผ๋Š” ๋‹จ์–ด๋Š” ์ƒ์† ๊ด€๊ณ„์—์„œ๋‚˜ ์“ฐ๋Š”๊ฑฐ๋‹ˆ๊นŒ. ๋”ฐ๋ผ์„œ ์ด๋ ‡๊ฒŒ ๋งํ•ด์•ผ ํ•œ๋‹ค: "๊ฐ€๋Šฅํ•œ ์ •์ฑ…์— ์˜์กดํ•˜๋ผ".

 

'์ƒ์œ„ ๋ชจ๋“ˆ ๋ฐ ํ•˜์œ„ ๋ชจ๋“ˆ'์— ๋Œ€ํ•œ ์–ธ๊ธ‰ ์—†์Œ → โœ•

์›๋ฌธ์—๋Š” ์ƒ์œ„ ๋ชจ๋“ˆ์ด๋‚˜ ํ•˜์œ„ ๋ชจ๋“ˆ์— ๋Œ€ํ•ด "Both should depend on abstractions"๋ผ๊ณ  ๋˜์–ด ์žˆ๋‹ค. ๋‘˜ ๋‹ค ์ •์ฑ…์— ์˜์กดํ•˜๋ผ๋Š” ์–˜๊ธฐ๋‹ค. ์—ฌ๊ธฐ์„œ ์ฃผ์˜ํ•  ์ ์€, ๋ฌด์˜์‹์ ์œผ๋กœ ์ƒ์œ„ ๋ชจ๋“ˆํ•˜๊ณ  ํ•˜์œ„ ๋ชจ๋“ˆ์ด ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„๋ผ๊ณ  ์ฐฉ๊ฐํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋ฌผ๋ก  DIP ์ด์ „ ์ฆ‰, #7-2์— ์žˆ๋Š” '์˜›๋‚  ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ •์„'๋Œ€๋กœ๋ผ๋ฉด ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„์ธ ๊ฒƒ์ด ์ž์—ฐ์Šค๋Ÿฝ๋‹ค. '์˜›๋‚  ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ •์„'๋Œ€๋กœ์˜€๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ ๊ทธ๋ ‡๊ฒŒ ์ฐฉ๊ฐํ•ด์„  ์•ˆ ๋œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์˜›๋‚  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ด€์ ์—์„œ, '์ƒ์œ„' ๋ชจ๋“ˆํ•˜๊ณ  'ํ•˜์œ„' ๋ชจ๋“ˆ์€ '์˜์กด์„ฑ' ์ธก๋ฉด์—์„œ ๊ตฌ๋ถ„ํ•ด ๋‘” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ž์‹ ํด๋ž˜์Šค๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์— ์ž๋™์œผ๋กœ ์˜์กดํ•˜๊ฒŒ ๋˜๋Š” ๊ฑด ๋งž์ง€๋งŒ, ๋ฐ˜๋Œ€๋กœ ์˜์กด์„ฑ์ด ์žˆ๋‹ค๊ณ  ๋ฐ˜๋“œ์‹œ ๋ถ€๋ชจ-์ž์‹ ๊ด€๊ณ„์ธ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๊ฒฐ๋ก ์€, ์˜›๋‚  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์ด์—ˆ๋‹ค๋ฉด ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„์ƒ์—์„œ ์ด์–ด์ ธ ์žˆ์—ˆ์„ ๋‘ ๋ชจ๋“ˆ์˜ ์˜์กด์„ฑ์„ ์ œ๊ฑฐํ•˜๊ณ , ๋‘ ๋ชจ๋“ˆ '๊ฐ๊ฐ' ์ •์ฑ…์— ์˜์กด์‹œํ‚ค๋ผ๋Š” ๊ฒƒ์ด๋‹ค. ์ด๋ฅผ ์˜์กด์„ฑ ๊ทธ๋ž˜ํ”„๋กœ ํ‘œํ˜„ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

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

 

๊ทธ๋ ‡๋‹ค๋ฉด ์ตœ์ข…์œผ๋กœ, ์ •ํ™•ํ•œ ์„ค๋ช…์€?

์ƒ์œ„ ๋ชจ๋“ˆ์€ ํ•˜์œ„ ๋ชจ๋“ˆ(= "์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•˜๋Š”๊ฐ€?")์— ์ง์ ‘ ์˜์กดํ•˜๋Š” ๋Œ€์‹ , ํ•˜์œ„ ๋ชจ๋“ˆ์ด ์˜์กดํ•˜๋Š” ์ถ”์ƒ(์ธํ„ฐํŽ˜์ด์Šค, ์ •์ฑ…)(= "๋ฌด์—‡์„ ํ•ด์•ผ ํ•˜๋Š”๊ฐ€")์— ์˜์กดํ•œ๋‹ค.

 

#7-4 ์˜ˆ์‹œใ†๊ธฐ๋Œ€ ํšจ๊ณผ

DIP๋ฅผ ์ง€ํ‚จ ์˜ˆ์‹œ

๋กฏ๋ฐ๋ฆฌ์•„๊ฐ€ ๋งฅ๋„๋‚ ๋“œ๋ฅผ ์ธ์ˆ˜ํ•œ ์„ธ๊ณ„๊ฐ€ ์กด์žฌํ•œ๋‹ค๊ณ  ํ•ด๋ณด์ž. ๊ทธ๋ฆฌ๊ณ  ์ด ์„ธ๊ณ„์—์„œ ๋กฏ๋ฐ๋ฆฌ์•„ ์ธก์€ ๋กฏ๋ฐ๋ฆฌ์•„ ๋งค์žฅ์—์„œ๋„ ๋งฅ๋„๋‚ ๋“œ์˜ ํ–„๋ฒ„๊ฑฐ๋ฅผ ์ œ๊ณตํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ „๊ตญ ๋กฏ๋ฐ๋ฆฌ์•„ ๋งค์žฅ์— ์žˆ๋Š” ํ‚ค์˜ค์Šคํฌ ์ผ๋ถ€๋ฅผ ๋งฅ๋„๋‚ ๋“œ ๋ฉ”๋‰ด ์ „์šฉ ํ‚ค์˜ค์Šคํฌ๋กœ ๋ฐ”๊พธ๊ธฐ๋กœ ํ•œ๋‹ค.

ํ•˜์ง€๋งŒ ํ‚ค์˜ค์Šคํฌ ๋‹ด๋‹น ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ์›ƒ๊ณ  ์žˆ๋‹ค(?). ์™œ๋ƒํ•˜๋ฉด Kiosk ํด๋ž˜์Šค๊ฐ€ LotteriaBurgerMenu๊ฐ€ ์•„๋‹Œ, (DIP๋ฅผ ์ค€์ˆ˜ํ•˜์—ฌ) BurgerMenu์— ์˜์กดํ•˜๋„๋ก ๋‘์—ˆ๊ธฐ ๋•Œ๋ฌธ์— (๋น„๊ต์ ) ์ˆ˜์›”ํ•˜๊ฒŒ ๋งฅ๋„๋‚ ๋“œ ๋ฉ”๋‰ด์šฉ ํ‚ค์˜ค์Šคํฌ๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

๊ธฐ๋Œ€ ํšจ๊ณผ
DIP ํŒจํ„ด์„ ์ค€์ˆ˜ํ•˜์—ฌ, ํด๋ž˜์Šค ๊ฐ„ ๊ฒฐํ•ฉ๋„(Coupling)๋ฅผ ๋‚ฎ์ถœ ์ˆ˜ ์žˆ๋‹ค.

 

#7-5 ํฌํ•จ ๊ด€๊ณ„ ์ •๋ฆฌ

"DIP๋ฅผ ์ง€ํ‚ค๋ฉด LSP๊ฐ€ ๋”ฐ๋ผ์˜จ๋‹ค." ๋˜๋Š” "LSP๋ฅผ ์ง€ํ‚ค๋ฉด DIP๊ฐ€ ๋”ฐ๋ผ์˜จ๋‹ค." → โœ•

๋‘˜ ๋‹ค ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๋Š” ๊ฑด ๋งž์ง€๋งŒ, ์–ด๋А ์ชฝ์ด ์–ด๋А ์ชฝ์„ ํฌํ•จํ•˜๋Š” ๊ด€๊ณ„๋Š” ์•„๋‹ˆ๋‹ค. DIP๋Š” ์ถ”์ƒ ์ค‘์‹ฌ์˜ ์„ค๊ณ„ ๊ตฌ์กฐ ํ™•๋ฆฝ์„ ์œ„ํ•จ์ด๊ณ , LSP๋Š” ์ƒ์† ๊ด€๊ณ„์˜ ํด๋ž˜์Šค๋“ค์˜ ์ถ”์ƒ '๊ธฐ๋Šฅ'์ด ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•จ์ด๋‹ค.

 

TMI: "LSP๋ฅผ ์ง€ํ‚ค๋ฉด DIP๋ฅผ ์ง€ํ‚ค๊ธฐ ์‰ฝ๋‹ค." → โ—‹

'๊ตฌํ˜„'(์ž์‹ ์ชฝ) ๋Œ€์‹  ''์ถ”์ƒ'(๋ถ€๋ชจ ์ชฝ)์— ์˜์กดํ•˜๊ธฐ ์œ„ํ•ด์„  (= DIP ์ค€์ˆ˜), ์ž์‹์„ ์‹ค์ œ๋กœ ๋ถ€๋ชจ๋กœ ๋Œ€์ฒด ๊ฐ€๋Šฅ(= LSP ์ค€์ˆ˜)ํ•ด์•ผ๋งŒ ์˜๋ฏธ๊ฐ€ ์žˆ๊ฒŒ ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.