블로그는 이미 있었습니다. 다만 열어볼 때마다 아쉬웠습니다. 디자인은 밋밋했고, 다크모드는 없었고, 기술 스택은 어느새 한 세대 뒤처져 있었죠. "언젠가 갈아엎어야지" 하던 일을 이번에 실행했습니다. Next.js 16 + DaisyUI + MDX 조합으로 블로그를 처음부터 다시 만들면서 내린 결정과, 그 과정에서 부딪힌 삽질을 솔직하게 기록합니다.
1. 왜 다시 만들기로 했나
기존 블로그의 문제는 사실 꽤 명확했습니다. 디자인이 밋밋한 데다 다크모드조차 없었고, Pages Router 기반이라 React Server Components의 이점을 전혀 살리지 못하고 있었습니다. 글 하나 추가하는 과정도 번거로웠고, 무엇보다 "이걸 포트폴리오로 내밀 수 있을까?" 싶은 완성도였습니다.
그래서 목표를 한 문장으로 정리했습니다. "읽을 만한 기술 블로그이자, 그 자체로 포트폴리오가 되는 사이트를 만들자." 글의 그릇이면서 동시에 결과물이기도 한 사이트. 이 기준이 이후 모든 기술 선택의 잣대가 됐습니다.
2. 기술 스택 결정
"익숙해서"가 아니라 "이 사이트의 목표에 맞아서"를 기준으로 골랐습니다. 고민했던 대안과 최종 선택 이유를 함께 정리하면 다음과 같습니다.
영역
선택
대안
선택 이유
Framework
Next.js 16 (App Router)
Gatsby, Astro
RSC 지원, 익숙함, Vercel 배포 편의성
UI Library
DaisyUI 5
shadcn/ui, Chakra UI
빠른 프로토타이핑, 테마 시스템 내장
Styling
Tailwind CSS 4
SCSS, styled-components
DaisyUI와의 궁합, 유틸리티 퍼스트
Content
MDX (next-mdx-remote)
Contentlayer, Notion API
파일 기반 관리, 유연한 커스터마이징
Animation
Framer Motion
GSAP, CSS Animation
React 생태계 통합, 선언적 API
Theme
next-themes
직접 구현
SSR 호환, 깜빡임 방지 내장
핵심 축은 결국 App Router(RSC) + 파일 기반 MDX였습니다. 콘텐츠를 파일로 두면 CMS를 붙이지 않아도 글쓰기 흐름이 단순해지고, RSC 덕분에 목록·상세 페이지를 서버에서 가볍게 그릴 수 있습니다. 나머지 선택은 이 두 축을 가장 매끄럽게 받쳐주는 도구를 고른 결과입니다.
3. 개발 타임라인
전체 과정을 커밋 히스토리 기준으로 네 단계로 나눠 돌아봤습니다.
Phase 1 — 기반 세팅 (1~2일)
DaisyUI 레이아웃을 잡고, Footer를 만들고, RotatingText 애니메이션을 실험하고, 라이트/다크 테마를 설정했습니다. 돌아보면 랜딩의 핵심 요소인 RotatingText부터 먼저 만든 것이 신의 한 수였습니다. 가장 눈에 띄는 부분을 초반에 프로토타이핑하니, 사이트 전체의 톤과 분위기가 일찍 잡혀서 이후 작업의 기준점이 됐거든요.
Phase 2 — 블로그 핵심 기능 (3~4일)
Post 목록 페이지, 카테고리 필터, MDX 기반 상세 페이지 렌더링, 그리고 Typography prose 스타일을 다듬었습니다. 이 단계에서 가장 발목을 잡은 건 Typography였습니다. rehype-pretty-code가 뱉어내는 코드 블록의 HTML 구조에 맞춰 CSS를 일일이 맞춰가는 작업이 생각보다 한참 더 걸렸습니다. 보기엔 단순한 코드 블록 하나가, 실제로는 토큰마다 색을 입히는 중첩 구조라는 걸 그제야 체감했죠.
Phase 3 — 디테일 & 수정 (2~3일)
Hydration Error 해결, 빌드 에러 수정, 메인 페이지 SSR 이슈 처리, 도메인 변경과 sitemap 생성, About 페이지 작성까지. 기능을 새로 만드는 시간보다 이미 만든 것을 안정화하는 시간이 더 길었습니다. 화려한 단계는 아니지만, 완성도는 사실상 여기서 결정됐습니다.
Phase 4 — 콘텐츠 (지속)
React Native 트러블슈팅, Supabase OAuth 가이드 등 실제 글을 쌓기 시작했습니다. 이 단계는 끝이 없습니다. 플랫폼을 다 만들고 글을 쓰는 게 아니라, 글을 쓰면서 플랫폼을 계속 다듬는 구조라는 걸 여기서 깨달았습니다.
4. 삽질 기록
4-1. Hydration Error와의 전쟁
가장 자주 마주친 적입니다. 서버에서 그린 HTML과 클라이언트에서 그린 HTML이 어긋나는 순간 어김없이 터졌습니다. 범인은 늘 비슷했습니다. useTheme()로 가져온 테마값을 서버 렌더링 시점에 쓰거나(서버는 테마를 모릅니다), Date 객체가 서버(UTC)와 클라이언트(KST)에서 다르게 포맷되거나, 서버에 존재하지 않는 window에 접근하는 경우였죠.
결국 클라이언트 전용 로직은 전부 "마운트된 뒤에만 그린다"는 한 가지 패턴으로 감쌌습니다.
규칙은 단순합니다. 서버가 알 수 없는 값에 의존하는 UI라면, 서버에서는 그리지 않는다.
4-2. 빌드 에러: Module not found
개발 서버에선 멀쩡한데 빌드만 하면 실패하는, 가장 약 오르는 유형입니다. 원인은 대개 둘 중 하나였습니다. import 경로의 대소문자가 실제 파일명과 미묘하게 다르거나(맥 로컬은 대소문자를 구분하지 않아 넘어가지만, 빌드 환경은 칼같습니다), tsconfig의 path alias가 제대로 잡히지 않은 경우였죠.
의외의 복병이었습니다. rehype 플러그인은 배열에 적은 순서가 곧 실행 순서이고, 그 순서가 결과를 바꿉니다.rehypePrettyCode를 rehypeSlug보다 먼저 두어야, 코드 블록 안의 텍스트가 heading으로 잘못 인식돼 엉뚱한 앵커가 붙는 일을 막을 수 있었습니다. 플러그인을 "기능 묶음"이 아니라 "순서가 있는 파이프라인"으로 바라보기 시작한 계기였습니다.
5. 잘한 점
파일 기반 콘텐츠 관리가 단연 최고의 선택이었습니다. CMS 없이 MDX 파일 하나만 추가하면 끝이라, 글쓰기 진입장벽이 거의 없습니다. IDE에서 바로 쓰고 git push 한 번이면 배포까지 이어지니, "글 쓰기 귀찮음"이라는 가장 큰 적이 사라졌습니다.
Glass Morphism 디자인은 사이트의 정체성이 됐습니다. 반투명 유리 질감을 전 페이지에 일관되게 적용했고, Tailwind 유틸리티로 재사용 가능한 스타일 패턴을 만들어 둔 덕분에 새 컴포넌트도 같은 톤으로 빠르게 찍어낼 수 있었습니다.
다크모드 완성도도 만족스럽습니다. DaisyUI와 next-themes 조합으로 깜빡임 없는 전환을 구현했고, 코드 블록·로고·배경까지 테마에 맞춰 자연스럽게 따라옵니다.
6. 아쉬운 점과 개선 계획
아직 비어 있는 칸이 있습니다. 포스트가 쌓이면 필요해질 검색 기능, giscus나 utterances 연동을 고민 중인 댓글 시스템, 구독자를 위한 RSS 피드, 그리고 글 길이에 따른 읽기 시간 표시 정도가 다음 차례입니다.
디자인 쪽으로는 상세 페이지의 Table of Contents, 카테고리별 고유 썸네일, 그리고 파싱만 되고 UI는 아직 비어 있는 태그 시스템 활성화를 손볼 계획입니다. 적어두고 보니 결국 "글이 많아지면 필요한 것들"이네요. 좋은 신호라고 생각합니다.
7. 배운 점
가장 크게 깨진 통념은 **"완벽하게 만든 뒤에 글을 쓰자"**는 생각이었습니다.
처음엔 모든 기능을 다 갖춘 뒤 글을 쓰려 했지만, 실제로는 정반대였습니다. 글을 쓰다 보니 부족한 기능이 보였고, 그 기능을 만들다 보니 또 새로운 글감이 생겼습니다. 결국 콘텐츠와 플랫폼을 번갈아 키우는 것이 가장 빠른 길이었습니다. 완성을 기다렸다면 아마 지금도 첫 글을 못 썼을 겁니다.
그리고 한 가지 더. 프론트엔드 개발자에게 자체 블로그는 최고의 사이드 프로젝트입니다. 결과물이 곧 포트폴리오가 되고, 만드는 과정 자체가 또 글감이 되니까요.
마무리
리뉴얼은 끝이 아니라 시작입니다. 앞으로도 글을 쓰면서 블로그를 계속 키워 나갈 생각입니다. 비슷한 고민을 하고 계신 분께 이 회고가 작은 참고가 되면 좋겠습니다.