# 시작하기
처음 `@vuepkg/calendar`를 사용하는 개발자를 위한 단계별 가이드입니다.
---
## 1단계: 설치
```bash
npm install @vuepkg/calendar
```
`main.ts`에 CSS를 한 번 전역 임포트합니다:
```ts
// main.ts
import { createApp } from 'vue'
import '@vuepkg/calendar/style.css' // ← 이 줄이 없으면 스타일이 적용되지 않습니다
import App from './App.vue'
createApp(App).mount('#app')
```
---
## 2단계: 캘린더 표시하기
아래가 동작하는 최소 코드입니다:
```vue
```
> **레이아웃 필수**: 캘린더는 부모 컨테이너를 100% 채웁니다. 부모에 `height`를 지정하지 않으면 높이가 0이 됩니다.
---
## 3단계: 핵심 개념 이해 — 왜 이렇게 작성해야 하나?
### 캘린더는 "표시만" 합니다
`ScheduleCalendar`는 **emit-only** 컴포넌트입니다. 뷰 탭을 클릭하거나 날짜를 이동해도 **캘린더 자신은 상태를 바꾸지 않습니다.** 대신 이벤트(emit)를 발생시키고, 부모가 그 이벤트를 받아 `v-model`을 업데이트해야 화면이 바뀝니다.
```
사용자 클릭
↓
ScheduleCalendar → emit('view-change', { view: 'week' }) → 부모
↓
ScheduleCalendar ← view prop 업데이트 ←────────────────── v-model 갱신
```
이 구조 덕분에 **부모가 모든 상태를 소유**하고 캘린더는 순수하게 UI 역할만 합니다. 서버 상태와 동기화하거나 URL에 상태를 저장하기 쉬워집니다.
### `useScheduleCalendarHost`가 하는 일
v-model 5개 + 이벤트 8개를 직접 연결하면 코드가 길어집니다. `useScheduleCalendarHost`는 이것을 한 번에 처리해 줍니다:
```ts
const {
view, // Ref — 현재 뷰
date, // Ref — 현재 날짜
listFilterDate, // Ref — List 뷰 날짜 필터
viewScope, // Ref — 'my' | 'company'
scheduleTypes, // Ref
calendarListeners // 이벤트 핸들러 객체 → v-on="calendarListeners"
} = useScheduleCalendarHost()
```
`v-on="calendarListeners"`는 Vue의 이벤트 핸들러 spread 문법입니다. 캘린더가 발생시키는 모든 이벤트(`view-change`, `navigate`, `date-select` 등)를 자동으로 연결합니다.
---
## 4단계: API에서 일정 가져오기
뷰나 날짜가 바뀔 때마다 `query-change` 이벤트가 발생합니다. `onQueryChange` 옵션으로 API 호출 로직을 연결하세요:
```vue
```
`query-change`는 다음 시점에 발생합니다:
| 시점 | `payload.trigger` |
| ---- | ---- |
| 컴포넌트 마운트 시 최초 1회 | `'init'` |
| ‹ › · Today 네비 | `'navigate'` |
| 뷰 탭 전환 | `'view-change'` |
| viewScope · scheduleTypes 필터 변경 | `'filter-change'` |
| List 날짜 필터 해제 | `'list-filter-clear'` |
`trigger === 'init'`일 때는 컴포넌트가 처음 로드되는 시점이므로, 이 한 번의 호출로 초기 데이터를 가져옵니다.
---
## 5단계: 일정 추가 / 수정 연결
### 빈 시간 슬롯 클릭 → 일정 생성
Week·Day 뷰에서 빈 영역을 클릭하면 `time-slot-select` 이벤트가 발생합니다:
```ts
const { view, date, listFilterDate, viewScope, scheduleTypes, calendarListeners } =
useScheduleCalendarHost({
onTimeSlotSelect(payload) {
// payload.start, payload.end — 클릭한 1시간 슬롯
openCreateDialog({
start: payload.start,
end: payload.end,
})
},
})
```
### 일정 클릭 → 상세/수정
```ts
useScheduleCalendarHost({
onScheduleClick(payload) {
// payload.schedule — 클릭한 일정
openEditDialog(payload.schedule)
},
})
```
### 일정 CRUD 헬퍼
```ts
import {
upsertSchedule,
removeSchedule,
buildScheduleFromDraft,
createScheduleId,
type ScheduleDraft,
} from '@vuepkg/calendar'
const allSchedules = ref([])
// 새 일정 추가
function handleCreate(draft: ScheduleDraft) {
const newSchedule = buildScheduleFromDraft({ ...draft, id: createScheduleId() })
allSchedules.value = upsertSchedule(allSchedules.value, newSchedule)
}
// 기존 일정 수정
function handleUpdate(draft: ScheduleDraft & { id: string }) {
const updated = buildScheduleFromDraft(draft)
allSchedules.value = upsertSchedule(allSchedules.value, updated)
}
// 일정 삭제
function handleDelete(id: string) {
allSchedules.value = removeSchedule(allSchedules.value, id)
}
```
---
## 6단계: 커스터마이징
### 커스텀 일정 타입 추가
기본 제공 타입(`my_schedule`, `team_schedule`, `company_schedule`) 외에 도메인 타입을 추가하려면 `SCHEDULE_TYPE_OPTIONS`를 spread해서 전달합니다:
```ts
import { SCHEDULE_TYPE_OPTIONS, type ScheduleTypeOption } from '@vuepkg/calendar'
const scheduleTypeOptions: ScheduleTypeOption[] = [
...SCHEDULE_TYPE_OPTIONS,
{ type: 'project', label: '프로젝트', color: '#fff', backgroundColor: '#6366f1' },
{ type: 'leave', label: '휴가', color: '#fff', backgroundColor: '#f59e0b' },
]
```
```vue
```
### 공휴일·기념일
**사내 기념일만** (가장 단순):
```vue
```
**한국 공공 API + 사내 기념일 병합** (opt-in):
```vue
```
공공 API를 사용하려면 same-origin 프록시 또는 BFF가 필요합니다. 자세한 설정은 [통합 가이드](./integration.md)를 참고하세요.
### 뷰 고정 임베딩
특정 뷰만 표시하고 툴바를 숨기려면:
```vue
```
### 테마 커스터마이징
모든 색상·크기·간격은 CSS 변수(`--vp-*`)로 정의되어 있습니다. `:root`에서 원하는 값만 덮어쓰세요:
```css
:root {
--vp-color-primary: #7c3aed; /* 강조 색상 */
--vp-today-badge-bg: #7c3aed; /* 오늘 뱃지 */
--vp-holiday-chip-bg: #fef3c7; /* 공휴일 칩 배경 */
--vp-holiday-chip-color: #92400e; /* 공휴일 칩 텍스트 */
}
```
다크 모드는 시스템 설정(`prefers-color-scheme: dark`) 자동 반영 또는 `.vp-dark` 클래스로 수동 전환할 수 있습니다.
토큰 전체 목록과 다크 모드 설정법은 [테마 커스터마이징 가이드](./theming.md)를 참고하세요.
---
## 전체 예시 (실전 패턴)
```vue
```
---
## 다음 단계
| 문서 | 내용 |
| ---- | ---- |
| [통합 가이드](./integration.md) | 소스 복사 이식, 공휴일 프록시 설정 |
| [테마 커스터마이징](./theming.md) | CSS 변수 토큰 전체 목록, 다크 모드 설정 |
| [API 레퍼런스](../dev/architecture.md) | 전체 Props · Emits · 타입 정의 |
| [배포 가이드](../dev/npm-publish-guide.md) | npm 배포 체크리스트 |