SOLID는 유지보수 가능하고 유연한 OOP 시스템을 구축하기 위한 다섯 가지 설계 원칙입니다. 각각은 경직되고 깨지기 쉬운 코드의 흔한 원인을 다룹니다.
SOLID는 유지보수 가능하고 유연한 OOP 시스템을 구축하기 위한 다섯 가지 설계 원칙입니다. 각각은 경직되고 깨지기 쉬운 코드의 흔한 원인을 다룹니다.
| 글자 | 원칙 | 한 줄 의미 |
|---|
| S | Single Responsibility | class는 변경 이유가 하나여야 한다 |
| O | Open/Closed | 확장에는 열려 있고 수정에는 닫혀 있다 |
| L | Liskov Substitution | 서브타입은 기반 타입이 쓰이는 어디서나 사용 가능해야 한다 |
| I | Interface Segregation | 하나의 큰 interface보다 작은 여러 개가 낫다 |
| D | Dependency Inversion | 구체 class가 아니라 추상화에 의존하라 |
# Dependency Inversion: 고수준 코드가 추상화에 의존
class Notifier: # 추상화
def send(self, msg): ...
class EmailNotifier(Notifier):
def send(self, msg): print("email:", msg)
class OrderService:
def __init__(self, notifier: Notifier): # 주입된 추상화
self.notifier = notifier # "new EmailNotifier()" 가 아님
def place(self):
self.notifier.send("order placed") # 어떤 Notifier 와도 작동
OrderService는 email에 구체적으로 의존하지 않습니다 — 이를 건드리지 않고 SMS나 테스트 더블로 교체할 수 있습니다(D). 새 notifier 타입을 추가해도 OrderService는 변경이 필요 없습니다(O).
SOLID는 지침이지 법이 아닙니다. 과도하게 적용하면 — class마다 interface, 곳곳에 간접 계층 — 해결하려던 문제보다 따라가기 어려운 "추상화 수프"가 됩니다.
SOLID는 공통 진단 언어를 제공합니다: 리뷰어는 취향으로 다투는 대신 class가 왜 변경하기 어려운지("이건 SRP 위반이다") 이름 붙일 수 있습니다.
판단력과 함께 적용하면, 원칙들은 파급 효과를 줄입니다 — 변경이 국소적으로 유지되고, 새 기능은 다시 작성하는 대신 확장하며, 테스트는 실제 의존성 대신 가짜를 대체할 수 있습니다.