{{ post.title }}
+{{ post.body }}
+diff --git a/README.md b/README.md index f906d37f9..72b9fa6b5 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ # vue-router-next [](https://www.npmjs.com/package/vue-router/v/next) [](https://circleci.com/gh/vuejs/vue-router-next) -> This is the repository for Vue Router 4 (for Vue 3) +> 여기는 Vue Router 4에 대한 저장소입니다. (Vue 3를 위한) -
@@ -24,7 +24,7 @@ Vue Router is part of the Vue Ecosystem and is an MIT-licensed open source proje
-@@ -44,7 +44,7 @@ Vue Router is part of the Vue Ecosystem and is an MIT-licensed open source proje
-
@@ -58,29 +58,29 @@ Vue Router is part of the Vue Ecosystem and is an MIT-licensed open source proje
---
-Get started with the [documentation](https://next.router.vuejs.org).
+이 [문서](https://next.router.vuejs.org)로 시작하세요.
-## Quickstart
+## 빠른시작
-- Via CDN: ``
-- In-browser playground on [CodeSandbox](https://codesandbox.io/s/vue-router-4-reproduction-hb9lh)
-- Add it to an existing Vue Project:
+- CDN을 통해: ``
+- [CodeSandbox](https://codesandbox.io/s/vue-router-4-reproduction-hb9lh)의 브라우저 내 playground
+- 기존 Vue 프로젝트에 추가:
```bash
npm install vue-router@4
```
-## Changes from Vue Router 3
+## Vue Router 3에서의 변경사항
-Please consult the [Migration Guide](https://next.router.vuejs.org/guide/migration/).
+[Migration Guide](https://next.router.vuejs.org/guide/migration/)를 참조하세요.
-## Contributing
+## 기여하기
-See [Contributing Guide](https://github.com/vuejs/vue-router-next/blob/master/.github/contributing.md).
+[Contributing Guid](https://github.com/vuejs/vue-router-next/blob/master/.github/contributing.md)를 참조하세요.
-## Special Thanks
+## 특별한 감사
{{ post.body }}
+
+
+
+ In Vue Router 3, I render inside the route component In Vue Router 3, I render inside the route component
-Special thanks to [BrowserStack](https://www.browserstack.com) for letting the maintainers use their service to debug browser specific issues.
+메인테이너가가 서비스를 사용하여 브라우저별 문제를 디버깅 할 수 있도록 해 준 [BrowserStack](https://www.browserstack.com)에 특별히 감사드립니다.
diff --git a/docs/.vitepress/components/HomeSponsors.vue b/docs/.vitepress/components/HomeSponsors.vue
index 92bf73467..827ea1763 100644
--- a/docs/.vitepress/components/HomeSponsors.vue
+++ b/docs/.vitepress/components/HomeSponsors.vue
@@ -23,6 +23,7 @@ import sponsors from './sponsors.json'
const translations = {
'en-US': 'Become a Sponsor!',
'zh-CN': '成为赞助者!',
+ 'ko-KR': '스폰서가 되어 주세요!',
}
diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js
index 02c920e1a..2ab6dcb39 100644
--- a/docs/.vitepress/config.js
+++ b/docs/.vitepress/config.js
@@ -15,7 +15,7 @@ if (process.env.NODE_ENV === 'production') {
/** @type {UserConfig} */
const config = {
- lang: 'en-US',
+ lang: 'en',
title: 'Vue Router',
description: 'The official router for Vue.js.',
head,
@@ -309,6 +309,138 @@ const config = {
},
],
},
+ '/ko/': {
+ lang: 'ko-KR',
+ label: '한국어',
+ selectText: '언어',
+ title: 'Vue Router',
+ description: 'Vue.js 공식 라우터',
+ nav: [
+ {
+ text: '가이드',
+ link: '/ko/guide/',
+ },
+ {
+ text: 'API 레퍼런스',
+ link: '/ko/api/',
+ },
+ {
+ text: 'v4.x',
+ items: [{ text: 'v3.x', link: 'https://router.vuejs.org/ko' }],
+ },
+ {
+ text: '변경내역',
+ link: 'https://github.com/vuejs/vue-router-next/blob/master/CHANGELOG.md',
+ },
+ ],
+
+ sidebar: [
+ {
+ text: '소개',
+ link: '/ko/introduction.html',
+ },
+ {
+ text: '설치',
+ link: '/ko/installation.html',
+ },
+ {
+ text: '핵심',
+ collapsable: false,
+ children: [
+ {
+ text: '시작하기',
+ link: '/ko/guide/',
+ },
+ {
+ text: '동적 라우트 매칭',
+ link: '/ko/guide/essentials/dynamic-matching.html',
+ },
+ {
+ text: '라우트 매칭 문법',
+ link: '/ko/guide/essentials/route-matching-syntax.html',
+ },
+ {
+ text: '중첩된 라우트',
+ link: '/ko/guide/essentials/nested-routes.html',
+ },
+ {
+ text: '프로그래밍 방식 네비게이션',
+ link: '/ko/guide/essentials/navigation.html',
+ },
+ {
+ text: '이름을 가지는 라우트',
+ link: '/ko/guide/essentials/named-routes.html',
+ },
+ {
+ text: '이름을 가지는 뷰',
+ link: '/ko/guide/essentials/named-views.html',
+ },
+ {
+ text: '리다이렉트와 별칭',
+ link: '/ko/guide/essentials/redirect-and-alias.html',
+ },
+ {
+ text: '라우트 컴포넌트에 속성 전달',
+ link: '/ko/guide/essentials/passing-props.html',
+ },
+ {
+ text: 'HTML5 히스토리 모드',
+ link: '/ko/guide/essentials/history-mode.html',
+ },
+ ],
+ },
+ {
+ text: '고급',
+ collapsable: false,
+ children: [
+ {
+ text: '네비게이션 가드 ',
+ link: '/ko/guide/advanced/navigation-guards.html',
+ },
+ {
+ text: '라우트 메타 필드',
+ link: '/ko/guide/advanced/meta.html',
+ },
+ {
+ text: '데이터 가져오기',
+ link: '/ko/guide/advanced/data-fetching.html',
+ },
+ {
+ text: '컴포지션 API',
+ link: '/ko/guide/advanced/composition-api.html',
+ },
+ {
+ text: '트랜지션',
+ link: '/ko/guide/advanced/transitions.html',
+ },
+ {
+ text: '스크롤 동작',
+ link: '/ko/guide/advanced/scroll-behavior.html',
+ },
+ {
+ text: '지연된 로딩',
+ link: '/ko/guide/advanced/lazy-loading.html',
+ },
+ {
+ text: 'RouterLink 확장하기',
+ link: '/ko/guide/advanced/extending-router-link.html',
+ },
+ {
+ text: '네비게이션 실패 처리하기',
+ link: '/ko/guide/advanced/navigation-failures.html',
+ },
+ {
+ text: '동적 라우팅',
+ link: '/ko/guide/advanced/dynamic-routing.html',
+ },
+ ],
+ },
+ {
+ text: 'Vue2에서 이전하기',
+ link: '/ko/guide/migration/index.html',
+ },
+ ],
+ },
},
},
}
diff --git a/docs/guide/essentials/history-mode.md b/docs/guide/essentials/history-mode.md
index 174764732..5ed0bd558 100644
--- a/docs/guide/essentials/history-mode.md
+++ b/docs/guide/essentials/history-mode.md
@@ -1,9 +1,5 @@
# Different History modes
-
{{ post.title }}
+ meta
필드를 `$route.meta` 로 병합해서 제공합니다.
다음 예제 처럼 간단히 쓸 수 있다는 의미입니다
+
+```js
+router.beforeEach((to, from) => {
+ // 경로가 접근 권한을 필요로 하는지 모든 매칭된 경로를 뒤지지 않고
+ if (to.meta.requiresAuth && !auth.isLoggedIn()) {
+ // 이 경로는 접근 권한을 필요로 하기 때문에 로그인 여부를 체크함
+ // 권한이 없다면 로그인 페이지로 리다이렉트
+ return {
+ path: '/login',
+ // 어느 페이지에서 왔는지 저장해둠
+ query: { redirect: to.fullPath },
+ }
+ }
+})
+```
+
+## TypeScript
+
+`RouteMeta` 인터페이스를 확장하여 메타 필드를 입력 할 수 있습니다.
+
+```ts
+// typings.d.ts or router.ts
+import 'vue-router'
+
+declare module 'vue-router' {
+ interface RouteMeta {
+ // is optional
+ isAdmin?: boolean
+ // must be declared by every route
+ requiresAuth: boolean
+ }
+}
+```
diff --git a/docs/ko/guide/advanced/navigation-failures.md b/docs/ko/guide/advanced/navigation-failures.md
new file mode 100644
index 000000000..a6657882d
--- /dev/null
+++ b/docs/ko/guide/advanced/navigation-failures.md
@@ -0,0 +1,92 @@
+# 네비게이션 결과를 기다리기
+
+`router-link` 사용할 때 Vue Router는 `router.push` 를 호출하여 탐색을 트리거합니다. 대부분의 링크에서 예상되는 동작은 사용자를 새 페이지로 이동하는 것이지만 사용자가 동일한 페이지에 남아있어야 하는 몇 가지 상황이 있습니다.
+
+- 사용자가 탐색하려는 페이지에 이미 있습니다.
+- [네비게이션 가드](./navigation-guards.md)함수가 `false`를 반환하여 탐색을 중단합니다.
+- 이전 가드가 완료되지 않은 동안 새로운 내비게이션 가드가 발생합니다.
+- [내비게이션 가드](./navigation-guards.md)가 새로운 위치를 반환하여 다른 곳으로 리디렉션합니다 (예 : `return '/login'` ).
+- [내비게이션 가드](./navigation-guards.md)가 `Error` 를 던집니다.
+
+네비게이션이 끝난후에 추가적으로 무언가를 하고 싶다면 `router.push` 를 호출 한 후 기다릴 방법이 필요합니다. 다른 페이지로 이동할 수있는 모바일 메뉴가 있고 새 페이지로 이동 한 후에 만 메뉴를 숨기고 싶다고 가정 해 보겠습니다. 다음과 같이 할 수 있습니다.
+
+```js
+router.push('/my-profile')
+this.isMenuOpen = false
+```
+
+그러나 이것은 **네비게이션은 비동기적으로 수행되기 때문에 ** 때문에 즉시 메뉴를 닫을 것입니다. 기다리기 위해서는 `router.push` 에서 반환 된 promise를 `await` 해야 합니다.
+
+```js
+await router.push('/my-profile')
+this.isMenuOpen = false
+```
+
+이제 네비게이션이 완료되면 메뉴가 닫힙니다. 하지만 이 코드는 네비게이션이 취소 된 경우에도 메뉴를 닫게 됩니다. 현재 페이지가 페이지를 실제로 변경되었는지 감지하는 방법이 필요합니다.
+
+## 네비게이션 실패 감지하기
+
+네비게이션이 취소되어 사용자가 동일한 페이지에 머무르게 된다면, `router.push`에서 반환한 `Promise` *의 resolve 된 값은 Navigation Failure*가 됩니다. 그렇지 않다면 *falsy* 값 (일반적으로 `undefined` )이됩니다. 이를 통해 네비게이션이 성공하는 경우를 구별 할 수 있습니다.
+
+```js
+const navigationResult = await router.push('/my-profile')
+
+if (navigationResult) {
+ // 네비게이션이 방지됨
+} else {
+ // 네비게이션이 성공함(리다이렉트 포함)
+ this.isMenuOpen = false
+}
+```
+
+*네비게이션 실패(Navigation Failure)* 는 `Error`의 인스턴스로, 여러 추가 정보를 제공합니다. 네비게이션 취소 여부와 그 이유를 담고 있습니다. 이렇게 반환된 네비게이션 결과를 확인 하기 위해서 `isNavigationFailure` 함수를 사용할수 있습니다.
+
+```js
+import { NavigationFailureType, isNavigationFailure } from 'vue-router'
+
+// 페이지 수정중에 저장없이 떠나도 되는지 시도해봄
+const failure = await router.push('/articles/2')
+
+if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
+ // 사용자에게 알림을 보여줌
+ showToast('You have unsaved changes, discard and leave anyway?')
+}
+```
+
+::: tip `isNavigationFailure(failure)` 함수를 호출할떄 두 번째 매개 변수 `failure`를 생략하면 *탐색 실패* 인지 여부 만 확인합니다. :::
+
+## 네비게이션 실패 구분하기
+
+처음에 언급했듯이 탐색을 중단하는 여러 상황이 있으며 모두 다른 *탐색 실패를* 초래합니다. `isNavigationFailure` 및 `NavigationFailureType` 사용하여 구분할 수 있습니다. 세 가지 유형이 있습니다.
+
+- `aborted` : 내비게이션이 발생했을때 내비게이션 가드 내에서 `false`를 반환함
+- `cancelled` : 현재 네비게이션이 완료되기 전에 새 네비게이션이 수행되었음. 예를 들어, 내비게이션 가드안에서 `router.push`가 호출됨(eg: 권한이 없어서 로그인 페이지로 이동시키는등)
+- `duplicated` : 이미 대상 위치에 있기 때문에 네비게이션이 차단되었습니다.
+
+## *네비게이션 실패(Natvigation Failure)* 속성
+
+모든 탐색 실패는 `to` 와 `from`속성을 제공하며, 이를 통해 현재 위치와 가고자 했던 위치를 알수 있습니다.
+
+```js
+// trying to access the admin page
+router.push('/admin').then(failure => {
+ if (isNavigationFailure(failure, NavigationFailureType.redirected)) {
+ failure.to.path // '/admin'
+ failure.from.path // '/'
+ }
+})
+```
+
+모든 경우에, `to` 와 `from` 는 정규화 된 경로 위치입니다.
+
+## 리디렉션 감지
+
+내비게이션 가드 내부에 새 위치를 반환 할 때 진행중인 위치를 무시하는 새 내비게이션을 트리거합니다. 다른 반환 값과 달리 리디렉션은 탐색을 방해하지 않고 새 값 **을 만듭니다** . 이를 알기 위해 Route Location에서 `redirectedFrom` 속성을 읽을수 있습니다.
+
+```js
+await router.push('/my-profile')
+if (router.currentRoute.value.redirectedFrom) {
+ // redirectedFrom is resolved route location like to and from in navigation
+ // guards
+}
+```
diff --git a/docs/ko/guide/advanced/navigation-guards.md b/docs/ko/guide/advanced/navigation-guards.md
new file mode 100644
index 000000000..8c0932373
--- /dev/null
+++ b/docs/ko/guide/advanced/navigation-guards.md
@@ -0,0 +1,248 @@
+# 네비게이션 가드
+
+이름에서 알 수 있듯이 Vue 라우터에서 제공하는 내비게이션 가드는 주로 리디렉션하거나 취소하여 내비게이션을 보호하는 데 사용됩니다. 경로를 네비게이션 하는 과정을 후킹하는 것은 몇가지 방법이 있습니다. 전역, 경로 별, 컴포넌트 내부 구성
+
+## 전역 선행(Before) 가드
+
+`router.beforeEach` 사용하여 전역 선행(Before)가드를 등록할수 있습니다.
+
+```js
+const router = createRouter({ ... })
+
+router.beforeEach((to, from) => {
+ // ...
+ // explicitly return false to cancel the navigation
+ return false
+})
+```
+
+전역 선행(Before)가드는 네비게이션이 요청되었을때 만들어진 순서대로 호출됩니다. 가드는 비동기적으로 해소(resolve) 될수 있기 때문에 모든 훅이 해소되기 전에는 네비게이션은 **대기(Pending)** 상태입니다.
+
+모든 가드 함수는 두 개의 인수를받습니다.
+
+- **`to`** : 탐색중인 [정규화 된 형식](../../api/#routelocationnormalized) 의 목적지 경로 위치.
+- **`from`** : 네비게이션이 출발하는 [되는 정규화 된 형식](../../api/#routelocationnormalized) 의 현재 경로 위치.
+
+선택적으로 다음 값 중 하나를 반환 할 수 있습니다.
+
+- `false` : 현재 탐색을 취소합니다. 브라우저 URL이 변경된 경우 (사용자가 수동으로 또는 뒤로 버튼을 통해) `from` 경로의 URL로 재설정됩니다.
+- [경로 위치](../../api/#routelocationraw): [`router.push()`](../../api/#push) 호출하는 것처럼, 새로운 경로 위치를 전달하여 다른 위치로 리디렉션합니다. `replace: true` 또는 `name: 'home'` 과 같은 옵션을 전달할 수 있습니다. 현재 실행중인 네비게이션을 버리고 `from` 을 새로 가지는 새로운 네비게이션이 만들어집니다.
+
+예기치 않은 상황이 발생 `Error` 발생시킬 수도 있습니다. [`router.onError()`](../../api/#onerror) 를 통해 등록 된 콜백을 호출합니다.
+
+`undefined` 또는 `true` 가 반환되지 않으면 ** 네비게이션에 대한 검증이 완료되고 ** 되고 다음 탐색 가드가 호출됩니다.
+
+모든 동작은 ** `async` 함수나 ** 프로마이즈(Promises)에서도 동일하게 동작합니다.
+
+```js
+router.beforeEach(async (to, from) => {
+ // canUserAccess() returns `true` or `false`
+ const canAccess = await canUserAccess(to)
+ if (!canAccess) return '/login'
+})
+```
+
+### 선택적 세 번째 인자:`next`
+
+이전 버전의 Vue Router에서는 next
세 번째 인자 를 사용할 수도있었습니다. 이것은 일반적인 실수의 원인이었으며 이를 제거하기 위해 [RFC를 거쳤습니다.](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0037-router-return-guards.md#motivation) 그러나 여전히 지원되므로 모든 내비게이션 가드에 세 번째 인수를 전달할 수 있습니다. 이 경우 내비게이션 가드를 통해 주어진 패스에서 **정확히 한 번 `next` 를 호출해야합니다.** 두 번 이상 나타날 수 있지만 논리적 경로가 겹치지 않는 경우에만 겹치지 않으면 후크가 해결되지 않거나 오류가 발생하지 않습니다. 다음은 사용자가 인증되지 않은 경우 /login
으로 리디렉션하는 잘못된 예입니다.
+
+```js
+// BAD
+router.beforeEach((to, from, next) => {
+ if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
+ // if the user is not authenticated, `next` is called twice
+ next()
+})
+```
+
+올바른 버전은 다음과 같습니다.
+
+```js
+// GOOD
+router.beforeEach((to, from, next) => {
+ if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
+ else next()
+})
+```
+
+## 전역 리졸빙 가드(Global Resolve Guards)
+
+`router.beforeResolve` 로 글로벌 가드를 등록 할 수 있습니다. 이는 모든 탐색 에서 트리거되기 때문에 router.beforeEach
와 비슷해 보이지만 네비게이션 이동이 확정되기 직전에 **모든 컴포넌트 가드 및 비동기 경로 컴포넌트가 의존성 해소 된 후에** 의존성 해소 가드(resolve guard)가 호출됩니다. [ 다음은 사용자 지정 메타](./meta.md) 속성 `requiresCamera` 정의한 경로에 대해 사용자가 카메라에 대한 액세스 권한을 부여했는지 확인하는 예입니다.
+
+```js
+router.beforeResolve(async to => {
+ if (to.meta.requiresCamera) {
+ try {
+ await askForCameraPermission()
+ } catch (error) {
+ if (error instanceof NotAllowedError) {
+ // ... handle the error and then cancel the navigation
+ return false
+ } else {
+ // unexpected error, cancel the navigation and pass the error to the global handler
+ throw error
+ }
+ }
+ }
+})
+```
+
+`router.beforeResolve` 는 데이터를 가져 오거나 사용자가 페이지에 들어갈 수없는 경우 수행하지 않으려는 다른 작업을 수행하기에 이상적인 지점입니다.
+
+
+
+## 전역 후행 훅(Global After Hooks)
+
+전역 후행 훅(Global after hook)은 가드와 달리 `next` 함수를 넘겨 받지 않기 때문에 탐색 결정에 영향을 주지 못합니다.
+
+```js
+router.afterEach((to, from) => {
+ sendToAnalytics(to.fullPath)
+})
+```
+
+
+
+분석, 페이지 제목 변경, 페이지 소개 같은 접근성 기능 및 기타 여러 가지에 유용합니다.
+
+[네비게이션 실패](./navigation-failures.md) 를 세 번째 인자로 받을수 있습니다.
+
+```js
+router.afterEach((to, from, failure) => {
+ if (!failure) sendToAnalytics(to.fullPath)
+})
+```
+
+[가이드](./navigation-failures.md) 에서 탐색 실패에 대해 자세히 알아보세요.
+
+## 경로별 가드(Per-Route Guard)
+
+경로 설정 객체에 바로 `beforeEnter` 가드를 정의 할 수 있습니다.
+
+```js
+const routes = [
+ {
+ path: '/users/:id',
+ component: UserDetails,
+ beforeEnter: (to, from) => {
+ // reject the navigation
+ return false
+ },
+ },
+]
+```
+
+`beforeEnter` 가드 **는 경로에 진입할때만 실행되며 ** `params` , `query` 또는 `hash`가 변경될때는 실행 되지 않습니다.(예 : `/users/2` 에서 `/users/3` 하거나 `/users/2#info` 에서 `/users/2#projects` . ** 다른** 경로에서 이 경로로 네비게이션 해올때만 실행됩니다.
+
+`beforeEnter` 에 함수 배열을 전달할 수도 있습니다. 이는 다른 경로에 대해 가드를 재사용 할 때 유용합니다.
+
+```js
+function removeQueryParams(to) {
+ if (Object.keys(to.query).length)
+ return { path: to.path, query: {}, hash: to.hash }
+}
+
+function removeHash(to) {
+ if (to.hash) return { path: to.path, query: to.query, hash: '' }
+}
+
+const routes = [
+ {
+ path: '/users/:id',
+ component: UserDetails,
+ beforeEnter: [removeQueryParams, removeHash],
+ },
+ {
+ path: '/about',
+ component: UserDetails,
+ beforeEnter: [removeQueryParams],
+ },
+]
+```
+
+[경로 메타 필드](./meta.md) 와 [전역 내비게이션 가드](#global-before-guards) 를 사용하여 유사한 동작을 달성 할 수 있습니다.
+
+## 컴포넌트 내부 가드(In-Component Guards)
+
+마지막으로 경로 컴포넌트(라우터 설정에 전달 된 컴포넌트) 내에서 경로 네비게이션 가드를 직접 정의 할 수 있습니다.
+
+### 옵션 API 사용
+
+다음 옵션을 추가하여 구성 요소를 라우팅 할 수 있습니다.
+
+- `beforeRouteEnter`
+- `beforeRouteUpdate`
+- `beforeRouteLeave`
+
+```js
+const UserDetails = {
+ template: `...`,
+ beforeRouteEnter(to, from) {
+ // called before the route that renders this component is confirmed.
+ // does NOT have access to `this` component instance,
+ // because it has not been created yet when this guard is called!
+ },
+ beforeRouteUpdate(to, from) {
+ // called when the route that renders this component has changed,
+ // but this component is reused in the new route.
+ // For example, given a route with params `/users/:id`, when we
+ // navigate between `/users/1` and `/users/2`, the same `UserDetails` component instance
+ // will be reused, and this hook will be called when that happens.
+ // Because the component is mounted while this happens, the navigation guard has access to `this` component instance.
+ },
+ beforeRouteLeave(to, from) {
+ // called when the route that renders this component is about to
+ // be navigated away from.
+ // As with `beforeRouteUpdate`, it has access to `this` component instance.
+ },
+}
+```
+
+The `beforeRouteEnter` guard does **NOT** have access to `this`, because the guard is called before the navigation is confirmed, thus the new entering component has not even been created yet.
+
+However, you can access the instance by passing a callback to `next`. The callback will be called when the navigation is confirmed, and the component instance will be passed to the callback as the argument:
+
+```js
+beforeRouteEnter (to, from, next) {
+ next(vm => {
+ // access to component public instance via `vm`
+ })
+}
+```
+
+Note that `beforeRouteEnter` is the only guard that supports passing a callback to `next`. For `beforeRouteUpdate` and `beforeRouteLeave`, `this` is already available, so passing a callback is unnecessary and therefore *not supported*:
+
+```js
+beforeRouteUpdate (to, from) {
+ // just use `this`
+ this.name = to.params.name
+}
+```
+
+The **leave guard** is usually used to prevent the user from accidentally leaving the route with unsaved edits. The navigation can be canceled by returning `false`.
+
+```js
+beforeRouteLeave (to, from) {
+ const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
+ if (!answer) return false
+}
+```
+
+### Using the composition API
+
+If you are writing your component using the [composition API and a `setup` function](https://v3.vuejs.org/guide/composition-api-setup.html#setup), you can add update and leave guards through `onBeforeRouteUpdate` and `onBeforeRouteLeave` respectively. Please refer to the [Composition API section](./composition-api.md#navigation-guards) for more details.
+
+## The Full Navigation Resolution Flow
+
+1. Navigation triggered.
+2. Call `beforeRouteLeave` guards in deactivated components.
+3. Call global `beforeEach` guards.
+4. Call `beforeRouteUpdate` guards in reused components.
+5. Call `beforeEnter` in route configs.
+6. Resolve async route components.
+7. Call `beforeRouteEnter` in activated components.
+8. Call global `beforeResolve` guards.
+9. Navigation is confirmed.
+10. Call global `afterEach` hooks.
+11. DOM updates triggered.
+12. Call callbacks passed to `next` in `beforeRouteEnter` guards with instantiated instances.
diff --git a/docs/ko/guide/advanced/scroll-behavior.md b/docs/ko/guide/advanced/scroll-behavior.md
new file mode 100644
index 000000000..1d72a5c0d
--- /dev/null
+++ b/docs/ko/guide/advanced/scroll-behavior.md
@@ -0,0 +1,109 @@
+# 스크롤 동작
+
+클라이언트 측 라우팅을 사용할 때 새 경로로 네비게이션 할때 맨 위로 스크롤 하거나 기존 페이지 리로딩처럼 스크롤 위치를 히스트리 이력으로 저장해두었다가 스크롤 위치를 복구 할수 있습니다. Vue Router를 사용하면 이러한 작업을 더 잘 수행 할 수 합니다. 또한 경로 네비게이션에서 스크롤 동작을 완전히 커스터마이징 할 수 있습니다.
+
+**참고 :이 기능은 브라우저가 `history.pushState`를 지원하는 경우에만 작동합니다.**
+
+라우터 인스턴스를 만들 때 `scrollBehavior` 함수를 설정 할 수 있습니다.
+
+```js
+const router = createRouter({
+ history: createWebHashHistory(),
+ routes: [...],
+ scrollBehavior (to, from, savedPosition) {
+ // return desired position
+ }
+})
+```
+
+`scrollBehavior` 함수는 다른 [네비게이션 가드](./navigation-guards.md)처럼 함수 인자로 `to` 과 `from`를 넘겨 받습니다. 세 번째 함수 인자로 `savedPosition`를 넘겨 받을수 있는데 이 인자는 브라우자 앞으로가기/뒤로가기 버튼을 눌러 히스토리 이력에서 `popstate`를 받아 왔을때만 넘겨 받습니다.
+
+이 함수는 [`ScrollToOptions`](https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions) 위치 객체를 반환 할 수 있습니다.
+
+```js
+const router = createRouter({
+ scrollBehavior(to, from, savedPosition) {
+ // 언제나 페이지 제일 위로 이동하기
+ return { top: 0 }
+ },
+})
+```
+
+`el` 통해 CSS 셀렉터나 DOM 앨리먼트를 전달할 수도 있습니다. 그럴 경우 `top` 과 `left` 은 해당 요소에 대한 상대적 오프셋으로 처리됩니다.
+
+```js
+const router = createRouter({
+ scrollBehavior(to, from, savedPosition) {
+ // 언제나 #main으로 부터 10px 만큼 위로 스크롤 시킨다
+ return {
+ // could also be
+ // el: document.getElementById('main'),
+ el: '#main',
+ top: -10,
+ }
+ },
+})
+```
+
+잘못된 값이나 빈 개체가 반환되면 스크롤이 발생하지 않습니다.
+
+`savedPosition` 을 반환하면 뒤로가기 / 앞으로가기 버튼으로 이동할떄 네이티브와 유사하게 동작합니다.
+
+```js
+const router = createRouter({
+ scrollBehavior(to, from, savedPosition) {
+ if (savedPosition) {
+ return savedPosition
+ } else {
+ return { top: 0 }
+ }
+ },
+})
+```
+
+"링크로 스크롤하기" 동작을 흉내낼때
+
+```js
+const router = createRouter({
+ scrollBehavior(to, from, savedPosition) {
+ if (to.hash) {
+ return {
+ el: to.hash,
+ }
+ }
+ },
+})
+```
+
+브라우저가 [스크롤 동작](https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions/behavior)을 지원하는 경우 부드럽게 만들 수 있습니다.
+
+```js
+const router = createRouter({
+ scrollBehavior(to, from, savedPosition) {
+ if (to.hash) {
+ return {
+ el: to.hash,
+ behavior: 'smooth',
+ }
+ }
+ }
+})
+```
+
+## 스크롤 지연
+
+때로는 페이지를 스크롤하기 전에 잠시 기다려야합니다. 예를 들어 트랜지션을 처리 할 때 스크롤하기 전에 트랜지션이 완료 될 때까지 기다립니다. 이를 위해 원하는 위치 설명자를 반환하는 Promise를 반환 할 수 있습니다. 다음은 스크롤하기 전에 500ms를 기다리는 예입니다.
+
+```js
+const router = createRouter({
+ scrollBehavior(to, from, savedPosition) {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ resolve({ left: 0, top: 0 })
+ }, 500)
+ })
+ },
+})
+```
+
+페이지 레벨을 구현하는 컴포넌트의 이벤트를 받아서 각 페이지 컴포넌트의 전환와 스크롤 동작을 잘 동작하게 할수 있습니다. 하지만 다양한 사용예와 복잡성 때문에 단순 구현만 제공하고, 그 외에는직접 구현을 해서 사용할수 있게 하였습니다.
diff --git a/docs/ko/guide/advanced/transitions.md b/docs/ko/guide/advanced/transitions.md
new file mode 100644
index 000000000..d59bf331d
--- /dev/null
+++ b/docs/ko/guide/advanced/transitions.md
@@ -0,0 +1,73 @@
+# 트랜지션(Transitions)
+
+<transition>
에서 메타 필드 와 동적 `name` 을 결합 할 수 있습니다.
+
+```js
+const routes = [
+ {
+ path: '/custom-transition',
+ component: PanelLeft,
+ meta: { transition: 'slide-left' },
+ },
+ {
+ path: '/other-transition',
+ component: PanelRight,
+ meta: { transition: 'slide-right' },
+ },
+]
+```
+
+```html
+
직전과 매우 유사한 예시 사용 :
+
+```html
+
+
예 :
+
+pattern | matched path | $route.params
+--- | --- | ---
+/users/:username | /users/eduardo | `{ username: 'eduardo' }`
+/users/:username/posts/:postId | /users/eduardo/posts/123 | `{ username: 'eduardo', postId: '123' }`
+
+`$route.params` 외에도 `$route` 객체는 `$route.query` 와 같은 기타 유용한 정보도 노출합니다.(URL 에 query 가 있는 경우) `$route.hash` 기타 등 [API Reference](../../api/#routelocationnormalized) 에서 자세한 내용을 확인할 수 있습니다.
+
+이 예제의 작동 데모는 [여기](https://codesandbox.io/s/route-params-vue-router-examples-mlb14?from-embed&initialpath=%2Fusers%2Feduardo%2Fposts%2F1) 에서 찾을 수 있습니다.
+
+
+
+## 매개변수(Params) 변경에 대한 반응
+
+User Settings
+ User {{ $route.params.id }}
+ /users/:userId
와 같은 동적 경로를 사용하지만 Vue Router는 훨씬 더 많은 것을 제공합니다!
+
+:::tip
+단순성을 위해 모든 경로 레코드 path
값에 초점을 맞추기 component
속성을 생략합니다.
+:::
+
+## params에 정규 표현식 사용하기
+
+`:userId` 와 같은 매개 변수를 정의 할 때 내부적으로 다음 정규식 `([^/]+)` `/` 가 아닌 하나 이상의 문자)을 사용하여 URL에서 매개 변수를 추출합니다. 매개 변수 내용을 기반으로 두 경로를 구별 할 필요가없는 한 이것은 잘 작동합니다. 두 경로 `/:orderId` 및 `/:productName` 상상해보십시오. 둘 다 정확히 동일한 URL과 일치하므로이를 구분할 방법이 필요합니다. 가장 쉬운 방법은 경로를 구분하는 정적 섹션을 추가하는 것입니다.
+
+```js
+const routes = [
+ // matches /o/3549
+ { path: '/o/:orderId' },
+ // matches /p/books
+ { path: '/p/:productName' },
+]
+```
+
+그러나 일부 시나리오에서는 정적 섹션 `/o` / `p` 를 추가하고 싶지 않습니다. 그러나 `orderId` 는 항상 숫자이고 `productName` 은 무엇이든 될 수 있으므로 괄호 안에 매개 변수에 대한 사용자 정의 정규식을 지정할 수 있습니다.
+
+```js
+const routes = [
+ // /:orderId -> 숫자만 일치
+ { path: '/:orderId(\\d+)' },
+ // /:productName -> 아무거나 일치
+ { path: '/:productName' },
+]
+```
+
+이제 `/25` 하면 `/:orderId` 와 일치하고 다른 항목으로 이동하면 `/:productName` 과 일치합니다. `routes` 배열의 순서는 중요하지 않습니다!
+
+:::tip
+Make sure to **escape backslashes (`\`)** like we did with `\d` (becomes `\\d`) to actually pass the backslash character in a string in JavaScript.
+:::
+
+## 반복되는 params
+
+`/first/second/third` 와 같은 여러 섹션이있는 경로를 일치시켜야하는 경우 `*` (0 이상) 및 `+` (1 이상)를 사용하여 매개 변수를 반복 가능한 것으로 표시해야합니다.
+
+```js
+const routes = [
+ // /:chapters -> matches /one, /one/two, /one/two/three, etc
+ { path: '/:chapters+' },
+ // /:chapters -> matches /, /one, /one/two, /one/two/three, etc
+ { path: '/:chapters*' },
+]
+```
+
+이렇게하면 문자열 대신 params 배열이 제공되며 명명 된 경로를 사용할 때 배열을 전달해야합니다.
+
+```js
+// 다음의 경우 { path: '/:chapters*', name: 'chapters' },
+router.resolve({ name: 'chapters', params: { chapters: [] } }).href
+// produces /
+router.resolve({ name: 'chapters', params: { chapters: ['a', 'b'] } }).href
+// produces /a/b
+
+// 다음의 경우 { path: '/:chapters+', name: 'chapters' },
+router.resolve({ name: 'chapters', params: { chapters: [] } }).href
+//`chapters`가 비어 있기 때문에 오류가 발생합니다.
+```
+
+**닫는 괄호 뒤에** 추가하여 사용자 지정 Regexp와 결합 할 수도 있습니다.
+
+```js
+const routes = [
+ // only match numbers
+ // matches /1, /1/2, etc
+ { path: '/:chapters(\\d+)+' },
+ // matches /, /1, /1/2, etc
+ { path: '/:chapters(\\d+)*' },
+]
+```
+
+## 옵션 파라메터
+
+`?` 를 사용하여 매개 변수를 선택 사항으로 표시 할 수도 있습니다. 수정 자 (0 또는 1) :
+
+```js
+const routes = [
+ // will match /users and /users/posva
+ { path: '/users/:userId?' },
+ // will match /users and /users/42
+ { path: '/users/:userId(\\d+)?' },
+]
+```
+
+`*` 기술적으로도 매개 변수를 선택 사항으로 표시하지만 `?` 매개 변수는 반복 할 수 없습니다.
+
+## 디버깅
+
+경로가 일치하지 않는 이유를 이해하기 위해 경로가 Regexp로 변환되는 방법을 파헤쳐 야하거나 버그를보고하기 위해 [경로 순위 지정 도구를](https://paths.esm.dev/?p=AAMeJSyAwR4UbFDAFxAcAGAIJXMAAA..#) 사용할 수 있습니다. URL을 통한 경로 공유를 지원합니다.
diff --git a/docs/ko/guide/index.md b/docs/ko/guide/index.md
new file mode 100644
index 000000000..508a17b96
--- /dev/null
+++ b/docs/ko/guide/index.md
@@ -0,0 +1,93 @@
+# 시작하기
+
+Vue + Vue Router 를 사용하여 싱글 페이지 애플리케이션(SPA) 만드는 것은 매우 자연스럽게 느껴집니다. Vue.js로 애플리케이션을 만들때 우리는 이미 컴포넌트들로 구성해서 만들고 있습니다. 그래서 애플리케이션에 Vue Router를 추가할때 , 우리는 컴포넌트를 경로에 매핑하고 Vue Router 에게 렌더링할 위치를 알려주기만 하면 됩니다.
다음은 기본적인 예입니다.
+
+## HTML
+
+```html
+
+
+
+Hello App!
+
모든 컴포넌트 내부 :
+
+```js
+// Home.vue
+export default {
+ computed: {
+ username() {
+ // 잠시 후 'params' 가 무엇인지 알아보겠습니다.
+ return this.$route.params.username
+ },
+ },
+ methods: {
+ goToDashboard() {
+ if (isAuthenticated) {
+ this.$router.push('/dashboard')
+ } else {
+ this.$router.push('/login')
+ }
+ },
+ },
+}
+```
+
+ `setup` 함수 안에서 라우터나 라우트에 접근하려면 `useRouter` 또는 `useRoute` 함수를 사용합니다. [Composition API](./advanced/composition-api.md#accessing-the-router-and-current-route-inside-setup) 에서 자세히 알아볼 것입니다.
+
+문서 전반에 걸쳐 `router` 인스턴스를 자주 사용합니다. `this.$router`는 `createRouter` 를 통해 생성된 `router` 인스턴스를 직접 사용하는 것과 동일합니다. `this.$router` 를 사용하는 이유는 라우팅 조작이 필요한 모든 컴포넌트에서 라우터를 import하고 싶지 않기 때문입니다.
diff --git a/docs/ko/guide/migration/index.md b/docs/ko/guide/migration/index.md
new file mode 100644
index 000000000..ba5522ac6
--- /dev/null
+++ b/docs/ko/guide/migration/index.md
@@ -0,0 +1,422 @@
+# Vue 2에서 마이그레이션
+
+Vue 라우터 API의 대부분은 v3(Vue 2의 경우)에서 v4(Vue 3의 경우)로 재작성하는 동안 변경되지 않았지만, 여전히 애플리케이션을 마이그레이션하는 동안 발생할 수 있는 몇 가지 주요 변경 사항이 있습니다. 이 가이드는 이러한 변경 사항이 발생한 이유와 Vue Router 4에서 작동하도록 애플리케이션을 조정하는 방법을 이해하는 데 도움이 됩니다.
+
+## 주요 변경 사항
+
+변경 사항은 용도에 따라 정렬됩니다. 따라서 이 목록을 순서대로 따르는 것이 좋습니다.
+
+### new Router는 createRouter가 됩니다.
+
+Vue Router는 더 이상 클래스가 아니라 기능의 집합입니다. `new Router()` 를 작성하는 대신 `createRouter` 를 호출해야 합니다.
+
+```js
+// previously was
+// import Router from 'vue-router'
+import { createRouter } from 'vue-router'
+
+const router = createRouter({
+ // ...
+})
+```
+
+### `mode` 를 대체하는 새로운 `history` 옵션
+
+`mode: 'history'`옵션dl `history` 라는 유연한 옵션으로 대체되었습니다. 사용 중인 모드에 따라 적절한 기능으로 교체해야 합니다.
+
+- `"history"`: `createWebHistory()`
+- `"hash"`: `createWebHashHistory()`
+- `"abstract"`: `createMemoryHistory()`
+
+전체 코드는 다음과 같습니다.
+
+```js
+import { createRouter, createWebHistory } from 'vue-router'
+// createWebHashHistory와 createMemoryHistory도 있습니다.
+
+createRouter({
+ history: createWebHistory(),
+ routes: [],
+})
+```
+
+SSR에서는 적절한 history를 수동으로 전달해야 합니다.
+
+```js
+// router.js
+let history = isServer ? createMemoryHistory() : createWebHistory()
+let router = createRouter({ routes, history })
+// server-entry.js 안의 어딘가
+router.push(req.url) // request url
+router.isReady().then(() => {
+ // request를 resolve
+})
+```
+
+**이유** : 기본 솔루션과 같은 고급 사용 사례에 대한 커스텀 history 구현뿐만 아니라 사용되지 않은 history의 트리 쉐이킹을 활성화합니다.
+
+### `base` 옵션을 이동했습니다.
+
+`base` 옵션은 이제 `createWebHistory` (및 기타 history)에 대한 첫 번째 인수로 전달됩니다.
+
+```js
+import { createRouter, createWebHistory } from 'vue-router'
+createRouter({
+ history: createWebHistory('/base-directory/'),
+ routes: [],
+})
+```
+
+### 제거된 `*` (별표 표시 또는 모두 표시) 경로
+
+이제 모든 경로( `*` , `/*` )를 사용자 지정 정규식과 함께 매개변수를 사용하여 정의해야 합니다.
+
+```js
+const routes = [
+ // pathMatch는 파라미터명입니다. 예를들어 /not/found로 이동합니다
+ // { params: { pathMatch: ['not', 'found'] }}
+ // 이 것은 반복되는 매개변수를 의미하는 마지막 * 덕분이며, 이름을 사용하여 찾을 수 없는 경로로 직접 탐색하는 경우 필요합니다.
+ { path: '/:pathMatch(.*)*', name: 'not-found', component: NotFound },
+ // 마지막 `*`를 생력하면, resolve하거나 push할 때, `/`문자가 인코딩됩니다.
+ { path: '/:pathMatch(.*)', name: 'bad-not-found', component: NotFound },
+]
+// named routes를 사용하는 경우의 나쁜 예:
+router.resolve({
+ name: 'bad-not-found',
+ params: { pathMatch: 'not/found' },
+}).href // '/not%2Ffound'
+// 좋은 예:
+router.resolve({
+ name: 'not-found',
+ params: { pathMatch: ['not', 'found'] },
+}).href // '/not/found'
+```
+
+:::tip 이름을 사용하여 찾을 수 없는 경로로 직접 푸시하지 않으려면 반복되는 매개변수에 `*`를 추가할 필요가 없습니다. `router.push('/not/found/url')` 를 호출하면, 올바른 `pathMatch` 매개변수를 제공됩니다. :::
+
+**이유** : Vue Router는 `path-to-regexp` 사용하지 않고, 대신 경로 순위를 부여하고 동적 라우팅을 가능하게 하는 자체 구문 분석 시스템을 구현합니다. 일반적으로 프로젝트당 하나의 포괄(catch-all) 경로를 추가하기 때문에 `*` 대한 특수 구문을 지원하는 데 큰 이점이 없습니다. params의 인코딩은 예측하기 쉽게 하기 위해 예외 없이 경로 전체를 인코딩하는 것입니다.
+
+### `onReady` 를 `isReady` 로 대체
+
+기존 `router.onReady()` 함수는 인수를 취하지 않고 Promise를 반환하는 `router.isReady()` 로 대체되었습니다.
+
+```js
+// 이전
+router.onReady(onSuccess, onError)
+// 이후
+router.isReady().then(onSuccess).catch(onError)
+// 또는 await 사용하기:
+try {
+ await router.isReady()
+ // 성공
+} catch (err) {
+ // 에러
+}
+```
+
+### `scrollBehavior` 변경 사항
+
+`scrollBehavior` 에서 반환된 객체 [`ScrollToOptions`](https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions) 와 유사합니다. `x` 는 `left` 으로 이름이 바뀌고 `y` `top` 으로 이름이 바뀝니다. [RFC를](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0035-router-scroll-position.md) 참조하십시오.
+
+**이유** `ScrollToOptions` 와 유사한 객체를 만들어 네이티브 JS API에 더 친숙하게 만들고 향후 새로운 옵션을 잠재적으로 활성화할 수 있습니다.
+
+### `append
함수를 정의해야 합니다.
+
+```js
+app.config.globalProperties.append = (path, pathToAppend) =>
+ path + (path.endsWith('/') ? '' : '/') + pathToAppend
+```
+
+**이유** : `append` 는 자주 사용되지 않으며, 사용자 영역에서 복제하기 쉽습니다.
+
+### `
기능은 다음과 같습니다.
+
+- 중첩 라우트 맵핑(Nested routes mapping)
+- 동적 라우팅(Dynamic Routing)
+- 모듈식, 컴포넌트 기반 라우트 구성(Modular, component-based router configuration)
+- 라우트 매개변수, 쿼리, 와일드카드(Route params, query, wildcards)
+- Vue.js 의 트랜지션 시스템에서 제공되는 뷰 트랜지션 효과(View transition effects powered by Vue.js' transition system)
+- 세밀한 네비게이션 제어(Fine-grained navigation control)
+- 자동 활성 CSS 클래스와의 링크(Links with automatic active CSS classes)
+- HTML5 히스토리 또는 해시 모드(HTML5 history mode or hash mode)
+- 사용자 정의 가능한 스크롤 동작(Customizable Scroll Behavior)
+- URL 에 대한 올바른 인코딩(Proper encoding for URLs)
+
+[시작하기](./guide/) 또는 [playground](https://github.com/vuejs/vue-router-next/tree/master/playground) 에서 시작해보세요.([`README.md`](https://github.com/vuejs/vue-router-next) 참고).
+