본문 바로가기

Web/웹 상식

Vue.js 3.0 과 Vite

모든 내용을 정리하지는 않았으므로 더 자세한 내용은 vue.js 3.0 공식 가이드를 확인해 주세요 ㅎㅎ

Vue.js 3.0 기능 & 변경된 부분

Composition API

2.x 와 3.0의 가장 큰 차이점은 Composition API 입니다. 하지만 2.x 버전에도 사용할 수 있습니다.
공식 사이트의 설명에 따르면 Composition API를 사용하면 코드 재사용, 코드 로직 모으기가 개선 되었다고 합니다.
React hook에서 아이디어를 가져왔다고 합니다. 예시를 통해서 간단히 알아보겠습니다.

기존 방식

<template>
  <div>
    <button @click="increaseCount">
      count is {{count}}, doubleCount is {{doubleCount}}
    </button>
    <button @click="search">
      data is {{simpleData}}
    </button>
  </div>
</template>

<script>
    export default {
        data() {
            return {
                simpleData: "",
                count: 0,
                doubleCount: 0
            }
        },
        computed: {
            count() {
                this.doubleCount = count * 2
            }
        },
        methods: {
            search() {
                // data를 가져오는 코드
        },
        increase() {
            this.count++
        }
    }
</script>

 
기존 방식에서는 data를 가져와서 표시하는 로직과 count를 변경하는 로직 2개가 data(), computed, methods로 나뉘어져 있습니다. 이 코드만 봐서는 데이터는 data() 부분을 보면 되고 메소드 부분은 methods에서 찾으면 되니까 편해보이기도 하지만 코드가 아주 길어질 경우 데이터가 처리되는 일련의 로직을 확인하려 스크롤을 많이 움직여야 했습니다.

따라서 데이터를 처리하는 로직이 모여있으면 좋겠다고 생각됩니다.

새로운 Composition API 방식

<template>
    <button @click="increaseCount">count is {{ count }}, doubleCount is {{ doubleCount }}</button>
    <button @click="search" style="margin-left: 15px">data is {{ simpleData }}</button>
    <button @click="increaseReactiveCount" style="margin-left: 15px">reactive count is {{ reactiveCount.count }}, doubleCount is {{ reactiveCount.doubleCount }}</button>
</template>

<script>
    import {computed, reactive, ref} from 'vue';

    const countLogic = () => {
        const count = ref(0);
        const doubleCount = computed(() => count.value * 2);

        function increaseCount() {
            count.value++
        }

        return {count, doubleCount, increaseCount}
    };

    const dataLogic = () => {
        const simpleData = ref("");

        function search() {
            // 데이터 가져오는 코드
            simpleData.value = "데이터입니다"
        }

        return {simpleData, search}
    };

    const reactiveLogic = () => {
        const reactiveCount = reactive({
            count: 0,
            doubleCount: computed(() => reactiveCount.count * 2)
        });

        function increaseReactiveCount() {
            reactiveCount.count++
        }

        return {reactiveCount, increaseReactiveCount}
    };

    export default {
        setup() {
            const {count, doubleCount, increaseCount} = countLogic();
            const {simpleData, search} = dataLogic();
            const {reactiveCount, increaseReactiveCount} = reactiveLogic();

            return {
                count, doubleCount, increaseCount,
                simpleData, search,
                reactiveCount, increaseReactiveCount
            }
        }
    }
</script>

 

  • 코드 결과

Compositiona API를 사용하면 위와 같이 코드를 구성 할 수 있습니다. 각각의 로직들을 모듈로 구성하고 사용할 수 있으며 외부의 컴포넌트에서 해당 모듈을 가져다가 쓸 수도 있습니다. 이러한 방식으로 재사용성과 로직 모으기가 개선되었습니다.

Reactivity APIs

reactive

2.x 버전의 Vue.observable()과 같고 간단하게 객체를 반응형으로 만듭니다. 위 코드에서 ref를 대신하여 사용한 것을 볼 수 있습니다.

ref

ref는 객체를 가변 참조 객체로 만들고, 내부 값을 가리키는 value 속성을 가지고 있게 합니다.

watchEffect

watchEffectwatch와 조금 다른 특성을 가집니다. watch는 특정 객체를 지정하고 그 객체가 변경되었을 때만 실행되지만 watchEffect는 생성 즉시 실행되고 이후에는 모든 반응형 객체를 감시하고 변경되면 실행됩니다. 제가 반응형 객체라고 표현한 것은 공식문서에는 reactive dependencies로 표시되어 있습니다. 어떻게 표현해야할지 몰라서 반응형 객체라 했습니다.

Lifecycle Hooks

Composition API에는 라이프 사이클 훅에도 일부 변경이 있습니다. 2.x에서는 각 Lifecycle hook을 export default 하위에 선언하도록 했지만 3.0에서는 setup 내부에 선언하도록 변경되었습니다.
 

  • beforeCreate -> setup()
  • created -> setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • activated -> onActivated
  • deactivated -> onDeactivated
  • errorCaptured -> onErrorCaptured
  • onRenderTracked (새로 추가)
  • onRenderTriggered (새로 추가)

emit, prop과 this 바인딩 분리

2.x 버전에서는 밑의 코드에서 this가 prop의 값인지 data의 값인지 알 수 없었습니다.
 

    mounted () {
        console.log('title: ' + this.title)
    }

 
하지만 이제 3.0에서는 props로 지칭하여 사용할 수 있습니다. setup에서 사용할 시에는 attribute로 받아서 사용 가능합니다.
 

    setup (props) {
        // ...
        onMounted(() => {
          console.log('title: ' + props.title)
        })
        // ...
    }

 
emit도 this와 분리되었습니다. 기존에는 this.$emit으로 사용되었지만 이제는 this를 뺀 emit으로 사용합니다.
 

    setup (props, { emit }) {
        // ...

        const login = () => {
          emit('login', {
            username: state.username,
            password: state.password
          })
        }

        // ...
    }

루트 element의 제한 해제

기존에는 루트 element로 하나의 element만 왔어야 했습니다. 그래서 div로 전체를 감싸도록 많이 사용했습니다.
3.0에서는 여러 element가 올 수 있도록 변경되었습니다.

    <template>
        <button @click="increaseCount">count is {{ count }}, doubleCount is {{ doubleCount }}</button>
        <button @click="search" style="margin-left: 15px">data is {{ simpleData }}</button>
        <button @click="increaseReactiveCount" style="margin-left: 15px">reactive count is {{ reactiveCount.count }}, doubleCount is {{ reactiveCount.doubleCount }}</button>
    </template>

VITE

VITE는 네이티브 ES 모듈을 지원하는 웹 개발 툴입니다. Vue.js 3.0 이상과 동작하게 설계 되었고 번들 시에는 Rollup.js를 사용하여 프로덕션 빌드를 제공합니다. 실제로 사용해본 결과 처음 구동할 때와 HMR시에 확연하게 차이가 느껴졌습니다.

VITE의 장점

  • 빠른 콜드 서버 스타트

    번들링을 수행하지 않고 서버 콜드 스타트가 매우 빠릅니다.
  • 인스턴트 HMR (hot module replacement)

    vue.js 코드는 수정 후 저장하면 HMR 되면서 바로 변경된 사항을 볼 수 있습니다. VITE는 HMR할 때 변경된 모듈만 교체하므로 프로그램의 크기에 상관없이 HMR이 일관되게 빠릅니다.

  • 진정한 온-디맨드 방식

    코드는 온-디맨드 방식으로 컴파일 됩니다. 그래서 실제로 보여지는 현재 화면만 컴파일 됩니다. 전체 앱이 번들링될 때까지 기다릴 필요가 없어서 프로젝트의 크기가 클 경우 더 효과적인 방식입니다.

VITE의 단점

  • Full Page Load 시에는 기존의 vue-cli 보다 느릴 수 있다.
  • 아직 CSS Preprocessor의 HMR을 지원하지 않는다.

사용법

  • npm 사용시
$ npm init vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev

 

  • Yarn 사용시
$ yarn create vite-app <project-name>
$ cd <project-name>
$ yarn
$ yarn dev

 


반응형