본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] 다중 상속의 복잡성을 해결하는 1가지 핵심 : MRO와 C3 Linearization 알고리즘의 차이

by Papa Martino V 2026. 3. 27.
728x90

 

MRO와 C3 Linearization 알고리즘의 차이
MRO(Method Resolution Order) 와  C3 Linearization  알고리즘

 

객체 지향 프로그래밍(OOP)에서 상속은 코드 재사용성을 높이는 강력한 도구입니다. 하지만 '다중 상속'의 영역으로 들어서면 구조가 복잡해지며, 어떤 부모 클래스의 메서드를 먼저 호출할 것인지에 대한 논리적 충돌이 발생합니다. 파이썬은 이를 MRO(Method Resolution Order)C3 Linearization 알고리즘을 통해 우아하게 해결합니다. 본 가이드에서는 숙련된 개발자의 관점에서 이들의 내부 동작 원리와 실무적 해결 방안을 심층 분석합니다.


1. 다중 상속의 난제: 다이아몬드 문제(Diamond Problem)

다중 상속을 지원하는 언어에서 공통적으로 발생하는 문제는 '어느 경로를 통해 메서드를 찾을 것인가'입니다. 예를 들어, 클래스 A를 상속받은 B와 C가 있고, D가 B와 C를 동시에 상속받는 구조(다이아몬드 구조)에서 A의 메서드를 호출할 때 발생할 수 있는 모호성을 파이썬은 알고리즘적으로 차단합니다.

과거의 방식과 한계

  • 깊이 우선 탐색(DFS): 초기 파이썬(2.2 이전)에서 사용되었으나, 다이아몬드 구조에서 최상위 클래스가 중복 방문되거나 서브 클래스보다 먼저 탐색 되는 모순이 발생했습니다.
  • 단조성(Monotonicity) 위배: 상속 구조가 복잡해질 때 부모 클래스의 순서가 뒤바뀌는 현상이 발생하여 예측 불가능한 버그를 초래했습니다.

2. C3 Linearization 알고리즘의 3가지 핵심 원칙

파이썬 2.3부터 도입되어 현재까지 표준으로 사용되는 C3 Linearization은 다음 세 가지 제약 조건을 완벽하게 충족합니다.

  1. 지역 우선순위 유지: 자식 클래스는 부모 클래스보다 먼저 탐색 됩니다.
  2. 단조성(Monotonicity): A가 B보다 먼저라면, 모든 하위 클래스에서도 이 순서가 유지됩니다.
  3. 상속 그래프의 보존: 프로그래머가 정의한 부모 클래스의 나열 순서(왼쪽에서 오른쪽)를 존중합니다.

3. MRO 계산 방식 비교 및 요약

파이썬의 발전 과정에 따른 MRO 결정 방식의 차이를 표로 정리하였습니다.

비교 항목 구형 클래스 (Classic Class) 신규 클래스 (New-style Class)
적용 알고리즘 DFS (Depth-First Search) C3 Linearization
중복 탐색 해결 미해결 (중복 방문 가능) 완벽 해결 (선형화)
탐색 순서 특징 왼쪽 가지를 끝까지 파고듦 계층 구조를 고려한 병합(Merge)
단조성 보장 보장되지 않음 엄격하게 보장됨

4. 실전 코드 예제 (Sample Example)

다음은 C3 Linearization이 실제로 어떻게 MRO를 구성하는지 보여주는 구체적인 코드 샘플입니다.


class Root:
    pass

class A(Root):
    def hello(self):
        print("Hello from A")

class B(Root):
    def hello(self):
        print("Hello from B")

class C(A, B):
    pass

# MRO 확인
print(C.mro())
# 결과: [<class 'C'>, <class 'A'>, <class 'B'>, <class 'Root'>, <class 'object'>]

obj = C()
obj.hello() # "Hello from A" 출력

위 예제에서 C(A, B)로 정의했기 때문에, C3 알고리즘에 의해 A → B 순서가 보장됩니다. 만약 class C(B, A)로 선언했다면 결과는 "Hello from B"가 되었을 것입니다. 파이썬은 L(C) = [C] + merge(L(A), L(B), [A, B]) 공식을 통해 이 선형화 과정을 처리합니다.


5. 잘못된 상속 구조 해결 방법

가끔 MRO를 계산할 수 없는 모순된 상속 구조를 설계하면 파이썬은 TypeError: Cannot create a consistent method resolution order (MRO)를 발생시킵니다. 이는 주로 교차 상속 상황에서 발생합니다.

  • 문제 원인: 부모 클래스 간의 순서 정의가 하위 클래스에서 뒤바뀔 때 발생.
  • 해결책: 상속 계층을 단순화하거나, 상위 클래스 설계 시 Composition(합성) 패턴 도입을 검토해야 합니다.

6. 결론: 왜 개발자가 MRO를 알아야 하는가?

대규모 프레임워크(Django, DRF 등)를 다룰 때 다중 상속은 빈번하게 사용됩니다. super() 함수가 단순히 "부모"를 찾는 것이 아니라 "MRO 상의 다음 클래스"를 찾는다는 사실을 이해하는 것이 전문 개발자로 거듭나는 첫걸음입니다.


참고 문헌 및 출처

  • Python Software Foundation. "The Python 2.3 Method Resolution Order." 공식 문서.
  • Guido van Rossum. "Method Resolution Order." The History of Python Blog.
  • C3 Linearization Algorithm (Paper by Barrett et al., OOPSLA '96).
728x90