definePageMeta에 변수를 넘겼더니 값이 사라진 이유
문제 발생
레이아웃과 미들웨어를 조건에 따라 다르게 주려고 했습니다.
<script setup>
const layoutName = useRuntimeConfig().public.adminLayout;
definePageMeta({
layout: layoutName, // 적용되지 않음
middleware: isAdmin ? "admin" : "auth",
});
</script>레이아웃이 기본값으로 나오거나 빌드가 실패했습니다. 같은 코드를 컴포넌트로 옮겼더니 아예 무시됐습니다.
원인 분석
런타임에 실행되는 함수가 아닙니다. Nuxt 문서는 definePageMeta를 app/pages/ 디렉터리의 페이지 컴포넌트에 메타데이터를 설정하는 컴파일러 매크로로 정의합니다.
컴파일러 매크로라는 것은 빌드 시점에 그 호출을 정적으로 읽어 라우트 정의로 옮긴다는 뜻입니다. 그래서 문서가 못박습니다 — 빌드 타임에 동작하므로 지역 변수나 외부 런타임 값을 참조할 수 없습니다. 라우트 테이블은 앱이 뜨기 전에 확정되어야 하니 당연한 제약입니다.
두 번째 문제도 여기서 나옵니다. 이 매크로는 페이지 컴포넌트에서만 의미가 있습니다. 일반 컴포넌트에 넣으면 아무 일도 일어나지 않습니다.
해결 방안
- 정적 값만 넘깁니다.
<script setup>
definePageMeta({
layout: "admin",
middleware: ["auth", "admin"],
});
</script>- 조건 분기는 미들웨어 안에서 합니다. "누가 볼 수 있는가"는 런타임 판단이므로 애초에 미들웨어의 일입니다.
// app/middleware/admin.ts
export default defineNuxtRouteMiddleware(() => {
const { user } = useUserSession();
if (user.value?.role !== "admin") return navigateTo("/");
});-
레이아웃을 런타임에 바꿔야 하면
setPageLayout을 씁니다. 매크로에 변수를 넣는 대신 미들웨어에서 호출합니다. -
매크로가 지원하는 속성을 먼저 확인합니다. 문서가 나열하는 것은
middleware,layout,alias,name,keepalive,pageTransition,validate,redirect등이고, 타입 확장으로 커스텀 메타도 추가할 수 있습니다.validate는 잘못된 파라미터를 404로 보내는 데 유용한데 자주 잊힙니다. -
왜 정적이어야 하는지 팀에 남깁니다. 이 제약은 불편이 아니라 라우트 테이블이 빌드 산출물이라는 사실의 결과입니다. 그 사실을 모르면 다음 사람이 같은 코드를 다시 씁니다.
댓글0
댓글을 남기려면 로그인이 필요해요. 로그인
아직 댓글이 없어요. 첫 의견을 편하게 남겨 보세요.