๐งฉ Git ์ด๊ธฐ ์ธํ
# README ์์ฑ
echo "# ์ ๋ชฉ" >> README.md
# Git ์ด๊ธฐํ
git init
# ํ์ผ Git ๋ฑ๋ก
git add README.md
# ์ฒซ ์ปค๋ฐ
git commit -m "first commit"
# ๊ธฐ๋ณธ ๋ธ๋์น๋ฅผ main์ผ๋ก ๋ณ๊ฒฝ
git branch -M main
# ์๊ฒฉ ์ ์ฅ์ ์ฐ๊ฒฐ
git remote add origin <๋ ํฌ์งํ ๋ฆฌ ์ฃผ์>
# ์๊ฒฉ ์ ์ฅ์์ ์ฒซ push
git push -u origin mainโ๏ธ Next.js ํ๋ก์ ํธ ์์ฑ
npx create-next-app@latest .
# ์คํ ์ค ์ ํ ์ถ์ฒ:
# TypeScript: Yes โ ํ์
์์ ์ฑ ํ๋ณด
# ESLint: Yes โ ์ฝ๋ ์ปจ๋ฒค์
์ ์ง
# Tailwind CSS: ์ ํ/Yes โ ๋น ๋ฅธ UI ์คํ์ผ๋ง
# src/ directory: Yes โ ๊ตฌ์กฐ ๊น๋
# App Router: ์ ํ/Yes โ ์ต์ ๊ตฌ์กฐ ์ฌ์ฉ
# Import alias: Yes โ @/*
# Turbopack: No โ ์์ ์ฑ ์ฐ์ ๐ ESLint
# 1. ESLint ์ค์น
npm install -D eslint
# JS/TS ์ฝ๋ ๋ฌธ๋ฒ๊ณผ ์คํ์ผ ๊ฒ์ฌ
# 2. TypeScript ESLint Parser ์ค์น
npm install -D @typescript-eslint/parser
# ESLint๊ฐ TypeScript ์ฝ๋๋ฅผ ์ดํดํ๋๋ก ํจ
# 3. TypeScript ESLint Plugin ์ค์น
npm install -D @typescript-eslint/eslint-plugin
# TypeScript ์ ์ฉ ๊ท์น ์ ๊ณต# ESLint ์ค์ ํ์ผ ์์ฑ
npx eslint --init
# ์๋์ผ๋ก .eslintrc.js ๋๋ eslint.config.mjs ์์ฑ// eslint.config.mjs
import tsPlugin from '@typescript-eslint/eslint-plugin';
import parser from '@typescript-eslint/parser';
import pluginImport from 'eslint-plugin-import';
import perfectionist from 'eslint-plugin-perfectionist';
import simpleImportSort from 'eslint-plugin-simple-import-sort';
export default [
{
files: ['**/*.{js,jsx,ts,tsx}'],
ignores: ['node_modules', '.next', 'dist'],
languageOptions: {
parser,
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
ecmaFeatures: { jsx: true },
project: './tsconfig.json',
},
},
plugins: {
import: pluginImport,
'simple-import-sort': simpleImportSort,
'@typescript-eslint': tsPlugin,
perfectionist,
},
rules: {
'simple-import-sort/imports': 'error',
'simple-import-sort/exports': 'error',
'perfectionist/sort-jsx-props': [
'error',
{
type: 'natural',
order: 'asc',
groups: ['multiline', 'unknown', 'shorthand'],
},
],
'perfectionist/sort-objects': [
'error',
{ type: 'natural', order: 'asc' },
],
'perfectionist/sort-array-includes': 'off',
'no-unused-vars': 'warn',
'@typescript-eslint/no-unused-vars': [
'warn',
{ argsIgnorePattern: '^_' },
],
},
},
];โจ Prettier
# Prettier ์ค์น
npm install -D prettier
# ESLint + Prettier ์ถฉ๋ ๋ฐฉ์ง ์ค์
npm install -D eslint-config-prettier
# Tailwind Prettier ํ๋ฌ๊ทธ์ธ ์ค์น
npm install -D prettier-plugin-tailwindcss// .prettierrc
{
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"tabWidth": 2,
"useTabs": false,
"printWidth": 80,
"arrowParens": "always",
"endOfLine": "lf",
"plugins": ["prettier-plugin-tailwindcss"]
}๐ช ESLint + Prettier
# ์ค์ ํตํฉ : ํ ๋ฒ์ ์ค์น ๊ฐ๋ฅ
npm install -D eslint prettier eslint-config-prettier @typescript-eslint/parser @typescript-eslint/eslint-plugin prettier-plugin-tailwindcss eslint-plugin-simple-import-sort eslint-plugin-perfectionist
๐ถ Husky
# Husky ์ค์น
npm install -D husky
# Husky ์ด๊ธฐํ
npx husky install// package.json ์คํฌ๋ฆฝํธ ์ถ๊ฐ, Git Hook ๊ด๋ฆฌ ๋๊ตฌ
"scripts": {
"prepare": "husky install"
}๐ lint-staged
# lint-staged ์ค์น
npm install -D lint-staged# pre-commit ํ
์์ฑ
mkdir -p .husky
echo "npx lint-staged" > .husky/pre-commit
chmod +x .husky/pre-commit// package.json์ lint-staged ์ค์
// ์ปค๋ฐ ๋์ ํ์ผ๋ง ์๋์ผ๋ก ESLint + Prettier ์ ์ฉ
// Husky pre-commit ํ
๊ณผ ํจ๊ป ์ฌ์ฉ
"lint-staged": {
"*.{js,jsx,ts,tsx}": ["eslint --fix", "prettier --write"],
"*.{json,css,md}": ["prettier --write"]
}โ๏ธ VSCode settings.json
// ์ ์ฅํ ๋ ESLint + Prettier ์๋ ์คํ
// import ์ ๋ ฌ๊ณผ ์ฝ๋ ํฌ๋งท ์ ์ฉ
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit",
"source.organizeImports": "explicit"
},
"eslint.validate": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact"
],
"eslint.useFlatConfig": true
}๐น Tailwind CSS (v4)
# Tailwind CSS ์ค์น
npm install tailwindcss
# globals.css ํ์ผ ์๋จ์ Tailwind import ์ถ๊ฐ
@import "tailwindcss";# layout.tsx ๋๋ ์ฑ entry ํ์ผ์ globals.css import
import './globals.css';๐ท shadcn/ui
# shadcn/ui ์ค์น
npx shadcn@latest init๐ฉน clsx + cva
# className ์กฐ๊ฑด๋ถ ํฉ์น๊ธฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
npm install clsx
# Tailwind + Variants ์ฝ๊ฒ ๊ด๋ฆฌ (cva)
npm install class-variance-authority๐ SVGR
# SVGR ์ค์น
npm install @svgr/webpack --save-dev// next.config.ts ์ค์
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
webpack(config) {
config.module.rules.push({
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: ['@svgr/webpack'],
});
return config;
},
};
export default nextConfig;// svg.d.ts ์์ฑ
declare module '*.svg' {
import React from 'react';
export const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
const src: string;
export default src;
}๐งธ Zustand
# Zustand ์ค์น
npm install zustand๐น React Query + QueryProvider
# React Query ์ค์น
npm install @tanstack/react-query
npm install @tanstack/react-query-devtools// src/components/QueryProvider.tsx
'use client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import { ReactNode, useState } from 'react';
export default function QueryProvider({ children }: { children: ReactNode }) {
const [queryClient] = useState(() => new QueryClient());
return (
<QueryClientProvider client={queryClient}>
{children}
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
);
}๐ฉ Zod
# Zod ์ค์น
npm install zod๐ง React Hook Form + @hookform/resolvers
# React Hook Form ์ค์น
npm install react-hook-form
# Resolvers ์ค์น (Zod ๋ฑ ์ฐ๋์ฉ)
npm install @hookform/resolvers
๐งญ Axios
# Axios ์ค์น
npm install axios
๐๏ธ Framer Motion
# Framer Motion ์ค์น
npm install framer-motion
๐คน๐ปโโ๏ธ Lucide React
# Lucide React ์ค์น
npm install lucide-react