설계 원칙(SOLID)이란?
객체지향을 공부하다 보면 “유지보수하기 좋은 코드”라는 표현을 자주 듣는다.
그런데 유지보수가 좋다는 건 결국 변경이 쉬운 구조라는 뜻이고,
그 구조를 만들기 위한 대표적인 가이드가 바로 SOLID 원칙이다.
SOLID는 5가지 설계 원칙의 앞글자를 딴 용어로,
변경에 강하고(유연),
재사용 가능하며,
테스트하기 쉬운 코드를 만들자.
라는 목표를 가지고 있다.

----------------------------------------------------------------------------------------------------------------------------------------------------------------
S — 단일 책임 원칙(SRP: Single Responsibility Principle)
한 클래스(모듈)는 하나의 책임만 가져야 한다.
여기서 “책임”은 보통 '변경 이유(Why it changes)'로 이해하면 쉽다.

위 그림을 보고 예시를 생각해본다면 다음과 같다.
나쁜 예: 이 클래스는 로그인도 하고, DB도 만지고, 메일도 보냄
좋은 예: 책임(변경 이유)을 기준으로 분리 함
즉, “요구사항 1개 바뀌었는데 파일 10개를 건드린다” → SRP 위반 가능성이 크다.
(로그/메일/DB/검증 로직이 한 곳에 뒤엉켜 있으면 분리 후보)
----------------------------------------------------------------------------------------------------------------------------------------------------------------
O — 개방-폐쇄 원칙(OCP: Open/Closed Principle)
확장에는 열려 있고, 수정에는 닫혀 있어야 한다.
예시를 들어본다면 다음과 같다.
나쁜 예: 결제 수단 추가할 때마다 if/else가 계속 늘어남
좋은 예: 공통 인터페이스(또는 추상 클래스) + 새 구현 추가로 확장
“추상화 + 다형성”이 OCP를 돕는 핵심 도구이다.
(조건문이 기능 추가마다 늘어나는 구조면, “전략 패턴(Strategy)” 같은 방식이 후보)
즉, 기존의 코드는 변경하지 않으면서 확장은 쉽게 할 수 있어야 한다.
----------------------------------------------------------------------------------------------------------------------------------------------------------------
L — 리스코프 치환 원칙(LSP: Liskov Substitution Principle)
자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 한다.
LSP 위반은 런타임 버그로 이어지기 쉬워서 테스트 관점에서도 중요한데,
예시를 들어본다면 다음과 같다.
나쁜 예: Bird.fly()가 있는데 Penguin이 Bird를 상속받아 fly()에서 예외를 던짐
→ 부모의 규약을 깨는 순간, 치환이 불가능해짐
즉, 상속을 사용했다면
부모 타입 자리에 자식 타입을 넣어도, 프로그램의 의미/규약(동작)이 깨지지 않아야 한다.
----------------------------------------------------------------------------------------------------------------------------------------------------------------
I — 인터페이스 분리 원칙(ISP: Interface Segregation Principle)
하나의 일반적인 인터페이스보다 구체적인 여러 개의 인터페이스를 만들어야한다.
만약, 인터페이스가 “만능 기능 모음”이 되면 구현체가 불필요한 메서드까지 억지로 구현하게 된다.
예시를 들어본다면 다음과 같다.
나쁜 예: IWorker 안에 work(), eat(), sleep()을 다 넣어버림
좋은 예: 역할에 따라 IWorkable, IEatable처럼 작게 쪼개기
특히 외부 연동/SDK 래퍼를 만들 때 ISP가 효율을 크게 올린다.
( “한 인터페이스가 너무 크다” → ISP 적용 후보)
즉, 클라이언트는 사용하지 않는 메서드에 의존하지 않도록, 인터페이스는 작고 목적별로 분리해야한다.
----------------------------------------------------------------------------------------------------------------------------------------------------------------
D — 의존성 역전 원칙(DIP: Dependency Inversion Principle)
어떤 class를 참조해서 사용하는 상황이 생긴다면,
그 class를 직접 참조하는 것이 아니라 그 대상의 상위요소(추상 클래스 or 인터페이스)로 참조해야한다.

ð 구현 클래스에 의존하지 말고, 인터페이스에 의존해야한다.
ð 의존 역전 원칙의 지향점은 각 클래스간의 결합도를 낮추는 것이다.
즉, 고수준 모듈은 저수준 구현에 직접 의존하지 말고, 둘 다 ‘추상(인터페이스/추상클래스)’에 의존해야 한다.
----------------------------------------------------------------------------------------------------------------------------------------------------------------
오늘의 결론 요약
'SOLID'원칙은 객체지향 설계를 현실적으로 유지보수 가능하게 만드는 5가지 원칙이다.
핵심은 결합도↓ / 응집도↑ / 변경 영향 범위 최소화다.
“원칙”은 법이 아니라 리팩터링 방향을 잡아주는 나침반이다.
'1일 1 cs' 카테고리의 다른 글
| 6. Unity의 생명주기(Life Cycle)란? (0) | 2026.01.21 |
|---|---|
| 5. 동기/비동기 프로그래밍이란? (0) | 2026.01.19 |
| 4. 제네릭 이란? (+ 오브젝트 풀링) (0) | 2026.01.18 |
| 3. 디자인 패턴(싱글톤, 팩토리, 상태, 전략)이란? (0) | 2026.01.17 |
| 1. 객체지향 프로그래밍(OOP)이란? (0) | 2026.01.15 |
