백엔드 기본 개념 정리/객체지향 프로그래밍 (OOP)

객체지향의 한계와 대안, 구성(Composition)

jelliclesu 2025. 3. 10. 16:29

객체지향 프로그래밍의 단점

상속의 남용

  • 코드 복잡도 증가
  • 깊은 상속 계층 구조 ➔ 유지보수 어려움
  • 부모 클래스 수정 시 모든 자식 클래스에 영향 ➔ 강한 결합(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(의존성 역전 원칙): 직접적인 의존성을 줄이고, 인터페이스 활용

함수형 프로그래밍 개념 활용

  • 불변성: 객체 변경이 아닌 새로운 객체 생성
  • 순수 함수: 부작용 최소화

디자인 패턴 활용

  • 전략 패턴: 특정 동작을 외부에서 주입하여 유연성 확보
  • 데코레이터 패턴: 객체 기능을 동적으로 확장