검색

레이블이 Vite인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Vite인 게시물을 표시합니다. 모든 게시물 표시

2023년 4월 12일

코딩 - Vuttify 3 (Vue 3 + Typescript + Vite ) : 무료 템플릿을 이용한 관리자 데시보드 프로그램 개발 시작하기

 ◼︎ 환경 

  • Model : MacBook Pro (14-inch, 2021)
  • CPU : Apple M1 Pro
  • MENORY : 16GB
  • DISK : 512 GB SSD
  • OS : macOS 13.2.1 (22D68)
  • TOOLS : Visual Studio Code, Git


Vuetify 프로젝트를 아래와 같이 yarn 명령을 사용하여 생성한다.

yarn create vuetify 



프로젝트를 Code 에서 확인하면 아래와 같이 개발을 쉽게 진행할 수 있도록 잘정리된  파일 구조를 확인할 수 있다.


터미널에서 npm run dev 명령을 입력하여 실행 프로젝트를 실행해 볼 수 있다.  

만일 Vue3 기술을 기반으로 하는 관리자 웹을 고려하고 있다면 무료 Modernize Free Vuetify + Vue js Admin Dashboard 템플릿 사용을 고려할 수 있다.  조금만 수정하면 아주 쉽게 관리자 웹  프로그램 개발을 시작할 수 있어 생산성에 많은 도움을 준다.



프로젝트 폴더 구성 역시 잘 구분되어 있어 바로 사용해도 무방할 것 같다.


   

2023년 3월 8일

코딩 - Vue 3 + Typescript + Vite + Vuetify 3.x 로 시작하는 웹 프로그램 : 사용자 정의 콤포넌트

컴포넌트를 사용하면 UI를 독립적이고 재사용 가능한 조각으로 분할하고 각 조각을 독립적으로 생각할 수 있다. 일반적으로 앱은 중첩된 컴포넌트의 트리로 구성된다.

사용자 정의 콤포넌트를 작성할떄 가장 고민되는 것이 부모 콤포넌트와 자식 콤포넌트 사이에 정보 교환인데 보통 아래 규칙을 따른다.

❶ 부모 > 컴포넌트 : Props 를 통하여 전달한다.
❷ 컴포넌트 > 부모 : 이벤트를 발생 시켜 데이터를 전달한다.
❸ 전역 : 전체 프로그램에서 공유가 필요한 데이터의 경우는 pinia Store 를 사용한다.

다음 예시는 이미지 목록을 사용자 정의 컴포넌트 사용하여 구현한 예이다.
  • /views/Photos.vue : 이미지 목록.
  • /components/PhotoCard.vue : 목록에 보여지는 사용자 정의 컴포넌트.
  • /store/photos.store.ts : 이미지 데이터를 위한 Store.

❶ Props 

 v-bind  를 사용해서 부모의 값을 props 에 바인딩 할 수 있다. 부모의 값이 변경되면 동적으로 하위(자식 컴포넌트)  값도 변경된다.  
 
<PhotoCard v-bind:image="image" @imageEditEvent="edit" @imageViewEvent="view"></PhotoCard>

 v-bind  를 단축하여 아래와 같이 사용할 수 도 있다.

<PhotoCard :image="image" @imageEditEvent="edit" @imageViewEvent="view"></PhotoCard>

props 는 단반향 바인딩 만을 지원하는데, 이는 자식 컴포넌트가 실수로 부모 콤포넌트의 값을 변경하는 것을 막기 위함이다.  props 값을 변경해야 할 필요가 있는 경우 ⑴ 자식 콤포넌트는 초기 값으로 만 사용하고 로컬 값을 생성하여 사용하거나 ⑵ prop 값으로 부터 계산되는 값을 사용하는 것이다. 

⑴ prop 값으로 로컬 값을 초기화하여 사용

const props = defineProps({
image: Object,
})
const localImage = ref(props.image)

⑵ prop 값으로 부터 계산되는 값을 사용

const props = defineProps({ attachment: Object })
const emit = defineEmits(['previewEvent'])
const thumbnailUrl = computed(() => {
return attachments.isAudio(props.attachment) ? attachments.thumbnails.AUDIO :
attachments.getAttachmentUrl(props.attachment,
{ thumbnail: true, width: 300, height: 300 });
})
 
 

❷ 커스텀 이벤트 

커스텀 이벤트를 사용하면 자식 컴포넌트에서 부모에게 값을 전달 할 수 있다. 

자식 컴포넌트 
<template>
<v-btn size="small" color="white" variant="text" icon="mdi-eye"
@click="emit('imageViewEvent', image)"></v-btn>
</template>
<script setup lang="ts">
defineProps({
image: Object,
})
const emit = defineEmits(['imageEditEvent', 'imageViewEvent'])
</script>

부모 컴포넌트
<PhotoCard :image="image" @imageEditEvent="edit" @imageViewEvent="view"></PhotoCard>

⓷ Pinia Store 

Vuex 와 다르게 Pinia 를 라이브러리를 사용하면 아주 쉽게 저장소를 생성하고 전역으로 공유할 수 있다. 
이미지 목록을 가져오는 Photos.vue 컴포넌트에서 fetch 함수를 사용하여 데이터를 가져온다. Store 의 상태는 전역으로 공유가 되기 때문에 다른 뷰로 이동하고 다시 돌아오는 경우에도 Store 가 가지고 있는 정보는 유지되어 사용할 수 있다. 

onMounted 함수 내에서 store에서 정보를 가져오는 코드를 포함하여 구현하는 경우 불필요한 서버 통신을 최소화할 수 있어 편리하게 사용할 수 있다.

import { usePhotosStore } from '@/store/photos.store'
const photos = usePhotosStore()
const images = ref([])
onMounted(async () => {
if (!photos.isLoaded) {
overlay.value = true
photos.setPage(1)
await photos.fetch()
overlay.value = false
}
images.value = photos.photos
})

참고자료

  1. How to use Watch in Vue 3 in Composition API
  2. https://vuejs.org/guide/essentials/watchers.html#basic-example
  3. https://www.zhenghao.io/posts/verify-image-url
  4. 12 VueJS Best Practices for Pro Developers
  5. How To Pass Data Between Components In Vue.js

2023년 2월 6일

코딩 - Vue 3 + Typescript + Vite + Vuetify 3.x 로 시작하는 웹 프로그램 : 반복작업

특정 화면에서 반복적인 작업을 수행해야하는 아래와 같은 경우를 가정해보자. 

  • Index.vue 는 15초를 주기로  새로운 배경 이미지를 보여 준다.

개발은 크게 고민하지 않고 공개된 Unsplash  API 을 활용 이미지 목록을 가져와서 주기적으로 화면의 배경 이미지를 바꿔주었다. 

  • src/store/unsplash.js 
  • src/view/Indes.vue

Index View 에서는 ① mounted 되면  upsplash 에서 가져온 이미지 목록이 있는지 확인하고 없는 경우 fetch 함수를 호출하여 이미지 목록을 가져온다. ② setTimeout 함수를 사용하여 15000 단위로 바탕하면 이미지를 바꿔준다.

위 코드의 문제점은 아래와 같다.

  1. 다른 View 로 이동하더라도 백그라우드에서 ② 작업이 무한 실행된다. 
  2. 다른 View 에서 Index View 로 이동하면 ① 작업을 수행하고 ② 작업을 다시 무한 실행한다.
  3.  불필요한 메모리 누수가 발생한다. 


◼︎ 개발환경 

  • Model : MacBook Pro (14-inch, 2021)
  • CPU : Apple M1 Pro 
  • MENORY : 16GB
  • DISK : 512 GB SSD
  • OS : macOS 13.2 (22D49)

문제 해결

Vue3 Lifecycle 에 따르면 Composition API 에서 setup 은 create 와 같으며 View 가 마운트 되면  (View 가 화면에 보여지면) mounted (onMounted) 가 실행되고 언마우트 되면 (다른 View 로 이동하면) unmounted (onUnmounted)가 실행되는데 이점을 이용하면 Index 가 화면에 보여질 때만 ② 작업을 수행하도록 할 수 있다. 

반복작업은  setInterval() 함수를 사용하고 더이상 반복작업이 필요없는 경우에는 (다른 View 로 이동할 때) , setInterval() 호출시 리턴되는 ID 값을 인자로 clearInterval() 함수를 호출하면 timer 을 초기활 할 수 있다. 



참고자료

코딩 - Vue 3 + Typescript + Vite + Vuetify 3.x 로 시작하는 웹 프로그램 : 로그인

 개발을 조금 쉽게 해보려고 무료로 이용이 가능한  Vuetify 3 - Vite Theme FREE 을 다운로드 하여 사용하였다.  (기본적인 환경만 미리 세팅이 되어 있어  사용할 필요성을 없을 것 같다. 타입스크립트라던지 개발 편의를 위한 설정이라든지 등의 여러 설정을 추가하느라 결과적으로는 더 힘들게 되어 버렸다.)

◼︎ 개발환경 

  • Model : MacBook Pro (14-inch, 2021)
  • CPU : Apple M1 Pro 
  • MENORY : 16GB
  • DISK : 512 GB SSD
  • OS : macOS 13.2 (22D49)

사전 준비

기본 프로젝트는 Vite Theme Free 를 일부 수정 사용하였다. 
  1. 필요없는 부분은 삭제를 하고 (src/plugins/vuetify.js) 전역으로 버튼 등의 UI 을 변경한 부분은 삭제하여 원래의 Vuetify 3 UI 을 사용할 수 있도록 변경. 
  2. 타입스크립트를 사용하기 위하여 js 파일을 ts 로 변경하고 관련 설정을 추가. 
  3. 개발 편의를 목적으로 vite-plugin-checker 플러그인을 추가. 

사용 주요 기술

① Pinia

Pinia 는 Vuejs 코어 팀이 구축한 새로운 상태 관리 라이브러리로 Vuex의 후속 제품이며 Vuex 보다 훨씬 적은 코드로 상태 관리가 가능하며 Vue 3에서 공식 권장되는 라이브러리이다.

Pinia 에서 State(데이터를 의미) 와 비즈니스 로직은 스토어(Store) 을 사용하여 정의되고, 각 스토어(Store) 에는 state, getters, actions 등이 포함한다. 
  • State - Store 에서 관리되는 데이터를 의미. 기존 Vue 구성요소 data 와 동일.
  • Getters - State 및/또는 다른 Getter 에서 파생(계산)된 값을 반환. 기존 Vue 구성요소 computed 와 동일.
  • Actions - 비즈니스 논리 또는 API 호출과 같은 비동기 작업을 실행하는 데 사용. 기존 Vue 구성요소 methods 와 동일.
Pinia 스토어는 원하는 만큼 정의하여 사용할 수 있고 Vue 애플리케이션 어디에서나 전역적으로 접근할 수 있다. (상세 내용은 https://pinia.vuejs.org/core-concepts 참조.)

② Vue Composition API

Vue 3과 함께 제공되는 새로운 Vue Composition API <script setup> 를 사용하여 컴포넌트들이 빌드되도록 하였다. 일단 필요한 부분만 기술하면 되기 때문에 코드가 아주 간격해지는 이점이 있다.  (Vue Composition API에 대한 자세한 내용은 https://vuejs.org/guide/extras/composition-api-faq.html 을 참조.)

③ Vuelidate

입력값에 대한 검사는 Vutify 3 가이드 문서를 참조하여 Vuelidate  을 사용하여 구현하였다.
npm install @vuelidate/core @vuelidate/validators --save
Vuelidate 을 사용하면 비교적 간단하게 입력값 검사 기능을 구현할 수 있다.

④ dotenv

Path: /.env

VITE(이하 비트) 개발 도구 환경에서 dotenv 파일은 서버 호출 API URL 과 같은 다양한 변수 값들을 포함할 수 있다. dotenv 에 정의되는 변수들은 반드시  VITE_ 로 시작하며 Vue 프로그램에서는 import.meta.env.<variable name> 형태로 사용할 수 있다. ( 자세한 것은 Env Variables and Modes | Vite (vitejs.dev) 참고)


VITE_API_URL=http://localhost:4000


로그인 주요 구성 요소및 구현

  • src/views/Login.vue : 로그인 UI 
  • src/components/Alert.vue : 오류 처리 콤포넌트 
  • src/store/auth.store.ts : 인증을 처리하는 스토어
  • src/store/alert.store.ts : 오류 정보를 처리하기 위한 스토어
  • src/router/index.ts : 라우터 메인 
  • src/router/accounts.router.ts : 로그인 라우터 정보 
  • src/App.vue : 메인 UI
  • src/main.ts : 메인 스크립트
로그인은 아래와 같은 로직으로 기반으로 구현된다.  

로그인 시 성공하면 Jwt 토큰과 사용자 정보를 같이 응답 받아 사용하도록 되어 있는데 이부분은 분리하는 것이 보안상 더 나은 선택인 것 같다. 

참고자료

  1. Form validation in Vue 3 in 10 minutes with Vuelidate
  2. Vue 3 + Pinia - User Registration and Login Example & Tutorial
  3. Vue.js의 공식 Store | Pinia
  4. Vue 3 Authentication with JWT, Vuex, Axios and Vue Router