29. 표준 라이브러리 스택 가이드

0. 먼저 알고 가기 (30초 요약)

  • 같은 일을 하는 라이브러리는 저장소마다 다르지 않게 하나로 모읍니다.
  • HTTP는 ky, 서버 상태는 react-query, 클라이언트 상태는 zustand, URL 상태는 nuqs를 기본으로 둡니다.
  • 버전은 pnpm catalog로 묶고, 의존 방향은 린트로 검사합니다.

초심자용 한눈에 보기

표준을 정해두면 저장소를 옮겨 다닐 때 매번 새로 익힐 필요가 줄고, 같은 문제를 같은 방법으로 풉니다. 도구를 줄이면 학습할 표면이 줄고, 보안 패치나 버전 업그레이드를 한 번에 적용하기 쉬워집니다.

핵심 용어 빠르게 정리

용어 쉬운 뜻
catalog 워크스페이스 의존성 버전을 한 곳에 모아 고정하는 pnpm 기능
공유 인스턴스 인증·에러 처리를 미리 설정해 재사용하는 HTTP 객체
트리셰이킹 실제로 쓰는 코드만 번들에 남기는 최적화
의존 방향 app→domains→shared 순서로만 import를 허용하는 규칙
철회 조건 표준을 더 이상 유지하지 않고 바꾸기로 하는 명시적 기준
분류 핵심 기술 상태 Stable
연관 가이드 04. 아키텍처, 05. API 통신 도구 원칙 벤더 중립
핵심 테마 HTTP·상태·URL·검증·로깅·스타일 표준, 선택 이유, 정렬 순서 Update 최신 기준

"도구를 통일하는 목적은 멋이 아니라, 저장소를 옮겨도 같은 방식으로 읽고 고치고 지울 수 있게 하는 것이다." 이 문서는 카테고리마다 하나의 표준 라이브러리를 정하고, 왜 그것을 골랐는지와 어떻게 옮겨갈지를 함께 적습니다. 새 라이브러리가 더 분명한 이점을 보이면 철회 조건에 따라 교체합니다.


문서 책임 범위

이 문서가 결정하는 것 단일 출처로 따르는 문서
카테고리별 표준 라이브러리와 선택 이유 04. 아키텍처, 22. 모노레포
HTTP·검증·모킹 적용 방식 05. API 통신
상태·URL 상태 도구 선택 03. 상태관리
버전 정렬·릴리스 경계 11. CI/CD

0. 모든 프론트엔드 그룹 공통 Baseline

기준 최소 적용
한 카테고리 한 표준 같은 일을 하는 라이브러리는 저장소마다 다르지 않게 하나로 모읍니다.
공유 스키마 검증은 zod로 작성해 프론트와 백엔드가 함께 씁니다.
버전 정렬 공통 의존성은 catalog로 버전을 맞춥니다.
구조 경계 import 방향은 린트로 검사합니다.
점진 적용 큰 변경은 저장소별 작은 PR로 나눠 검증한 뒤 머지합니다.

0.1 교차 검증 매트릭스

권고 1차 출처 실행 증거 운영 증거 철회 조건
브라우저 HTTP는 ky 공유 인스턴스로 둔다 라이브러리 공식 문서 요청·에러·인증 헤더 테스트 API 에러율, 재시도율 플랫폼 fetch만으로 동일 요구가 더 단순할 때
URL 상태는 nuqs로 둔다 라이브러리 공식 문서 딥링크·뒤로가기 E2E 잘못된 파라미터 유입률 라우터 내장 기능으로 충분할 때
NestJS 검증은 shared zod로 둔다 zod 문서, nestjs-zod 문서 DTO 검증 단위 테스트 잘못된 요청 4xx 비율 런타임 검증이 불필요한 내부 전용 경로일 때
의존 방향은 boundaries 린트로 강제한다 eslint-plugin-boundaries 문서 lint 위반 0건 구조 회귀 PR 수 단일 모듈 규모라 계층이 불필요할 때

0.2 운영 게이트

Gate Evidence Owner Rollback
라이브러리 채택 번들 diff, 라이선스 확인 플랫폼 오너 표준 외 라이브러리 제거
검증 계층 shared 스키마 테스트 백엔드 오너 이전 검증 방식 복원
구조 경계 boundaries lint 리포트 FE 오너 위반 import 되돌리기
버전 정렬 catalog diff 플랫폼 오너 이전 버전 핀 복원

1. 표준 스택 카탈로그

1.1 프론트엔드 표준

영역 표준 한 줄 이유
HTTP 클라이언트 ky ESM·경량·fetch 기반, 캐싱·재시도는 react-query 담당
서버 상태 @tanstack/react-query 캐싱·재요청·동기화를 한 계층에 모음
클라이언트 상태 zustand 작은 API, 보일러플레이트 최소
URL/쿼리 파라미터 nuqs URL을 단일 상태원으로, 타입과 함께 다룸
react-hook-form + @hookform/resolvers 비제어 입력, 리렌더 최소
검증 zod 프론트·백 공유 스키마
스타일 Tailwind CSS + clsx + tailwind-merge CSS-first·토큰화, 변형은 CVA
UI 프리미티브 Radix + lucide-react 접근성 내장, 아이콘 일관
토스트 알림 sonner 알림 스택·키보드·접근성 기본 제공
애니메이션 motion 기존 라이브러리의 후속 패키지명
날짜 date-fns (+ date-fns-tz) 트리셰이킹·함수형
유틸 es-toolkit 작고 빠른 TS 우선 유틸
에러 경계 react-error-boundary Suspense·Error 경계 표준화
깊은 비교 dequal 경량 deep compare
ID 생성 crypto.randomUUID() 런타임 내장, 외부 의존 0

1.2 백엔드(NestJS) 표준

영역 표준 한 줄 이유
DTO 검증 nestjs-zod shared zod 재사용, 이중 정의 제거
로깅 nestjs-pino 구조적 JSON·요청 컨텍스트
인증 @nestjs/jwt + google-auth-library 별도 추상화 계층 제거
비밀번호 해시 argon2 메모리-하드 해시
ORM 기본값 Prisma (기존 Drizzle 저장소 유지) 새 백엔드의 go-forward 기본값

1.3 툴체인 표준

영역 표준 한 줄 이유
패키지 매니저 pnpm + catalog 워크스페이스 버전 단일화
빌드 Vite + Rolldown 빠른 dev·번들
React 컴파일 React Compiler (babel-plugin-react-compiler) 자동 메모이제이션
린트 ESLint flat + eslint-plugin-react-compiler + eslint-plugin-boundaries RC 규칙·계층 경계 강제
포맷 Prettier 단일 포맷
테스트 vitest + @testing-library + msw + playwright Vite 변환 공유, e2e 분리
시크릿 스캔 secretlint pre-commit 유출 차단
타입 TypeScript strict null 안전

발행 공유 config 패키지 (@heejun/*)

위 툴체인 표준은 npm에 발행된 @heejun/* config 패키지로 구현되어, 각 저장소가 의존성으로 가져다 쓴다. 한 곳에서 관리하므로 설정 드리프트가 사라진다.

패키지 역할
@heejun/eslint-config ESLint flat config (typescript-eslint + React 19 + React Compiler + 계층 경계)
@heejun/prettier-config Prettier 설정
@heejun/typescript-config tsconfig (base / react / node)
@heejun/tailwind-config Tailwind v4 CSS-first @theme
@heejun/vite-config Vite 8 + React Compiler
pnpm add -D @heejun/eslint-config @heejun/prettier-config @heejun/typescript-config @heejun/vite-config @heejun/tailwind-config

적용 방법

각 저장소는 인라인 설정을 지우고 위 패키지를 의존성으로 참조한다.

Prettierpackage.json 에 설정 파일 대신 패키지명을 적고 인라인 .prettierrc 는 삭제한다. 기본값이 형제 저장소 공통 컨벤션(semi: false, trailingComma: 'es5')이라 재포맷 없이 채택된다. Tailwind 클래스 정렬이 필요하면 prettierConfigWithTailwind 를 쓴다.

// package.json
{ "prettier": "@heejun/prettier-config" }

ESLintbase()react() 를 펼쳐 합친다. base() 는 import 위생·typescript-eslint 권장 규칙·Prettier 충돌 비활성을 제공하고, react() 는 React 19·React Compiler·접근성 규칙을 더한다. 저장소별 정책(전역 함수 제한, 테스트 완화 등)은 뒤에 덧붙인다.

// eslint.config.mjs
import { base, react, defineConfig } from '@heejun/eslint-config'

export default defineConfig(
  base({ files: ['**/*.{ts,tsx}'] }),
  react({ files: ['apps/web/**/*.{ts,tsx}'] }),
  // 저장소별 override는 뒤에 덧붙인다
)

테스트/목 컨벤션을 강제하는 heejunRules() 는 opt-in 이므로 필요한 저장소만 defineConfig(base(), react(), heejunRules()) 로 펼친다.

적용 시 알아둘 점eslint-plugin-jsx-a11yminimatch v3을 쓰므로, 저장소가 minimatch v10을 전역 고정했다면 스코프 override(eslint-plugin-jsx-a11y>minimatch)로 v3을 함께 둔다. 의존성 감사 게이트가 있는 저장소는 eslint-plugin-boundaries 가 끌어오는 전이 의존성을 override로 고정한다.

2. 표준 선택 이유

  • ky (HTTP): ESM 네이티브이며 번들이 가볍고 플랫폼 fetch 위에서 동작합니다. 캐싱과 재시도는 react-query가 담당하므로, 클라이언트에는 얇은 fetch 래퍼만 있으면 충분합니다.
  • nuqs (URL/쿼리 파라미터): 화면 상태를 URL에 두면 뒤로가기, 새로고침, 링크 공유가 자연스럽게 동작합니다. 쿼리 파라미터를 타입과 함께 다뤄 수동 파싱 코드를 없앱니다.
  • sonner (토스트 알림): 알림 스택, 키보드 처리, 접근성 기본값을 제공해 별도 구현 부담을 줄입니다.
  • motion (애니메이션): 기존 라이브러리의 후속 패키지명으로 API가 이어지며, 앞으로의 릴리스 라인을 따릅니다.
  • date-fns / es-toolkit: 함수 단위로 임포트해 번들에 필요한 것만 포함됩니다. 타입 우선 설계라 별도 타입 패키지가 필요 없습니다.
  • argon2 (해시): 메모리 비용을 조절할 수 있는 해시로, 무차별 대입 공격에 더 강합니다.
  • nestjs-zod (검증): 프론트와 백엔드가 같은 zod 스키마를 공유해 검증 규칙이 한 곳에서 관리됩니다. 데코레이터 검증과의 이중 정의를 없앱니다.
  • nestjs-pino (로깅): 요청 컨텍스트가 붙은 구조적 JSON 로그로 관측성 도구와 바로 연동됩니다(09. 장애 대응).
  • ESLint flat + Prettier: React Compiler 규칙을 검사하는 플러그인이 ESLint 위에서만 제공되므로, 자동 메모이제이션의 안전망을 유지하려면 ESLint 계열을 유지합니다.
  • eslint-plugin-boundaries: app→domains→shared→infrastructure 의존 방향을 린트로 강제해 구조가 시간이 지나도 무너지지 않게 합니다(04. 아키텍처).
  • pnpm + catalog: 워크스페이스 전반의 버전을 한 곳에서 고정해 드리프트를 막습니다.
  • Prisma 기본값, 기존 Drizzle 유지: 새 백엔드는 Prisma를 기본으로 하되, 이미 Drizzle로 운영 중인 저장소는 옮기지 않습니다. 데이터 계층 이전은 위험 대비 효용이 낮습니다.

추천 항목 (실무 우선순위)

  • 시작 추천: 버전 정렬과 패키지명 교체처럼 위험이 낮은 항목부터 맞춥니다.
  • 안정 추천: HTTP·검증·토스트 알림 라이브러리를 표준으로 교체합니다.
  • 운영 추천: 의존 방향 린트와 catalog로 다시 어긋나지 않게 고정합니다.

추천 항목 고도화 체크

  • 즉시 적용 — 추천 항목 1개를 이번 주 내에 실제 작업 1건에 반영한다.
  • 1주 내 정리 — 적용 결과를 PR 본문이나 회고 노트에 간단히 기록한다.
  • 1개월 내 점검 — 재작업률/리뷰 충돌/배포 이슈 중 적어도 한 항목이 개선되었는지 확인한다.

추천 항목 실행 기록 템플릿

  • 담당자 : 항목 적용 주체(문서 오너/팀원)를 명시
  • 적용일 : 실제 반영된 날짜 및 작업 ID를 남김
  • 측정 지표 : 리뷰 충돌/재작업/버그 재발 중 1개 이상 수치로 기록
  • 보류 사유 : 적용을 못한 경우 이유를 1줄 기록하고 다음 액션을 지정

추천 항목 실행 우선순위 매핑

  • P1(7일 내) — 추천 항목 1개를 우선 적용하고 1회 사용자 관측 신호(에러율/실패율/지연)와 연결한다.
  • P2(30일 내) — 추천 항목 1개를 팀 내 표준/템플릿에 반영해 재사용성을 확보한다.
  • P3(90일 내) — 추천 항목 1개를 다른 관련 문서에 역링크로 연동해 중복 작업을 줄인다.
  • 완료 기준 — 각 항목별 산출물(예: PR 링크/체크리스트/회고 노트)을 1개 이상 남긴다.

추천 항목 실행 체크리스트

  • [ ] 1단계(7일) : 추천 항목 1개를 실제 작업으로 전환
  • [ ] 2단계(30일) : 전환 결과를 팀 산출물(ADR/PR/체크리스트)에 반영
  • [ ] 3단계(60일) : 정적 지표 1개 이상으로 효과 검증
  • [ ] 문제 대응 : 미달성 시 보류 사유와 다음 실행 액션을 문서화

추천 항목 실행 운영 규칙

  • 실행 게이트 : 위험, 비용, 기대 효과가 1회 이상 정량화되어야 적용한다.
  • 승인 체계 : 적용 전 사전 승인자(팀 리드/보안/운영)와 rollback 담당자를 확인한다.
  • 리스크 점수 : 1~5 등급으로 현재 위험도를 기록하고 정량 기준을 남긴다.
  • 리더 승인자 : 최종 승인 책임자(예: 팀 리드/PO/보안리더)를 명시한다.
  • 승인 역할 : 승인자, 실행자, 모니터링 주체 역할을 분리해 적는다.
  • 재개 조건 : 실패 신호가 기준치 이내로 돌아오면 다음 단계로 확장한다.
  • 정지 조건 : 회귀 지표 악화가 1개 이상이면 즉시 중단하고 보류 사유를 갱신한다.
  • 재평가 주기 : 최소 2주 단위로 상태를 리뷰하고 조정한다.

실무 적용 가이드

언제 이 문서를 펼칠까

  • 새 저장소를 만들거나 라이브러리를 새로 추가할 때
  • 같은 일을 하는 라이브러리가 저장소마다 달라 정리가 필요할 때
  • 의존성 버전이 저장소 간에 어긋나 빌드나 동작이 갈릴 때

적용 순서

  1. 대상 저장소의 현재 라이브러리를 카테고리별로 정리한다.
  2. 이 문서의 표준과 다른 항목을 골라낸다.
  3. 저위험 항목(버전 정렬, 패키지명 교체)부터 작은 PR로 바꾼다.
  4. 라이브러리 교체(HTTP, 토스트 알림, 검증)는 동작 테스트와 함께 PR을 만든다.
  5. typecheck·lint·test·build를 모두 통과시킨 뒤 머지한다.

함께 두는 파일

  • HTTP 공유 인스턴스: src/infrastructure/http/
  • env 스키마: src/shared/config/
  • 린트 경계 설정: eslint.config.mjs

흔한 실수

  • react-query를 쓰면서 HTTP 클라이언트에 재시도·캐싱을 또 얹어 동작이 중복된다.
  • 버전을 저장소마다 손으로 올려 다시 어긋난다(catalog로 묶어야 한다).
  • 검증 스키마를 프론트와 백엔드에 따로 정의해 규칙이 갈린다.
  • 큰 구조 변경을 한 PR에 몰아 리뷰와 롤백이 어려워진다.

PR 완료 기준

  • [ ] 변경한 카테고리가 이 문서의 표준과 일치한다
  • [ ] typecheck·lint·test·build가 모두 통과한다
  • [ ] 교체한 라이브러리의 동작을 테스트나 스모크로 확인했다
  • [ ] 버전은 catalog 또는 공통 기준에 맞춰 정렬했다