객체지향 설계 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 |
