객체지향 설계 원칙 SOLID 완벽 이해하기
Java 객체지향 프로그래밍(OOP)을 공부하다 보면 반드시 등장하는 개념이 바로:
SOLID 원칙
입니다.
실무에서도:
- Spring
- 클린 아키텍처
- DDD
- 대규모 백엔드 설계
전부 SOLID 철학 위에서 설계됩니다.
초보 시절에는 보통:
SRP
OCP
LSP
ISP
DIP
약어만 외우고 넘어가기 쉽습니다.
하지만 실제로 SOLID는 단순 암기용 이론이 아니라:
- 유지보수 쉬운 구조
- 변경에 강한 설계
- 유연한 객체 구조
- 확장 가능한 시스템
을 만들기 위한 핵심 설계 원칙입니다.
이번 글에서는:
- SOLID가 왜 등장했는가
- 각 원칙의 진짜 의미
- 실무 사례
- Spring과의 연결
- 잘못 이해하기 쉬운 부분
까지 정리해보겠습니다.
1. SOLID란?
SOLID는 객체지향 설계 원칙 5가지를 정리한 개념입니다.
| S | SRP (단일 책임 원칙) |
| O | OCP (개방 폐쇄 원칙) |
| L | LSP (리스코프 치환 원칙) |
| I | ISP (인터페이스 분리 원칙) |
| D | DIP (의존 역전 원칙) |
2. 왜 SOLID가 중요할까?
대규모 시스템에서는:
- 기능 계속 추가
- 요구사항 계속 변경
- 개발자 여러 명 협업
상황이 반복됩니다.
이때 설계가 좋지 않으면:
기능 하나 수정
↓
전체 코드 영향
↓
버그 폭발
발생 가능.
SOLID는 이를 줄이기 위한 설계 원칙입니다.
3. SRP (Single Responsibility Principle)
단일 책임 원칙
의미:
클래스는 하나의 책임만 가져야 한다
4. SRP 안 좋은 예
class UserService {
void login() {}
void sendEmail() {}
void saveToDB() {}
void createPdf() {}
}
문제:
- 책임 과도
- 변경 이유 너무 많음
- 유지보수 어려움
5. SRP 좋은 예
UserService
MailService
PdfService
UserRepository
책임 분리.
6. SRP 핵심
중요한 건:
메서드 개수
가 아니라:
변경 이유가 하나인가?
입니다.
7. 실무에서 SRP 매우 중요
대표 사례:
| Controller | 요청 처리 |
| Service | 비즈니스 로직 |
| Repository | DB 접근 |
Spring 구조 자체가 SRP 기반.
8. OCP (Open Closed Principle)
개방 폐쇄 원칙
의미:
확장에는 열려 있고 수정에는 닫혀 있어야 한다
9. OCP 안 좋은 예
if (type.equals("CARD")) {
} else if (type.equals("KAKAO")) {
}
새 결제 방식 추가 시:
기존 코드 수정 필요
10. OCP 좋은 예
interface Payment {
void pay();
}
구현체 추가:
class CardPayment implements Payment
class KakaoPayment implements Payment
새 기능 추가 시:
기존 코드 수정 최소화
가능.
11. OCP 핵심 기술
핵심은:
- 다형성
- 인터페이스
- 추상화
입니다.
Spring DI도 사실상 OCP 구현 구조.
12. LSP (Liskov Substitution Principle)
리스코프 치환 원칙
의미:
부모 타입 자리에 자식 객체가 문제 없이 들어갈 수 있어야 한다
13. LSP 안 좋은 예
class Bird {
void fly() {}
}
class Penguin extends Bird {
@Override
void fly() {
throw new UnsupportedOperationException();
}
}
문제:
Penguin은 사실 fly 불가능
즉:
is-a 관계 깨짐
14. LSP 핵심
상속은 단순 코드 재사용이 아니라:
타입 호환성 보장
이 핵심.
15. 실무에서 LSP 중요 사례
예시:
List list = new ArrayList();
→ LinkedList로 교체해도 동작 동일해야 함.
16. ISP (Interface Segregation Principle)
인터페이스 분리 원칙
의미:
클라이언트는 자신이 사용하지 않는 메서드에 의존하면 안 된다
17. ISP 안 좋은 예
interface Worker {
void work();
void eat();
void sleep();
}
Robot도 구현해야 한다면?
불필요 메서드 강제
문제 발생.
18. ISP 좋은 예
interface Workable {
void work();
}
interface Eatable {
void eat();
}
필요한 인터페이스만 구현.
19. ISP 핵심
핵심은:
작고 명확한 인터페이스
입니다.
실무에서 거대한 인터페이스는 유지보수 어려움.
20. DIP (Dependency Inversion Principle)
의존 역전 원칙
의미:
구현체가 아니라 추상화에 의존해야 한다
21. DIP 안 좋은 예
class UserService {
private MySqlRepository repository =
new MySqlRepository();
}
문제:
구현체 강결합
22. DIP 좋은 예
interface UserRepository {
}
class UserService {
private UserRepository repository;
}
즉:
구현이 아니라 인터페이스 의존
구조.
23. Spring과 DIP
Spring 핵심 철학 중 하나.
예시:
@Autowired
UserRepository repository;
실제 구현체는:
- JpaRepository
- MyBatisRepository
- MemoryRepository
교체 가능.
24. SOLID와 Spring 관계
Spring은 사실상:
SOLID 실현 프레임워크
에 가깝습니다.
대표 연결:
| SRP | Layer 분리 |
| OCP | DI + 다형성 |
| DIP | Interface 기반 |
| ISP | 작은 Bean 역할 |
| LSP | 구현체 교체 가능 |
25. SOLID를 잘못 이해하는 경우
초보자가 자주 하는 실수:
“클래스를 무조건 많이 쪼개야 한다”
아닙니다.
핵심은:
변경에 강한 구조
입니다.
26. 인터페이스 남발 문제
예시:
UserService
UserServiceImpl
구현체 하나뿐인데 무조건 인터페이스 생성.
작은 프로젝트에서는 오히려 복잡도 증가 가능.
27. 실무에서 중요한 건 균형
너무 과한 추상화는:
- 코드 복잡도 증가
- 이해 어려움
- 유지보수 비용 증가
가능.
28. 좋은 SOLID 적용 기준
좋은 설계는:
- 변경 가능성 높은 부분 분리
- 구현체 교체 가능
- 책임 명확
- 결합도 낮음
특징을 가집니다.
29. SOLID의 진짜 목적
SOLID 핵심 목적은:
유지보수 쉬운 시스템
입니다.
즉:
- 변경 영향 최소화
- 확장 쉬운 구조
- 테스트 쉬운 구조
를 만드는 것이 핵심.
30. 정리
SOLID는 단순 암기용 이론이 아닙니다.
실제로는:
- Spring 설계
- 객체지향 구조
- DI
- 다형성
- 유지보수성
전체를 지탱하는 핵심 설계 원칙입니다.
특히 실무에서는:
- 책임 분리(SRP)
- 인터페이스 기반 설계(DIP)
- 확장 가능한 구조(OCP)
를 이해하는 것이 매우 중요합니다.
다음 글에서는:
불변 객체(Immutable Object) 설계
를 Thread-safe와 JVM 메모리 관점까지 포함해서 정리해보겠습니다.
'language > java' 카테고리의 다른 글
| Java Builder Pattern 완벽 이해하기 (0) | 2026.05.22 |
|---|---|
| Java 불변 객체(Immutable Object) 완벽 이해하기 (0) | 2026.05.22 |
| Java 오버라이딩(Overriding) vs 오버로딩(Overloading) 완벽 이해하기 (0) | 2026.05.22 |
| Java this / super 키워드 완벽 이해하기 (0) | 2026.05.22 |
| Java 접근 제어자(private/protected/public/default) 완벽 이해하기 (0) | 2026.05.22 |
댓글