server

server/ 디렉토리는 API 및 서버 핸들러를 애플리케이션에 등록하는 데 사용된다.

 

Nuxt는 이러한 디렉터리 내의 파일을 자동으로 스캔하여 HMR(Hot Module replacement) 지원으로 API 및 서버 핸들러를 등록한다.

 

디렉토리 구조

-| server/
---| api/
-----| hello.ts      # /api/hello
---| routes/
-----| bonjour.ts    # /bonjour
---| middleware/
-----| log.ts        # log all requests

각 파일은 defineEventHandler() 또는 eventHandler()(별칭)으로 정의된 기본 함수를 내보내야 한다.

 

핸들러는 JSON 데이터인 Promise를 직접 반환하거나 event.node.res.end()를 사용하여 응답을 보낼 수 있다.

 

 

 

 

 

 

 

 

server/api/hello.ts

// server/api/hello.ts

export default defineEventHandler((event) => {
  return {
    hello: 'world'
  }
})

이제 페이지와 컴포넌트에서 이 API를 보편적으로 호출할 수 있습니다.

 

pages/index.vue

<!--
pages/index.vue
-->

<script setup lang="ts">
const { data } = await useFetch('/api/hello')
</script>

<template>
  <pre>{{ data }}</pre>
</template>

 

서버 경로

~/server/api 내부의 파일에는 해당 경로에 자동으로 /api 접두사가 붙는다.

 

접두사 없이 /api 서버 경로를 추가하려면 해당 경로를 ~/server/routes 디렉토리에 넣는다.

 

예:

server/routes/hello.ts

// server/routes/hello.ts

export default defineEventHandler(() => 'Hello World!')

 

위의 예에서 /hello 경로는 http://localhost:3000/hello

현재 서버 경로는 페이지 처럼 동적 경로의 전체 기능을 지원하지 않는다.

 

서버 미들웨어

Nuxt는 ~/server/middleware의 모든 파일을 자동으로 읽어 프로젝트에 대한 서버 미들웨어를 생성한다.

 

미들웨어 핸들러는 헤더를 추가하거나 확인하고, 요청을 기록하거나, 이벤트의 요청 개체를 확장하기 위해 다른 서버 경로 이전에 모든 요청에 ​​대해 실행된다.

미들웨어 핸들러는 아무것도 반환하지 않아야 하며(요청을 닫거나 응답하지 않아도 됨) 요청 컨텍스트를 검사 또는 확장하거나 오류를 발생시키기만 하면 된다.

 

사용 예

server/middleware/log.ts

// server/middleware/log.ts

export default defineEventHandler((event) => {
  console.log('New request: ' + getRequestURL(event))
})

 

server/middleware/auth.ts

// server/middleware/auth.ts

export default defineEventHandler((event) => {
  event.context.auth = { user: 123 }
})

 

서버 플러그인

Nuxt는 ~/server/plugins 디렉토리의 모든 파일을 자동으로 읽고 이를 Nitro 플러그인으로 등록한다. 이를 통해 Nitro의 런타임 동작을 확장하고 수명 주기 이벤트에 연결할 수 있다.

 

예:

server/plugins/nitroPlugin.ts

// server/plugins/nitroPlugin.ts

export default defineNitroPlugin((nitroApp) => {
  console.log('Nitro plugin', nitroApp)
})

참고) Nitro plugins

 

서버 유틸리티

서버 경로는 편리한 헬퍼 세트와 함께 제공되는 unjs/h3에 의해 구동된다.

참고) H3 요청 헬퍼

 

~/server/utils 디렉토리에 더 많은 헬퍼를 직접 추가할 수 있다.

 

예를 들어 원래 핸들러를 래핑하고 최종 응답을 반환하기 전에 추가 작업을 수행하는 사용자 정의 핸들러 유틸리티를 정의할 수 있다.

 

예:

server/utils/handler.ts

// server/utils/handler.ts

import type { EventHandler, EventHandlerRequest } from 'h3'

export const defineWrappedResponseHandler = <T extends EventHandlerRequest, D> (
  handler: EventHandler<T, D>
): EventHandler<T, D> =>
  defineEventHandler<T>(async event => {
    try {
      // do something before the route handler
      const response = await handler(event)
      // do something after the route handler
      return { response }
    } catch (err) {
      // Error handling
      return { err }
    }
  })

 

서버 Types ( Nuxt >= 3.5)

IDE 내에서 'nitro'와 'vue'의 자동 임포트 사이의 명확성을 높이려면 아래 내용이 포함된 ~/server/tsconfig.json을 추가할 수 있다.

server/tsconfig.json

// server/tsconfig.json

{
  "extends": "../.nuxt/tsconfig.server.json"
}

현재 이러한 값은 유형 검사(nuxi typecheck) 시 고려되지 않지만 IDE에서 더 나은 유형 힌트를 얻을 수 있다.

 

레시피

경로 매개변수

서버 경로는 /api/hello/[name].ts과 같은 파일 이름의 대괄호 안에 동적 매개변수를 사용할 수 있으며 event.context.params를 통해 액세스할 수 있다.

 

server/api/hello/[name].ts

// server/api/hello/[name].ts

export default defineEventHandler((event) => {
  const name = getRouterParam(event, 'name')

  return `Hello, ${name}!`
})

이제 /api/hello/nuxt에서 이 API를 보편적으로 호출하고 Hello, nuxt!를 얻을 수 있다.

 

HTTP 메서드 매칭

핸들 파일 이름에는  HTTP 메서드 와 일치시키기 위해 .get, .post, .put, .delete, ... 등의 접미사를 넣을 수 있다.

 

server/api/test.get.ts

// server/api/test.get.ts

export default defineEventHandler(() => 'Test get handler')

 

server/api/test.post.ts

// server/api/test.post.ts

export default defineEventHandler(() => 'Test post handler')

위의 예에서 다음을 사용하여 /test 가져옵니다:

  • GET 메소드: Test get handler 반환 
  • POST 메소드: Test post handler 반환 
  • 기타 방법: 405 오류를 반환한다.

또한 디렉토리 내에서 index.[method].ts를 사용하여 코드를 다르게 구성할 수 있으며 이는 API 네임스페이스를 생성하는 데 용이하다.

 

server/api/foo/index.get.ts

// server/api/foo/index.get.ts

export default defineEventHandler((event) => {
  // handle GET requests for the `api/foo` endpoint
})

 

server/api/foo/index.post.ts

// server/api/foo/index.post.ts

export default defineEventHandler((event) => {
  // handle GET requests for the `api/foo` endpoint
})

 

server/api/foo/bar.get.ts

// server/api/foo/bar.get.ts

export default defineEventHandler((event) => {
  // handle GET requests for the `api/foo` endpoint
})

 

포괄 경로 (Catch-all Route)

포괄 경로는 대체 경로 처리에 유용하다.

예를 들어 ~/server/api/foo/[...].ts이라는 파일을 생성하면 /api/foo/bar/baz와 같은 경로 핸들러와 일치하지 않는 모든 요청에 ​​대해 포괄 경로가 등록된다.

 

server/api/foo/[...].ts

// server/api/foo/[...].ts

export default defineEventHandler((event) => {
  // event.context.path to get the route path: '/api/foo/bar/baz'
  // event.context.params._ to get the route segment: 'bar/baz'
  return `Default foo handler`
})

~/server/api/foo/[...slug].ts을 사용하여 포괄 경로의 이름을 설정하고 event.context.params.slug를 통해 액세스할 수 있다.

 

server/api/foo/[...slug].ts

// server/api/foo/[...slug].ts

export default defineEventHandler((event) => {
  // event.context.params.slug to get the route segment: 'bar/baz'
  return `Default foo handler`
})

 

요청 Body 처리 (Body Handling)

server/api/submit.post.ts

// server/api/submit.post.ts

export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  return { body }
})

이제 다음을 사용하여 이 API를 보편적으로 호출할 수 있다.

 

app.vue

<!--
app.vue
-->

<script setup>
async function submit() {
  const { body } = await $fetch('/api/submit', {
    method: 'post',
    body: { test: 123 }
  })
}
</script>
요청 본문을 수락할 수 있는 POST 메서드와 요청을 일치시키기 위해서만 파일 이름에 submit.post.ts를 사용하고 있다. GET 요청 내에서 readBody를 사용할 때 readBody는 405 Method Not Allowed HTTP 오류를 발생시킨다.

 

Query Parameters

샘플 쿼리 /api/query?foo=bar&baz=qux

 

server/api/query.get.ts

// server/api/query.get.ts

export default defineEventHandler((event) => {
  const query = getQuery(event)

  return { a: query.foo, b: query.baz }
})

 

오류 처리

오류가 발생하지 않으면 200 OK 상태 코드가 반환된다.

 

잡히지 않은 오류는 500 Internal Server Error HTTP 오류를 반환한다.

 

다른 오류 코드를 반환하려면 createError 를 사용하여 예외를 발생시켜야한다.

 

server/api/validation/[id].ts

// server/api/validation/[id].ts

export default defineEventHandler((event) => {
  const id = parseInt(event.context.params.id) as number

  if (!Number.isInteger(id)) {
    throw createError({
      statusCode: 400,
      statusMessage: 'ID should be an integer',
    })
  }
  return 'All good'
})

 

상태 코드

다른 상태 코드를 반환하려면 setResponseStatus 유틸리티를 사용한다.

 

아래 예를 들어, 202 Accepted 를 반환하려면...

server/api/validation/[id].ts

// server/api/validation/[id].ts

export default defineEventHandler((event) => {
  setResponseStatus(event, 202)
})

 

런타임 구성

server/api/foo.ts

// server/api/foo.ts

export default defineEventHandler(async (event) => {
  const config = useRuntimeConfig(event)

  const repo = await $fetch('https://api.github.com/repos/nuxt/nuxt', {
    headers: {
      Authorization: `token ${config.githubToken}`
    }
  })

  return repo
})

 

nuxt.config.ts

// nuxt.config.ts

export default defineNuxtConfig({
  runtimeConfig: {
    githubToken: ''
  }
})

 

.env

# .env

NUXT_GITHUB_TOKEN='<my-super-token>'

 

요청 쿠키

server/api/cookies.ts

// server/api/cookies.ts

export default defineEventHandler((event) => {
  const cookies = parseCookies(event)

  return { cookies }
})

 

고급 사용

Nitro 구성

nitro 키를 사용하여 nuxt.config 에 직접 Nitro 구성.

이는 고급 옵션이므로, Nuxt의 semver-minor 버전에서 Nitro가 업그레이드되면 구성 인터페이스가 시간이 지남에 따라 변경될 수 있으므로 사용자 지정 구성은 프로덕션 배포에 영향을 미칠 수 있다.

 

nuxt.config.ts

// nuxt.config.ts

export default defineNuxtConfig({
  // https://nitro.unjs.io/config
  nitro: {}
})

참고) Nuxt-개요 > 서버

 

중첩 라우터

server/api/hello/[...slug].ts

// server/api/hello/[...slug].ts

import { createRouter, defineEventHandler, useBase } from 'h3'

const router = createRouter()

router.get('/test', defineEventHandler(() => 'Hello World'))

export default useBase('/api/hello', router.handler)

 

스트림 보내기

이는 실험적인 기능이며 모든 환경에서 사용할 수 있다.

 

server/api/foo.get.ts

// server/api/foo.get.ts

import fs from 'node:fs'
import { sendStream } from 'h3'

export default defineEventHandler((event) => {
  return sendStream(event, fs.createReadStream('/path/to/file'))
})

 

리디렉션 보내기

server/api/foo.get.ts

// server/api/foo.get.ts

export default defineEventHandler(async (event) => {
  await sendRedirect(event, '/path/redirect/to', 302)
})

 

레거시 핸들러 또는 미들웨어

server/api/legacy.ts

// server/api/legacy.ts

export default fromNodeMiddleware((req, res) => {
  res.end('Legacy handler')
})
레거시 지원은 unjs/h3 을 사용하여 가능하지만 레거시 핸들러는 최대한 피하는 것이 좋다.

 

서버 스토리지

Nitro는 크로스 플랫폼 저장 계층을 제공한다. 추가 스토리지 마운트 지점을 구성하려면 nitro.storage 또는 서버 플러그인을 사용할 수 있다.

 

Redis 스토리지 추가의 예:

nitro.storage 사용 :

 

nuxt.config.ts

// nuxt.config.ts

export default defineNuxtConfig({
  nitro: {
    storage: {
      redis: {
        driver: 'redis',
        /* redis connector options */
        port: 6379, // Redis port
        host: "127.0.0.1", // Redis host
        username: "", // needs Redis >= 6
        password: "",
        db: 0, // Defaults to 0
        tls: {} // tls/ssl
      }
    }
  }
})

이 구성을 API 핸들러에서 사용하려면...

 

server/api/storage/test.ts

// server/api/storage/test.ts

export default defineEventHandler(async (event) => {
  // List all keys with
  const keys = await useStorage('redis').getKeys()

  // Set a key with
  await useStorage('redis').setItem('foo', 'bar')

  // Remove a key with
  await useStorage('redis').removeItem('foo')

  return {}
})

참고) Nitro 스토리지 레이어

 

또는 서버 플러그인 및 런타임 구성을 사용하여 스토리지 마운트 지점을 생성할 수 있다.

 

server/plugins/storage.ts

// server/plugins/storage.ts

import redisDriver from 'unstorage/drivers/redis'

export default defineNitroPlugin(() => {
  const storage = useStorage()

  // Dynamically pass in credentials from runtime configuration, or other sources
  const driver = redisDriver({
      base: 'redis',
      host: useRuntimeConfig().redis.host,
      port: useRuntimeConfig().redis.port,
      /* other redis connector options */
    })

  // Mount driver
  storage.mount('redis', driver)
})

 

nuxt.config.ts

// nuxt.config.ts

export default defineNuxtConfig({
  runtimeConfig: {
    redis: { // Default values
      host: '',
      port: 0,
      /* other redis connector options */
    }
  }
})

'Nuxt 공식문서 번역 > Directories' 카테고리의 다른 글

.env  (0) 2023.12.18
utils  (1) 2023.12.18
public  (0) 2023.12.17
plugins  (1) 2023.12.17
pages  (1) 2023.12.17
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유