Mixin은 코드를 재사용하는 패턴중 하나입니다. 그리고 다중상속의 다른 표현법이라 볼 수도 있습니다. 자세한 내용은 밑에서 설명하도록 하겠습니다.
Mixin이란?
Mixin은 전통적인 다중상속을 클래스의 부분부분을 쪼개어 조립하는 것입니다. 하지만 Mixin이 다중상속의 대안으로만 사용되는 것은 아닙니다.
전통적인 클래스 상속을 이용할 때에는 필요하지 않은 부분도 모조리 상속되는 그런 불편함이 있습니다. 하지만 Mixin으로 클래스를 조립한다면 더 깔끔한 구현이 가능하게 됩니다.
전통적인 클래스 상속 구조의 문제점
많은 언어에서는 클래스 다중 상속을 지원하지 않습니다. 하지만 인터페이스는 예외로 다중상속을 지원합니다.
인터페이스란, 클래스의 기능 명세와도 같습니다. 그 자체로 인스턴스화 될 수 없고, 껍데기만 있습니다. 그리고 인터페이스를 상속받는 클래스들은 껍데기인 인터페이스의 메서드들을 구현해야만 합니다.
날 수 있는 것, 동물은 인터페이스입니다. 이 인터페이스를 상속받는 클래스들이 있고 새는 두 인터페이스를 상속받아서 구현할 수 있습니다. 이런 식의 인터페이스 다중 상속은 가능하지만, 클래스를 다중 상속받아야 할 일이 있다면 어떻게 해야 할까요?
사람인 엄마, 아빠의 유전자를 내가 물려받는 것을 표현한 구조입니다. 여기서 사람은 인터페이스, 엄마, 아빠는 클래스이고 나 또한 클래스입니다.
위에서 보았던 인터페이스를 다중 상속받는 것과 달리 이 그림에선 클래스를 다중 상속받습니다. 대부분의 언어는 다중 상속을 지원하지 않는데 이런 경우 Mixin을 이용하여 가볍게 해결할 수 있습니다!
다음 예제는 아빠의 키와 엄마의 키, 성격을 물려받는데 엄마의 키는 아빠의 키 형질에 의해 무시당하는 것을 표현한 예제입니다.
Ruby의 Mixin 구현 예시
언어마다 다를 수 있지만, Ruby같은 경우는 이름이 동일한 메서드의 경우 먼저 include된 모듈(Mixin)을 사용하게 됩니다.
비슷하지만 다른 것들
Swift에서는 Interface, Trait, Mixin을 이렇게 정의할 수 있다고 합니다.
하지만 일반적으로 Mixin과 Trait는 큰 구분이 없이 혼용해서 사용하는 경우가 많고, 학술적인 정의로 구분하자면
- Trait : 상태(state)가 없고 메서드만 존재하는 코드 조각(모듈)
- Mixin : Trait와 달리 상태(state)도 가질 수 있음
이렇게 구분할 수 있습니다.
Component
믹스인 외에도 컴포넌트 패턴을 이용해서 이러한 문제를 해결할 수도 있습니다. 믹스인은 언어에서 지원하는 기능이지만 보통 컴포넌트는 직접 구현해야 합니다. 이 둘의 가장 큰 차이라면, 믹스인과 클래스의 관계는 Is-A 관계입니다. 조금 쉬운 말로 풀어 쓰자면 믹스인은 클래스에 흡수되는 것과 유사합니다. 하지만 컴포넌트는 Has-A 관계입니다. 한마디로 클래스가 컴포넌트들을 가지고 있는 것입니다.
또 다른 차이로, 믹스인으로 구현한 클래스는 변할 수 없지만 컴포넌트로 구현한 클래스는 런타임시에 동적으로 컴포넌트를 추가하거나 삭제할 수 있습니다.
컴포넌트 패턴에 대해서 좀 더 알아보고 싶다면 이곳을 참고해보세요.
정리
상속만을 이용해 OOP를 구현하는 것은 요즘 트렌드에 맞지 않다고 생각합니다. Mixin 또는 Component Pattern을 이용하여 OOP를 구현한다면 더욱 좋은 생산성과 재사용성을 얻을 수 있을거라 생각합니다.