icon안동민 개발노트

유용한 Next.js 라이브러리 소개


 Next.js App Router 생태계에는 개발을 더욱 효율적으로 만들어주는 다양한 라이브러리들이 있습니다.

 이 절에서는 주요 영역별로 유용한 라이브러리들을 소개하고, 각각의 특징과 Next.js App Router와의 통합 방법을 알아보겠습니다.

상태 관리

 1. Zustand

  • 특징 : 간단하고 가벼운 상태 관리 라이브러리
  • 사용 사례 : 중소규모 애플리케이션의 전역 상태 관리
  • Next.js 통합
app/store/useStore.js
import { create } from 'zustand'
 
const useStore = create((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}))
 
export default useStore
app/components/Counter.js
'use client'
import useStore from '../store/useStore'
 
export default function Counter() {
  const { count, increment } = useStore()
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  )
}
  • 장점 : 간단한 API, 작은 번들 크기
  • 단점 : 복잡한 상태 로직 관리에는 부적합할 수 있음

 2. Jotai

  • 특징 : 원자적 접근 방식의 상태 관리
  • 사용 사례 : React 18의 동시성 모드와 호환되는 상태 관리
  • Next.js 통합
app/atoms/countAtom.js
import { atom } from 'jotai'
 
export const countAtom = atom(0)
app/components/Counter.js
'use client'
import { useAtom } from 'jotai'
import { countAtom } from '../atoms/countAtom'
 
export default function Counter() {
  const [count, setCount] = useAtom(countAtom)
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(c => c + 1)}>Increment</button>
    </div>
  )
}
  • 장점 : React 18 기능과의 우수한 호환성, 작은 API 표면
  • 단점 : 복잡한 상태 로직 구현 시 다소 번거로울 수 있음

폼 처리

 React Hook Form

  • 특징 : 성능 중심의 폼 관리 라이브러리
  • 사용 사례 : 복잡한 폼 처리, 유효성 검사
  • Next.js 통합
app/components/LoginForm.js
'use client'
import { useForm } from 'react-hook-form'
 
export default function LoginForm() {
  const { register, handleSubmit, errors } = useForm()
  const onSubmit = data => console.log(data)
 
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('email', { required: true })} />
      {errors.email && <span>This field is required</span>}
      <input {...register('password', { required: true })} type="password" />
      {errors.password && <span>This field is required</span>}
      <button type="submit">Submit</button>
    </form>
  )
}
  • 장점 : 높은 성능, 적은 리렌더링
  • 단점 : 복잡한 폼에서는 러닝 커브가 있을 수 있음

스타일링

 Tailwind CSS

  • 특징 : 유틸리티 우선 CSS 프레임워크
  • 사용 사례 : 빠른 UI 개발, 일관된 디자인 시스템 구축
  • Next.js 통합
app/components/Button.js
export default function Button({ children }) {
  return (
    <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
      {children}
    </button>
  )
}
  • 장점 : 빠른 개발 속도, 높은 커스터마이징 가능성
  • 단점 : 클래스 이름이 길어질 수 있음, 디자인 시스템 없이는 일관성 유지가 어려울 수 있음

인증

 NextAuth.js

  • 특징 : Next.js를 위한 완전한 인증 솔루션
  • 사용 사례 : 소셜 로그인, JWT 인증
  • Next.js 통합
app/api/auth/[...nextauth]/route.js
import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'
 
const handler = NextAuth({
  providers: [
    Providers.Google({
      clientId: process.env.GOOGLE_ID,
      clientSecret: process.env.GOOGLE_SECRET
    }),
  ],
})
 
export { handler as GET, handler as POST }
  • 장점 : 다양한 인증 제공자 지원, 간편한 설정
  • 단점 : 고도로 커스터마이징된 인증 로직에는 부적합할 수 있음

데이터 페칭

 SWR

  • 특징 : React Hooks for Data Fetching
  • 사용 사례 : 실시간 데이터 업데이트, 캐시 관리
  • Next.js 통합
app/components/UserProfile.js
'use client'
import useSWR from 'swr'
 
const fetcher = (...args) => fetch(...args).then(res => res.json())
 
export default function UserProfile({ id }) {
  const { data, error } = useSWR(`/api/user/${id}`, fetcher)
 
  if (error) return <div>Failed to load</div>
  if (!data) return <div>Loading...</div>
 
  return <div>Hello {data.name}!</div>
}
  • 장점 : 자동 재검증, 낙관적 UI 업데이트
  • 단점 : 서버 컴포넌트와 함께 사용 시 주의 필요

테스팅

 Jest & React Testing Library

  • 특징 : JavaScript 테스팅 프레임워크와 React 컴포넌트 테스트 유틸리티
  • 사용 사례 : 단위 테스트, 통합 테스트
  • Next.js 통합
__tests__/Home.test.js
import { render, screen } from '@testing-library/react'
import Home from '../app/page'
 
describe('Home', () => {
  it('renders a heading', () => {
    render(<Home />)
    const heading = screen.getByRole('heading', { name: /welcome/i })
    expect(heading).toBeInTheDocument()
  })
})
  • 장점 : 광범위한 생태계, 사용자 중심 테스트 접근 방식
  • 단점 : 서버 컴포넌트 테스트에 추가 설정 필요

 이 라이브러리들은 이전 장들에서 다룬 주제들과 밀접하게 연관됩니다.

 예를 들어, 상태 관리 라이브러리는 8장의 상태 관리 개념을 확장하며, NextAuth.js는 10장의 인증 및 권한 관리와 직접적으로 연결됩니다.

실습 : 라이브러리 선택 및 통합

 Next.js App Router 프로젝트에 Zustand를 사용한 상태 관리와 React Hook Form을 사용한 폼 처리를 통합해보세요.

  1. 라이브러리 설치
npm install zustand react-hook-form
  1. Zustand 스토어 생성
app/store/useStore.js
import { create } from 'zustand'
 
const useStore = create((set) => ({
  user: null,
  setUser: (user) => set({ user }),
}))
 
export default useStore
  1. React Hook Form을 사용한 로그인 폼 구현
app/components/LoginForm.js
'use client'
import { useForm } from 'react-hook-form'
import useStore from '../store/useStore'
 
export default function LoginForm() {
  const { register, handleSubmit, errors } = useForm()
  const setUser = useStore((state) => state.setUser)
 
  const onSubmit = async (data) => {
    // 실제 로그인 로직 구현
    const user = { name: data.email }
    setUser(user)
  }
 
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register('email', { required: true })} placeholder="Email" />
      {errors.email && <span>This field is required</span>}
      <input {...register('password', { required: true })} type="password" placeholder="Password" />
      {errors.password && <span>This field is required</span>}
      <button type="submit">Login</button>
    </form>
  )
}
  1. 사용자 프로필 컴포넌트 구현
app/components/UserProfile.js
'use client'
import useStore from '../store/useStore'
 
export default function UserProfile() {
  const user = useStore((state) => state.user)
 
  if (!user) return <div>Please log in</div>
 
  return <div>Welcome, {user.name}!</div>
}
  1. 페이지에 컴포넌트 통합
app/page.js
import LoginForm from './components/LoginForm'
import UserProfile from './components/UserProfile'
 
export default function Home() {
  return (
    <div>
      <h1>Welcome to My App</h1>
      <LoginForm />
      <UserProfile />
    </div>
  )
}

 이 실습을 통해 Zustand를 사용한 상태 관리와 React Hook Form을 사용한 폼 처리를 Next.js App Router 프로젝트에 통합하는 방법을 경험할 수 있습니다.

 이러한 라이브러리들을 활용함으로써 개발 생산성을 높이고 코드의 품질을 향상시킬 수 있습니다.

 Next.js 생태계의 다양한 라이브러리들은 개발 프로세스를 더욱 효율적으로 만들어줍니다.

 각 라이브러리의 특성과 장단점을 이해하고, 프로젝트의 요구사항에 맞는 적절한 라이브러리를 선택하는 것이 중요합니다.

 지속적으로 변화하는 JavaScript 생태계에서 최신 트렌드를 파악하고 새로운 라이브러리들을 탐구하는 것도 개발자의 중요한 역량 중 하나입니다.