개발여행
Vue 달력 라이브러리 v-calendar의 버그와 대안책 본문
리액트 생태계에 react-calendar가 있듯, Vue 생태계에는 v-calendar 라이브러리가 있다. 현재 깃헙에 수많은 이슈들이 오픈되어 있지만, 간단한 캘린더를 구현할 땐 특별히 큰 문제는 없어서 나도 계속 사용할 것 같다.
다만 v-calendar의 주간 view 컴포넌트에 버그가 있어서 해결하기 위해 이런저런 시도를 해봤고, 그 끝에 나름대로의 대안책을 찾았다.
v-calendar는 view prop을 통해 주 단위로 보여주는 캘린더를 구현할 수 있다. 추가로 attributes prop을 전달하면 캘린더 날짜에 이벤트가 있음을 나타내주는 표시와 팝업도 넣을 수 있다.
그런데 주간 view와 과거 날짜의 이벤트가 포함되어 있는 attributes를 함께 설정하면 제일 오래된 이벤트가 발생한 주를 디폴트로 보여주는 것이다. 아래와 같이 코드를 작성하면 (현 시점) 2024년 7월 둘째주 대신 제일 첫 이벤트가 있는 2017년 10월부터 시작한다.
<script setup lang="ts">
import { Calendar } from "v-calendar"
// v-calendar에 attributes prop으로 전달할 값 (내용 생략)
const attributes = ...
</script>
<template>
<Calendar view="weekly" :attributes="attributes" locale="ko-KR" />
</template>
다행히 <Calendar> 컴포넌트는 시작 지점을 따로 설정하는 initial-page prop도 있어서, 포맷에 맞게 시작 날짜를 객체로 전달하면 위와 같은 문제는 해결할 수 있다.
<script setup lang="ts">
import { Calendar } from "v-calendar"
const attributes = ...
// initial-page prop에 전달할 weekly view의 시작 페이지
const startPage = {
year: new Date().getFullYear(),
month: new Date().getMonth() + 1,
day: new Date().getDate()
}
</script>
<template>
<Calendar view="weekly" :attributes="attributes" :initial-page="startPage" locale="ko-KR" />
</template>
하지만 startPage 객체를 initial-page prop으로 넘겨도 주간 view는 7월 둘째주부터 시작하지 않는다. 아래처럼 7월 첫째주가 캘린더의 시작페이지로 고정된다.
day 값을 바꿔봐도 7월 첫째주가 고정인 것을 보면 day의 값이 무용지물인 버그가 있는 것 같다. 대신 week 값을 전달하면 정상적으로 7월 둘째주가 시작 페이지로 설정되는 것을 확인했다.
day 대신 week을 지정해주면 해결되지만, 자바스크립트의 Date prototype에는 getWeek() 메소드가 없다... 주어진 날짜가 그 달의 몇째 주에 해당하는지는 따로 계산식을 만들어야 한다.
date-fns 라이브러리로 해결
소스코드를 보던 중, v-calendar가 date-fns 라이브러리를 dependency로 사용하고 있다는 것을 알게 됐다. date-fns는 Date 객체를 조작하기 편하도록 각종 메소드를 제공하는데, 그 중 week의 값을 계산해주는 getWeekOfMonth() 메소드도 포함되어 있었다. 근본적인 문제(버그)를 해결한 건 아니지만, 일단 겪고 있던 이슈는 없어졌다.
const startPage = {
year: new Date().getFullYear(),
month: new Date().getMonth() + 1,
week: getWeekOfMonth(new Date())
}
실력이 부족해 라이브러리의 소스코드에서 문제가 되는 부분을 찾진 못했지만, 그 과정에서 또다른 유용한 라이브러리를 알게 된 경험이었던 것 같다. 언젠간 꼭 버그를 직접 해결해 오픈소스 프로젝트에 기여해보고 싶다.
'Frontend' 카테고리의 다른 글
Nuxt 시작하기 (2) | 2024.07.16 |
---|---|
Konva 배우기 (1) (1) | 2024.07.12 |
Vue SFC 컴포넌트의 CSS 적용 방식 (0) | 2024.06.12 |
Vue 배우기 (3) (0) | 2024.06.06 |
Clerk metadata로 어드민 계정 롤 부여하기 (0) | 2024.06.05 |