Next.js 16κ³Ό React 19λ₯Ό κΈ°λ°μΌλ‘ ν λͺ¨λν κΈ°μ λΈλ‘κ·Έμ λλ€. λ§ν¬λ€μ΄ νμΌ κΈ°λ°μ μ μ λΈλ‘κ·Έλ‘, μΉ΄ν κ³ λ¦¬λ³ ν¬μ€νΈ κ΄λ¦¬, κ²μ κΈ°λ₯, λ€ν¬λͺ¨λ, λκΈ μμ€ν λ±μ μ§μν©λλ€.
- μ£Όμ κΈ°λ₯
- κΈ°μ μ€ν
- νλ‘μ νΈ κ΅¬μ‘°
- μ€ν λ°©λ²
- E2E ν μ€νΈ
- μ±λ₯ μ΅μ ν
- κ°μ ν μ
flowchart LR
Home[λ©μΈνλ©΄]
SideBar(μ¬μ΄λλ°)
Header(ν€λ)
Footer(νΈν°)
List[κΈ λͺ©λ‘]
Detail[κΈ μμΈ νλ©΄]
About[μκ° νμ΄μ§]
Contact[λ¬Έμ νμ΄μ§]
Home --- Header
Home --- Footer
Home --- SideBar
Home --- List
List -.-> Detail
SideBar -.-> Detail
Header -.-> About
Header -.-> Contact
- β
λ§ν¬λ€μ΄ κΈ°λ° λΈλ‘κ·Έ:
public/markdownλλ ν 리μ λ§ν¬λ€μ΄ νμΌμ μλμΌλ‘ μ½μ΄ ν¬μ€νΈλ‘ λ³ν - β μΉ΄ν κ³ λ¦¬λ³ λΆλ₯: Archive, Career, Learning, Personal, Projects λ± μΉ΄ν κ³ λ¦¬λ³ ν¬μ€νΈ κ΄λ¦¬
- β κ²μ κΈ°λ₯: μ λͺ©, μ€λͺ , νκ·Έ κΈ°λ° ν¬μ€νΈ κ²μ
- β λ€ν¬λͺ¨λ: μ¬μ©μ μ νΈλμ λ°λ₯Έ λΌμ΄νΈ/λ€ν¬ λͺ¨λ μ ν
- β λ°μν λμμΈ: λͺ¨λ°μΌ, νλΈλ¦Ώ, λ°μ€ν¬ν± λͺ¨λ κΈ°κΈ° μ§μ
- β SEO μ΅μ ν: λ©ν νκ·Έ, ꡬ쑰νλ λ°μ΄ν°, sitemap, robots.txt, OG μ΄λ―Έμ§ μλ μμ±
- β
RSS Feed:
/feed.xmlμλν¬μΈνΈλ‘ RSS νΌλ μ 곡 - β λκΈ μμ€ν : Utterancesλ₯Ό νμ©ν GitHub κΈ°λ° λκΈ μμ€ν
- β 곡μ κΈ°λ₯: μΉ΄μΉ΄μ€ν‘, νΈμν°, λ§ν¬ λ³΅μ¬ λ± μμ 곡μ κΈ°λ₯
- β μΏ ν€ κ΄λ¦¬: μ¬μ©μ λμ κΈ°λ° μΏ ν€ κ΄λ¦¬ λ° Google AdSense ν΅ν©
- β μ±λ₯ λͺ¨λν°λ§: Vercel Analytics λ° Speed Insights ν΅ν©
- β μ κ·Όμ± κ°μ : ARIA μμ±, μμ λλΉ, λ§ν¬ μ κ·Όμ± μ΅μ ν
- β PWA μ§μ: Service Workerλ₯Ό ν΅ν μ€νλΌμΈ μ§μ
- β
ν μΌ κ΄λ¦¬ μμ€ν
: toris-devμ ν μΌμ 곡κ°μ μΌλ‘ κ΄λ¦¬νκ³ κ³΅μ νλ κΈ°λ₯
- 리μ€νΈ, μΉΈλ° λ³΄λ, μΊλ¦°λ λ·° μ§μ
- μ΄λ리μ μ§κ° κΈ°λ° μΈκ° μμ€ν (μ½κΈ°λ 곡κ°, μ°κΈ°/μμ /μμ λ μΈκ°λ μ¬μ©μλ§)
- MongoDB Atlasλ₯Ό ν΅ν μꡬ λ°μ΄ν° μ μ₯
- Next.js 16.0.7 - React νλ μμν¬ (App Router)
- React 19.2.1 - UI λΌμ΄λΈλ¬λ¦¬
- TypeScript 5.3 - νμ μμ μ±
- Tailwind CSS - μ νΈλ¦¬ν° κΈ°λ° CSS νλ μμν¬
- Framer Motion - μ λλ©μ΄μ λΌμ΄λΈλ¬λ¦¬
- next-themes - λ€ν¬λͺ¨λ μ§μ
- tailwind-merge - Tailwind ν΄λμ€ λ³ν©
- class-variance-authority - μ»΄ν¬λνΈ λ³ν κ΄λ¦¬
- @tanstack/react-query - μλ² μν κ΄λ¦¬
- React Hooks - ν΄λΌμ΄μΈνΈ μν κ΄λ¦¬
- MongoDB Atlas - ν΄λΌμ°λ λ°μ΄ν°λ² μ΄μ€ (ν μΌ κ΄λ¦¬ λ°μ΄ν° μ μ₯)
- Mongoose - MongoDB κ°μ²΄ λͺ¨λΈλ§ λΌμ΄λΈλ¬λ¦¬
- @uiw/react-md-editor - λ§ν¬λ€μ΄ μλν°
- @uiw/react-markdown-preview - λ§ν¬λ€μ΄ ν리뷰
- react-markdown - λ§ν¬λ€μ΄ λ λλ§
- remark-gfm - GitHub Flavored Markdown μ§μ
- rehype-highlight - μ½λ νμ΄λΌμ΄ν
- Cypress - E2E ν μ€νΈ
- Vercel Analytics - μΉ λΆμ λꡬ
- Vercel Speed Insights - μ±λ₯ λͺ¨λν°λ§
- Google Tag Manager - λΆμ λꡬ
- Google AdSense - κ΄κ³ μμ΅ν (μΏ ν€ λμ κΈ°λ°)
- Structured Data - SEO ꡬ쑰νλ λ°μ΄ν°
- ethers.js - μ΄λ리μ μ§κ° μ°κ²° λ° μλͺ κΈ°λ₯
- dayjs - λ μ§ μ²λ¦¬
- octokit - GitHub API ν΄λΌμ΄μΈνΈ (μ νμ )
- react-hot-toast - ν μ€νΈ μλ¦Ό
- react-intersection-observer - μ€ν¬λ‘€ μ λλ©μ΄μ
- shiki - μ½λ νμ΄λΌμ΄ν
- mermaid - λ€μ΄μ΄κ·Έλ¨ λ λλ§
Toris_Blog/
βββ public/
β βββ markdown/ # λ§ν¬λ€μ΄ ν¬μ€νΈ νμΌλ€
β βββ Archive/ # μμΉ΄μ΄λΈ μΉ΄ν
κ³ λ¦¬
β βββ Career/ # μ»€λ¦¬μ΄ κ΄λ ¨ ν¬μ€νΈ
β βββ Design/ # λμμΈ κ΄λ ¨ ν¬μ€νΈ
β βββ Learning/ # νμ΅ μλ£
β βββ Personal/ # κ°μΈ κ΄λ ¨ ν¬μ€νΈ
β βββ Projects/ # νλ‘μ νΈ κ΄λ ¨ ν¬μ€νΈ
βββ src/
β βββ app/ # Next.js App Router νμ΄μ§
β β βββ about/ # μκ° νμ΄μ§
β β βββ contact/ # λ¬Έμ νμ΄μ§
β β βββ posts/ # λΈλ‘κ·Έ ν¬μ€νΈ νμ΄μ§
β β β βββ [id]/ # ν¬μ€νΈ μμΈ νμ΄μ§
β β β βββ _components/ # ν¬μ€νΈ κ΄λ ¨ μ»΄ν¬λνΈ
β β β βββ page.tsx # ν¬μ€νΈ λͺ©λ‘ νμ΄μ§
β β βββ categories/ # μΉ΄ν
κ³ λ¦¬λ³ ν¬μ€νΈ νμ΄μ§
β β βββ tags/ # νκ·Έλ³ ν¬μ€νΈ νμ΄μ§
β β βββ todos/ # ν μΌ κ΄λ¦¬ νμ΄μ§
β β βββ api/ # API λΌμ°νΈ
β β β βββ todos/ # ν μΌ κ΄λ¦¬ API
β β βββ feed.xml/ # RSS Feed
β β βββ layout.tsx # λ£¨νΈ λ μ΄μμ
β β βββ page.tsx # ν νμ΄μ§
β βββ components/ # React μ»΄ν¬λνΈ
β β βββ ads/ # κ΄κ³ μ»΄ν¬λνΈ (AdSense)
β β βββ blog/ # λΈλ‘κ·Έ κ΄λ ¨ μ»΄ν¬λνΈ
β β βββ common/ # κ³΅ν΅ μ»΄ν¬λνΈ (Header, Footer, CookieConsent λ±)
β β βββ forms/ # νΌ μ»΄ν¬λνΈ
β β βββ seo/ # SEO κ΄λ ¨ μ»΄ν¬λνΈ
β β βββ todos/ # ν μΌ κ΄λ¦¬ μ»΄ν¬λνΈ
β β βββ ui/ # UI μ»΄ν¬λνΈ
β βββ contexts/ # React Context (TodoContext, WalletContext λ±)
β βββ hooks/ # 컀μ€ν
ν
β βββ lib/ # λΌμ΄λΈλ¬λ¦¬ μ€μ (mongodb μ°κ²° λ±)
β βββ models/ # λ°μ΄ν°λ² μ΄μ€ λͺ¨λΈ (Mongoose μ€ν€λ§)
β βββ styles/ # μ μ μ€νμΌ
β βββ types/ # TypeScript νμ
μ μ
β βββ utils/ # μ νΈλ¦¬ν° ν¨μ
βββ .cursor/ # Cursor IDE μ€μ
β βββ rules/ # λ§ν¬λ€μ΄ μμ± μ€νμΌ κ°μ΄λ
βββ cypress/ # E2E ν
μ€νΈ
β βββ e2e/ # ν
μ€νΈ νμΌλ€
βββ README.md
νλ‘μ νΈ λ£¨νΈμ .env.local νμΌμ μμ±νκ³ λ€μ λ³μλ€μ μ€μ ν©λλ€:
# μ νμ : GitHub API ν ν° (λ§ν¬λ€μ΄ νμΌμ GitHubμμ κ°μ Έμ¬ κ²½μ°)
GITHUB_TOKEN=your_github_token
# μ νμ : μ¬μ΄νΈ URL
NEXT_PUBLIC_SITE_URL=https://your-domain.com
# μ νμ : Google AdSense Publisher ID
NEXT_PUBLIC_ADSENSE_PUBLISHER_ID=ca-pub-xxxxxxxxxxxxx
# μ νμ : Google Tag Manager ID
NEXT_PUBLIC_GTM_ID=GTM-XXXXXXX
# ν μΌ κ΄λ¦¬ μΈκ°λ μ§κ° μ£Όμ (μΌνλ‘ κ΅¬λΆ)
# μ: NEXT_PUBLIC_AUTHORIZED_ADDRESSES=0x1234...,0x5678...
NEXT_PUBLIC_AUTHORIZED_ADDRESSES=your_wallet_address
# νμ: MongoDB Atlas μ°κ²° URI
MONGODB_URI=mongodb+srv://username:password@cluster.mongodb.net/dbnamepnpm installpnpm devκ°λ° μλ²κ° http://localhost:3000μμ μ€νλ©λλ€.
pnpm build
pnpm startCypressλ₯Ό μ¬μ©νμ¬ E2E ν μ€νΈλ₯Ό μ€νν μ μμ΅λλ€.
pnpm cypress:openpnpm cypress:run# λ€λΉκ²μ΄μ
ν
μ€νΈ
pnpm cypress:run:navigation
# λΈλ‘κ·Έ ν
μ€νΈ
pnpm cypress:run:blog
# λ°μν ν
μ€νΈ
pnpm cypress:run:responsive
# κ²μ ν
μ€νΈ
pnpm cypress:run:searchabout.cy.ts- μκ° νμ΄μ§ ν μ€νΈblog.cy.ts- λΈλ‘κ·Έ ν¬μ€νΈ ν μ€νΈcontact.cy.ts- λ¬Έμ νΌ ν μ€νΈhome.cy.ts- ν νμ΄μ§ ν μ€νΈnavigation.cy.ts- λ€λΉκ²μ΄μ ν μ€νΈresponsive.cy.ts- λ°μν λμμΈ ν μ€νΈsearch.cy.ts- κ²μ κΈ°λ₯ ν μ€νΈ
- ISR (Incremental Static Regeneration): ν¬μ€νΈ λ°μ΄ν°λ₯Ό 6μκ°λ§λ€ μ¬μμ±
- Server Components: μλ² μ»΄ν¬λνΈλ₯Ό νμ©ν μ±λ₯ μ΅μ ν
- Image Optimization: Next.js Image μ»΄ν¬λνΈ μ¬μ©
- Code Splitting: μλ μ½λ λΆν
- β LCP (Largest Contentful Paint) μ΅μ ν
- β CLS (Cumulative Layout Shift) μ΅μν
- β FID (First Input Delay) κ°μ
- β
μ κ·Όμ± (Accessibility) κ°μ
- ARIA μμ± μ΅μ ν
- μμ λλΉ λΉμ¨ κ°μ
- λ§ν¬ μ κ·Όμ± ν₯μ
μΉ μ ν리μΌμ΄μ μ μ λ§λ€κΈ° μν΄ λ€μμ μ κ²½μ¨μΌ ν©λλ€:
- LCP: μ΄κΈ° λ‘λ© μ±λ₯ μ΅μ ν
- CLS: λ μ΄μμ μννΈ λ°©μ§
- FID: μΈν°λμ μλ΅μ± κ°μ
- Next.js λ λλ§ μ λ΅: SSR, SSG, ISRμ ν¨μ¨μ μΌλ‘ μ¬μ©
- ν립 ν¨κ³Ό (μ: μ λͺ©, μΉ΄ν κ³ λ¦¬, νκ·Έ / λ€: λ³Έλ¬Έ)
- λΉνμ λκΈ κΈ°λ₯ ꡬν (CRUD)
- μμ± μ ID, PWD μ λ ₯
- μμ , μμ μ μ λ ₯νλ ID, PWD νμΈ
- λ°©λͺ
λ‘ κΈ°λ₯ ꡬν (CR)
- μμ± μ λλ€μλ§ μμ±
- μμ , μμ λΆκ°
- μ€μκ° μ±ν ꡬν
- λ€κ΅μ΄ μ§μ (i18n)
- μ μ ν μΊμ± μμ
- μ κ·Όμ± κ°μ (ARIA μμ±, μμ λλΉ, λ§ν¬ μ κ·Όμ±)
- SEO μ΅μ ν (λ©ν νκ·Έ, ꡬ쑰νλ λ°μ΄ν°, OG μ΄λ―Έμ§ μλ μμ±)
- E2E ν μ€νΈ κ°ν
- λκΈ μμ€ν (Utterances) ν΅ν©
- μμ 곡μ κΈ°λ₯ (μΉ΄μΉ΄μ€ν‘, νΈμν°, λ§ν¬ 볡μ¬)
- μΏ ν€ κ΄λ¦¬ λ° Google AdSense ν΅ν©
- Vercel Analytics λ° Speed Insights ν΅ν©
- PWA μ§μ (Service Worker)
- λ§ν¬λ€μ΄ μμ± μ€νμΌ κ°μ΄λ ν΅μΌ (.cursor/rules)
- ν μΌ κ΄λ¦¬ μμ€ν
ꡬν
- 리μ€νΈ, μΉΈλ° λ³΄λ, μΊλ¦°λ λ·° μ§μ
- μ΄λ리μ μ§κ° κΈ°λ° μΈκ° μμ€ν
- MongoDB Atlas μꡬ λ°μ΄ν° μ μ₯
- ν μΌ κ΄λ¦¬ μμ€ν
: toris-devμ ν μΌμ 곡κ°μ μΌλ‘ κ΄λ¦¬νκ³ κ³΅μ νλ κΈ°λ₯ μΆκ°
- 리μ€νΈ, μΉΈλ° λ³΄λ, μΊλ¦°λ λ·° μ§μ
- μ΄λ리μ μ§κ° κΈ°λ° μΈκ° μμ€ν (μ½κΈ°λ 곡κ°, μ°κΈ°/μμ /μμ λ μΈκ°λ μ¬μ©μλ§)
- MongoDB Atlasλ₯Ό ν΅ν μꡬ λ°μ΄ν° μ μ₯
- React Context APIλ₯Ό νμ©ν μ μ μν κ΄λ¦¬
- Framer Motionμ νμ©ν λΆλλ¬μ΄ μ λλ©μ΄μ
- React Portalμ νμ©ν λͺ¨λ¬ μ΅μ ν
- Next.js 16 μ κ·Έλ μ΄λ: μ΅μ λ²μ μΌλ‘ μ κ·Έλ μ΄λ
- λκΈ μμ€ν : Utterancesλ₯Ό νμ©ν GitHub κΈ°λ° λκΈ μμ€ν ν΅ν©
- μμ 곡μ : μΉ΄μΉ΄μ€ν‘, νΈμν°, λ§ν¬ λ³΅μ¬ κΈ°λ₯ μΆκ°
- μΏ ν€ κ΄λ¦¬: μ¬μ©μ λμ κΈ°λ° μΏ ν€ κ΄λ¦¬ μμ€ν ꡬν
- Google AdSense: μΏ ν€ λμ κΈ°λ° κ΄κ³ ν΅ν©
- μ±λ₯ λͺ¨λν°λ§: Vercel Analytics λ° Speed Insights ν΅ν©
- PWA μ§μ: Service Workerλ₯Ό ν΅ν μ€νλΌμΈ μ§μ
- λ§ν¬λ€μ΄ μ€νμΌ ν΅μΌ:
.cursor/rules/toris-markdown-style.mdκ°μ΄λ μμ± λ° λͺ¨λ λ§ν¬λ€μ΄ νμΌ μ€νμΌ ν΅μΌ - λ©΄μ μ§λ¬Έ μ 리: JavaScriptμ μκ³ λ¦¬μ¦ κΈ°μ΄ κ°λ μ 리 ν¬μ€ν μΆκ°
- μ κ·Όμ± κ°μ : Lighthouse κ²½κ³ ν΄κ²°
- κΈμ§λ ARIA μμ± μμ
- μμ λλΉ λΉμ¨ κ°μ
- λ§ν¬ μ κ·Όμ± ν₯μ
- νλ‘μ νΈ κ΅¬μ‘° κ°μ : λ§ν¬λ€μ΄ κΈ°λ° λΈλ‘κ·Έλ‘ μ ν
- E2E ν μ€νΈ κ°ν: Cypress ν μ€νΈ μ½λ μ λ°μ΄νΈ
- κΈ°λ₯ μ κ±° λ° κ΅¬μ‘° κ°μ :
- κΈ°μ‘΄ ν¬νΈν΄λ¦¬μ€, κ΄λ¦¬μ, λ°©λͺ λ‘, μΈμ¦ κ΄λ ¨ κΈ°λ₯ μ κ±°
- λ§ν¬λ€μ΄ μ½ν μΈ κ΅¬μ‘° μ¬μ λΉ
public/markdownλλ ν 리 μλ μΉ΄ν κ³ λ¦¬λ³ λλ ν 리 λμ
- E2E ν
μ€νΈ κ°ν:
- Cypressλ₯Ό μ¬μ©ν μ£Όμ νμ΄μ§ λ° κΈ°λ₯ ν μ€νΈ μ½λ μ λ°μ΄νΈ
μ΄ νλ‘μ νΈλ κ°μΈ νλ‘μ νΈμ λλ€.
ν λ¦¬μ€ (Toris)
- GitHub: @toris-dev
- λΈλ‘κ·Έ: Toris Blog
νλ‘μ νΈμ λͺ¨λ λ§ν¬λ€μ΄ νμΌμ .cursor/rules/toris-markdown-style.md κ°μ΄λλ₯Ό λ°λ¦
λλ€.
- 1λ μ°¨ κ°λ°μ κ΄μ μ μ§
- κ°μΈμ κ²½νκ³Ό κ°μ νν ν¬ν¨
- μ΄λ³΄μλ μ΄ν΄ν μ μλλ‘ μ€λͺ
- μ€λ¬΄μμ λ°λ‘ νμ© κ°λ₯ν λ΄μ©
- μμ§νκ³ μΉκ·Όν ν€ μ¬μ©
μΉ΄ν κ³ λ¦¬λ³ μμ± κ°μ΄λ:
- Projects: νλ‘μ νΈ λ¦¬λ·° νμ (μ²μ μ νμ λ β μ΄λ €μ λ μ β ν΄κ²° λ°©λ² β λ°°μ΄ μ )
- Learning: κ°λ μ€λͺ μ€μ¬, μ½λ μμ μ μ€λ¬΄ ν
- Career: μ€λ¬΄ μ€μ¬, μκ³ λ¦¬μ¦/μ½λ©ν μ€νΈ κ΄λ ¨