[OOP] 객체 지향 설계의 5가지 원칙 - S.O.L.I.D

2026. 1. 26. 18:39·Knowledge/디자인 패턴
📚
Design Pattern:SOILD
Problem Source: GitHub - Sw_Pilot_Java (Chapter 4 / Step 4)

SOLID 원칙이란?

객체지향 설계 5대 원칙으로, 유지보수성과 확장성을 높이고 코드의 복잡도를 줄이기 위한 핵심 설계 지침입니다.

SOLID 원칙은 특정 언어나 프레임워크에 종속되지 않는, "변화에 유연하고 유지보수하기 쉬운 코드"를 만들기 위한 기본 철학입니다.

 


 

1. SRP: 단일 책임 원칙 (Single Responsibility Principle)

"한 클래스는 하나의 책임(기능)만 가져야 한다."

하나의 클래스에 여러 책임이 섞여 있으면, 한 기능의 변경이 다른 기능에 연쇄적인 영향을 줄 수 있습니다. 책임을 명확히 분리하면 변경의 파급효과를 줄이고 유지보수성이 높아집니다.

💡 Tip:
청소기는 청소만 잘하면 됩니다. 화분에 물 주고 드라이 기능까지 넣으면 하나만 고장 나도 전체를 못 쓰게 되죠. 하나의 클래스는 한 가지 책임만 지게 하세요!

✅ 간단한 예시

// 보고서 생성 책임
public class ReportGenerator {
    public String generate() {
        return "Report 내용";
    }
}

// 보고서 출력 책임 (분리됨)
public class ReportPrinter {
    public void print(String report) {
        System.out.println(report);
    }
}

2. OCP: 개방-폐쇄 원칙 (Open/Closed Principle)

"클래스는 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 한다."

기능이 변경되거나 추가될 때, 기존 코드를 뜯어고치지 않고 새로운 기능을 추가할 수 있도록 설계해야 합니다. 주로 추상화(인터페이스/상속)를 통해 이를 달성합니다.

💡 Tip:
역할(인터페이스)과 구현(클래스)을 분리하세요. 기존 코드는 건드리지 말고, 새로운 클래스를 추가(상속/구현)하는 방식으로 기능을 확장하세요.

✅ 간단한 예시

interface Payment {
    void pay();
}

// 새로운 결제 수단이 추가되어도 Payment 인터페이스만 구현하면 됨
class CardPayment implements Payment {
    public void pay() {
        System.out.println("카드 결제 진행");
    }
}

class OrderService {
    private Payment payment;
    
    // 생성자 주입을 통해 유연하게 변경 가능
    public OrderService(Payment payment) {
        this.payment = payment;
    }
    
    public void checkout() {
        payment.pay(); // 기존 코드는 수정할 필요 없음
    }
}

3. LSP: 리스코프 치환 원칙 (Liskov Substitution Principle)

"자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 한다."

다형성을 활용할 때, 부모 클래스 타입으로 선언된 변수에 자식 객체를 대입해도 프로그램이 원래 의도대로 동작해야 한다는 원칙입니다. 즉, 자식 클래스는 부모의 규약을 철저히 지켜야 합니다.

💡 Tip:
자바의 Collection 프레임워크가 대표적인 예입니다. LinkedList에서 HashSet으로 구현체를 바꿔도 .add() 동작은 논리적으로 문제없이 작동해야 합니다.

✅ 간단한 예시

// 부모 타입 Collection
Collection<String> myData = new LinkedList<>();
myData.add("apple");

// 자식 클래스를 HashSet으로 교체해도 add() 동작은 보장됨 -> LSP 만족
myData = new HashSet<>();
myData.add("banana");

4. ISP: 인터페이스 분리 원칙 (Interface Segregation Principle)

"인터페이스는 작게 나눠서, 구현체가 필요한 기능만 구현하게 하자."

범용적인 큰 인터페이스 하나보다는, 구체적인 여러 개의 인터페이스가 낫습니다. 구현하는 클래스가 자신이 사용하지 않는 기능까지 억지로 구현하지 않도록 해야 합니다.

💡 Tip:
인터페이스는 다중 상속(구현)이 가능합니다. 기능별로 잘게 쪼개서 필요한 것만 골라 구현하도록 설계하세요.

✅ 간단한 예시

// 기능별로 인터페이스 분리
interface Printer {
    void print();
}

interface Fax {
    void fax();
}

// 팩스 기능이 없는 프린터는 Printer만 구현하면 됨 (불필요한 fax() 구현 강제 X)
class BasicPrinter implements Printer {
    public void print() {
        System.out.println("프린트 출력 중");
    }
}

5. DIP: 의존 역전 원칙 (Dependency Inversion Principle)

"구현 클래스에 의존하지 말고, 추상화(인터페이스)에 의존해야 한다."

변하기 쉬운 것(구현체)보다는 변하지 않는 것(인터페이스, 추상 클래스)에 의존해야 유지보수가 쉬워집니다. 이를 위해 보통 의존성 주입(DI)을 활용합니다.

💡 Tip:
"저장한다"는 역할(인터페이스)에 의존해야지, "MySQL에 저장한다"는 구체적인 사실에 의존하면 나중에 오라클로 DB를 바꿀 때 코드를 다 뜯어고쳐야 합니다.

✅ 간단한 예시

// 추상화에 의존
interface Database {
    void save(String data);
}

class MySQLDatabase implements Database {
    public void save(String data) {
        System.out.println("MySQL에 저장: " + data);
    }
}

class DataService {
    private Database db; // 구체적인 MySQLDatabase가 아닌 인터페이스에 의존
    
    public DataService(Database db) {
        this.db = db;
    }
    
    public void store(String input) {
        db.save(input);
    }
}

마무리 요약

원칙 설명
SRP 하나의 클래스는 하나의 책임만 가져야 한다.
OCP 확장에는 열려 있고, 수정에는 닫혀 있어야 한다.
LSP 자식 클래스는 부모 클래스를 대체해도 문제없어야 한다.
ISP 필요한 기능만 가진 인터페이스로 분리해야 한다.
DIP 구현체가 아닌, 추상화(인터페이스)에 의존해야 한다.

 

 


 

📚 Reference & Source

🔗 [Inpa Dev 👨‍💻] solid
🔗 SRP
🔗 ISP

'Knowledge > 디자인 패턴' 카테고리의 다른 글

[OOP] GoF(Gang of Four) 디자인 패턴 장점 과 종류 !!  (2) 2026.01.26
'Knowledge/디자인 패턴' 카테고리의 다른 글
  • [OOP] GoF(Gang of Four) 디자인 패턴 장점 과 종류 !!
hlxecz
hlxecz
1인분 개발자가 되고 싶은 개발 기록
  • hlxecz
    H.Dev Log
    hlxecz
  • 전체
    오늘
    어제
    • 분류 전체보기 (12)
      • Language (7)
        • Java (7)
        • C (0)
        • PHP (0)
        • Python (0)
      • Framewrok (0)
        • Spring (0)
      • Data (0)
        • DBMS (0)
      • Cloud (0)
        • Amazon Cloud (0)
      • Knowledge (3)
        • 자료구조 (0)
        • 알고리즘 (1)
        • 디자인 패턴 (2)
      • DevOps (0)
      • Dev Kit (0)
        • InteliJ (0)
        • VSCode (0)
      • TEST (2)
        • Testing (2)
        • Error (0)
      • ETC (0)
        • 일상 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    자바
    피드백
    알고리즘
    인터페이스
    재귀함수
    GOF
    문제풀이
    시간복잡도
    Abstract
    캡슐화
    BIG-O
    문제점
    생각정리
    Collection
    Stack
    빅오표기법
    Solid
    collections
    Interface
    string
    getter
    setter
    Java
    OOP
    바밀로니아
    인터페이스 vs 추상클래스
    디자인 패턴
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
hlxecz
[OOP] 객체 지향 설계의 5가지 원칙 - S.O.L.I.D
GitHub 상단으로

티스토리툴바