객체지향 프로그래밍의 단점
상속의 남용
- 코드 복잡도 증가
- 깊은 상속 계층 구조 ➔ 유지보수 어려움
- 부모 클래스 수정 시 모든 자식 클래스에 영향 ➔ 강한 결합(Tight Coupling) 발생
객체 간 강한 의존성
- 재사용성 저하
- 하나의 클래스를 수정하면 여러 곳에 영향을 받을 수 있음
- 객체 간 관계가 복잡해지면 확장성과 유연성이 떨어짐
불필요한 메모리 낭비
- 상속을 사용할 경우, 부모 클래스의 불필요한 필드/메서드도 함께 사용됨
- 필요하지 않은 기능이 포함될 수 있음
상속이 과도하게 사용된 경우
class Animal {
void eat() { System.out.println("먹는 중..."); }
}
class Bird extends Animal {
void fly() { System.out.println("나는 중..."); }
}
class Penguin extends Bird {
void swim() { System.out.println("헤엄치는 중..."); }
}
➡︎ Penguin 은 Bird 를 상속받지만, 펭귄은 fly() 메서드 불필요
➡︎ 잘못된 상속 구조로 인해 불필요한 메서드가 포함됨
➡︎ 강한 결합도가 발생하여 유지보수가 어려워짐
‼️ 상속을 사용하기 보다 구성(Composition) 으로 변경
구성
구성(Composition) 이란?
하나의 객체가 다른 객체를 멤버 변수로 포함하는 방식
객체 간 결합도를 줄이고, 유연성을 높일 수 있음
구성 적용 코드
class Swimmer {
void swim() { System.out.println("헤엄치는 중..."); }
}
class Penguin {
private Swimmer swimmer; // 조합(Composition) 사용
Penguin() {
this.swimmer = new Swimmer();
}
void swim() {
swimmer.swim();
}
}
➡︎ 필요한 기능만 포함하여 유연한 설계 가능
상속과의 비교
비교 항목 | 상속(Inheritance) | 구성(Composition) |
코드 재사용성 | 높음 | 높음 |
유지보수성 | 낮음 (부모 클래스 변경 시 영향) | 녹음 (독립적인 기능 구성 가능) |
객체 간 결합도 | 높음 (Tight Coupling) | 낮음 (Loose Coupling) |
유연성 | 낮음 (상속 관계 변경 어려움) | 높음 (필요한 기능만 구성 가능) |
⭐️ 유지보수성과 확장성을 고려할 때, 가능하면 구성(Composition) 을 우선적으로 고려하고,
부모-자식 관계가 명확한 경우에만 상속(Inheritance) 을 사용
객체지향 대안
SOLID 원칙 준수
- SRP(단일 책임 원칙): 하나의 클래스가 너무 많은 역할을 하지 않도록 정리
- DIP(의존성 역전 원칙): 직접적인 의존성을 줄이고, 인터페이스 활용
함수형 프로그래밍 개념 활용
- 불변성: 객체 변경이 아닌 새로운 객체 생성
- 순수 함수: 부작용 최소화
디자인 패턴 활용
- 전략 패턴: 특정 동작을 외부에서 주입하여 유연성 확보
- 데코레이터 패턴: 객체 기능을 동적으로 확장
'백엔드 기본 개념 정리 > 객체지향 프로그래밍 (OOP)' 카테고리의 다른 글
의존성(Dependency) 과 싱글톤(Singleton) (0) | 2025.03.10 |
---|---|
객체지향 설계 원리(SOLID) & 추상화(Abstraction) (1) | 2025.03.07 |
상속(Inheritance)과 다형성(Polymorphism) (0) | 2025.03.06 |
객체지향의 기본 개념(클래스, 객체, 캡슐화) (0) | 2025.03.05 |