컨텐츠로 건너뛰기

라우팅

Astro는 파일 기반 라우팅을 사용하여 프로젝트 src/pages/ 디렉터리의 파일 레이아웃을 기반으로 빌드 URL을 생성합니다.

Astro는 표준 HTML <a> 요소를 사용하여 경로를 탐색합니다. 프레임워크별 <Link> 컴포넌트는 제공되지 않습니다.

src/pages/index.astro
<p>Read more <a href="/about/">about</a> Astro!</p>
<!-- `base: "/docs"`가 구성된 경우 -->
<p>Learn more in our <a href="/docs/reference/">reference</a> section!</p>

.astro 페이지 컴포넌트src/pages/ 디렉터리의 Markdown 및 MDX 파일 (.md, .mdx)은 자동으로 웹사이트의 페이지가 됩니다. 각 페이지의 경로는 src/pages/ 디렉터리의 경로와 파일 이름에 해당합니다.

# Example: Static routes
src/pages/index.astro -> mysite.com/
src/pages/about.astro -> mysite.com/about
src/pages/about/index.astro -> mysite.com/about
src/pages/about/me.astro -> mysite.com/about/me
src/pages/posts/1.md -> mysite.com/posts/1

Astro 페이지 파일은 파일 이름에 동적 경로 매개변수를 지정하여 일치하는 여러 페이지를 생성할 수 있습니다. 예를 들어 src/pages/authors/[author].astro 파일은 블로그의 모든 작성자에 대한 약력 페이지를 생성합니다. author는 페이지 내부에서 액세스할 수 있는 매개변수 가 됩니다.

Astro의 기본 정적 출력 모드에서 이러한 페이지는 빌드 시 생성되므로, 해당 파일을 가져오는 author 목록을 미리 결정해야 합니다. SSR 모드에서는 일치하는 경로에 대한 요청이 있을 때 페이지가 생성됩니다.

모든 경로는 빌드 시 결정되어야 하기 때문에 동적 경로는 params 속성이 있는 객체 배열을 반환하는 getStaticPaths()를 내보내야 합니다. 이러한 각 객체는 해당 경로를 생성합니다.

[dog].astro 파일은 파일 이름에 동적 dog 매개변수를 정의하므로 getStaticPaths()에 의해 반환된 객체는 paramsdog을 포함해야 합니다. 그러면 페이지는 Astro.params를 사용하여 이 매개변수에 액세스할 수 있습니다.

src/pages/dogs/[dog].astro
---
export function getStaticPaths() {
return [
{params: {dog: 'clifford'}},
{params: {dog: 'rover'}},
{params: {dog: 'spot'}},
];
}
const { dog } = Astro.params;
---
<div>Good dog, {dog}!</div>

이렇게 하면 /dogs/clifford, /dogs/rover, /dogs/spot의 세 페이지가 생성되며 각각에 해당되는 개 이름을 표시합니다.

파일 이름에는 여러 매개변수가 포함될 수 있으며, 이 매개변수는 getStaticPaths()params 객체에 모두 포함되어야 합니다.

src/pages/[lang]-[version]/info.astro
---
export function getStaticPaths () {
return [
{params: {lang: 'en', version: 'v1'}},
{params: {lang: 'fr', version: 'v2'}},
];
}
const { lang, version } = Astro.params;
---
...

그러면 /en-v1/info/fr-v2/info가 생성됩니다.

매개변수는 경로의 개별 부분에 포함될 수 있습니다. 예를 들어, 위와 동일한 getStaticPaths()가 있는 src/pages/[lang]/[version]/info.astro 파일은 /en/v1/info/fr/v2/info 경로를 생성합니다.

getStaticPaths() 함수에 제공되는 params는 디코딩되지 않았습니다. 매개변수 값을 디코딩해야 할 때는 decodeURI 함수를 사용하세요.

src/pages/[slug].astro
---
export function getStaticPaths() {
return [
{ params: { slug: decodeURI("%5Bpage%5D") } }, // "[page]"로 디코딩
]
}
---
getStaticPaths()에 대해 자세히 알아보세요.
관련 레시피: 국제화 기능 추가

URL 라우팅에 더 많은 유연성이 필요한 경우 나머지 매개변수 ([...path])를 .astro 파일 이름에 추가하여 모든 깊이의 파일 경로와 일치시킵니다.

src/pages/sequences/[...path].astro
---
export function getStaticPaths() {
return [
{params: {path: 'one/two/three'}},
{params: {path: 'four'}},
{params: {path: undefined }}
]
}
const { path } = Astro.params;
---
...

그러면 /sequences/one/two/three, /sequences/four, /sequences가 생성됩니다. (나머지 매개변수를 undefined로 설정하면 최상위 페이지와 일치하게 됩니다.)

나머지 매개변수는 다른 명명된 매개변수와 함께 사용할 수 있습니다. 예를 들어 GitHub의 파일 뷰어는 다음 동적 경로로 표시될 수 있습니다.

/[org]/[repo]/tree/[branch]/[...file]

이 예시에서 /withastro/astro/tree/main/docs/public/favicon.svg에 대한 요청은 다음과 같은 명명된 매개변수로 분할됩니다.

{
org: 'withastro',
repo: 'astro',
branch: 'main',
file: 'docs/public/favicon.svg'
}

예: 여러 수준의 동적 페이지

섹션 제목: 예: 여러 수준의 동적 페이지

다음 예시에서 나머지 매개변수 ([...slug])와 getStaticPaths()props 기능은 다양한 깊이의 슬러그에 대한 페이지를 생성합니다.

src/pages/[...slug].astro
---
export async function getStaticPaths() {
const pages = [
{
slug: undefined,
title: "Astro Store",
text: "Welcome to the Astro store!",
},
{
slug: "products",
title: "Astro products",
text: "We have lots of products for you",
},
{
slug: "products/astro-handbook",
title: "The ultimate Astro handbook",
text: "If you want to learn Astro, you must read this book.",
},
];
return pages.map(({ slug, title, text }) => {
return {
params: { slug },
props: { title, text },
};
});
}
const { title, text } = Astro.props;
---
<html>
<head>
<title>{title}</title>
</head>
<body>
<h1>{title}</h1>
<p>{text}</p>
</body>
</html>

SSR 모드에서 동적 경로는 동일한 방식으로 정의됩니다. 임의의 문자열이나 경로와 일치하도록 파일 이름에 [param] 또는 [...path] 대괄호를 포함합니다. 그러나 경로가 더 이상 미리 빌드되지 않기 때문에 페이지는 일치하는 모든 경로에 제공됩니다. 이는 “정적” 경로가 아니므로 getStaticPaths를 사용하면 안 됩니다.

src/pages/resources/[resource]/[id].astro
---
const { resource, id } = Astro.params;
---
<h1>{resource}: {id}</h1>

이 페이지는 resourceid 값 (resources/users/1, resources/colors/blue 등)에 대해 제공됩니다.

SSR에 대한 [...slug] 예시 수정

섹션 제목: SSR에 대한 [...slug] 예시 수정

SSR 페이지는 getStaticPaths()를 사용할 수 없기 때문에 props를 받을 수 없습니다. 이전 예시는 객체에서 slug 매개변수 값을 조회하여 SSR 모드에 맞게 조정할 수 있습니다. 경로가 루트 (”/“)에 있으면 슬러그 매개변수는 undefined가 됩니다. 객체에 값이 없으면 404 페이지로 리디렉션됩니다.

src/pages/[...slug].astro
---
const pages = [
{
slug: undefined,
title: 'Astro Store',
text: 'Welcome to the Astro store!',
},
{
slug: 'products',
title: 'Astro products',
text: 'We have lots of products for you',
},
{
slug: 'products/astro-handbook',
title: 'The ultimate Astro handbook',
text: 'If you want to learn Astro, you must read this book.',
}
];
const { slug } = Astro.params;
const page = pages.find((page) => page.slug === slug);
if (!page) return Astro.redirect("/404");
const { title, text } = page;
---
<html>
<head>
<title>{title}</title>
</head>
<body>
<h1>{title}</h1>
<p>{text}</p>
</body>
</html>

사이트 구조가 영구적으로 변경되었거나 인증된 경로에 로그인하는 등의 작업에 대한 응답으로 사용자를 새 페이지로 리디렉션해야 하는 경우가 있습니다.

Astro 구성에서 영구적으로 이동된 페이지로 사용자를 리디렉션하는 규칙을 정의할 수 있습니다. 또는 사용자가 여러분의 사이트를 사용할 때 사용자를 동적으로 리디렉션할 수도 있습니다.

Added in: astro@2.9.0

redirects 값을 사용하여 Astro 구성에서 영구 리디렉션 매핑을 지정할 수 있습니다. 대부분의 리디렉션에서 이는 이전 경로를 새 경로로 매핑합니다.

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
redirects: {
'/old-page': '/new-page'
}
});

이러한 리디렉션은 파일 기반 라우팅과 동일한 우선순위 규칙을 따르며, 프로젝트에서 같은 이름의 기존 페이지 파일보다 항상 우선순위가 낮습니다. 예를 들어 프로젝트에 src/pages/old-page.astro 파일이 포함되어 있으면 /old-page/new-page로 리디렉션되지 않습니다.

새 경로와 이전 경로에 모두 동일한 매개변수가 포함되어 있는 한 동적 경로는 허용됩니다.

{
"/blog/[...slug]": "/articles/[...slug]"
}

SSR 또는 정적 어댑터를 사용하면 객체를 값으로 제공하여 새로운 destination 외에 status 코드를 지정할 수도 있습니다.

astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
redirects: {
'/old-page': {
status: 302,
destination: '/new-page'
}
}
});

astro build를 실행하면 Astro는 기본적으로 meta refresh 태그가 포함된 HTML 파일을 출력합니다. 지원되는 어댑터는 대신 리디렉션을 사용하여 호스트의 구성 파일을 작성합니다.

상태 코드는 기본적으로 301입니다. HTML 파일로 빌드하는 경우 서버에서는 상태 코드를 사용하지 않습니다.

Astro 전역에서 Astro.redirect 메소드를 사용하면 다른 페이지로 동적으로 리디렉션할 수 있습니다. 쿠키에서 세션을 가져와 사용자가 로그인했는지 확인한 후 이 작업을 수행할 수 있습니다.

src/pages/account.astro
---
import { isLoggedIn } from '../utils';
const cookie = Astro.request.headers.get('cookie');
// 사용자가 로그인되어 있지 않은 경우 로그인 페이지로 리디렉션
if (!isLoggedIn(cookie)) {
return Astro.redirect('/login');
}
---
<html>
<!-- 페이지... -->
</html>

Added in: astro@4.13.0

리라이트를 사용하면 브라우저를 다른 페이지로 리디렉션하지 않고도 다른 경로를 제공할 수 있습니다. 브라우저는 URL 표시줄에 원래 주소를 표시하지만, 대신 Astro.rewrite()에 제공된 URL의 콘텐츠를 표시합니다.

리라이트는 두 개의 다른 소스 파일을 유지 관리할 필요 없이 여러 경로 (예: /products/shoes/men//products/men/shoes/)에서 동일한 콘텐츠를 표시하는 데 유용할 수 있습니다.

리라이트는 SEO 목적과 사용자 경험에도 유용합니다. 방문자를 다른 페이지로 리디렉션해야 하거나 404 상태를 반환하는 콘텐츠를 표시할 수 있습니다. 리라이트의 일반적인 용도 중 하나는 다양한 언어 변형에 대해 동일한 현지화된 콘텐츠를 표시하는 것입니다.

다음은 방문자가 /es-CU/ (쿠바 스페인어) URL 경로에 방문했을 때 리라이트를 사용하여 페이지의 /es/ 버전을 렌더링하는 예시입니다. 방문자가 /es-cu/articles/introduction URL로 이동하면 Astro는 src/pages/es/articles/introduction.astro 파일에 의해 생성된 콘텐츠를 렌더링합니다.

src/pages/es-cu/articles/introduction.astro
---
return Astro.rewrite("/es/articles/introduction")
---

다른 페이지로 경로를 변경하려면 엔드포인트 파일에서 context.rewrite()를 사용하세요:

src/pages/api.js
export function GET(context) {
if (!context.locals.allowed) {
return context.rewrite("/")
}
}

Astro.rewrite()에 전달된 URL이 런타임 오류를 발생시키면 개발 환경에서는 오버레이 오류가 표시되고 프로덕션 환경에서는 500 상태 코드가 반환됩니다. URL이 프로젝트에 존재하지 않으면 404 상태 코드가 반환됩니다.

예를 들어 이커머스 스토어의 제품을 더 이상 사용할 수 없음을 표시하기 위해 의도적으로 /404 페이지를 렌더링하는 리라이트를 생성할 수 있습니다:

src/pages/[item].astro
---
const { item } = Astro.params;
if (!itemExists(item)) {
return Astro.rewrite("/404")
}
---
<div>...</div>

예를 들어, 존재하지 않는 URL을 방문할 때 사이트의 특정 페이지를 표시하는 등 HTTP 응답 상태에 따라 조건부로 리라이트할 수도 있습니다:

src/middleware.mjs
export const onRequest = async (context, next) => {
const response = await next();
if (response.status === 404) {
return context.rewrite("/");
}
return response;
}

지정된 리라이트 경로의 콘텐츠를 표시하기 전에 Astro.rewrite() 함수는 새롭고 완전한 렌더링 단계를 트리거합니다. 그러면 새 경로/요청에 대한 모든 미들웨어가 다시 실행됩니다.

Astro.rewrite() API 참조에 대해 자세히 알아보세요.

정의된 여러 경로가 동일한 URL 경로를 빌드하려고 시도할 수 있습니다. 예를 들어, 다음 경로는 모두 /posts/create를 빌드할 수 있습니다.

  • 디렉터리src/pages/
    • […slug].astro
    • 디렉터리posts/
      • create.astro
      • [page].astro
      • [pid].ts
      • […slug].astro

Astro는 페이지를 빌드하는 데 어떤 경로를 사용해야 하는지 알아야 합니다. 이를 위해 다음 규칙에 따라 순서대로 정렬합니다.

  • Astro 예약된 경로
  • 더 많은 경로 세그먼트를 가진 경로가 덜 구체적인 경로보다 우선합니다. 위 예시에서 /posts/ 아래의 모든 경로는 루트의 /[...slug].astro보다 우선합니다.
  • 경로 매개변수가 없는 정적 경로는 동적 경로보다 우선합니다. 예: /posts/create.astro는 예시의 다른 모든 경로보다 우선합니다.
  • 명명된 매개변수를 사용하는 동적 경로는 나머지 매개변수보다 우선합니다. 예: /posts/[page].astro/posts/[...slug].astro보다 우선합니다.
  • 사전 렌더링된 동적 경로는 서버 동적 경로보다 우선합니다.
  • 엔드포인트가 페이지보다 우선합니다.
  • 파일 기반 경로가 리디렉션보다 우선합니다.
  • 위 규칙 중 어느 것도 순서를 결정하지 않으면 노드 설치의 기본 로케일을 기준으로 경로가 알파벳순으로 정렬됩니다.

위 예시에서 규칙이 요청된 URL을 HTML 작성에 사용된 경로와 일치시키는 방법에 대한 몇 가지 예시는 다음과 같습니다.

  • pages/posts/create.astro - /posts/create만 빌드합니다.
  • pages/posts/[pid].ts - /posts/abc, /posts/xyz 등을 빌드하지만 /posts/create는 빌드하지 않습니다.
  • pages/posts/[page].astro - /posts/1, /posts/2 등을 빌드하지만 /posts/create, /posts/abc, /posts/xyz는 빌드하지 않습니다.
  • pages/posts/[...slug].astro - /posts/1/2, /posts/a/b/c 등을 빌드하지만 /posts/create, /posts/1, /posts/abc 등은 빌드하지 않습니다.
  • pages/[...slug].astro - /abc, /xyz, /abc/xyz 등을 빌드하지만 /posts/create, /posts/1, /posts/abc 등은 빌드하지 않습니다.

내부 경로는 Astro 기능이 작동하는 데 필요하므로 사용자 정의 또는 통합 정의 경로보다 우선합니다. 다음은 Astro의 예약된 경로입니다:

  • _astro/: CSS 문서, 번들링된 클라이언트 스크립트, 최적화된 이미지, 모든 Vite 자산을 포함한 모든 정적 자산을 클라이언트에 제공합니다.
  • _server_islands/: 서버 아일랜드에 지연된 동적 컴포넌트를 제공합니다.
  • _actions/: 정의된 모든 액션을 제공합니다.

Astro는 여러 페이지로 분할해야 하는 대규모 데이터 컬렉션에 대해 내장된 페이지네이션을 지원합니다. Astro는 이전/다음 페이지 URL, 총 페이지 수 등을 포함한 일반적인 페이지네이션 속성을 생성합니다.

페이지가 매겨진 경로 이름은 표준 동적 경로와 동일한 [대괄호] 구문을 사용해야 합니다. 예를 들어 파일 이름 /astronauts/[page].astro/astronauts/1, /astronauts/2 등에 대한 경로를 생성합니다. 여기서 [page]는 생성된 페이지 번호입니다.

paginate() 함수를 사용하여 다음과 같은 값 배열에 대한 이러한 페이지를 생성할 수 있습니다.

src/pages/astronauts/[page].astro
---
export async function getStaticPaths({ paginate }) {
const astronautPages = [{
astronaut: 'Neil Armstrong',
}, {
astronaut: 'Buzz Aldrin',
}, {
astronaut: 'Sally Ride',
}, {
astronaut: 'John Glenn',
}];
// astronauts 배열에서 한 페이지에 2개의 페이지를 생성합니다.
return paginate(astronautPages, { pageSize: 2 });
}
// 페이지가 매겨진 모든 데이터는 "page" prop으로 전달됩니다.
const { page } = Astro.props;
---
<!--현재 페이지 번호를 표시합니다. Astro.params.page도 사용할 수 있습니다!-->
<h1>Page {page.currentPage}</h1>
<ul>
<!--astronauts 정보 배열 나열-->
{page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>

그러면 한 페이지에 2개의 항목이 포함된 다음 페이지가 생성됩니다.

  • /astronauts/1 - 페이지 1: “Neil Armstrong” 및 “Buzz Aldrin” 표시
  • /astronauts/2 - 페이지 2: “Sally Ride” 및 “John Glenn” 표시

paginate() 함수를 사용하면 각 페이지는 page prop을 통해 데이터가 전달됩니다. page 속성에는 페이지와 페이지 간 링크를 만드는 데 사용할 수 있는 유용한 속성이 많이 있습니다:

interface Page<T = any> {
/** paginate () 함수로 전달한 페이지의 데이터 슬라이스가 포함 된 배열 */
data: T[];
/** 메타데이터 */
/** 0부터 시작하는 페이지의 첫 번째 항목 수 */
start: number;
/** 0부터 시작하는 페이지의 마지막 항목 수 */
end: number;
/** 총 결과 수 */
total: number;
/** 1부터 시작하는 현재 페이지 번호 */
currentPage: number;
/** 페이지당 항목 수 (기본값: 10) */
size: number;
/** 마지막 페이지 수 */
lastPage: number;
url: {
/** 현재 페이지의 URL */
current: string;
/** 이전 페이지의 URL (존재하는 경우) */
prev: string | undefined;
/** 다음 페이지의 URL (존재하는 경우) */
next: string | undefined;
/** 첫 페이지의 URL (현재 페이지가 첫 페이지가 아닌 경우) */
first: string | undefined;
/** 마지막 페이지의 URL (현재 페이지가 마지막 페이지가 아닌 경우) */
last: string | undefined;
};
}

다음 예시에서는 페이지의 현재 정보와 페이지 간 이동할 수 있는 링크를 표시합니다:

src/pages/astronauts/[page].astro
---
// 이전 예시와 동일한 { astronaut } 객체 목록에 페이지를 매깁니다.
export async function getStaticPaths({ paginate }) { /* ... */ }
const { page } = Astro.props;
---
<h1>Page {page.currentPage}</h1>
<ul>
{page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
{page.url.first ? <a href={page.url.first}>First</a> : null}
{page.url.prev ? <a href={page.url.prev}>Previous</a> : null}
{page.url.next ? <a href={page.url.next}>Next</a> : null}
{page.url.last ? <a href={page.url.last}>Last</a> : null}
페이지네이션의 page prop에 대해 알아보세요.

페이지네이션의 고급 사용 사례는 중첩 페이지네이션입니다. 이는 페이지네이션이 다른 동적 경로 매개변수와 결합되는 경우입니다. 중첩된 페이지네이션을 사용하여 페이지가 매겨진 컬렉션을 일부 속성이나 태그별로 그룹화할 수 있습니다.

예를 들어, 페이지가 매겨진 Markdown 게시물을 일부 태그로 그룹화하려면 다음 URL과 일치하는 /src/pages/[tag]/[page].astro 페이지를 생성하여 중첩된 페이지네이션을 사용합니다.

  • /red/1 (태그=red)
  • /red/2 (태그=red)
  • /blue/1 (태그=blue)
  • /green/1 (태그=green)

중첩된 페이지네이션은 getStaticPaths()에서 paginate() 결과 배열을 각 그룹마다 하나씩 반환하여 작동합니다.

다음 예시에서는 위에 나열된 URL을 작성하기 위해 중첩된 페이지네이션을 구현합니다.

src/pages/[tag]/[page].astro
---
export async function getStaticPaths({ paginate }) {
const allTags = ['red', 'blue', 'green'];
const allPosts = Object.values(import.meta.glob('../pages/post/*.md', { eager: true }));
// 모든 태그에 대해 paginate() 결과를 반환합니다.
// `{params: {tag}}`를 `paginate()`에 전달했는지 확인합니다.
// Astro가 결과가 어떤 태그 그룹에 대한 것인지 알 수 있도록 합니다.
return allTags.flatMap((tag) => {
const filteredPosts = allPosts.filter((post) => post.frontmatter.tag === tag);
return paginate(filteredPosts, {
params: { tag },
pageSize: 10
});
});
}
const { page } = Astro.props;
const params = Astro.params;

src/pages에 위치한 페이지나 디렉터리 이름 앞에 밑줄 (_)을 붙여서 빌드되지 않도록 제외할 수 있습니다. _ 접두사가 붙은 파일은 라우터에서 인식되지 않으며 dist/ 디렉터리에 배치되지 않습니다.

이를 사용하여 페이지를 일시적으로 비활성화하고 테스트, 유틸리티 및 컴포넌트를 관련 페이지와 동일한 폴더에 넣을 수도 있습니다.

이 예시에서는 src/pages/index.astrosrc/pages/projects/project1.md 파일만 페이지 경로 및 HTML 파일로 빌드됩니다.

  • 디렉터리src/pages/
    • 디렉터리_hidden-directory/
      • page1.md
      • page2.md
    • _hidden-page.astro
    • index.astro
    • 디렉터리projects/
      • _SomeComponent.astro
      • _utils.js
      • project1.md
기여하기

여러분의 생각을 들려주세요!

GitHub Issue 생성

우리에게 가장 빨리 문제를 알려줄 수 있어요.

커뮤니티