SOLID 원칙

2025. 3. 24. 23:08개발자 능력치 물약/C++

SOLID 원칙은 유지보수성과 확장성이 뛰어난 소프트웨어를 설계하는 데 도움을 주는 객체 지향 설계 원칙이다.
SOLID는 다음 5가지 원칙의 앞글자를 따서 만든 약어다.

대부분의 디자인패턴은 solid원칙을 기반으로 파생되었다.

  1. Single Responsibility Principle (SRP) - 단일 책임 원칙
  2. Open/Closed Principle (OCP) - 개방-폐쇄 원칙
  3. Liskov Substitution Principle (LSP) - 리스코프 치환 원칙
  4. Interface Segregation Principle (ISP) - 인터페이스 분리 원칙
  5. Dependency Inversion Principle (DIP) - 의존 역전 원칙

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

"클래스는 단 하나의 책임만 가져야 한다."
즉, 하나의 클래스는 오직 하나의 목적을 가져야 하며, 하나의 변경 이유만 가져야 한다.

 

class Report {
public:
    void generateReport() { cout << "Report 생성" << endl; }
};

class FileManager {
public:
    void saveToFile(Report report) { cout << "파일 저장" << endl; }
};

 

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

"확장에는 열려 있고, 수정에는 닫혀 있어야 한다."
즉, 기존 코드를 수정하지 않고 새로운 기능을 추가할 수 있어야 한다.

class Payment {
public:
    virtual void process() = 0;
};

class CreditCard : public Payment {
public:
    void process() override { cout << "신용카드 결제" << endl; }
};

class PayPal : public Payment {
public:
    void process() override { cout << "페이팔 결제" << endl; }
};

// 새로운 결제 방식 추가 (OCP 적용)
class ApplePay : public Payment {
public:
    void process() override { cout << "애플페이 결제" << endl; }
};

void processPayment(Payment* payment) {
    payment->process();
}

 

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

"자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 한다."
즉, 기본 클래스(부모)를 사용하는 코드에서 파생 클래스(자식)로 변경해도 문제없이 동작해야 한다.

 

class Bird {
public:
    virtual void move() = 0;
};

class FlyingBird : public Bird {
public:
    virtual void fly() { cout << "새가 날아감" << endl; }
};

class NonFlyingBird : public Bird {
public:
    virtual void walk() { cout << "새가 걸어감" << endl; }
};

class Penguin : public NonFlyingBird {
public:
    void walk() override { cout << "펭귄이 걸어감" << endl; }
};

 

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

"클라이언트가 자신이 사용하지 않는 인터페이스에 의존하지 않아야 한다."
즉, 필요한 기능만 가진 작은 인터페이스를 여러 개 만드는 것이 좋다.

class Workable {
public:
    virtual void work() = 0;
};

class Eatable {
public:
    virtual void eat() = 0;
};

class Engineer : public Workable, public Eatable {
public:
    void work() override { cout << "엔지니어 일함" << endl; }
    void eat() override { cout << "엔지니어 밥먹음" << endl; }
};

class Robot : public Workable {
public:
    void work() override { cout << "로봇 일함" << endl; }
};

 

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

"고수준 모듈(상위 레벨)은 저수준 모듈(하위 레벨)에 의존하면 안 된다. 둘 다 추상화에 의존해야 한다."
즉, 구체적인 클래스가 아니라 인터페이스(추상 클래스)에 의존해야 한다.

class Device {
public:
    virtual void turnOn() = 0;
};

class Light : public Device {
public:
    void turnOn() override { cout << "불 켜짐" << endl; }
};

class Switch {
    Device* device;
public:
    Switch(Device* d) : device(d) {}
    void operate() { device->turnOn(); }
};