4.8 KiB
다형성 (Polymorphism)
📌 Brief Summary
다형성(Polymorphism)은 객체의 타입이나 종류에 따라 달라지는 행동을 명시적인 조건문(switch나 if-else)으로 확인하는 대신, 객체지향적인 방식으로 자연스럽게 처리할 수 있게 해주는 핵심 개념이다 [1-3]. 리팩토링에서 다형성은 주로 수많은 분기를 가진 복잡한 조건문을 서브클래스의 오버라이딩 메서드로 교체하여 코드의 중복을 제거하고 구조를 개선하는 데 활용된다 [4-6]. 이를 통해 새로운 타입이나 사례가 추가될 때 기존의 로직을 뜯어고칠 필요 없이 새로운 클래스만 추가하면 되므로, 개방-폐쇄 원칙(Open/Closed Principle)을 준수하며 아키텍처의 변경을 관리하기 쉽게 만든다 [1, 3, 4, 7].
📖 Core Content
-
조건문(Switch/Case)의 문제점과 객체지향 남용(OO Abusers): 객체지향 코드의 주요 특징 중 하나는 switch(또는 case) 문이 상대적으로 적다는 점이다 [5]. 동일한 조건의 switch 문이 프로그램 곳곳에 흩어져 있으면, 새로운 타입을 추가할 때마다 모든 조건문을 찾아 업데이트해야 하는 치명적인 유지보수 문제가 발생한다 [1]. 이러한 상태는 상속과 다형성 같은 객체지향의 이점을 제대로 살리지 못하고 절차지향적으로 구현된 것으로, '객체지향 남용(OO Abusers)'이라는 코드 스멜(Code Smell)로 분류된다 [8]. 대부분의 switch 문을 발견했을 때는 다형성 적용을 고려해야 한다 [9].
-
다형성을 통한 조건문 교체 (Replace Conditional with Polymorphism): 객체의 타입에 따라 다른 동작을 선택하는 조건문이 있다면, 해당 조건문의 각 분기(leg)를 서브클래스의 오버라이딩 메서드로 이동시키고 원본 메서드는 추상(abstract) 메서드로 만들어야 한다 [6]. 이는 변경의 지식을 클라이언트에서 클래스 내부로 옮겨준다 [10]. 다형성을 통해 복잡한 조건식을 다형성 메서드 호출로 대체함으로써 각 행동을 고립시키고 테스트를 매우 단순하게 만들 수 있다 [4, 7].
-
리팩토링 적용 단계:
- 다중 분기를 가진 복잡한 조건문을 식별한다 [4]. 다형성을 적용하기 전에는 이를 지원할 상속 구조(Inheritance Structure)가 먼저 준비되어 있어야 한다 [11].
- 달라지는 행동을 담을 인터페이스나 베이스 클래스(Base Class)를 생성한다 [4].
- 조건 분기마다 해당하는 구체 클래스(Concrete Class)를 구현한다 [4].
- 기존 조건 로직을 다형성을 활용한 메서드 호출로 교체한다 [4].
- 각각의 구현 클래스를 독립적으로 테스트한다 [4].
-
Null 객체 도입 (Introduce Null Object): 다형성의 본질은 객체에게 어떤 타입인지 묻고 그 대답에 따라 행동을 호출하는 것이 아니라, 단순히 행동을 호출하면 객체가 자신의 타입에 맞게 올바른 일을 수행하도록 하는 것이다 [2]. 반복되는 Null 값 검사 역시 Null 객체라는 특별한 형태의 서브클래스(Special Case)를 도입하여 다형성을 통해 조건문을 제거할 수 있다 [12, 13].
⚖️ Trade-offs & Caveats
-
과도한 설계 (Overkill): 조건문이 단 하나의 메서드에만 영향을 미치고, 향후에도 새로운 타입의 조건이 추가되거나 변경될 것으로 예상되지 않는다면 다형성을 적용하는 것은 지나친 설계(Overkill)가 될 수 있다 [14]. 이러한 경우에는 '명시적 메서드로 매개변수 교체(Replace Parameter with Explicit Methods)'와 같은 더 단순한 대안이 적합하다 [14].
-
객체 수명 주기 동안의 타입 변경 제약: 다형성을 구현하기 위해 서브클래싱(Subclassing)을 사용할 때 한 가지 제약이 있다. 객체는 생성된 이후 수명 주기 동안 자신의 클래스(분류)를 변경할 수 없다는 점이다 [15]. 따라서 객체의 상태나 타입 코드가 실행 도중에 변경되어야 하거나, 이미 다른 이유로 인해 서브클래싱이 적용된 상태라면 다형성을 직접 적용할 수 없다 [11, 15, 16]. 이 경우에는 '상태/전략 패턴으로 타입 코드 교체(Replace Type Code with State/Strategy)'를 활용하여 인디렉션(Indirection)을 추가하고 위임을 통해 다형성을 달성해야 한다 [11, 15, 16].
-
상속 구조 생성의 선행: 다형성을 통해 조건문을 교체하려면 반드시 서브클래싱이나 상태/전략 패턴을 이용한 상속 계층 구조가 사전에 만들어져 있어야 하므로, 초기 구조를 잡기 위한 추가적인 작업이 요구된다 [11, 17].
Last updated: 2026-05-03