객체지향 설계 5원칙. SRP(단일 책임), OCP(개방-폐쇄), LSP(리스코프), ISP(인터페이스 분리), DIP(의존성 역전).

 

SOLID가 없는 코드

- 기능 하나 수정할 경우 여러 곳이 깨짐

- 새 기능 추가 -> 기존 코드 수정

- 테스트 작성 불가

- 건드리기 두려움

 

S - 단일 책임 원칙 ( SRP )

Single Responsibility Principle

 

클래스는 변경되어야 할 이유가 단 하나만 있어야 한다. - Robert C. Martin

// SRP 위반 — GameManager가 너무 많은 책임
class GameManager {
    void UpdatePhysics() {...}   // 물리
    void RenderFrame() {...}     // 렌더링
    void SaveGame() {...}        // 저장
    void PlaySound() {...}       // 사운드
    void HandleInput() {...}     // 입력
};

// SRP 적용 — 각자 하나의 책임
class PhysicsSystem   { void Update() {...} }
class RenderSystem    { void Render() {...} }
class SaveSystem      { void Save() {...}   }

 

O - 개방-폐쇄 원칙 ( OCP )

Open-Closed Principle

 

확장에는 열려 있고 수정에는 닫혀 있어야 한다.

// OCP 위반 — 새 무기 추가할 때마다 기존 코드 수정
void Attack(EWeaponType type) {
    if(type == Sword)  { ... }
    if(type == Bow)    { ... }
    if(type == Spear)  { ... }  // 새 무기 추가 = 이 함수 수정
}

// OCP 적용 — 새 무기 = 새 클래스만 추가
class IWeapon          { virtual void Attack() = 0; }
class Sword : IWeapon  { void Attack() override {...} }
class Bow   : IWeapon  { void Attack() override {...} }
class Spear : IWeapon  { void Attack() override {...} }
// 새 무기 추가 = 기존 코드 한 줄도 수정 안 함

 

L - 리스코프 치환 원칙 ( LSP )

Liskov Substiution Principle

 

부모 클래스를 사용하는 곳에 자식 클래스를 넣어도 동작이 이상해지면 안된다.

// LSP 위반 — 자식이 부모 계약을 깨뜨림
class Bird {
    virtual void Fly() {...}
}
class Penguin : public Bird {
    void Fly() override {
        throw "펭귄은 못 날아요!";  // 부모 계약 파괴
    }
}

// LSP 적용 — 계층 재설계
class Bird     { virtual void Move() {...} }
class FlyingBird : public Bird { virtual void Fly() {...} }
class Penguin  : public Bird   { void Move() override {...} }

 

I - 인터페이스 분리 원칙 ( ISP )

Interface Segregation Principle

 

클라이언트는 자신이 사용하지 않는 메서드에 의존하면 안 된다

거대한 인터페이스 하나보다 작은 인터페이스 여럿이 낫다

// ISP 위반 — 모든 것을 하나의 인터페이스에
class IEntity {
    virtual void Move()    = 0;  // 움직이는 것만 필요
    virtual void Attack()  = 0;  // 공격하는 것만 필요
    virtual void TakeDmg() = 0;  // 피격당하는 것만 필요
    virtual void Save()    = 0;  // 저장되는 것만 필요
};
// 돌덩어리 오브젝트도 Move, Attack, Save를 구현해야 함 ← 문제

// ISP 적용 — 인터페이스 분리
class IMovable   { virtual void Move()    = 0; }
class IAttackable{ virtual void Attack()  = 0; }
class IDamageable{ virtual void TakeDmg() = 0; }
class ISaveable  { virtual void Save()    = 0; }
// 필요한 것만 조합

 

D - 의존성 역전 원칙 ( DIP )

Dependency Inversion Principle

 

고수준 모듈이 저수준 모듈에 직접 의존하면 안 된다

둘 다 추상화(인터페이스)에 의존해야 한다.

// DIP 위반 — 고수준이 저수준에 직접 의존
class CombatSystem {
    MySQLDatabase db;  // 구체적인 DB에 직접 의존
    void SaveResult() {
        db.Save(...);  // DB가 바뀌면 CombatSystem 수정 필요
    }
}

// DIP 적용 — 인터페이스에 의존
class IDatabase    { virtual void Save() = 0; }
class MySQLDB      : public IDatabase {...}
class LocalFileDB  : public IDatabase {...}

class CombatSystem {
    IDatabase* db;  // 인터페이스에만 의존
    CombatSystem(IDatabase* database) : db(database) {}
    // DB가 바뀌어도 CombatSystem 수정 불필요
}

 

 

연결되는 단어들

 

God Object : SRP 위반의 극단. 모든 것을 아는 클래스. 유지보수의 악몽

 

디자인 패턴과의 관계 : SOLID는 원칙, 디자인 패턴은 그 원칙을 구현한 구체적 해법. 전략 패턴은 OCP, 옵저버는 DIP, 팩토리는 DIP를 구현하는 패턴

 

Clean Architecture : SOLID를 시스템 전체 아키텍처 레벨로 확장한 것. Robert C. Martin이 SOLID와 함께 제안한 개념.

'Word' 카테고리의 다른 글

OpenGL ( Open Graphics Library )  (0) 2026.07.07
스마트 포인터 ( Smart Pointer )  (0) 2026.07.06
나라티브 디자인 ( Narrative Design )  (0) 2026.07.06
수직 슬라이드 ( Vertical Slice )  (0) 2026.07.02
KPI ( Key Performance Indicator )  (0) 2026.07.02

+ Recent posts