vue-draggable-next를 활용한 Drag & Drop 구현

심추진·2024년 11월 28일

Nuxt3

목록 보기
3/4
post-thumbnail

이번 프로젝트에서 구현해야 했던 기능은 다음과 같았다. 사용자가 왼쪽 리스트에서 퀘스트를 선택하여 오른쪽 리스트에 추가하거나, 드래그 앤 드롭으로 순서를 변경하는 UI를 제공하는 것이다. 또한, 특정 상태(완료, 진행 중)에 있는 항목은 드래그로 순서를 변경할 수 없도록 해야 했다. 이를 위해 vue-draggable-next 라이브러리를 활용해 기능을 구현했다.

라이브러리 : vue-draggable-next


구현하고자 한 기능

  • 왼쪽: 퀘스트 목록을 서버에서 받아와 표시
  • 오른쪽: 환자에게 등록된 퀘스트를 순서대로 보여줌
  • 사용자가 드래그 앤 드롭으로 순서 변경 가능
  • 특정 상태(완료나 진행 중)의 퀘스트는 드래그 불가
  • 변경된 순서나 추가된 퀘스트를 저장하기 버튼으로 서버에 전송

vue-draggable-next를 활용한 구현

vue-draggable-next는 Vue 3에서 드래그 앤 드롭 기능을 제공하는 가벼운 라이브러리로, 드래그 순서 변경 및 조건부 제어를 쉽게 구현할 수 있다. 이번 프로젝트에서는 이 라이브러리를 사용해 간결하게 요구사항을 만족시켰다.

다음은 주요 구현 코드이다:


<template>
  <VueDraggableNext 
    v-model="quests" 
    @end="onDragEnd" 
    :move="onMove" 
    tag="ul"
  >
    <li 
      v-for="quest in quests" 
      :key="quest.id"
      :class="{ 'non-draggable': quest.status === 'done' || quest.status === 'processing' }"
    >
      <p>{{ quest.title }}</p>
      <button v-if="!quest.status" @click="deleteQuest(quest.id)">삭제</button>
    </li>
  </VueDraggableNext>
</template>

<script setup>
import { VueDraggableNext } from "vue-draggable-next";
import { ref } from "vue";

interface MoveEventContext<T> {
  element: T; // 드래그 중인 또는 대상 아이템
  index: number; // 해당 아이템의 인덱스
}

interface MoveEvent<T> {
  relatedContext: MoveEventContext<T>; // 드래그가 놓이는 대상 컨텍스트
  draggedContext: MoveEventContext<T>; // 드래그 중인 컨텍스트
}

const quests = ref([
  { id: 1, title: "퀘스트 1", status: "todo" },
  { id: 2, title: "퀘스트 2", status: "done" },
  { id: 3, title: "퀘스트 3", status: "processing" },
]);

const onMove = ({ relatedContext, draggedContext }: MoveEvent<QuestOrder>): boolean => {
  const targetItem = relatedContext.element;
  const draggedItem = draggedContext.element;

  // 완료 또는 진행 중 상태의 항목은 이동 불가
  if (targetItem.status === "done" || targetItem.status === "processing") {
    return false;
  }
  return true;
};

const onDragEnd = ({ moved }: { moved?: { newIndex: number; oldIndex: number } }) => {
  if (moved) {
    console.log("퀘스트 순서 변경됨:", quests.value);
  }
};

const deleteQuest = (questId: number) => {
  quests.value = quests.value.filter((quest) => quest.id !== questId);
};
</script>

핵심 구현 요소

v-model로 상태 관리

VueDraggableNext는 배열 상태를 바인딩하여 변경 사항을 자동으로 반영한다.
위 예제에서는 quests를 v-model로 연결해 드래그 후 변경된 순서를 바로 업데이트했다.

onMove로 드래그 제한

onMove 이벤트를 활용해 특정 상태(예: 완료, 진행 중)에 있는 항목은 드래그되지 않도록 제한했다.

onDragEnd로 순서 변경 처리

드래그 완료 시 호출되는 onDragEnd에서 새로운 순서를 서버로 전송하거나 로컬 상태를 업데이트하도록 처리했다.


vue-draggable-next는 Vue 3 환경에서 드래그 앤 드롭을 구현하기에 매우 직관적인 라이브러리였다. 특히, onMove와 onDragEnd 같은 이벤트 핸들러를 통해 드래그 동작을 세밀하게 제어할 수 있었고, 상태 관리에 pinia를 결합해 간결하고 효율적인 코드를 작성할 수 있었다.

profile
Product 개발에 항상 설레는 Web • App 개발자입니다.

0개의 댓글