본문으로 건너뛰기
← 블로그로 돌아가기
개발트렌드

블로그 정리의 날포스트 분류와 인포그래픽 업그레이드

4분 읽기
#blog#infographic#framer-motion#Next.js#리팩토링

블로그에 글이 쌓이면서 문제가 생겼다. /blog 페이지에 AI 뉴스와 개인 개발 글이 뒤섞여 있었다. Claude 4.6 업데이트 요약 글이 "개발환경" 카테고리에 들어가 있는 걸 보고 정리가 필요하다고 느꼈다.

오늘 두 가지 작업을 했다. 포스트 분류 재정비, 그리고 Hello World 포스트에 인터랙티브 인포그래픽 추가.

왜 정리가 필요했나

White Place는 2단계 카테고리 시스템을 쓴다. category(대분류)와 subcategory(소분류). AI 뉴스는 ai/ai-news, 개발 글은 dev/web-dev 같은 식이다.

문제는 초기에 작성한 포스트 중 일부가 잘못 분류되어 있었다는 것이다. claude-4-6-update-summary.md가 대표적이다. Claude 4.6 모델 업데이트를 다룬 글인데 dev/dev-env로 분류되어 /blog 목록에 노출되고 있었다.

/blog와 /ai-news 페이지는 subcategory로 필터링한다. 분류가 틀리면 글이 엉뚱한 곳에 나타난다. 카테고리 시스템은 구축보다 유지가 어렵다.

포스트 분류 작업

변경은 frontmatter 한 줄이면 된다.

수정 전:

category: "dev"
subcategory: "dev-env"

수정 후:

category: "ai"
subcategory: "ai-news"

단순해 보이지만 확인할 것이 있다. 블로그 리스트 페이지의 필터링 로직이 이 값을 어떻게 쓰는지 봐야 한다.

// src/app/blog/page.tsx - 필터링 로직
const blogPosts = allPosts.filter(
  (post) => post.subcategory !== "ai-news"
);
// src/app/ai-news/page.tsx - AI 뉴스 전용
const aiNewsPosts = allPosts.filter(
  (post) => post.subcategory === "ai-news"
);

subcategory"ai-news"로 바꾸면 자동으로 /blog에서 빠지고 /ai-news에 나타난다. 별도 라우팅 수정은 필요 없었다.

Hello World에 인포그래픽 얹기

White Place의 모든 포스트에는 인터랙티브 인포그래픽을 넣는 것이 원칙이다. Hello World는 블로그 첫 글이라 인포그래픽 없이 올라간 상태였다.

커스텀 page.tsx 패턴을 사용한다. Next.js App Router에서 /blog/hello-world/page.tsx를 만들면 [slug]/page.tsx보다 우선한다. 이 파일에서 인포그래픽 컴포넌트를 dynamic import한다.

const HelloWorldInfographic = dynamic(
  () => import("@/components/visuals/hello-world/HelloWorldInfographic"),
  { ssr: false }
);

ssr: false는 필수다. framer-motion 애니메이션은 클라이언트에서만 돌아간다.

3개 비주얼 컴포넌트를 만들었다.

  • BlogTopicsCards: 블로그가 다루는 3가지 주제를 카드로 보여준다
  • PhilosophyVisual: 미니멀리즘 철학을 시각적으로 표현한다
  • TechStackPills: 사용 기술 스택을 필 형태로 나열한다

오케스트레이터(HelloWorldInfographic.tsx)가 이 세 컴포넌트를 staggerContainer variants로 순차 등장시킨다.

framer-motion 애니메이션 패턴

프로젝트 전체에서 재사용하는 핵심 패턴은 두 가지다.

fadeUp + staggerContainer 조합:

import { fadeUp, staggerContainer } from "@/lib/animations";

<motion.div
  initial="hidden"
  whileInView="visible"
  viewport={{ once: true, amount: 0.2 }}
  variants={staggerContainer}
>
  <motion.div variants={fadeUp}>첫 번째</motion.div>
  <motion.div variants={fadeUp}>두 번째</motion.div>
</motion.div>

staggerContainer는 자식 요소를 0.1초 간격으로 순차 등장시킨다. fadeUp은 y축 24px 아래에서 위로 올라오면서 나타난다. 이 두 variants만으로 대부분의 섹션 애니메이션을 처리할 수 있다.

whileInView로 스크롤 트리거:

viewport={{ once: true, amount: 0.2 }}는 요소가 뷰포트에 20% 이상 들어오면 한 번만 애니메이션을 실행한다. once: true가 없으면 스크롤할 때마다 반복된다.

animations.ts에 정의된 variants는 as const가 아닌 Variants 타입으로 선언되어 있다. framer-motion v12에서 ease 배열의 타입 추론 문제를 피하기 위한 선택이다.

배운 것

카테고리 시스템은 처음 설계할 때보다 운영하면서 일관성을 유지하는 게 핵심이다. 포스트가 10개를 넘기면 분류 실수가 눈에 띄기 시작한다. 주기적인 정리가 필요하다.

인포그래픽은 글의 가독성을 체감할 수 있을 정도로 올린다. 텍스트만 있는 포스트와 비주얼이 섞인 포스트는 스크롤 깊이가 다르다. 만드는 데 시간이 들지만 투자 대비 효과가 있다.

다음 작업은 나머지 초기 포스트들에도 인포그래픽을 추가하는 것이다. 그리고 카테고리별 포스트 수를 대시보드로 볼 수 있는 관리 도구를 만들어볼 계획이다.

관련 포스트