웹 애플리케이션을 개발할 때 페이지마다 공통적인 UI 구조(예: 헤더, 푸터, 사이드바)를 유지하려면 레이아웃(Layout) 개념이 필수적입니다. Vue에서는 여러 가지 방법으로 레이아웃을 적용할 수 있으며, 실무에서는 중첩 라우트(Nested Routes) 방식과 meta 속성을 활용하는 방식이 주로 사용됩니다.
이번 글에서는 실무에서 가장 많이 쓰이는 Vue의 레이아웃 관리 방법을 작성해보겠습니다.
1. 중첩 라우트(Nested Routes) 방식으로 레이아웃 적용하기
중첩 라우트 방식은 각 레이아웃을 상위 라우트로 설정한 후, 하위 페이지를 해당 레이아웃 내부에서 렌더링하는 방법입니다. 이를 통해 모든 하위 페이지는 자연스럽게 공통 UI를 공유할 수 있습니다.
✅ App.vue 설정
먼저, App.vue에서 RouterView가 렌더링 되게 설정하겠습니다.
<template>
<RouterView />
</template>
✅ 레이아웃 컴포넌트 생성
MainLayout.vue라는 공통 레이아웃을 만들어 보겠습니다.
<!-- src/layouts/MainLayout.vue -->
<template>
<div class="main-layout">
<header class="header">
<h1>My App</h1>
<nav>
<RouterLink to="/">Home</RouterLink> |
<RouterLink to="/about">About</RouterLink>
</nav>
</header>
<main class="content">
<RouterView />
</main>
<footer class="footer">
<p>© 2025 My Company</p>
</footer>
</div>
</template>
✅ 개별 페이지 예제
이제 Home.vue 같은 개별 페이지 컴포넌트를 작성합니다.
<!-- src/views/Home.vue -->
<template>
<div>
<h2>Home Page</h2>
<p>Welcome to the home page!</p>
</div>
</template>
<!-- src/views/About.vue -->
<template>
<div>
<h2>About Page</h2>
<p>Welcome to the about page!</p>
</div>
</template>
<!-- src/views/Login.vue -->
<template>
<div>
<h2>Login Page</h2>
<p>Welcome to the login page!</p>
</div>
</template>
✅ 라우터 설정
라우터에서 MainLayout을 상위 컴포넌트로 설정하면, 하위 라우트들이 자동으로 해당 레이아웃을 적용받습니다.
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import MainLayout from '@/layouts/MainLayout.vue'
const routes = [
{
path: '/',
component: MainLayout,
children: [
{
path: '',
name: 'Home',
component: () => import('@/views/Home.vue')
},
{
path: 'about',
name: 'About',
component: () => import('@/views/About.vue')
}
]
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
✅ 동작 확인
✅ 이 방식의 장점:
- 코드가 직관적이며, 유지보수가 용이하다.
- 라우트 구조를 통해 레이아웃이 명확하게 구분된다.
- 다양한 레이아웃을 적용할 때도 자연스럽게 확장 가능하다.
✅ 이 방식의 단점:
- 특정 페이지에서 다른 레이아웃을 사용하고 싶다면 새로운 라우트 그룹을 만들어야 한다.
- 일부 경우, 유연성이 떨어질 수 있다.
2. meta 속성을 활용하여 동적으로 레이아웃 적용하기
두 번째 방법은 라우트의 meta 속성을 이용해 동적으로 레이아웃을 변경하는 방식입니다. 이 방법은 하나의 공통 컴포넌트(예: App.vue)에서 meta 데이터를 기반으로 알맞은 레이아웃을 불러오는 구조입니다.
✅ 라우터 설정 (meta 활용)
라우터 설정에서 meta.layout을 추가하여 각 페이지별로 다른 레이아웃을 지정할 수 있습니다.
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import MainLayout from '@/layouts/MainLayout.vue'
import AuthLayout from '@/layouts/AuthLayout.vue'
const routes = [
{
path: '/',
name: 'Home',
component: import('@/views/Home.vue'),
meta: { layout: MainLayout },
},
{
path: '/about',
name: 'About',
component: import('@/views/About.vue'),
meta: { layout: MainLayout },
},
{
path: '/login',
name: 'Login',
component: import('@/views/Login.vue'),
meta: { layout: AuthLayout },
},
]
const router = createRouter({
history: createWebHistory(),
routes,
})
export default router
✅ 레이아웃 컴포넌트
레이아웃을 MainLayout.vue와 AuthLayout.vue로 나누어 관리할 수 있습니다.
<!-- src/layouts/MainLayout.vue -->
<template>
<div class="main-layout">
<header class="header">
<h1>Main Header</h1>
<nav>
<RouterLink to="/">Home</RouterLink> | <RouterLink to="/about">About</RouterLink> |
<RouterLink to="/login">Login</RouterLink>
</nav>
</header>
<main class="content">
<RouterView />
</main>
<footer class="footer">
<p>© 2025 My Company</p>
<p>Main Footer</p>
</footer>
</div>
</template>
<!-- src/layouts/AuthLayout.vue -->
<template>
<div class="main-layout">
<header class="header">
<h1>Auth Header</h1>
<nav>
<RouterLink to="/">Home</RouterLink> | <RouterLink to="/about">About</RouterLink> |
<RouterLink to="/login">Login</RouterLink>
</nav>
</header>
<main class="content">
<RouterView />
</main>
<footer class="footer">
<p>© 2025 My Company</p>
<p>Auth Footer</p>
</footer>
</div>
</template>
✅ App.vue에서 동적 레이아웃 적용
현재 라우트의 meta.layout 값을 읽어 해당 레이아웃을 동적으로 적용합니다.
<!-- src/App.vue -->
<template>
<component :is="layout">
<router-view />
</component>
</template>
<script setup>
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import MainLayout from '@/layouts/MainLayout.vue'
const route = useRoute()
// meta에 컴포넌트 자체가 지정되어 있으면 바로 사용, 없을 경우 기본 레이아웃(MainLayout) 사용
const layout = computed(() => {
return route.meta.layout || MainLayout
})
</script>
✅ 동작 확인
✅ 이 방식의 장점:
- 특정 페이지마다 자유롭게 레이아웃을 다르게 설정할 수 있다.
- 유지보수 및 확장성이 좋다.
- 라우트 설정만 변경하면 쉽게 레이아웃을 바꿀 수 있다.
✅ 이 방식의 단점:
- App.vue에서 동적 컴포넌트 처리 로직이 필요하다.
- 레이아웃이 암시적으로 적용되므로 코드 가독성이 떨어질 수 있다.
🔥 마무리
Vue에서 레이아웃을 적용하는 두 가지 주요 방법(중첩 라우트, meta 속성 활용)을 알아보았습니다.
React와 비교하면, Vue는 페이지마다 레이아웃을 명시적으로 설정할 수 있어서 훨씬 간결하고 직관적인 방식으로 관리할 수 있습니다.