본문 바로가기
  • ANALOG CODE
  • AnalogCode
개발

Vue Multiple Layout (다중 레이아웃) 적용하기

by 아날로그코더 2023. 6. 7.
반응형

Nuxt를 사용하면 자동으로 다중 레이아웃이 가능하게 세팅된다. 하지만 Nuxt를 사용안하고 Vue만 사용한다면 이걸 자체적으로 구현해야 한다. 가장 간단하면서도 효율적으로 다중 Layout 구성을 해보는 방법을 Vue 3를 기반으로 설명한다.

 

 

우리의 목표는 페이지마다 다른 레이아웃을 선택해서 사용할 수 있도록 하는 것이다. Vue3 기본 프로젝트를 기반으로 여러 개의 레이아웃을 만들고 페이지마다 다른 레이아웃을 어떻게 적용시킬 수 있는지를 코드를 보면서 설명하도록 하겠다. 이해하기 쉽게 최소한의 코드만으로 샘플소스를 만들었다.

 


 

프로젝트 구조

 

기본적으로 Vue 3를 기반으로 프로젝트를 만들었고, 아래와 같이 폴더 구조를 구성하였다.

기본 구조에 layouts, pages 폴더를 추가하였다. 그외에는 Vue 3 프로젝트를 만들면 기본으로 생성되는 폴더이다.

 

폴더 구조

 

폴더 용도
pages pages 단위의 Vue 컴포넌트를 담을 폴더
layouts layouts 단위의 Vue 컴포넌트를 담을 폴더

 

 

 

페이지 만들기

 

라우팅할 페이지를 먼저 만들어두자. 테스트용 페이지 2개를 만들었다.

 

pages/index.vue

<template>
  <div>Home Page</div>
</template>

 

pages/main.vue

<template>
  <div>Main Page</div>
</template>

 

 

레이아웃 만들기

 

2개의 레이아웃 컴포넌트를 만든다. 

 

layouts/Layout1.vue

<template>
  <div>
    <h1>Layout 1</h1>
    <slot />
  </div>
</template>

 

layouts/Layout2.vue

<template>
  <div>
    <h1>Layout 2</h1>
    <slot />
  </div>
</template>

 

여기서 핵심은 <slot> 이다. Vue의 Slot은 부모 컴포넌트가 제공한 템플릿을 자식 컴포넌트에서 렌더링할 수 있게 해준다.

우리는 Layout 컴포는트의 slot에 vue-router에서 제공한 router-view를 넣어줄 것이다.

 

라우터 만들기

 

라우팅을 위해서는 vue-router가 필요하므로 설치하여 준다.

 

$ npm install vue-router@4

 

그리고 위에서 만든 page와 layout을 가지고 router에 적용시켜주면 된다.

 

router.js

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

// Layouts
import Layout1 from './layouts/Layout1.vue'
import Layout2 from './layouts/Layout2.vue'

// Pages
import Home from './pages/Home.vue'
import Main from './pages/Main.vue'

const routes = [
  { 
    path: '/',
    component: Home,
    meta: { layout: Layout1 }
  },
  { 
    path: '/main',
    component: Main,
    meta: { layout: Layout2 }
  }
]

const router = createRouter({
  history: createWebHashHistory(),
  routes
})

export default router

router의 meta 필드는 임의의 정보를 전달할 수 있는 필드이다. meta 필드를 이용하여 페이지마다 별도의 Layout 컴포넌트를 전달하여 준다.

 

 

main.js

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

import router from './router'

const app = createApp(App)

app.use(router)

app.mount('#app')

main.js에서 위에서 만든 router를 import 하여 vue 인스턴스에 적용시켜주면 된다.

 

 

 

 

레이아웃 동적 컴포넌트 적용

 

마지막으로 가장 핵심이 되는 부분이다. 페이지마다 별도의  레이아웃을 어떻게 적용시켜줄 수 있을까? 

 

App.vue

<template>

  <!-- 페이지 전환 테스트를 위한 링크 -->
  <ul>
    <li><router-link to="/">Home</router-link></li>
    <li><router-link to="/main">Main</router-link></li>
  </ul>
  
  <!-- 핵심이 되는 부분 -->
  <component :is="$route.meta.layout || 'div'">
    <router-view></router-view>
  </component>
  
</template>

 

 

동적 컴포넌트 (Dynamic Component)

동적 컴포넌트는 동적으로 컴포넌트를 교체할 수 있는 기능이다.
is 속성으로 미리 등록된 컴포넌트의 이름을 전달하거나, import된 컴포넌트 자체를 전달할 수 있다.

 

<component>의 하위컴포넌트로 <router-view>를 넣어줌으로써 아래와 같은 구조가 될 수 있는 것이다.

<Layout>
  <Page />
</Layout1>

 

Page마다 $route.meta.layout 에 레이아웃 컴포넌트가 지정되어 있으므로, 라우팅되는 페이지의 레이아웃이 바뀌면 해당 레이아웃 컴포넌트로 동적으로 바뀌게 돠는 것이다. 그리고 <router-view> 에는 router.js에서 정의된 page component가 들어가게 된다.

 

 

실행 결과

 

아래 2개의 페이지를 전환하면서 확인해보면 layout이 바뀌는 걸 확인할 수 있다.

  • / 페이지
  • /main 페이지

페이지별 레이아웃 전환

 

 

 

 

반응형

댓글