React 사용자들을 위한 Vue 전환 가이드: 공부해야 할 스킬셋

전솔·2023년 8월 9일
0

2019년에 Vue로 토이 프로젝트를 진행한 후, 이후로는 React를 쭉 사용해왔는데 최근에 새로운 프로젝트에서 Vue를 사용해서 Vue에 대한 공부를 시작했다.

Vue와 React는 많은 유사점이 있지만, 각각의 특성과 문법적인 차이들이 있다. 나는 기존 SPA 지식을 바탕으로 빠르게 Vue를 익혀 실무에 투입 하고자한다.

추천 온라인 강의

새로 투입할 프로젝트가 신규프로젝트가 아니라 vue3가 아닌 vue2를 사용한다.(심지어 타입스크립트도 사용하지 않는다..🥲)

최근에 나온 강의들은 대부분 vue3 강의여서 vue2 강의 찾기가 까다로웠다.

관련해서 여러 서칭을 하다가 트렐로 개발로 배우는 Vuejs, Vuex, Vue-Router 프론트엔드 실전 기술을 듣기로 결정했다.

(예전에 김정환님의 실습 UI 개발로 배워보는 순수 javascript 와 VueJS 개발 라는 강의가 MVC 패턴과 MVVM패턴을 이해하는데 많은 도움이 됐어서 망설임 없이 선택했다.)

Vue CLI로 프로젝트 셋팅

npm install -g vue-cli
vue init 프로젝트이름

Vue 기본 문법

data

data 옵션은 Vue 인스턴스에서 사용할 데이터를 정의하는 객체이다. 이 데이터는 뷰 템플릿에서 사용되며, 변경되면 화면이 자동으로 업데이트된다.

예시

<div id="app">
  <p>{{ message }}</p>
</div>
export default {
  data() {
      return {
        message: '안녕, Vue!'
	}
  }
}

react에서 비슷한 개념

state

computed

computed 옵션은 기존의 데이터를 가공하거나 연산하여 새로운 값을 계산하는 속성이다. data와 달리, 의존하는 데이터가 변경될 때만 다시 계산된다.

예시

<div id="app">
  <p>{{ message }}</p>
  <p>{{ reversedMessage }}</p>
</div>
const app = new Vue({
  el: '#app',
  data: {
    message: 'Vue로 배우는',
  },
  computed: {
    reversedMessage() {
      return this.message.split('').reverse().join('');
    }
  }
});

react에서 비슷한 개념

useMemo

methods

methods 옵션은 Vue 인스턴스에서 사용할 메서드를 정의하는 객체이다. 이 메서드들은 뷰 템플릿에서 호출할 수 있다.

예시

<div id="app">
  <button v-on:click="sayHello">인사하기</button>
</div>
const app = new Vue({
  el: '#app',
  methods: {
    sayHello() {
      alert('안녕하세요!');
    }
  }
});

watch

watch 옵션은 데이터의 변경을 감시하고, 해당 데이터가 변경될 때 특정 로직을 실행할 수 있다.

예시

<div id="app">
  <p>{{ message }}</p>
</div>
const app = new Vue({
  el: '#app',
  data: {
    message: 'Vue를 배우자!',
  },
  watch: {
    message(newVal, oldVal) {
      console.log('메시지가 변경되었습니다:', newVal, oldVal);
    }
  }
});

wath와 computed와 차이점

watch는 데이터의 변화를 감시하고 추가적인 로직을 수행할 때 사용되며, computed는 데이터의 가공이나 연산 결과를 계산하여 사용할 때 사용된다.

react에서 비슷한 개념

useEffect

created / mounted

createdmounted는 라이프사이클 훅으로, Vue 인스턴스의 생성과 DOM 요소와의 연결을 다룬다. created는 인스턴스가 생성된 후에 호출되는데, 이때 데이터 초기화 등의 로직을 수행할 수 있다. mounted는 인스턴스가 DOM에 부착된 후에 호출되는데, 이때 외부 라이브러리와의 연동이나 비동기 작업 등을 처리할 수 있다.

예시

<div id="app">
  <p>{{ message }}</p>
</div>
const app = new Vue({
  el: '#app',
  data: {
    message: 'Vue로 웹 앱 만들기!',
  },
  created() {
    console.log('Vue 인스턴스가 생성되었습니다.');
  },
  mounted() {
    console.log('Vue 인스턴스가 DOM에 부착되었습니다.');
  }
});

updated

updated 훅은 Vue 컴포넌트의 뷰가 다시 렌더링되고 화면이 업데이트된 후에 호출되는 라이프사이클 훅이다. 이 훅은 컴포넌트가 업데이트된 후에 추가적인 작업을 수행하거나, DOM을 조작하거나, 외부 라이브러리와의 상호작용을 처리하는 데 유용하다.

예시

<template>
  <div>
    <input v-model="message" ref="inputField" type="text">
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: '안녕하세요, Vue!',
    };
  },
  updated() {
    // 컴포넌트가 업데이트되고 나서 실행됨
    // 입력 요소의 값을 변경한 후 포커스를 설정함
    this.$refs.inputField.focus();
  },
};
</script>

react에서 비슷한 개념

useEffect(() => {
	// 컴포넌트가 업데이트된 후 실행됨
	// 추가적인 작업 수행
	if (inputRef.current) {
	  inputRef.current.focus();
	}
});

v-model

v-model은 양방향 데이터 바인딩을 위한 디렉티브로, 사용자 입력을 즉시 반영하고, 반대로 데이터 변경이 입력 요소에도 즉시 반영된다.

예시

<div id="app">
  <input v-model="message" type="text">
  <p>{{ message }}</p>
</div>
const app = new Vue({
  el: '#app',
  data: {
    message: '입력 값을 바꿔보세요!',
  }
});

props / this.$emit

props는 부모 컴포넌트로부터 자식 컴포넌트로 데이터를 전달하기 위해 사용되는 속성이다. 자식 컴포넌트에서는 props로 받은 데이터를 변경할 수 없다. 데이터 변경이 필요한 경우 emit을 사용하여 이벤트를 발생시키고, 부모 컴포넌트에서 이벤트를 처리할 수 있다.

예시

<!-- 부모 컴포넌트 -->
<div id="app">
  <child-component :message="parentMessage" @childEvent="handleChildEvent"></child-component>
</div>
// 자식 컴포넌트
Vue.component('child-component', {
  props: ['message'],
  template: `
    <div>
      <p>{{ message }}</p>
      <button @click="emitEvent">자식 컴포넌트 이벤트 발생</button>
    </div>
  `,
  methods: {
    emitEvent() {
      this.$emit('childEvent', '자식 컴포넌트에서 이벤트 발생!');
    }
  }
});

const app = new Vue({
  el: '#app',
  data: {
    parentMessage: '부모 컴포넌트로부터 데이터 전달',
  },
  methods: {
    handleChildEvent(message) {
      alert('부모 컴포넌트에서 이벤트 처리: ' + message);
    }
  }
});

Vue Router 사용법

1. Vue Router 설치

npm install vue-router

2. Vue Router 설정

// router.js
import Vue from 'vue';
import VueRouter from 'vue-router';

// Vue.use를 사용하여 Vue Router를 전역으로 등록합니다.
Vue.use(VueRouter);

// 라우트 컴포넌트를 가져옵니다.
import Home from './components/Home.vue';
import About from './components/About.vue';

// 라우트 정의
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
];

// 라우터 인스턴스 생성
export default new VueRouter({
  routes,
});
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'

new Vue({
  el: '#app',
  router,
  render: h => h(App)
})

3. 라우트 링크 및 뷰 렌더링

<template>
  <div>
    <router-link to="/"></router-link>
    <router-link to="/about">소개</router-link>
    <router-view></router-view>
  </div>
</template>

Vuex 사용법

1. Vuex 설치

npm install vuex

2. Vuex 설정

import Vue from 'vue';
import Vuex from 'vuex';

// Vue.use를 사용하여 Vuex를 전역으로 등록합니다.
Vue.use(Vuex);

// 상태(state) 정의
const state = {
  count: 0,
};

// 변이(mutations) 정의
const mutations = {
  increment(state) {
    state.count++;
  },
  decrement(state) {
    state.count--;
  },
};

// 액션(actions) 정의
const actions = {
  increment(context) {
    context.commit('increment');
  },
  decrement(context) {
    context.commit('decrement');
  },
};

// Vuex 스토어 생성
const store = new Vuex.Store({
  state,
  mutations,
  actions,
});

export default store;

mutation과 action의 차이

mutation은 동기적인 상태 변경을 다루는 반면에 action은 비동기적인 작업과 상태 변경을 다룬다. 비동기 작업을 처리해야 할 때 action을 사용하고, 상태를 동기적으로 변경해야 할 때 mutation을 사용하는 것이 일반적인 패턴이다.

  • mutation을 호출하는 함수: commit
  • action을 호출하는 함수: dispatch

3. 컴포넌트에서 Vuex 사용

mapStatemapActions를 활용하면 Vuex의 상태와 액션을 더 직관적이고 간결하게 컴포넌트 내에서 사용할 수 있다. 이를 통해 코드 가독성을 높이고 반복적인 작업을 줄일 수 있다.

<template>
  <div>
    <p>카운트: {{ count }}</p>
    <button @click="increment">증가</button>
    <button @click="decrement">감소</button>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex';

export default {
  computed: mapState(['count']),
  methods: mapActions(['increment', 'decrement']),
};
</script>
profile
Frontend Engineer.

0개의 댓글