๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Programming Language ๐Ÿ’ป/Java โ˜•

[Java] ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(OOP) - 4. SOLID๋ž€? ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„์˜ ๋‹ค์„ฏ ๊ฐ€์ง€ ํ•ต์‹ฌ ์›์น™

by lxvxxu 2025. 10. 18.

 

 


SOLID ์›์น™

  • SRP (๋‹จ์ผ ์ฑ…์ž„ ์›์น™)
  • OCP (๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™)
  • LSP (๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™)
  • DIP (์˜์กด ์—ญ์ „ ์›์น™)
  • ISP (์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™)

๐Ÿ“˜ SOLID — ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„์˜ ๋‹ค์„ฏ ๊ฐ€์ง€ ํ•ต์‹ฌ ์›์น™

ํ•™์Šต๋ชฉํ‘œ

  • ์†Œํ”„ํŠธ์›จ์–ด ์„ค๊ณ„์˜ ๊ธฐ๋ณธ ์›๋ฆฌ์ธ SOLID ์›์น™์„ ์ดํ•ดํ•œ๋‹ค.
  • ๊ฐ ์›์น™์˜ ์ •์˜์™€ ์ ์šฉ ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•˜์—ฌ ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ํ™•์žฅ์„ฑ์ด ๋†’์€ ํ”„๋กœ๊ทธ๋žจ์„ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์‹ค์ œ ์˜ˆ์‹œ๋ฅผ ํ†ตํ•ด ์ž˜๋ชป๋œ ์„ค๊ณ„์™€ ๊ฐœ์„ ๋œ ์„ค๊ณ„์˜ ์ฐจ์ด๋ฅผ ์ดํ•ดํ•œ๋‹ค.

1. SRP (Single Responsibility Principle) — ๋‹จ์ผ ์ฑ…์ž„ ์›์น™

“ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋Š” ์˜ค์ง ํ•˜๋‚˜์˜ ์ด์œ ๋กœ๋งŒ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•œ๋‹ค.”

์ •์˜

  • ํด๋ž˜์Šค๋Š” ํ•˜๋‚˜์˜ ์ฑ…์ž„(๋ณ€๊ฒฝ ์ด์œ )๋งŒ์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.
  • ์„œ๋กœ ๋‹ค๋ฅธ ๋ชฉ์ ์˜ ๊ธฐ๋Šฅ์„ ํ•œ ํด๋ž˜์Šค์— ๋‹ด์œผ๋ฉด, ํ•˜๋‚˜์˜ ๋ณ€๊ฒฝ์ด ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์— ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

ํ•ต์‹ฌ ๊ฐœ๋…

  • ์ฑ…์ž„(Responsibility)์€ ๊ณง ๋ณ€๊ฒฝ ์ด์œ (Reason for Change)์ด๋‹ค.
  • ์—ฌ๋Ÿฌ ์ฑ…์ž„์„ ๊ฐ€์ง„ ํด๋ž˜์Šค๋Š” ์—ฌ๋Ÿฌ ๋ณ€๊ฒฝ ์›์ธ์— ๋…ธ์ถœ๋˜์–ด ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ์–ด๋ ต๋‹ค.
  • ์ฆ‰, ํ•œ ํด๋ž˜์Šค๊ฐ€ ๋‹ด๋‹นํ•ด์•ผ ํ•  ์—ญํ• ์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

์˜ˆ์‹œ

 
// โŒ ์ž˜๋ชป๋œ ์˜ˆ์‹œ: Student ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ ์—ญํ• ์„ ์ˆ˜ํ–‰
class Student {
    void saveToDatabase() {}
    void printReportCard() {}
    void findAdvisor() {}
}

// โœ… ๊ฐœ์„ ๋œ ์˜ˆ์‹œ: ์ฑ…์ž„ ๋ถ„๋ฆฌ
class StudentRepository { void save(Student s) {} }
class ReportPrinter { void print(Student s) {} }
class AdvisorFinder { void find(Student s) {} }
// โŒ ์ž˜๋ชป๋œ ์˜ˆ์‹œ: Student ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ ์—ญํ• ์„ ์ˆ˜ํ–‰
class Student {
    void saveToDatabase() {}
    void printReportCard() {}
    void findAdvisor() {}
}

// โœ… ๊ฐœ์„ ๋œ ์˜ˆ์‹œ: ์ฑ…์ž„ ๋ถ„๋ฆฌ
class StudentRepository { void save(Student s) {} }
class ReportPrinter { void print(Student s) {} }
class AdvisorFinder { void find(Student s) {} }

์ฃผ์š” ๋ฌธ์ œ์ 

  • ์—ฌ๋Ÿฌ ์ฑ…์ž„์„ ๊ฐ€์ง„ ํด๋ž˜์Šค๋Š” “์‚ฐํƒ„์ด ์ˆ˜์ˆ (Shotgun Surgery)” ํ˜„์ƒ์„ ์œ ๋ฐœํ•œ๋‹ค.
    → ํ•˜๋‚˜์˜ ๋ณ€๊ฒฝ์ด ์—ฌ๋Ÿฌ ํด๋ž˜์Šค ๋˜๋Š” ์—ฌ๋Ÿฌ ๋ฉ”์„œ๋“œ์— ๋™์‹œ์— ์˜ํ–ฅ์„ ๋ฏธ์นจ.

2. OCP (Open-Closed Principle) — ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™

“์†Œํ”„ํŠธ์›จ์–ด ์—”ํ‹ฐํ‹ฐ๋Š” ํ™•์žฅ์—๋Š” ์—ด๋ ค ์žˆ๊ณ , ์ˆ˜์ •์—๋Š” ๋‹ซํ˜€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.”

์ •์˜

  • ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜์ง€ ์•Š๊ณ  ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•ด์•ผ ํ•œ๋‹ค.
  • ์ฆ‰, ํ™•์žฅ์€ ์—ด๋ ค(Open) ์žˆ์œผ๋‚˜, ์ˆ˜์ •์€ ๋‹ซํ˜€(Closed) ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ ์šฉ ๋ฐฉ๋ฒ•

  • ์ธํ„ฐํŽ˜์ด์Šค๋‚˜ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๋ถ€๋ถ„(๋‹ซํžŒ ๋ถ€๋ถ„)๊ณผ ๋ณ€๊ฒฝ๋  ๋ถ€๋ถ„(์—ด๋ฆฐ ๋ถ€๋ถ„)์„ ๋ถ„๋ฆฌํ•œ๋‹ค.

์˜ˆ์‹œ

interface MusicPlayer {
    void play();
}

class MP3Player implements MusicPlayer {
    public void play() { System.out.println("Playing MP3"); }
}

class TimeTrigger {
    private MusicPlayer player;
    public TimeTrigger(MusicPlayer player) { this.player = player; }

    public void trigger() {
        player.play(); // ๋ณ€๊ฒฝ ์—†์ด ํ™•์žฅ ๊ฐ€๋Šฅ
    }
}

์œ„ ์„ค๊ณ„์—์„œ๋Š” ์ƒˆ๋กœ์šด ์žฌ์ƒ ์žฅ์น˜๊ฐ€ ์ถ”๊ฐ€๋˜์–ด๋„ MusicPlayer ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ๊ตฌํ˜„ํ•˜๋ฉด ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.


3. LSP (Liskov Substitution Principle) — ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™

“ํ•˜์œ„ ํด๋ž˜์Šค๋Š” ์ƒ์œ„ ํด๋ž˜์Šค๋ฅผ ์™„๋ฒฝํžˆ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.”

์ •์˜

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

์˜ˆ์‹œ

 
class Rectangle {
    int width, height;
    void setWidth(int w) { width = w; }
    void setHeight(int h) { height = h; }
    int getArea() { return width * height; }
}

class Square extends Rectangle {
    void setWidth(int w) {
        width = w;
        height = w; // ์ •์‚ฌ๊ฐํ˜•์˜ ํŠน์„ฑ ์œ ์ง€
    }
}

ํ•˜์ง€๋งŒ, Rectangle์„ ๊ธฐ๋Œ€ํ•œ ์ฝ”๋“œ๊ฐ€ Square๋ฅผ ๋Œ€์ž…ํ–ˆ์„ ๋•Œ ์˜ˆ๊ธฐ์น˜ ๋ชปํ•œ ๋™์ž‘์„ ํ•œ๋‹ค๋ฉด LSP ์œ„๋ฐ˜์ด๋‹ค.
์ฆ‰, “is-a ๊ด€๊ณ„”๊ฐ€ ์žˆ๋‹ค๊ณ  ํ•ด์„œ ๋ฌด์กฐ๊ฑด ์ƒ์†์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์œ„ํ—˜ํ•˜๋‹ค.

ํ•ต์‹ฌ ํฌ์ธํŠธ

  • ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ๊ทœ์•ฝ์„ ๊นจ๋œจ๋ฆฌ์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.
  • ํ•˜์œ„ ํด๋ž˜์Šค๊ฐ€ ๋ถ€๋ชจ์˜ ํ–‰์œ„๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์ œ์•ฝ์„ ์œ„๋ฐ˜ํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.

4. DIP (Dependency Inversion Principle) — ์˜์กด ์—ญ์ „ ์›์น™

“๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹ˆ๋ผ ์ถ”์ƒํ™”์— ์˜์กดํ•˜๋ผ.”

์ •์˜

  • ์ƒ์œ„ ๋ชจ๋“ˆ์ด ํ•˜์œ„ ๋ชจ๋“ˆ์˜ ์„ธ๋ถ€ ๊ตฌํ˜„์— ์˜์กดํ•˜์ง€ ์•Š๊ณ , **์ถ”์ƒํ™”(์ธํ„ฐํŽ˜์ด์Šค)**์— ์˜์กดํ•ด์•ผ ํ•œ๋‹ค.
  • ๋ณ€ํ™”์— ์ทจ์•ฝํ•œ ๊ตฌ์ฒด์  ์š”์†Œ๋ณด๋‹ค, ์ƒ๋Œ€์ ์œผ๋กœ ์•ˆ์ •์ ์ธ ์ถ”์ƒ ๊ณ„์ธต์„ ์ค‘์‹ฌ์œผ๋กœ ์„ค๊ณ„ํ•œ๋‹ค.

์˜ˆ์‹œ

 
interface Robot {
    void doWork();
}

class CleaningRobot implements Robot {
    public void doWork() { System.out.println("Cleaning!"); }
}

class Kid {
    private Robot robot;
    public Kid(Robot robot) { this.robot = robot; }
    public void start() { robot.doWork(); }
}

Kid ํด๋ž˜์Šค๋Š” Robot ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋ฏ€๋กœ, CleaningRobot ์ด์™ธ์˜ ๋กœ๋ด‡์œผ๋กœ ์‰ฝ๊ฒŒ ๊ต์ฒด ๊ฐ€๋Šฅํ•˜๋‹ค.


5 ISP (Interface Segregation Principle) — ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™

“ํ•˜๋‚˜์˜ ๋ฒ”์šฉ ์ธํ„ฐํŽ˜์ด์Šค๋ณด๋‹ค๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ตฌ์ฒด์  ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋‚ซ๋‹ค.”

์ •์˜

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

์˜ˆ์‹œ

 
interface Printer {
    void print();
}

interface Scanner {
    void scan();
}

// ๋ฉ€ํ‹ฐํ”„๋ฆฐํ„ฐ๋Š” ๋‘ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
class MultiDevice implements Printer, Scanner {
    public void print() {}
    public void scan() {}
}

๋ถˆํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ ์˜์กด์„ ๋ง‰๊ณ , ๊ฐ ๊ธฐ๋Šฅ๋ณ„๋กœ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์„ธ๋ถ„ํ™”ํ•จ์œผ๋กœ์จ ์‹œ์Šคํ…œ์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ˜๋‹ค.


๐Ÿ“ํ•ต์‹ฌ ์š”์•ฝ

์›์น™์ด๋ฆ„ํ•ต์‹ฌ ๊ฐœ๋…
SRP ๋‹จ์ผ ์ฑ…์ž„ ์›์น™ ํด๋ž˜์Šค๋Š” ํ•˜๋‚˜์˜ ๋ณ€๊ฒฝ ์ด์œ ๋งŒ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค
OCP ๊ฐœ๋ฐฉ-ํ์‡„ ์›์น™ ํ™•์žฅ์—๋Š” ์—ด๋ ค ์žˆ๊ณ , ์ˆ˜์ •์—๋Š” ๋‹ซํ˜€ ์žˆ์–ด์•ผ ํ•œ๋‹ค
LSP ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™ ํ•˜์œ„ ํด๋ž˜์Šค๋Š” ์ƒ์œ„ ํด๋ž˜์Šค๋ฅผ ์™„๋ฒฝํžˆ ๋Œ€์ฒดํ•ด์•ผ ํ•œ๋‹ค
DIP ์˜์กด ์—ญ์ „ ์›์น™ ๊ตฌ์ฒด๊ฐ€ ์•„๋‹Œ ์ถ”์ƒ์— ์˜์กดํ•ด์•ผ ํ•œ๋‹ค
ISP ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™ ํด๋ผ์ด์–ธํŠธ ์ „์šฉ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋ถ„๋ฆฌํ•˜๋ผ