Skip to content

Latest commit

 

History

391 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Devy Archive preview

Devy Archive

React, TypeScript, Vite로 만든 개인 기술 블로그입니다.
문제 해결 과정, 백엔드 아키텍처, 운영 경험, 프론트엔드 개선 기록을 Markdown 기반으로 발행합니다.


Deploy React TypeScript Vite Tailwind CSS

Live Site  ·  RSS  ·  Sitemap


소개

Devy Archive는 단순한 SPA가 아니라, GitHub Pages에서 안정적으로 동작하도록 hydrated SSG를 얹은 개인 기술 아카이브입니다. 글은 content/posts/*.md로 관리하고, 빌드 시 RSS, sitemap, route별 HTML, SEO metadata를 함께 생성합니다.

주요 기능

Markdown publishing
frontmatter, GFM, raw HTML, 태그, 시리즈, 예약 발행, draft 지원
Hydrated SSG
SSR HTML을 빌드 산출물에 주입하고 클라이언트에서 안전하게 hydration
Technical writing UX
Shiki dual-theme code highlighting, Mermaid diagram, TOC, 읽기 시간
Discovery
전체 검색, 고급 검색, 태그별 목록, 시리즈별 목록, Cmd+K command menu
Personalization
light/dark/system theme, color theme, 한국어/English language toggle
Operations
Google Analytics page views, Giscus comments, RSS, sitemap, OG metadata

아키텍처

flowchart LR
  Posts["content/posts/*.md"] --> Glob["import.meta.glob"]
  Glob --> Parser["src/lib/posts.ts"]
  Parser --> Pages["React Router pages"]

  Pages --> Client["CSR hydration"]
  Pages --> Server["src/entry-server.tsx"]
  Server --> Prerender["scripts/prerender.mjs"]
  Prerender --> Dist["dist HTML"]

  Parser --> Feed["RSS / Sitemap"]
  Feed --> Dist
Loading

빌드 흐름은 tsc -> Vite client build -> Vite SSR build -> hydrated prerender 순서로 실행됩니다. 글 상세, 프로젝트 상세, 404 fallback까지 정적 HTML을 생성해 GitHub Pages의 SPA fallback에서도 hydration mismatch를 줄입니다.

라우트

Path Page Description
/ Home 최신글, 인기글, 블로그 통계
/posts Posts 전체 글 목록, 검색, 정렬, 태그/연도 필터
/posts/:slug Post Markdown 글 상세, TOC, 댓글
/tags Tags 태그별 주제 탐색, 관련 태그, 최근 글
/series Series 시리즈별 글 탐색
/analytics Analytics 방문자 및 조회수 대시보드
/about About 소개, 경력, 프로젝트 요약
/about/projects/:slug Project Detail 프로젝트 상세

빠른 시작

pnpm install --frozen-lockfile
pnpm dev

packageManager에 pnpm 11.17.0을 고정합니다. 패키지 파일은 머신 전역 pnpm store에서 중복 없이 재사용하며, 프로젝트의 node_modules에는 실행에 필요한 링크만 생성되고 Git에서는 제외됩니다.

개발 서버는 기본적으로 http://localhost:5173에서 실행됩니다.

명령어

Command Description
pnpm dev Vite 개발 서버 실행
pnpm build 타입 체크, client/SSR 빌드, hydrated SSG 생성
pnpm preview dist 결과 미리보기
pnpm lint ESLint 검사
pnpm type-check TypeScript 타입 검사

글 작성

content/posts/에 Markdown 파일을 추가하면 빌드 시 자동으로 로드됩니다.

---
title: "제목"
date: "2025-01-01"
updated: "2025-02-01"      # 최종 수정일
description: "설명"
tags: ["react", "typescript"]
series: "시리즈명"          # optional
seriesOrder: 1              # optional
draft: true                 # optional, production에서 숨김
publishDate: "2025-12-01"   # optional, 예약 발행
---

draft: true 또는 미래의 publishDate가 있는 글은 production 빌드에서 자동으로 제외됩니다. date는 최초 게시일, updated는 최종 수정일이며 둘 다 필수입니다. 처음 게시할 때는 같은 값을 기록하고, 이후 본문·구조화 데이터·주요 링크처럼 검색 결과에 영향을 주는 내용을 실제로 수정했을 때만 updated를 변경합니다. 게시일보다 빠르거나 미래인 수정일은 빌드에서 거부됩니다.

프로젝트 구조

.
├── content/posts/          # Markdown posts
├── public/                 # favicon, OG image, robots.txt, CNAME
├── scripts/
│   └── prerender.mjs       # SSR 결과를 dist HTML에 주입
├── src/
│   ├── components/         # UI, markdown, comments, charts
│   ├── data/               # resume/project data
│   ├── hooks/              # theme, meta, page views
│   ├── i18n/               # ko/en translations
│   ├── layouts/            # root layout
│   ├── lib/                # posts, analytics, shiki, utils
│   ├── pages/              # route pages
│   ├── routes.tsx          # client routes and lazy loading
│   ├── routes.server.tsx   # server prerender routes
│   └── entry-server.tsx    # React SSR entry
└── vite.config.ts          # Vite, manual chunks, RSS, sitemap

기술 스택

Area Stack
App React 19, TypeScript 5.8, Vite 8
Routing React Router v7
Styling Tailwind CSS v4, shadcn/ui, Radix UI
Content react-markdown, remark-gfm, rehype-raw, rehype-slug
Code & Diagram Shiki, Mermaid.js
Data Viz Recharts
Community Giscus
Analytics Google Analytics, Google Apps Script API
Deploy GitHub Pages, custom domain dev.devy.dev

배포

GitHub Pages로 배포하며, 커스텀 도메인은 public/CNAME의 dev.devy.dev를 사용합니다. 빌드 시 rss.xml, sitemap.xml, route별 prerendered HTML이 함께 생성됩니다.

읽기 화면과 검증

  • 데스크톱의 접기·검색은 사이드바에 모으고, 모바일에만 48px 상단 바를 표시합니다. 검색 창은 하나로 공유하며 ⌘K와 Ctrl+K를 지원합니다.

  • 본문 최대 폭은 800px이며, 1280px 이상에서는 옆 목차를 사용합니다. 작은 화면에서는 접는 목차를 제공합니다.

  • 절 링크와 목차 선택은 URL hash에 반영되며, 뒤로가기 시 읽던 위치를 복원합니다.

  • 공개 이미지 원본은 유지하고, Vite 이미지 플러그인이 640/1280/1600px WebP를 생성합니다. 본문 이미지는 크기를 예약하고 지연 로딩합니다. 개발 서버에서도 같은 압축본을 제공합니다.

  • 검색 필터는 hydration이 끝난 뒤 URL에서 읽습니다. 미리보기의 없는 경로는 GitHub Pages처럼 404.html을 HTTP 404로 응답합니다.

  • 조회수는 메모리와 sessionStorage에 15분 동안 캐시합니다. 저장소 차단, 손상된 캐시, API 오류에 대비하며 갱신 실패 시 마지막 정상 데이터를 유지합니다.

  • 일별 조회수 비교는 KST 달력 날짜를 사용합니다. apps-script/Code.js는 60일 조회 및 명시적 실패 응답으로 변경했습니다. 외부 Apps Script 웹 앱에는 이 소스를 별도로 반영해야 합니다.

  • 예약 글은 UTC 날짜를 기준으로 필터링하고, 매일 KST 09:10의 배포 워크플로에서 다시 빌드합니다.

pnpm type-check
pnpm lint
pnpm build
node --test scripts/*.test.mjs
pnpm check:internal-links
pnpm exec playwright install chromium
pnpm test:browser
pnpm preview --host 127.0.0.1 --port 4173

브라우저 검사는 검색 URL, 404 hydration, 절 링크, 읽던 위치 복원, 모바일 목차, 이미지 크기 예약, 키보드 다이어그램 확대와 저장소 차단을 확인합니다. CI에서도 실행하며, ESLint 경고와 High 이상 의존성 취약점을 차단합니다. shadcn의 정적 variant 및 sidebar hook export는 Fast Refresh 검사 예외로 유지합니다.

About

No description, website, or topics provided.

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages