Skip to content

다양한 히스토리 모드

라우터 인스턴스를 만들 때 사용하는 history 옵션을 통해 다양한 히스토리 모드 중 하나를 선택할 수 있습니다.

HTML5 모드

HTML5 모드는 createWebHistory()로 생성하며 권장되는 모드입니다:

js
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    //...
  ],
})

createWebHistory()를 사용하면 URL이 https://example.com/user/id처럼 "일반적인" 형태가 됩니다. 보기 좋죠!

하지만 문제가 하나 있습니다. 우리 앱은 싱글 페이지 클라이언트 사이드 앱이기 때문에, 서버 구성이 올바르지 않으면 사용자가 브라우저에서 https://example.com/user/id에 직접 접근했을 때 404 오류를 보게 됩니다. 이건 좋지 않죠.

걱정할 필요는 없습니다. 이 문제를 해결하려면 서버에 간단한 catch-all fallback 라우트를 추가하면 됩니다. URL이 어떤 정적 asset과도 매치되지 않으면, 앱이 들어 있는 동일한 index.html 페이지를 반환해야 합니다. 다시 깔끔해집니다!

Hash 모드

hash 히스토리 모드는 createWebHashHistory()로 생성합니다:

js
import { createRouter, createWebHashHistory } from 'vue-router'

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    //...
  ],
})

내부적으로 전달되는 실제 URL 앞에 hash 문자(#)를 사용합니다. URL의 이 부분은 서버로 전송되지 않기 때문에 서버 측에서 특별한 처리가 필요하지 않습니다. 하지만 SEO에는 좋지 않은 영향을 줍니다. 이 점이 중요하다면 HTML5 히스토리 모드를 사용하세요.

메모리 모드

메모리 히스토리 모드는 브라우저 환경을 가정하지 않으므로 URL과 상호작용하지 않으며 초기 내비게이션도 자동으로 트리거하지 않습니다. 이 때문에 Node 환경과 SSR에 적합합니다. createMemoryHistory()로 생성하며, app.use(router)를 호출한 뒤 초기 내비게이션을 직접 push해야 합니다.

js
import { createRouter, createMemoryHistory } from 'vue-router'

const router = createRouter({
  history: createMemoryHistory(),
  routes: [
    //...
  ],
})

권장되지는 않지만 브라우저 애플리케이션 안에서도 이 모드를 사용할 수 있습니다. 다만 히스토리가 없기 때문에 뒤로 또는 앞으로 이동할 수 없습니다.

서버 설정 예제

참고: 아래 예제는 앱을 루트 폴더에서 제공한다고 가정합니다. 하위 폴더에 배포한다면 Vue CLI의 publicPath 옵션과 관련된 라우터의 base 속성을 사용해야 합니다. 또한 아래 예제도 루트 폴더 대신 하위 폴더를 사용하도록 조정해야 합니다(예: RewriteBase /RewriteBase /name-of-your-subfolder/로 변경).

Apache

<IfModule mod_negotiation.c>
  Options -MultiViews
</IfModule>

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

mod_rewrite 대신 FallbackResource를 사용할 수도 있습니다.

nginx

nginx
location / {
  try_files $uri $uri/ /index.html;
}

Native Node.js

js
const http = require('http')
const fs = require('fs')
const httpPort = 80

http
  .createServer((req, res) => {
    fs.readFile('index.html', 'utf-8', (err, content) => {
      if (err) {
        console.log('We cannot open "index.html" file.')
      }

      res.writeHead(200, {
        'Content-Type': 'text/html; charset=utf-8',
      })

      res.end(content)
    })
  })
  .listen(httpPort, () => {
    console.log('Server listening on: http://localhost:%s', httpPort)
  })

Express with Node.js

Node.js/Express에서는 connect-history-api-fallback middleware 사용을 고려해 보세요.

Internet Information Services (IIS)

  1. IIS UrlRewrite를 설치합니다
  2. 사이트 루트 디렉터리에 다음과 같은 web.config 파일을 만듭니다:
xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Handle History Mode and custom 404/500" stopProcessing="true">
          <match url="(.*)" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Caddy v2

try_files {path} /

Caddy v1

rewrite {
    regexp .*
    to {path} /
}

Firebase hosting

다음을 firebase.json에 추가하세요:

json
{
  "hosting": {
    "public": "dist",
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

Netlify

배포 파일에 포함되는 _redirects 파일을 만드세요:

/* /index.html 200

vue-cli, nuxt, vite 프로젝트에서는 이 파일을 보통 static 또는 public 폴더 아래에 둡니다.

문법에 대한 자세한 내용은 Netlify 문서에서 확인할 수 있습니다. netlify.toml을 생성리디렉션 을 다른 Netlify 기능과 함께 사용할 수도 있습니다.

Vercel

프로젝트 루트 디렉터리에 다음 내용의 vercel.json 파일을 만드세요:

json
{
  "rewrites": [{ "source": "/:path*", "destination": "/index.html" }]
}

주의 사항

이 방식에는 주의할 점이 있습니다. 이제 찾을 수 없는 모든 경로가 index.html 파일을 제공하게 되므로 서버는 더 이상 404 오류를 보고하지 않습니다. 이 문제를 해결하려면 Vue 앱 안에 catch-all 라우트를 구현해 404 페이지를 표시해야 합니다:

js
const router = createRouter({
  history: createWebHistory(),
  routes: [{ path: '/:pathMatch(.*)', component: NotFoundComponent }],
})

또는 Node.js 서버를 사용 중이라면 서버 측에서 라우터를 사용해 들어오는 URL을 매치하고, 어떤 라우트도 매치되지 않으면 404로 응답하는 방식으로 fallback을 구현할 수 있습니다. 자세한 내용은 Vue 서버 사이드 렌더링 문서를 참고하세요.

모두를 위한 문서 한글화