·약 32분 읽기
바이브 코딩으로 블로그 만들기 시리즈 코딩을 몰라도 AI와 대화하며 ‘내 소유’ 수익형 웹사이트를 만드는 15일 여정
DAY 07에서 마크다운 글쓰기 시스템을 완성했습니다. 글을 쓸 수 있게 됐고, 포스트 상세 페이지도 수익형으로 다듬었습니다.
오늘은 방문자가 블로그에 ‘더 오래 머물게’ 만드는 기능을 추가합니다.
왜 체류 시간에 집착하냐고요? 숫자로 보여드리겠습니다.
평균 체류 시간 3분인 블로그:
→ 방문자가 글 1개를 대충 읽고 이탈
→ 광고 노출 1~2회
→ 클릭 확률: 낮음
평균 체류 시간 7분인 블로그:
→ 방문자가 글 1개를 꼼꼼히 읽고 + 관련 글 1개 더 읽음
→ 광고 노출 4~6회
→ 클릭 확률: 2~3배
같은 방문자 수라도 체류 시간이 길면 수익이 2~3배 차이 납니다.
그리고 체류 시간은 구글 검색 순위에도 영향을 줍니다. 방문자가 오래 머무는 글 = ‘이 글이 유용하다’는 신호 = 검색 순위 상승 = 더 많은 방문자. 선순환입니다.
오늘 추가할 기능은 두 가지입니다. 자동 목차(TOC) 와 카테고리 시스템. 둘 다 AI에게 프롬프트 한 번이면 됩니다.
긴 글을 열었을 때 목차가 없으면 방문자는 이렇게 행동합니다.
목차 없는 글:
방문자 → 스크롤 내려봄 → ‘길다...’ → 뒤로 가기 (이탈)
목차 있는 글:
방문자 → 목차 훑어봄 → ‘3번 항목이 궁금하네’ → 클릭 → 바로 이동 → 읽기 시작
목차는 ‘이 글에 뭐가 있는지 미리 보여주는 메뉴판’입니다. 레스토랑에서 메뉴 없이 ‘일단 앉아서 나오는 거 드세요’라고 하면 나가겠죠? 블로그도 마찬가지입니다.
DAY 05에서 AI가 기본적인 TOC를 만들어줬고, DAY 07에서 포스트 상세 페이지를 개선할 때 TOC 영역도 다뤘습니다. 하지만 아직 부족한 부분이 있을 수 있습니다. 오늘은 TOC를 수익형 블로그 수준으로 완성합니다.
완성된 TOC는 이렇게 작동해야 합니다.
| 📑 목차 | 사이드바 영역 |
|---|---|
| 소제목 1 | 클릭하면 해당 위치로 스크롤 |
| 소제목 2 | — |
| └ 세부항목 A | H3 들여쓰기 |
| └ 세부항목 B | — |
| 소제목 3 · 현재 | 현재 읽는 위치 하이라이트 |
| 소제목 4 | — |
스크롤하면 ‘현재’ 하이라이트가 따라 이동합니다.
| 목차 ▼ | 탭하면 펼쳐짐 |
|---|---|
| 소제목 1 | — |
| 소제목 2 | — |
| └ 세부항목 A | — |
| 소제목 3 | — |
| 소제목 4 | — |
TOC(목차) 컴포넌트를 완성해줘.
현재 TOC 관련 코드가 있으면 확인하고 아래 스펙에 맞게 수정,
없으면 새로 만들어줘.
## 데스크톱 (768px 이상)
1. 사이드바 영역에 위치
2. position: sticky, top: 80px (헤더 높이 + 여유)
3. 본문의 H2, H3 태그를 자동으로 추출해서 목록 생성
4. H2는 기본 들여쓰기, H3는 왼쪽 padding 16px 추가
5. 각 항목 클릭 시 해당 위치로 smooth scroll
6. 현재 스크롤 위치에 해당하는 항목에 하이라이트:
- 포인트 컬러로 텍스트 색상 변경
- 왼쪽에 2px 포인트 컬러 보더 표시
7. 글자 크기: 14px
8. 항목 간 간격: 8px
9. "목차"라는 제목 표시 (굵게, 16px)
## 모바일 (768px 미만)
1. 본문 시작 전, 첫 번째 광고 아래에 위치
2. 기본 상태: 접혀 있음 ("목차 ▼" 텍스트만 보임)
3. 탭하면 펼쳐짐 ("목차 ▲"로 변경)
4. 펼쳐졌을 때 항목 클릭하면 해당 위치로 이동 + 목차 자동으로 접힘
5. 배경: 카드 배경색, 둥근 모서리 8px, 패딩 16px
## 기술 요구사항
- Intersection Observer API 사용 (스크롤 위치 감지)
- 본문의 H2/H3에 자동으로 id 부여 (이미 되어 있을 수 있음)
- 'use client' 컴포넌트로 작성 (상태 관리 필요)
- 목차 항목이 3개 미만이면 TOC 자체를 숨기기
현재 코드를 확인하고 수정해줘.
AI가 수정을 완료하면 localhost:3000에서 글 상세 페이지를 열고 이렇게 확인하세요.
더미 포스트의 소제목(H2)이 2개 이하면 TOC가 안 보일 수 있습니다. H2가 3개 이상인 긴 글로 테스트하세요. 없으면 AI에게 “테스트용으로 H2가 5개인 긴 더미 포스트를 하나 만들어줘”라고 요청하세요.
카테고리는 ‘같은 주제에 관심 있는 방문자를 더 오래 잡아두는 장치’입니다.
카테고리 없는 블로그:
방문자 → ‘개발’ 글 읽음 → 다음 글이 ‘요리’ → ‘나랑 상관없네’ → 이탈
페이지뷰: 1
카테고리 있는 블로그:
방문자 → ‘개발’ 글 읽음 → ‘개발’ 카테고리 클릭 → 관련 글 3개 더 읽음
페이지뷰: 4 (광고 노출 4배)
카테고리는 복잡한 기능이 아닙니다. 글의 frontmatter에 이미 category 필드가 있으니, 이걸 기반으로 분류하고 페이지를 만들면 됩니다.
우리가 만들 카테고리 시스템은 세 군데에서 작동합니다.
헤더 내비게이션
사이드바 카테고리 목록(글 개수 표시)
카테고리 페이지
카테고리 시스템을 완성해줘.
기존 코드에 카테고리 관련 기능이 있으면 확인하고 보완,
없으면 새로 만들어줘.
## 1. 카테고리 데이터 추출 (lib/posts.js)
- 모든 포스트의 frontmatter에서 category를 추출
- 중복 제거 후 카테고리 목록 생성
- 각 카테고리별 글 개수 계산
- 글 개수 기준 내림차순 정렬
- 함수명: getAllCategories() → { name: string, count: number }[]
- 특정 카테고리의 글만 반환하는 함수: getPostsByCategory(category: string)
## 2. 헤더 카테고리 네비게이션
- Header 컴포넌트에 카테고리 링크 표시
- 상위 카테고리 최대 5개만 표시 (글이 많은 순)
- 각 링크는 /category/[카테고리명]으로 이동
- 현재 페이지의 카테고리에 해당하는 링크에 활성 표시
(하단 2px 포인트 컬러 보더 또는 굵은 글씨)
- 모바일 햄버거 메뉴에도 카테고리 표시
## 3. 사이드바 카테고리 위젯
- Sidebar 컴포넌트에 카테고리 섹션 추가/보완
- "카테고리" 제목 (굵게)
- 각 카테고리 이름 + 글 개수를 괄호로 표시
예: 개발 (5)
- 클릭 시 /category/[카테고리명]으로 이동
- hover 시 포인트 컬러
## 4. 카테고리 페이지 (/category/[name])
- 상단에 "📁 [카테고리명]" 제목 (H1)
- 해당 카테고리의 글만 필터링해서 표시
- 글 목록은 홈페이지와 동일한 PostCard 컴포넌트 사용
- 날짜 내림차순 정렬
- 해당 카테고리에 글이 없으면 "아직 글이 없습니다" 메시지
- SSG: generateStaticParams로 모든 카테고리 경로를 빌드 타임에 생성
## 5. 포스트 상세 페이지의 카테고리 배지
- 글 상단의 카테고리 배지 클릭 시 해당 카테고리 페이지로 이동
- (이미 구현되어 있다면 링크만 확인)
기존 코드를 확인하고 필요한 부분을 수정/추가해줘.
TOC와 카테고리가 핵심이지만, 추가로 넣으면 좋은 작은 기능들이 있습니다. 지금 당장 하지 않아도 되고, 나중에 글이 쌓인 뒤에 해도 됩니다. AI에게 한 줄이면 추가할 수 있으니 참고만 해두세요.
페이지 맨 위에 얇은 바가 스크롤에 따라 채워지는 기능:
방문자에게 ‘얼마나 남았는지’를 보여줍니다. ‘조금만 더 읽으면 끝인데’라는 심리가 작동해서 이탈을 줄여줍니다.
AI에게 요청할 때:
페이지 상단에 스크롤 진행률 바를 추가해줘.
헤더 바로 위 또는 아래에 높이 3px, 포인트 컬러로.
스크롤 비율에 따라 왼쪽에서 오른쪽으로 채워지게.
긴 글을 다 읽은 뒤 목차로 돌아가거나 다른 글을 보려면 스크롤을 한참 올려야 합니다. 화면 오른쪽 하단에 [↑] 버튼을 배치하면 한 번에 올라갈 수 있습니다.
AI에게 요청할 때:
화면 오른쪽 하단에 "맨 위로" 버튼 추가해줘.
스크롤 300px 이상 내려갔을 때만 표시.
클릭 시 smooth scroll로 맨 위로 이동.
둥근 원형 버튼, 포인트 컬러 배경, 흰색 화살표.
스크롤 진행률 바와 다른 개념입니다. 글 상단의 ‘읽는 시간 3분’ 옆에 읽기 진행률을 퍼센트로 보여주는 겁니다. 이건 나중에 추가해도 되니 아이디어만 기억해두세요.
지금까지 다음의 기능을 만들었습니다.
앞으로 다룰 내용은 다음과 같습니다.
블로그로서의 핵심 기능은 거의 완성됐습니다. 남은 건 검색 엔진 최적화(DAY 09), 배포(DAY 11), 수익화(DAY 12~14)입니다.
브라우저에서 블로그를 열고, 아래 질문에 스스로 답해보세요.
“모르는 사람이 이 블로그에 처음 왔을 때, 3초 안에 ‘여기 괜찮네’라고 느낄까?”
느낀다면 → 잘하고 있습니다. 다음 단계로. 못 느낀다면 → 구체적으로 뭐가 거슬리는지 적어보세요. ‘헤더가 너무 두껍다’, ‘색상이 칙칙하다’, ‘글 목록이 밋밋하다’ 같은 것들. 그리고 AI에게 그대로 말하면 됩니다.
완벽하지 않아도 됩니다. 지금 가장 중요한 건 ‘돌아가는 블로그’를 ‘배포 가능한 블로그’로 만드는 겁니다. 디자인 미세 조정은 배포 후에도 언제든 할 수 있습니다. 전진하세요.
이 코너는 매 회 해당 단계에서 자주 겪는 문제와 해결법을 다룹니다.
에러 1: TOC의 스크롤 하이라이트가 전혀 작동하지 않는다
→ Intersection Observer가 감시할 대상(H2/H3 요소)을 찾지 못하고 있을 가능성이 높습니다. 본문의 H2/H3 태그에 id 속성이 제대로 부여되어 있는지가 핵심입니다. AI에게 “마크다운이 HTML로 변환될 때 H2, H3 태그에 자동으로 id가 생성되는지 확인해줘. rehype-slug 같은 플러그인이 필요할 수 있어”라고 요청하세요.
에러 2: TOC 클릭 시 해당 위치로 이동하지만 헤더에 가려진다
→ sticky 헤더(64px) 때문에 스크롤 목표 지점이 헤더 뒤로 숨는 겁니다. AI에게 “TOC 클릭 시 스크롤 위치에 offset을 추가해줘. 헤더 높이(64px) + 여유(16px) = 80px만큼 위에서 멈추도록”이라고 요청하세요. CSS의 scroll-margin-top 속성을 H2/H3에 적용하는 방법도 있습니다.
에러 3: 카테고리 페이지에 들어가면 404가 뜬다
→ 두 가지 원인이 있습니다. 첫째, app/category/[name]/page.js 파일이 없는 경우. AI에게 “카테고리 페이지 파일이 존재하는지 확인해줘”라고 요청하세요. 둘째, generateStaticParams 함수가 빠져서 빌드 시 경로가 생성되지 않은 경우. AI에게 “카테고리 페이지에 generateStaticParams를 추가해서 모든 카테고리 경로를 정적으로 생성하게 해줘”라고 요청하세요.
에러 4: 사이드바 카테고리 목록에 같은 카테고리가 중복으로 뜬다
→ 카테고리 이름의 대소문자나 공백이 미묘하게 다른 겁니다. 예를 들어 한 글에는 “개발”, 다른 글에는 “개발 ” (뒤에 공백)으로 적었을 수 있습니다. AI에게 “getAllCategories 함수에서 카테고리 이름을 trim() 처리하고 대소문자를 통일해줘”라고 요청하세요. 근본적으로는 frontmatter의 category를 쓸 때 일관된 이름을 사용하는 게 중요합니다.
마크다운 문법·frontmatter·포스트 상세 페이지 다듬기, Cursor 글쓰기 워크플로·이미지·AI 뼈대 팁까지 수익형 블로그 글쓰기 입문.
헤더·푸터·색상·타이포를 수익 관점에서 다시 설계하고, 애드센스와 조화되는 링크 색·체크리스트까지.
create-next-app으로 뼈대 만들기, Cursor 프롬프트로 수익형 블로그 UI 생성, localhost 확인·에러 대처·마크다운 글까지 첫 화면 띄우기.