Nuxt 디렉토리 구조

Nuxt Directory 1

1.Nuxt 프로젝트 디렉토리

막 생성된 nuxt 프로젝트의 디렉토리는 아래와 같다. 디렉토리에 대한 정의를 잘 몰라도 이미 Vue.js를 사용했던 개발자라면 비슷한 구조이며 스캐폴딩이 이미 되어있다는 생각이 들것이다.
nuxt 프로젝트 디렉토리

각 디렉토리의 역할에 대해 알아보자.

.nuxt

.directory를 빌드 디렉토리라고 부르며 기본적으로 숨겨져 있고 동적으로 생성됩니다. nuxt dev를 사용했을땐 이 디렉토리에서 동적으로 생성된 파일들을 찾을 수 있으며 nuxt build를 사용하면 작업물들을 빌드할 수 있습니다.

assets

assets 디렉토리는 Stylus 또는 Sass files, images 또는 fonts 와 같은 컴파일된 애셋이 포함되어 있습니다.

Images

vue 템플릿 내부에는, 만약 assets을 링크해야 한다면, 슬래시(/)와 앞에 ~/assets/your_image.png와 같이 사용할 수 있습니다.

1
2
3
<template>
<img src="~/assets/your_image.png" />
</template>

css 파일에서 assets 디렉토리에 대한 참조가 필요하다면, 슬래시 없이 ~assets/your_image.png와 같이 사용할 수 있습니다.

1
background: url('~assets/banner.svg');
Styles

Nuxt.js를 사용하면 모든 페이지에서 포함된 전역으로 설정하기 원하는 CSS 파일/모듈/라이브러리를 정의할 수 있습니다. nuxt.config 에서 CSS 프로퍼티를 사용합으로써 스타일을 쉽게 추가할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
export default {
css: [
// Load a Node.js module directly (here it's a Sass file)
'bulma',
// CSS file in the project
'~/assets/css/main.css',
// SCSS file in the project
'~/assets/css/main.scss'
]
}
Fonts

여러분의 에셋 폴더에 로컬 폰트를 추가해 사용할 수 있습니다. 일단 폰트를 추가하면, 여러분은 @font-face를 사용해 css에서 폰트에 접근할 수 있습니다.

1
2
3
4
-| assets
----| fonts
------| DMSans-Regular.ttf
------| DMSans-Bold.ttf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@font-face {
font-family: 'DM Sans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('~assets/fonts/DMSans-Regular.ttf') format('truetype');
}

@font-face {
font-family: 'DM Sans';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('~assets/fonts/DMSans-Bold.ttf') format('truetype');
}

components

컴포넌트 디렉토리는 Vue.js 컴포넌트들을 포함하고 있으며 컴포넌트들은 페이지의 서로 다른 부분을 구성할 것이고 페이지, 레이아웃 심지어 다른 컴포넌트안에서 불러지고, 재사용할 될 수 있습니다.

Fetching Data

컴포넌트에서 API에 동적으로 데이터를 접근하기 위해서 Nuxt의 fetch() hook을 사용할 수 있습니다.

$fetchState.pending을 확인함으로써, 데이터가 로드될 때까지 기다리고 있을때 메시지를 표시할 수 있다. 또한, 데이터를 가져오는데 오류가 있을 경우 $fetchState.error를 확인해 오류 메시지를 표시할 수 있습니다. fetch()을 사용하면 data()에서 적절한 프로퍼티에 선언해야 합니다. fetch로부터 받은 데이터는 이러한 속성들에 선언할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<div>
<p v-if="$fetchState.pending">Loading....</p>
<p v-else-if="$fetchState.error">Error while fetching mountains</p>
<ul v-else>
<li v-for="(mountain, index) in mountains" :key="index">
{{ mountain.title }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
}
}
</script>

content

content/ 디렉토리에 작성한 @nuxtjs/content 모듈은 Nuxt.js 어플리케이션을 강력하게 만들수 있으며 Git-based Headless CMS 와 같은 역할을 하는 MongoDB와 같은 API를 통해 Markdown, JSON, YAML and CSV 파일들을 불러옵니다.

dist

배포 폴더를 간추려 dist 폴더라고 하며 nuxt generate 명령어를 사용해 동적으로 생성하고, 생성된 프로덕션에 준비된 HTML 파일들과 배포하기 위해 필수적인 에셋들이 포함되고, 전략적으로 생성한 Nuxt.js 어플리케이션이 작동합니다.

layouts

사이드바 또는 모바일이나 데스크톱에 대한 구별된 레이아웃을 원할 경우 레이아웃은 Nuxt.js 앱의 느낌과 외형을 변경하려고 할때 큰 도움이 됩니다.

이 디렉토리는 추가 설졍없이 이름을 재설정할 수 없습니다.

Default Layout

layouts/default.vue 파일을 추가하면 메인 레이아웃을 확장할 수 있으며 특정 레이아웃을 가지고 있지 않은 모든 페이지에서 사용할 수 있습니다. 실제로 페이지 컴포넌트에 포함하도록 생성한 레이아웃을 생성할때 <Nuxt> 컴포넌트를 추가해야 합니다.

레이아웃에서 필요한 것은 페이지 컴포넌트를 렌더링 할 세줄의 코드입니다.

1
2
3
4
<!-- layouts/default.vue -->
<template>
<Nuxt />
</template>

네비게이션, 헤너, 푸터 등과 같은 더 많은 컴포넌트들을 추가할 수 있습니다.

1
2
3
4
5
6
7
8
<!-- layouts/default.vue -->
<template>
<div>
<TheHeader />
<Nuxt />
<TheFooter />
</div>
</template>

만약 componentstrue를 설정하면 컴포넌트를 위한 그 어떠한 import 구분도 필요하지 않습니다.

Custom Layout

layouts 디렉토리의 (top-level의) 모든 파일은 페이지 컴포넌트에서 레이아웃 속성에 접근 가능한 커스텀 레이아웃을 만듭니다.

블로그 레이아웃을 생성하기 위해 layouts/blog.vue에 아래의 코드를 저장합니다.

1
2
3
4
5
6
<template>
<div>
<div>My blog navigation bar here</div>
<Nuxt />
</div>
</template>

그리고나서 페이지에서 아래와 같이 여러분의 커스텀 레이아웃을 설정해야 합니다.

1
2
3
4
5
6
7
8
9
<script>
export default {
layout: 'blog',
// OR
layout (context) {
return 'blog'
}
}
</script>

middleware

middleware 디렉토리는 어플리케이션 미들웨어를 포함하며 페이지 하나 또는 페이지 그룹 또는 레이아웃리 렌더링되기 전에 작동할 수 있는 커스텀 함수들을 정의할 수 있습니다.

공유된 middlewaremiddleware/ 디렉토리에 배치해야 하며 파일이름은 미들웨어의 이름이 될 것 입니다(middleware/auth.jsauth 미들웨어가 됩니다). 또한 페이지 특정 미들웨어는 직접 함수로 사용할 수 있습니다.
anonymous middleware를 참고하세요.

미들웨어는 첫번째 인자로 the context 를 받습니다.

1
2
3
4
5
6
export default function (context) {
// Add the userAgent property to the context
context.userAgent = process.server
? context.req.headers['user-agent']
: navigator.userAgent
}

universal 모드에서 미들웨어는 (예를 들어 앱에 바로 접속하거나 페이지를 새로고침할때, Nuxt 어플리케이션에서 처음 요청할때) 서버사이드에서 그리고 다른 라우트로 네이게이팅될때 클라이언트 사이드에서 단 한번만 호출됩니다. ssr: false를 설정하면, 미들웨어는 두 가지 상황에서 클라이언트 사이드에서만 호출됩니다.

미들웨어는 아래의 순서대로 실행됩니다.

  1. nuxt.config.js (파일 내부 순서대로)
  2. 매칭된 레이아웃
  3. 매칭된 페이지
Router Middleware

미들웨어는 비동기적일 수 있으며 이를 위해 Promise를 반환하거나 async/await를 사용해야합니다.

1
2
3
4
5
6
7
8
9
<!-- middleware/stats.js -->

import http from 'http'

export default function ({ route }) {
return http.post('http://my-stats-api.com', {
url: route.fullPath
})
}

그러고나서 nuxt.config.js에서 router.middleware key를 사용해야 합니다.

1
2
3
4
5
6
7
<!-- nuxt.config.js -->

export default {
router: {
middleware: 'stats'
}
}

이제 모든 라우트 변경에 대해 stats 미들웨어가 호출됩니다. 또한 특정 레이아웃 또는 페이지에 대한 (복수의) 미들웨어를 추가할 수 있습니다.

1
2
3
4
<!-- pages/index.vue / layouts/default.vue -->
export default {
middleware: ['auth', 'stats']
}
Named middleware

middleware/ 디렉토리 내부에 파일을 생성함으로써 named 디렉토리를 생성할 수 있으며 미들웨어 이름이 될 것입니다.

1
2
3
4
5
6
7
8
<!-- middleware/authenticated.js -->

export default function ({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}
1
2
3
4
5
6
7
8
9
10
11
<!-- pages/secret.vue -->

<template>
<h1>Secret page</h1>
</template>

<script>
export default {
middleware: 'authenticated'
}
</script>
Anonymous middleware

만약 오직 특정 페이지만을 위한 미들웨어를 사용하고자 한다면 직접 함수(또는 함수 배열)를 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- pages/secret.vue -->

<template>
<h1>Secret page</h1>
</template>

<script>
export default {
middleware({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}
}
</script>