배워서 남 주자

디자인 패턴 - Mixin 패턴

미래에서 온 개발자 2023. 10. 26. 21:25

Mixin 패턴

 

  • 특정 기능을 구현한 객체나 함수를 다른 객체에 '혼합'하여 그 기능을 추가하는 패턴
  • 다시 말해 특정 행동을 실행해주는 메소드를 제공하는데, 단독으로 쓰이지 않고 다른 클래스에 행동을 더해주는 용도로 사용된다.
  • 상속을 사용하지 않고도 여러 객체나 클래스의 프로토타입에 동일한 기능을 제공할 수 있다. 
class Dog {
  constructor(name) {
    this.name = name
  }
}

const dogFunctionality = {
  bark: () => console.log('Woof!'),
  wagTail: () => console.log('Wagging my tail!'),
  play: () => console.log('Playing!'),
}

// 메소드 복사
Object.assign(Dog.prototype, dogFunctionality)

const pet1 = new Dog('Daisy')

pet1.name // Daisy
pet1.bark() // Woof!
pet1.play() // Playing!

 

  • 상속 없이 객체에 기능을 추가할 수 있지만 믹스인 자체는 상속을 사용할 수 있다.
const animalFunctionality = {
  walk: () => console.log('Walking!'),
  sleep: () => console.log('Sleeping!'),
}

// 방법 1) 
const dogFunctionality = {
  bark: () => console.log('Woof!'),
  wagTail: () => console.log('Wagging my tail!'),
  play: () => console.log('Playing!'),
  walk() {
    super.walk()
  },
  sleep() {
    super.sleep()
  },
}

Object.assign(dogFunctionality, animalFunctionality)
Object.assign(Dog.prototype, dogFunctionality)

// 방법 2) 
const dogFunctionality = {
  __proto__: animalFunctionality,
  bark: () => console.log("Woof!"),
  wagTail: () => console.log("Wagging my tail!"),
  play: () => console.log("Playing!"),
  walk() {
    super.walk();
  },
  sleep() {
    super.sleep();
  }
};

Object.assign(Dog.prototype, dogFunctionality);

const pet1 = new Dog("Daisy");
pet1.bark();
pet1.play();
pet1.walk();
pet1.sleep();

target 객체(Dog.prototype)에 source 객체(믹스인 객체 - dogFunctionality)를 복사해 붙여넣는 Object.assign() 메소드나 super.method()와 같은 super 키워드에 대한 내용은 각각의 링크를 참조하기 바란다. 

 

 

주의 사항

객체의 프로토타입을 직접 수정하는 것은 의도하지 않은 프로토타입 프로퍼티의 수정으로 이어질 수 있어 주의가 필요하다. 실수로 메소드를 덮어쓰면 충돌이 발생할 수 있기 때문에 믹스인을 만들 때는 충돌이 발생하지 않도록 메소드 이름을 신중하게 정해야 한다. 

 

지금은 legacy가 된 이전 React 공홈의 2016년도 포스팅에서 Dan Abramov는 mixin 패턴을 사용하는 대신 고차컴포넌트(HOC)를 사용하길 권장했었다. (지금은 hook으로 대체 가능하다.)

 

 

사족:

mixin 이라는 용어를 처음 본 건 Sass의 @mixin 문법을 배울 때였다. CSS 스타일 시트에서 반복적으로 재사용할 CSS 스타일 그룹 선언을 정의할 때 사용하는 키워드로, 마치 함수 같은 역할을 한다. 함수를 선언하고 필요한 곳에서 함수를 호출하여 사용하는 것처럼 @mixin으로 필요한 스타일 그룹을 선언하고, 사용부에서는 @include로 믹스인에 선언된 스타일 속성을 불러온다. 

 

필요한 기능을 원한다면 얼마든지 여러 곳에 추가할 수 있다는 점에서 믹스인 패턴과 일맥상통한다고 할 수 있겠다. 공부를 해내가면서 점이 연결되어서 선이 되는 과정은 참으로 흥미롭다. 

 

 

📚 같이 읽어보면 좋은 자료

 

믹스인

 

ko.javascript.info

 

"Real" Mixins with JavaScript Classes

How to build a simple, powerful, real mixin system for JavaScript and ES6 classes.

justinfagnani.com