4.7 KiB
4.7 KiB
3. 서버 라우트·엔드포인트 (server/api/* & server/routes/*)
Nitro 엔진
Nuxt의 서버는 Nitro로 구동된다. server/ 디렉토리에 파일을 만들면 자동으로 API 엔드포인트가 생성된다.
server/
├── api/ # /api/ 접두사가 붙음
│ ├── hello.ts → GET /api/hello
│ ├── users/
│ │ ├── index.ts → GET /api/users
│ │ └── [id].ts → GET /api/users/:id
│ └── products.post.ts → POST /api/products (메서드 지정)
└── routes/ # 접두사 없음
└── sitemap.xml.ts → GET /sitemap.xml
기본 사용법
eventHandler
// server/api/hello.ts
export default defineEventHandler((event) => {
return { message: 'Hello, Nuxt!' }
})
getQuery — 쿼리 파라미터 읽기
// server/api/products.ts
// GET /api/products?category=tent&limit=10
export default defineEventHandler((event) => {
const query = getQuery(event)
// query.category → 'tent'
// query.limit → '10'
return {
category: query.category,
limit: Number(query.limit) || 20
}
})
readBody — 요청 본문(Body) 읽기
// server/api/products.post.ts
// POST /api/products
export default defineEventHandler(async (event) => {
const body = await readBody(event)
// body = { name: '텐트', price: 150000 }
// DB에 저장하는 로직
const product = await db.create(body)
return product
})
라우트 파라미터
// server/api/users/[id].ts
// GET /api/users/123
export default defineEventHandler((event) => {
const id = getRouterParam(event, 'id')
// id → '123'
return { userId: id }
})
HTTP 메서드 지정
파일명에 메서드를 붙이면 해당 메서드만 처리한다.
server/api/products.get.ts → GET만 처리
server/api/products.post.ts → POST만 처리
server/api/products.put.ts → PUT만 처리
server/api/products.delete.ts → DELETE만 처리
메서드 제한 없이 처리하려면 내부에서 분기한다:
// server/api/products.ts
export default defineEventHandler(async (event) => {
const method = getMethod(event)
if (method === 'GET') {
return await getProducts()
}
if (method === 'POST') {
const body = await readBody(event)
return await createProduct(body)
}
})
유틸리티 함수 모음
import {
defineEventHandler, // 핸들러 정의
getQuery, // ?key=value 읽기
readBody, // POST body 읽기
getRouterParam, // URL 파라미터 읽기 (/users/:id)
getMethod, // HTTP 메서드 확인
getHeaders, // 요청 헤더 읽기
getCookie, // 쿠키 읽기
setCookie, // 쿠키 설정
setResponseStatus, // 응답 상태코드 설정
sendRedirect, // 리다이렉트
createError, // 에러 생성
} from 'h3' // Nuxt가 내부적으로 h3를 사용
에러 처리
// server/api/users/[id].ts
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id')
const user = await db.findUser(id)
if (!user) {
// 404 에러를 던지면 Nuxt가 적절한 응답을 보냄
throw createError({
statusCode: 404,
statusMessage: '사용자를 찾을 수 없습니다'
})
}
return user
})
미들웨어 (서버 전용)
// server/middleware/auth.ts
// 모든 API 요청에 자동으로 실행됨
export default defineEventHandler((event) => {
const token = getHeader(event, 'authorization')
if (!token) {
throw createError({ statusCode: 401, statusMessage: '인증 필요' })
}
})
server/routes/ vs server/api/
// server/api/data.ts → /api/data
// server/routes/data.ts → /data (접두사 없음)
// sitemap, robots.txt 같은 특수 엔드포인트에 유용
// server/routes/robots.txt.ts
export default defineEventHandler(() => {
return `User-agent: *\nDisallow: /admin`
})
실전 예시: CRUD API
// server/api/purchases/index.get.ts
export default defineEventHandler(async (event) => {
const query = getQuery(event)
const purchases = await db
.from('purchases')
.select('*')
.limit(Number(query.limit) || 20)
return purchases
})
// server/api/purchases/index.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const purchase = await db.from('purchases').insert(body)
setResponseStatus(event, 201)
return purchase
})
// server/api/purchases/[id].delete.ts
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id')
await db.from('purchases').delete().eq('id', id)
return { success: true }
})