create-next-0to1
v0.1.14
Published
실무에서 반복되는 구조를 바로 가져다 쓸 수 있도록 만든 `Next.js App Router` 템플릿이다.
Readme
Next.js Frontend Template
실무에서 반복되는 구조를 바로 가져다 쓸 수 있도록 만든 Next.js App Router 템플릿이다.
Defaults
feature-first구조- 공통
request코어 + 환경별 wrapper 분리 TanStack Query중심 서버 상태 관리Zustand는 전역 UI 상태에만 사용React Hook Form + Zod예제는 CRUD feature 생성 시 추가- 날짜, 포맷팅, query string, 에러 처리 같은 공통 로직 분리
- 인증 redirect, 전역 모달, query 전역 에러 처리는 옵션 예제로 제공
Quick Start
npm install
cp .env.example .env.local
npm run dev필수 환경 변수:
API_BASE_URL=http://localhost:4000
NEXT_PUBLIC_API_BASE_URL=http://localhost:4000- 클라이언트는
NEXT_PUBLIC_API_BASE_URL을 사용한다. - 서버는
API_BASE_URL ?? NEXT_PUBLIC_API_BASE_URL을 사용한다. - 서버 인증 요청은 기본적으로
session,access_token,refresh_token쿠키만 upstream API로 전달한다.
Structure
src/
app/
features/
shared/
api/
auth/
routes/
config/
error/
lib/
query/
ui/
utils/app- App Router entry.
layout,page,error, provider 연결을 둔다.
- App Router entry.
features- 특정 도메인에서만 쓰는 API, hook, component, lib를 둔다.
shared- 두 개 이상 feature 또는 앱 전역에서 재사용하는 공통 코드만 둔다.
shared/api- 공통 네트워크 계층과 환경별 request wrapper를 둔다.
shared/auth- 인증 오류 redirect 같은 얇은 auth 반응을 둔다.
shared/errorAppError정규화와 서버/클라이언트 에러 처리 예시를 둔다.
shared/queryQueryClient, provider, hydration 같은 query 인프라를 둔다.
shared/routes- 전역에서 반복 참조하는 route 상수를 둔다.
shared/ui- 버튼, 인풋, 전역 모달 같은 범용 UI primitive를 둔다.
shared/lib- 라이브러리 초기화, 공통 설정, 프로젝트 정책이 들어간 진입점을 둔다.
shared/utils- 순수 함수 위주의 얕은 유틸을 둔다.
Request And Error Flow
요청 함수 선택 기준:
- 클라이언트 일반 요청:
requestClient - 클라이언트 인증 요청:
requestClientAuth - 서버 일반 요청:
requestServer - 서버 인증 요청:
requestServerAuth
기준:
request.ts는 공통 타입과 실행 함수 정의를 두고, 실제 사용은 환경별 wrapper를 통해 한다.- 서버 인증 요청은 allowlist에 있는 인증 쿠키만 전달한다.
- feature API 함수는
features/<name>/api아래에 둔다.
예시:
import { requestClient } from '@/shared/api/request.client';
export function getProducts(search?: string) {
return requestClient<Product[]>({
method: 'GET',
url: '/products',
params: { search },
});
}에러 처리 기준:
request는 정규화된AppError를 throw한다.- 서버 컴포넌트에서는
try/catch후handleServerAppError()를 사용한다. - 서버에서
401은 기본적으로 로그인 페이지로 redirect한다. 404는notFound()로 처리할 수 있다.app/error.tsx는 세부 코드 분기 없이 generic fallback UI만 렌더한다.
옵션 예제:
src/shared/error/handle-app-error.client.tssrc/shared/auth/auth-error-listener.tsxsrc/shared/ui/global-modal.tsx- 기본 템플릿에서는 연결하지 않으며, 필요하면
src/app/providers.tsx에서 수동으로 연결한다.
서버 컴포넌트 예시:
import { handleServerAppError } from '@/shared/error/handle-app-error.server';
import { requestServerAuth } from '@/shared/api/request.server';
export default async function Page() {
try {
const me = await requestServerAuth<{ name: string }>({
method: 'GET',
url: '/me',
});
return <div>{me.name}</div>;
} catch (error) {
handleServerAppError(error);
}
}Scripts
npm run dev
npm run lint
npm run lint:fix
npm run format
npm run format:check
npm run create:feature -- products
npm run create:feature:crud -- productsCreate Feature
npm run create:feature -- products생성 대상:
src/features/<name>/api/src/features/<name>/components/src/features/<name>/hooks/src/features/<name>/lib/src/app/<name>/page.tsx
주의:
- 최소 폴더 구조와 route만 만든다.
- CRUD 예제가 필요하면 아래 명령을 사용한다.
npm run create:feature:crud -- productsCRUD 예시 생성 대상:
src/features/<name>/apisrc/features/<name>/componentssrc/features/<name>/hookssrc/features/<name>/libsrc/app/<name>/page.tsxsrc/app/<name>/new/page.tsx
주의:
- 생성된 API 함수는 외부 백엔드 연동을 전제로 한다.
- same-origin
app/api/.../route.tsmock은 생성하지 않는다. routePaths는 자동 병합하지 않는다.- 필요하면 생성 후
src/shared/routes/route-paths.ts에 직접 추가한다.
관련 스크립트:
scripts/create-feature.mjsscripts/create-feature-crud.mjsscripts/create-app.mjs
Coding Defaults
- 앱 내부 타입 선언은 기본적으로
.ts/.tsx에서type을 우선 사용한다. interface는 declaration merging이나 외부 타입 확장처럼 확장 계약이 필요할 때만 사용한다..d.ts는 전역 타입 보강, 환경 변수 타입 확장, 외부 라이브러리 선언 보완 같은 ambient declaration 용도로만 제한한다.- query key는 feature별 파일에서 관리하고,
GET은 query,POST/PUT/PATCH/DELETE는 mutation으로 분리한다. - URL로 표현 가능한 상태는 URL에 두고, 전역 store는 여러 컴포넌트가 함께 알아야 하는 UI 상태에만 사용한다.
- 날짜와 숫자 포맷팅은 공통 함수로 관리한다.
- 클릭 가능한 요소는
button, 이동은a/Link를 사용하고, input은label과 연결한다.
Create App
패키지로 사용할 때는 아래처럼 새 프로젝트를 만들 수 있다.
npm create next-0to1@latest my-app또는:
pnpm create next-0to1 my-appyarn create next-0to1 my-appbun create next-0to1 my-appcommitlint까지 같이 넣고 싶으면 아래처럼 생성한다.
npm create next-0to1@latest my-app -- --with-commitlint이 옵션을 켜면 commit-msg hook과 commitlint 설정이 추가되고, feat: 내용 같은 Conventional Commits 형식을 검사한다.
스타일 없이 시작하고 싶으면 아래처럼 생성한다.
npm create next-0to1@latest my-app -- --no-style--no-style을 켜면 Tailwind 관련 의존성과 postcss.config.mjs, 전역 CSS import를 제외하고 기본 화면과 feature 스캐폴드도 스타일 없이 생성한다.
이 템플릿은 TypeScript + App Router + ESLint 전제를 가진다.
Husky는 기본 설치하며, pre-commit에서 lint만 실행한다.
React Compiler는 템플릿이 강제로 켜지지 않고, create-next-app 인터랙션 또는 --react-compiler 옵션 선택을 그대로 따른다.
