(01) OpenClaw를 사용한 개인 홈페이지 개발기 — 설계
에이전트 주도 워크플로(OpenClaw)로 개인 홈페이지를 설계한 과정을 기록합니다. 동기, 하이브리드 SSG+D1 아키텍처, 디자인-퍼스트 프로세스까지.
TL;DR
- 동기: “내 글을 내 인프라에서, 내 방식으로 서빙하고 싶다.”
- OpenClaw: 에이전트가 문서를 읽고, 태스크를 쪼개고, PR을 열고, 리뷰까지 돌리는 워크플로.
- 하이브리드 아키텍처: 콘텐츠는 SSG(Astro), 동적 데이터는 D1+KV — 둘을 깔끔하게 분리.
- 디자인-퍼스트: 코드를 치기 전에 디자인 가이드를 먼저 확정하고, 리뷰를 거친 뒤 구현에 들어간다.
1) 왜 개인 홈페이지를 직접 만드는가
블로그 플랫폼은 많다. Medium, Velog, Notion 퍼블리시, Substack… 그런데 어느 순간 이런 생각이 들었다.
- 플랫폼이 사라지면 내 글도 사라진다.
- 디자인을 내 취향대로 바꿀 수 없다.
- 댓글·반응·조회수 같은 동적 기능을 원하는 대로 붙일 수 없다.
- 무엇보다, 개발자라면 자기 홈페이지 하나쯤은 직접 굴릴 줄 알아야 하지 않나.
그래서 목표를 이렇게 잡았다.
Git에 마크다운을 커밋하면 블로그가 되고, 동적 기능(댓글·좋아요·조회수)은 엣지 DB로 붙이고, 전체 파이프라인을 에이전트가 돌린다.
2) OpenClaw: 에이전트 주도 개발 워크플로
혼자서 홈페이지를 만들면 가장 큰 병목은 컨텍스트 스위칭이다. 디자인하다가 API 짜다가 배포 설정하다가… 멀티태스킹의 늪에 빠지기 쉽다.
OpenClaw는 이 문제를 문서 기반 에이전트 오케스트레이션으로 해결한다.
핵심 구조
TODO.md ← 지금 할 일(AUTO_NOW), 대기(PENDING_CHAIN), 사용자 승인(WITH_USER)
SESSIONS.md ← 실행 세션 추적 (implement / review / design / deploy)
tasks/*.md ← 태스크 단위 체크리스트 + 완료 조건
에이전트는 이 문서들을 **단일 진실(Single Source of Truth)**로 삼고 동작한다.
실제 흐름
- 태스크 문서 작성: 무엇을, 왜, 어디까지 할 것인지 정의
- 에이전트 실행: Claude Code 세션이 태스크를 읽고 구현 시작
- PR 생성: 변경사항을 feature 브랜치로 올리고 PR 오픈
- 독립 리뷰: 별도 세션(OpenClaw 서브에이전트)이 PR을 리뷰
- 머지: 리뷰 통과 후 dev → main으로 단계적 머지
중요한 건 DONE의 정의다.
코드를 짰다고 끝이 아니라, REVIEW:done까지가 DONE이다.
이 규칙이 있어야 “PR은 열려 있는데 다음 작업으로 넘어가버리는” 상태를 방지할 수 있다.
worktree-per-task 전략
병렬로 여러 태스크를 돌릴 때 가장 큰 문제는 git checkout 충돌이다.
그래서 태스크 1개 = 브랜치 1개 = worktree 1개 원칙을 세웠다.
feature/floating-bg → /tmp/ys-floating-bg
feature/blog-tags → /tmp/ys-blog-tags
이 방식으로 Claude Code 5세션을 동시에 굴려도 서로 간섭하지 않는다.
3) 하이브리드 SSG + D1 아키텍처
개인 홈페이지의 데이터는 크게 두 종류다.
| 구분 | 특성 | 저장소 |
|---|---|---|
| 콘텐츠 | 글, 포트폴리오 — Git 히스토리가 중요 | Astro Content Collections (MD/MDX) |
| 동적 데이터 | 댓글, 좋아요, 조회수 — 실시간 쓰기 필요 | Cloudflare D1 + KV |
이 둘을 섞지 않는 게 핵심이다.
콘텐츠 레이어 (SSG)
- Astro의 Content Collections로 마크다운을 관리
- 빌드 타임에 정적 HTML 생성 → Cloudflare Pages로 서빙
- 빠르고, 안정적이고, Git으로 버전 관리
동적 레이어 (D1 + KV)
블로그 글에 달리는 댓글, 좋아요, 조회수 같은 데이터는 DB가 필요하다. 하지만 풀 백엔드를 올리면 오버킬이니까, Cloudflare Workers + D1을 선택했다.
데이터 모델 요약:
posts— SSG 콘텐츠와 DB를 연결하는 인덱스 테이블comments— 댓글 (moderation 상태 관리 포함)reaction_events+reaction_counts— 좋아요 등 반응view_events_daily— 일별 조회수 집계
동기화 전략:
DB에 블로그 글 전체를 복제하지 않는다.
posts 테이블에는 slug, title, published_at 같은 최소 메타데이터만 동기화하고,
실제 콘텐츠는 항상 SSG가 진실이다.
API 설계
GET /api/engagement/v1/posts/:postId ← 카운터 조회
GET /api/engagement/v1/posts/:postId/comments ← 댓글 목록
POST /api/engagement/v1/posts/:postId/view ← 조회수 기록
POST /api/engagement/v1/posts/:postId/reactions ← 반응 기록
POST /api/engagement/v1/posts/:postId/comments ← 댓글 작성 (Turnstile 보호)
Phase 1(Thin MVP)에서는 조회수·반응·기본 댓글만 구현하고, Phase 2에서 모더레이션·인기글 집계, Phase 3에서 Durable Objects를 통한 스케일링으로 점진 확장한다.
4) 디자인-퍼스트 프로세스
“코드부터 짜고 나중에 디자인을 맞추자”는 접근은 항상 부채를 남긴다. 이 프로젝트에서는 디자인 가이드를 먼저 확정하고, 리뷰를 거친 뒤에 구현하는 순서를 지킨다.
디자인 가이드의 구조
각 UI 컴포넌트마다 디자인 가이드 문서를 작성한다.
# Component Design Guide
## 1. Non-goals ← 하지 않을 것을 명확히
## 2. Layout ← 구조적 제약
## 3. Visual Style ← 색상, 대비, 타이포
## 4. Motion ← 애니메이션 파라미터
## 5. Tokens ← CSS 변수 (디자인 ↔ 코드 브릿지)
## 6. Implementation ← CSS-only / Canvas / WebGL 선택지와 트레이드오프
## 7. Checklist ← 검증 기준
왜 이렇게까지 하는가
- Non-goals: “이건 안 한다”를 먼저 못 박으면 스코프 크리프를 줄일 수 있다.
- 토큰화:
--bg-opacity: 0.12같은 CSS 변수로 디자인 의도를 코드에 직접 매핑한다. 디자인 문서와 코드 사이의 간극이 줄어든다. - 체크리스트: 접근성(
prefers-reduced-motion), CLS 방지, 퍼포먼스 기준을 구현 전에 정의한다.
실제 사례: 플로팅 배경
홈페이지의 배경 효과를 만들 때, 먼저 127줄짜리 디자인 가이드를 작성했다.
- 레이아웃:
position: fixed; inset: 0— 콘텐츠 아래 고정 - 마스킹: 중앙 클리어 존 + 가장자리 페이드
- 모션: 18–60초 주기, 최소 진폭
- 접근성:
prefers-reduced-motion시 정적 렌더
이 가이드를 독립 리뷰 세션에서 검증한 뒤 구현에 들어갔다. 결과적으로 “구현했는데 느낌이 다르네, 다시 하자” 같은 루프를 거의 없앨 수 있었다.
5) 여기까지의 교훈
| 원칙 | 왜 |
|---|---|
| 문서가 곧 실행 | 에이전트가 읽을 수 있어야 자동화가 된다 |
| 콘텐츠와 데이터를 분리 | 각각 최적의 저장소를 쓸 수 있다 |
| DONE = REVIEW:done | ”코드 짰다”와 “끝났다”는 다른 말이다 |
| 디자인 가이드 → 리뷰 → 구현 | 재작업 루프를 줄이고 품질을 올린다 |
| worktree-per-task | 병렬 작업 시 충돌을 구조적으로 차단 |
6) 다음: 구현으로
설계는 끝났다. 다음 글에서는 실제 구현 과정을 다룬다.
- Astro 프로젝트 셋업과 Content Collections 설정
- Cloudflare Pages + D1 배포 파이프라인
- 디자인 가이드에서 코드로의 변환 과정
- 에이전트가 실제로 PR을 열고 리뷰하는 모습
이 글은 OpenClaw 에이전트 워크플로로 작성·리뷰되었습니다.