Next.js 12 업데이트

2021년 12월 26일
Template Library

Template Library 시리즈의 세 번째 글은 Next.js 12 적용에 대한 이야기입니다.

Next.js 12 업데이트 소식 나온 지 거의 두 달이 지나가고 있네요. Template Library에서 먼저 적용하여 테스트해보고 실무에도 적용한 지도 한 달이란 시간이 넘게 지나가고 있습니다. 사실 이 글은 Template Library를 적용하고 바로 작성하고자 했지만, 정작 적용 후 개인적으로 너무 바쁜 시간을 보내어 지금에서야 작성하게 되었습니다.

  • Rust Compiler: ~3x faster Fast Refresh and ~5x faster builds
  • Middleware (beta): Enabling full flexibility in Next.js with code over configuration
  • React 18 Support: Native Next.js APIs are now supported, as well as Suspense
  • <Image /> AVIF Support: Opt-in for 20% smaller images
  • Bot-aware ISR Fallback: Optimized SEO for web crawlers
  • Native ES Modules Support: Aligning with the standardized module system
  • URL Imports (alpha): Import packages from any URL, no installs required
  • React Server Components (alpha): Try it today, including SSR streaming

Next.js 12에서 업데이트된 내용을 위와 같이 8가지입니다만, 실제 제가 Template Library에 적용하고 실무에서 사용하고 있는 사항은 Middleware뿐이어서 이 글에서는 Middleware에 대한 정리만 진행하고자 합니다.

// pages/_middleware.ts

import type { NextFetchEvent, NextRequest } from 'next/server'

export function middleware(req: NextRequest, ev: NextFetchEvent) {
  return new Response('Hello, world!')
}

Middleware의 사용 방법은 Middleware를 적용하고자 하는 페이지에서 _middleware.ts 파일을 생성하고 적용하고자 하는 로직을 넣으면 됩니다.

Middleware가 들어오기 전에는 Next.js의 내장된 서버 대신 Express나 Nest.js를 사용하여 별도의 서버를 구성하거나, 혹은 별도의 서버에서 해야 될 작업 중 일부를 Api RoutesgetServerSideProps, Custom App 등을 사용하여 구현하곤 하였습니다.

물론 Middleware가 들어온 지금도 더 복잡한 로직을 사용해야 하는 경우에는 전자를, 그 이외의 상황에서도 일부는 후자에 기술된 내용들을 사용해야 하는 것은 변함이 없을 것 같습니다. 다만, 후자의 상황에서 일부 애매하게 사용하던 부분들을 해결할 수 있다는 생각이 듭니다.

- package.json
- /pages
    - index.tsx
    - _app.tsx # App getInitialProps
    - _middleware.ts # root middleware
    - /parent
      - _middleware.ts # parent middleware
      - /child
        - _middleware.ts # child middleware
        - index.tsx # child getServerSideProps

Middleware의 호출 순서를 확인하기 위하여 상단과 구조를 구성하고 _middleware, Page.getServerSideProps, App.getInitialProps에 url 정보와 함께 로그를 남겨보았고 결과는 아래와 같았습니다.

root middleware /parent/child
parent middleware /parent/child
child middleware /parent/child
App getInitialProps /parent/child
child getServerSideProps /parent/child
root middleware /manifest.json
root middleware /images/favicon-32x32.png

root middleware가 가장 먼저 호출되면 이어 parent middleware, child middleware 순으로 호출되고, App의 getInitialProps, child의 getServerSideProps 순으로 호출되는 것을 확인할 수 있었습니다. 페이지에 대한 호출이 완료되면 페이지에서 호출되는 자원들이 root middleware를 호출하게 됩니다.

root middleware /parent/child
parent middleware /parent/child
child middleware /parent/child
App getInitialProps /_next/data/development/parent/child.json
child getServerSideProps /_next/data/development/parent/child.json

클라이언트에서 이동하게 될 경우에는 위와 같이 로그가 남았습니다.

middleware가 App의 getInitialProps 보다 먼저 호출되기 때문에 서버에서 수행됐으면 하는 작업 중에, 전역에 적용하기에는 getInitialProps는 클라이언트에 노출되고, 고차함수로 getServerSideProps를 Wrapping하기 애매한 경우를 대치하기에 좋은 수단일 것 같습니다.

이 경우에 가장 먼저 떠오른 부분이 인증 관련 처리였습니다. 필자는 Template Library의 인증 부분에 적용하여 검증해보았고, 실무에서도 인증 로직을 middleware이 적용되어 사용해보고 있는데 기존에 사용하던 방식들에 비해 깔끔하고 확장하기도 용이해 잘 사용하고 있습니다.

middleware에서 cookie에 대한 read, write가 지원되고, redirectrewrite가 지원되어 인증 등의 작업에서는 아주 유용하게 사용하고 있습니다. 다만, 하나 아쉬운 부분은 middleware 체인 사이에 데이터를 넘겨줄 수 없어서, 체인 간 데이터를 전달해야 할 경우에는 대응할 수 없어 다소 아쉬웠습니다.

Recently posts
© 2016-2023 smilecat.dev