docs(ko): add Korean docs to the official site (#4052)

pull/4063/head
Niceplugin 4 months ago committed by GitHub
parent 256d742b73
commit f7479ecb16
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -5,6 +5,7 @@ import { zh } from './zh'
import { pt } from './pt' import { pt } from './pt'
import { ru } from './ru' import { ru } from './ru'
import { es } from './es' import { es } from './es'
import { ko } from './ko'
export default defineConfig({ export default defineConfig({
...shared, ...shared,
@ -14,6 +15,6 @@ export default defineConfig({
pt: { label: 'Português', ...pt }, pt: { label: 'Português', ...pt },
ru: { label: 'Русский', ...ru }, ru: { label: 'Русский', ...ru },
es: { label: 'Español', ...es }, es: { label: 'Español', ...es },
ko: { label: '한국어', lang: 'ko-KR', link: 'https://vitepress.vuejs.kr/' } ko: { label: '한국어', ...ko }
} }
}) })

@ -0,0 +1,252 @@
import { createRequire } from 'module'
import { defineConfig, type DefaultTheme } from 'vitepress'
const require = createRequire(import.meta.url)
const pkg = require('vitepress/package.json')
export const ko = defineConfig({
lang: 'ko-KR',
description: 'Vite 및 Vue 기반 정적 사이트 생성기.',
themeConfig: {
nav: nav(),
sidebar: {
'/ko/guide/': { base: '/ko/guide/', items: sidebarGuide() },
'/ko/reference/': { base: '/ko/reference/', items: sidebarReference() }
},
editLink: {
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
text: 'GitHub에서 이 페이지를 편집하세요'
},
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2019-present Evan You'
},
docFooter: {
prev: '이전',
next: '다음'
},
outline: {
label: '이 페이지에서'
},
lastUpdated: {
text: '업데이트 날짜'
},
langMenuLabel: '언어 변경',
returnToTopLabel: '맨 위로 돌아가기',
sidebarMenuLabel: '사이드바 메뉴',
darkModeSwitchLabel: '다크 모드',
lightModeSwitchTitle: '라이트 모드로 변경',
darkModeSwitchTitle: '다크 모드로 변경'
}
})
function nav(): DefaultTheme.NavItem[] {
return [
{
text: '가이드',
link: '/ko/guide/what-is-vitepress',
activeMatch: '/ko/guide/'
},
{
text: '레퍼런스',
link: '/ko/reference/site-config',
activeMatch: '/ko/reference/'
},
{
text: pkg.version,
items: [
{
text: '변경 로그',
link: 'https://github.com/vuejs/vitepress/blob/main/CHANGELOG.md'
},
{
text: '기여',
link: 'https://github.com/vuejs/vitepress/blob/main/.github/contributing.md'
}
]
}
]
}
function sidebarGuide(): DefaultTheme.SidebarItem[] {
return [
{
text: '소개',
collapsed: false,
items: [
{
text: 'VitePress란 무엇인가?',
link: 'what-is-vitepress'
},
{
text: '시작하기',
link: 'getting-started'
},
{
text: '라우팅',
link: 'routing'
},
{
text: '배포하기',
link: 'deploy'
}
]
},
{
text: '글쓰기',
collapsed: false,
items: [
{
text: '마크다운 확장',
link: 'markdown'
},
{
text: '에셋 핸들링',
link: 'asset-handling'
},
{
text: '프론트마터',
link: 'frontmatter'
},
{
text: '마크다운에서 Vue 사용',
link: 'using-vue'
},
{
text: '국제화',
link: 'i18n'
}
]
},
{
text: '사용자 정의',
collapsed: false,
items: [
{
text: '맞춤 테마 사용',
link: 'custom-theme'
},
{
text: '기본 테마 확장',
link: 'extending-default-theme'
},
{
text: '빌드할 때 데이터 로딩',
link: 'data-loading'
},
{
text: 'SSR 호환성',
link: 'ssr-compat'
},
{
text: 'CMS 연결',
link: 'cms'
}
]
},
{
text: '실험적인',
collapsed: false,
items: [
{
text: 'MPA 모드',
link: 'mpa-mode'
},
{
text: '사이트맵 생성',
link: 'sitemap-generation'
}
]
},
{
text: '설정 & API 참조',
base: '/ko/reference/',
link: 'site-config'
}
]
}
function sidebarReference(): DefaultTheme.SidebarItem[] {
return [
{
text: '레퍼런스',
items: [
{ text: '사이트 구성', link: 'site-config' },
{ text: '머리말 구성', link: 'frontmatter-config' },
{ text: '런타임 API', link: 'runtime-api' },
{ text: 'CLI', link: 'cli' },
{
text: '기본 테마',
base: '/ko/reference/default-theme-',
items: [
{ text: '개요', link: 'config' },
{ text: '네비게이션', link: 'nav' },
{ text: '사이드바', link: 'sidebar' },
{ text: '홈 페이지', link: 'home-page' },
{ text: '푸터', link: 'footer' },
{ text: '레이아웃', link: 'layout' },
{ text: '배지', link: 'badge' },
{ text: '팀 페이지', link: 'team-page' },
{ text: '이전 / 다음 링크', link: 'prev-next-links' },
{ text: '편집 링크', link: 'edit-link' },
{ text: '마지막 업데이트 시간', link: 'last-updated' },
{ text: '검색', link: 'search' },
{ text: '카본 광고', link: 'carbon-ads' }
]
}
]
}
]
}
export const search: DefaultTheme.AlgoliaSearchOptions['locales'] = {
ko: {
placeholder: '문서 검색',
translations: {
button: {
buttonText: '검색',
buttonAriaLabel: '검색'
},
modal: {
searchBox: {
resetButtonTitle: '검색 지우기',
resetButtonAriaLabel: '검색 지우기',
cancelButtonText: '취소',
cancelButtonAriaLabel: '취소'
},
startScreen: {
recentSearchesTitle: '검색 기록',
noRecentSearchesText: '최근 검색 없음',
saveRecentSearchButtonTitle: '검색 기록에 저장',
removeRecentSearchButtonTitle: '검색 기록에서 삭제',
favoriteSearchesTitle: '즐겨찾기',
removeFavoriteSearchButtonTitle: '즐겨찾기에서 삭제'
},
errorScreen: {
titleText: '결과를 가져올 수 없습니다',
helpText: '네트워크 연결을 확인하세요'
},
footer: {
selectText: '선택',
navigateText: '탐색',
closeText: '닫기',
searchByText: '검색 기준'
},
noResultsScreen: {
noResultsText: '결과를 찾을 수 없습니다',
suggestedQueryText: '새로운 검색을 시도할 수 있습니다',
reportMissingResultsText: '해당 검색어에 대한 결과가 있어야 합니까?',
reportMissingResultsLinkText: '피드백 보내기 클릭'
}
}
}
}
}

@ -3,6 +3,7 @@ import { search as zhSearch } from './zh'
import { search as ptSearch } from './pt' import { search as ptSearch } from './pt'
import { search as ruSearch } from './ru' import { search as ruSearch } from './ru'
import { search as esSearch } from './es' import { search as esSearch } from './es'
import { search as koSearch } from './ko'
export const shared = defineConfig({ export const shared = defineConfig({
title: 'VitePress', title: 'VitePress',
@ -61,7 +62,13 @@ export const shared = defineConfig({
appId: '8J64VVRP8K', appId: '8J64VVRP8K',
apiKey: 'a18e2f4cc5665f6602c5631fd868adfd', apiKey: 'a18e2f4cc5665f6602c5631fd868adfd',
indexName: 'vitepress', indexName: 'vitepress',
locales: { ...zhSearch, ...ptSearch, ...ruSearch, ...esSearch } locales: {
...zhSearch,
...ptSearch,
...ruSearch,
...esSearch,
...koSearch
}
} }
}, },

@ -0,0 +1,63 @@
# 자산 처리 {#asset-handling}
## 정적 자산 참조하기 {#referencing-static-assets}
모든 Markdown 파일은 Vue 컴포넌트로 컴파일되며 [Vite](https://vitejs.dev/ko/guide/assets.html)에 의해 처리됩니다. 상대 URL을 사용하여 어떠한 자산도 참조할 수 **있으며 해야 합니다**:
```md
![이미지](./image.png)
```
Markdown 파일, 테마의 `*.vue` 컴포넌트, 스타일 및 일반 `.css` 파일에서 정적 자산을 참조할 수 있으며, 절대 공개 경로(프로젝트 루트를 기준으로 함) 또는 상대 경로(파일 시스템을 기준으로 함)를 사용할 수 있습니다. 후자는 Vite, Vue CLI 또는 webpack의 `file-loader`를 사용해 본 적이 있다면 익숙한 동작 방식과 유사합니다.
일반적인 이미지, 미디어, 폰트 파일 유형은 자동으로 자산으로 감지되어 포함됩니다.
::: tip 링크된 파일은 자산으로 취급되지 않음
Markdown 파일 내의 링크로 참조된 PDF 또는 기타 문서는 자동으로 자산으로 취급되지 않습니다. 링크된 파일을 접근 가능하게 만들기 위해서는 수동으로 해당 파일을 프로젝트의 [`public`](#the-public-directory) 디렉토리에 배치해야 합니다.
:::
절대 경로를 포함한 모든 참조된 자산은 생산 빌드에서 해시된 파일 이름으로 출력 디렉토리에 복사됩니다. 참조되지 않은 자산은 복사되지 않습니다. 4kb보다 작은 이미지 자산은 base64 인라인으로 처리됩니다 - 이는 [`vite`](../reference/site-config#vite) 구성 옵션을 통해 설정할 수 있습니다.
모든 **정적** 경로 참조, 절대 경로를 포함하여, 작업 디렉토리 구조를 기반으로 해야 합니다.
## Public 디렉토리 {#the-public-directory}
Markdown이나 테마 컴포넌트에서 직접 참조되지 않은 정적 자산을 제공할 필요가 있거나, 특정 파일을 원본 파일명으로 제공하고 싶은 경우가 있을 수 있습니다. 이러한 파일의 예로는 `robots.txt`, 파비콘, PWA 아이콘이 있습니다.
이 파일들은 [소스 디렉토리](./routing#source-directory) 아래의 `public` 디렉토리에 배치할 수 있습니다. 예를 들어, 프로젝트 루트가 `./docs`이고 기본 소스 디렉토리 위치를 사용한다면, public 디렉토리는 `./docs/public`이 됩니다.
`public`에 배치된 자산은 그대로 출력 디렉토리의 루트로 복사됩니다.
`public`에 배치된 파일을 참조할 때는 루트 절대 경로를 사용해야 한다는 점에 유의하세요 - 예를 들어, `public/icon.png`는 소스 코드에서 항상 `/icon.png`로 참조되어야 합니다.
## 기본 URL {#base-url}
사이트가 루트 URL이 아닌 곳에 배포되는 경우, `.vitepress/config.js`에서 `base` 옵션을 설정해야 합니다. 예를 들어, 사이트를 `https://foo.github.io/bar/`에 배포할 계획이라면, `base``'/bar/'`(항상 슬래시로 시작하고 끝나야 함)로 설정해야 합니다.
모든 정적 자산 경로는 다양한 `base` 구성 값에 맞게 자동으로 처리됩니다. 예를 들어, 마크다운에서 `public` 아래에 있는 자산에 대한 절대 참조가 있는 경우:
```md
![이미지](/image-inside-public.png)
```
이 경우 `base` 구성 값을 변경하더라도 업데이트할 필요가 **없습니다**.
그러나 자산을 동적으로 연결하는 테마 컴포넌트를 작성하는 경우, 예를 들어 테마 구성 값에 기반한 이미지의 `src`가 있는 경우:
```vue
<img :src="theme.logoPath" />
```
이 경우 VitePress에 제공되는 [`withBase` 헬퍼](../reference/runtime-api#withbase)로 경로를 래핑하는 것이 권장됩니다:
```vue
<script setup>
import { withBase, useData } from 'vitepress'
const { theme } = useData()
</script>
<template>
<img :src="withBase(theme.logoPath)" />
</template>
```

@ -0,0 +1,56 @@
---
outline: deep
---
# CMS에 연결하기 {#connecting-to-a-cms}
## 일반 워크플로우 {#general-workflow}
VitePress를 CMS에 연결하는 것은 주로 [동적 라우트](./routing#dynamic-routes)를 중심으로 진행될 것입니다. 진행하기 전에 이것이 어떻게 작동하는지 이해하는 것이 중요합니다.
각 CMS는 다르게 작동하기 때문에, 여기서는 특정 상황에 맞게 조정해야 할 일반적인 워크플로우만 제공할 수 있습니다.
1. CMS에서 인증이 필요한 경우, API 토큰을 저장할 `.env` 파일을 만들고 다음과 같이 로드하세요:
```js
// posts/[id].paths.js
import { loadEnv } from 'vitepress'
const env = loadEnv('', process.cwd())
```
2. CMS에서 필요한 데이터를 가져와 적절한 경로 데이터로 포맷하세요:
```js
export default {
async paths() {
// 필요시 각 CMS 클라이언트 라이브러리 사용
const data = await (await fetch('https://my-cms-api', {
headers: {
// 필요한 경우 토큰
}
})).json()
return data.map(entry => {
return {
params: { id: entry.id, /* 제목, 저자, 날짜 등 */ },
content: entry.content
}
})
}
}
```
3. 페이지에서 콘텐츠를 렌더링하세요:
```md
# {{ $params.title }}
- {{ $params.author }}에 의해 {{ $params.date }}에
<!-- @content -->
```
## 통합 가이드 {#integration-guides}
VitePress와 특정 CMS의 통합에 대한 가이드를 작성한 경우, 아래 "이 페이지 편집" 링크를 사용하여 여기에 제출하세요!

@ -0,0 +1,222 @@
# 사용자 정의 테마 사용하기 {#using-a-custom-theme}
## 테마 해결 {#theme-resolving}
`.vitepress/theme/index.js` 또는 `.vitepress/theme/index.ts` 파일(“테마 엔트리 파일”)을 생성하여 사용자 정의 테마를 활성화할 수 있습니다:
```
.
├─ docs # 프로젝트 루트
│ ├─ .vitepress
│ │ ├─ theme
│ │ │ └─ index.js # 테마 엔트리
│ │ └─ config.js # 설정 파일
│ └─ index.md
└─ package.json
```
VitePress는 테마 엔트리 파일의 존재를 감지하면 기본 테마 대신 항상 사용자 정의 테마를 사용합니다. 하지만 [기본 테마를 확장하여](./extending-default-theme) 그 위에 고급 사용자 정의를 수행할 수 있습니다.
## 테마 인터페이스 {#theme-interface}
VitePress 사용자 정의 테마는 다음 인터페이스를 가진 객체로 정의됩니다:
```ts
interface Theme {
/**
* 모든 페이지의 루트 레이아웃 컴포넌트
* @필수
*/
Layout: Component
/**
* Vue 앱 인스턴스 개선
* @선택적
*/
enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>
/**
* 다른 테마 확장, 우리의 `enhanceApp` 전에 호출
* @선택적
*/
extends?: Theme
}
interface EnhanceAppContext {
app: App // Vue 앱 인스턴스
router: Router // VitePress 라우터 인스턴스
siteData: Ref<SiteData> // 사이트 수준 메타데이터
}
```
테마 엔트리 파일은 테마를 기본으로 내보내야 합니다:
```js
// .vitepress/theme/index.js
// 테마 엔트리에서 Vue 파일을 직접 가져올 수 있습니다
// VitePress는 @vitejs/plugin-vue로 미리 설정되어 있습니다.
import Layout from './Layout.vue'
export default {
Layout,
enhanceApp({ app, router, siteData }) {
// ...
}
}
```
기본 내보내기는 사용자 정의 테마에 대한 유일한 계약이며, `Layout` 속성만 필수입니다. 기술적으로, VitePress 테마는 단일 Vue 컴포넌트만큼 간단할 수 있습니다.
레이아웃 컴포넌트 내부에서는 평소처럼 Vite + Vue 3 애플리케이션처럼 작동합니다. 테마도 [SSR-호환성이](./ssr-compat) 있어야 합니다.
## 레이아웃 만들기 {#building-a-layout}
가장 기본적인 레이아웃 컴포넌트는 [`<Content />`](../reference/runtime-api#content) 컴포넌트를 포함해야 합니다:
```vue
<!-- .vitepress/theme/Layout.vue -->
<template>
<h1>사용자 정의 레이아웃!</h1>
<!-- 마크다운 내용이 여기에 렌더링됩니다 -->
<Content />
</template>
```
위의 레이아웃은 각 페이지의 마크다운을 HTML로 단순히 렌더링합니다. 우리가 추가할 수 있는 첫 번째 개선 사항은 404 오류를 처리하는 것입니다:
```vue{1-4,9-12}
<script setup>
import { useData } from 'vitepress'
const { page } = useData()
</script>
<template>
<h1>사용자 정의 레이아웃!</h1>
<div v-if="page.isNotFound">
사용자 정의 404 페이지!
</div>
<Content v-else />
</template>
```
[`useData()`](../reference/runtime-api#usedata) 헬퍼는 우리가 필요로 하는 모든 런타임 데이터를 제공하여, 다른 레이아웃을 조건부로 렌더링할 수 있습니다. 우리가 접근할 수 있는 또 다른 데이터는 현재 페이지의 프론트매터입니다. 이를 활용하여 사용자가 각 페이지의 레이아웃을 제어할 수 있도록 합니다. 예를 들어, 사용자는 특별한 홈페이지 레이아웃을 사용해야 한다고 지정할 수 있습니다:
```md
---
layout: home
---
```
그리고 우리는 이를 처리하기 위해 테마를 조정할 수 있습니다:
```vue{3,12-14}
<script setup>
import { useData } from 'vitepress'
const { page, frontmatter } = useData()
</script>
<template>
<h1>사용자 정의 레이아웃!</h1>
<div v-if="page.isNotFound">
사용자 정의 404 페이지!
</div>
<div v-if="frontmatter.layout === 'home'">
사용자 정의 홈 페이지!
</div>
<Content v-else />
</template>
```
물론, 레이아웃을 더 많은 컴포넌트로 나눌 수 있습니다:
```vue{3-5,12-15}
<script setup>
import { useData } from 'vitepress'
import NotFound from './NotFound.vue'
import Home from './Home.vue'
import Page from './Page.vue'
const { page, frontmatter } = useData()
</script>
<template>
<h1>사용자 정의 레이아웃!</h1>
<NotFound v-if="page.isNotFound" />
<Home v-if="frontmatter.layout === 'home'" />
<Page v-else /> <!-- <Page />는 <Content />를 렌더링합니다 -->
</template>
```
테마 컴포넌트에서 사용할 수 있는 모든 것에 대한 [런타임 API 참조](../reference/runtime-api)를 참조하세요. 또한, [빌드할 때 데이터 로딩](./data-loading)을 활용하여 데이터 기반 레이아웃을 생성할 수 있습니다 - 예를 들어, 현재 프로젝트 내 모든 블로그 포스트를 나열하는 페이지 등.
## 사용자 정의 테마 배포하기 {#distributing-a-custom-theme}
사용자 정의 테마를 배포하는 가장 쉬운 방법은 [GitHub에서 템플릿 저장소로 제공하는 것입니다](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-template-repository).
npm 패키지로 테마를 배포하려면 다음 단계를 따르세요:
1. 패키지 엔트리에서 테마 객체를 기본 내보내기로 내보냅니다.
2. 적용된다면, 테마 설정 타입 정의를 `ThemeConfig`로 내보냅니다.
3. 테마가 VitePress 설정을 조정해야 하는 경우, 사용자가 확장할 수 있도록 패키지 하위 경로(예: `my-theme/config`)에 해당 설정을 내보냅니다.
4. 설정 파일 및 프론트매터를 통한 테마 설정 옵션을 문서화합니다.
5. 테마를 소비하는 방법에 대한 명확한 지침을 제공합니다(아래 참조).
## 사용자 정의 테마 소비하기 {#consuming-a-custom-theme}
외부 테마를 소비하려면 사용자 정의 테마 엔트리에서 가져와서 다시 내보냅니다:
```js
// .vitepress/theme/index.js
import Theme from 'awesome-vitepress-theme'
export default Theme
```
테마를 확장해야 하는 경우:
```js
// .vitepress/theme/index.js
import Theme from 'awesome-vitepress-theme'
export default {
extends: Theme,
enhanceApp(ctx) {
// ...
}
}
```
테마가 특별한 VitePress 설정을 요구하는 경우, 자신의 설정에서도 그 설정을 확장해야 합니다:
```ts
// .vitepress/config.ts
import baseConfig from 'awesome-vitepress-theme/config'
export default {
// 필요한 경우 테마 기본 설정 확장
extends: baseConfig
}
```
마지막으로, 테마가 테마 설정에 대한 타입을 제공하는 경우:
```ts
// .vitepress/config.ts
import baseConfig from 'awesome-vitepress-theme/config'
import { defineConfigWithTheme } from 'vitepress'
import type { ThemeConfig } from 'awesome-vitepress-theme'
export default defineConfigWithTheme<ThemeConfig>({
extends: baseConfig,
themeConfig: {
// 타입은 `ThemeConfig`입니다.
}
})
```

@ -0,0 +1,248 @@
# 빌드할 때 데이터 로딩 {#build-time-data-loading}
VitePress는 **데이터 로더**라고 불리는 기능을 제공하여 임의의 데이터를 로드하고 페이지나 컴포넌트에서 가져올 수 있습니다. 데이터 로딩은 **빌드 시간에만 실행**됩니다: 결과적으로 생성된 데이터는 최종 자바스크립트 번들에 JSON으로 직렬화됩니다.
데이터 로더는 원격 데이터를 가져오거나 로컬 파일을 기반으로 메타데이터를 생성하는 데 사용할 수 있습니다. 예를 들어, 모든 로컬 API 페이지를 파싱하고 모든 API 항목의 색인을 자동으로 생성하기 위해 데이터 로더를 사용할 수 있습니다.
## 기본 사용법 {#basic-usage}
데이터 로더 파일은 `.data.js` 또는 `.data.ts`로 끝나야 합니다. 이 파일은 `load()` 메서드를 가진 객체를 기본 내보내기해야 합니다:
```js
// example.data.js
export default {
load() {
return {
hello: 'world'
}
}
}
```
로더 모듈은 Node.js에서만 평가되므로, 필요에 따라 Node API와 npm 종속성을 가져올 수 있습니다.
이 파일에서 데이터를 `.md` 페이지와 `.vue` 컴포넌트에서 `data`라는 이름으로 내보낼 수 있습니다:
```vue
<script setup>
import { data } from './example.data.js'
</script>
<pre>{{ data }}</pre>
```
출력:
```json
{
"hello": "world"
}
```
데이터 로더 자체가 `data`를 내보내지 않는 것을 알 수 있습니다. 이는 VitePress가 내부에서 `load()` 메서드를 호출하고 `data`라는 이름으로 결과를 암시적으로 노출한다는 것을 의미합니다.
로더가 비동기인 경우에도 작동합니다:
```js
export default {
async load() {
// 원격 데이터 가져오기
return (await fetch('...')).json()
}
}
```
## 로컬 파일에서 데이터 가져오기 {#data-from-local-files}
로컬 파일을 기반으로 데이터를 생성해야 할 때는 데이터 로더에서 `watch` 옵션을 사용해야 합니다. 그래야 해당 파일에 변경 사항이 발생했을 때 핫 업데이트를 트리거할 수 있습니다.
`watch` 옵션은 또한 여러 파일을 일치시키기 위해 [글로브 패턴](https://github.com/mrmlnc/fast-glob#pattern-syntax)을 사용할 수 있어 편리합니다. 패턴은 로더 파일 자체에 상대적이며, `load()` 함수는 일치한 파일을 절대 경로로 받습니다.
다음 예제는 [csv-parse](https://github.com/adaltas/node-csv/tree/master/packages/csv-parse/)를 사용하여 CSV 파일을 불러오고 JSON으로 변환하는 방법을 보여줍니다. 이 파일은 빌드 시간에만 실행되므로, CSV 파서를 클라이언트에 전송하지 않을 것입니다!
```js
import fs from 'node:fs'
import { parse } from 'csv-parse/sync'
export default {
watch: ['./data/*.csv'],
load(watchedFiles) {
// watchedFiles는 일치하는 파일의 절대 경로 배열이 될 것입니다.
// 블로그 포스트 메타데이터의 배열을 생성하여
// 테마 레이아웃에서 목록을 렌더링하는 데 사용할 수 있습니다
return watchedFiles.map((file) => {
return parse(fs.readFileSync(file, 'utf-8'), {
columns: true,
skip_empty_lines: true
})
})
}
}
```
## `createContentLoader`
콘텐츠 중심 사이트를 구축할 때, 우리는 종종 "아카이브" 또는 "인덱스" 페이지를 만들 필요가 있습니다: 우리 콘텐츠 컬렉션에서 사용 가능한 모든 항목을 나열하는 페이지, 예를 들어 블로그 게시물이나 API 페이지의 경우입니다. 데이터 로더 API를 직접 사용하여 이를 구현할 **수 있지만**, 이는 흔한 사용 사례이므로 VitePress는 이를 단순화하기 위해 `createContentLoader` 헬퍼를 제공합니다:
```js
// posts.data.js
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', /* 옵션 */)
```
헬퍼는 [소스 디렉토리](./routing#source-directory)에 상대적인 글로브 패턴을 취하며, 기본 내보내기로 사용할 수 있는 `{ watch, load }` 데이터 로더 객체를 반환합니다. 이는 또한 파일 수정 타임스탬프를 기반으로 캐싱을 구현하여 개발 성능을 향상시킵니다.
로더는 마크다운 파일과만 작동합니다 - 마크다운이 아닌 일치하는 파일은 건너뜁니다.
로드된 데이터는 `ContentData[]` 타입의 배열일 것입니다:
```ts
interface ContentData {
// 페이지의 매핑된 URL입니다. 예: /posts/hello.html (base는 포함하지 않음)
// 수동으로 반복하거나 사용자 정의 `transform`을 사용하여 경로를 정규화하세요
url: string
// 페이지의 프론트매터 데이터
frontmatter: Record<string, any>
// 다음은 관련 옵션이 활성화되어 있을 때만 존재합니다
// 아래에서 이에 대해 논의할 것입니다
src: string | undefined
html: string | undefined
excerpt: string | undefined
}
```
기본적으로 `url``frontmatter`만 제공됩니다. 로드된 데이터는 클라이언트 번들에 JSON으로 인라인되기 때문에 크기에 대해 신중해야 합니다. 다음은 데이터를 사용하여 최소한의 블로그 인덱스 페이지를 구축하는 예입니다:
```vue
<script setup>
import { data as posts } from './posts.data.js'
</script>
<template>
<h1>모든 블로그 게시물</h1>
<ul>
<li v-for="post of posts">
<a :href="post.url">{{ post.frontmatter.title }}</a>
<span>by {{ post.frontmatter.author }}</span>
</li>
</ul>
</template>
```
### 옵션 {#options}
기본 데이터가 모든 요구 사항에 맞지 않을 수 있습니다 - 옵션을 사용하여 데이터를 변환할 수 있습니다:
```js
// posts.data.js
import { createContentLoader } from 'vitepress'
export default createContentLoader('posts/*.md', {
includeSrc: true, // 원시 마크다운 소스를 포함시킬까요?
render: true, // 완성된 전체 페이지 HTML을 렌더링하여 포함시킬까요?
excerpt: true, // 발췌문을 포함시킬까요?
transform(rawData) {
// 원하는 대로 원시 데이터를 매핑, 정렬 또는 필터링하세요.
// 최종 결과가 클라이언트에 전송될 것입니다.
return rawData.sort((a, b) => {
return +new Date(b.frontmatter.date) - +new Date(a.frontmatter.date)
}).map((page) => {
page.src // 원시 마크다운 소스
page.html // 렌더링된 전체 페이지 HTML
page.excerpt // 렌더링된 발췌문 HTML (`---` 위의 내용)
return {/* ... */}
})
}
})
```
[Vue.js 블로그](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts)에서 사용되는 방법을 확인하세요.
`createContentLoader` API는 [빌드 후크](../reference/site-config#build-hooks) 내에서도 사용될 수 있습니다:
```js
// .vitepress/config.js
export default {
async buildEnd() {
const posts = await createContentLoader('posts/*.md').load()
// 포스트 메타데이터를 기반으로 파일 생성하기, 예: RSS 피드
}
}
```
**타입**
```ts
interface ContentOptions<T = ContentData[]> {
/**
* src를 포함시킬까요?
* @default false
*/
includeSrc?: boolean
/**
* src를 HTML로 렌더링하고 데이터에 포함시킬까요?
* @default false
*/
render?: boolean
/**
* `boolean`인 경우, 발췌문을 구문 분석하고 포함할지 여부입니다. (HTML로 렌더링됨)
*
* `function`인 경우, 콘텐츠에서 발췌문이 추출되는 방식을 제어합니다.
*
* `string`인 경우, 발췌문을 추출하는 데 사용되는 사용자 정의 구분자를 정의합니다.
* `excerpt``true`인 경우 기본 구분자는 `---`입니다.
*
* @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt
* @see https://github.com/jonschlinkert/gray-matter#optionsexcerpt_separator
*
* @default false
*/
excerpt?:
| boolean
| ((file: { data: { [key: string]: any }; content: string; excerpt?: string }, options?: any) => void)
| string
/**
* 데이터를 변환하십시오. 컴포넌트나 마크다운 파일에서 가져올 경우,
* 데이터는 클라이언트 번들에 JSON으로 인라인될 것입니다.
*/
transform?: (data: ContentData[]) => T | Promise<T>
}
```
## 타입된 데이터 로더 {#typed-data-loaders}
TypeScript를 사용할 때, 다음과 같이 로더와 `data` 내보내기를 타입할 수 있습니다:
```ts
import { defineLoader } from 'vitepress'
export interface Data {
// 데이터 타입
}
declare const data: Data
export { data }
export default defineLoader({
// 타입 검사된 로더 옵션
watch: ['...'],
async load(): Promise<Data> {
// ...
}
})
```
## 구성 {#configuration}
로더 내부에서 구성 정보를 가져오려면 다음과 같은 코드를 사용할 수 있습니다:
```ts
import type { SiteConfig } from 'vitepress'
const config: SiteConfig = (globalThis as any).VITEPRESS_CONFIG
```

@ -0,0 +1,337 @@
---
outline: deep
---
# VitePress 사이트 배포하기 {#deploy-your-vitepress-site}
다음 가이드는 몇 가지 공유된 가정을 바탕으로 합니다:
- VitePress 사이트는 프로젝트의 `docs` 디렉토리 안에 있습니다.
- 기본 빌드 출력 디렉토리(`.vitepress/dist`)를 사용하고 있습니다.
- VitePress를 프로젝트의 로컬 의존성으로 설치했으며, `package.json`에 다음 스크립트를 설정했습니다:
```json
{
"scripts": {
"docs:build": "vitepress build docs",
"docs:preview": "vitepress preview docs"
}
}
```
## 로컬에서 빌드하고 테스트하기 {#build-and-test-locally}
1. 이 명령어를 실행하여 문서를 빌드합니다:
```sh
$ npm run docs:build
```
2. 빌드가 완료되면, 다음 명령어를 실행하여 로컬에서 미리보기를 합니다:
```sh
$ npm run docs:preview
```
`preview` 명령어는 `.vitepress/dist` 출력 디렉토리를 `http://localhost:4173`에서 제공하는 로컬 정적 웹 서버를 부팅합니다. 이를 사용하여 프로덕션에 푸시하기 전에 모든 것이 잘 보이는지 확인할 수 있습니다.
3. `--port` 인수를 전달하여 서버의 포트를 구성할 수 있습니다.
```json
{
"scripts": {
"docs:preview": "vitepress preview docs --port 8080"
}
}
```
이제 `docs:preview` 메소드가 `http://localhost:8080`에서 서버를 시작합니다.
## public 기본 경로 설정하기 {#setting-a-public-base-path}
기본적으로, 사이트가 도메인의 루트 경로(`/`)에서 배포될 것으로 가정합니다. 사이트가 하위 경로, 예를 들어 `https://mywebsite.com/blog/`에서 제공되는 경우, VitePress 구성에서 [`base`](../reference/site-config#base) 옵션을 `'/blog/'`로 설정해야 합니다.
**예:** GitHub(또는 GitLab) 페이지를 사용하여 `user.github.io/repo/`로 배포하는 경우, `base``/repo/`로 설정하세요.
## HTTP 캐시 헤더 {#http-cache-headers}
프로덕션 서버에서 HTTP 헤더를 제어할 수 있다면, 반복 방문 시 성능을 향상시키기 위해 `cache-control` 헤더를 구성할 수 있습니다.
프로덕션 빌드는 정적 자산(JavaScript, CSS, `public`에 있지 않은 다른 가져온 자산)을 위해 해시된 파일 이름을 사용합니다. 브라우저 개발 도구의 네트워크 탭을 사용하여 프로덕션 미리보기를 검사하면, `app.4f283b18.js`와 같은 파일을 볼 수 있습니다.
`4f283b18` 해시는 이 파일의 내용에서 생성됩니다. 같은 해시된 URL은 항상 동일한 파일 내용을 제공하도록 보장됩니다 - 내용이 변경되면 URL도 변경됩니다. 이는 이러한 파일에 대해 가장 강력한 캐시 헤더를 안전하게 사용할 수 있음을 의미합니다. 이러한 모든 파일이 출력 디렉토리의 `assets/` 아래에 배치되므로, 그들을 위해 다음 헤더를 구성할 수 있습니다:
```
Cache-Control: max-age=31536000,immutable
```
::: details Netlify `_headers` 파일 예시
```
/assets/*
cache-control: max-age=31536000
cache-control: immutable
```
참고: `_headers` 파일은 [public 디렉토리](./asset-handling#the-public-directory)에 배치해야 합니다 - 우리의 경우, `docs/public/_headers` - 출력 디렉토리에 그대로 복사되도록 하기 위해서입니다.
[Netlify 사용자 정의 헤더 문서](https://docs.netlify.com/routing/headers/)
:::
::: details `vercel.json` 내의 Vercel 설정 예시
```json
{
"headers": [
{
"source": "/assets/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "max-age=31536000, immutable"
}
]
}
]
}
```
참고: `vercel.json` 파일은 **리포지토리**의 루트에 위치해야 합니다.
[Vercel 헤더 설정에 대한 문서](https://vercel.com/docs/concepts/projects/project-configuration#headers)
:::
## 플랫폼 가이드 {#platform-guides}
### Netlify / Vercel / Cloudflare Pages / AWS Amplify / Render
새 프로젝트를 설정하고 대시보드를 사용하여 이 설정을 변경하세요:
- **빌드 명령어:** `npm run docs:build`
- **출력 디렉토리:** `docs/.vitepress/dist`
- **노드 버전:** `18` (또는 그 이상)
::: warning
HTML 코드에 대해 _Auto Minify_와 같은 옵션을 활성화하지 마세요. Vue에 의미를 가진 주석이 제거될 수 있습니다. 제거되면 수화 불일치 오류가 발생할 수 있습니다.
:::
### GitHub Pages
1. 프로젝트의 `.github/workflows` 디렉토리 안에 `deploy.yml`이라는 파일을 생성하고 다음과 같은 내용을 넣으세요:
```yaml
# GitHub Pages에 VitePress 사이트를 빌드하고 배포하기 위한 샘플 워크플로우
#
name: Deploy VitePress site to Pages
on:
# `main` 브랜치를 대상으로 하는 푸시에 대해 실행합니다. 기본 브랜치로 `master`
# 사용하는 경우, 이를 `master`로 변경하세요.
push:
branches: [main]
# Actions 탭에서 이 워크플로우를 수동으로 실행할 수 있도록 허용합니다.
workflow_dispatch:
# GitHub Pages에 배포를 허용하기 위해 GITHUB_TOKEN의 권한을 설정합니다.
permissions:
contents: read
pages: write
id-token: write
# 동시에 하나의 배포만 허용하며, 진행 중인 실행과 최신 대기열 사이에 대기열에 있는 실행을 건너뛰기.
# 그러나, 이러한 프로덕션 배포를 완료하도록 진행 중인 실행을 취소하지는 마세요.
concurrency:
group: pages
cancel-in-progress: false
jobs:
# 빌드 작업
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # lastUpdated가 활성화되어 있지 않다면 필요 없습니다
# - uses: pnpm/action-setup@v3 # pnpm을 사용하는 경우 이것을 주석 해제하세요
# - uses: oven-sh/setup-bun@v1 # Bun을 사용하는 경우 이것을 주석 해제하세요
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm # 또는 pnpm / yarn
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Install dependencies
run: npm ci # 또는 pnpm install / yarn install / bun install
- name: Build with VitePress
run: npm run docs:build # 또는 pnpm docs:build / yarn docs:build / bun run docs:build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/.vitepress/dist
# 배포 작업
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
needs: build
runs-on: ubuntu-latest
name: Deploy
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
```
::: warning
VitePress의 `base` 옵션이 제대로 구성되어 있는지 확인하세요. 자세한 내용은 [public 기본 경로 설정하기](#setting-a-public-base-path)를 참조하세요.
:::
2. 저장소 설정에서 "Pages" 메뉴 항목 아래 "빌드 및 배포 > 출처"에서 "GitHub Actions"를 선택하세요.
3. `main` 브랜치에 변경 사항을 푸시하고 GitHub Actions 워크플로우가 완료되기를 기다리세요. 설정에 따라 사이트가 `https://<username>.github.io/[repository]/` 또는 `https://<custom-domain>/`에 배포된 것을 볼 수 있습니다. `main` 브랜치에 푸시할 때마다 사이트가 자동으로 배포됩니다.
### GitLab Pages
1. VitePress 구성에서 `outDir``../public`으로 설정합니다. `https://<username>.gitlab.io/<repository>/`에 배포하려면 `base` 옵션을 `'/<repository>/'`로 구성하세요.
2. 변경 사항을 적용할 때마다 사이트를 빌드하고 배포하도록 하기 위해 프로젝트의 루트에 다음 내용을 가진 `.gitlab-ci.yml` 파일을 생성하세요:
```yaml
image: node:18
pages:
cache:
paths:
- node_modules/
script:
# - apk add git # lastUpdated가 활성화되어 있고 alpine과 같은 작은 도커 이미지를 사용하는 경우 이것을 주석 해제하세요
- npm install
- npm run docs:build
artifacts:
paths:
- public
only:
- main
```
### Azure 정적 Web 앱 {#azure-static-web-apps}
1. [공식 문서](https://docs.microsoft.com/en-us/azure/static-web-apps/build-configuration)를 따르세요.
2. 구성 파일에 이 값을 설정하세요(필요하지 않은 값들, 예를 들어 `api_location` 같은 것은 제거하세요):
- **`app_location`**: `/`
- **`output_location`**: `docs/.vitepress/dist`
- **`app_build_command`**: `npm run docs:build`
### Firebase {#firebase}
1. 프로젝트의 루트에 `firebase.json``.firebaserc`를 생성하세요:
`firebase.json`:
```json
{
"hosting": {
"public": "docs/.vitepress/dist",
"ignore": []
}
}
```
`.firebaserc`:
```json
{
"projects": {
"default": "<YOUR_FIREBASE_ID>"
}
}
```
2. `npm run docs:build`를 실행한 후, 배포하려면 이 명령어를 실행하세요:
```sh
firebase deploy
```
### Surge
1. `npm run docs:build`를 실행한 후, 배포하기 위해 이 명령어를 실행하세요:
```sh
npx surge docs/.vitepress/dist
```
### Heroku
1. [`heroku-buildpack-static`](https://elements.heroku.com/buildpacks/heroku/heroku-buildpack-static)에 주어진 문서 및 가이드를 따르세요.
2. 프로젝트의 루트에 아래 내용을 가진 `static.json` 파일을 생성하세요:
```json
{
"root": "docs/.vitepress/dist"
}
```
### Edgio
[Edgio에 VitePress 앱 생성 및 배포하기](https://docs.edg.io/guides/vitepress)를 참조하세요.
### Kinsta 정적 사이트 호스팅 {#kinsta-static-site-hosting}
[Kinsta](https://kinsta.com/static-site-hosting/)에서 VitePress 웹사이트를 배포하는 방법은 [이 지침](https://kinsta.com/docs/vitepress-static-site-example/)을 따르세요.
### 스톰킷
VitePress 프로젝트를 [Stormkit](https://www.stormkit.io)에 배포하려면 이 [지침](https://stormkit.io/blog/how-to-deploy-vitepress)을 따르세요.
### Nginx
다음은 Nginx 서버 블록 구성의 예입니다. 이 설정에는 일반적인 텍스트 기반 자산에 대한 gzip 압축, 적절한 캐싱 헤더로 VitePress 사이트의 정적 파일을 제공하는 규칙, `cleanUrls: true`를 처리하는 규칙이 포함되어 있습니다.
```nginx
server {
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
listen 80;
server_name _;
index index.html;
location / {
# 내용 위치
root /app;
# 정확한 일치 -> 깨끗한 URL로 처리 -> 폴더 -> 찾을 수 없음
try_files $uri $uri.html $uri/ =404;
# 존재하지 않는 페이지
error_page 404 /404.html;
# index.html이 없는 폴더는 이 설정에서 403을 발생시킴
error_page 403 /404.html;
# 캐싱 헤더 조정
# assets 폴더의 파일은 해시 파일 이름을 가짐
location ~* ^/assets/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
}
```
이 구성은 빌드된 VitePress 사이트가 서버상의 `/app` 디렉토리에 위치한다고 가정합니다. 사이트 파일이 다른 곳에 위치한 경우 `root` 지시문을 그에 맞게 조정하세요.
::: warning index.html을 기본값으로 설정하지 마세요.
try_files 해결은 다른 Vue 애플리케이션처럼 index.html로 기본 설정되어서는 안 됩니다. 이것은 유효하지 않은 페이지 상태로 이어질 것입니다.
:::
추가 정보는 [공식 nginx 문서](https://nginx.org/en/docs/), 이슈 [#2837](https://github.com/vuejs/vitepress/discussions/2837), [#3235](https://github.com/vuejs/vitepress/issues/3235) 그리고 Mehdi Merah의 [블로그 포스트](https://blog.mehdi.cc/articles/vitepress-cleanurls-on-nginx-environment#readings)에서 찾을 수 있습니다.

@ -0,0 +1,341 @@
---
outline: deep
---
# 기본 테마 확장하기 {#extending-the-default-theme}
VitePress의 기본 테마는 문서화에 최적화되어 있으며, 커스터마이징이 가능합니다. [기본 테마 구성 개요](../reference/default-theme-config)를 참조하여 가능한 옵션의 전체 목록을 확인하세요.
그러나 설정만으로는 충분하지 않은 경우가 여러 번 있을 수 있습니다. 예를 들면:
1. CSS 스타일링을 조정해야 할 때;
2. 전역 컴포넌트 등록과 같이 Vue 앱 인스턴스를 수정해야 할 때;
3. 레이아웃 슬롯을 통해 테마에 사용자 정의 컨텐츠를 삽입해야 할 때.
이러한 고급 커스터마이징은 기본 테마를 "확장하는" 사용자 지정 테마를 사용해야 합니다.
::: tip
진행하기 전에, 사용자 지정 테마가 어떻게 작동하는지 이해하기 위해 [사용자 지정 테마 사용하기](./custom-theme)를 먼저 읽어보세요.
:::
## CSS 커스터마이징하기 {#customizing-css}
기본 테마의 CSS는 루트 레벨 CSS 변수를 오버라이딩하여 커스터마이즈 할 수 있습니다:
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import './custom.css'
export default DefaultTheme
```
```css
/* .vitepress/theme/custom.css */
:root {
--vp-c-brand-1: #646cff;
--vp-c-brand-2: #747bff;
}
```
오버라이딩할 수 있는 [기본 테마 CSS 변수](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css)를 확인하세요.
## 다른 폰트 사용하기 {#using-different-fonts}
VitePress는 기본 폰트로 [Inter](https://rsms.me/inter/)를 사용하며, 빌드 출력물에 폰트를 포함합니다. 또한, 이 폰트는 프로덕션 환경에서 자동으로 프리로드됩니다. 하지만, 다른 메인 폰트를 사용하고 싶은 경우에는 바람직하지 않을 수 있습니다.
빌드 출력물에서 Inter를 포함하지 않으려면, 대신 `vitepress/theme-without-fonts`에서 테마를 임포트하세요:
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme-without-fonts'
import './my-fonts.css'
export default DefaultTheme
```
```css
/* .vitepress/theme/custom.css */
:root {
--vp-font-family-base: /* 일반 텍스트 폰트 */
--vp-font-family-mono: /* 코드 폰트 */
}
```
::: warning
[팀 페이지](../reference/default-theme-team-page)와 같은 선택적 컴포넌트를 사용하는 경우, 이들도 `vitepress/theme-without-fonts`에서 가져와야 합니다!
:::
폰트가 `@font-face`를 통해 참조된 로컬 파일이라면, 자산으로 처리되어 해시된 파일명과 함께 `.vitepress/dist/assets` 아래에 포함될 것입니다. 이 파일을 프리로드하려면, [transformHead](../reference/site-config#transformhead) 빌드 훅을 사용하세요:
```js
// .vitepress/config.js
export default {
transformHead({ assets }) {
// 폰트를 매칭하기 위해 정규식을 적절히 조정하세요
const myFontFile = assets.find(file => /font-name\.\w+\.woff2/)
if (myFontFile) {
return [
[
'link',
{
rel: 'preload',
href: myFontFile,
as: 'font',
type: 'font/woff2',
crossorigin: ''
}
]
]
}
}
}
```
## 전역 컴포넌트 등록하기 {#registering-global-components}
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
/** @type {import('vitepress').Theme} */
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
// 사용자 지정 전역 컴포넌트를 등록하세요
app.component('MyGlobalComponent' /* ... */)
}
}
```
TypeScript를 사용하는 경우:
```ts
// .vitepress/theme/index.ts
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
// 사용자 지정 전역 컴포넌트를 등록하세요
app.component('MyGlobalComponent' /* ... */)
}
} satisfies Theme
```
Vite를 사용하기 때문에, Vite의 [글로브 임포트 기능](https://vitejs.dev/ko/guide/features.html#glob-import)을 활용하여 컴포넌트 디렉터리를 자동으로 등록할 수도 있습니다.
## 레이아웃 슬롯 {#layout-slots}
기본 테마의 `<Layout/>` 컴포넌트는 페이지의 특정 위치에 컨텐츠를 삽입할 수 있도록 몇 개의 슬롯을 제공합니다. 아웃라인 앞에 컴포넌트를 삽입하는 예시입니다:
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import MyLayout from './MyLayout.vue'
export default {
extends: DefaultTheme,
// 슬롯을 삽입하는 래퍼 컴포넌트로
// Layout을 오버라이드합니다
Layout: MyLayout
}
```
```vue
<!--.vitepress/theme/MyLayout.vue-->
<script setup>
import DefaultTheme from 'vitepress/theme'
const { Layout } = DefaultTheme
</script>
<template>
<Layout>
<template #aside-outline-before>
나만의 사용자 사이드바 상단 컨텐츠
</template>
</Layout>
</template>
```
렌더 함수를 사용하는 것도 가능합니다.
```js
// .vitepress/theme/index.js
import { h } from 'vue'
import DefaultTheme from 'vitepress/theme'
import MyComponent from './MyComponent.vue'
export default {
extends: DefaultTheme,
Layout() {
return h(DefaultTheme.Layout, null, {
'aside-outline-before': () => h(MyComponent)
})
}
}
```
기본 테마 레이아웃에서 사용할 수 있는 전체 슬롯 목록:
- 프론트매터를 통해 `layout: 'doc'` (기본값)이 활성화될 때:
- `doc-top`
- `doc-bottom`
- `doc-footer-before`
- `doc-before`
- `doc-after`
- `sidebar-nav-before`
- `sidebar-nav-after`
- `aside-top`
- `aside-bottom`
- `aside-outline-before`
- `aside-outline-after`
- `aside-ads-before`
- `aside-ads-after`
- 프론트매터를 통해 `layout: 'home'`이 활성화될 때:
- `home-hero-before`
- `home-hero-info-before`
- `home-hero-info`
- `home-hero-info-after`
- `home-hero-actions-after`
- `home-hero-image`
- `home-hero-after`
- `home-features-before`
- `home-features-after`
- 프론트매터를 통해 `layout: 'page'`가 활성화될 때:
- `page-top`
- `page-bottom`
- 찾을 수 없는 (404) 페이지에서:
- `not-found`
- 항상:
- `layout-top`
- `layout-bottom`
- `nav-bar-title-before`
- `nav-bar-title-after`
- `nav-bar-content-before`
- `nav-bar-content-after`
- `nav-screen-content-before`
- `nav-screen-content-after`
## 뷰 전환 API 사용하기 {#using-view-transitions-api}
### 외형 토글 시 {#on-appearance-toggle}
기본 테마를 확장하여 색상 모드가 토글될 때 사용자 정의 전환을 제공할 수 있습니다. 예시:
```vue
<!-- .vitepress/theme/Layout.vue -->
<script setup lang="ts">
import { useData } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import { nextTick, provide } from 'vue'
const { isDark } = useData()
const enableTransitions = () =>
'startViewTransition' in document &&
window.matchMedia('(prefers-reduced-motion: no-preference)').matches
provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
if (!enableTransitions()) {
isDark.value = !isDark.value
return
}
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y)
)}px at ${x}px ${y}px)`
]
await document.startViewTransition(async () => {
isDark.value = !isDark.value
await nextTick()
}).ready
document.documentElement.animate(
{ clipPath: isDark.value ? clipPath.reverse() : clipPath },
{
duration: 300,
easing: 'ease-in',
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`
}
)
})
</script>
<template>
<DefaultTheme.Layout />
</template>
<style>
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root),
.dark::view-transition-new(root) {
z-index: 1;
}
::view-transition-new(root),
.dark::view-transition-old(root) {
z-index: 9999;
}
.VPSwitchAppearance {
width: 22px !important;
}
.VPSwitchAppearance .check {
transform: none !important;
}
</style>
```
결과 (**경고!**: 눈부심, 갑작스러운 움직임, 밝은 빛):
<details>
<summary>데모</summary>
![외형 토글 전환 데모](/appearance-toggle-transition.webp)
</details>
뷰 전환에 대한 자세한 정보는 [Chrome 문서](https://developer.chrome.com/docs/web-platform/view-transitions/)를 참고하세요.
### 라우트 변경 시 {#on-route-change}
곧 제공될 예정입니다.
## 내부 컴포넌트 오버라이딩하기 {#overriding-internal-components}
Vite의 [별칭](https://vitejs.dev/config/shared-options.html#resolve-alias)을 사용하여 기본 테마 컴포넌트를 사용자 지정 컴포넌트로 대체할 수 있습니다:
```ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vitepress'
export default defineConfig({
vite: {
resolve: {
alias: [
{
find: /^.*\/VPNavBar\.vue$/,
replacement: fileURLToPath(
new URL('./components/CustomNavBar.vue', import.meta.url)
)
}
]
}
}
})
```
컴포넌트의 정확한 이름을 알고 싶다면 [저희 소스 코드](https://github.com/vuejs/vitepress/tree/main/src/client/theme-default/components)를 참조하세요. 컴포넌트가 내부적으로 사용되기 때문에, 소규모 릴리스 사이에 이름이 업데이트될 수 있습니다.

@ -0,0 +1,48 @@
# 전문 {#frontmatter}
## 사용법 {#usage}
VitePress는 모든 Markdown 파일에서 YAML 전문(frontmatter)을 지원하며, 이를 [gray-matter](https://github.com/jonschlinkert/gray-matter)로 분석합니다. 전문은 Markdown 파일의 맨 위에 위치해야 합니다(`<script>` 태그를 포함한 모든 요소 이전에)하며, 세 개의 대시 라인 사이에 유효한 YAML 형식으로 설정되어야 합니다. 예시:
```md
---
title: VitePress로 문서 작성하기
editLink: true
---
```
많은 사이트 또는 기본 테마 구성 옵션이 전문에서 대응하는 옵션을 가지고 있습니다. 전문을 사용하여 현재 페이지에 대한 특정 동작을 재정의 할 수 있습니다. 자세한 내용은 [전문 구성 참조](../reference/frontmatter-config)를 참조하십시오.
또한 페이지상의 동적 Vue 표현식에서 사용될 수 있는 자체적인 전문 데이터를 정의할 수 있습니다.
## 전문 데이터 접근 {#accessing-frontmatter-data}
전문 데이터는 특별한 `$frontmatter` 전역 변수를 통해 접근할 수 있습니다:
여기 Markdown 파일에서 사용하는 방법의 예시입니다:
```md
---
title: VitePress로 문서 작성하기
editLink: true
---
# {{ $frontmatter.title }}
가이드 내용
```
`<script setup>`에서 현재 페이지의 전문 데이터에 접근하려면 [`useData()`](../reference/runtime-api#usedata) 헬퍼를 사용할 수 있습니다.
## 대체 전문 형식 {#alternative-frontmatter-formats}
VitePress는 중괄호로 시작하고 끝나는 JSON 전문 구문도 지원합니다:
```json
---
{
"title": "해커처럼 블로깅하기",
"editLink": true
}
---
```

@ -0,0 +1,221 @@
# 시작하기 {#getting-started}
## 온라인에서 시도해보기 {#try-it-online}
브라우저에서 바로 VitePress를 시도해 볼 수 있습니다 [StackBlitz](https://vitepress.new).
## 설치 {#installation}
### 사전 준비 사항 {#prerequisites}
- [Node.js](https://nodejs.org/) 버전 18 이상.
- VitePress를 명령줄 인터페이스(CLI)를 통해 접근하기 위한 터미널.
- [Markdown](https://en.wikipedia.org/wiki/Markdown) 문법 지원이 있는 텍스트 에디터.
- [VSCode](https://code.visualstudio.com/)와 [공식 Vue 확장 프로그램](https://marketplace.visualstudio.com/items?itemName=Vue.volar) 사용을 권장합니다.
VitePress는 독립 실행형으로 사용하거나 기존 프로젝트에 설치할 수 있습니다. 어떤 경우든 다음과 같이 설치할 수 있습니다:
::: code-group
```sh [npm]
$ npm add -D vitepress
```
```sh [pnpm]
$ pnpm add -D vitepress
```
```sh [yarn]
$ yarn add -D vitepress
```
```sh [yarn (pnp)]
$ yarn add -D vitepress vue
```
```sh [bun]
$ bun add -D vitepress
```
:::
::: details 필요한 피어 종속성 경고가 나타나나요?
PNPM을 사용할 경우 `@docsearch/js`에 대한 누락된 피어 경고를 볼 수 있습니다. 이것은 VitePress 작동을 방해하지 않습니다. 이 경고를 억제하려면, `package.json`에 다음을 추가하세요:
```json
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"@algolia/client-search",
"search-insights"
]
}
}
```
:::
::: tip 참고
VitePress는 ESM-only 패키지입니다. `require()`를 사용하여 가져오지 마십시오, 그리고 가장 가까운 `package.json``"type": "module"`이 포함되어 있는지 확인하거나, 관련 파일(예: `.vitepress/config.js`)의 확장자를 `.mjs`/`.mts`로 변경하십시오. 자세한 내용은 [Vite의 문제 해결 가이드](http://vitejs.dev/ko/guide/troubleshooting.html#this-package-is-esm-only)를 참조하십시오. 또한, 비동기 CJS 컨텍스트 내에서는 대신 `await import('vitepress')`를 사용할 수 있습니다.
:::
### 설정 마법사 {#setup-wizard}
VitePress는 기본 프로젝트를 스캐폴딩하는 데 도움이 되는 명령줄 설정 마법사를 제공합니다. 설치 후, 마법사를 시작하려면 다음을 실행하세요:
::: code-group
```sh [npm]
$ npx vitepress init
```
```sh [pnpm]
$ pnpm vitepress init
```
```sh [yarn]
$ yarn vitepress init
```
```sh [bun]
$ bun vitepress init
```
:::
몇 가지 간단한 질문들이 나타날 것입니다:
<<< @/snippets/init.ansi
::: tip Vue를 피어 의존성으로
Vue 컴포넌트나 API를 사용하여 커스터마이즈를 수행하려면, `vue`도 명시적으로 의존성으로 설치해야 합니다.
:::
## 파일 구조 {#file-structure}
독립 실행형 VitePress 사이트를 빌딩하는 경우, 현재 디렉토리(`./`)에 사이트를 스캐폴딩할 수 있습니다. 그러나 다른 소스 코드와 함께 기존 프로젝트에 VitePress를 설치하는 경우, 프로젝트의 나머지 부분과 별도로 (`예: `./docs`) 중첩된 디렉토리에 사이트를 스캐폴딩하는 것이 좋습니다.
VitePress 프로젝트를 `./docs`에 스캐폴딩하기로 선택한 경우 생성된 파일 구조는 다음과 같아야 합니다:
```
.
├─ docs
│ ├─ .vitepress
│ │ └─ config.js
│ ├─ api-examples.md
│ ├─ markdown-examples.md
│ └─ index.md
└─ package.json
```
`docs` 디렉토리는 VitePress 사이트의 **프로젝트 루트**로 간주됩니다. `.vitepress` 디렉토리는 VitePress의 설정 파일, 개발 서버 캐시, 빌드 출력 및 선택적 테마 사용자 정의 코드를 위한 예약된 위치입니다.
::: tip
기본적으로, VitePress는 개발 서버 캐시를 `.vitepress/cache`에, 프로덕션 빌드 출력을 `.vitepress/dist`에 저장합니다. Git을 사용하는 경우, 이들을 `.gitignore` 파일에 추가해야 합니다. 이 위치는 또한 [구성할 수 있습니다](../reference/site-config#outdir).
:::
### 설정 파일 {#the-config-file}
설정 파일(`.vitepress/config.js`)을 사용하면 사이트의 제목과 설명과 같은 VitePress 사이트의 다양한 측면을 커스터마이즈할 수 있습니다:
```js
// .vitepress/config.js
export default {
// 사이트 수준 옵션
title: 'VitePress',
description: '그냥 해보는 중.',
themeConfig: {
// 테마 수준 옵션
}
}
```
`themeConfig` 옵션을 통해 테마의 동작을 구성할 수도 있습니다. 모든 구성 옵션에 대한 전체 세부 정보는 [구성 참조](../reference/site-config)를 참조하십시오.
### 소스 파일 {#source-files}
`.vitepress` 디렉토리 밖의 마크다운 파일들은 **소스 파일**로 간주됩니다.
VitePress는 **파일 기반 라우팅**을 사용합니다: 각 `.md` 파일은 동일한 경로에 해당하는 `.html` 파일로 컴파일됩니다. 예를 들어, `index.md``index.html`로 컴파일되며, 결과적인 VitePress 사이트의 루트 경로 `/`에서 방문할 수 있습니다.
VitePress는 또한 깨끗한 URL 생성, 경로 리라이팅 및 동적 페이지 생성 기능을 제공합니다. 이러한 내용은 [라우팅 가이드](./routing)에서 다뤄질 것입니다.
## 실행 및 작동 {#up-and-running}
설정 프로세스 중에 허용한 경우, 도구는 `package.json`에 다음 npm 스크립트를 주입해야 합니다:
```json
{
...
"scripts": {
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs",
"docs:preview": "vitepress preview docs"
},
...
}
```
`docs:dev` 스크립트는 즉각적인 핫 업데이트를 제공하는 로컬 개발 서버를 시작합니다. 다음 명령으로 실행하세요:
::: code-group
```sh [npm]
$ npm run docs:dev
```
```sh [pnpm]
$ pnpm run docs:dev
```
```sh [yarn]
$ yarn docs:dev
```
```sh [bun]
$ bun run docs:dev
```
:::
npm 스크립트 대신, 다음과 같이 VitePress를 직접 호출할 수도 있습니다:
::: code-group
```sh [npm]
$ npx vitepress dev docs
```
```sh [pnpm]
$ pnpm vitepress dev docs
```
```sh [yarn]
$ yarn vitepress dev docs
```
```sh [bun]
$ bun vitepress dev docs
```
:::
명령줄 사용법은 [CLI 참조](../reference/cli)에 문서화되어 있습니다.
개발 서버는 `http://localhost:5173`에서 실행되어야 합니다. 브라우저에서 URL을 방문하여 새 사이트를 확인하세요!
## 다음 단계는? {#what-s-next}
- 생성된 HTML로 마크다운 파일이 어떻게 매핑되는지 더 잘 이해하려면, [라우팅 가이드](./routing)로 진행하세요.
- 페이지에서 할 수 있는 일에 대해 더 알아보려면, 마크다운 콘텐츠 작성이나 Vue 컴포넌트 사용과 같은 "작성" 섹션의 가이드를 참조하십시오. 시작하기 좋은 곳은 [마크다운 확장](./markdown)에 대해 배우는 것입니다.
- 기본 문서 테마가 제공하는 기능을 탐색하려면, [기본 테마 구성 참조](../reference/default-theme-config)를 확인하세요.
- 사이트의 모양을 더욱 커스터마이즈하고 싶다면, [기본 테마 확장](./extending-default-theme)이나 [커스텀 테마 빌드](./custom-theme)하는 방법을 탐색해보세요.
- 문서 사이트가 구성되기 시작하면, [배포 가이드](./deploy)를 반드시 읽어보세요.

@ -0,0 +1,114 @@
# 국제화 {#internationalization}
내장 i18n 기능을 사용하기 위해서는 다음과 같은 디렉토리 구조를 생성해야 합니다:
```
docs/
├─ es/
│ ├─ foo.md
├─ fr/
│ ├─ foo.md
├─ foo.md
```
그런 다음 `docs/.vitepress/config.ts`에서:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
// 공유 속성 및 기타 최상위 항목...
locales: {
root: {
label: '영어',
lang: 'en'
},
fr: {
label: '프랑스어',
lang: 'fr', // 선택 사항, `html` 태그에 `lang` 속성으로 추가됩니다
link: '/fr/guide' // 기본적으로 /fr/ -- navbar 변역 메뉴에 표시됩니다, 외부일 수 있습니다
// 다른 로케일 특정 속성...
}
}
})
```
다음 속성들은 각 로케일(루트 포함)에 대해 덮어쓸 수 있습니다:
```ts
interface LocaleSpecificConfig<ThemeConfig = any> {
lang?: string
dir?: string
title?: string
titleTemplate?: string | boolean
description?: string
head?: HeadConfig[] // 기존 헤드 항목과 병합되며, 중복된 메타 태그는 자동으로 제거됩니다
themeConfig?: ThemeConfig // 얕게 병합됩니다, 공통 항목은 최상위 themeConfig 항목에 넣을 수 있습니다
}
```
기본 테마의 플레이스홀더 텍스트를 사용자 정의하는 방법은 [`DefaultTheme.Config`](https://github.com/vuejs/vitepress/blob/main/types/default-theme.d.ts) 인터페이스를 참조하세요. 로케일 레벨에서 `themeConfig.algolia` 또는 `themeConfig.carbonAds`를 덮어쓰지 마세요. 다국어 검색을 사용하는 방법에 대해서는 [Algolia 문서](../reference/default-theme-search#i18n)를 참조하세요.
**전문가 팁:** 구성 파일은 `docs/.vitepress/config/index.ts`에도 저장될 수 있습니다. 로케일별로 구성 파일을 생성한 다음 이를 `index.ts`에서 병합하여 내보내는 것으로, 내용을 구성하는데 도움이 될 수 있습니다.
## 각 로케일별 별도의 디렉토리 {#separate-directory-for-each-locale}
다음은 완전히 괜찮은 구조입니다:
```
docs/
├─ en/
│ ├─ foo.md
├─ es/
│ ├─ foo.md
├─ fr/
├─ foo.md
```
그러나, VitePress는 기본적으로 `/``/en/`로 리다이렉트하지 않습니다. 이를 위해 서버를 구성해야 합니다. 예를 들어, Netlify에서는 다음과 같이 `docs/public/_redirects` 파일을 추가할 수 있습니다:
```
/* /es/:splat 302 Language=es
/* /fr/:splat 302 Language=fr
/* /en/:splat 302
```
**전문가 팁:** 위의 접근 방식을 사용한다면, `nf_lang` 쿠키를 사용하여 사용자의 언어 선택을 유지할 수 있습니다:
```ts
// docs/.vitepress/theme/index.ts
import DefaultTheme from 'vitepress/theme'
import Layout from './Layout.vue'
export default {
extends: DefaultTheme,
Layout
}
```
```vue
<!-- docs/.vitepress/theme/Layout.vue -->
<script setup lang="ts">
import DefaultTheme from 'vitepress/theme'
import { useData } from 'vitepress'
import { watchEffect } from 'vue'
const { lang } = useData()
watchEffect(() => {
if (inBrowser) {
document.cookie = `nf_lang=${lang.value}; expires=Mon, 1 Jan 2030 00:00:00 UTC; path=/`
}
})
</script>
<template>
<DefaultTheme.Layout />
</template>
```
## RTL 지원 (실험적) {#rtl-support-experimental}
RTL 지원을 위해, 설정에서 `dir: 'rtl'`을 지정하고 <https://github.com/MohammadYounes/rtlcss>, <https://github.com/vkalinichev/postcss-rtl>, 또는 <https://github.com/elchininet/postcss-rtlcss>과 같은 RTLCSS PostCSS 플러그인을 사용하세요. CSS 전문성 문제를 방지하기 위해 `:where([dir="ltr"])``:where([dir="rtl"])`을 접두사로 사용하여 PostCSS 플러그인을 구성해야 합니다.

@ -0,0 +1,967 @@
# 마크다운 확장 {#markdown-extensions}
VitePress는 내장된 마크다운 확장을 제공합니다.
## 헤더 앵커 {#header-anchors}
헤더에는 자동으로 앵커 링크가 적용됩니다. 앵커의 렌더링은 `markdown.anchor` 옵션을 사용하여 구성할 수 있습니다.
### 사용자 정의 앵커 {#custom-anchors}
자동 생성된 것 대신 헤더에 대한 사용자 정의 앵커 태그를 지정하려면, 헤딩에 접미사를 추가하세요:
```
# 사용자 정의 앵커 사용 {#my-anchor}
```
이를 통해 기본값인 `#using-custom-anchors` 대신 `#my-anchor`로 헤딩에 링크할 수 있습니다.
## 링크 {#links}
내부 및 외부 링크는 특별한 처리를 받습니다.
### 내부 링크 {#internal-links}
내부 링크는 SPA 탐색을 위한 라우터 링크로 변환됩니다. 또한, 각 하위 디렉토리에 포함된 모든 `index.md`는 자동으로 `index.html`로 변환되며, 해당 URL은 `/`입니다.
예를 들어, 다음과 같은 디렉토리 구조가 주어져 있습니다:
```
.
├─ index.md
├─ foo
│ ├─ index.md
│ ├─ one.md
│ └─ two.md
└─ bar
├─ index.md
├─ three.md
└─ four.md
```
그리고 `foo/one.md`에 있다고 하면:
```md
[](/) <!-- 사용자를 루트 index.md로 보냅니다 -->
[foo](/foo/) <!-- foo 디렉토리의 index.html로 보냅니다 -->
[foo 헤딩](./#heading) <!-- foo index 파일의 헤딩으로 앵커링합니다 -->
[bar - three](../bar/three) <!-- 확장자를 생략할 수 있습니다 -->
[bar - three](../bar/three.md) <!-- .md를 추가할 수 있습니다 -->
[bar - four](../bar/four.html) <!-- 또는 .html을 추가할 수 있습니다 -->
```
### 페이지 접미사 {#page-suffix}
기본적으로 페이지와 내부 링크는 `.html` 접미사를 가지고 생성됩니다.
### 외부 링크 {#external-links}
외부 링크는 자동으로 `target="_blank" rel="noreferrer"`를 받습니다:
- [vuejs.org](https://vuejs.org)
- [GitHub에서 VitePress](https://github.com/vuejs/vitepress)
## 프론트매터 {#frontmatter}
[YAML 프론트매터](https://jekyllrb.com/docs/front-matter/)가 기본적으로 지원됩니다:
```yaml
---
title: 해커처럼 블로깅하기
lang: en-US
---
```
이 데이터는 페이지의 나머지 부분, 모든 사용자 정의 및 테마 구성 요소와 함께 사용할 수 있습니다.
자세한 내용은 [프론트매터](../reference/frontmatter-config)를 참조하세요.
## GitHub 스타일 테이블 {#github-style-tables}
**입력**
```md
| 테이블 | 은 | 멋져 |
| ------------- | :-----------: | ----: |
| 3열은 | 오른쪽 정렬입니다 | $1600 |
| 2열은 | 가운데 정렬입니다 | $12 |
| 얼룩말 줄무늬 | 멋져요 | $1 |
```
**출력**
| 테이블 | 은 | 멋져 |
| ------------- | :-----------: | -----: |
| 3열은 | 오른쪽 정렬입니다 | \$1600 |
| 2열은 | 가운데 정렬입니다 | \$12 |
| 얼룩말 줄무늬 | 멋져요 | \$1 |
## Emoji :tada:
**입력**
```
:tada: :100:
```
**출력**
:tada: :100:
[모든 이모지의 목록](https://github.com/markdown-it/markdown-it-emoji/blob/master/lib/data/full.mjs)이 제공됩니다.
## 목차 {#table-of-contents}
**입력**
```
[[toc]]
```
**출력**
[[toc]]
TOC의 렌더링은 `markdown.toc` 옵션을 사용하여 구성할 수 있습니다.
## 사용자 정의 컨테이너 {#custom-containers}
사용자 정의 컨테이너는 그들의 유형, 제목, 그리고 내용에 의해 정의될 수 있습니다.
### 기본 제목 {#default-title}
**입력**
```md
::: info
정보 상자입니다.
:::
::: tip
팁입니다.
:::
::: warning
경고입니다.
:::
::: danger
위험한 경고입니다.
:::
::: details
세부 정보 블록입니다.
:::
```
**출력**
::: info
정보 상자입니다.
:::
::: tip
팁입니다.
:::
::: warning
경고입니다.
:::
::: danger
위험한 경고입니다.
:::
::: details
세부 정보 블록입니다.
:::
### 사용자 정의 제목 {#custom-title}
컨테이너의 "유형" 바로 뒤에 텍스트를 추가하여 사용자 정의 제목을 설정할 수 있습니다.
**입력**
````md
::: danger 정지
위험 지대, 진행하지 마세요
:::
::: details 코드를 보려면 클릭하세요
```js
console.log('Hello, VitePress!')
```
:::
````
**출력**
::: danger 정지
위험 지대, 진행하지 마세요
:::
::: details 코드를 보려면 클릭하세요
```js
console.log('Hello, VitePress!')
```
:::
또한, 사이트 구성에서 다음과 같은 내용을 추가하여 전역적으로 사용자 정의 제목을 설정할 수 있습니다. 영어로 작성하지 않는 경우 유용합니다:
```ts
// config.ts
export default defineConfig({
// ...
markdown: {
container: {
tipLabel: '팁',
warningLabel: '경고',
dangerLabel: '위험',
infoLabel: '정보',
detailsLabel: '세부 정보'
}
}
// ...
})
```
### `raw`
VitePress와 스타일 및 라우터 충돌을 방지하기 위해 사용될 수 있는 특수 컨테이너입니다. 이는 특히 컴포넌트 라이브러리를 문서화할 때 유용합니다. 더 나은 격리를 위해 [whyframe](https://whyframe.dev/docs/integrations/vitepress)을 확인해보세요.
**문법**
```md
::: raw
<div class="vp-raw">로 감쌉니다
:::
```
`vp-raw` 클래스는 직접 요소에 사용될 수도 있습니다. 현재 스타일 격리는 선택 사항입니다:
- 원하는 패키지 관리자로 `postcss`를 설치하세요:
```sh
$ npm add -D postcss
```
- `docs/postcss.config.mjs`라는 파일을 만들고 이것을 추가하세요:
```js
import { postcssIsolateStyles } from 'vitepress'
export default {
plugins: [postcssIsolateStyles()]
}
```
이것은 내부적으로 [`postcss-prefix-selector`](https://github.com/postcss/postcss-load-config)를 사용합니다. 이렇게 옵션을 전달할 수 있습니다:
```js
postcssIsolateStyles({
includeFiles: [/vp-doc\.css/] // 기본값은 /base\.css/
})
```
## GitHub 스타일 경고 {#github-flavored-alerts}
VitePress는 [GitHub 스타일 경고](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts)를 콜아웃으로 렌더링하는 것을 지원합니다. 이것은 [사용자 정의 컨테이너](#custom-containers)와 같은 방식으로 렌더링됩니다.
```md
> [!NOTE]
> 사용자가 훑어보더라도 알아야 할 정보를 강조합니다.
> [!TIP]
> 사용자가 더 성공할 수 있도록 도움이 되는 선택적 정보입니다.
> [!IMPORTANT]
> 사용자가 성공하기 위해 필수적인 중요 정보입니다.
> [!WARNING]
> 잠재적인 위험으로 인해 즉각적인 사용자의 주의를 요하는 중요한 내용입니다.
> [!CAUTION]
> 행동의 부정적인 잠재적 결과입니다.
```
> [!NOTE]
> 사용자가 훑어보더라도 알아야 할 정보를 강조합니다.
> [!TIP]
> 사용자가 더 성공할 수 있도록 도움이 되는 선택적 정보입니다.
> [!IMPORTANT]
> 사용자가 성공하기 위해 필수적인 중요 정보입니다.
> [!WARNING]
> 잠재적인 위험으로 인해 즉각적인 사용자의 주의를 요하는 중요한 내용입니다.
> [!CAUTION]
> 행동의 부정적인 잠재적 결과입니다.
## 코드 블록 내 구문 강조 {#syntax-highlighting-in-code-blocks}
VitePress는 마크다운 코드 블록 내 언어 문법을 색상이 있는 텍스트로 강조하는 데 [Shiki](https://github.com/shikijs/shiki)를 사용합니다. Shiki는 다양한 프로그래밍 언어를 지원합니다. 코드 블록의 시작 백틱에 유효한 언어 별칭을 추가하기만 하면 됩니다:
**입력**
````markdown
```js
export default {
name: 'MyComponent',
// ...
}
```
````
````markdown
```html
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
```
````
**출력**
```js
export default {
name: 'MyComponent',
// ...
}
```
```html
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
</li>
</ul>
```
Shiki의 저장소에서 사용 가능한 [유효한 언어 목록](https://shiki.style/languages)이 제공됩니다.
또한 응용 프로그램 구성에서 구문 강조 테마를 사용자 지정할 수 있습니다. 자세한 내용은 [`markdown` 옵션](../reference/site-config#markdown)을 참조하세요.
## 코드 블록에서 라인 강조 {#line-highlighting-in-code-blocks}
**입력**
````markdown
```js{4}
export default {
data () {
return {
msg: '강조됨!'
}
}
}
```
````
**출력**
```js{4}
export default {
data() {
return {
msg: '강조됨!'
}
}
}
```
단일 라인 뿐만 아니라 여러 개의 단일 라인, 범위 또는 둘 다를 지정할 수도 있습니다:
- 라인 범위: 예를 들어 `{5-8}`, `{3-10}`, `{10-17}`
- 다수의 단일 라인: 예를 들어 `{4,7,9}`
- 라인 범위 및 단일 라인: 예를 들어 `{4,7-13,16,23-27,40}`
**입력**
````markdown
```js{1,4,6-8}
export default { // 강조됨
data () {
return {
msg: `강조됨!
이 줄은 강조되지 않습니다,
하지만 이 줄과 다음 2줄은 강조됩니다.`,
motd: 'VitePress는 멋져요',
lorem: 'ipsum'
}
}
}
```
````
**출력**
```js{1,4,6-8}
export default { // 강조됨
data () {
return {
msg: `강조됨!
이 줄은 강조되지 않습니다,
하지만 이 줄과 다음 2줄은 강조됩니다.`,
motd: 'VitePress는 멋져요',
lorem: 'ipsum',
}
}
}
```
또한, `// [!code highlight]` 주석을 사용하여 직접 라인에 강조를 추가할 수 있습니다.
**입력**
````markdown
```js
export default {
data () {
return {
msg: '강조됨!' // [!!code highlight]
}
}
}
```
````
**출력**
```js
export default {
data () {
return {
msg: '강조됨!' // [!code highlight]
}
}
}
```
## 코드 블록에서 포커싱 {#focus-in-code-blocks}
`// [!code focus]` 주석을 라인에 추가하면 해당 라인이 포커싱되고 코드의 다른 부분은 흐릿하게 처리됩니다.
추가로, `// [!code focus:<lines>]`를 사용하여 포커싱할 라인 수를 정의할 수 있습니다.
**입력**
````markdown
```js
export default {
data () {
return {
msg: '포커싱됨!' // [!!code focus]
}
}
}
```
````
**출력**
```js
export default {
data () {
return {
msg: '포커싱됨!' // [!code focus]
}
}
}
```
## 코드 블록 내 컬러 차이점 {#colored-diffs-in-code-blocks}
`// [!code --]` 또는 `// [!code ++]` 주석을 라인에 추가하면 해당 라인의 차이점을 나타내며, 코드 블록의 색상을 유지합니다.
**입력**
````markdown
```js
export default {
data () {
return {
msg: '삭제됨' // [!!code --]
msg: '추가됨' // [!!code ++]
}
}
}
```
````
**출력**
```js
export default {
data () {
return {
msg: '삭제됨' // [!code --]
msg: '추가됨' // [!code ++]
}
}
}
```
## 코드 블록 내 오류 및 경고 {#errors-and-warnings-in-code-blocks}
`// [!code warning]` 또는 `// [!code error]` 주석을 라인에 추가하면 해당 색깔에 따라 라인이 색칠됩니다.
**입력**
````markdown
```js
export default {
data () {
return {
msg: '오류', // [!!code error]
msg: '경고' // [!!code warning]
}
}
}
```
````
**출력**
```js
export default {
data () {
return {
msg: '오류', // [!code error]
msg: '경고' // [!code warning]
}
}
}
```
## 라인 번호 {#line-numbers}
구성을 통해 각 코드 블록에 라인 번호를 활성화할 수 있습니다:
```js
export default {
markdown: {
lineNumbers: true
}
}
```
자세한 내용은 [`markdown` 옵션](../reference/site-config#markdown)을 참조하세요.
또한 울타리 코드 블록에 `:line-numbers` / `:no-line-numbers` 마크를 추가하여 구성에서 설정한 값을 재정의할 수 있습니다.
또한 `:line-numbers` 뒤에 `=`를 추가하여 시작 라인 번호를 사용자 정의할 수 있습니다. 예를 들어, `:
**입력**
````md
```ts {1}
// 줄 번호는 기본적으로 비활성화되어 있음
const line2 = 'This is line 2'
const line3 = 'This is line 3'
```
```ts:line-numbers {1}
// 줄 번호가 활성화됨
const line2 = 'This is line 2'
const line3 = 'This is line 3'
```
```ts:line-numbers=2 {1}
// 줄 번호가 활성화되고 2부터 시작함
const line3 = 'This is line 3'
const line4 = 'This is line 4'
```
````
**출력**
```ts {1}
// 줄 번호는 기본적으로 비활성화되어 있음
const line2 = 'This is line 2'
const line3 = 'This is line 3'
```
```ts:line-numbers {1}
// 줄 번호가 활성화됨
const line2 = 'This is line 2'
const line3 = 'This is line 3'
```
```ts:line-numbers=2 {1}
// 줄 번호가 활성화되고 2부터 시작함
const line3 = 'This is line 3'
const line4 = 'This is line 4'
```
## 코드 스니펫 가져오기 {#import-code-snippets}
다음 문법을 통해 기존 파일에서 코드 스니펫을 가져올 수 있습니다:
```md
<<< @/파일경로
```
다음과 같이 [라인 하이라이팅](#line-highlighting-in-code-blocks)도 지원합니다:
```md
<<< @/파일경로{하이라이트할 라인}
```
**입력**
```md
<<< @/snippets/snippet.js{2}
```
**코드 파일**
<<< @/snippets/snippet.js
**출력**
<<< @/snippets/snippet.js{2}
::: tip
'@'의 값은 소스 루트에 해당합니다. 기본값은 VitePress 프로젝트 루트이지만, `srcDir`이 구성되어 있을 경우가 아니면 다릅니다. 상대 경로에서도 가져올 수 있습니다:
```md
<<< ../snippets/snippet.js
```
:::
특정 부분의 코드 파일만 포함하려면 [VS Code 리전](https://code.visualstudio.com/docs/editor/codebasics#_folding)을 사용할 수 있습니다. 파일 경로 뒤에 `#`을 사용한 다음 커스텀 리전 이름을 제공할 수 있습니다:
**입력**
```md
<<< @/snippets/snippet-with-region.js#snippet{1}
```
**코드 파일**
<<< @/snippets/snippet-with-region.js
**출력**
<<< @/snippets/snippet-with-region.js#snippet{1}
괄호(`{}`) 안에 언어를 지정할 수도 있습니다:
```md
<<< @/snippets/snippet.cs{c#}
<!-- 라인 하이라이팅과 함께: -->
<<< @/snippets/snippet.cs{1,2,4-6 c#}
<!-- 라인 번호와 함께: -->
<<< @/snippets/snippet.cs{1,2,4-6 c#:line-numbers}
```
이는 파일 확장명에서 소스 언어를 유추할 수 없을 때 유용합니다.
## 코드 그룹 {#code-groups}
다음과 같이 여러 코드 블록을 그룹화할 수 있습니다:
**입력**
````md
::: code-group
```js [config.js]
/**
* @type {import('vitepress').UserConfig}
*/
const config = {
// ...
}
export default config
```
```ts [config.ts]
import type { UserConfig } from 'vitepress'
const config: UserConfig = {
// ...
}
export default config
```
:::
````
**출력**
::: code-group
```js [config.js]
/**
* @type {import('vitepress').UserConfig}
*/
const config = {
// ...
}
export default config
```
```ts [config.ts]
import type { UserConfig } from 'vitepress'
const config: UserConfig = {
// ...
}
export default config
```
:::
코드 그룹에서 [스니펫 가져오기](#import-code-snippets)도 할 수 있습니다:
**입력**
```md
::: code-group
<!-- 기본적으로 파일 이름이 제목으로 사용됩니다 -->
<<< @/snippets/snippet.js
<!-- 커스텀 제목도 제공할 수 있습니다 -->
<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [지역 스니펫]
:::
```
**출력**
::: code-group
<<< @/snippets/snippet.js
<<< @/snippets/snippet-with-region.js#snippet{1,2 ts:line-numbers} [지역 스니펫]
:::
## 마크다운 파일 포함 {#markdown-file-inclusion}
다른 마크다운 파일에 마크다운 파일을 포함시킬 수 있으며, 중첩도 가능합니다.
::: tip
마크다운 경로 앞에 '@'을 붙이면 소스 루트로 작용합니다. 기본값은 VitePress 프로젝트 루트이지만, `srcDir`이 구성되어 있을 경우가 아닙니다.
:::
예를 들어, 다음과 같이 상대적인 마크다운 파일을 포함할 수 있습니다:
**입력**
```md
# 문서
## 기초
<!--@include: ./parts/basics.md-->
```
**부분 파일** (`parts/basics.md`)
```md
일부 시작하는 방법입니다.
### 구성
`.foorc.json`을 사용하여 생성할 수 있습니다.
```
**동일한 코드**
```md
# 문서
## 기초
일부 시작하는 방법입니다.
### 구성
`.foorc.json`을 사용하여 생성할 수 있습니다.
```
라인 범위 선택도 지원합니다:
**입력**
```md
# 문서
## 기초
<!--@include: ./parts/basics.md{3,}-->
```
**부분 파일** (`parts/basics.md`)
```md
일부 시작하는 방법입니다.
### 구성
`.foorc.json`을 사용하여 생성할 수 있습니다.
```
**동일한 코드**
```md
# 문서
## 기초
### 구성
`.foorc.json`을 사용하여 생성할 수 있습니다.
```
선택된 라인 범위의 형식은: `{3,}`, `{,10}`, `{1,10}`이 될 수 있습니다.
VS Code 영역을 사용하여 코드 파일의 해당 부분만 포함할 수도 있습니다. 파일 경로 뒤에 `#`를 붙여 사용자 정의 영역 이름을 제공할 수 있습니다:
**입력**
```md
# Docs
## Basics
<!--@include: ./parts/basics.md#basic-usage{,2}-->
<!--@include: ./parts/basics.md#basic-usage{5,}-->
```
**부분 파일** (`parts/basics.md`)
```md
<!-- #region basic-usage -->
## Usage Line 1
## Usage Line 2
## Usage Line 3
<!-- #endregion basic-usage -->
```
**동등한 코드**
```md
# Docs
## Basics
## Usage Line 1
## Usage Line 3
```
::: warning
파일이 없는 경우 오류를 발생시키지 않으니, 이 기능을 사용할 때는 내용이 예상대로 렌더링되고 있는지 확인해야 합니다.
:::
## 수식 {#math-equations}
현재 선택 사항입니다. 활성화하려면 `markdown-it-mathjax3`를 설치하고 설정 파일에서 `markdown.math``true`로 설정해야 합니다:
```sh
npm add -D markdown-it-mathjax3
```
```ts
// .vitepress/config.ts
export default {
markdown: {
math: true
}
}
```
**입력**
```md
$a \ne 0$일 때, $(ax^2 + bx + c = 0)$의 두 해는
$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$입니다
**맥스웰 방정식:**
| 방정식 | 설명 |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| $\nabla \cdot \vec{\mathbf{B}} = 0$ | $\vec{\mathbf{B}}$의 발산은 0입니다 |
| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | $\vec{\mathbf{E}}$의 회전은 $\vec{\mathbf{B}}$의 시간에 따른 변화율에 비례합니다 |
| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ |
```
**출력**
$a \ne 0$ 일 때, $(ax^2 + bx + c = 0)$의 두 해는 다음과 같습니다:
$$ x = {-b \pm \sqrt{b^2-4ac} \over 2a} $$
**맥스웰 방정식:**
| 방정식 | 설명 |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| $\nabla \cdot \vec{\mathbf{B}} = 0$ | $\vec{\mathbf{B}}$의 발산은 0입니다 |
| $\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} = \vec{\mathbf{0}}$ | $\vec{\mathbf{E}}$의 회전은 $\vec{\mathbf{B}}$의 시간에 따른 변화율에 비례합니다 |
| $\nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} = \frac{4\pi}{c}\vec{\mathbf{j}} \nabla \cdot \vec{\mathbf{E}} = 4 \pi \rho$ | _wha?_ |
## 이미지 지연 로딩 {#image-lazy-loading}
마크다운을 통해 추가된 각 이미지에 대해 지연 로딩을 활성화하려면 설정 파일에서 `lazyLoading``true`로 설정하세요:
```js
export default {
markdown: {
image: {
// 이미지 지연 로딩은 기본적으로 비활성화 되어 있습니다
lazyLoading: true
}
}
}
```
## 고급 설정 {#advanced-configuration}
VitePress는 마크다운 렌더링을 위해 [markdown-it](https://github.com/markdown-it/markdown-it)을 사용합니다. 위의 확장 프로그램 대부분은 커스텀 플러그인을 통해 구현됩니다. `.vitepress/config.js``markdown` 옵션을 사용하여 `markdown-it` 인스턴스를 더욱 커스터마이징할 수 있습니다:
```js
import { defineConfig } from 'vitepress'
import markdownItAnchor from 'markdown-it-anchor'
import markdownItFoo from 'markdown-it-foo'
export default defineConfig({
markdown: {
// markdown-it-anchor의 옵션
// https://github.com/valeriangalliat/markdown-it-anchor#usage
anchor: {
permalink: markdownItAnchor.permalink.headerLink()
},
// @mdit-vue/plugin-toc의 옵션
// https://github.com/mdit-vue/mdit-vue/tree/main/packages/plugin-toc#options
toc: { level: [1, 2] },
config: (md) => {
// 더 많은 markdown-it 플러그인을 사용!
md.use(markdownItFoo)
}
}
})
```
[설정 참조: 앱 설정](../reference/site-config#markdown)에서 구성 가능한 속성의 전체 목록을 확인할 수 있습니다.

@ -0,0 +1,23 @@
# Migration from VitePress 0.x {#migration-from-vitepress-0-x}
If you're coming from VitePress 0.x version, there're several breaking changes due to new features and enhancement. Please follow this guide to see how to migrate your app over to the latest VitePress.
## App Config {#app-config}
- The internationalization feature is not yet implemented.
## Theme Config {#theme-config}
- `sidebar` option has changed its structure.
- `children` key is now named `items`.
- Top level item may not contain `link` at the moment. We're planning to bring it back.
- `repo`, `repoLabel`, `docsDir`, `docsBranch`, `editLinks`, `editLinkText` are removed in favor of more flexible api.
- For adding GitHub link with icon to the nav, use [Social Links](../reference/default-theme-nav#navigation-links) feature.
- For adding "Edit this page" feature, use [Edit Link](../reference/default-theme-edit-link) feature.
- `lastUpdated` option is now split into `config.lastUpdated` and `themeConfig.lastUpdatedText`.
- `carbonAds.carbon` is changed to `carbonAds.code`.
## Frontmatter Config {#frontmatter-config}
- `home: true` option has changed to `layout: home`. Also, many Homepage related settings have been modified to provide additional features. See [Home Page guide](../reference/default-theme-home-page) for details.
- `footer` option is moved to [`themeConfig.footer`](../reference/default-theme-config#footer).

@ -0,0 +1,30 @@
# Migration from VuePress {#migration-from-vuepress}
## Config {#config}
### Sidebar {#sidebar}
The sidebar is no longer automatically populated from frontmatter. You can [read the frontmatter yourself](https://github.com/vuejs/vitepress/issues/572#issuecomment-1170116225) to dynamically populate the sidebar. [Additional utilities for this](https://github.com/vuejs/vitepress/issues/96) may be provided in the future.
## Markdown {#markdown}
### Images {#images}
Unlike VuePress, VitePress handles [`base`](./asset-handling#base-url) of your config automatically when you use static image.
Hence, now you can render images without `img` tag.
```diff
- <img :src="$withBase('/foo.png')" alt="foo">
+ ![foo](/foo.png)
```
::: warning
For dynamic images you still need `withBase` as shown in [Base URL guide](./asset-handling#base-url).
:::
Use `<img.*withBase\('(.*)'\).*alt="([^"]*)".*>` regex to find and replace it with `![$2]($1)` to replace all the images with `![](...)` syntax.
---
more to follow...

@ -0,0 +1,23 @@
# MPA 모드 <Badge type="warning" text="실험적" /> {#mpa-mode}
MPA(멀티 페이지 애플리케이션) 모드는 `vitepress build --mpa` 명령어를 통해 또는 `mpa: true` 옵션을 통해 설정 파일에서 활성화할 수 있습니다.
MPA 모드에서는 모든 페이지가 기본적으로 JavaScript 없이 렌더링됩니다. 결과적으로, 생산 사이트는 감사 도구로부터 초기 방문 성능 점수를 더 좋게 받을 가능성이 높습니다.
그러나, SPA 네비게이션이 없기 때문에, 페이지 간 링크는 전체 페이지를 다시 로드하게 합니다. MPA 모드에서의 포스트-로드 탐색은 SPA 모드처럼 즉각적으로 느껴지지 않을 것입니다.
또한, 기본적으로 JS 없음을 의미하는 것은 여러분이 본질적으로 Vue를 서버 측 템플리팅 언어로만 사용하고 있다는 것을 의미합니다. 브라우저에서는 이벤트 핸들러가 연결되지 않으므로, 상호 작용성이 없을 것입니다. 클라이언트 측 JavaScript를 로드하려면 특별한 `<script client>` 태그를 사용해야 합니다:
```html
<script client>
document.querySelector('h1').addEventListener('click', () => {
console.log('클라이언트 측 JavaScript!')
})
</script>
# 안녕하세요
```
`<script client>`는 VitePress 전용 기능으로, Vue 기능이 아닙니다. `.md``.vue` 파일 모두에서 작동하지만 MPA 모드에서만 작동합니다. 모든 테마 컴포넌트의 클라이언트 스크립트는 함께 번들링되며, 특정 페이지의 클라이언트 스크립트는 해당 페이지만을 위해 분할됩니다.
`<script client>`**Vue 컴포넌트 코드로 평가되지 않는다**는 점을 주의하세요: 이것은 일반 JavaScript 모듈로 처리됩니다. 이러한 이유로, MPA 모드는 여러분의 사이트가 절대적으로 최소한의 클라이언트 측 상호작용만을 필요로 할 때만 사용되어야 합니다.

@ -0,0 +1,373 @@
---
개요: 심층
---
# 라우팅 {#routing}
## 파일 기반 라우팅 {#file-based-routing}
VitePress는 파일 기반 라우팅을 사용하므로, 생성된 HTML 페이지는 소스 마크다운 파일의 디렉토리 구조에서 매핑됩니다. 예를 들어, 다음과 같은 디렉토리 구조가 주어진 경우:
```
.
├─ 가이드
│ ├─ 시작하기.md
│ └─ index.md
├─ index.md
└─ 프롤로그.md
```
생성된 HTML 페이지는 다음과 같습니다:
```
index.md --> /index.html (접근 가능 경로 /)
프롤로그.md --> /프롤로그.html
가이드/index.md --> /가이드/index.html (접근 가능 경로 /가이드/)
가이드/시작하기.md --> /가이드/시작하기.html
```
결과적으로 생성된 HTML은 정적 파일을 제공할 수 있는 모든 웹 서버에서 호스팅할 수 있습니다.
## 루트와 소스 디렉토리 {#root-and-source-directory}
VitePress 프로젝트의 파일 구조에서 두 가지 중요한 개념이 있습니다: **프로젝트 루트**와 **소스 디렉토리**.
### 프로젝트 루트 {#project-root}
프로젝트 루트는 VitePress가 `.vitepress` 특수 디렉토리를 찾으려고 시도하는 위치입니다. `.vitepress` 디렉토리는 VitePress의 설정 파일, 개발 서버 캐시, 빌드 출력, 그리고 선택적 테마 커스터마이징 코드를 위한 예약된 위치입니다.
명령 줄에서 `vitepress dev``vitepress build`를 실행할 때, VitePress는 현재 작업 디렉토리를 프로젝트 루트로 사용합니다. 서브 디렉토리를 루트로 지정하려면 상대 경로를 명령에 전달해야 합니다. 예를 들어, VitePress 프로젝트가 `./docs`에 위치한 경우, `vitepress dev docs`를 실행해야 합니다:
```
.
├─ docs # 프로젝트 루트
│ ├─ .vitepress # 설정 디렉토리
│ ├─ 시작하기.md
│ └─ index.md
└─ ...
```
```sh
vitepress dev docs
```
이것은 다음과 같은 소스-HTML 매핑을 결과로 합니다:
```
docs/index.md --> /index.html (접근 가능 경로 /)
docs/시작하기.md --> /시작하기.html
```
### 소스 디렉토리 {#source-directory}
소스 디렉토리는 마크다운 소스 파일이 위치하는 곳입니다. 기본적으로, 이는 프로젝트 루트와 동일합니다. 하지만, [`srcDir`](../reference/site-config#srcdir) 설정 옵션을 통해 이를 구성할 수 있습니다.
`srcDir` 옵션은 프로젝트 루트에 상대적으로 해결됩니다. 예를 들어, `srcDir: 'src'`로 설정하면, 파일 구조는 다음과 같아질 것입니다:
```
. # 프로젝트 루트
├─ .vitepress # 설정 디렉토리
└─ src # 소스 디렉토리
├─ 시작하기.md
└─ index.md
```
결과적으로 생성된 소스-HTML 매핑:
```
src/index.md --> /index.html (접근 가능 경로 /)
src/시작하기.md --> /시작하기.html
```
## 페이지 간 연결 {#linking-between-pages}
페이지 간 연결 시 절대 경로와 상대 경로를 모두 사용할 수 있습니다. `.md``.html` 확장자 모두 작동하더라도, 파일 확장자를 생략하여 VitePress가 설정에 기반한 최종 URL을 생성하도록 하는 것이 좋은 방법입니다.
```md
<!-- 수행 -->
[시작하기](./getting-started)
[시작하기](../guide/getting-started)
<!-- 수행하지 말 것 -->
[시작하기](./getting-started.md)
[시작하기](./getting-started.html)
```
[Asset Handling](./asset-handling)에서 이미지와 같은 에셋에 연결하는 방법에 대해 자세히 알아보세요.
### VitePress 페이지가 아닌 페이지로 연결 {#linking-to-non-vitepress-pages}
VitePress에서 생성하지 않은 사이트의 페이지에 연결하려면, 전체 URL을 사용해야 합니다(새 탭에서 열림) 또는 명시적으로 대상을 지정해야 합니다:
**입력**
```md
[Link to pure.html](/pure.html){target="_self"}
```
**출력**
[Link to pure.html](/pure.html){target="_self"}
::: tip 참고
마크다운 링크에서 `base`는 자동으로 URL에 추가됩니다. 즉, base 외부의 페이지에 연결하려면 링크에 `../../pure.html`와 같은 것이 필요합니다(브라우저에 의해 현재 페이지에 상대적으로 해결됨).
또는, 앵커 태그 구문을 직접 사용할 수 있습니다:
```md
<a href="/pure.html" target="_self">Link to pure.html</a>
```
:::
## 깨끗한 URL 생성 {#generating-clean-url}
::: warning 서버 지원 필요
VitePress로 깨끗한 URL을 제공하려면 서버 측 지원이 필요합니다.
:::
기본적으로, VitePress는 `.html`로 끝나는 URL로 들어오는 링크를 해결합니다. 그러나, 일부 사용자는 `.html` 확장자 없이 "깨끗한 URL"을 선호할 수 있습니다 - 예를 들어, `example.com/path` 대신 `example.com/path.html`.
일부 서버나 호스팅 플랫폼(예: Netlify, Vercel, GitHub 페이지)은 `/foo`와 같은 URL을 `/foo.html`로 매핑할 수 있는 기능을 제공합니다(리다이렉트 없이):
- Netlify와 GitHub 페이지는 기본적으로 이 기능을 지원합니다.
- Vercel은 [`vercel.json`에서 `cleanUrls` 옵션을 활성화](https://vercel.com/docs/concepts/projects/project-configuration#cleanurls)해야 합니다.
이 기능을 사용할 수 있다면, VitePress의 자체 [`cleanUrls`](../reference/site-config#cleanurls) 설정 옵션을 활성화해서:
- 페이지 간의 들어오는 링크가 `.html` 확장자 없이 생성됩니다.
- 현재 경로가 `.html`로 끝나면, 라우터가 클라이언트 측에서 확장자가 없는 경로로 리다이렉트를 수행합니다.
그러나, 서버를 이러한 지원으로 구성할 수 없다면, 다음과 같은 디렉토리 구조를 수동으로 활용해야 합니다:
```
.
├─ 시작하기
│ └─ index.md
├─ 설치
│ └─ index.md
└─ index.md
```
## 라우트 재작성 {#route-rewrites}
소스 디렉토리 구조와 생성된 페이지 간의 매핑을 커스터마이즈할 수 있습니다. 복잡한 프로젝트 구조를 가지고 있을 때 유용합니다. 예를 들어, 여러 패키지가 있는 모노레포를 가지고 있고, 소스 파일과 함께 문서를 배치하고 싶다고 가정해 봅시다:
```
.
├─ 패키지
│ ├─ pkg-a
│ │ └─ src
│ │ ├─ pkg-a-code.ts
│ │ └─ pkg-a-docs.md
│ └─ pkg-b
│ └─ src
│ ├─ pkg-b-code.ts
│ └─ pkg-b-docs.md
```
그리고 VitePress 페이지가 다음과 같이 생성되기를 원합니다:
```
packages/pkg-a/src/pkg-a-docs.md --> /pkg-a/index.html
packages/pkg-b/src/pkg-b-docs.md --> /pkg-b/index.html
```
이것은 다음과 같이 [`rewrites`](../reference/site-config#rewrites) 옵션을 구성하여 달성할 수 있습니다:
```ts
// .vitepress/config.js
export default {
rewrites: {
'패키지/pkg-a/src/pkg-a-docs.md': 'pkg-a/index.md',
'패키지/pkg-b/src/pkg-b-docs.md': 'pkg-b/index.md'
}
}
```
`rewrites` 옵션은 동적 라우트 매개변수도 지원합니다. 위의 예제에서, 많은 패키지를 가지고 있다면 모든 경로를 나열하는 것은 장황할 것입니다. 모두 같은 파일 구조를 가지고 있다면, 설정을 다음과 같이 간단하게 할 수 있습니다:
```ts
export default {
rewrites: {
'패키지/:pkg/src/(.*)': ':pkg/index.md'
}
}
```
재작성 경로는 `path-to-regexp` 패키지를 사용하여 컴파일됩니다 - 보다 고급 구문에 대해서는 [해당 문서](https://github.com/pillarjs/path-to-regexp#parameters)를 참조하십시오.
::: warning 재작성과 상대 링크
재작성이 활성화된 경우, **상대 링크는 재작성된 경로를 기반으로 해야 합니다**. 예를 들어, `패키지/pkg-a/src/pkg-a-code.md`에서 `패키지/pkg-b/src/pkg-b-code.md`로 상대 링크를 생성하려면 다음을 사용해야 합니다:
```md
[PKG B로의 링크](../pkg-b/pkg-b-code)
```
:::
## 동적 라우트 {#dynamic-routes}
단일 마크다운 파일과 동적 데이터를 사용하여 많은 페이지를 생성할 수 있습니다. 예를 들어, 프로젝트의 모든 패키지에 해당하는 페이지를 생성하는 `패키지/[pkg].md` 파일을 만들 수 있습니다. 여기서 `[pkg]` 세그먼트는 각 페이지를 다른 페이지와 구별하는 라우트 **매개변수**입니다.
### 경로 로더 파일 {#paths-loader-file}
VitePress는 정적 사이트 생성기이므로, 가능한 페이지 경로는 빌드 시간에 결정되어야 합니다. 따라서 동적 라우트 페이지는 **경로 로더 파일**을 동반해야 합니다. `패키지/[pkg].md`의 경우, `패키지/[pkg].paths.js`(`.ts`도 지원)가 필요합니다:
```
.
└─ 패키지
├─ [pkg].md # 라우트 템플릿
└─ [pkg].paths.js # 라우트 경로 로더
```
경로 로더는 `params` 속성을 가진 객체의 배열을 반환하는 `paths` 메서드를 기본 export로 제공하는 객체여야 합니다. 이러한 객체 각각은 해당하는 페이지를 생성할 것입니다.
다음 `paths` 배열이 주어진 경우:
```js
// 패키지/[pkg].paths.js
export default {
paths() {
return [
{ params: { pkg: 'foo' }},
{ params: { pkg: 'bar' }}
]
}
}
```
생성된 HTML 페이지는 다음과 같습니다:
```
.
└─ 패키지
├─ foo.html
└─ bar.html
```
### 여러 매개변수 {#multiple-params}
동적 라우트는 여러 매개변수를 포함할 수 있습니다:
**파일 구조**
```
.
└─ 패키지
├─ [pkg]-[version].md
└─ [pkg]-[version].paths.js
```
**경로 로더**
```js
export default {
paths: () => [
{ params: { pkg: 'foo', version: '1.0.0' }},
{ params: { pkg: 'foo', version: '2.0.0' }},
{ params: { pkg: 'bar', version: '1.0.0' }},
{ params: { pkg: 'bar', version: '2.0.0' }}
]
}
```
**출력**
```
.
└─ 패키지
├─ foo-1.0.0.html
├─ foo-2.0.0.html
├─ bar-1.0.0.html
└─ bar-2.0.0.html
```
### 동적으로 경로 생성 {#dynamically-generating-paths}
경로 로더 모듈은 Node.js에서 실행되며 빌드 시간에만 실행됩니다. 로컬 또는 원격 데이터를 사용하여 경로 배열을 동적으로 생성할 수 있습니다.
로컬 파일에서 경로 생성:
```js
import fs from 'fs'
export default {
paths() {
return fs
.readdirSync('패키지')
.map((pkg) => {
return { params: { pkg }}
})
}
}
```
원격 데이터에서 경로 생성:
```js
export default {
async paths() {
const pkgs = await (await fetch('https://my-api.com/packages')).json()
return pkgs.map((pkg) => {
return {
params: {
pkg: pkg.name,
version: pkg.version
}
}
})
}
}
```
### 페이지에서 매개변수 접근 {#accessing-params-in-page}
각 페이지에 추가 데이터를 전달하기 위해 매개변수를 사용할 수 있습니다. 마크다운 라우트 파일은 `$params` 전역 속성을 통해 현재 페이지 매개변수에 Vue 표현식에서 접근할 수 있습니다:
```md
- 패키지 이름: {{ $params.pkg }}
- 버전: {{ $params.version }}
```
[`useData`](../reference/runtime-api#usedata) 런타임 API를 통해 마크다운 파일과 Vue 컴포넌트에서 현재 페이지의 매개변수에도 접근할 수 있습니다:
```vue
<script setup>
import { useData } from 'vitepress'
// params는 Vue ref입니다
const { params } = useData()
console.log(params.value)
</script>
```
### 원시 콘텐츠 렌더링 {#rendering-raw-content}
페이지로 전달된 매개변수는 클라이언트 JavaScript 페이로드에 직렬화되므로, 예를 들어 원격 CMS에서 가져온 원시 마크다운이나 HTML 콘텐츠와 같이 무거운 데이터를 매개변수로 전달하지 마십시오.
대신, 각 경로 객체의 `content` 속성을 사용하여 각 페이지에 이러한 콘텐츠를 전달할 수 있습니다:
```js
export default {
async paths() {
const posts = await (await fetch('https://my-cms.com/blog-posts')).json()
return posts.map((post) => {
return {
params: { id: post.id },
content: post.content // 원시 마크다운 또는 HTML
}
})
}
}
```
그런 다음 다음 특수 구문을 사용하여 마크다운 파일 자체의 일부로 콘텐츠를 렌더링하세요:
```md
<!-- @content -->
```

@ -0,0 +1,58 @@
# 사이트맵 생성 {#sitemap-generation}
VitePress는 사이트를 위한 `sitemap.xml` 파일 생성을 기본적으로 지원합니다. 이를 활성화하려면 다음을 `.vitepress/config.js`에 추가하세요:
```ts
export default {
sitemap: {
hostname: 'https://example.com'
}
}
```
`<lastmod>` 태그를 `sitemap.xml`에 포함하려면 [`lastUpdated`](../reference/default-theme-last-updated) 옵션을 활성화할 수 있습니다.
## 옵션 {#options}
사이트맵 지원은 [`sitemap`](https://www.npmjs.com/package/sitemap) 모듈에 의해 제공됩니다. 설정 파일의 `sitemap` 옵션에 이 모듈이 지원하는 모든 옵션을 전달할 수 있습니다. 이 옵션들은 `SitemapStream` 생성자에 직접 전달됩니다. 자세한 내용은 [`sitemap` 문서](https://www.npmjs.com/package/sitemap#options-you-can-pass)를 참조하세요. 예제:
```ts
export default {
sitemap: {
hostname: 'https://example.com',
lastmodDateOnly: false
}
}
```
설정 파일에서 `base`를 사용하는 경우, `hostname` 옵션에 이를 추가해야 합니다:
```ts
export default {
base: '/my-site/',
sitemap: {
hostname: 'https://example.com/my-site/'
}
}
```
## `transformItems` Hook
`sitemap.transformItems` 훅을 사용하여 `sitemap.xml` 파일에 작성되기 전에 사이트맵 항목을 수정할 수 있습니다. 이 훅은 사이트맵 항목 배열을 인자로 받아 배열을 반환해야 합니다. 예제:
```ts
export default {
sitemap: {
hostname: 'https://example.com',
transformItems: (items) => {
// 새로운 항목 추가 또는 기존 항목 수정/필터링
items.push({
url: '/extra-page',
changefreq: 'monthly',
priority: 0.8
})
return items
}
}
}
```

@ -0,0 +1,136 @@
---
outline: deep
---
# SSR 호환성 {#ssr-compatibility}
VitePress는 Vue의 서버 사이드 렌더링(SSR) 기능을 사용하여 프로덕션 빌드 중에 Node.js에서 앱을 사전 렌더링합니다. 이는 테마 컴포넌트의 모든 사용자 정의 코드가 SSR 호환성을 준수해야 함을 의미합니다.
[공식 Vue 문서의 SSR 섹션](https://vuejs.org/guide/scaling-up/ssr.html)은 SSR이 무엇인지, SSR/SSG 간의 관계 및 SSR 친화적인 코드 작성에 대한 일반적인 참고 사항에 대한 더 많은 컨텍스트를 제공합니다. 핵심 원칙은 브라우저/DOM API에는 Vue 컴포넌트의 `beforeMount` 또는 `mounted` 후크에서만 접근해야 합니다.
## `<ClientOnly>`
SSR 친화적이지 않은 컴포넌트(예: 사용자 정의 지시문이 포함된 경우)를 사용하거나 시연하는 경우, 내장된 `<ClientOnly>` 컴포넌트 내부에 이를 래핑할 수 있습니다:
```md
<ClientOnly>
<NonSSRFriendlyComponent />
</ClientOnly>
```
## 가져오기 시 브라우저 API에 접근하는 라이브러리 {#libraries-that-access-browser-api-on-import}
일부 컴포넌트나 라이브러리는 **가져오기 시**에 브라우저 API에 접근합니다. 가져오기를 통해 브라우저 환경을 가정하는 코드를 사용하려면 동적으로 이를 가져와야 합니다.
### Mounted 후크에서 가져오기 {#importing-in-mounted-hook}
```vue
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
import('./lib-that-access-window-on-import').then((module) => {
// 코드 사용하기
})
})
</script>
```
### 조건부 가져오기 {#conditional-import}
`import.meta.env.SSR` 플래그([Vite env 변수](https://vitejs.dev/ko/guide/env-and-mode.html#env-variables)의 일부)를 사용하여 종속성을 조건부로 가져올 수도 있습니다:
```js
if (!import.meta.env.SSR) {
import('./lib-that-access-window-on-import').then((module) => {
// 코드 사용하기
})
}
```
[`Theme.enhanceApp`](./custom-theme#theme-interface)가 비동기적일 수 있기 때문에, 가져오기 시에 브라우저 API에 접근하는 Vue 플러그인을 조건부로 가져오고 등록할 수 있습니다:
```js
// .vitepress/theme/index.js
/** @type {import('vitepress').Theme} */
export default {
// ...
async enhanceApp({ app }) {
if (!import.meta.env.SSR) {
const plugin = await import('plugin-that-access-window-on-import')
app.use(plugin.default)
}
}
}
```
TypeScript를 사용하는 경우:
```ts
// .vitepress/theme/index.ts
import type { Theme } from 'vitepress'
export default {
// ...
async enhanceApp({ app }) {
if (!import.meta.env.SSR) {
const plugin = await import('plugin-that-access-window-on-import')
app.use(plugin.default)
}
}
} satisfies Theme
```
### `defineClientComponent`
VitePress는 가져오기 시에 브라우저 API에 접근하는 Vue 컴포넌트를 가져오기 위한 편리한 도우미를 제공합니다.
```vue
<script setup>
import { defineClientComponent } from 'vitepress'
const ClientComp = defineClientComponent(() => {
return import('component-that-access-window-on-import')
})
</script>
<template>
<ClientComp />
</template>
```
대상 컴포넌트에 props/children/slots를 전달할 수도 있습니다:
```vue
<script setup>
import { ref } from 'vue'
import { defineClientComponent } from 'vitepress'
const clientCompRef = ref(null)
const ClientComp = defineClientComponent(
() => import('component-that-access-window-on-import'),
// args are passed to h() - https://vuejs.org/api/render-function.html#h
[
{
ref: clientCompRef
},
{
default: () => '기본 슬롯',
foo: () => h('div', 'foo'),
bar: () => [h('span', '하나'), h('span', '둘')]
}
],
// 컴포넌트가 로드된 후 콜백함수, 비동기일 수 있음
() => {
console.log(clientCompRef.value)
}
)
</script>
<template>
<ClientComp />
</template>
```
대상 컴포넌트는 래퍼 컴포넌트의 mounted 후크에서만 가져올 것입니다.

@ -0,0 +1,256 @@
# Markdown에서 Vue 사용하기 {#using-vue-in-markdown}
VitePress에서 각 Markdown 파일은 HTML로 컴파일된 다음 [Vue 단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)로 처리됩니다. 이는 Markdown 내에서 동적 템플릿, Vue 컴포넌트 사용 또는 `<script>` 태그를 추가하여 임의의 페이지 내 Vue 컴포넌트 로직을 사용할 수 있음을 의미합니다.
VitePress가 Vue의 컴파일러를 활용하여 Markdown 콘텐츠의 순수 정적 부분을 자동으로 감지하고 최적화한다는 점에 주목할 가치가 있습니다. 정적 콘텐츠는 단일 자리표시자 노드로 최적화되어 초기 방문시 페이지의 JavaScript 페이로드에서 제거됩니다. 또한 클라이언트 측 하이드레이션 중에도 건너뜁니다. 간단히 말해서, 주어진 페이지에서 동적 부분에 대해서만 비용을 지불합니다.
::: tip SSR 호환성
모든 Vue 사용은 SSR과 호환되어야 합니다. 자세한 내용과 일반적인 해결 방법은 [SSR 호환성](./ssr-compat)을 참조하십시오.
:::
## 템플릿 {#templating}
### 보간(interpolation) {#interpolation}
각 Markdown 파일은 먼저 HTML로 컴파일되고 나서 Vite 프로세스 파이프라인으로 Vue 컴포넌트로 전달됩니다. 이는 텍스트에서 Vue 스타일 보간을 사용할 수 있음을 의미합니다:
**입력**
```md
{{ 1 + 1 }}
```
**출력**
<div class="language-text"><pre><code>{{ 1 + 1 }}</code></pre></div>
### 지시문 {#directives}
디자인상 원시 HTML도 마크다운에서 유효하기 때문에 지시문도 동작합니다:
**입력**
```html
<span v-for="i in 3">{{ i }}</span>
```
**출력**
<div class="language-text"><pre><code><span v-for="i in 3">{{ i }} </span></code></pre></div>
## `<script>``<style>` {#script-and-style}
Markdown 파일의 최상위 `<script>``<style>` 태그는 Vue SFC에서와 마찬가지로 작동합니다. `<script setup>`, `<style module>` 등을 포함합니다. 여기서 주된 차이점은 `<template>` 태그가 없다는 것입니다: 다른 모든 최상위 콘텐츠는 Markdown입니다. 또한 모든 태그는 frontmatter **이후에** 위치해야 함을 유의하십시오:
```html
---
hello: world
---
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
## Markdown 콘텐츠
현재 카운트: {{ count }}
<button :class="$style.button" @click="count++">증가</button>
<style module>
.button {
color: red;
font-weight: bold;
}
</style>
```
::: warning Markdown에서 `<style scoped>` 사용을 피하세요
Markdown에서 `<style scoped>`를 사용할 경우, 현재 페이지의 모든 요소에 특별한 속성을 추가해야 하므로 페이지 크기가 현저하게 증가할 수 있습니다. 페이지 내에서 지역적으로 범위가 지정된 스타일링이 필요할 때는 `<style module>`이 선호됩니다.
:::
현재 페이지의 메타데이터에 접근할 수 있는 [`useData` 도우미](../reference/runtime-api#usedata)와 같은 VitePress의 런타임 API에도 접근할 수 있습니다:
**입력**
```html
<script setup>
import { useData } from 'vitepress'
const { page } = useData()
</script>
<pre>{{ page }}</pre>
```
**출력**
```json
{
"path": "/using-vue.html",
"title": "Markdown에서 Vue 사용하기",
"frontmatter": {},
...
}
```
## 컴포넌트 사용하기 {#using-components}
Markdown 파일 내에서 Vue 컴포넌트를 직접 가져오고 사용할 수 있습니다.
### Markdown에서 가져오기 {#importing-in-markdown}
컴포넌트가 몇 페이지에서만 사용되는 경우, 해당되는 곳에서 명시적으로 가져오는 것이 좋습니다. 이를 통해 적절하게 코드를 분할하고 관련 페이지가 표시될 때만 로드할 수 있습니다:
```md
<script setup>
import CustomComponent from '../components/CustomComponent.vue'
</script>
# 문서
이것은 커스텀 컴포넌트를 사용하는 .md입니다
<CustomComponent />
## 더 많은 문서
...
```
### 전역적으로 컴포넌트 등록하기 {#registering-components-globally}
컴포넌트가 대부분의 페이지에서 사용될 것인 경우, Vue 앱 인스턴스를 사용자 지정하여 전역적으로 등록할 수 있습니다. 예제는 [기본 테마 확장](./extending-default-theme#registering-global-components) 관련 섹션을 참조하십시오.
::: warning 중요
커스텀 컴포넌트의 이름이 하이픈을 포함하거나 파스칼케이스(PascalCase)인지 확인하십시오. 그렇지 않으면 인라인 요소로 처리되어 `<p>` 태그 내에 포함되어 하이드레이션 불일치가 발생할 수 있습니다. `<p>`는 내부에 블록 요소를 포함할 수 없기 때문입니다.
:::
### 헤더에 컴포넌트 사용하기 <ComponentInHeader /> {#using-components-in-headers}
헤더에서 Vue 컴포넌트를 사용할 수 있지만, 다음 구문 사이의 차이를 유의하십시오:
| Markdown | 출력 HTML | 파싱된 헤더 |
| ------------------------------------------------------- | ----------------------------------------- | ------------- |
| <pre v-pre><code> # 텍스트 &lt;Tag/&gt; </code></pre> | `<h1>텍스트 <Tag/></h1>` | `텍스트` |
| <pre v-pre><code> # 텍스트 \`&lt;Tag/&gt;\` </code></pre> | `<h1>텍스트 <code>&lt;Tag/&gt;</code></h1>` | `텍스트 <Tag/>` |
`<code>`로 둘러싸인 HTML은 그대로 표시됩니다; **아니면** `<code>`로 둘러싸이지 않은 HTML만 Vue에 의해 파싱됩니다.
::: tip
출력 HTML은 [Markdown-it](https://github.com/Markdown-it/Markdown-it)에 의해 이루어지며, 파싱된 헤더는 VitePress(사이드바와 문서 제목 모두에 사용됨)에 의해 처리됩니다.
:::
## 이스케이프 {#escaping}
`v-pre` 지시문을 사용하여 `<span>`이나 다른 요소에 Vue 보간을 이스케이프할 수 있습니다:
**입력**
```md
이것은 <span v-pre>{{ 그대로 표시됩니다 }}</span>
```
**출력**
<div class="escape-demo">
<p>이것은 <span v-pre>{{ 그대로 표시됩니다 }}</span></p>
</div>
또한, 전체 단락을 `v-pre` 커스텀 컨테이너로 둘러싸도록 선택할 수 있습니다:
```md
::: v-pre
{{ 이것은 그대로 표시됩니다 }}
:::
```
**출력**
<div class="escape-demo">
::: v-pre
{{ 이것은 그대로 표시됩니다 }}
:::
</div>
## 코드 블록에서 이스케이프 해제하기 {#unescape-in-code-blocks}
기본적으로 모든 fenced 코드 블록은 자동으로 `v-pre`로 둘러싸입니다. 따라서 내부에서 Vue 구문을 처리하지 않습니다. 펜스 내에서 Vue 스타일 보간을 활성화하려면, 예를 들어 `js-vue`처럼 언어에 `-vue` 접미사를 추가할 수 있습니다:
**입력**
````md
```js-vue
안녕하세요 {{ 1 + 1 }}
```
````
**출력**
```js-vue
안녕하세요 {{ 1 + 1 }}
```
이는 일부 토큰이 제대로 구문 강조되지 않을 수 있음을 의미합니다.
## CSS 전처리기 사용하기 {#using-css-pre-processors}
VitePress는 CSS 전처리기에 대한 [내장 지원](https://vitejs.dev/ko/guide/features.html#css-pre-processors)을 가지고 있습니다: `.scss`, `.sass`, `.less`, `.styl``.stylus` 파일. 이것들을 위한 Vite 특정 플러그인을 설치할 필요는 없지만, 해당 전처리기 자체는 설치해야 합니다:
```
# .scss 및 .sass
npm install -D sass
# .less
npm install -D less
# .styl 및 .stylus
npm install -D stylus
```
그런 다음 다음을 Markdown 및 테마 컴포넌트에서 사용할 수 있습니다:
```vue
<style lang="sass">
.title
font-size: 20px
</style>
```
## Teleports 사용하기 {#using-teleports}
현재 VitePress는 본문으로만 teleport에 대한 SSG 지원을 가지고 있습니다. 다른 대상을 위해서는, 내장된 `<ClientOnly>` 컴포넌트 내에 감싸거나 텔레포트 마크업을 최종 페이지 HTML의 올바른 위치에 주입할 수 있습니다 [`postRender` 훅](../reference/site-config#postrender)을 통해.
<ModalDemo />
::: details
<<< @/components/ModalDemo.vue
:::
```md
<ClientOnly>
<Teleport to="#modal">
<div>
// ...
</div>
</Teleport>
</ClientOnly>
```
<script setup>
import ModalDemo from '../../components/ModalDemo.vue'
import ComponentInHeader from '../../components/ComponentInHeader.vue'
</script>
<style>
.escape-demo {
border: 1px solid var(--vp-c-border);
border-radius: 8px;
padding: 0 20px;
}
</style>

@ -0,0 +1,57 @@
# VitePress란 무엇인가? {#what-is-vitepress}
VitePress는 빠르고 컨텐츠 중심의 웹사이트를 구축하기 위해 설계된 [정적 사이트 생성기](https://en.wikipedia.org/wiki/Static_site_generator) (SSG)입니다. 간단히 말해, VitePress는 [Markdown](https://en.wikipedia.org/wiki/Markdown)으로 작성된 소스 컨텐츠를 가져와서 테마를 적용하고, 어디에나 쉽게 배포할 수 있는 정적 HTML 페이지를 생성합니다.
<div class="tip custom-block" style="padding-top: 8px">
그냥 시도해보고 싶으세요? [빠른 시작](./getting-started)으로 건너뛰세요.
</div>
## 사용 사례 {#use-cases}
- **문서화**
VitePress는 기술 문서를 위해 설계된 기본 테마와 함께 제공됩니다. 이 테마는 바로 지금 읽고 있는 이 페이지뿐만 아니라 [Vite](https://vitejs.dev/), [Rollup](https://rollupjs.org/), [Pinia](https://pinia.vuejs.org/), [VueUse](https://vueuse.org/), [Vitest](https://vitest.dev/), [D3](https://d3js.org/), [UnoCSS](https://unocss.dev/), [Iconify](https://iconify.design/) 그리고 [기타 많은](https://www.vuetelescope.com/explore?framework.slug=vitepress) 문서화에 힘을 실어줍니다.
[공식 Vue.js 문서](https://vuejs.org/)도 VitePress 기반으로 되어 있지만, 여러 번역 간에 공유되는 커스텀 테마를 사용합니다.
- **블로그, 포트폴리오 및 마케팅 사이트**
VitePress는 표준 Vite + Vue 애플리케이션의 개발자 경험과 함께 [완전히 맞춤화된 테마](./custom-theme)를 지원합니다. Vite 기반이기 때문에 풍부한 생태계에서 Vite 플러그인을 직접 활용할 수 있습니다. 또한, VitePress는 [데이터 불러오기](./data-loading) (로컬 또는 원격) 및 [동적으로 경로 생성하기](./routing#dynamic-routes)를 위한 유연한 API를 제공합니다. 빌드 시점에 데이터를 결정할 수 있다면 거의 모든 것을 구축할 수 있습니다.
공식 [Vue.js 블로그](https://blog.vuejs.org/)는 로컬 콘텐츠를 기반으로 색인 페이지를 생성하는 간단한 블로그입니다.
## 개발자 경험 {#developer-experience}
VitePress는 Markdown 컨텐츠를 다룰 때 훌륭한 개발자 경험(DX)을 제공하고자 합니다.
- **[Vite 구동:](https://vitejs.dev/)** 즉각적인 서버 시작이 가능하며, 페이지 새로고침 없이 항상 (<100ms) 즉시 수정 사항이 반영됩니다.
- **[내장 Markdown 확장 기능:](./markdown)** Frontmatter, 테이블, 구문 하이라이팅… 필요한 것이라면 무엇이든 있습니다. 특히, VitePress는 코드 블록과 작업할 때 많은 고급 기능을 제공하여 기술적 문서에 이상적입니다.
- **[Vue를 향상된 Markdown:](./using-vue)** 각 Markdown 페이지는 HTML과 100% 문법 호환성을 가진 Vue 템플릿 덕분에 Vue [단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)입니다. Vue 템플릿 기능이나 가져온 Vue 컴포넌트를 사용하여 정적 콘텐츠에 상호작용성을 삽입할 수 있습니다.
## 성능 {#performance}
전통적인 SSG들과 달리 각 탐색이 전체 페이지 새로고침을 초래하는 것이 아니라, VitePress로 생성된 웹사이트는 초기 방문 시 정적 HTML을 제공하지만, 사이트 내 이후 탐색에 대해서는 [싱글 페이지 애플리케이션](https://en.wikipedia.org/wiki/Single-page_application) (SPA)이 됩니다. 우리의 견해에 따르면, 이 모델은 성능에 있어 최적의 균형을 제공합니다:
- **빠른 초기 로딩**
어떤 페이지에 대한 초기 방문은 빠른 로딩 속도와 최적의 SEO를 위해 정적으로 사전 렌더링된 HTML이 제공됩니다. 그런 다음 페이지는 Vue SPA로 페이지를 변환하는 JavaScript 번들을 로드합니다("hydration"). SPA hydration이 느리다는 일반적인 가정과 달리, 이 과정은 실제로 Vue 3의 순수 성능과 컴파일러 최적화 덕분에 매우 빠릅니다. [PageSpeed Insights](https://pagespeed.web.dev/report?url=https%3A%2F%2Fvitepress.dev%2F)에서 일반적인 VitePress 사이트는 저사양 모바일 장치에서도 느린 네트워크에서 거의 완벽한 성능 점수를 달성합니다.
- **빠른 후속 로드 탐색**
더 중요한 것은 초기 로드 **이후** 사용자 경험이 개선된다는 것입니다. 사이트 내의 이후 탐색에서는 전체 페이지 새로고침이 더 이상 발생하지 않습니다. 대신, 들어오는 페이지의 콘텐츠가 가져와져 동적으로 업데이트됩니다. VitePress는 또한 뷰포트 내 링크에 대한 페이지 청크를 자동으로 사전 로드합니다. 대부분의 경우, 이후 로드 탐색은 즉각적으로 느껴질 것입니다.
- **패널티 없는 상호작용성**
정적 Markdown 내에 내장된 동적 Vue 파트를 hydrate할 수 있도록 각 Markdown 페이지는 Vue 컴포넌트로 처리되고 JavaScript로 컴파일됩니다. 이것은 비효율적으로 들릴 수 있지만, Vue 컴파일러는 정적 부분과 동적 부분을 분리하여 hydration 비용과 페이로드 크기를 최소화하는 데 충분히 똑똑합니다. 초기 페이지 로드에 대해서, 정적 부분은 JavaScript 페이로드에서 자동으로 제거되고 hydration 동안 건너뛰어집니다.
## VuePress는 어떤가요? {#what-about-vuepress}
VitePress는 VuePress의 영적 후계자입니다. 원래 VuePress는 Vue 2와 webpack에 기반을 두고 있었습니다. Vue 3와 Vite를 기반으로 한 VitePress는 훨씬 더 나은 DX, 더 나은 프로덕션 성능, 더 완성된 기본 테마, 그리고 더욱 유연한 커스터마이징 API를 제공합니다.
VitePress와 VuePress 사이의 API 차이는 주로 테마와 커스터마이징에 있습니다. 기본 테마를 사용하는 VuePress 1을 사용하는 경우, VitePress로 마이그레이션하는 것이 비교적 간단할 수 있습니다.
VuePress 2에도 투자된 노력이 있으며, 이것도 Vue 3와 Vite를 지원하고 VuePress 1과 더 호환됩니다. 그러나 동시에 두 개의 SSG를 병행하여 유지하는 것은 지속 가능하지 않으므로, Vue 팀은 장기적으로 주요 권장 SSG로 VitePress에 집중하기로 결정했습니다.

@ -0,0 +1,60 @@
---
layout: home
title: VitePress
titleTemplate: Vite & Vue로 구동되는 정적 사이트 생성기
hero:
name: VitePress
text: Vite & Vue로 구동되는 정적 사이트 생성기
tagline: 마크다운으로 멋진 문서를 몇 분 안에
actions:
- theme: brand
text: VitePress란 무엇인가?
link: /ko/guide/what-is-vitepress
- theme: alt
text: 빠른 시작
link: /ko/guide/getting-started
- theme: alt
text: GitHub
link: https://github.com/vuejs/vitepress
image:
src: /vitepress-logo-large.webp
alt: VitePress
features:
- icon: 📝
title: 콘텐츠에 집중하세요
details: 단지 마크다운으로 아름다운 문서 사이트를 쉽게 만들 수 있습니다.
- icon: <svg xmlns="http://www.w3.org/2000/svg" width="30" viewBox="0 0 256 256.32"><defs><linearGradient id="a" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"/><stop offset="100%" stop-color="#BD34FE"/></linearGradient><linearGradient id="b" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"/><stop offset="8.333%" stop-color="#FFDD35"/><stop offset="100%" stop-color="#FFA800"/></linearGradient></defs><path fill="url(#a)" d="M255.153 37.938 134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"/><path fill="url(#b)" d="M185.432.063 96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028 72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"/></svg>
title: Vite DX를 즐기세요
details: 즉각적인 서버 시작, 번개 같은 핫 업데이트, 및 Vite 생태계 플러그인을 활용하세요.
- icon: <svg xmlns="http://www.w3.org/2000/svg" width="30" viewBox="0 0 256 220.8"><path fill="#41B883" d="M204.8 0H256L128 220.8 0 0h97.92L128 51.2 157.44 0h47.36Z"/><path fill="#41B883" d="m0 0 128 220.8L256 0h-51.2L128 132.48 50.56 0H0Z"/><path fill="#35495E" d="M50.56 0 128 133.12 204.8 0h-47.36L128 51.2 97.92 0H50.56Z"/></svg>
title: Vue로 커스터마이징하세요
details: 마크다운에서 직접 Vue 구문과 컴포넌트를 사용하거나 Vue로 커스텀 테마를 만들어보세요.
- icon: 🚀
title: 빠른 사이트 출시
details: 정적 HTML로 빠른 초기 로드와 클라이언트 측 라우팅으로 빠른 포스트 로드 내비게이션을 제공합니다.
---
<style>
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe 30%, #41d1ff);
--vp-home-hero-image-background-image: linear-gradient(-45deg, #bd34fe 50%, #47caff 50%);
--vp-home-hero-image-filter: blur(44px);
}
@media (min-width: 640px) {
:root {
--vp-home-hero-image-filter: blur(56px);
}
}
@media (min-width: 960px) {
:root {
--vp-home-hero-image-filter: blur(68px);
}
}
</style>

@ -0,0 +1,74 @@
# 명령 줄 인터페이스 {#command-line-interface}
## `vitepress dev`
지정된 디렉토리를 루트로 사용하여 VitePress 개발 서버 시작. 기본값은 현재 디렉토리입니다. 현재 디렉토리에서 실행할 때는 `dev` 명령을 생략할 수도 있습니다.
### 사용법
```sh
# 현재 디렉토리에서 시작, `dev` 생략
vitepress
# 서브 디렉토리에서 시작
vitepress dev [root]
```
### 옵션
| 옵션 | 설명 |
|-----------------|-----------------------------------------|
| `--open [path]` | 시작 시 브라우저 열기 (`boolean \| string`) |
| `--port <port>` | 포트 지정 (`number`) |
| `--base <path>` | 공개 기본 경로 (기본값: `/`) (`string`) |
| `--cors` | CORS 활성화 |
| `--strictPort` | 지정된 포트가 이미 사용 중인 경우 종료 (`boolean`) |
| `--force` | 최적화기가 캐시를 무시하고 다시 번들링하도록 강제 (`boolean`) |
## `vitepress build`
VitePress 사이트를 프로덕션 용으로 빌드합니다.
### 사용법
```sh
vitepress build [root]
```
### 옵션
| 옵션 | 설명 |
|--------------------------------|--------------------------------------------------------------------------------------|
| `--mpa` (실험적) | 클라이언트 측 수화 없이 [MPA 모드](../guide/mpa-mode)에서 빌드 (`boolean`) |
| `--base <path>` | 공개 기본 경로 (기본값: `/`) (`string`) |
| `--target <target>` | 트랜스파일 대상 (기본값: `"modules"`) (`string`) |
| `--outDir <dir>` | **cwd**에 상대적인 출력 디렉토리 (기본값: `<root>/.vitepress/dist`) (`string`) |
| `--minify [minifier]` | 미니화 활성화/비활성화하거나 사용할 미니화기를 지정 (기본값: `"esbuild"`) (`boolean \| "terser" \| "esbuild"`) |
| `--assetsInlineLimit <number>` | 바이트 단위로 정적 자산 base64 인라인 임계값 (기본값: `4096`) (`number`) |
## `vitepress preview`
프로덕션 빌드를 로컬에서 미리 볼 수 있습니다.
### 사용법
```sh
vitepress preview [root]
```
### 옵션
| 옵션 | 설명 |
|-----------------|--------------------------------|
| `--base <path>` | 공개 기본 경로 (기본값: `/`) (`string`) |
| `--port <port>` | 포트 지정 (`number`) |
## `vitepress init`
현재 디렉토리에서 [설정 마법사](../guide/getting-started#setup-wizard) 시작.
### 사용법
```sh
vitepress init
```

@ -0,0 +1,69 @@
# 배지 {#badge}
배지는 헤더에 상태를 추가할 수 있게 해줍니다. 예를 들어, 섹션의 유형이나 지원되는 버전을 명시하는 것이 유용할 수 있습니다.
## 사용법 {#usage}
글로벌하게 사용 가능한 `Badge` 컴포넌트를 사용할 수 있습니다.
```html
### 제목 <Badge type="info" text="default" />
### 제목 <Badge type="tip" text="^1.9.0" />
### 제목 <Badge type="warning" text="beta" />
### 제목 <Badge type="danger" text="주의" />
```
위 코드는 다음과 같이 렌더링됩니다:
### 제목 <Badge type="info" text="default" />
### 제목 <Badge type="tip" text="^1.9.0" />
### 제목 <Badge type="warning" text="beta" />
### 제목 <Badge type="danger" text="주의" />
## 사용자 정의 자식 요소 {#custom-children}
`<Badge>``children`을 받아들이며, 이는 배지 안에 표시됩니다.
```html
### 제목 <Badge type="info">사용자 정의 요소</Badge>
```
### 제목 <Badge type="info">사용자 정의 요소</Badge>
## 타입 색상 사용자 정의 {#customize-type-color}
css 변수를 오버라이딩함으로써 배지의 스타일을 사용자 정의할 수 있습니다. 다음은 기본값입니다:
```css
:root {
--vp-badge-info-border: transparent;
--vp-badge-info-text: var(--vp-c-text-2);
--vp-badge-info-bg: var(--vp-c-default-soft);
--vp-badge-tip-border: transparent;
--vp-badge-tip-text: var(--vp-c-brand-1);
--vp-badge-tip-bg: var(--vp-c-brand-soft);
--vp-badge-warning-border: transparent;
--vp-badge-warning-text: var(--vp-c-warning-1);
--vp-badge-warning-bg: var(--vp-c-warning-soft);
--vp-badge-danger-border: transparent;
--vp-badge-danger-text: var(--vp-c-danger-1);
--vp-badge-danger-bg: var(--vp-c-danger-soft);
}
```
## `<Badge>`
`<Badge>` 컴포넌트는 다음의 prop들을 받습니다:
```ts
interface Props {
// `<slot>`이 전달되면, 이 값은 무시됩니다.
text?: string
// 기본값은 `tip`입니다.
type?: 'info' | 'tip' | 'warning' | 'danger'
}
```

@ -0,0 +1,22 @@
# 카본 광고 {#carbon-ads}
VitePress는 [카본 광고](https://www.carbonads.net/)에 대한 내장된 네이티브 지원을 제공합니다. config에서 카본 광고 자격증명을 정의함으로써, VitePress는 페이지에 광고를 표시합니다.
```js
export default {
themeConfig: {
carbonAds: {
code: '당신의-카본-코드',
placement: '당신의-카본-위치'
}
}
}
```
이 값들은 아래와 같이 카본 CDN 스크립트를 호출하는 데 사용됩니다.
```js
`//cdn.carbonads.com/carbon.js?serve=${code}&placement=${placement}`
```
카본 광고 설정에 대해 자세히 알아보려면, [카본 광고 웹사이트](https://www.carbonads.net/)를 방문해 주십시오.

@ -0,0 +1,452 @@
# 기본 테마 설정 {#default-theme-config}
테마 설정을 통해 테마를 사용자 정의할 수 있습니다. 설정 파일의 `themeConfig` 옵션을 통해 테마 설정을 정의할 수 있습니다:
```ts
export default {
lang: 'en-US',
title: 'VitePress',
description: 'Vite & Vue로 구동되는 정적 사이트 생성기.',
// 테마 관련 설정.
themeConfig: {
logo: '/logo.svg',
nav: [...],
sidebar: { ... }
}
}
```
**이 페이지에 문서화된 옵션은 기본 테마에만 적용됩니다.** 다른 테마는 다른 테마 설정을 기대합니다. 커스텀 테마를 사용할 때, 테마 설정 객체는 테마로 전달되어 테마가 그것에 따라 조건적인 동작을 정의할 수 있습니다.
## i18nRouting
- 타입: `boolean`
예를 들어 `zh`로 로케일을 변경하면 URL이 `/foo` (또는 `/en/foo/`)에서 `/zh/foo`로 변경됩니다. 이 동작을 비활성화하려면 `themeConfig.i18nRouting``false`로 설정하세요.
## logo
- 타입: `ThemeableImage`
내비게이션 바에 사이트 제목 바로 앞에 표시되는 로고 파일입니다. 경로 문자열을 받거나, 밝은/어두운 모드에 따라 다른 로고를 설정하기 위해 객체를 사용할 수 있습니다.
```ts
export default {
themeConfig: {
logo: '/logo.svg'
}
}
```
```ts
type ThemeableImage =
| string
| { src: string; alt?: string }
| { light: string; dark: string; alt?: string }
```
## siteTitle
- 타입: `string | false`
내비게이션에서 기본 사이트 제목(`app config`의 `title`)을 대체하기 위해 이 항목을 사용자 정의할 수 있습니다. `false`로 설정하면 내비게이션의 제목이 비활성화됩니다. `logo`가 이미 사이트 제목 텍스트를 포함하고 있을 때 유용합니다.
```ts
export default {
themeConfig: {
siteTitle: 'Hello World'
}
}
```
## nav
- 타입: `NavItem`
내비게이션 메뉴 항목의 설정입니다. 자세한 내용은 [기본 테마: Nav](./default-theme-nav#navigation-links)에서 확인할 수 있습니다.
```ts
export default {
themeConfig: {
nav: [
{ text: '가이드', link: '/guide' },
{
text: '드롭다운 메뉴',
items: [
{ text: '항목 A', link: '/item-1' },
{ text: '항목 B', link: '/item-2' },
{ text: '항목 C', link: '/item-3' }
]
}
]
}
}
```
```ts
type NavItem = NavItemWithLink | NavItemWithChildren
interface NavItemWithLink {
text: string
link: string
activeMatch?: string
target?: string
rel?: string
noIcon?: boolean
}
interface NavItemChildren {
text?: string
items: NavItemWithLink[]
}
interface NavItemWithChildren {
text?: string
items: (NavItemChildren | NavItemWithLink)[]
activeMatch?: string
}
```
## sidebar
- 타입: `Sidebar`
사이드바 메뉴 항목의 설정입니다. 자세한 내용은 [기본 테마: Sidebar](./default-theme-sidebar)에서 확인할 수 있습니다.
```ts
export default {
themeConfig: {
sidebar: [
{
text: '가이드',
items: [
{ text: '소개', link: '/introduction' },
{ text: '시작하기', link: '/getting-started' },
...
]
}
]
}
}
```
```ts
export type Sidebar = SidebarItem[] | SidebarMulti
export interface SidebarMulti {
[path: string]: SidebarItem[] | { items: SidebarItem[]; base: string }
}
export type SidebarItem = {
/**
* 항목의 텍스트 레이블.
*/
text?: string
/**
* 항목의 링크.
*/
link?: string
/**
* 항목의 자식들.
*/
items?: SidebarItem[]
/**
* 명시되지 않은 경우, 그룹은 접을 수 없습니다.
*
* `true`이면, 그룹은 접을 수 있고 기본적으로 접혀 있습니다
*
* `false`이면, 그룹은 접을 수 있지만 기본적으로 펼쳐져 있습니다
*/
collapsed?: boolean
}
```
## aside
- 타입: `boolean | 'left'`
- 기본값: `true`
- [frontmatter](./frontmatter-config#aside)를 통해 페이지별로 재정의 가능
이 값을 `false`로 설정하면 aside 컨테이너의 렌더링을 방지합니다.\
이 값을 `true`로 설정하면 aside를 오른쪽에 렌더링합니다.\
이 값을 `left`로 설정하면 aside를 왼쪽에 렌더링합니다.
모든 뷰포트에 대해 비활성화하려면 `outline: false`를 사용해야 합니다.
## outline
- 타입: `Outline | Outline['level'] | false`
- [frontmatter](./frontmatter-config#outline)를 통해 페이지별로 레벨 재정의 가능
이 값을 `false`로 설정하면 윤곽선 컨테이너의 렌더링을 방지합니다. 자세한 내용은 이 인터페이스를 참조하세요:
```ts
interface Outline {
/**
* 개요에 표시될 제목 수준.
* 단일 수치는 해당 수준의 제목만 표시됨을 의미합니다.
* 튜플이 전달되면 첫 번째 수치는 최소 수준이고 두 번째 수치는 최대 수준입니다.
* `'deep'``[2, 6]`과 동일하며, `<h2>`부터 `<h6>`까지의 모든 제목이 표시됨을 의미합니다.
*
* @default 2
*/
level?: number | [number, number] | 'deep'
/**
* 개요에 표시될 제목.
*
* @default '이 페이지에서'
*/
label?: string
}
```
## socialLinks
- 타입: `SocialLink[]`
내비게이션에 아이콘과 함께 소셜 계정 링크를 표시하기 위해 이 옵션을 정의할 수 있습니다.
```ts
export default {
themeConfig: {
socialLinks: [
{ icon: 'github', link: 'https://github.com/vuejs/vitepress' },
{ icon: 'twitter', link: '...' },
// SVG 문자열을 전달하여 사용자 정의 아이콘을 추가할 수도 있습니다:
{
icon: {
svg: '<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Dribbble</title><path d="M12...6.38z"/></svg>'
},
link: '...',
// 접근성을 위해 사용자 정의 레이블을 포함할 수도 있습니다 (선택 사항이지만 권장됨):
ariaLabel: '멋진 링크'
}
]
}
}
```
```ts
interface SocialLink {
icon: SocialLinkIcon
link: string
ariaLabel?: string
}
type SocialLinkIcon =
| 'discord'
| 'facebook'
| 'github'
| 'instagram'
| 'linkedin'
| 'mastodon'
| 'npm'
| 'slack'
| 'twitter'
| 'x'
| 'youtube'
| { svg: string }
```
## footer
- 타입: `Footer`
- [frontmatter](./frontmatter-config#footer)를 통해 페이지별로 재정의 가능
풋터 설정입니다. 풋터에 메시지나 저작권 텍스트를 추가할 수 있지만, 사이드바를 포함하지 않는 페이지에서만 표시됩니다. 이는 디자인 우려사항 때문입니다.
```ts
export default {
themeConfig: {
footer: {
message: 'MIT 라이선스에 따라 릴리즈되었습니다.',
copyright: '저작권 © 2019-현재 Evan You'
}
}
}
```
```ts
export interface Footer {
message?: string
COPYRIGHT?: string
}
```
## editLink
- 타입: `EditLink`
- [frontmatter](./frontmatter-config#editlink)를 통해 페이지별로 재정의 가능
편집 링크를 통해 GitHub이나 GitLab과 같은 Git 관리 서비스에서 페이지를 편집하는 링크를 표시할 수 있습니다. [기본 테마: 편집 링크](./default-theme-edit-link)에서 자세한 내용을 확인하세요.
```ts
export default {
themeConfig: {
editLink: {
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
text: 'GitHub에서 이 페이지 편집하기'
}
}
}
```
```ts
export interface EditLink {
pattern: string
text?: string
}
```
## lastUpdated
- 타입: `LastUpdatedOptions`
마지막 업데이트 텍스트와 날짜 형식을 사용자 정의할 수 있습니다.
```ts
export default {
themeConfig: {
lastUpdated: {
text: '업데이트 되었습니다',
formatOptions: {
dateStyle: 'full',
timeStyle: 'medium'
}
}
}
}
```
```ts
export interface LastUpdatedOptions {
/**
* @default '마지막 업데이트'
*/
text?: string
/**
* @default
* {dateStyle: 'short', timeStyle: 'short'}
*/
formatOptions?: Intl.DateTimeFormatOptions & { forceLocale?: boolean }
}
```
## algolia
- 타입: `AlgoliaSearch`
[Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch)를 사용하여 문서 사이트를 검색할 수 있는 옵션입니다. [기본 테마: 검색](./default-theme-search)에서 자세히 알아보세요.
```ts
export interface AlgoliaSearchOptions extends DocSearchProps {
locales?: Record<string, Partial<DocSearchProps>>
}
```
전체 옵션은 [여기](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)에서 확인하세요.
## carbonAds {#carbon-ads}
- 타입: `CarbonAdsOptions`
[Carbon Ads](https://www.carbonads.net/)를 표시할 수 있는 옵션입니다.
```ts
export default {
themeConfig: {
carbonAds: {
code: 'your-carbon-code',
placement: 'your-carbon-placement'
}
}
}
```
```ts
export interface CarbonAdsOptions {
code: string
placement: string
}
```
[기본 테마: Carbon Ads](./default-theme-carbon-ads)에서 자세히 알아보세요.
## docFooter
- 타입: `DocFooter`
영어로 문서를 작성하지 않을 때 이전 및 다음 링크 위에 나타나는 텍스트를 사용자 정의하는 데 사용할 수 있습니다. 또한 이전/다음 링크를 전역적으로 비활성화할 수 있습니다. 이전/다음 링크를 선택적으로 활성화/비활성화하려면 [frontmatter](./default-theme-prev-next-links)를 사용할 수 있습니다.
```ts
export default {
themeConfig: {
docFooter: {
prev: '이전 페이지',
next: '다음 페이지'
}
}
}
```
```ts
export interface DocFooter {
prev?: string | false
next?: string | false
}
```
## darkModeSwitchLabel
- 타입: `string`
- 기본값: `외관`
어두운 모드 전환 레이블을 사용자 정의하는 데 사용할 수 있습니다. 이 레이블은 모바일 뷰에서만 표시됩니다.
## lightModeSwitchTitle
- 타입: `string`
- 기본값: `라이트 테마로 전환`
호버 시 나타나는 라이트 모드 전환 제목을 사용자 정의하는 데 사용할 수 있습니다.
## darkModeSwitchTitle
- 타입: `string`
- 기본값: `어두운 테마로 전환`
호버 시 나타나는 어두운 모드 전환 제목을 사용자 정의하는 데 사용할 수 있습니다.
## sidebarMenuLabel
- 타입: `string`
- 기본값: `메뉴`
사이드바 메뉴 레이블을 사용자 정의하는 데 사용할 수 있습니다. 이 레이블은 모바일 뷰에서만 표시됩니다.
## returnToTopLabel
- 타입: `string`
- 기본값: `맨 위로 돌아가기`
맨 위로 돌아가기 버튼의 레이블을 사용자 정의하는 데 사용할 수 있습니다. 이 레이블은 모바일 뷰에서만 표시됩니다.
## langMenuLabel
- 타입: `string`
- 기본값: `언어 변경`
내비게이션 바의 언어 토글 버튼의 aria-label을 사용자 정의하는 데 사용됩니다. [i18n](../guide/i18n)을 사용하는 경우에만 사용됩니다.
## externalLinkIcon
- 타입: `boolean`
- 기본값: `false`
마크다운의 외부 링크 옆에 외부 링크 아이콘을 표시할지 여부입니다.

@ -0,0 +1,60 @@
# 편집 링크 {#edit-link}
## 사이트 레벨 설정 {#site-level-config}
편집 링크를 사용하면 GitHub이나 GitLab과 같은 Git 관리 서비스에서 페이지를 편집하는 링크를 표시할 수 있습니다. 활성화하려면, `themeConfig.editLink` 옵션을 설정에 추가하세요.
```js
export default {
themeConfig: {
editLink: {
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path'
}
}
}
```
`pattern` 옵션은 링크의 URL 구조를 정의하며, `:path`는 페이지 경로로 대체됩니다.
또한 [`PageData`](./runtime-api#usedata)를 인수로 받아 URL 문자열을 반환하는 순수 함수를 넣을 수도 있습니다.
```js
export default {
themeConfig: {
editLink: {
pattern: ({ filePath }) => {
if (filePath.startsWith('packages/')) {
return `https://github.com/acme/monorepo/edit/main/${filePath}`
} else {
return `https://github.com/acme/monorepo/edit/main/docs/${filePath}`
}
}
}
}
}
```
이 함수는 부작용이 없어야 하며, 범위 외의 것에 접근할 수 없으며, 브라우저에서 직렬화되어 실행됩니다.
기본적으로, 이 옵션은 문서 페이지 하단에 "Edit this page"라는 링크 텍스트를 추가합니다. `text` 옵션을 정의하여 이 텍스트를 사용자 정의할 수 있습니다.
```js
export default {
themeConfig: {
editLink: {
pattern: 'https://github.com/vuejs/vitepress/edit/main/docs/:path',
text: 'GitHub에서 이 페이지를 편집하세요'
}
}
}
```
## 프론트매터 설정 {#frontmatter-config}
프론트매터의 `editLink` 옵션을 사용하여 페이지별로 이 기능을 비활성화할 수 있습니다:
```yaml
---
editLink: false
---
```

@ -0,0 +1,53 @@
# 푸터 {#footer}
VitePress는 `themeConfig.footer`가 존재할 때 페이지 하단에 전역 푸터를 표시합니다.
```ts
export default {
themeConfig: {
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2019-present Niceplugin'
}
}
}
```
```ts
export interface Footer {
// 저작권 전에 표시되는 메시지.
message?: string
// 실제 저작권 텍스트.
copyright?: string
}
```
위의 구성은 HTML 문자열도 지원합니다. 예를 들어, 푸터 텍스트에 몇 가지 링크를 구성하고 싶다면, 다음과 같이 구성을 조정할 수 있습니다:
```ts
export default {
themeConfig: {
footer: {
message: '<a href="https://github.com/vuejs/vitepress/blob/main/LICENSE">MIT 라이선스</a>에 따라 릴리즈되었습니다.',
copyright: '저작권 © 2019-현재 <a href="https://github.com/yyx990803">Evan You</a>'
}
}
}
```
::: warning
`message``저작권`에는 `<p>` 요소 안에 렌더링되기 때문에 인라인 요소만 사용할 수 있습니다. 블록 요소를 추가하고 싶다면, 대신 [`layout-bottom`](../guide/extending-default-theme#layout-slots) 슬롯을 사용하는 것을 고려하세요.
:::
푸터는 [사이드바](./default-theme-sidebar)가 보이는 경우에는 표시되지 않습니다.
## 프론트매터 구성 {#frontmatter-config}
이 기능은 프론트매터의 `footer` 옵션을 사용하여 페이지별로 비활성화될 수 있습니다:
```yaml
---
footer: false
---
```

@ -0,0 +1,195 @@
# 홈페이지 {#home-page}
VitePress 기본 테마는 홈페이지 레이아웃을 제공하며, 이 사이트의 [홈페이지](../)에서도 사용된 것을 볼 수 있습니다. [frontmatter](./frontmatter-config)에 `layout: home`을 지정함으로써 여러분의 페이지에도 이를 사용할 수 있습니다.
```yaml
---
layout: home
---
```
하지만, 이 옵션만으로는 큰 효과를 보지 못합니다. `hero``features`와 같은 추가적인 옵션을 설정함으로써 홈페이지에 여러 가지 다른 사전 템플릿 "섹션"을 추가할 수 있습니다.
## Hero 섹션 {#hero-section}
Hero 섹션은 홈페이지 맨 위에 옵니다. 여기에서 Hero 섹션을 구성하는 방법입니다.
```yaml
---
layout: home
hero:
name: VitePress
text: Vite & Vue로 구동되는 정적 사이트 생성기.
tagline: Lorem ipsum...
image:
src: /logo.png
alt: VitePress
actions:
- theme: brand
text: 시작하기
link: /guide/what-is-vitepress
- theme: alt
text: GitHub에서 보기
link: https://github.com/vuejs/vitepress
---
```
```ts
interface Hero {
// `text` 위에 표시되는 문자열입니다. 브랜드 색상이
// 함께 제공되며 제품 이름과 같이 짧을 것으로 예상됩니다.
name?: string
// hero 섹션의 주요 텍스트입니다.
// 이는 `h1` 태그로 정의됩니다.
text: string
// `text` 아래에 표시되는 태그라인입니다.
tagline?: string
// 이미지는 텍스트 및 태그라인 영역 옆에 표시됩니다.
image?: ThemeableImage
// 홈 hero 섹션에 표시할 작업 버튼들입니다.
actions?: HeroAction[]
}
type ThemeableImage =
| string
| { src: string; alt?: string }
| { light: string; dark: string; alt?: string }
interface HeroAction {
// 버튼의 색상 테마입니다. 기본값은 `brand`입니다.
theme?: 'brand' | 'alt'
// 버튼의 레이블입니다.
text: string
// 버튼의 목적지 링크입니다.
link: string
// 링크 타겟 속성입니다.
target?: string
// 링크 rel 속성입니다.
rel?: string
}
```
### 이름 색상 사용자 정의 {#customizing-the-name-color}
VitePress는 `name`에 대해 브랜드 색상 (`--vp-c-brand-1`)을 사용합니다. 하지만, `--vp-home-hero-name-color` 변수를 오버라이딩함으로써 이 색상을 사용자 정의할 수 있습니다.
```css
:root {
--vp-home-hero-name-color: blue;
}
```
또한 `--vp-home-hero-name-background`와 결합하여 `name`에 그라데이션 색상을 부여할 수도 있습니다.
```css
:root {
--vp-home-hero-name-color: transparent;
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #bd34fe, #41d1ff);
}
```
## 기능 섹션 {#features-section}
기능 섹션에서는 Hero 섹션 바로 다음에 보여주고 싶은 기능의 수를 제한 없이 나열할 수 있습니다. 구성하려면 frontmatter에 `features` 옵션을 전달합니다.
각 기능에 대해 이모지나 이미지 형태의 아이콘을 제공할 수 있습니다. 구성된 아이콘가 이미지(svg, png, jpeg...)인 경우, 적절한 너비와 높이를 가진 아이콘을 제공해야 합니다; 필요한 경우 어두운 테마 및 밝은 테마의 변형뿐만 아니라 설명, 본질적인 크기도 제공할 수 있습니다.
```yaml
---
layout: home
features:
- icon: 🛠️
title: 항상 간단하고 최소한의
details: Lorem ipsum...
- icon:
src: /cool-feature-icon.svg
title: 또 다른 멋진 기능
details: Lorem ipsum...
- icon:
dark: /dark-feature-icon.svg
light: /light-feature-icon.svg
title: 또 다른 멋진 기능
details: Lorem ipsum...
---
```
```ts
interface Feature {
// 각 기능 상자에 아이콘을 표시합니다.
icon?: FeatureIcon
// 기능의 제목입니다.
title: string
// 기능의 세부 정보입니다.
details: string
// 기능 구성 요소에서 클릭 시 링크합니다.
// 링크는 내부 또는 외부 모두 가능합니다.
//
// 예: `guide/reference/default-theme-home-page` 또는 `https://example.com`
link?: string
// 기능 구성 요소 내에서 표시될 링크 텍스트입니다.
// `link` 옵션과 함께 사용하는 것이 좋습니다.
//
// 예: `더 알아보기`, `페이지 방문`, 등
linkText?: string
// `link` 옵션을 위한 링크 rel 속성입니다.
//
// 예: `external`
rel?: string
// `link` 옵션을 위한 링크 target 속성입니다.
target?: string
}
type FeatureIcon =
| string
| { src: string; alt?: string; width?: string; height: string }
| {
light: string
dark: string
alt?: string
width?: string
height: string
}
```
## 마크다운 컨텐츠 {#markdown-content}
`---` frontmatter 구분자 아래에 마크다운을 더함으로써 사이트의 홈페이지에 추가 컨텐츠를 추가할 수 있습니다.
````md
---
layout: home
hero:
name: VitePress
text: Vite & Vue로 구동되는 정적 사이트 생성기.
---
## 시작하기
`npx`를 사용하여 바로 VitePress를 사용할 수 있습니다!
```sh
npm init
npx vitepress init
```
````
::: info
VitePress는 항상 `layout: home` 페이지의 추가 컨텐츠에 자동 스타일을 적용하지는 않았습니다. 이전 동작으로 되돌리려면, frontmatter에 `markdownStyles: false`를 추가할 수 있습니다.
:::

@ -0,0 +1,27 @@
# 마지막 업데이트 시간 {#last-updated}
마지막 내용의 업데이트 시간은 페이지의 오른쪽 하단에 표시됩니다. 활성화하려면 config에 `lastUpdated` 옵션을 추가하세요.
::: tip
업데이트 시간을 보려면 markdown 파일을 커밋해야 합니다.
:::
## 사이트 수준 설정 {#site-level-config}
```js
export default {
lastUpdated: true
}
```
## 프런트매터 설정 {#frontmatter-config}
이 기능은 frontmatter의 `lastUpdated` 옵션을 사용하여 페이지별로 비활성화할 수 있습니다:
```yaml
---
lastUpdated: false
---
```
자세한 내용은 [기본 테마: 마지막 업데이트 시간](./default-theme-config#lastupdated)를 참조하세요. 테마 수준에서 참 값을 설정하면 사이트 또는 페이지 수준에서 명시적으로 비활성화하지 않는 한 기능이 활성화됩니다.

@ -0,0 +1,62 @@
# 레이아웃 {#layout}
페이지 [프런트매터](./frontmatter-config)에 `layout` 옵션을 설정함으로써 페이지 레이아웃을 선택할 수 있습니다. `doc`, `page`, `home`의 세 가지 레이아웃 옵션이 있습니다. 아무것도 지정하지 않으면, 해당 페이지는 `doc` 페이지로 처리됩니다.
```yaml
---
layout: doc
---
```
## Doc 레이아웃 {#doc-layout}
`doc` 옵션은 기본 레이아웃이며, 전체 마크다운 내용을 "문서화"된 모양으로 스타일링합니다. 이것은 전체 내용을 `vp-doc` css 클래스로 감싸고, 그 아래 요소들에 스타일을 적용함으로써 작동합니다.
`p``h2`와 같은 거의 모든 일반 요소들은 특별한 스타일링을 받습니다. 따라서 마크다운 내용 내에 사용자 정의 HTML을 추가할 경우, 이러한 스타일들에 영향을 받게 될 것임을 명심하세요.
또한 아래 나열된 문서화 특정 기능들을 제공합니다. 이 기능들은 이 레이아웃에서만 활성화됩니다.
- 편집 링크
- 이전/다음 링크
- 개요
- [카본 광고](./default-theme-carbon-ads)
## 페이지 레이아웃 {#page-layout}
`page` 옵션은 "빈 페이지"로 처리됩니다. 마크다운은 여전히 파싱되며, 모든 [마크다운 확장](../guide/markdown) 기능은 `doc` 레이아웃과 동일하게 작동하지만, 기본 스타일은 적용받지 않습니다.
페이지 레이아웃을 통해 VitePress 테마의 마크업 영향을 받지 않고 모든 것을 직접 스타일링할 수 있습니다. 이는 사용자 정의 페이지를 생성하고 싶을 때 유용합니다.
이 레이아웃에서도 페이지가 일치하는 사이드바 구성이 있는 경우 여전히 사이드바가 표시됨을 유의하세요.
## 홈 레이아웃 {#home-layout}
`home` 옵션은 템플릿화된 "홈페이지"를 생성합니다. 이 레이아웃에서는 `hero``features`와 같은 추가 옵션을 설정해 컨텐츠를 더 자세히 커스터마이즈할 수 있습니다. 자세한 내용은 [기본 테마: 홈 페이지](./default-theme-home-page)를 방문해주세요.
## 레이아웃 없음 {#no-layout}
레이아웃을 원하지 않는 경우, 프런트매터를 통해 `layout: false`를 전달할 수 있습니다. 이 옵션은 완전히 맞춤화된 랜딩 페이지(기본적으로 사이드바, 내비게이션 바, 또는 푸터 없음)를 원할 때 유용합니다.
## 사용자 정의 레이아웃 {#custom-layout}
또한 사용자 정의 레이아웃을 사용할 수 있습니다:
```md
---
layout: foo
---
```
이것은 컨텍스트에 등록된 `foo`라는 이름의 컴포넌트를 찾습니다. 예를 들어, `.vitepress/theme/index.ts`에서 컴포넌트를 전역으로 등록할 수 있습니다:
```ts
import DefaultTheme from 'vitepress/theme'
import Foo from './Foo.vue'
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.component('foo', Foo)
}
}
```

@ -0,0 +1,216 @@
# Nav {#nav}
Nav 페이지 상단에 표시되는 내비게이션 바입니다. 사이트 제목, 전역 메뉴 링크 등을 포함하고 있습니다.
## 사이트 제목 및 로고 {#site-title-and-logo}
기본적으로 nav는 [`config.title`](./site-config#title) 값이 참조하는 사이트 제목을 표시합니다. nav에 표시되는 내용을 변경하고 싶다면 `themeConfig.siteTitle` 옵션에 사용자 정의 텍스트를 정의할 수 있습니다.
```js
export default {
themeConfig: {
siteTitle: 'My Custom Title'
}
}
```
사이트에 로고가 있다면 이미지 경로를 전달하여 표시할 수 있습니다. 로고를 `public` 디렉터리에 위치시키고, 그 절대 경로를 정의해야 합니다.
```js
export default {
themeConfig: {
logo: '/my-logo.svg'
}
}
```
로고를 추가하면 사이트 제목과 함께 표시됩니다. 로고만 필요하고 사이트 제목 텍스트를 숨기고 싶다면 `siteTitle` 옵션에 `false`를 설정하세요.
```js
export default {
themeConfig: {
logo: '/my-logo.svg',
siteTitle: false
}
}
```
`alt` 속성을 추가하거나 어두운/밝은 모드에 따라 로고를 커스터마이즈하고 싶다면 객체로써 로고를 전달할 수 있습니다. 자세한 내용은 [`themeConfig.logo`](./default-theme-config#logo)를 참조하세요.
## 내비게이션 링크 {#navigation-links}
`themeConfig.nav` 옵션을 정의하여 nav에 링크를 추가할 수 있습니다.
```js
export default {
themeConfig: {
nav: [
{ text: '가이드', link: '/guide' },
{ text: '설정', link: '/config' },
{ text: '변경사항', link: 'https://github.com/...' }
]
}
}
```
`text`는 nav에 표시되는 실제 텍스트이고, `link`는 텍스트를 클릭할 때 이동할 링크입니다. 링크는 실제 파일의 경로를 `.md` 접두어 없이 설정하고 항상 `/`로 시작해야 합니다.
Nav 링크는 드롭다운 메뉴일 수도 있습니다. 이를 위해 링크 옵션에 `items` 키를 설정하세요.
```js
export default {
themeConfig: {
nav: [
{ text: '가이드', link: '/guide' },
{
text: '드롭다운 메뉴',
items: [
{ text: '항목 A', link: '/item-1' },
{ text: '항목 B', link: '/item-2' },
{ text: '항목 C', link: '/item-3' }
]
}
]
}
}
```
드롭다운 메뉴 제목(`위 예제에서의 드롭다운 메뉴`)은 드롭다운 대화상자를 열 버튼이 되므로 `link` 속성을 가질 수 없습니다.
더 많은 중첩된 항목을 전달하여 드롭다운 메뉴 항목에 "섹션"을 추가할 수도 있습니다.
```js
export default {
themeConfig: {
nav: [
{ text: '가이드', link: '/guide' },
{
text: '드롭다운 메뉴',
items: [
{
// 섹션의 제목.
text: '섹션 A 제목',
items: [
{ text: '섹션 A 항목 A', link: '...' },
{ text: '섹션 B 항목 B', link: '...' }
]
}
]
},
{
text: '드롭다운 메뉴',
items: [
{
// 제목을 생략할 수도 있습니다.
items: [
{ text: '섹션 A 항목 A', link: '...' },
{ text: '섹션 B 항목 B', link: '...' }
]
}
]
}
]
}
}
```
### 링크의 "active" 상태 커스터마이징 {#customize-link-s-active-state}
현재 페이지가 일치하는 경로에 있을 때 Nav 메뉴 항목이 강조 표시됩니다. 매치되길 원하는 경로를 커스터마이징하고 싶다면 문자열 값으로 `activeMatch` 속성과 정규식을 정의하세요.
```js
export default {
themeConfig: {
nav: [
// 사용자가 `/config/` 경로에 있을 때
// 이 링크는 활성 상태가 됩니다.
{
text: '가이드',
link: '/guide',
activeMatch: '/config/'
}
]
}
}
```
::: warning
`activeMatch`는 정규식 문자열로 예상되지만, 문자열로 정의해야 합니다. 실제 RegExp 객체를 여기서 사용할 수 없는 이유는 빌드 시간 동안 직렬화가 가능하지 않기 때문입니다.
:::
### 링크의 "target" 및 "rel" 속성 커스터마이즈 {#customize-link-s-target-and-rel-attributes}
기본적으로 VitePress는 링크가 외부 링크인지에 따라 `target``rel` 속성을 자동으로 결정합니다. 하지만 원한다면 이들도 커스터마이징할 수 있습니다.
```js
export default {
themeConfig: {
nav: [
{
text: '상품',
link: 'https://www.thegithubshop.com/',
target: '_self',
rel: 'sponsored'
}
]
}
}
```
## 소셜 링크 {#social-links}
[`socialLinks`](./default-theme-config#sociallinks)를 참조하세요.
## 사용자 정의 구성 요소 {#custom-components}
`component` 옵션을 사용하여 탐색 모음에 사용자 정의 구성 요소를 포함할 수 있습니다. `component` 키는 Vue 구성 요소 이름이어야 하며, [Theme.enhanceApp](../guide/custom-theme#theme-interface)을 사용하여 전역으로 등록해야 합니다.
```js
// .vitepress/config.js
export default {
themeConfig: {
nav: [
{
text: 'My Menu',
items: [
{
component: 'MyCustomComponent',
// 구성 요소에 전달할 선택적 props
props: {
title: 'My Custom Component'
}
}
]
},
{
component: 'AnotherCustomComponent'
}
]
}
}
```
그런 다음, 구성 요소를 전역으로 등록해야 합니다:
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import MyCustomComponent from './components/MyCustomComponent.vue'
import AnotherCustomComponent from './components/AnotherCustomComponent.vue'
/** @type {import('vitepress').Theme} */
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.component('MyCustomComponent', MyCustomComponent)
app.component('AnotherCustomComponent', AnotherCustomComponent)
}
}
```
구성 요소가 탐색 모음에 렌더링됩니다. VitePress는 구성 요소에 다음과 같은 추가 props를 제공합니다:
- `screenMenu`: 구성 요소가 모바일 탐색 메뉴 내부에 있는지 여부를 나타내는 선택적 boolean 값
예제는 [여기](https://github.com/vuejs/vitepress/tree/main/__tests__/e2e/.vitepress)에서 확인할 수 있습니다.

@ -0,0 +1,43 @@
# 이전 다음 링크 {#prev-next-links}
이전 페이지와 다음 페이지에 대한 텍스트와 링크를 사용자 정의할 수 있습니다(문서 하단에 표시됨). 사이드바에 있는 텍스트와 다른 텍스트를 원하는 경우에 유용합니다. 또한, 하단부를 비활성화하거나 사이드바에 포함되지 않은 페이지로 링크하는 것이 유용할 수 있습니다.
## prev
- 타입: `string | false | { text?: string; link?: string }`
- 세부 사항:
이전 페이지로의 링크에 표시할 텍스트/링크를 지정합니다. frontmatter에서 이를 설정하지 않으면, 사이드바 구성에서 텍스트/링크를 추론합니다.
- 예제:
- 텍스트만 사용자 정의할 경우:
```yaml
---
prev: '시작하기 | 마크다운'
---
```
- 텍스트와 링크 모두 사용자 정의할 경우:
```yaml
---
prev:
text: '마크다운'
link: '/guide/markdown'
---
```
- 이전 페이지 숨기기:
```yaml
---
prev: false
---
```
## next
`prev`와 동일하지만 다음 페이지에 대한 설정입니다.

@ -0,0 +1,386 @@
---
outline: deep
---
# 검색 {#search}
## 로컬 검색 {#local-search}
VitePress는 [minisearch](https://github.com/lucaong/minisearch/)를 통해 브라우저 내 인덱스를 사용한 퍼지 전문 검색을 지원합니다. 이 기능을 활성화하려면, `.vitepress/config.ts` 파일 내에서 `themeConfig.search.provider` 옵션을 `'local'`로 설정하면 됩니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local'
}
}
})
```
예시 결과:
![검색 모달의 스크린샷](/search.png)
또는, [Algolia DocSearch](#algolia-search)나 <https://www.npmjs.com/package/vitepress-plugin-search>, <https://www.npmjs.com/package/vitepress-plugin-pagefind>과 같은 커뮤니티 플러그인을 사용할 수 있습니다.
### i18n {#local-search-i18n}
다국어 검색을 사용하려면 다음과 같은 설정을 사용할 수 있습니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
locales: {
zh: { // 기본 로케일을 번역하려면 이것을 `root`로 만드십시오.
translations: {
button: {
buttonText: '搜索',
buttonAriaLabel: '搜索'
},
modal: {
displayDetails: '显示详细列表',
resetButtonTitle: '重置搜索',
backButtonTitle: '关闭搜索',
noResultsText: '没有结果',
footer: {
selectText: '选择',
selectKeyAriaLabel: '输入',
navigateText: '导航',
navigateUpKeyAriaLabel: '上箭头',
navigateDownKeyAriaLabel: '下箭头',
closeText: '关闭',
closeKeyAriaLabel: 'esc'
}
}
}
}
}
}
}
}
})
```
### miniSearch 옵션 {#mini-search-options}
다음과 같이 MiniSearch를 구성할 수 있습니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
miniSearch: {
/**
* @type {Pick<import('minisearch').Options, 'extractField' | 'tokenize' | 'processTerm'>}
*/
options: {
/* ... */
},
/**
* @type {import('minisearch').SearchOptions}
* @default
* { fuzzy: 0.2, prefix: true, boost: { title: 4, text: 2, titles: 1 } }
*/
searchOptions: {
/* ... */
}
}
}
}
}
})
```
[MiniSearch 문서](https://lucaong.github.io/minisearch/classes/MiniSearch.MiniSearch.html)에서 더 많은 정보를 얻을 수 있습니다.
### 사용자 정의 콘텐츠 렌더러 {#custom-content-renderer}
색인 생성 전에 마크다운 콘텐츠를 렌더링하는 데 사용되는 함수를 커스터마이즈할 수 있습니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
/**
* @param {string} src
* @param {import('vitepress').MarkdownEnv} env
* @param {import('markdown-it')} md
*/
_render(src, env, md) {
// return html string
}
}
}
}
})
```
이 함수는 클라이언트 사이드 사이트 데이터에서 제거될 것이므로, 여기서 Node.js API를 사용할 수 있습니다.
#### 예시: 검색에서 페이지 제외 {#example-excluding-pages-from-search}
페이지에서 `search: false`를 프론트매터에 추가하여 검색에서 페이지를 제외할 수 있습니다. 또는 다음과 같이 합니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
_render(src, env, md) {
const html = md.render(src, env)
if (env.frontmatter?.search === false) return ''
if (env.relativePath.startsWith('some/path')) return ''
return html
}
}
}
}
})
```
::: warning 참고
사용자 정의 `_render` 함수를 제공하는 경우, `search: false` 프론트매터를 직접 처리해야 합니다. 또한, `md.render`가 호출되기 전에는 `env` 객체가 완전히 채워지지 않으므로, `frontmatter`와 같은 선택적 `env` 속성에 대한 검사는 그 이후에 수행해야 합니다.
:::
#### 예시: 콘텐츠 변환 - 앵커 추가 {#example-transforming-content-adding-anchors}
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'local',
options: {
_render(src, env, md) {
const html = md.render(src, env)
if (env.frontmatter?.title)
return md.render(`# ${env.frontmatter.title}`) + html
return html
}
}
}
}
})
```
## Algolia 검색 {#algolia-search}
VitePress는 [Algolia DocSearch](https://docsearch.algolia.com/docs/what-is-docsearch)를 사용하여 문서 사이트 검색을 지원합니다. 시작 가이드를 참조하세요. 작동하게 하려면 `.vitepress/config.ts`에서 최소한 다음 정보를 제공해야 합니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...'
}
}
}
})
```
### i18n {#algolia-search-i18n}
다국어 검색을 사용하려면 다음과 같은 설정을 사용할 수 있습니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
search: {
provider: 'algolia',
options: {
appId: '...',
apiKey: '...',
indexName: '...',
locales: {
zh: {
placeholder: '搜索文档',
translations: {
button: {
buttonText: '搜索文档',
buttonAriaLabel: '搜索文档'
},
modal: {
searchBox: {
resetButtonTitle: '清除查询条件',
resetButtonAriaLabel: '清除查询条件',
cancelButtonText: '取消',
cancelButtonAriaLabel: '取消'
},
startScreen: {
recentSearchesTitle: '搜索历史',
noRecentSearchesText: '没有搜索历史',
saveRecentSearchButtonTitle: '保存至搜索历史',
removeRecentSearchButtonTitle: '从搜索历史中移除',
favoriteSearchesTitle: '收藏',
removeFavoriteSearchButtonTitle: '从收藏中移除'
},
errorScreen: {
titleText: '无法获取结果',
helpText: '你可能需要检查你的网络连接'
},
footer: {
selectText: '选择',
navigateText: '切换',
closeText: '关闭',
searchByText: '搜索提供者'
},
noResultsScreen: {
noResultsText: '无法找到相关结果',
suggestedQueryText: '你可以尝试查询',
reportMissingResultsText: '你认为该查询应该有结果?',
reportMissingResultsLinkText: '点击反馈'
}
}
}
}
}
}
}
}
})
```
[이 옵션들](https://github.com/vuejs/vitepress/blob/main/types/docsearch.d.ts)은 덮어쓸 수 있습니다. 공식 Algolia 문서에서 더 많은 정보를 알아보세요.
### 크롤러 구성 {#crawler-config}
이 사이트가 사용하는 것을 기반으로 한 예제 구성입니다:
```ts
new Crawler({
appId: '...',
apiKey: '...',
rateLimit: 8,
startUrls: ['https://vitepress.dev/'],
renderJavaScript: false,
sitemaps: [],
exclusionPatterns: [],
ignoreCanonicalTo: false,
discoveryPatterns: ['https://vitepress.dev/**'],
schedule: '매주 토요일 05:10에',
actions: [
{
indexName: 'vitepress',
pathsToMatch: ['https://vitepress.dev/**'],
recordExtractor: ({ $, helpers }) => {
return helpers.docsearch({
recordProps: {
lvl1: '.content h1',
content: '.content p, .content li',
lvl0: {
selectors: '',
defaultValue: '문서'
},
lvl2: '.content h2',
lvl3: '.content h3',
lvl4: '.content h4',
lvl5: '.content h5'
},
indexHeadings: true
})
}
}
],
initialIndexSettings: {
vitepress: {
attributesForFaceting: ['type', 'lang'],
attributesToRetrieve: ['hierarchy', 'content', 'anchor', 'url'],
attributesToHighlight: ['hierarchy', 'hierarchy_camel', 'content'],
attributesToSnippet: ['content:10'],
camelCaseAttributes: ['hierarchy', 'hierarchy_radio', 'content'],
searchableAttributes: [
'unordered(hierarchy_radio_camel.lvl0)',
'unordered(hierarchy_radio.lvl0)',
'unordered(hierarchy_radio_camel.lvl1)',
'unordered(hierarchy_radio.lvl1)',
'unordered(hierarchy_radio_camel.lvl2)',
'unordered(hierarchy_radio.lvl2)',
'unordered(hierarchy_radio_camel.lvl3)',
'unordered(hierarchy_radio.lvl3)',
'unordered(hierarchy_radio_camel.lvl4)',
'unordered(hierarchy_radio.lvl4)',
'unordered(hierarchy_radio_camel.lvl5)',
'unordered(hierarchy_radio.lvl5)',
'unordered(hierarchy_radio_camel.lvl6)',
'unordered(hierarchy_radio.lvl6)',
'unordered(hierarchy_camel.lvl0)',
'unordered(hierarchy.lvl0)',
'unordered(hierarchy_camel.lvl1)',
'unordered(hierarchy.lvl1)',
'unordered(hierarchy_camel.lvl2)',
'unordered(hierarchy.lvl2)',
'unordered(hierarchy_camel.lvl3)',
'unordered(hierarchy.lvl3)',
'unordered(hierarchy_camel.lvl4)',
'unordered(hierarchy.lvl4)',
'unordered(hierarchy_camel.lvl5)',
'unordered(hierarchy.lvl5)',
'unordered(hierarchy_camel.lvl6)',
'unordered(hierarchy.lvl6)',
'content'
],
distinct: true,
attributeForDistinct: 'url',
customRanking: [
'desc(weight.pageRank)',
'desc(weight.level)',
'asc(weight.position)'
],
ranking: [
'words',
'filters',
'typo',
'attribute',
'proximity',
'exact',
'custom'
],
highlightPreTag: '<span class="algolia-docsearch-suggestion--highlight">',
highlightPostTag: '</span>',
minWordSizefor1Typo: 3,
minWordSizefor2Typos: 7,
allowTyposOnNumericTokens: false,
minProximity: 1,
ignorePlurals: true,
advancedSyntax: true,
attributeCriteriaComputedByMinProximity: true,
removeWordsIfNoResults: 'allOptional'
}
}
})
```
<style>
img[src="/search.png"] {
width: 100%;
aspect-ratio: 1 / 1;
}
</style>

@ -0,0 +1,215 @@
# 사이드바 {#sidebar}
사이드바는 문서의 주요 탐색 블록입니다. 사이드바 메뉴를 [`themeConfig.sidebar`](./default-theme-config#sidebar)에서 설정할 수 있습니다.
```js
export default {
themeConfig: {
sidebar: [
{
text: '가이드',
items: [
{ text: '소개', link: '/introduction' },
{ text: '시작하기', link: '/getting-started' },
...
]
}
]
}
}
```
## 기초 {#the-basics}
사이드바 메뉴의 가장 간단한 형태는 링크의 단일 배열을 전달하는 것입니다. 첫 번째 레벨 아이템은 사이드바의 "섹션"을 정의합니다. 해당 섹션의 제목인 `text`와 실제 탐색 링크인 `items`를 포함해야 합니다.
```js
export default {
themeConfig: {
sidebar: [
{
text: '섹션 제목 A',
items: [
{ text: '아이템 A', link: '/item-a' },
{ text: '아이템 B', link: '/item-b' },
...
]
},
{
text: '섹션 제목 B',
items: [
{ text: '아이템 C', link: '/item-c' },
{ text: '아이템 D', link: '/item-d' },
...
]
}
]
}
}
```
`link``/`로 시작하는 실제 파일 경로를 지정해야 합니다. 링크 끝에 슬래시를 추가하면 해당 디렉토리의 `index.md`를 보여줍니다.
```js
export default {
themeConfig: {
sidebar: [
{
text: '가이드',
items: [
// 이것은 `/guide/index.md` 페이지를 보여줍니다.
{ text: '소개', link: '/guide/' }
]
}
]
}
}
```
루트 레벨부터 시작해서 최대 6레벨 깊이까지 사이드바 아이템을 중첩할 수 있습니다. 6레벨 이상 중첩된 아이템은 무시되며 사이드바에 표시되지 않습니다.
```js
export default {
themeConfig: {
sidebar: [
{
text: '레벨 1',
items: [
{
text: '레벨 2',
items: [
{
text: '레벨 3',
items: [
...
]
}
]
}
]
}
]
}
}
```
## 다중 사이드바 {#multiple-sidebars}
페이지 경로에 따라 다른 사이드바를 표시할 수 있습니다. 예를 들어, 이 사이트에 표시된 것과 같이 "가이드" 페이지와 "설정" 페이지와 같이 문서의 콘텐츠 섹션을 별도로 생성할 수 있습니다.
이를 위해 먼저 각 원하는 섹션에 대한 디렉토리로 페이지를 구성합니다:
```
.
├─ guide/
│ ├─ index.md
│ ├─ one.md
│ └─ two.md
└─ config/
├─ index.md
├─ three.md
└─ four.md
```
그다음, 구성을 업데이트하여 각 섹션에 대한 사이드바를 정의합니다. 이때, 배열 대신 객체를 전달해야 합니다.
```js
export default {
themeConfig: {
sidebar: {
// 이 사이드바는 사용자가
// `guide` 디렉토리에 있을 때 표시됩니다.
'/guide/': [
{
text: '가이드',
items: [
{ text: '인덱스', link: '/guide/' },
{ text: '하나', link: '/guide/one' },
{ text: '둘', link: '/guide/two' }
]
}
],
// 이 사이드바는 사용자가
// `config` 디렉토리에 있을 때 표시됩니다.
'/config/': [
{
text: '설정',
items: [
{ text: '인덱스', link: '/config/' },
{ text: '셋', link: '/config/three' },
{ text: '넷', link: '/config/four' }
]
}
]
}
}
}
```
## 접을 수 있는 사이드바 그룹 {#collapsible-sidebar-groups}
사이드바 그룹에 `collapsed` 옵션을 추가하면 각 섹션을 숨기기/보이기 위한 토글 버튼이 나타납니다.
```js
export default {
themeConfig: {
sidebar: [
{
text: '섹션 제목 A',
collapsed: false,
items: [...]
}
]
}
}
```
모든 섹션은 기본적으로 "열림" 상태입니다. 초기 페이지 로드 시 "닫힘" 상태로 하고 싶다면 `collapsed` 옵션을 `true`로 설정하세요.
```js
export default {
themeConfig: {
sidebar: [
{
text: '섹션 제목 A',
collapsed: true,
items: [...]
}
]
}
}
```
## `useSidebar` <Badge type="info" text="composable" />
사이드바 관련 데이터를 반환합니다. 반환된 객체는 다음과 같은 유형을 가집니다:
```ts
export interface DocSidebar {
isOpen: Ref<boolean>
sidebar: ComputedRef<DefaultTheme.SidebarItem[]>
sidebarGroups: ComputedRef<DefaultTheme.SidebarItem[]>
hasSidebar: ComputedRef<boolean>
hasAside: ComputedRef<boolean>
leftAside: ComputedRef<boolean>
isSidebarEnabled: ComputedRef<boolean>
open: () => void
close: () => void
toggle: () => void
}
```
**예제:**
```vue
<script setup>
import { useSidebar } from 'vitepress/theme'
const { hasSidebar } = useSidebar()
</script>
<template>
<div v-if="hasSidebar">사이드바가 있을 때만 보여줍니다</div>
</template>
```

@ -0,0 +1,258 @@
<script setup>
import { VPTeamMembers } from 'vitepress/theme'
const members = [
{
avatar: 'https://github.com/yyx990803.png',
name: 'Evan You',
title: '창작자',
links: [
{ icon: 'github', link: 'https://github.com/yyx990803' },
{ icon: 'twitter', link: 'https://twitter.com/youyuxi' }
]
},
{
avatar: 'https://github.com/kiaking.png',
name: 'Kia King Ishii',
title: '개발자',
links: [
{ icon: 'github', link: 'https://github.com/kiaking' },
{ icon: 'twitter', link: 'https://twitter.com/KiaKing85' }
]
}
]
</script>
# 팀 페이지 {#team-page}
팀을 소개하고 싶다면, 팀 페이지를 구성하기 위해 Team 컴포넌트를 사용할 수 있습니다. 이러한 컴포넌트를 사용하는 방법에는 두 가지가 있습니다. 하나는 문서 페이지에 포함시키는 것이고, 다른 하나는 전체 팀 페이지를 만드는 것입니다.
## 페이지에서 팀 멤버 보여주기 {#show-team-members-in-a-page}
`vitepress/theme`에서 제공되는 `<VPTeamMembers>` 컴포넌트를 사용하여 어떤 페이지에서든 팀 멤버 목록을 표시할 수 있습니다.
```html
<script setup>
import { VPTeamMembers } from 'vitepress/theme'
const members = [
{
avatar: 'https://www.github.com/yyx990803.png',
name: 'Evan You',
title: '창작자',
links: [
{ icon: 'github', link: 'https://github.com/yyx990803' },
{ icon: 'twitter', link: 'https://twitter.com/youyuxi' }
]
},
...
]
</script>
# 우리 팀
우리 훌륭한 팀을 만나보세요.
<VPTeamMembers size="small" :members="members" />
```
위 코드는 카드 형태의 요소로 팀 멤버를 표시합니다. 아래와 비슷하게 표시될 것입니다.
<VPTeamMembers size="small" :members="members" />
`<VPTeamMembers>` 컴포넌트는 `small``medium`의 두 가지 다른 크기로 제공됩니다. 선호도에 달렸지만, 보통 문서 페이지에서 사용할 때는 `small` 크기가 더 잘 맞을 것입니다. 또한 "description"이나 "sponsor" 버튼을 추가하는 등 각 멤버에 대해 더 많은 속성을 추가할 수 있습니다. [`<VPTeamMembers>`](#vpteammembers)에서 더 자세히 알아보세요.
문서 페이지에 팀 멤버를 포함시키는 것은 전용 전체 팀 페이지를 만드는 것이 너무 과한 경우나, 문서 맥락을 참조로 일부 멤버를 소개할 때 좋습니다.
멤버 수가 많거나, 멤버를 보여주기 위해 더 많은 공간을 원한다면 [전체 팀 페이지 만들기](#create-a-full-team-page)를 고려해보세요.
## 전체 팀 페이지 만들기 {#create-a-full-team-page}
문서 페이지에 팀 멤버를 추가하는 대신, 전체 팀 페이지를 만들 수도 있습니다. 사용자 지정 [홈 페이지](./default-theme-home-page)를 생성하는 방법과 유사합니다.
팀 페이지를 생성하려면 먼저, 새 md 파일을 만듭니다. 파일 이름은 중요하지 않지만, 여기서는 `team.md`라고 하겠습니다. 이 파일에서 frontmatter 옵션 `layout: page`를 설정한 다음, `TeamPage` 컴포넌트를 사용하여 페이지 구조를 구성합니다.
```html
---
layout: page
---
<script setup>
import {
VPTeamPage,
VPTeamPageTitle,
VPTeamMembers
} from 'vitepress/theme'
const members = [
{
avatar: 'https://www.github.com/yyx990803.png',
name: 'Evan You',
title: '창작자',
links: [
{ icon: 'github', link: 'https://github.com/yyx990803' },
{ icon: 'twitter', link: 'https://twitter.com/youyuxi' }
]
},
...
]
</script>
<VPTeamPage>
<VPTeamPageTitle>
<template #title>
우리 팀
</template>
<template #lead>
VitePress의 개발은 국제적인
팀에 의해 지도되며, 그 중 일부는 아래에 소개되어 있습니다.
</template>
</VPTeamPageTitle>
<VPTeamMembers
:members="members"
/>
</VPTeamPage>
```
전체 팀 페이지를 생성할 때는 모든 컴포넌트를 `<VPTeamPage>` 컴포넌트로 감싸야 합니다. 이 컴포넌트는 공간 구조와 같은 적절한 레이아웃 구조를 팀 관련 컴포넌트에 적용할 것입니다.
`<VPPageTitle>` 컴포넌트는 페이지 제목 섹션을 추가합니다. 제목은 `<h1>` 헤딩입니다. 팀에 대해 문서화하려면 `#title``#lead` 슬롯을 사용하십시오.
`<VPMembers>`는 문서 페이지에서 사용할 때와 동일하게 작동합니다. 회원 목록을 표시합니다.
### 팀 멤버를 구분하기 위한 섹션 추가 {#add-sections-to-divide-team-members}
팀 페이지에 "섹션"을 추가할 수 있습니다. 예를 들어, 코어 팀 멤버와 커뮤니티 파트너와 같은 다양한 유형의 팀 멤버가 있을 수 있습니다. 이러한 멤버를 섹션으로 나누어 각 그룹의 역할을 더 잘 설명할 수 있습니다.
이를 위해 이전에 만든 `team.md` 파일에 `<VPTeamPageSection>` 컴포넌트를 추가하십시오.
```html
---
layout: page
---
<script setup>
import {
VPTeamPage,
VPTeamPageTitle,
VPTeamMembers,
VPTeamPageSection
} from 'vitepress/theme'
const coreMembers = [...]
const partners = [...]
</script>
<VPTeamPage>
<VPTeamPageTitle>
<template #title>우리 팀</template>
<template #lead>...</template>
</VPTeamPageTitle>
<VPTeamMembers size="medium" :members="coreMembers" />
<VPTeamPageSection>
<template #title>파트너</template>
<template #lead>...</template>
<template #members>
<VPTeamMembers size="small" :members="partners" />
</template>
</VPTeamPageSection>
</VPTeamPage>
```
`<VPTeamPageSection>` 컴포넌트는 `VPTeamPageTitle` 컴포넌트와 유사하게 `#title``#lead` 슬롯을 가질 수 있으며, 팀 멤버를 표시하기 위한 `#members` 슬롯도 가질 수 있습니다.
`#members` 슬롯 안에 `<VPTeamMembers>` 컴포넌트를 넣는 것을 잊지 마십시오.
## `<VPTeamMembers>`
`<VPTeamMembers>` 컴포넌트는 주어진 멤버 목록을 표시합니다.
```html
<VPTeamMembers
size="medium"
:members="[
{ avatar: '...', name: '...' },
{ avatar: '...', name: '...' },
...
]"
/>
```
```ts
interface Props {
// 각 회원의 크기입니다. 기본값은 `medium`입니다.
size?: 'small' | 'medium'
// 표시할 회원 목록입니다.
members: TeamMember[]
}
interface TeamMember {
// 회원의 아바타 이미지입니다.
avatar: string
// 회원의 이름입니다.
name: string
// 회원 이름 아래에 표시될 직함입니다.
// 예: 개발자, 소프트웨어 엔지니어 등
title?: string
// 회원이 속한 조직입니다.
org?: string
// 조직의 URL입니다.
orgLink?: string
// 회원에 대한 설명입니다.
desc?: string
// 소셜 링크입니다. 예: GitHub, Twitter 등.
// 여기에 소셜 링크 객체를 전달할 수 있습니다.
// 참조: https://vitepress.dev/ko/reference/default-theme-config.html#sociallinks
links?: SocialLink[]
// 회원의 후원 페이지 URL입니다.
sponsor?: string
// 후원 링크의 텍스트입니다. 기본값은 'Sponsor'입니다.
actionText?: string
}
```
## `<VPTeamPage>`
전체 팀 페이지를 생성할 때 기본 컴포넌트입니다. 단일 슬롯만 허용합니다. 전달된 모든 팀 관련 컴포넌트에 적절한 스타일을 적용합니다.
## `<VPTeamPageTitle>`
페이지의 "제목" 섹션을 추가합니다. `<VPTeamPage>` 아래에서 맨 처음 사용하는 것이 가장 좋습니다. `#title``#lead` 슬롯을 받습니다.
```html
<VPTeamPage>
<VPTeamPageTitle>
<template #title>
우리 팀
</template>
<template #lead>
VitePress의 개발은 국제적인
팀에 의해 지도되며, 그 중 일부는 아래에 소개되어 있습니다.
</template>
</VPTeamPageTitle>
</VPTeamPage>
```
## `<VPTeamPageSection>`
팀 페이지 내에 "섹션"을 생성합니다. `#title`, `#lead`, 그리고 `#members` 슬롯을 받습니다. `<VPTeamPage>` 안에 원하는 만큼 많은 섹션을 추가할 수 있습니다.
```html
<VPTeamPage>
...
<VPTeamPageSection>
<template #title>파트너</template>
<template #lead>Lorem ipsum...</template>
<template #members>
<VPTeamMembers :members="data" />
</template>
</VPTeamPageSection>
</VPTeamPage>
```

@ -0,0 +1,221 @@
---
outline: deep
---
# 프론트매터 구성 {#frontmatter-config}
프론트매터(머리말)는 페이지 기반 구성을 가능하게 합니다. 모든 마크다운 파일에서, 사이트 수준 또는 테마 수준의 구성 옵션을 재정의하기 위해 프론트매터 구성을 사용할 수 있습니다. 또한, 프론트매터에서만 정의할 수 있는 구성 옵션이 있습니다.
사용 예시:
```md
---
title: VitePress로 문서화
editLink: true
---
```
Vue 표현식에서 `$frontmatter` 전역을 통해 프론트매터 데이터에 접근할 수 있습니다:
```md
{{ $frontmatter.title }}
```
## title
- 유형: `string`
페이지의 제목입니다. [config.title](./site-config#title)과 동일하며, 사이트 수준의 구성을 재정의합니다.
```yaml
---
title: VitePress
---
```
## titleTemplate
- 유형: `string | boolean`
제목의 접미사입니다. [config.titleTemplate](./site-config#titletemplate)와 동일하며, 사이트 수준의 구성을 재정의합니다.
```yaml
---
title: VitePress
titleTemplate: Vite & Vue로 구동되는 정적 사이트 생성기
---
```
## description
- 유형: `string`
페이지의 설명입니다. [config.description](./site-config#description)과 동일하며, 사이트 수준의 구성을 재정의합니다.
```yaml
---
description: VitePress
---
```
## head
- 유형: `HeadConfig[]`
현재 페이지에 삽입할 추가 head 태그를 지정합니다. 사이트 수준 구성에 의해 삽입된 head 태그들 이후에 추가됩니다.
```yaml
---
head:
- - meta
- name: description
content: 안녕하세요
- - meta
- name: keywords
content: 슈퍼 두퍼 SEO
---
```
```ts
type HeadConfig =
| [string, Record<string, string>]
| [string, Record<string, string>, string]
```
## 기본 테마 전용 {#default-theme-only}
다음 프론트매터 옵션은 기본 테마를 사용할 때만 적용됩니다.
### layout
- 유형: `doc | home | page`
- 기본값: `doc`
페이지의 레이아웃을 결정합니다.
- `doc` - 마크다운 콘텐츠에 기본 문서 스타일을 적용합니다.
- `home` - "홈 페이지"를 위한 특별한 레이아웃입니다. `hero``features`와 같은 추가 옵션을 추가하여 아름다운 랜딩 페이지를 빠르게 만들 수 있습니다.
- `page` - `doc`과 비슷하게 동작하지만 콘텐츠에 스타일을 적용하지 않습니다. 완전히 사용자 정의된 페이지를 만들고 싶을 때 유용합니다.
```yaml
---
layout: doc
---
```
### hero <Badge type="info" text="홈 페이지 전용" />
`layout``home`으로 설정될 때 홈 히어로 섹션의 내용을 정의합니다. [기본 테마: 홈 페이지](./default-theme-home-page)에서 자세한 내용을 확인할 수 있습니다.
### features <Badge type="info" text="홈 페이지 전용" />
`layout``home`으로 설정될 때 기능 섹션에 표시할 항목을 정의합니다. [기본 테마: 홈 페이지](./default-theme-home-page)에서 자세한 내용을 확인할 수 있습니다.
### navbar
- 유형: `boolean`
- 기본값: `true`
[navbar](./default-theme-nav)를 표시할지 여부입니다.
```yaml
---
navbar: false
---
```
### sidebar
- 유형: `boolean`
- 기본값: `true`
[sidebar](./default-theme-sidebar)를 표시할지 여부입니다.
```yaml
---
sidebar: false
---
```
### aside
- 유형: `boolean | 'left'`
- 기본값: `true`
`doc` 레이아웃에서 aside 컴포넌트의 위치를 정의합니다.
이 값을 `false`로 설정하면 aside 컨테이너가 렌더링되지 않습니다.\
이 값을 `true`로 설정하면 aside가 오른쪽에 렌더링됩니다.\
이 값을 `'left'`로 설정하면 aside가 왼쪽에 렌더링됩니다.
```yaml
---
aside: false
---
```
### outline
- 유형: `number | [number, number] | 'deep' | false`
- 기본값: `2`
페이지에 표시할 개요의 헤더 레벨입니다. [config.themeConfig.outline.level](./default-theme-config#outline)과 동일하며, 사이트 수준 구성에서 설정한 값을 재정의합니다.
### lastUpdated
- 유형: `boolean | Date`
- 기본값: `true`
현재 페이지의 바닥글에 [마지막 업데이트](./default-theme-last-updated) 텍스트를 표시할지 여부입니다. 날짜와 시간이 지정되면 마지막 git 수정 타임스탬프 대신 표시됩니다.
```yaml
---
lastUpdated: false
---
```
### editLink
- 유형: `boolean`
- 기본값: `true`
현재 페이지의 바닥글에 [편집 링크](./default-theme-edit-link)를 표시할지 여부입니다.
```yaml
---
editLink: false
---
```
### footer
- 유형: `boolean`
- 기본값: `true`
[footer](./default-theme-footer)를 표시할지 여부입니다.
```yaml
---
footer: false
---
```
### pageClass
- 유형: `string`
특정 페이지에 추가 클래스 이름을 추가합니다.
```yaml
---
pageClass: custom-page-class
---
```
그런 다음 `.vitepress/theme/custom.css` 파일에서 이 특정 페이지의 스타일을 사용자 정의할 수 있습니다:
```css
.custom-page-class {
/* 페이지별 스타일 */
}
```

@ -0,0 +1,169 @@
# 런타임 API {#runtime-api}
VitePress는 앱 데이터에 액세스할 수 있도록 몇 가지 내장 API를 제공합니다. 또한 전역적으로 사용할 수 있는 몇 가지 내장 컴포넌트도 제공합니다.
도우미 메서드는 `vitepress`에서 전역적으로 가져올 수 있으며 일반적으로 사용자 지정 테마 Vue 컴포넌트에서 사용됩니다. 그러나 마크다운 파일이 Vue [단일 파일 컴포넌트](https://vuejs.org/guide/scaling-up/sfc.html)로 컴파일되기 때문에 `.md` 페이지 내에서도 사용할 수 있습니다.
`use*`로 시작하는 메서드는 `setup()` 또는 `<script setup>` 내에서만 사용할 수 있는 [Vue 3 구성 API](https://vuejs.org/guide/introduction.html#composition-api) 함수("컴퍼저블")임을 나타냅니다.
## `useData` <Badge type="info" text="컴퍼저블" />
페이지별 데이터를 반환합니다. 반환된 객체는 다음 유형을 가집니다:
```ts
interface VitePressData<T = any> {
/**
* 사이트 수준 메타데이터
*/
site: Ref<SiteData<T>>
/**
* .vitepress/config.js에서의 themeConfig
*/
theme: Ref<T>
/**
* 페이지 수준 메타데이터
*/
page: Ref<PageData>
/**
* 페이지 앞부분 메타데이터
*/
frontmatter: Ref<PageData['frontmatter']>
/**
* 동적 라우트 매개변수
*/
params: Ref<PageData['params']>
title: Ref<string>
description: Ref<string>
lang: Ref<string>
isDark: Ref<boolean>
dir: Ref<string>
localeIndex: Ref<string>
/**
* 현재 위치 해시
*/
hash: Ref<string>
}
interface PageData {
title: string
titleTemplate?: string | boolean
description: string
relativePath: string
filePath: string,
headers: Header[]
frontmatter: Record<string, any>
params?: Record<string, any>
isNotFound?: boolean
lastUpdated?: number
}
```
**예시:**
```vue
<script setup>
import { useData } from 'vitepress'
const { theme } = useData()
</script>
<template>
<h1>{{ theme.footer.copyright }}</h1>
</template>
```
## `useRoute` <Badge type="info" text="컴퍼저블" />
현재 라우트 객체를 다음 유형으로 반환합니다:
```ts
interface Route {
path: string
data: PageData
component: Component | null
}
```
## `useRouter` <Badge type="info" text="컴퍼저블" />
다른 페이지로 프로그래밍 방식으로 이동할 수 있도록 VitePress 라우터 인스턴스를 반환합니다.
```ts
interface Router {
/**
* 현재 route.
*/
route: Route
/**
* 새 URL로 이동합니다.
*/
go: (to?: string) => Promise<void>
/**
* 라우트가 변경되기 전에 호출됩니다. 이동을 취소하려면 `false`를 반환하십시오.
*/
onBeforeRouteChange?: (to: string) => Awaitable<void | boolean>
/**
* 페이지 컴포넌트가 로드되기 전(히스토리 상태가 업데이트된 후)에 호출됩니다.
* 이동을 취소하려면 `false`를 반환하십시오.
*/
onBeforePageLoad?: (to: string) => Awaitable<void | boolean>
/**
* 라우트가 변경된 후 호출됩니다.
*/
onAfterRouteChanged?: (to: string) => Awaitable<void>
}
```
## `withBase` <Badge type="info" text="도움" />
- **타입**: `(path: string) => string`
설정된 [`base`](./site-config#base)를 주어진 URL 경로에 추가합니다. [Base URL](../guide/asset-handling#base-url)도 참조하십시오.
## `<Content />` <Badge type="info" text="컴포넌트" />
`<Content />` 컴포넌트는 렌더링된 마크다운 내용을 표시합니다. [자신만의 테마를 만들 때](../guide/custom-theme) 유용합니다.
```vue
<template>
<h1>커스텀 레이아웃!</h1>
<Content />
</template>
```
## `<ClientOnly />` <Badge type="info" text="컴포넌트" />
`<ClientOnly />` 컴포넌트는 클라이언트 측에서만 슬롯을 렌더링합니다.
VitePress 애플리케이션은 정적 빌드를 생성할 때 Node.js에서 서버 렌더링되므로, 모든 Vue 사용은 범용 코드 요구 사항에 부합해야 합니다. 간단히 말해서, beforeMount 또는 mounted 훅에서만 브라우저 / DOM API에 액세스하십시오.
SSR 친화적이지 않은 컴포넌트(예: 커스텀 지시문이 포함된 경우)를 사용하거나 시연하는 경우 해당 컴포넌트를 `ClientOnly` 컴포넌트 안에 포함시킬 수 있습니다.
```vue-html
<ClientOnly>
<NonSSRFriendlyComponent />
</ClientOnly>
```
- 관련: [SSR 호환성](../guide/ssr-compat)
## `$frontmatter` <Badge type="info" text="템플릿 전역" />
Vue 표현식에서 현재 페이지의 [앞부분 메타데이터](../guide/frontmatter)를 직접 액세스합니다.
```md
---
title: 안녕하세요
---
# {{ $frontmatter.title }}
```
## `$params` <Badge type="info" text="템플릿 전역" />
Vue 표현식에서 현재 페이지의 [동적 라우트 매개변수](../guide/routing#dynamic-routes)를 직접 액세스합니다.
```md
- package name: {{ $params.pkg }}
- version: {{ $params.version }}
```

@ -0,0 +1,722 @@
---
outline: deep
---
# 사이트 설정 {#site-config}
사이트 설정은 사이트의 전역 설정을 정의할 수 있는 곳입니다. 앱 설정 옵션은 사용되는 테마에 상관없이 모든 VitePress 사이트에 적용되는 설정을 정의합니다. 예를 들어, 기본 디렉토리 또는 사이트의 제목 등이 있습니다.
## 개요 {#overview}
### 설정 해석 {#config-resolution}
설정 파일은 항상 `<root>/.vitepress/config.[ext]`에서 해석되며, 여기서 `<root>`는 여러분의 VitePress [프로젝트 루트](../guide/routing#root-and-source-directory), 그리고 `[ext]`는 지원되는 파일 확장명 중 하나입니다. TypeScript는 기본적으로 지원됩니다. 지원되는 확장명에는 `.js`, `.ts`, `.mjs`, 그리고 `.mts`가 포함됩니다.
설정 파일에서는 ES 모듈 문법의 사용을 권장합니다. 설정 파일은 객체를 기본 내보내기해야 합니다:
```ts
export default {
// 앱 레벨 설정 옵션
lang: 'en-US',
title: 'VitePress',
description: 'Vite & Vue를 활용한 정적 사이트 생성기.',
...
}
```
::: details 동적(비동기) 설정
동적으로 설정을 생성해야 하는 경우, 함수를 기본 내보내기로 사용할 수도 있습니다. 예를 들면:
```ts
import { defineConfig } from 'vitepress'
export default async () => {
const posts = await (await fetch('https://my-cms.com/blog-posts')).json()
return defineConfig({
// 앱 레벨 설정 옵션
lang: 'en-US',
title: 'VitePress',
description: 'Vite & Vue를 활용한 정적 사이트 생성기.',
// 테마 레벨 설정 옵션
themeConfig: {
sidebar: [
...posts.map((post) => ({
text: post.name,
link: `/posts/${post.name}`
}))
]
}
})
}
```
예를 들어 상위 수준의 `await`도 사용할 수 있습니다:
```ts
import { defineConfig } from 'vitepress'
const posts = await (await fetch('https://my-cms.com/blog-posts')).json()
export default defineConfig({
// 앱 레벨 설정 옵션
lang: 'en-US',
title: 'VitePress',
description: 'Vite & Vue를 활용한 정적 사이트 생성기.',
// 테마 레벨 설정 옵션
themeConfig: {
sidebar: [
...posts.map((post) => ({
text: post.name,
link: `/posts/${post.name}`
}))
]
}
})
```
:::
### 설정 옵션에 대한 인텔리센스 {#config-intellisense}
`defineConfig` 헬퍼를 사용하면 설정 옵션에 대해 TypeScript로 제공되는 인텔리센스를 활용할 수 있습니다. 여러분의 IDE가 지원한다면, JavaScript와 TypeScript 모두에서 작동할 것입니다.
```js
import { defineConfig } from 'vitepress'
export default defineConfig({
// ...
})
```
### 타입이 지정된 테마 설정 {#typed-theme-config}
기본적으로, `defineConfig` 헬퍼는 기본 테마에서 테마 설정 유형을 예상합니다:
```ts
import { defineConfig } from 'vitepress'
export default defineConfig({
themeConfig: {
// 유형은 `DefaultTheme.Config`
}
})
```
커스텀 테마를 사용하고 테마 설정에 대한 타입 검사를 원한다면, 대신 `defineConfigWithTheme`을 사용해야 하며, 일반 인수를 통해 귀하의 커스텀 테마에 대한 설정 유형을 전달해야 합니다:
```ts
import { defineConfigWithTheme } from 'vitepress'
import type { ThemeConfig } from 'your-theme'
export default defineConfigWithTheme<ThemeConfig>({
themeConfig: {
// 유형은 `ThemeConfig`
}
})
```
### Vite, Vue & Markdown 설정 {#vite-vue-markdown-config}
- **Vite**
여러분은 VitePress 설정에서 [vite](#vite) 옵션을 사용하여 기본 Vite 인스턴스를 구성할 수 있습니다. 별도의 Vite 설정 파일을 만들 필요는 없습니다.
- **Vue**
VitePress는 이미 Vite용 공식 Vue 플러그인([@vitejs/plugin-vue](https://github.com/vitejs/vite-plugin-vue))을 포함하고 있습니다. VitePress 설정에서 [vue](#vue) 옵션을 사용하여 그 옵션을 구성할 수 있습니다.
- **Markdown**
[Markdown-It](https://github.com/markdown-it/markdown-it) 인스턴스를 VitePress 설정에서 [markdown](#markdown) 옵션을 사용하여 구성할 수 있습니다.
## 사이트 메타데이터 {#site-metadata}
### title
- 유형: `string`
- 기본값: `VitePress`
- 페이지별로 [frontmatter](./frontmatter-config#title)를 통해 재정의 가능
사이트의 제목입니다. 기본 테마를 사용할 경우, 이것은 내비게이션 바에 표시됩니다.
전체 페이지 제목에 기본 접미사로도 사용됩니다. 그렇지 않으면 [`titleTemplate`](#titletemplate)이 정의되어 있습니다. 개별 페이지의 최종 제목은 첫 번째 `<h1>` 헤더의 텍스트 내용과 전역 `title`을 접미사로 결합한 것입니다. 예를 들어 다음과 같은 설정과 페이지 내용을 가진 경우:
```ts
export default {
title: '나의 멋진 사이트'
}
```
```md
# 안녕하세요
```
페이지의 제목은 `안녕하세요 | 나의 멋진 사이트`가 될 것입니다.
### titleTemplate
- 유형: `string | boolean`
- 페이지별로 [frontmatter](./frontmatter-config#titletemplate)를 통해 재정의 가능
각 페이지의 제목 접미사 또는 전체 제목을 사용자 정의할 수 있습니다. 예를 들면:
```ts
export default {
title: '나의 멋진 사이트',
titleTemplate: '커스텀 접미사'
}
```
```md
# 안녕하세요
```
페이지의 제목은 `안녕하세요 | 커스텀 접미사`가 될 것입니다.
`:title` 기호를 `titleTemplate`에 사용하여 제목이 어떻게 렌더링될지 완전히 사용자 정의할 수 있습니다:
```ts
export default {
titleTemplate: ':title - 커스텀 접미사'
}
```
이 경우 `:title`은 페이지의 첫 번째 `<h1>` 헤더에서 추론된 텍스트로 대체됩니다. 이전 예제 페이지의 제목은 `안녕하세요 - 커스텀 접미사`가 될 것입니다.
이 옵션은 `false`로 설정하여 제목 접미사를 비활성화할 수 있습니다.
### description
- 유형: `string`
- 기본값: `VitePress 사이트`
- 페이지별로 [frontmatter](./frontmatter-config#description)를 통해 재정의 가능
사이트에 대한 설명입니다. 이것은 페이지 HTML의 `<meta>` 태그로 렌더링됩니다.
```ts
export default {
description: 'VitePress 사이트'
}
```
### head
- 유형: `HeadConfig[]`
- 기본값: `[]`
- 페이지별로 [frontmatter](./frontmatter-config#head)를 통해 추가 가능
페이지 HTML의 `<head>` 태그에 렌더링할 추가 요소들입니다. 사용자가 추가한 태그는 VitePress 태그 뒤, `head` 태그가 닫히기 전에 렌더링됩니다.
```ts
type HeadConfig =
| [string, Record<string, string>]
| [string, Record<string, string>, string]
```
#### 예제: 파비콘 추가 {#example-adding-a-favicon}
```ts
export default {
head: [['link', { rel: 'icon', href: '/favicon.ico' }]]
} // base가 설정된 경우, /base/favicon.ico를 사용하세요
/* 다음을 렌더링할 것입니다:
<link rel="icon" href="/favicon.ico">
*/
```
#### 예제: Google Fonts 추가 {#example-adding-google-fonts}
```ts
export default {
head: [
[
'link',
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' }
],
[
'link',
{ rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' }
],
[
'link',
{ href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' }
]
]
}
/* 다음을 렌더링할 것입니다:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet">
*/
```
#### 예제: 서비스 워커 등록 {#example-registering-a-service-worker}
```ts
export default {
head: [
[
'script',
{ id: 'register-sw' },
`;(() => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
}
})()`
]
]
}
/* 다음을 렌더링할 것입니다:
<script id="register-sw">
;(() => {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
}
})()
</script>
*/
```
#### 예제: Google Analytics 사용 {#example-using-google-analytics}
```ts
export default {
head: [
[
'script',
{ async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' }
],
[
'script',
{},
`window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'TAG_ID');`
]
]
}
/* 다음을 렌더링할 것입니다:
<script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'TAG_ID');
</script>
*/
```
### lang
- 유형: `string`
- 기본값: `en-US`
사이트의 lang 속성입니다. 이것은 페이지 HTML의 `<html lang="en-US">` 태그로 렌더링됩니다.
```ts
export default {
lang: 'en-US'
}
```
### base
- 유형: `string`
- 기본값: `/`
사이트가 배포될 기본 URL입니다. 여러분이 사이트를 GitHub 페이지와 같은 하위 경로에 배포할 계획이라면 이것을 설정해야 합니다. 예를 들어, 여러분의 사이트를 `https://foo.github.io/bar/`에 배포할 계획이라면 base를 `'/bar/'`로 설정해야 합니다. 항상 슬래시로 시작하고 끝나야 합니다.
base는 자동으로 다른 옵션에서 /로 시작하는 모든 URL에 자동으로 추가되므로 한 번만 지정하면 됩니다.
```ts
export default {
base: '/base/'
}
```
## 라우팅 {#routing}
### cleanUrls
- 유형: `boolean`
- 기본값: `false`
`true`로 설정하면, VitePress는 URL에서 끝부분 `.html`을 제거합니다. 또한 [클린 URL 생성](../guide/routing#generating-clean-url)을 참조하세요.
::: warning 서버 지원 필요
이를 활성화하려면 호스팅 플랫폼에서 추가 구성이 필요할 수 있습니다. 작동하려면 서버가 `/foo.html`을 방문할 때 `/foo`**리디렉션 없이** 제공할 수 있어야 합니다.
:::
### rewrites
- 유형: `Record<string, string>`
사용자 지정 디렉토리 &lt;-&gt; URL 매핑을 정의합니다. 자세한 내용은 [라우팅: 라우트 재작성](../guide/routing#route-rewrites)을 참조하십시오.
```ts
export default {
rewrites: {
'source/:page': 'destination/:page'
}
}
```
## 빌드 {#build}
### srcDir
- 유형: `string`
- 기본값: `.`
프로젝트 루트에 대해 상대적인 마크다운 페이지가 저장되는 디렉토리입니다. 또한 [루트 및 소스 디렉토리](../guide/routing#root-and-source-directory)를 참조하십시오.
```ts
export default {
srcDir: './src'
}
```
### srcExclude
- 유형: `string`
- 기본값: `undefined`
소스 콘텐츠로 제외해야 하는 마크다운 파일을 일치시키는 [글로브 패턴](https://github.com/mrmlnc/fast-glob#pattern-syntax)입니다.
```ts
export default {
srcExclude: ['**/README.md', '**/TODO.md']
}
```
### outDir
- 유형: `string`
- 기본값: `./.vitepress/dist`
사이트의 빌드 출력 위치로, [프로젝트 루트](../guide/routing#root-and-source-directory)에 대해 상대적입니다.
```ts
export default {
outDir: '../public'
}
```
### assetsDir
- 유형: `string`
- 기본값: `assets`
생성된 자산을 중첩할 디렉토리를 지정합니다. 경로는 [`outDir`](#outdir) 내부에 있어야 하며 이에 대해 상대적으로 해결됩니다.
```ts
export default {
assetsDir: 'static'
}
```
### cacheDir
- 유형: `string`
- 기본값: `./.vitepress/cache`
캐시 파일을 위한 디렉토리로, [프로젝트 루트](../guide/routing#root-and-source-directory)에 대해 상대적입니다. 또한: [cacheDir](https://vitejs.dev/config/shared-options.html#cachedir)을 참조하세요.
```ts
export default {
cacheDir: './.vitepress/.vite'
}
```
### ignoreDeadLinks
- 유형: `boolean | 'localhostLinks' | (string | RegExp | ((link: string) => boolean))[]`
- 기본값: `false`
`true`로 설정하면, VitePress는 죽은 링크로 인해 빌드가 실패하지 않습니다.
`'localhostLinks'`로 설정하면, 빌드가 죽은 링크로 실패하지만, `localhost` 링크는 확인하지 않습니다.
```ts
export default {
ignoreDeadLinks: true
}
```
정확한 url 문자열, 정규식 패턴, 또는 사용자 정의 필터 함수의 배열일 수도 있습니다.
```ts
export default {
ignoreDeadLinks: [
// 정확한 url "/playground"를 무시
'/playground',
// 모든 localhost 링크 무시
/^https?:\/\/localhost/,
// 모든 "/repl/" 포함 링크 무시
/\/repl\//,
// 사용자 정의 함수, "ignore"를 포함한 모든 링크 무시
(url) => {
return url.toLowerCase().includes('ignore')
}
]
}
```
### metaChunk <Badge type="warning" text="실험적" />
- 타입: `boolean`
- 기본값: `false`
`true`로 설정하면, 초기 HTML에 인라인으로 포함되는 대신 별도의 JavaScript 청크로 페이지 메타데이터를 추출합니다. 이렇게 하면 각 페이지의 HTML 페이로드가 줄어들고 페이지 메타데이터 캐싱이 가능해져 사이트에 많은 페이지가 있을 때 서버 대역폭이 줄어듭니다.
### mpa <Badge type="warning" text="실험적" />
- 타입: `boolean`
- 기본값: `false`
`true`로 설정하면, 프로덕션 앱이 [MPA 모드](../guide/mpa-mode)로 빌드됩니다. MPA 모드는 기본적으로 0kb의 JavaScript를 제공하지만, 클라이언트 측 탐색을 비활성화하고 상호작용에 대해 명시적인 동의가 필요합니다.
## 테마 {#theming}
### appearance
- 타입: `boolean | 'dark' | 'force-dark' | 'force-auto' | import('@vueuse/core').UseDarkOptions`
- 기본값: `true`
다크 모드(HTML 요소에 `.dark` 클래스 추가) 활성화 여부입니다.
- 옵션이 `true`로 설정되면, 기본 테마는 사용자의 선호 색상 체계에 따라 결정됩니다.
- 옵션이 `dark`로 설정되면, 테마는 기본적으로 다크 모드가 되며, 사용자가 수동으로 전환할 수 있습니다.
- 옵션이 `false`로 설정되면, 사용자는 테마를 전환할 수 없습니다.
- 옵션이 `'force-dark'`로 설정된 경우, 테마는 항상 어둡게 유지되며 사용자는 이를 변경할 수 없습니다.
- 옵션이 `'force-auto'`로 설정된 경우, 테마는 항상 사용자의 선호 색상에 의해 결정되며 사용자는 이를 변경할 수 없습니다.
이 옵션은 `vitepress-theme-appearance` 키를 사용하여 로컬 스토리지에서 사용자 설정을 복원하는 인라인 스크립트를 삽입합니다. 이는 페이지가 렌더링되기 전에 `.dark` 클래스가 적용되어 깜빡임을 방지합니다.
`appearance.initialValue``'dark' | undefined`만 가능합니다. Refs나 게터는 지원되지 않습니다.
### lastUpdated
- 타입: `boolean`
- 기본값: `false`
Git을 사용하여 각 페이지의 마지막 업데이트 타임스탬프를 가져옵니다. 타임스탬프는 각 페이지의 페이지 데이터에 포함되며, [`useData`](./runtime-api#usedata)를 통해 접근할 수 있습니다.
기본 테마를 사용하는 경우, 이 옵션을 활성화하면 각 페이지의 마지막 업데이트 시간이 표시됩니다. [`themeConfig.lastUpdatedText`](./default-theme-config#lastupdatedtext) 옵션을 통해 텍스트를 사용자 정의할 수 있습니다.
## 사용자 정의 {#customization}
### markdown
- 타입: `MarkdownOption`
Markdown 파서 옵션을 구성합니다. VitePress는 파서로 [Markdown-it](https://github.com/markdown-it/markdown-it)를, 언어 구문을 강조하는 데 [Shiki](https://github.com/shikijs/shiki)를 사용합니다. 이 옵션 안에서 필요에 맞는 다양한 Markdown 관련 옵션을 전달할 수 있습니다.
```js
export default {
markdown: {...}
}
```
모든 사용 가능한 옵션에 대해서는 [타입 선언과 jsdocs](https://github.com/vuejs/vitepress/blob/main/src/node/markdown/markdown.ts)를 확인하세요.
### vite
- 타입: `import('vite').UserConfig`
내부 Vite 개발 서버/번들러에 직접 [Vite 설정](https://vitejs.dev/config/)을 전달합니다.
```js
export default {
vite: {
// Vite 설정 옵션
}
}
```
### vue
- 타입: `import('@vitejs/plugin-vue').Options`
내부 플러그인 인스턴스에 [`@vitejs/plugin-vue` 옵션](https://github.com/vitejs/vite-plugin-vue/tree/main/packages/plugin-vue#options)을 직접 전달합니다.
```js
export default {
vue: {
// @vitejs/plugin-vue 옵션
}
}
```
## 빌드 후크 {#build-hooks}
VitePress 빌드 후크는 웹사이트에 새로운 기능과 동작을 추가할 수 있습니다:
- 사이트맵
- 검색 색인 작성
- PWA
- Teleports
### buildEnd
- 타입: `(siteConfig: SiteConfig) => Awaitable<void>`
`buildEnd`는 빌드 CLI 후크로, 빌드(정적 사이트 생성, SSG) 완료 후 VitePress CLI 프로세스가 종료되기 전에 실행됩니다.
```ts
export default {
async buildEnd(siteConfig) {
// ...
}
}
```
### postRender
- 타입: `(context: SSGContext) => Awaitable<SSGContext | void>`
`postRender`는 SSG 렌더링이 완료되었을 때 호출되는 빌드 후크입니다. SSG 중 Teleports 콘텐츠를 다루는 것을 허용합니다.
```ts
export default {
async postRender(context) {
// ...
}
}
```
```ts
interface SSGContext {
content: string
teleports?: Record<string, string>
[key: string]: any
}
```
### transformHead
- 타입: `(context: TransformContext) => Awaitable<HeadConfig[]>`
`transformHead`는 각 페이지를 생성하기 전에 head를 변환하는 빌드 후크입니다. 정적으로 VitePress 설정에 추가할 수 없는 head 항목을 추가할 수 있습니다. 기존 항목과 자동으로 병합되므로 추가 항목만 반환하면 됩니다.
::: warning
`context` 내부에서 어떤 것도 변형하지 마세요.
:::
```ts
export default {
async transformHead(context) {
// ...
}
}
```
```ts
interface TransformContext {
page: string // 예: index.md (srcDir에 대해 상대적)
assets: string[] // 모든 비-js/css 자산을 전적으로 해결된 공개 URL로
siteConfig: SiteConfig
siteData: SiteData
pageData: PageData
title: string
description: string
head: HeadConfig[]
content: string
}
```
이 후크는 웹사이트를 정적으로 생성할 때만 호출됩니다. 개발 중에는 호출되지 않습니다. 개발 중에 동적 head 항목을 추가해야 하는 경우, [`transformPageData`](#transformpagedata) 후크를 사용할 수 있습니다:
```ts
export default {
transformPageData(pageData) {
pageData.frontmatter.head ??= []
pageData.frontmatter.head.push([
'meta',
{
name: 'og:title',
content:
pageData.frontmatter.layout === 'home'
? `VitePress`
: `${pageData.title} | VitePress`
}
])
}
}
```
#### 예시: 정규 URL `<link>` 추가 {#example-adding-a-canonical-url-link}
```ts
export default {
transformPageData(pageData) {
const canonicalUrl = `https://example.com/${pageData.relativePath}`
.replace(/index\.md$/, '')
.replace(/\.md$/, '.html')
pageData.frontmatter.head ??= []
pageData.frontmatter.head.push([
'link',
{ rel: 'canonical', href: canonicalUrl }
])
}
}
```
### transformHtml
- 타입: `(code: string, id: string, context: TransformContext) => Awaitable<string | void>`
`transformHtml`는 디스크에 저장하기 전 각 페이지의 콘텐츠를 변환하는 빌드 훅입니다.
::: warning
`context` 내에서는 어떠한 것도 변경하지 마세요. 또한, html 콘텐츠를 수정하는 것은 런타임에 수화 문제를 일으킬 수 있습니다.
:::
```ts
export default {
async transformHtml(code, id, context) {
// ...
}
}
```
### transformPageData
- 타입: `(pageData: PageData, context: TransformPageContext) => Awaitable<Partial<PageData> | { [key: string]: any } | void>`
`transformPageData`는 각 페이지의 `pageData`를 변환하는 훅입니다. `pageData`를 직접 변경하거나 변경된 값들을 반환하여 페이지 데이터에 병합할 수 있습니다.
::: warning
`context` 내에서는 어떠한 것도 변경하지 마세요. 또한, 이 작업은 개발 서버의 성능에 영향을 줄 수 있으므로 주의하세요. 특히, 훅에서 네트워크 요청이나 이미지 생성과 같은 무거운 연산을 수행하는 경우에는 조건부 로직을 위해 `process.env.NODE_ENV === 'production'`를 확인할 수 있습니다.
:::
```ts
export default {
async transformPageData(pageData, { siteConfig }) {
pageData.contributors = await getPageContributors(pageData.relativePath)
}
// 또는 병합할 데이터 반환
async transformPageData(pageData, { siteConfig }) {
return {
contributors: await getPageContributors(pageData.relativePath)
}
}
}
```
```ts
interface TransformPageContext {
siteConfig: SiteConfig
}
```

@ -6,7 +6,7 @@
}, },
"files": [ "files": [
{ {
"location": ".vitepress/config/{en,zh,pt,ru,es}.ts", "location": ".vitepress/config/{en,zh,pt,ru,es,ko}.ts",
"pattern": ".vitepress/config/@lang.ts", "pattern": ".vitepress/config/@lang.ts",
"type": "universal" "type": "universal"
}, },
@ -36,6 +36,10 @@
{ {
"label": "Español", "label": "Español",
"lang": "es" "lang": "es"
},
{
"label": "한국어",
"lang": "ko"
} }
], ],
"outDir": ".vitepress/dist/_translations", "outDir": ".vitepress/dist/_translations",

@ -160,7 +160,7 @@ export default createContentLoader('posts/*.md', {
查看它在 [Vue.js 博客](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts)中是如何使用的。 查看它在 [Vue.js 博客](https://github.com/vuejs/blog/blob/main/.vitepress/theme/posts.data.ts)中是如何使用的。
`createContentLoader` API 也可以在[构建钩子](/reference/site-config#build-hooks)中使用: `createContentLoader` API 也可以在[构建钩子](../reference/site-config#build-hooks)中使用:
```js ```js
// .vitepress/config.js // .vitepress/config.js

@ -73,7 +73,7 @@ Cache-Control: max-age=31536000,immutable
cache-control: immutable cache-control: immutable
``` ```
注意:该 `_headers` 文件应放置在 [public 目录](/guide/asset-handling#the-public-directory)中 (在我们的例子中是 `docs/public/_headers`),以便将其逐字复制到输出目录。 注意:该 `_headers` 文件应放置在 [public 目录](./asset-handling#the-public-directory)中 (在我们的例子中是 `docs/public/_headers`),以便将其逐字复制到输出目录。
[Netlify 自定义标头文档](https://docs.netlify.com/routing/headers/) [Netlify 自定义标头文档](https://docs.netlify.com/routing/headers/)

@ -63,10 +63,10 @@ export default DefaultTheme
``` ```
::: warning ::: warning
如果你在使用像是[团队页](/reference/default-theme-team-page)这样的组件,请确保也从 `vitepress/theme-without-fonts` 中导入它们! 如果你在使用像是[团队页](../reference/default-theme-team-page)这样的组件,请确保也从 `vitepress/theme-without-fonts` 中导入它们!
::: :::
如果字体是通过 `@font-face` 引用的本地文件,它将会被作为资源被包含在 `.vitepress/dist/asset` 目录下,并且使用哈希后的文件名。为了预加载这个文件,请使用 [transformHead](/reference/site-config#transformhead) 构建钩子: 如果字体是通过 `@font-face` 引用的本地文件,它将会被作为资源被包含在 `.vitepress/dist/asset` 目录下,并且使用哈希后的文件名。为了预加载这个文件,请使用 [transformHead](../reference/site-config#transformhead) 构建钩子:
```js ```js
// .vitepress/config.js // .vitepress/config.js

@ -48,7 +48,7 @@ if (!import.meta.env.SSR) {
} }
``` ```
因为 [`Theme.enhanceApp`](/guide/custom-theme#theme-interface) 可以是异步的,所以可以有条件地导入并注册访问浏览器 API 的 Vue 插件: 因为 [`Theme.enhanceApp`](./custom-theme#theme-interface) 可以是异步的,所以可以有条件地导入并注册访问浏览器 API 的 Vue 插件:
```js ```js
// .vitepress/theme/index.js // .vitepress/theme/index.js

Loading…
Cancel
Save