Daily Dev Q&A: 상속과 컴포지션(Composition)의 차이와, 언제 컴포지션을 사용하는가?

2025. 12. 2. 16:57·Archive/Daily Dev Q&A

📝 Topic (오늘의 주제)

자바 상속(Inheritance)과 컴포지션(Composition)의 차이 및 사용 기준

: 객체지향 프로그래밍(OOP)에서 코드를 재사용하는 두 가지 핵심 기법인 '상속'과 '조합(컴포지션)'의 개념을 명확히 하고, 왜 현대 개발에서 "상속보다는 컴포지션을 선호하라(Favor Composition over Inheritance)"는 원칙이 강조되는지 학습한다.


Why (왜 사용하는가? 왜 중요한가?)

  • 실무: 상속은 부모-자식 간의 **결합도(Coupling)**가 매우 높아, 부모 클래스 수정 시 자식 클래스에 예기치 않은 오류(Fragile Base Class 문제)를 발생시켜 유지보수 비용을 급증시킨다.
  • 구조적 의미: 컴포지션은 인터페이스를 통해 객체를 **느슨하게 결합(Loose Coupling)**하여, 런타임에 기능을 동적으로 변경하거나 캡슐화를 유지하면서 필요한 기능만 노출하는 최적화된 구조를 제공한다.
  • 면접 의도: 지원자가 단순히 문법(extends)을 아는 것을 넘어, 객체지향 설계 원칙(OCP, LSP 등)을 이해하고 설계 유연성을 고려하여 코드를 작성할 수 있는지 확인하려 한다.

Core Concept (핵심 개념 정리)

요소 내용
개념 정의 상속: 부모 클래스의 모든 속성과 기능을 물려받아 IS-A (자식은 부모다) 관계를 형성하는 것.

컴포지션: 다른 객체의 인스턴스를 필드(부품)로 가지고 기능을 위임받아 HAS-A (A는 B를 가지고 있다) 관계를 형성하는 것.
동작 방식 상속: extends 키워드를 사용. 컴파일 시점에 관계가 고정됨(정적). 부모의 public, protected 메서드가 자동 노출됨.

컴포지션: 클래스 내부의 private 필드로 객체를 선언. 생성자 등을 통해 주입(DI)받고, 필요한 메서드만 호출하여 사용(Delegation).
장점/단점 상속: 코드 작성이 간편하고 다형성 구현이 쉽지만, 결합도가 높고 불필요한 기능까지 상속됨.

컴포지션: 유연하고 테스트가 용이하며 캡슐화가 보장되지만, 코드가 길어지고 래퍼(Wrapper) 메서드를 작성해야 하는 번거로움이 있음.
필요 조건 상속: 확실한 계층 구조와 타입 호환성(IS-A)이 보장되어야 함.

컴포지션: 기능의 재사용이 목적이며, 내부 구현을 감추고 싶을 때 사용.
비교 화이트박스 재사용(상속): 부모의 내부 구현을 자식이 훤히 앎.

블랙박스 재사용(컴포지션): 객체의 인터페이스만 알면 됨.

Interview Answer Version (면접 답변식 요약)

"상속과 컴포지션의 가장 큰 차이는 결합도와 관계의 본질에 있습니다.

상속은 IS-A 관계로 부모의 기능을 물려받으며 결합도가 높습니다. 반면 컴포지션은 HAS-A 관계로 다른 객체를 필드로 소유하여 기능을 위임해 사용하며 결합도가 낮습니다.

저는 코드의 재사용만이 목적이라면 컴포지션을 우선적으로 고려합니다. 상속은 부모 클래스의 변경이 자식에게 치명적인 영향을 줄 수 있고, 불필요한 메서드까지 노출되어 캡슐화를 해칠 수 있기 때문입니다. 따라서 명확한 타입 계층 구조가 필요한 경우가 아니라면, 컴포지션을 통해 유연하고 유지보수하기 쉬운 설계를 지향합니다."


Practical Tip (사용시 주의할 점 or 활용 예)

1. 이걸 모르고 사용하면 생기는 문제 (Java API 실제 사례)

자바의 java.util.Stack은 대표적인 상속의 오용 사례입니다.

  • 상황: Stack은 LIFO(Last In First Out) 구조여야 하므로 중간에 데이터를 넣거나 빼면 안 됩니다.
  • 문제: Vector를 상속받아 구현했기 때문에, Vector의 add(index, element) 메서드가 Stack에 노출되었습니다.
  • 결과: 스택의 원칙이 깨져버려, 사용자가 중간에 데이터를 삽입해도 막을 수 없습니다. (현재는 Deque 인터페이스 사용 권장)

2. 컴포지션 적용 코드 예시 (Wrapper Class 패턴)

상속 대신 필드로 객체를 가지고, 필요한 기능만 '전달(Forwarding)'합니다.

Java
 
// [컴포지션 활용] Set의 기능을 확장(계측)하고 싶을 때
public class InstrumentedTestedSet<E> {
    private int addCount = 0;
    private final Set<E> set; // 컴포지션: Set 인스턴스를 품음

    public InstrumentedTestedSet(Set<E> set) {
        this.set = set;
    }

    public boolean add(E e) {
        addCount++;
        return set.add(e); // 위임 (Delegation)
    }

    public int getAddCount() {
        return addCount;
    }
    
    // Set의 다른 기능이 필요하면 추가로 위임 메서드 작성
}
  • 장점: HashSet을 쓰든 TreeSet을 쓰든 생성자로 주입만 받으면 되므로 훨씬 유연합니다.

3. 설정 시 고려 포인트

  • Lombok 활용: 컴포지션은 코드가 길어지는 단점이 있는데, Lombok의 @Delegate (현재는 실험적 기능이라 주의 필요) 등을 활용하거나 IDE의 'Delegate Methods' 자동 생성 기능을 활용하면 생산성을 높일 수 있습니다.

예상 꼬리질문 정리

  1. Q: 그렇다면 상속은 언제 써야 하나요? 반드시 써야 하는 경우가 있나요?
    • A: 상위 클래스와 하위 클래스가 완벽한 IS-A 관계일 때, 그리고 상위 클래스의 코드가 변경될 때 하위 클래스도 같이 변경되는 것이 논리적으로 타당할 때 사용합니다. 또한 프레임워크(React 컴포넌트, JPA 엔티티 등)에서 설계를 위해 상속을 강제하는 경우에는 따라야 합니다.
  2. Q: 리스코프 치환 원칙(LSP)과 상속의 관계에 대해 설명해 주세요.
    • A: LSP는 자식 클래스가 부모 클래스의 자리를 완벽하게 대체할 수 있어야 한다는 원칙입니다. 상속을 잘못 사용하면(예: 직사각형을 상속받은 정사각형), 부모의 동작 규약을 자식이 깨뜨리게 되어 LSP를 위반하게 됩니다. 이럴 때는 상속을 끊고 컴포지션을 써야 합니다.
  3. Q: 컴포지션과 전략 패턴(Strategy Pattern)의 관계는 무엇인가요?
    • A: 전략 패턴은 컴포지션의 장점을 극대화한 디자인 패턴입니다. 객체의 행위(전략)를 인터페이스로 정의하고, 이를 필드(컴포지션)로 가짐으로써 런타임에 전략을 갈아끼울 수 있게 하여 코드 수정 없이 유연한 확장을 가능하게 합니다.

'Archive > Daily Dev Q&A' 카테고리의 다른 글

Daily Dev Q&A: 오버로딩과 오버라이딩  (0) 2025.12.05
Daily Dev Q&A: 다형성  (0) 2025.12.03
Daily Dev Q&A: 객체지향언어란? & 왜 JAVA가 객체지향언어인가?  (0) 2025.12.01
Daily Dev Q&A: 자바의 예외 처리(Exception) 구조  (0) 2025.11.28
Daily Dev Q&A: 자바는 컴파일 언어? 인터프린터 언어?  (0) 2025.11.28
'Archive/Daily Dev Q&A' 카테고리의 다른 글
  • Daily Dev Q&A: 오버로딩과 오버라이딩
  • Daily Dev Q&A: 다형성
  • Daily Dev Q&A: 객체지향언어란? & 왜 JAVA가 객체지향언어인가?
  • Daily Dev Q&A: 자바의 예외 처리(Exception) 구조
tlsgkstj
tlsgkstj
짱구의 성장 일기
  • tlsgkstj
    코딩하는 짱구
    tlsgkstj
  • 전체
    오늘
    어제
    • 분류 전체보기 (159)
      • About (1)
      • Projects (35)
        • Personal Projects (21)
        • Team Projects (14)
      • Engineering (20)
        • CS & Tools (0)
        • Backend Core (15)
        • Frontend (1)
        • Infra & Cloud (2)
        • AI & Tools (1)
      • Trouble Shooting & Issues (0)
      • Growth & Career (38)
        • Interview Prep (0)
        • Retrospectives (38)
      • Archive (65)
        • TIL (8)
        • Daily Dev Q&A (56)
  • 블로그 메뉴

    • 홈
    • About
    • Projects
    • Tech Stack
    • Dev Log
    • GitHub
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    Project_Review
    프로덕트개발자
    jpa
    SpringBoot
    프로젝트회고
    spring
    REACT
    backend
    OrphanRemova
    DevFestIncheon2025
    경기기후바이브코딩
    aws_s3
    network
    클로드코드
    커리어리셋
    Spring비교
    devlog
    데브페스트
    java
    til
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
tlsgkstj
Daily Dev Q&A: 상속과 컴포지션(Composition)의 차이와, 언제 컴포지션을 사용하는가?
상단으로

티스토리툴바