[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -2,92 +2,227 @@
|
||||
id: wiki-2026-0508-seo-중심의-마케팅-및-블로그-사이트-구축
|
||||
title: SEO 중심의 마케팅 및 블로그 사이트 구축
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: []
|
||||
aliases: [seo-marketing-site, blog-site-construction]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.92
|
||||
tags: [uncategorized]
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [seo, marketing-site, blog, ssg, frontend, next-js, astro]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-08
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
language: typescript
|
||||
framework: astro-next-js
|
||||
---
|
||||
|
||||
# [[SEO 중심의 마케팅 및 블로그 사이트 구축]]
|
||||
# SEO 중심의 마케팅 및 블로그 사이트 구축
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
SEO 중심의 마케팅 및 블로그 사이트 구축은 검색 엔진 가시성과 빠른 초기 콘텐츠 로딩 속도를 최우선으로 고려하는 렌더링 전략이 필요합니다. 검색 엔진 크롤러가 페이지의 내용을 즉시 수집할 수 있도록 완성된 HTML을 제공하는 서버 사이드 렌더링(SSR)이나 정적 사이트 생성(SSG) 방식이 필수적입니다. 반면, 자바스크립트 실행 전까지 빈 화면을 제공하는 클라이언트 사이드 렌더링(CSR)은 SEO에 불리하므로, 최적의 사용자 경험과 검색 랭킹을 달성하기 위해서는 프로젝트 성격에 맞는 사전 렌더링(Pre-rendering) 및 하이브리드 접근법을 채택해야 합니다.
|
||||
## 매 한 줄
|
||||
> **"매 organic search 의 의 LCP < 2.5s + crawlability + structured data + content velocity 의 four-pillar 의 site architecture."**. 2026 의 의 SEO-first build 의 의 default stack 의 Astro / Next.js (SSG) + MDX content + Schema.org JSON-LD + Core Web Vitals optimization — 매 GEO (Generative Engine Optimization, AI overview) 의 등장 의 의 traditional SEO 의 augment.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
* **SEO와 렌더링의 관계:** 검색 엔진은 크롤링, 렌더링, 인덱싱의 과정을 거쳐 웹 페이지를 분석합니다. 검색 엔진 봇이 자바스크립트를 실행하는 과정을 기다리지 않고도 콘텐츠, 메타 태그, 구조화된 데이터를 즉시 파악할 수 있도록 서버에서 완성된 형태의 HTML을 제공하는 것이 SEO 및 검색 랭킹 향상의 핵심입니다 [1-3].
|
||||
* **마케팅 사이트 및 블로그를 위한 정적 사이트 생성(SSG):** SSG는 빌드 시점에 모든 페이지의 HTML 파일을 미리 렌더링하여 CDN을 통해 즉각적으로 제공하는 방식입니다 [4, 5]. 변경이 자주 일어나지 않는 블로그 포스트, 문서 페이지, 랜딩 페이지 및 마케팅 웹사이트에 가장 이상적이며, 초고속 로딩 성능과 탁월한 SEO 역량을 제공하여 리드 생성과 고객 확보에 매우 유리합니다 [6-8].
|
||||
* **콘텐츠가 풍부한 사이트를 위한 서버 사이드 렌더링(SSR):** SSR은 사용자의 요청이 있을 때마다 서버에서 HTML을 생성하여 브라우저에 전달합니다 [9, 10]. 항상 최신 상태의 데이터가 반영되어야 하는 뉴스 플랫폼이나 콘텐츠 중심의 웹사이트에 적합하며, 빠른 초기 콘텐츠 페인트(FCP)와 즉각적인 검색 엔진 가시성을 확보할 수 있습니다 [3, 11-13].
|
||||
* **성능과 최신성 균형을 위한 점진적 정적 재생성(ISR):** 대규모 블로그나 콘텐츠 사이트의 경우, ISR을 활용할 수 있습니다. 이는 사전 생성된 정적 페이지의 빠른 로딩 속도를 유지하면서도 백그라운드에서 지정된 주기에 따라 페이지를 재생성하므로, 성능과 콘텐츠 최신성이라는 두 마리 토끼를 모두 잡을 수 있습니다 [14-16].
|
||||
* **클라이언트 사이드 렌더링(CSR)의 한계와 하이브리드 접근:** CSR은 초기 로드 시 빈 HTML 셸과 자바스크립트 리소스만 제공하므로 검색 엔진 크롤러가 콘텐츠를 놓치거나 인덱싱이 지연될 수 있어 순수 마케팅 사이트에는 부적합합니다 [17-20]. 하지만 [[Next.js]]와 같은 최신 프레임워크를 사용하면, 메인 홈페이지나 블로그 글에는 SSG나 SSR을 적용해 SEO를 챙기고, 댓글 섹션이나 개인화된 대시보드같이 상호작용이 중요한 부분에는 CSR을 적용하는 하이브리드(Hybrid) 렌더링 방식을 채택하여 페이지별로 렌더링 전략을 최적화할 수 있습니다 [21-23].
|
||||
## 매 핵심
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Server-Side Rendering (SSR)]], [[Static Site Generation (SSG)]], Incremental Static Regeneration (ISR), [[Client-Side Rendering (CSR)]]
|
||||
- **Projects/Contexts:** Next.js 기반 하이브리드 렌더링 프레임워크 도입, 대규모 콘텐츠 플랫폼 구조 설계
|
||||
- **Contradictions/Notes:** 소스에 따르면, CSR 방식은 앱과 같은 동적이고 매끄러운 상호작용을 제공하는 데는 유리하지만, SEO 최적화 측면에서는 빈 페이지 인식으로 인한 크롤링 지연 및 인덱싱 누락 위험이라는 치명적인 단점이 존재합니다. 따라서 SEO가 필수적인 마케팅 및 블로그 사이트에서는 반드시 SSR이나 SSG를 주력으로 사용하거나 병행해야 합니다.
|
||||
### 매 4-pillar
|
||||
1. **Crawlability**: server-rendered HTML, sitemap, robots.txt, canonical URLs, hreflang.
|
||||
2. **Performance**: LCP < 2.5s, INP < 200ms, CLS < 0.1 — Core Web Vitals 의 ranking factor.
|
||||
3. **Content**: depth, freshness, E-E-A-T (Experience, Expertise, Authoritativeness, Trust).
|
||||
4. **Structure**: Schema.org JSON-LD, OpenGraph, semantic HTML, internal linking.
|
||||
|
||||
### 매 stack 선택
|
||||
- **Astro**: content-heavy, Islands architecture, minimal JS — best LCP.
|
||||
- **Next.js (App Router, SSG mode)**: hybrid 가능, MDX support, vast ecosystem.
|
||||
- **Hugo / 11ty**: pure SSG, sub-second build, no JS runtime.
|
||||
- **WordPress (headless)**: editorial workflow + Astro/Next frontend.
|
||||
|
||||
### 매 2026 GEO consideration
|
||||
- AI overview (Google SGE, Perplexity, ChatGPT search) 의 citation 의 desired — clear `<h1>`, summary paragraph, bulleted facts, schema markup.
|
||||
- LLM-friendly: clean semantic HTML, llms.txt 의 publishing.
|
||||
|
||||
### 매 응용
|
||||
1. SaaS marketing site (homepage + features + pricing + blog).
|
||||
2. Tech blog with MDX + code highlighting.
|
||||
3. Documentation site (Mintlify, Nextra, Starlight).
|
||||
4. Local business + multi-region landing pages.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### Astro 의 blog setup
|
||||
```astro
|
||||
---
|
||||
*Last updated: 2026-04-25*
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
|
||||
- **과거 데이터와의 충돌:** 없음
|
||||
- **정책 변화:** 없음
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
// src/pages/blog/[slug].astro
|
||||
import { getCollection } from 'astro:content';
|
||||
import Layout from '@/layouts/Article.astro';
|
||||
export async function getStaticPaths() {
|
||||
const posts = await getCollection('blog');
|
||||
return posts.map((post) => ({ params: { slug: post.slug }, props: { post } }));
|
||||
}
|
||||
const { post } = Astro.props;
|
||||
const { Content } = await post.render();
|
||||
---
|
||||
<Layout
|
||||
title={post.data.title}
|
||||
description={post.data.description}
|
||||
canonical={`https://site.com/blog/${post.slug}`}
|
||||
ogImage={post.data.ogImage}
|
||||
>
|
||||
<article>
|
||||
<h1>{post.data.title}</h1>
|
||||
<Content />
|
||||
</article>
|
||||
</Layout>
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### JSON-LD (Article schema)
|
||||
```tsx
|
||||
// components/ArticleSchema.tsx
|
||||
export function ArticleSchema({ post }: { post: Post }) {
|
||||
return (
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify({
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Article',
|
||||
headline: post.title,
|
||||
datePublished: post.publishedAt,
|
||||
dateModified: post.updatedAt,
|
||||
author: { '@type': 'Person', name: post.author },
|
||||
image: post.ogImage,
|
||||
}),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
### Sitemap (Next.js App Router)
|
||||
```ts
|
||||
// app/sitemap.ts
|
||||
import type { MetadataRoute } from 'next';
|
||||
import { getAllPosts } from '@/lib/posts';
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
||||
const posts = await getAllPosts();
|
||||
return [
|
||||
{ url: 'https://site.com', lastModified: new Date(), priority: 1 },
|
||||
...posts.map((p) => ({
|
||||
url: `https://site.com/blog/${p.slug}`,
|
||||
lastModified: p.updatedAt,
|
||||
changeFrequency: 'monthly' as const,
|
||||
priority: 0.7,
|
||||
})),
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### Robots + canonical (Next.js metadata)
|
||||
```ts
|
||||
// app/blog/[slug]/page.tsx
|
||||
export async function generateMetadata({ params }): Promise<Metadata> {
|
||||
const post = await getPost(params.slug);
|
||||
return {
|
||||
title: post.title,
|
||||
description: post.summary,
|
||||
alternates: { canonical: `/blog/${post.slug}` },
|
||||
openGraph: {
|
||||
title: post.title,
|
||||
description: post.summary,
|
||||
images: [post.ogImage],
|
||||
type: 'article',
|
||||
},
|
||||
twitter: { card: 'summary_large_image' },
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
### LCP 최적화 (preload hero image)
|
||||
```html
|
||||
<link rel="preload" as="image" href="/hero.avif" fetchpriority="high" />
|
||||
<img src="/hero.avif" alt="..." width="1200" height="630" loading="eager" decoding="async" />
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### MDX + content collection (Astro)
|
||||
```ts
|
||||
// src/content/config.ts
|
||||
import { defineCollection, z } from 'astro:content';
|
||||
|
||||
export const collections = {
|
||||
blog: defineCollection({
|
||||
type: 'content',
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
description: z.string().max(160),
|
||||
publishedAt: z.date(),
|
||||
author: z.string(),
|
||||
tags: z.array(z.string()),
|
||||
ogImage: z.string().optional(),
|
||||
}),
|
||||
}),
|
||||
};
|
||||
```
|
||||
|
||||
### llms.txt (2026 GEO)
|
||||
```txt
|
||||
# https://site.com/llms.txt
|
||||
# Site: Acme Inc. — SaaS for X
|
||||
# License: CC-BY-4.0 for blog content
|
||||
# Index:
|
||||
- /blog/* — engineering articles
|
||||
- /docs/* — product documentation
|
||||
- /pricing — current pricing
|
||||
```
|
||||
|
||||
### CWV 의 monitoring (Vercel Speed Insights / web-vitals)
|
||||
```ts
|
||||
import { onLCP, onINP, onCLS } from 'web-vitals';
|
||||
|
||||
function send(metric: any) {
|
||||
navigator.sendBeacon('/api/vitals', JSON.stringify(metric));
|
||||
}
|
||||
onLCP(send);
|
||||
onINP(send);
|
||||
onCLS(send);
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Stack |
|
||||
|---|---|
|
||||
| Pure content / blog | **Astro** (Islands, near-zero JS) |
|
||||
| Marketing + app shell | **Next.js (App Router, SSG/ISR)** |
|
||||
| Editorial team (CMS) | **Headless WP / Sanity + Astro** |
|
||||
| Docs site | **Starlight / Nextra / Mintlify** |
|
||||
| Multi-region SEO | Next.js + i18n routing + hreflang |
|
||||
|
||||
**기본값**: Astro + MDX + Vercel/Netlify deploy + Sanity/Contentlayer (if CMS needed).
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[SEO]] · [[Static-Site-Generation]] · [[Frontend-Architecture]]
|
||||
- 변형: [[Headless-CMS-Architecture]] · [[Documentation-Site]]
|
||||
- 응용: [[Astro]] · [[Next-js-App-Router]] · [[MDX]] · [[Hugo]]
|
||||
- Adjacent: [[Core-Web-Vitals]] · [[Schema-org]] · [[GEO-AI-Search]] · [[Sitemap]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: marketing site, blog, docs, public-facing SEO-critical content, GEO optimization.
|
||||
**언제 X**: authenticated app (SPA), real-time UI (SPA/SSR), no SEO requirement.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **SPA 의 marketing site**: crawlable HTML 의 부재 — SSG/SSR 의 mandatory.
|
||||
- **Render-blocking JS / fonts**: LCP 의 destroy — `font-display: swap`, defer non-critical JS.
|
||||
- **Image 의 dimensions 의 unspecified**: CLS regression — `width`/`height` 의 항상 의 specify.
|
||||
- **Duplicate content 의 canonical 의 부재**: SEO penalty — `<link rel="canonical">` 의 필수.
|
||||
- **Schema.org 없음**: rich result + AI overview citation 의 lose — JSON-LD 의 add.
|
||||
- **Sitemap 의 stale**: ISR / on-demand revalidate or build-time regenerate.
|
||||
- **GEO ignore**: AI search traffic 의 2026 의 surge — llms.txt + clear semantic HTML.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (Google Search Central, web.dev CWV, Astro/Next.js 2026 docs, llms.txt spec).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — full 2026 SEO playbook with GEO + Astro/Next stack |
|
||||
|
||||
Reference in New Issue
Block a user