반응형

 

1. Option API와 Composition API 비교 설명

 

Option API:

전통적인 Vue.js 방식으로, 컴포넌트의 로직을 data, methods, computed, watch 등으로 구분합니다.

코드의 구조가 명확하게 나누어져 있어, 이해하기 쉬운 것이 장점입니다.

큰 컴포넌트에서는 로직이 흩어져 있어 관리가 어려워질 수 있습니다.

Composition API:

Vue 3에서 도입된 새로운 방식으로, 함수형 프로그래밍 스타일에 가까운 접근법입니다.

관련 로직을 setup 함수 내에서 함께 정의할 수 있어, 큰 컴포넌트에서도 관련 로직을 그룹화하여 관리할 수 있습니다.

ref, computed, watch, onMounted 등의 기능을 활용하여 상태와 라이프사이클을 관리합니다.

코드 재사용성이 높아지며, 특히 큰 프로젝트에서 유리합니다.

 

Composition API를 사용하여 post 게시판을 구현하면서 기존의 Option API 방식과 비교할 수 있었습니다. Composition API는 보다 유연하고 코드 재사용성을 높이는 데 유리하며, Vuex와의 결합도 자연스럽습니다. 이를 통해 학생들이 Vue의 두 가지 API 스타일을 이해하고, 필요에 따라 적절히 선택할 수 있도록 도울 수 있습니다.

todoList 를 postList 로 동일한 코드로 composition api 로 변형 해보았습니다. 


PostList.vue

<template>
    <v-container>
      <v-row>
        <v-col>
          <h1>Vue.js Post Board</h1>
          <AddPost @add-post="addPost" />
          <v-list>
            <v-list-item
              v-for="(post, index) in posts"
              :key="index"
              @click="navigateToDetail(index)"
            >
              <template v-slot:prepend>
                <v-checkbox
                  v-model="post.completed"
                  @click.stop="togglePostStatus(index, !post.completed)"
                  hide-details
                />
              </template>
              
              <v-list-item-title>{{ post.text }}</v-list-item-title>
              
              <template v-slot:append>
                <v-btn icon="mdi-delete" size="small" @click.stop="removePost(index)">
                </v-btn>
              </template>
            </v-list-item>
          </v-list>
        </v-col>
      </v-row>
    </v-container>
  </template>
  
  <script>
  import { computed, onMounted } from 'vue';
  import { useRouter } from 'vue-router';  // useRouter를 import
  import { useStore } from 'vuex';
  import AddPost from './AddPost.vue';
  
  export default {
    name: 'PostList',
    components: { AddPost },
    setup() {
      const store = useStore();
      const router = useRouter();
  
      const posts = computed(() => store.getters.posts);
      const addPost = (postText) => store.dispatch('addPost', postText);
      const removePost = (index) => store.dispatch('removePost', index);
      const togglePostStatus = (index, completed) =>
        store.dispatch('togglePostStatus', { index, completed });
  
      const navigateToDetail = (index) => {
        // Navigate to post detail page
        router.push({ name: 'PostDetail', params: { id: index } });
      };
  
      onMounted(() => {
        store.dispatch('loadPosts');
      });
  
      return {
        posts,
        addPost,
        removePost,
        togglePostStatus,
        navigateToDetail,
      };
    },
  };
  </script>

 

AddPost.vue

<template>
    <v-text-field
      v-model="newPost"
      label="Add a new post"
      @keyup.enter="submitPost"
      outlined
      dense
    />
    <v-btn color="primary" @click="submitPost">Add</v-btn>
  </template>
  
  <script>
  import { ref } from 'vue';
  
  export default {
    name: 'AddPost',
    emits: ['add-post'],  // 커스텀 이벤트를 정의합니다.
    setup(props, { emit }) {
      const newPost = ref('');
  
      const submitPost = () => {
        if (newPost.value.trim()) {
          emit('add-post', newPost.value);
          newPost.value = '';
        }
      };
  
      return {
        newPost,
        submitPost,
      };
    },
  };
  </script>

 

PostDetail.vue

<template>
    <v-container>
      <h2>Post Detail</h2>
      <v-card>
        <v-card-text>
          <p>ID: {{ id }}</p>
          <p v-if="post">Text: {{ post.text }}</p>
          <p v-else>Post not found</p>
        </v-card-text>
      </v-card>
      <v-btn @click="$router.push('/post')">Back</v-btn>
    </v-container>
  </template>
  
  <script>
  import { computed } from 'vue';
  import { useStore } from 'vuex';
  import { useRoute } from 'vue-router';
  
  export default {
    setup() {
      const store = useStore();
      const route = useRoute();
  
      const id = computed(() => route.params.id);
      const post = computed(() => store.getters['posts'][id.value]);
  
      return {
        id,
        post,
      };
    },
  };
  </script>

 

 

이전에 만들었던 todo List 와 비교하면서 보면 이해가 빠를 겁니다. 



2. Composition API 구성 요소

 

1) setup 함수

 

setup 함수는 Composition API의 핵심으로, 컴포넌트가 생성될 때 호출됩니다. 이 함수 내에서 상태 관리, 메서드 정의, 라이프사이클 훅 등을 설정할 수 있습니다.

 

리턴값: setup 함수에서 반환하는 객체는 템플릿에서 사용됩니다. 이 함수에서 정의한 모든 데이터와 메서드는 setup의 반환 객체를 통해 템플릿에서 접근 가능합니다.

 

2) useStore와 useRouter

 

useStore: Vuex의 스토어에 접근하기 위해 사용됩니다. store 객체를 반환하며, 이를 통해 상태 관리와 관련된 모든 작업을 수행할 수 있습니다.

useRouter: Vue Router에서 제공하는 훅으로, 현재 라우터 인스턴스에 접근하여 라우팅을 처리할 수 있습니다. 예를 들어, 페이지 이동을 위해 router.push를 사용할 수 있습니다.

 

3) computed

 

computed 속성은 반응형 데이터를 정의할 때 사용됩니다. 여기서 posts는 Vuex 스토어에서 가져온 할 일 목록으로, computed로 선언하여 Vue의 반응형 시스템과 연결됩니다.

 

4) onMounted

 

onMounted는 Vue의 라이프사이클 훅 중 하나로, 컴포넌트가 DOM에 마운트된 직후 호출됩니다. 이 훅을 사용하여 컴포넌트가 초기화될 때 필요한 작업을 수행할 수 있습니다. 예를 들어, 이 코드에서는 컴포넌트가 마운트될 때 loadPosts 액션을 디스패치하여 로컬 스토리지에서 데이터를 불러옵니다.

3. 구현된 기능 설명

 

Post 목록 가져오기 (posts): posts는 Vuex의 getters.postscomputed로 받아와, 템플릿에서 렌더링됩니다.

Post 추가하기 (addPost): 사용자가 새로운 포스트를 추가하면, 해당 텍스트가 Vuex 액션을 통해 posts 상태에 추가됩니다.

Post 상태 토글 (togglePostStatus): 체크박스를 클릭하여 포스트의 완료 상태를 토글할 수 있습니다. 이 상태는 v-modelstore.dispatch를 통해 Vuex와 동기화됩니다.

Post 삭제하기 (removePost): 삭제 버튼을 클릭하면 해당 포스트가 삭제됩니다. 이 작업 역시 Vuex 액션을 통해 처리됩니다.

Post 상세보기 페이지로 이동 (navigateToDetail): 포스트 항목을 클릭하면 해당 포스트의 상세 페이지로 라우팅됩니다. router.push를 통해 PostDetail 페이지로 이동하며, id 파라미터를 전달합니다.

 

4. Composition API와 Options API 비교

 

유연성: Composition API는 로직과 상태 관리를 한 곳에 모아서 정의할 수 있으므로, 관련된 코드를 쉽게 그룹화하고 재사용할 수 있습니다.

재사용성: Composition API는 함수로 로직을 캡슐화하여 재사용할 수 있어, 복잡한 컴포넌트에서 더 나은 코드 조직화를 제공합니다.

명확성: setup 함수 안에서 모든 로직을 관리하므로, 상태와 메서드가 어디에서 정의되고 어떻게 사용되는지 명확히 알 수 있습니다.


이전 블로그 
vuex 를 이용한 todo list 작성
https://juntcom.tistory.com/323 

 

vue 가이드 - option, composition api 
https://ko.vuejs.org/guide/introduction.html

 

반응형

'프론트엔드 > Vuejs' 카테고리의 다른 글

vue lifecycle 라이프사이클 정리  (0) 2024.08.18
Vuetify 문서 레퍼런스 가이드  (0) 2024.08.17
vue vuex 란  (0) 2024.08.17
vue to-do 리스트 구현 6 - vuex 구현  (0) 2024.08.17
Vue Router란?  (0) 2024.08.17

+ Recent posts