Topic (오늘의 주제)
객체지향 설계 5대 원칙 (SOLID)
로버트 C. 마틴(Robert C. Martin)이 정립한, "유지보수하기 쉽고, 유연하며, 확장이 쉬운 소프트웨어"를 만들기 위한 5가지 설계 원칙의 앞글자를 딴 것입니다.
Why (왜 사용하는가? 왜 중요한가?)
이 개념이 실무, 설계, 면접에서 중요한 이유
- 실무: 요구사항이 변경되었을 때, 이 원칙을 지키지 않은 코드는 '스파게티 코드'가 되어 수정 시 버그가 연쇄적으로 발생합니다. (하나 고치면 다른 곳이 터짐)
- 구조적 의미: 소프트웨어 설계의 핵심 목표인 "높은 응집도(High Cohesion)와 낮은 결합도(Low Coupling)"를 달성하게 해줍니다.
- 면접 의도: 지원자가 단순히 "돌아가는 코드"를 짜는 코더인지, 아니면 "지속 가능한 아키텍처"를 고민하는 엔지니어인지 판단하는 기준입니다.
Core Concept (핵심 개념 정리)
SOLID는 다음 5가지 원칙으로 구성됩니다.

| 원칙 | 전체 이름 (Full Name) | 핵심 내용 (한 줄 요약) |
| S | SRP (Single Responsibility Principle) 단일 책임 원칙 |
"클래스는 변경해야 할 이유가 단 하나여야 한다." (하나의 기능만 담당해라) |
| O | OCP (Open/Closed Principle) 개방-폐쇄 원칙 |
"확장에는 열려 있고, 변경에는 닫혀 있어야 한다." (기존 코드를 건드리지 않고 기능을 추가해라) |
| L | LSP (Liskov Substitution Principle) 리스코프 치환 원칙 |
"자식 클래스는 부모 클래스의 자리를 대체할 수 있어야 한다." (상속의 규약을 깨지 마라) |
| I | ISP (Interface Segregation Principle) 인터페이스 분리 원칙 |
"범용 인터페이스 하나보다 구체적인 여러 개가 낫다." (자신이 쓰지 않는 메소드에 의존하지 마라) |
| D | DIP (Dependency Inversion Principle) 의존관계 역전 원칙 |
"구체적인 것이 추상적인 것에 의존해야 한다." (클래스가 아닌 인터페이스를 바라봐라) |
- 장점: 시스템의 복잡도를 낮추고, 재사용성을 높이며, 테스트 작성을 용이하게 합니다.
- 단점: 초기 설계 비용이 들고, 클래스와 인터페이스의 수가 늘어나 구조가 복잡해 보일 수 있습니다 (과한 엔지니어링 주의).
Interview Answer Version (면접 답변식 요약)
"SOLID는 객체지향 설계를 위한 5가지 원칙입니다.
단일 책임 원칙(SRP), 개방-폐쇄 원칙(OCP), 리스코프 치환 원칙(LSP), 인터페이스 분리 원칙(ISP), 의존관계 역전 원칙(DIP)으로 구성됩니다.
이 원칙들을 사용하는 이유는 결합도를 낮추고 응집도를 높여, 요구사항 변경 시 기존 코드의 수정을 최소화하고 유연하게 확장 가능한 시스템을 만들기 위해서입니다. 특히 스프링 프레임워크는 이 중 DI(의존성 주입)를 통해 OCP와 DIP를 강력하게 지원합니다."
Practical Tip (사용시 주의할 점 or 활용 예)
1. 실무 활용 코드 (OCP와 DIP의 조화)
if-else로 도배된 코드를 인터페이스(다형성)로 리팩토링하는 것이 SOLID의 가장 흔한 적용 사례입니다.
- Bad (OCP 위반): 결제 수단이 늘어날 때마다 OrderService 코드를 수정해야 함.
- Java
class OrderService { void pay(String type) { if (type.equals("NAVER")) { /* 네이버 로직 */ } else if (type.equals("KAKAO")) { /* 카카오 로직 */ } } } - Good (OCP + DIP 준수): 인터페이스를 사용.
-
Java
// DIP: OrderService는 구체적인 NaverPay가 아닌 Payment 인터페이스에 의존 class OrderService { private Payment payment; // 인터페이스 public OrderService(Payment payment) { // 생성자 주입 this.payment = payment; } public void process() { payment.pay(); // OCP: 새로운 결제수단이 생겨도 이 코드는 변경 없음 } }
2. 주의할 점 (과유불급)
- 오버 엔지니어링: 모든 코드에 SOLID를 강박적으로 적용하면 인터페이스와 클래스가 폭발적으로 늘어납니다. 변경 가능성이 거의 없는 간단한 로직에는 적용하지 않는 것이 좋습니다. (YAGNI 원칙: You Ain't Gonna Need It)
- LSP 위반 사례: 부모 클래스의 메소드가 예상과 다르게 동작하게 자식을 구현하면 안 됩니다. (예: 직사각형을 상속받은 정사각형이 가로 길이를 바꿨는데 세로 길이까지 같이 바뀌어 버리는 경우)
예상 꼬리질문 정리
- Spring 프레임워크와 SOLID는 어떤 관계가 있나요?
- 답변 키워드: Spring의 핵심인 DI(의존성 주입) 컨테이너가 바로 **DIP(의존관계 역전)**를 구현한 것이며, 이를 통해 **OCP(개방-폐쇄)**를 쉽게 달성하게 해줍니다.
- LSP(리스코프 치환 원칙)를 위반하면 어떤 문제가 생기나요?
- 답변 키워드: 부모 타입으로 업캐스팅해서 사용할 때 예상치 못한 버그가 발생합니다. 즉, 다형성을 믿고 사용할 수 없게 되어 상속의 의미가 퇴색됩니다.
- 단일 책임 원칙(SRP)에서 '책임'의 기준은 무엇인가요?
- 답변 키워드: "변경의 이유"입니다. 어떤 클래스를 수정해야 하는 이유가 기획 변경, DB 변경 등 여러 가지라면 책임이 많은 것입니다. 하나만 바뀌었을 때 클래스를 수정해야 한다면 SRP를 잘 지킨 것입니다.
'Archive > Daily Dev Q&A' 카테고리의 다른 글
| Daily Dev Q&A: 자바의 접근 제어자(Access Modifier) (0) | 2025.12.09 |
|---|---|
| Daily Dev Q&A: 자바의 Collections Framework (0) | 2025.12.08 |
| Daily Dev Q&A: 오버로딩과 오버라이딩 (0) | 2025.12.05 |
| Daily Dev Q&A: 다형성 (0) | 2025.12.03 |
| Daily Dev Q&A: 상속과 컴포지션(Composition)의 차이와, 언제 컴포지션을 사용하는가? (0) | 2025.12.02 |