Vue.js Mixin

강정우·2023년 5월 6일
2

vue.js

목록 보기
55/72
post-thumbnail
  • 앞으로 코드 재사용성에 관하여 Mixin커스텀 컴포지션 함수에 관하여 포스팅하는데
    이는 정확하게 말하자면 Options 및 Composition API를 활용해 코드 재사용에 관한 기본 개념에 대해 포스팅 하겠다.

재사용성의 개념

  • 사실 그동안 우리가 <bast-blabla> 이런식으로 만든 많은 컴포넌트들이 있다. 이것을 빌딩블록화하여 재사용해 온 것은 여전히 똑같다.
    하지만 어떨 땐 로직의 일부가 남아서 재사용하고 싶어도 사용하지 못 하는 경험이 있다.

  • 그래서 이러한 Options API를 사용할 때 data(){}, methods:{}, computed:{}, watch:{}, life-cycle hooks 까지 컴포넌트 간 필요항 모든 구성요소를 공유할 수 있게 만들어주는 라이브러리가 바로 Mixin이다.

즉, 양 컴포넌트 간의 구성 공유를 쉽게 해주는 강력한 도구라고 생각하면 된다.

  • Mixin은 컴포넌트의 기능을 단위로 분리하여 다른 컴포넌트와 공유하고, 코드 중복을 줄이며, 코드 재사용성을 높이는 데 도움을 줍니다.

사용법

1. 폴더 및 파일생성

  • 우선 src 폴더 바로 밑에 mixin이라고 파일을 생성해준다. 마치 store 폴더를 따로 만들어 vuex의 state값들을 따로 관리해준것 처럼 말이다.

  • 그리고 해당 폴더 밑에 .vue가 아닌 .js파일을 생성해준다.

  • 이때 해당 파일에 중복되거나 반복하여 사용하고 싶은 로직을 덜어서 생성해준다.

예제코드 (alert.js)

import UserAlert from "@/components/UserAlert.vue";

export default {
    components: {
        UserAlert,
    },
    data() {
        return {
            alertIsVisible: false,
        };
    },
    methods: {
        showAlert() {
            this.alertIsVisible = true;
        },
        hideAlert() {
            this.alertIsVisible = false;
        },
    },
};
  • 그리고 위 코드에서 보면 알 수 있듯 만약 import해올 파일이 있으면 반드시 사용되는 곳이 아닌 mixin 파일 자체에 넣어주어야한다.

  • 결과적으로 이렇게 믹스인을 통해 거의 모든 컴포넌트 옵션을 공유할 수 있다.
    울론 components 옵션이란 예외도 있다. 이는 아래서 다루겠다.

  • 그 외에는 데이터, 연산 메서드, 감시자(Watcher) 등 필요한 모든 것을 믹스인을 통해 공유할 수 있다.
    이렇듯 믹스인은 컴포넌트를 더 간결히 하고 컴포넌트 간에 재사용 로직을 공유하게 해주는 강력한 도구이다.

2. 해당 mixin 사용

  • Mixin을 사용하려면 Vue.mixin 메소드를 사용하여 전역적으로 Mixin을 등록하거나, mixins 옵션을 사용하여 특정 컴포넌트에 Mixin을 적용할 수 있다.

  • 우선 mixins 옵션에 대해 먼저 알아보자.
    해당 로직을 사용하고싶다면 사용하고싶은 컴포넌트에 접근하여 export 한 .js 파일을 import 해준다.

  • 다음 mixins 라는 옵션값을 선언한다. 이때 type은 props와 같은 ary 타입이다.

에러

  • 혹시 위와같은 에러가 뜬다면 component를 resolve하지 못 했기 때문에 해당 mixin 파일에 components 프로퍼티를 삭제하고 따로 컴포넌트단에서 작성해줘야한다.

  • 컴포넌트에 등록해야 할 components가 있을 시 components 옵션은 믹스인을 통해 공유할 수 없다고 한다.
    (그런데 난 왜 되지...?) => 하지만 로직을 공유하는 기능이고 또 OptionsAPI의 data, methods, computed, watch, life-cycle을 재사용하기 위해 만들어진 기능이니 components 프로퍼티는 사용되는 컴포넌트에 작성해주도록 하자.

주의사항

  • Mixin은 다른 컴포넌트의 Option API과 병합되어 최종 컴포넌트 Option API을 형성하는데 이때 동일한 Option API 이름이 충돌할 경우, 컴포넌트의 Option API이 우선순위를 가지게 된다.

  • 이는 매우 안 좋은 상황이다. 왜냐하면 오용되면 컴포넌트 간의 의존성을 알기 어렵게 만들 수 있기 때문이다.
    Mixin을 적용한 컴포넌트의 동작을 이해하기 위해서는 해당 컴포넌트와 적용된 모든 Mixin을 살펴야 할 수도 있다.
    이는 코드의 추적과 유지보수를 어렵게 만들 수 있기 때문이다.

Mixin을 사용할 때에는 충돌이 발생하지 않도록 주의해야 한다.

같은 이름의 데이터, 메서드 또는 라이프사이클 훅을 Mixin과 컴포넌트에서 동시에 정의하는 경우 예기치 않은 동작이 발생할 수 있다.
이러한 충돌을 피하기 위해 Mixin과 컴포넌트에서 고유한 이름을 사용하거나, Mixin을 사용하기 전에 충돌 가능성을 검토해야 한다.

Mixin을 너무 많이 사용하면 코드의 복잡성이 증가할 수 있다.

Mixin은 재사용성과 코드 공유를 위해 사용되지만, 지나치게 많이 사용하면 코드를 이해하고 유지보수하기 어려워질 수 있다.
필요한 로직을 적절하게 분리하여 Mixin을 만들고, 컴포넌트 간의 관계와 의존성을 신중하게 설계해야 한다.

merge

  • minin 컴포넌트 옵션 이외에도 그냥 추가적으로도 더 사용할 수 있다.
    즉, Vue.js가 import한 mixin 파일과 컴포넌트의 옵션들을 "병합" 해주는 것이다.
<template>
  <user-alert v-if="alertIsVisible" :title=alertTitle @close="hideAlert">
    <p>Do you want to continue with deleting a user?</p>
  </user-alert>
  <section>
    <h2>Delete a User</h2>
    <button @click="showAlert">Delete User</button>
  </section>
</template>

<script>
import alertMixin from '../mixins/alert';
export default {
  mixins:[alertMixin],
  data() {
    return{
      alertTitle : 'Delete User?'
    }
  },
};
</script>
  • 그래서 따로 해당 컴포넌트에 hideAlert 메서드나, alertIsVisible 데이터 옵션을 설정하지 않아도 적용이 된다.

  • 그렇다면 같은 것을 설정한다면 어떻게 될까? 앞서 주의사항에서 언급한 것 처럼 mixin option 보다 components option이 더 우선이다.
    즉, components optionmixin optionoveride 한다.

전역 mixin

  • 앞서 언급한 mixin은 지역적인 mixin으로 <style scoped> 처럼 지역적으로 해당 컴포넌트에만 적용하는 방식이다.
    그렇다면 이제 전역적으로 사용하는 방법에 대하여 알아보자.

  • 하지만 이러한 전역 mixin은 용도가 아주 제한적이기에 모든 컴포넌트에 추가하려는 일부 로깅 또는 분석 기능 정도가 사용에 적합하겠다.
    즉, 컴포넌트가 언제 마운트되었는지를 알려준다든가 그런 것들을 뜻한다.

logger.js

export default {
    mounted() {
        console.log('mounted!');
    },
}
  • 위 객체에서 데이터를 변경할 건 아니고 대신 마운트된 생명 주기 훅을 추가해준다.
    이때 모든 컴포넌트에 추가된다고 생각해도 된다.

  • 참고로 이 믹스인이 마운트된 생명 주기 훅을 이미 갖고 있는 컴포넌트와 병합된다면 컴포넌트와 믹스인이 각각 가지는 두 생명 주기 훅이 모두 실행된다. overide되지 않는다는 뜻이다.

  • 컴포넌트에 있는 생명 주기 훅이 가장 늦게 실행되고 따라서 믹스인에서 발생한 변경 사항을 덮어쓸 수 있다.

  • 여기 있는 어떤 데이터베이스에 어떤 분석 데이터를 저장한다거나 뭐 이런 일들도 전역 믹스인에서 수행될 수 있다.

  • 이제 전역에 "등록"을 해보자.

main.js

import { createApp } from 'vue';
import App from './App.vue';
import loggerMixin from './mixins/logger'
const app = createApp(App)
app.mixin(loggerMixin);
app.mount('#app');
  • app.comp() 가 글로벌 컴포넌트로 선언했던 것 처럼 app.mixin()을 사용하면 된다.

  • 전역 mixin은 정말 쓸데가 거의 없으나 애플리케이션의 전체 컴포넌트에 어떤 기능을 추가하는 경우에는 필요할 수 있으니 알아 두면 좋을 수도 있다.

단점

협업의 어려움

  • 큰 애플리케이션을 구축하거나 여럿이서 팀으로 작업하는 경우 mixin인은 코드와 컴포넌트 구성 이해를 방해하는 요인이 될 수 있다.

  • 왜냐하면 어떤 값이 어디서 오는지가 항상 명확하진 않기 때문이다.

  • 사진으로 보면 좀 더 이해가 쉬운데 위 마크업단에 보면 굉장히 많은 변수와 메서들이 생략되어있음(mixin안에 포함)에도 IDE가 인식하고 오류를 내보내지 않고 있다. 따라서 만약에 이러한 mixin이 5~6개 까지 늘어난다면 뭐가 어디서 오는지 알 수 없다.

  • 즉, hideAlert이라는 함수를 바꿀 때 mixin이 개많으면 이 mixin을 다 찾으러 다녀야한다는 것이다.

병합의 주의점

  • 기본 병합 전략이 여러분에게 적합하지 않은 경우를 가정해보자. 물론 overide도 가능하지만 mixin이 똑바로 작동하게 하려면 그만큼 신경을 더 많이 써야한다.

  • 그렇게 한다고 해도 여전히 이 메서드는 어디에서 오고 저 데이터 조각은 또 어디에서 오는 건지 바로 알아차리기 어렵다는 문제가 남아 있게되는 것이다.

profile
智(지)! 德(덕)! 體(체)!

0개의 댓글