iBetter Books
수정

Ch 01. Nitro 서버 이해하기

Nuxt 3를 설치하면 자동으로 따라오는 것이 있습니다. Nitro라는 서버 엔진입니다. 별도로 Express나 Fastify를 설치하지 않아도, server/ 폴더에 파일을 하나 만들면 즉시 API 엔드포인트가 열립니다.

Nitro는 UnJS 생태계의 일부로, 특정 런타임에 종속되지 않도록 설계되었습니다. Node.js는 물론 Deno, Bun, Cloudflare Workers, Vercel Edge 등 다양한 환경에 동일한 코드를 배포할 수 있습니다. Nuxt 팀이 직접 개발하고 관리하므로 Nuxt와의 통합이 매우 자연스럽습니다.

Express, FastAPI와 무엇이 다른가

Express나 FastAPI를 사용하면 프론트엔드와 백엔드를 별도 프로젝트로 분리해서 개발합니다. API 서버를 따로 띄우고, 프론트에서 HTTP 요청을 보내는 구조입니다.

Nitro는 이 구조를 단순화합니다. Nuxt 프로젝트 안에서 server/api/ 폴더에 파일을 만들면 그것이 곧 API 엔드포인트가 됩니다. 두 프로젝트를 관리할 필요가 없고, 공통 타입을 공유하기도 쉽습니다.

물론 규모가 커지거나 팀이 분리된다면 별도 백엔드 서버가 필요할 수 있습니다. 하지만 개인 프로젝트나 중소 규모 서비스라면 Nitro 하나로 충분합니다.

h3 이벤트 핸들러

Nitro는 내부적으로 h3라는 경량 HTTP 프레임워크를 사용합니다. API 핸들러는 defineEventHandler 함수로 감싸서 작성합니다.

// server/api/hello.tsexport default defineEventHandler((event) => {  return { message: '안녕하세요, Nitro!' }})

이 파일을 만들면 GET /api/hello로 접근할 수 있습니다. 반환값은 자동으로 JSON으로 직렬화됩니다.

요청 정보 다루기

실제 API에서는 요청 메서드, 본문, 쿼리스트링을 읽어야 합니다. h3는 이를 위한 유틸리티 함수를 제공합니다.

// server/api/example.tsexport default defineEventHandler(async (event) => {  // 요청 메서드 확인  const method = getMethod(event)  // POST 본문 파싱 (JSON 자동 파싱)  const body = await readBody(event)  // 쿼리스트링 파싱 (?page=1&limit=10)  const query = getQuery(event)  return { method, body, query }})

readBodyasync로 호출해야 합니다. JSON, FormData 등 다양한 Content-Type을 자동으로 파싱합니다.

서버에서만 실행된다는 의미

Nitro 핸들러는 서버에서만 실행됩니다. 브라우저로 전송되지 않기 때문에 다음과 같은 작업을 안전하게 수행할 수 있습니다.

  • 데이터베이스 직접 접근
  • 환경변수에서 시크릿 키 읽기
  • 서드파티 API 비밀 키 사용
  • 파일시스템 접근

클라이언트 측 useFetch$fetch에서 이 API를 호출하면 HTTP 요청이 이루어지고, 서버는 결과만 응답합니다. 내부 구현 세부사항은 클라이언트에 노출되지 않습니다.

이처럼 Nitro는 파일 기반 라우팅과 h3 핸들러라는 단순한 규칙만으로 백엔드 기능을 완성할 수 있게 해 줍니다. 복잡한 설정 없이 파일을 만드는 것만으로 API가 생긴다는 점이 Nitro의 가장 큰 매력입니다.