[Design Patterns] Mixin 패턴

·2024년 2월 6일
0

patterns

목록 보기
8/11
post-thumbnail

Mixin 패턴

Mixin은 상속 없이 어떤 객체나 클래스에 재사용 가능한 기능을 추가할 수 있는 객체이다. Mixin은 단독으로 사용할 수는 없고, 상속 없이 객체나 클래스에 기능을 추가하는 목적으로 사용된다.

앱에서 여러 강아지를 만들어야 한다고 가정해보자. 아래 강아지 클래스는 name 프로퍼티 외에 다른 프로퍼티를 가지고 있지 않다.

class Dog {
  constructor(name) {
    this.name = name
  }
}

강아지는 이름 외에도 짖거나 꼬리를 흔들거나 신나게 놀 수 있어야 한다. Dog 클래스에 직접 정의하는 대신 bark, wagTail, play를 프로퍼티로 가진 믹스인을 만들 수 있다.

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

Object.assign 메서드를 이용해 dogFunctionality 믹스인의 기능을 Dog 프로토타입에 추가할 수 있다.
아래 예시에서는 Dog.prototype에 프로퍼티들을 추가하고 있다. 이 경우 새로 만들어지는 Dog 클래스의 인스턴스들은 Dog의 프로토타입 객체에 추가된 dogFunctionality의 기능들을 사용할 수 있다.

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!

상속 없이 객체에 기능을 추가할 수 있지만 믹스인 자체는 상속을 사용할 수 있다.

대부분의 포유류는 걷거나 잠을 잘 수 있다. 강아지는 포유류이니 똑같이 걷거나 잘 수 있어야 한다.
아래 예제에서는 walk, sleep 프로퍼티를 가진 animalFunctionality 믹스인을 만들고 있다.

const animalFunctionality = {
  walk: () => console.log('Walking!'),
  sleep: () => console.log('Sleeping!'),
}

Object.assign을 사용하여 dogFunctionalityanimalFunctionality의 프로퍼티를 추가할 수 있다.

const animalFunctionality = {
  walk: () => console.log('Walking!'),
  sleep: () => console.log('Sleeping!'),
}

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)

Window 객체

Window 객체는 WindowOrWorkerGlobalScope과 WindowEventHandler의 믹스인으로 구성되어 있기 때문에 setTimeout, setInterval, indexedDB, isSecureContext와 같은 프로퍼티를 사용할 수 있다.

WindowOrWorkerGlobalScope는 믹스인이기 때문에 해당 믹스인을 직접 사용할 수는 없다.

window.indexedDB.open("toDoList");

window.addEventListener("beforeunload", event => {
  event.preventDefault();
  event.returnValue = "";
});

window.onbeforeunload = function() {
  console.log("Unloading!");
};

console.log(
  "From WindowEventHandlers mixin: onbeforeunload",
  window.onbeforeunload
);

console.log(
  "From WindowOrWorkerGlobalScope mixin: isSecureContext",
  window.isSecureContext
);

console.log(
  "WindowEventHandlers itself is undefined",
  window.WindowEventHandlers
);

console.log(
  "WindowOrWorkerGlobalScope itself is undefined",
  window.WindowOrWorkerGlobalScope
);

React (ES6 이전)

ES6 클래스 문법이 소개되기 전에 믹스인은 React에서 컴포넌트에 기능을 추가하기 위해 종종 사용되었다. React 개발팀은 mixin을 사용하지 말라는 글과 함께 컴포넌트의 믹스인이 복잡도를 증가시키고 재사용하기 어렵게 만든다고 이야기했다.
대신 React 개발팀은 (지금은 훅에 의해 대체 가능하지만) 고차 컴포넌트를 사용하길 권장했다.

믹스인은 상속을 하지 않고도 객체의 프로토타입에 특정 기능들을 주입할 수 있다. 다만 객체의 프로토타입을 직접 수정하는 것은 의도하지 않은 프로토타입 프로퍼티의 수정으로 이어질 수 있어 주의가 필요하다.

< 출처 : https://patterns-dev-kr.github.io/design-patterns/mixin-pattern/ >

profile
개발을 개발새발 열심히➰🐶

0개의 댓글