유용한 Next.js 라이브러리 소개
인증·상태·UI·폼·데이터베이스 요구사항과 서버·클라이언트 실행 위치를 기준으로 보조 라이브러리를 선택합니다.
Next.js는 React 기반 프레임워크이지만, 추가 라이브러리는 기본 기능과 기존 의존성으로 해결하기 어려운 요구가 있을 때 검토합니다.
Next.js 프로젝트에서는 인증, 상태 관리, UI, 데이터 페칭, 유효성 검사 같은 요구사항에 맞춰 외부 라이브러리를 함께 검토해야 합니다.
이 절에서는 Next.js 프로젝트의 생산성과 효율성을 극대화하는 데 유용한 핵심 라이브러리들을 카테고리별로 소개하고, 각 라이브러리의 주요 기능과 Next.js 환경에서의 활용 팁을 제시합니다.
인증 (Authentication)
사용자별 데이터나 보호된 기능이 있다면 로그인·세션과 서버 권한 검사를 설계합니다.
-
Auth.js
- 설명: Next.js 애플리케이션을 위한 강력하고 유연한 오픈 소스 인증 솔루션입니다. Google, GitHub, Kakao 등 다양한 소셜 로그인 제공자(Provider)를 쉽게 통합할 수 있으며, 자격 증명(Credentials) 방식도 연결할 수 있습니다. 비밀번호 검증·저장·가입 정책은 애플리케이션이 구현해야 합니다. 세션 관리, JWT(JSON Web Tokens), OAuth 같은 복잡한 인증 로직을 추상화해 개발자가 인증 구현에 드는 노력을 최소화합니다.
- Next.js 활용 팁: App Router에서
src/auth.ts가 내보낸handlers를 인증 라우트에 연결하고, 서버 컴포넌트와 라우트 핸들러에서는auth()로 세션을 확인합니다. Route Handler와 Server Action은 각 작업의 권한도 확인해야 하며, 인증 라우트 연결만으로 보호되지 않습니다. - 설치: v5의
auth()API를 사용하려면npm install next-auth@beta로 설치합니다. - 링크: https://authjs.dev/
상태 관리 (State Management)
클라이언트 컴포넌트에서 복잡한 전역 상태를 효율적으로 관리하기 위한 라이브러리들입니다. 아래의 서버 상태 도구는 서버에서 받은 데이터의 재조회·동기화도 담당하므로, UI에서 직접 만든 상태와 구분합니다.
같은 화면의 세 가지 값 구분하기 재고 목록에서 설명의 열림 여부는 그 컴포넌트의 지역 상태로 시작할 수 있습니다. 여러 화면이 공유하는 정렬 조건은 URL에 남겨 새로고침·공유가 필요한지, 클라이언트 스토어에서만 유지할지 먼저 정합니다. 서버가 보내는 현재 재고 수량은 여러 사용자에 의해 바뀔 수 있으므로 서버 데이터입니다. 이를 조회한 캐시는 DB 원본이나 구매 가능 여부의 최종 판정을 대신하지 않습니다. 같은 재고 데이터를 SWR과 React Query 양쪽에서 따로 캐시하면 한쪽만 갱신될 수도 있으므로, 중복 도입 전에 조회·갱신 책임을 정합니다.
-
Zustand
- 설명: 작고 빠르며 확장 가능한 상태 관리 라이브러리입니다. 비교적 적은 코드로 스토어를 정의하고 업데이트하며, 미들웨어와 개발자 도구 연동도 가능합니다.
- Next.js 활용 팁: React Hook을 사용하는 UI는 Client Component 경계에 둡니다. SSR에서는 스토어를 요청별로 만들고 양쪽 초기 데이터를 맞추며, RSC에서 공유 전역 스토어를 읽거나 수정하지 않습니다. Zustand의 vanilla 스토어 API 자체가 브라우저 전용인 것은 아닙니다.
- 설치:
npm install zustand - 링크: https://zustand-demo.pmnd.rs/
-
Jotai
- 설명: Zustand와 유사하게 작고 원자적인(atomic) 상태 관리를 지향하는 라이브러리입니다. React의
useState와 유사한atom개념을 사용하여 상태를 정의하며, atom 의존 관계를 통해 필요한 구독 업데이트를 줄일 수 있습니다. 렌더 횟수의 최솟값을 보장하지는 않습니다. - Next.js 활용 팁: Hook을 사용하는 UI는 Client Component에 둡니다. SSR에서 요청 간 상태가 섞이지 않게 적절한 Provider로 스토어 범위를 정하고, 서버와 클라이언트의 초기값을 맞춥니다.
- 설치:
npm install jotai - 링크: https://jotai.org/
- 설명: Zustand와 유사하게 작고 원자적인(atomic) 상태 관리를 지향하는 라이브러리입니다. React의
-
React Query (TanStack Query)
- 설명: 서버 상태(Server State) 관리에 특화된 라이브러리입니다. 데이터 페칭, 캐싱, 동기화, 업데이트 등 비동기 데이터와 관련된 복잡한 작업을 선언적으로 처리합니다. 로딩, 에러, 성공 상태를 자동으로 관리해 주어 불필요한 보일러플레이트 코드를 줄여 줍니다.
- Next.js 활용 팁: Next.js의 SSR/SSG 환경에서 데이터를 미리 페칭하고, 클라이언트에서 하이드레이션(Hydration)하여 사용자 경험을 개선할 수 있습니다.
app라우터에서는 서버 컴포넌트에서 데이터를 페칭하고 클라이언트 컴포넌트에서 React Query를 활용하여 추가 데이터 관리 및 UI 업데이트를 처리하는 방식이 일반적입니다. - 설치:
npm install @tanstack/react-query - 링크: https://tanstack.com/query/latest
-
SWR
- 설명: Vercel에서 개발한 데이터 페칭 라이브러리로, React Query와 유사하게 서버 상태 관리에 사용됩니다. stale-while-revalidate 전략을 사용하여 캐시된 데이터를 즉시 반환하고 백그라운드에서 최신 데이터를 다시 가져와 업데이트합니다.
- Next.js 활용 팁: React Query와 마찬가지로 Next.js의 데이터 페칭 패턴과 잘 통합됩니다.
- 설치:
npm install swr - 링크: https://swr.vercel.app/ko
UI 컴포넌트 및 스타일링
아름답고 반응성 있는 UI를 빠르게 구축하는 데 도움을 주는 라이브러리들입니다.
-
Tailwind CSS
- 설명: 유틸리티 우선(Utility-first) CSS 프레임워크입니다. 작은 단위의 유틸리티 클래스를 조합하고 CSS의
@theme에서 디자인 토큰을 선언합니다. - Next.js 활용 팁: Tailwind CSS 4에서는
@tailwindcss/postcss를 PostCSS 플러그인으로 등록하고 전역 CSS에@import "tailwindcss";를 작성합니다. 일반적인 프로젝트에는 별도의content배열이나 Purge 설정이 필요하지 않습니다. - 설치:
npm install -D tailwindcss @tailwindcss/postcss postcss - 링크: https://tailwindcss.com/
- 설명: 유틸리티 우선(Utility-first) CSS 프레임워크입니다. 작은 단위의 유틸리티 클래스를 조합하고 CSS의
-
Chakra UI
- 설명: 접근성(Accessibility)에 중점을 둔 React 컴포넌트 라이브러리입니다. 버튼, 폼, 다이얼로그 같은 컴포넌트와 일관된 스타일 속성·레시피를 제공합니다.
- Next.js 활용 팁: Chakra UI 3의 CLI snippet이 생성하는
Provider를 App Router의layout.tsx에 배치합니다. 이 Provider는 Chakra 설정과next-themes기반 색상 모드를 묶습니다. Turbopack에서 Emotion 하이드레이션 불일치가 보이면 Chakra의 공식 Next.js 가이드에 따라 개발·빌드의 번들러 조건을 맞춰 확인합니다. - 설치:
npm install @chakra-ui/react @emotion/react후npx @chakra-ui/cli snippet add - 링크: https://chakra-ui.com/
-
Radix UI
- 설명: CSS 프레임워크나 디자인 시스템에 종속되지 않는 저수준(low-level) UI 컴포넌트 프리미티브(Primitive) 라이브러리입니다. Headless UI로, 컴포넌트의 논리와 접근성에만 집중하며 스타일은 개발자가 직접 정의할 수 있습니다.
- Next.js 활용 팁: 개발자가 원하는 어떤 스타일링 방식(CSS Modules, Tailwind CSS, styled-components 등)과도 함께 사용할 수 있습니다. 프리미티브가 키보드 이동·포커스 관리 같은 동작을 돕더라도, 아이콘만 있는 버튼의 접근 가능한 이름과 올바른 컴포넌트 조합은 애플리케이션이 제공해야 합니다. 완성한 화면에서 키보드로 열고 닫으며 포커스가 돌아오는지도 확인합니다.
- 설치:
npm install @radix-ui/react-<component-name>(예:@radix-ui/react-dialog) - 링크: https://www.radix-ui.com/
폼 유효성 검사 (Form Validation)
사용자 입력 폼의 유효성을 검사하고 관리하는 데 사용됩니다.
-
React Hook Form
- 설명: React 폼 관리를 위한 고성능 라이브러리입니다. 적은 리렌더링, 쉬운 유효성 검사 통합(Zod, Yup 등), 그리고 적은 코드량으로 복잡한 폼을 처리할 수 있습니다.
useForm훅을 통해 폼 상태와 유효성 검사 로직을 효율적으로 관리합니다. - Next.js 활용 팁: 클라이언트 컴포넌트에서 폼을 정의할 때 주로 사용합니다. Server Actions와 함께 사용할 경우, 클라이언트 측에서 1차 유효성 검사를 수행하고 서버 측에서 2차 검사를 통해 데이터 무결성을 확보할 수 있습니다.
- 설치:
npm install react-hook-form - 링크: https://react-hook-form.com/
- 설명: React 폼 관리를 위한 고성능 라이브러리입니다. 적은 리렌더링, 쉬운 유효성 검사 통합(Zod, Yup 등), 그리고 적은 코드량으로 복잡한 폼을 처리할 수 있습니다.
-
Zod
- 설명: TypeScript 우선 스키마 유효성 검사 라이브러리입니다. 런타임 검증 스키마를 정의하고, 그 스키마에서 정적 TypeScript 타입을 추론합니다. TypeScript 타입 선언만으로 런타임 검사가 생기는 것은 아닙니다. React Hook Form, Next.js Server Actions 등과 함께 사용하여 프론트엔드와 백엔드 모두에서 데이터의 형태와 유효성을 강력하게 보장할 수 있습니다.
- Next.js 활용 팁: Server Actions의 입력값 유효성 검사에 Zod 스키마를 사용하여 안정적인 데이터 처리를 구현할 수 있습니다. 클라이언트 컴포넌트에서는
@hookform/resolvers의zodResolver로 React Hook Form과 연결할 수 있습니다. 스키마 검증은 작업 권한 검사를 대체하지 않습니다. - 설치:
npm install zod(React Hook Form 연결 시@hookform/resolvers도 설치) - 링크: https://zod.dev/
입력 형태 검사와 작업 권한을 이어서 확인하기
FormData.get()은 숫자 입력란의 값도 보통 문자열로 돌려줍니다. z.number()에 문자열 "3"을 그대로 넣으면 숫자 검증에 실패합니다. 다음은 수량을 1 이상 99 이하의 정수로 받는 예입니다. 빈 문자열과 파일 입력을 먼저 제외하고, 의도적으로 숫자로 변환한 뒤 런타임 검사를 합니다.
import { z } from 'zod';
const Quantity = z.number().int().min(1).max(99);
export function parseQuantity(formData: FormData): number | null {
const raw = formData.get('quantity');
if (typeof raw !== 'string' || raw.trim() === '') return null;
const result = Quantity.safeParse(Number(raw));
return result.success ? result.data : null;
}"3"은 3이 되지만 "abc", "3.5", "100"은 이 조건을 만족하지 않습니다. 빈 문자열은 Number("")가 0이 되기 전에 거절합니다. 이 예는 숫자 변환 결과를 검사하며, 입력 표기까지 십진 숫자로만 제한하려면 별도의 형식 조건도 정해야 합니다.
수량 3을 얻었어도 사용자 2가 사용자 1의 장바구니 항목을 바꿀 권한은 생기지 않습니다. 서버는 검증한 세션에서 사용자 ID를 얻고, DB의 항목 소유자와 비교한 뒤 변경합니다. 폼이 보낸 ownerId를 소유권의 근거로 믿지 않습니다. 클라이언트 검사는 빠른 피드백을 주고, 서버 검사는 직접 보낸 요청에도 적용합니다.
데이터베이스 ORM/ODM
데이터베이스와 애플리케이션 간의 상호작용을 돕는 라이브러리입니다.
-
Mongoose
- 설명: Node.js 환경에서 MongoDB를 위한 객체 데이터 모델링(ODM) 라이브러리입니다. 스키마 기반으로 데이터를 정의하고, 데이터 유효성 검사, 쿼리 빌더, 미들웨어 등 다양한 기능을 제공하여 MongoDB 사용을 편리하게 합니다.
- Next.js 활용 팁: Route Handler, 서버 컴포넌트와 Server Actions에서 MongoDB를 사용할 때 연결 로직은
lib/db.ts같은 서버 전용 모듈로 분리합니다. Mongoose는 Node.js 런타임을 사용하며 Next.js Edge Runtime에서의 직접 MongoDB 연결을 지원하지 않습니다. - 설치:
npm install mongoose - 링크: https://mongoosejs.com/
-
Prisma
- 설명: 차세대 Node.js 및 TypeScript ORM(객체 관계형 매핑)입니다. 데이터베이스 스키마를 정의하고 이를 기반으로 타입 세이프한 쿼리를 자동으로 생성합니다. PostgreSQL, MySQL, SQLite 등 다양한 관계형 데이터베이스를 지원합니다.
- Next.js 활용 팁: Route Handler, 서버 컴포넌트와 Server Actions의 데이터 계층에서 사용합니다. 생성된 Prisma Client의 타입을 서버 데이터 계층에서 활용합니다. 선택한 Prisma 버전·DB·런타임에 맞는 드라이버 또는 어댑터와 생성 설정도 필요합니다.
- 설치:
npm install prisma @prisma/client및npx prisma init - 링크: https://www.prisma.io/
기타 유용한 라이브러리
use-debounce: 사용자 입력(검색어, 텍스트 입력 등)에 대한 이벤트를 디바운싱(Debouncing) 처리하여 과도한 함수 호출이나 API 요청을 방지합니다. 검색 필터링 기능 구현 시 유용합니다.- 설치:
npm install use-debounce - 링크: https://www.npmjs.com/package/use-debounce
- 설치:
react-icons: 인기 있는 아이콘 라이브러리(Font Awesome, Material Design Icons 등)의 아이콘들을 React 컴포넌트로 제공하여 쉽게 사용할 수 있습니다.- 설치:
npm install react-icons - 링크: https://react-icons.github.io/react-icons/
- 설치:
date-fns/moment/dayjs: 날짜 및 시간 조작을 위한 유틸리티 라이브러리입니다. 날짜 포매팅과 계산을 지원합니다. 간단한 표시라면 표준IntlAPI부터 확인하고, 추가 연산은 필요한 함수와 번들 영향을 비교합니다. Moment는 유지보수 모드의 기존 프로젝트이므로 새 도입은 유지보수 정책을 먼저 확인합니다.- 설치:
npm install date-fns(또는moment,dayjs) - 링크: https://date-fns.org/
- 설치:
검색 요청이 끝나는 순서도 다루기 디바운스는 입력이 잦을 때 아직 실행하지 않은 호출을 늦추거나 취소하는 데 도움이 됩니다. 이미 시작한 요청의 취소나 응답 순서를 자동으로 보장하지는 않습니다. 검색 A 요청이 시작된 뒤 검색 B 요청이 시작되고 B 응답이 먼저 왔다면, 늦게 온 A 응답이 화면을 덮지 않도록 요청 번호를 비교하거나 취소·오래된 응답 무시 정책을 함께 구현합니다. 디바운스의 대기 호출 취소와 네트워크 요청 취소는 서로 다른 동작입니다.
Next.js 생태계의 라이브러리는 프로젝트 요구사항, 유지보수성, 번들 영향, 팀 숙련도를 기준으로 선택해야 합니다.
새 기능을 추가할 때는 라이브러리가 제공하는 추상화가 실제 복잡도를 줄이는지도 함께 확인합니다.
필요한 책임부터 고르기 도서 상세에서 접힌 설명의 열림 상태만 저장한다면 먼저 컴포넌트의 useState로 충분한지 확인합니다. 여러 화면이 함께 읽는 UI 상태, 반복 조회할 서버 데이터, 폼 입력 검증은 서로 다른 요구입니다. 라이브러리 이름을 먼저 고르기보다 저장할 값과 실행 위치를 적어 선택합니다.
요구사항을 나누어 보기 장바구니 수량 폼이 있고 서버에서 사용자의 항목만 바꿔야 한다고 합시다. 수량 형식 검사를 통과하면 항목 소유권 검사도 끝난 것일까요? 로그인·입력 검증·서버 데이터 재조회·UI 열림 상태를 모두 하나의 전역 상태 라이브러리로 해결해야 할까요?
검증과 권한의 다른 질문
수량이 올바른 숫자인지는 입력 검증의 질문이며, 그 사용자가 그 항목을 바꿀 수 있는지는 서버 권한 검사의 질문입니다. 로그인 세션을 확인한 뒤에도 항목의 소유자를 검사합니다. 서버에서 받은 장바구니를 재조회·동기화하는 일과 폼의 열림 상태를 관리하는 일도 구분합니다. 작은 UI 상태에는 지역 상태가 충분할 수 있고, 서버 데이터 캐시에는 해당 요구에 맞는 도구를 검토합니다.
채택한 패키지의 버전·지원 런타임·기본 설정을 기록하고, 그 라이브러리를 제거했을 때 사라지는 구체적 복잡도를 설명해 봅니다. 설치 명령을 실행했다는 사실만으로 세션 정책·업무 검증·서버 권한까지 구현된 것은 아닙니다.
추가 연습: 도구의 책임과 입력 조건 적용하기 각 문제는 다음 조건만을 사용합니다.
- 한 재고 목록에서 설명을 열고 닫는 값과 서버가 보내는 재고 수량을 관리합니다. 열림 여부는 다른 화면과 공유하지 않습니다. 두 값을 처음부터 모두 전역 UI 스토어에 넣어야 할까요? 구매 가능 여부는 어디서 최종 확인할까요?
- 검증된 세션의 사용자 ID는 2이고, DB의 장바구니 항목 소유자는 1입니다. 폼은
ownerId=2, 수량"3"을 보냈습니다. 수량 검사가 성공하면 항목을 변경해도 될까요? - 위
parseQuantity에 수량 문자열"3","","abc","3.5","100"을 각각 전달하면 어떤 값이 반환될까요? TypeScript에서 입력을number라고 선언하는 것만으로 같은 검사가 생길까요? - 검색 A와 B의 요청은 이미 시작됐습니다. B 응답을 표시한 뒤 A 응답이 도착했습니다. 디바운스의 대기 호출을 취소하면 A가 화면을 덮는 문제까지 해결될까요?
책임·입력·응답 순서 풀이
- 아닙니다. 열림 여부는 해당 컴포넌트의 지역 상태로 시작할 수 있습니다. 재고 수량은 서버 데이터이므로 재조회·캐시 갱신 요구를 검토합니다. 표시용 캐시가 있어도 구매 시의 권한과 재고 조건은 서버가 확인해야 합니다. 두 값은 저장 위치뿐 아니라 누가 최신값의 권위를 갖는지도 다릅니다.
- 변경하면 안 됩니다. 수량의 형태와 범위는 유효해도 사용자 2는 항목 소유자 1과 다릅니다. 폼의
ownerId는 사용자가 바꿀 수 있는 입력이므로 소유권을 증명하지 않습니다. 검증된 세션 사용자와 DB 소유자를 비교한 결과로 거절합니다. - 차례대로 3,
null,null,null,null입니다. 빈 문자열은 변환 전에 거절하고,"abc"는 숫자로 변환해도 유효한 수가 아니며, 3.5는 정수가 아니고 100은 상한을 넘습니다. TypeScript 타입 선언은 실행 중 들어온 폼 값의 범위나 형태를 자동으로 검사하지 않습니다. - 해결되지 않습니다. A는 대기 호출이 아니라 이미 실행 중인 요청입니다. 현재 검색의 요청 번호와 응답의 요청 번호를 비교해 오래된 A를 무시하는 등의 정책이 필요합니다. 요청 취소를 쓰더라도 완료 경합을 고려해 오래된 응답을 적용하지 않는 조건을 유지합니다.