Tech Blog Post
작업 중 쌓인 실전 경험을 검색하는 사람이 찾아올 수 있는 글로 바꾼다.
내부 기록용 학습 로그와 다른 점은 독자가 남이라는 것이다. 같은 문제를 검색해서 들어온 사람이 끝까지 읽고 문제를 해결할 수 있어야 하고, 검색엔진이 그 글을 그 문제의 답으로 인식할 수 있어야 한다. 독자를 위한 완결성과 검색엔진을 위한 구조, 둘 다 챙긴다.
진입 모드 판별 (가장 먼저)
이 스킬은 두 결로 불린다. 아래 단계로 들어가기 전에 어느 쪽인지 먼저 가른다.
1) 명시적 블로그·포스팅 요청 — "블로그 글로 써줘", "포스팅해줘", "SEO 최적화해서", "상위노출"
등. 이 경우 파일을 원하는 게 분명하므로 저장 여부를 따로 묻지 않는다. 아래 0~6단계를 그대로
따라 SEO 최적화된 글을 만들고 기본값으로 posts/{slug}.html까지 저장한다.
2) 일반 정리 요청 — "이 내용 정리해줘", "지금까지 한 거 정리해줘", "이거 정리해줘", "이 대화 정리해줘" 등. 파일을 원하는지 불분명하므로 먼저 물어본다:
정리한 결과를 파일로 저장할까요? HTML(기본) / 마크다운 / 저장 안 하고 여기서 보여주기
- HTML(기본) 또는 마크다운을 고르면 → 아래 단계를 따라 정리하고 6단계에서 그 형식으로 저장한다.
- 저장 안 함을 고르면 → 파일을 만들지 않는다. 6단계(파일 저장)·
posts/index.json갱신· 4-1단계(밈 삽입)·5-1단계(SEO 체크리스트)는 전부 건너뛰고, 내용 정리에 집중해 대화로 바로 보여주고 끝낸다. 파일로 안 남기는데 태그·메타 설명·slug 같은 SEO 부산물을 굳이 만들지 않는다.
사용자가 처음부터 형식을 지정했으면("HTML로 정리해줘", "md로 정리해줘") 다시 묻지 말고 그 형식으로 바로 저장한다. 저장 여부가 애매하면 묻는 쪽이 기본이다 — 사용자가 원치 않는 파일을 함부로 만들지 않는다.
0단계: 주제와 범위 확정
이 스킬은 날짜 단위가 아니라 주제 단위로 움직인다. 먼저 확정한다.
주제: 무엇에 대한 글인지. 사용자가 명시하지 않았으면 최근 대화나 작업에서 가장 완결된 하나의 문제/개념을 골라 제안하고 확인받는다. 여러 주제가 섞여 있으면 한 글에 욱여넣지 말고 쪼갠다 — 검색엔진은 주제 하나에 집중한 글을 더 명확한 답으로 인식한다.
범위: 아래 둘 중 하나다. 사용자 말에서 명확하지 않으면 물어본다.
- 단일 세션형: 지금 대화/오늘 작업에서 다룬 것만으로 충분히 완결된 글이 나오는 경우.
- 누적형: "요즘 계속 붙잡고 있던", "지난 2주간" 처럼 여러 날에 걸친 작업을 한 편으로 묶는 경우. 이때는 대상 기간(YYYY-MM-DD ~ YYYY-MM-DD)을 사용자에게 확정받아 아래 수집 단계에 쓴다.
타겟 키워드: 사람들이 이 문제를 검색할 때 실제로 칠 법한 말(에러 메시지, 기술명 조합 등)을 1차로 뽑아 사용자에게 확인받는다. 이 키워드가 제목·본문·태그에 일관되게 쓰인다.
경쟁 글 확인: 확정한 타겟 키워드로 웹 검색을 해서, 지금 그 키워드로 상위에 노출되어 있는 글들을 실제로 열어본다. 어떤 하위 주제를 다루는지, 대략적인 분량과 구성(코드 예제 유무, 단계별 설명 여부)인지 확인한다. 이 글에서 반드시 다뤄야 할 항목이 빠지지 않게 하고, 이미 있는 글을 그대로 베끼지 않도록 차별화할 지점(더 최신 버전 기준, 더 구체적인 재현 조건, 실제로 겪은 트레이드오프 등)을 하나 이상 잡는다.
0-1단계: 기존 글 확인 (중복 체크)
재료를 모으기 전에 posts/index.json을 먼저 읽는다 (없으면 이 단계는 건너뛴다 — 첫 글이라는
뜻이다). 방금 확정한 주제·타겟 키워드와 tags·meta_description이 겹치는 항목이 있으면
사용자에게 알린다:
- 다루는 각도가 다르면(예: 같은 라이브러리라도 "설치" vs "성능 튜닝") 새 글로 진행해도 된다고 판단하되, 겹치는 이유를 사용자에게 짧게 알리고 계속할지 확인한다.
- 사실상 같은 내용이면 새 글을 또 만들지 말고, 기존 글(
index.json의file경로)을 갱신하는 방향으로 갈지 사용자에게 묻는다 — 검색엔진 입장에서 같은 키워드를 두고 글이 쪼개져 있으면 서로 경쟁하며 순위를 깎아먹는다(키워드 카니발라이제이션).
index.json이 아직 없거나 이번 글이 확실히 다른 주제면 조용히 다음 단계로 넘어간다 — 매번
사용자에게 "중복 없음"까지 보고할 필요는 없다.
1단계: 재료 수집
날짜가 아니라 주제/키워드로 필터링한다는 점만 빼면 원리는 같다 — 근거 없이 지어내지 않는다. 현재 환경에서 쓸 수 있는 도구만 쓰고, 접근할 수 없는 소스는 조용히 건너뛴다.
Claude와 나눈 대화
지금 이 대화에서 다룬 내용이면 별도 도구 없이 바로 재료로 쓴다 — 이미 컨텍스트에 있다.
과거 대화까지 봐야 하면 conversation_search(주제 키워드)와 recent_chats(기간)를 쓰되,
이 도구들은 환경에 따라 없을 수 있다 — 없으면 조용히 건너뛰고 git/문서/사용자 확인으로 채운다.
막혔던 지점, 여러 번 시도한 흔적, 사용자가 정정한 부분이 본문의 "원인 분석"과 "해결 과정"이 된다.
git 커밋
git log --grep="{키워드}" -i --pretty=format:"%h %ad %s" --date=short
# 또는 범위가 확정된 누적형이면
git log --since="{시작일} 00:00" --until="{종료일} 23:59" --pretty=format:"%h %ad %s" --date=short
git show {해시}로 실제 코드 변경을 확인한다. git 저장소가 아니면 이 소스는 조용히 건너뛴다.
여러 저장소를 오갔다면 사용자에게 경로를 묻는다.
관련 문서
프로젝트 안에 이미 정리해둔 메모나 문서가 있는지 확인한다 (grep -ril "{키워드}" . 등).
수집한 내용이 글 하나 분량이 안 되면 지어내지 말고, 무엇을 더 다뤄야 하는지 사용자에게 묻는다.
2단계: 글 유형 정하기
수집한 내용의 성격에 따라 넷 중 하나로 정한다. SEO 구조가 유형마다 다르다.
| 유형 | 판별 기준 |
|---|---|
| 트러블슈팅형 | 특정 에러/증상을 원인을 찾아 해결했다. 검색엔진에 가장 잘 걸리는 유형 — 사람들이 에러 메시지를 그대로 검색한다. |
| 개념정리형 | 기술/개념을 설명하고 실제 사용법을 보여준다. |
| 비교분석형 | A와 B 중 뭘 쓸지 실제로 비교·선택해본 경험이 있다. "A vs B"류 검색에 걸린다. |
| 튜토리얼형 | 아무것도 없는 상태에서 뭔가를 처음부터 끝까지 만들어봤다. " |
여러 유형이 섞여 있으면(예: 비교해보고 그중 하나로 튜토리얼까지 진행) 가장 검색 유입이 클 유형 하나로 좁힌다 — 0단계에서 "여러 주제가 섞여 있으면 쪼갠다"고 정한 것과 같은 이유다.
3단계: SEO 요소 정하기
제목
공식: {핵심 키워드} + {얻을 수 있는 것/구체적 정보}. 키워드를 앞쪽에 자연스럽게 배치하고,
가능하면 숫자·범위·대상을 구체적으로 명시해 클릭을 유도한다.
- 트러블슈팅형 예:
TypeError: Cannot read properties of undefined 해결 방법 3가지 - 개념정리형 예:
React Suspense로 로딩 상태 관리하기 (예제 코드 포함) - 비교분석형 예:
Redis vs Memcached 실제로 써보고 비교한 결과 - 튜토리얼형 예:
Docker로 Node.js 개발 환경 처음부터 구축하기키워드를 단순 나열하지 않는다 — 사람이 읽었을 때도 자연스러운 문장이어야 한다.
태그 / 카테고리 태그는 핵심 키워드와 관련 기술명으로 5~10개. 사용자의 블로그에 기존 카테고리 체계가 있으면 그걸 따르고, 없으면 어떤 카테고리로 분류할지 사용자에게 묻는다.
메타 설명(요약) 150자 이내로, 핵심 키워드를 포함해 "이 글에서 뭘 얻을 수 있는지"를 압축한다. 블로그 플랫폼의 글쓰기 화면에 보통 있는 요약/설명 입력란에 들어갈 문장이다.
키워드 배치
핵심 키워드를 제목에 1회, 첫 문단에 1회, 본문 중간에 23회 — 총 35회 자연스럽게 녹인다.
억지로 욱여넣지 않는다. 문장이 어색해지면서까지 키워드를 반복하면 가독성도 떨어지고
검색엔진도 이런 패턴(키워드 스터핑)을 오히려 감점 요인으로 본다.
구조 제목(H1)은 하나. 본문 소제목은 H2, 그 아래는 H3로 위계를 지킨다. 글이 길면 목차를 넣는다.
분량 정보를 충분히 담다 보면 자연스럽게 1,500자 이상이 된다. 분량을 채우려고 같은 말을 반복하거나 관련 없는 배경지식을 늘리지 않는다 — 다뤄야 할 하위 주제(원인의 종류, 대안 방법, 자주 하는 실수 등)를 빠짐없이 다뤘는지로 분량을 판단한다.
4단계: 유형별로 본문 작성
2단계에서 정한 유형에 맞춰 본문을 쓴다. 유형별 소제목 골격은 references/post-types.md에서
해당 유형 하나만 읽어 따른다 (나머지 유형은 볼 필요 없다). 어느 유형이든 소제목은 이 글의
주제에 맞게 자연스럽게 바꾸고, 마지막은 핵심 키워드를 한 번 더 담은 "정리"로 닫는다.
본문의 톤: 내용은 진지하되 문체는 여유로워야 한다. 짤처럼 가벼워지라는 게 아니다 — 정보의 정확성과 깊이는 그대로 두고, 말투에서 힘을 뺀다. 독자를 가르치려 들거나 과장하지 않고, 삽질한 과정이나 헷갈렸던 지점을 담담하게 인정하는 정도의 여유다. 밈(4-1)이 위트를 담당하니 본문 문장까지 웃기려 애쓰지 않는다 — 본문은 신뢰가 가면서 읽기 편한 글이면 된다.
4-1단계: 밈(짤) 삽입 (선택)
글에 숨 돌릴 틈과 위트를 주는 리액션 짤을 넣는 경로다. API 키·과금이 전혀 없고, assets/memes/에
미리 저장해둔 템플릿에 캡션만 얹는다.
- 넣을지 판단: 본문에 리액션이 자연스러운 자리(삽질 구간, 반전, 허탈한 결론, 놀라운 발견)가
있고,
assets/memes/memes.json에 그 상황에 맞는 템플릿(use_when)이 있을 때만 넣는다. 폴더가 비었거나 맞는 템플릿이 없으면 넣지 않는다 — 짤을 위해 억지 자리를 만들지 않는다. - 그림은 고정, 캡션은 동적: 그림은 저장된 템플릿에서 고르고, 캡션 문구는 글 맥락에 맞게
매번 새로 쓴다.
example_caption은 말투 참고용일 뿐 복붙하지 않는다. - 분량: 한 글에 1~2개면 충분하다. 소제목마다 다는 건 과하다.
- 블로그에선 이미지를 직접 업로드해야 한다: 짤은 로컬
posts/images/에 저장되지만, 상대 경로src는 티스토리 등에 붙여넣으면 안 보인다. 사용자가 자기 블로그 에디터에 그 PNG를 올리고 나온 URL로src를 교체해야 한다(각자 자기 블로그에 올라가므로 외부 계정·키·과금 없음). HTML에 교체 안내 주석을 넣고, 글을 다 만든 뒤 채팅으로도 이 점을 한 번 알린다.
넣기로 했으면 실행 세부(템플릿 고르기, 캡션 쓰기, make_meme.py 호출, <img> 삽입, 업로드
안내)는 references/meme.md를 따른다.
4-2단계: 자주 묻는 질문 (선택)
이 주제를 검색하는 사람이 실제로 따라 물을 법한 질문이 2~3개 이상 자연스럽게 나오면, 조립본의 "마무리" 앞에 FAQ 섹션을 넣는다. 본문 내용을 억지로 쪼개 질문을 지어내지 않는다 — 자연스러운 질문이 그만큼 안 나오면 이 섹션은 그냥 생략한다.
FAQ를 넣기로 했으면 섹션 형식, posts/{slug}.schema.json의 schema.org FAQPage 구조화
데이터, 그리고 "JSON-LD를 본문 <script>로 넣지 않는다"는 주의사항까지 references/faq-schema.md를
따른다.
5단계: 전체 글 조립
조립하기 전에, 4단계에서 쓴 본문 전체에 elements-of-style 플러그인의
writing-clearly-and-concisely 스킬을 적용해 문장을 다듬는다 — 불필요한 단어를 쳐내고,
수동태를 능동태로 바꾸고, 한 문장에 한 가지 생각만 담는다. SEO를 위한 키워드 배치나 글 구조는
그대로 두고, 문장 단위의 표현만 정리한다.
다듬은 본문을 가지고 아래 구조로 내용을 조립한다. 이 조립본은 최종 산출물이 아니라 다음 단계에서 HTML로 옮기기 위한 중간 골격이다.
# {SEO 제목}
{리드 문단: 이 글이 어떤 문제를 다루는지, 읽으면 뭘 얻는지. 핵심 키워드 1회 포함.}
## 목차
(글이 길 때만. 위 소제목들을 그대로 나열한 일반 텍스트 목록으로 — 하이퍼링크나
`{#anchor}` 같은 kramdown/Pandoc 확장 문법은 쓰지 않는다. 티스토리 등 대부분의
블로그 마크다운 변환기는 헤더에 id를 안 붙이고 `{#...}` 문법도 파싱하지 못해서,
링크는 클릭해도 안 움직이고 `{#...}` 자체가 본문에 그대로 노출된다.)
{4단계에서 작성한 본문}
## 마무리
핵심 요약 2~3줄. `posts/index.json`이 있으면(0-1단계에서 이미 읽었을 것이다) 지금 쓰는 글과
`tags`가 1개 이상 겹치는 기존 글을 찾아 최대 2~3개까지 내부 링크로 건다 — 관련성 없는 글을
억지로 끼워 넣지 않는다. 겹치는 글이 없으면 이 문단은 그냥 생략한다.
```html
<a href="{기존 글 file 경로, 예: ./other-slug.html}" style="color:#3454d1;text-decoration:underline;">{기존 글 title}</a>
연관 글끼리 묶이면 검색엔진이 사이트 전체를 더 신뢰할 만한 자료로 본다.
태그: #태그1 #태그2 ... 카테고리: ... 메타 설명: (150자 이내 요약) 참고: 실제로 참고한 공식 문서·자료 링크
slug는 플랫폼에 따라 글 URL에 그대로 쓰이기도 하므로 한글 대신 핵심 키워드를 영문으로 짧게
옮긴다. 같은 slug의 파일이 이미 있으면 덮어쓰지 말고 새 글인지 기존 글 수정인지 물어본다.
## 5-1단계: 발행 전 SEO 체크리스트
6단계로 넘어가기 전에 조립본을 대상으로 아래 항목을 직접 확인한다. 사람이 눈대중으로 훑는
대신, 셀 수 있는 건 실제로 세어서 확인한다 — `wc -m`이나 `grep -o`로 충분하다. 기준을 벗어나면
바로 고치고, 판단이 필요한 경우(예: 제목을 어떻게 줄일지)만 사용자에게 확인한다.
1. **제목 길이** — 대략 15~60자 권장. 60자를 넘기면 검색 결과 목록에서 뒷부분이 잘릴 수 있다.
넘었으면 핵심 키워드가 앞쪽에 남도록 줄인다.
2. **메타 설명 길이** — 150자를 넘지 않는지 `echo -n "{메타 설명}" | wc -m`로 확인한다.
3단계에서 이미 150자 기준으로 썼어도, 실제로 세어서 확인하지 않으면 종종 넘어가 있다.
3. **핵심 키워드 등장 횟수** — 조립본 전체에서 `grep -o "{핵심 키워드}" 파일 | wc -l`로 센다.
3~5회 범위 밖이면(너무 적으면 검색엔진이 이 글을 그 키워드의 답으로 못 알아보고, 너무
많으면 키워드 스터핑으로 감점된다) 자연스러운 선에서 조정한다 — 문장을 어색하게 만들면서까지
숫자를 맞추지 않는다.
4. **이미지 alt 텍스트** — 4-1단계에서 짤을 넣었다면, `<img alt="...">`가 비어 있지 않고
그 자리에서 무엇을 표현한 짤인지 설명하는지 확인한다.
5. **헤딩 위계** — 본문에 `<h1>`이 없는지 확인한다(SEO 제목은 블로그 입력란에 따로 들어가므로
본문엔 `<h1>` 없이 `<h2>`부터 시작해야 한다 — 6단계 참고).
이 체크리스트를 통과한 조립본만 6단계로 넘긴다.
## 6단계: HTML로 저장 (기본 출력 형식)
**기본 산출물은 HTML이다.** 5단계 조립본을 `posts/{slug}.html`로 저장한다 — 마크다운 모드가
아니라 티스토리 등 블로그의 **HTML 편집 모드**에 그대로 붙여넣는 용도다.
마크다운 파일이 별도로 필요하면(GitHub, 마크다운 에디터를 쓰는 플랫폼 등 사용자가 명시적으로
요청한 경우) 5단계 조립본을 그대로 `posts/{slug}.md`로도 저장한다.
블로그 에디터(티스토리 포함)는 대부분 붙여넣기 시 `<style>` 블록과 외부 스타일시트는 걸러내지만
태그의 `style` 속성은 그대로 보존한다. 그래서 스킨 CSS에 기대지 않고, **모든 요소에 스타일을
직접 인라인으로 박아 넣는다.** 폰트·크기·태그별 인라인 스타일 값, 코드블록 문법 강조, 커스텀
불릿 리스트, 목차 처리, 최상위 `<div>` 래핑 등 구체적인 스타일 명세는 `references/html-style.md`의
"스타일 1"(기본값)을 따른다.
핵심 규칙만 여기서 다시 짚으면: 본문에 `<h1>`은 넣지 않는다(SEO 제목은 블로그의 별도 제목
입력란에 넣게 안내한다 — 5-1단계 헤딩 위계 확인과 이어진다). 조립본 첫 줄 `# {SEO 제목}`은
빼고 나머지만 HTML로 옮긴다.
**제목 보존용 주석**: 완성된 HTML 파일의 맨 첫 줄에, 렌더링에는 영향 없는 HTML 주석으로
제목·slug·작성일을 남긴다 — 본문에 `<h1>`을 안 넣기로 했기 때문에(위 참고), 이렇게라도
기록해두지 않으면 이 글의 SEO 제목이 파일 어디에도 안 남는다. 블로그 에디터에 붙여넣어도
브라우저가 주석을 렌더링하지 않으므로 실제 글에는 보이지 않는다.
```html
<!-- tech-blog-post: title="{SEO 제목}" slug="{slug}" created="{YYYY-MM-DD}" -->
인덱스 갱신: 파일 저장 직후 posts/index.json에 이 글의 항목을 추가한다(파일이 없으면
새로 만든다). 이후 글을 쓸 때 0-1단계(중복 체크)와 5단계(내부 링크 추천)가 이 파일을 읽는다.
{
"slug": "{slug}",
"title": "{SEO 제목}",
"tags": ["태그1", "태그2"],
"category": "{카테고리}",
"meta_description": "{메타 설명}",
"created": "{YYYY-MM-DD}",
"file": "posts/{slug}.html"
}
지켜야 할 것
추측으로 채우지 않는다. 원인이나 해결 과정 중 근거가 불확실한 부분은 "확실하지 않지만"이라고 명시하거나 사용자에게 확인한다. 공개 글에 틀린 정보를 확신하는 어조로 쓰면, 그 글을 보고 따라한 사람에게 실질적인 피해를 준다.
코드는 실제 코드에서 가져온다. 예시를 새로 지어내면 디테일이 뭉개지고, 그 디테일이야말로 검색해서 들어온 사람이 필요로 하는 부분이다.
남이 읽는다는 걸 전제로 쓴다. 프로젝트 내부 약어, 사내 도구 이름, "그때 그거"식 표현을 풀어쓴다. 독자는 이 문제의 배경을 전혀 모르는 상태로 검색해서 들어온다.
일기가 아니라 정보다. 그날의 기분이나 개인적 소회는 배움과 직접 연결되지 않으면 뺀다. 독자가 얻어가는 건 감상이 아니라 재현 가능한 해결책이다.
키워드보다 문장이 먼저. 검색엔진 최적화는 자연스러운 문장 안에서 이뤄져야 한다. 키워드를 억지로 반복해 넣느니 못 채운 자리를 비워두는 게 낫다.
사용자의 언어를 따른다. 한국어로 요청하면 한국어로, 영어면 영어로 쓴다.
문장은 짧고 힘 있게. 5단계에서 elements-of-style의 writing-clearly-and-concisely로
다듬는 것과 별개로, 초안을 쓰는 단계부터 늘어지는 문장·군더더기 수식어·수동태를 피한다.
독자는 끝까지 읽어야 검색엔진도 그 글을 좋은 답으로 인식한다 — 문장이 늘어지면 이탈이 빨라진다.