Nuxt와 Bootstrap4 기반의 Dashboard 만들기

6. Page & UI 개발 - 레이아웃 설계

Nuxt.js

오늘의 포스트는 Nuxt와 Bootstrap4 기반의 Dashboard 만들기 의 여섯번째 포스트로 Page & UI 개발에 대해 작성해보겠습니다.

지난 포스트에서는 Bootstrap & Bootstrap-vue 환경구성에 대해 작업해봤습니다. 본 포스트에서는 Page & UI 개발에 대해 다뤄보겠습니다.

개발 순서

  1. 프로젝트 생성 및 Github Repository 환경구성
  2. Heroku 배포 환경구성
  3. Nuxt & Express API 환경구성
  4. Axios
  5. Bootstrap & Bootstrap-vue 환경구성
  6. Page & UI 개발

Layout

Nuxt Views Architecture

Layout은 Nuxt Views 구성 중 하나로, 이번 포스트에서 다룰 Layout은 Nuxt의 View 계층 중 상위 레벨에 속하며 header, footer 또는 sidebar와 같은 반복되는 UI 컴포넌트들을 특정 기준으로 그룹화해 특정 페이지등에 공통된 UI를 렌더링 할 수 있도록 합니다. 각 레이아웃에는 Vue 기반의 UI Component와 middleware 및 head 태그 옵션들을 property로 지정할 수 있습니다.

Default Layout

기본 레이아웃은 메인 레이아웃으로 확장할 수 있으며 layout property를 설정하지 않은 모든 페이지에서 사용가능하도록 설정됩니다. 페이지 구성요소에 포함되는 Layout을 만들때 가장 중요한 것은 </Nuxt> 태그를 추가하는 것이며 Layout에 필요한 가장 기본적인 코드는 page 컴포넌트에 렌더링하는 아래의 세줄의 코드 입니다.

1
2
3
4
5
// layouts/default.vue

<template>
<Nuxt />
</template>

또한, Navigation, Header 그리고 Footer 등의 더 많은 Component를 추가할 수도 있습니다.

1
2
3
4
5
6
7
8
9
// layouts/default.vue

<template>
<div>
<TheHeader />
<Nuxt />
<TheFooter />
</div>
</template>

Custom Layout

layouts 디렉토리의 top-level 수준의 모든 파일은 page 컴포넌트에서 layout property로 접근 가능한 custom Layout을 만듭니다.

1
2
3
4
5
6
7
8
// layouts/blog.vue

<template>
<div>
<div>My blog navigation bar here</div>
<Nuxt />
</div>
</template>

예를 들어, blog 레이아웃을 만들기 위해 layouts 디렉토리에 blog.vue 레이아웃(layouts/blog.vue)을 생성했고 pages/posts.vue에서 blog 레이아웃을 사용하길 원한다면 pages/posts.vue의 layout property에서 아래와 같이 설정해 사용하면 됩니다.

1
2
3
4
5
6
7
8
9
10
11
pages/posts.vue

<script>
export default {
layout: 'blog',
// OR
layout (context) {
return 'blog'
}
}
</script>

Error Page

에러 페이지는 에러가 발생했을때 반드시 볼 수 있는 page 컴포넌트로써, 비로 layouts 폴더에 배치되었지만, 페이지와 같이 다뤄야합니다. Layout이자 Page인 Error Page는 template에서 <Nuxt>를 포함하지 않는데 그 이유는 404, 500 과 같은 에러가 발생했을때 Component로 Error Page를 보여줄 것이기 때문입니다. 다른 page 컴포넌트와 비슷하게 동일한 방법으로 Error Page에 대한 custom layout을 설정할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// layouts/error.vue

<template>
<div class="container">
<h1 v-if="error.statusCode === 404">Page not found</h1>
<h1 v-else>An error occurred</h1>
<NuxtLink to="/">Home page</NuxtLink>
</div>
</template>

<script>
export default {
props: ['error'],
layout: 'blog' // you can set a custom layout for the error page
}
</script>

Component

기존의 Vue.js에 익숙한 개발자라면 알고 있듯이 페이지 또는 layout에 반복되는 재사용 가능한 UI Component로써, /components 디렉토리에서 생성해 불러올 수 있습니다. 또한, Component에서 특정 데이터가 필요한 경우 API에서 비동기 데이터에 접근하기 위해 Nuxt의 fetch() hook을 사용할 수 있습니다.

v2.13 버전부터 Nuxt는 템플릿에서 사용할때 nuxt.config.js에서 아래와 같이 components: true를 설정하면 Component를 자동으로 가져올 수 있도록 활성화할 수 있습니다.

1
2
3
4
5
// nuxt.config.js

export default {
components: true
}

아래와 같이 components/ 디렉토리에 TheHeaderTheFooter 컴포넌트를 생성하면 layouts/default.vue이라는 기본 레이아웃에서 바로 가져올 수 있습니다.

1
2
3
components/
TheHeader.vue
TheFooter.vue
1
2
3
4
5
6
7
8
9
// layouts/default.vue

<template>
<div>
<TheHeader />
<Nuxt />
<TheFooter />
</div>
</template>

Dynamic Imports

Component의 Dynamic Imports는 lazy loading을 통해 구현할 수 있으며 template에서 Component 태그 이름에 Lazy prefix를 추가해주면 됩니다.

1
2
3
4
5
6
7
8
9
// layouts/default.vue

<template>
<div>
<TheHeader />
<Nuxt />
<LazyTheFooter />
</div>
</template>

Lazy prefix가 추가된 Component는 이벤트가 발생했을때 동적으로 불러올 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// pages/index.vue

<template>
<div>
<h1>Mountains</h1>
<LazyMountainsList v-if="show" />
<button v-if="!show" @click="showList">Show List</button>
</div>
</template>

<script>
export default {
data() {
return {
show: false
}
},
methods: {
showList() {
this.show = true
}
}
}
</script>

Nested Directories

1
2
3
4
components/
base/
foo/
Button.vue

만약 컴포넌트가 위와 같은 중접 디렉토리(Nested Directories)에 있다면, Component의 이름은 Component가 속한 디렉토리의 경로와 파일이름이 되어야 합니다. 따라서 위 Button Component를 template에서 사용하려면 <BaseFooButton />와 같이 사용해야 합니다. 그러나 만약 디렉토리 구조를 Component의 이름으로 사용하지 않길 원한다면 nuxt.config.js에 Component가 속한 특정 디렉토리의 경로를 명시해야 하며 다음과 같은 <FooButton /> Component 태그이름을 사용할 수 있습니다.

1
2
3
4
5
6
7
8
// nuxt.config.js

components: {
dirs: [
'~/components',
'~/components/base'
]
}

Layout 및 Component 설계

위에서 간략하게 Nuxt의 Layout과 Component 개념에 대해 알아봤으므로 프로젝트에 필요한 설계를 시작해보겠습니다. 이번 프로젝트는 제목에서도 알 수 있듯이 관리자 대시보드 프로젝트로써 필요한 Layout과 Component는 아래와 같습니다.

Layout

  1. 기본 Dashboard 페이지 레이아웃 (for pages of needed authenticated)
  2. 비서비스 페이지 레이아웃 (for pages of not needed authenticated)
  3. 에러 레이아웃 (페이지)

Component

1. 기본 Dashboard 페이지 레이아웃

(for pages of needed authenticated)

  1. Header
  2. Sidebar
  3. Main content area (for dashboard)

2. 비서비스 페이지 레이아웃

(for pages of not needed authenticated)

  1. Header
  2. Main content area (for each page content)

3. 에러 레이아웃

  1. Icon depending on Error Status
  2. Error Message
  3. Action Button area

Layout 구현

위에서 설계한 Layout을 차례대로 구현해보기전에 각 Layout에 중복되는 Component 이름이 있으므로 Component 디렉토리 구조를 아래와 같이 구성했습니다.

  • 기본 Dashboard 페이지 레이아웃: components/dashboard
  • 비서비스 페이지 레이아웃: components/base
  • 에러 레이아웃: components/error

기본 Dashboard 페이지 레이아웃

기본 Dashboard 페이지 레이아웃의 경우 아래와 같은 구조로 개발하려고 합니다. SidebarContent로 구조를 단순화 하고, Content 영역 내부에서 HeaderMain content Area 영역을 구분지어 각 대시보드 페이지의 페이지를 렌더링할 수 있는 영역을 남겨놓도록 기획했습니다.

1
2
3
4
5
6
(root)
├─ Sidebar
└─ Content
├─ Header
└─ Main content Area

비서비스 페이지 레이아웃

비서비스 페이지 레이아웃의 경우 아래와 같은 구조로 개발하려고 합니다. HeaderMain content Area로 구조를 단순화 하고, Main content Area 영역에서 추가로 레이아웃을 나눌수 있도록 했으며 각 페이지를 렌더링할 수 있는 영역을 남겨놓도록 기획했습니다.

1
2
3
4
(root)
├─ Header
└─ Main content Area

에러 레이아웃

비서비스 페이지 레이아웃의 경우 아래와 같은 구조로 개발하려고 합니다. HeaderMain content Area로 구조를 단순화 하고, Main content Area 영역에서 추가로 레이아웃을 나눌수 있도록 했으며 각 페이지를 렌더링할 수 있는 영역을 남겨놓도록 기획했습니다.

1
2
3
4
5
6
(root)
├─ Error Message
│ ├─ Error Icon (Status Code)
│ └─ Error Message
└─ Main content Area

마치며

본 포스트에서는 Nuxt.js의 Views 컨셉과 그 요소인 Page, Layout 그리고 Component에 대해 알아보았고, 이번 프로젝트에서 필요한 Layout에 대한 설계와 Component에 대해 정의내려봤습니다. 앞으로는 페이지를 구현할 것이며 중간중간 Layout 또는 Layout에서 사용할 Component가 변경될 수 있을거 같습니다. 다음 포스트에서는 Dashboard 페이지의 첫번째 페이지인 Overview 페이지를 개발해보겠습니다. 감사합니다.


참고