Skip to content

์‡ผ์ผ€์ด์Šค ํŽ˜์ด์ง€ ๊ตฌํ˜„ (DS-02 ์‹œ์•ˆ ๊ธฐ๋ฐ˜)ย #29

Description

@hyoseong1994

๋ฐฐ๊ฒฝ

DaleUI๋ฅผ ์‚ฌ์šฉ ์ค‘์ธ ์‚ฌ๋ก€๋ฅผ ๊ธฐ์—ฌ์ž๊ฐ€ ์ž๊ธฐ ํ”„๋กœ์ ํŠธ URL๋งŒ ๋“ฑ๋กํ•˜๋ฉด, ๊ทธ URL์˜ Open Graph(OG) ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ์ถ”์ถœํ•ด ์นด๋“œ ํ˜•ํƒœ๋กœ ๊ทธ๋ ค์ฃผ๋Š” ์‡ผ์ผ€์ด์Šค ํŽ˜์ด์ง€๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ ์Šคํ‚ค๋งˆ๋Š” DS-02(#1025) ์‹œ์•ˆ์˜ ์นด๋“œ props์—์„œ ๋„์ถœํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰ OG๋Š” ๊ธฐ์—ฌ์ž๊ฐ€ ์†์œผ๋กœ ์ฑ„์šฐ๋Š” ์ž…๋ ฅ ํผ์ด ์•„๋‹ˆ๋ผ, URL์—์„œ ๊ธ์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ ์†Œ์Šค์ž…๋‹ˆ๋‹ค. ๊ธฐ์—ฌ ์ง„์ž… ์žฅ๋ฒฝ์„ ๋‚ฎ์ถ”๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

๋™์ž‘ ๋ฐฉ์‹ (๋นŒ๋“œ ํƒ€์ž„ ์ถ”์ถœ)

๊ธฐ์—ฌ์ž: showcase ๋ชฉ๋ก์— { url } ๋“ฑ๋ก (PR)
   โ†“  (predev/prebuild)
๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ: ๊ฐ url์„ fetch โ†’ <head>์˜ og:* / twitter:* ํŒŒ์‹ฑ โ†’ JSON ์บ์‹œ๋กœ ์ €์žฅ
   โ†“
๋ผ์šฐํŠธ loader: ์ƒ์„ฑ๋œ JSON๋งŒ ์ฝ์–ด ์นด๋“œ ๋ Œ๋”๋ง (๋Ÿฐํƒ€์ž„ ์™ธ๋ถ€ fetch ์—†์Œ)

๊ธฐ์กด scripts/generate-og.mts(๋นŒ๋“œ ํƒ€์ž„์— ๊ฒฐ์ •์  ์‚ฐ์ถœ๋ฌผ์„ public/์— ์ƒ์„ฑ)์™€ ๋™์ผํ•œ ์ฒ ํ•™์ž…๋‹ˆ๋‹ค. ์ •์  ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ ๋Ÿฐํƒ€์ž„ CORSยทํƒ€์ž„์•„์›ƒยท์‹คํŒจ ์ฒ˜๋ฆฌ ๋ถ€๋‹ด์ด ์—†์Šต๋‹ˆ๋‹ค.

ํŠธ๋ ˆ์ด๋“œ์˜คํ”„: ๋Œ€์ƒ ์‚ฌ์ดํŠธ๊ฐ€ OG๋ฅผ ๋ฐ”๊ฟ”๋„ ์žฌ๋นŒ๋“œ ์ „๊นŒ์ง€ ๋ฐ˜์˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์Šคํ‚ค๋งˆ์— ์ˆ˜๋™ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•„๋“œ์™€ fallback ๊ธฐ๋ณธ๊ฐ’์„ ํ•จ๊ป˜ ๋‘ก๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ์Šคํ‚ค๋งˆ

src/content/showcase/schema.ts์— zod๋กœ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์—ฌ์ž ์ž…๋ ฅ์€ ์ตœ์†Œํ™”ํ•˜๊ณ , ๋‚˜๋จธ์ง€๋Š” ๋นŒ๋“œ ํƒ€์ž„์— ์ฑ„์›๋‹ˆ๋‹ค.

๊ธฐ์—ฌ์ž ์ž…๋ ฅ (frontmatter)

ํ•„๋“œ ํƒ€์ž…/์ œ์•ฝ ํ•„์ˆ˜ ์„ค๋ช…
url string.url() โœ… ํ”„๋กœ์ ํŠธ URL. OG ์ถ”์ถœ ๋Œ€์ƒ
title string.optional() ์ˆ˜๋™ ์˜ค๋ฒ„๋ผ์ด๋“œ. ์—†์œผ๋ฉด og:title ์‚ฌ์šฉ
description string.optional() ์ˆ˜๋™ ์˜ค๋ฒ„๋ผ์ด๋“œ. ์—†์œผ๋ฉด og:description ์‚ฌ์šฉ
image string.optional() ์ˆ˜๋™ ์˜ค๋ฒ„๋ผ์ด๋“œ. ์—†์œผ๋ฉด og:image ์‚ฌ์šฉ

๋นŒ๋“œ ํƒ€์ž„์— ์ถ”์ถœยท๋ณ‘ํ•ฉ๋˜๋Š” ๊ฐ’

๊ฐ ์นด๋“œ๊ฐ€ ์‹ค์ œ๋กœ ๊ทธ๋ฆด ๊ฐ’์€ ์ˆ˜๋™ ์˜ค๋ฒ„๋ผ์ด๋“œ ?? OG ์ถ”์ถœ๊ฐ’ ?? fallback ์ˆœ์œผ๋กœ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

์นด๋“œ ํ•„๋“œ ์†Œ์Šค
title frontmatter.title ?? og:title ?? URL ํ˜ธ์ŠคํŠธ๋ช…
description frontmatter.description ?? og:description ?? ""
image frontmatter.image ?? og:image ?? ๊ธฐ๋ณธ ํ”Œ๋ ˆ์ด์Šคํ™€๋” ์ด๋ฏธ์ง€
siteName og:site_name ?? URL ํ˜ธ์ŠคํŠธ๋ช…
url frontmatter.url (๊ทธ๋Œ€๋กœ)

์ž‘์—… ๋‚ด์šฉ

  • OG ํŒŒ์‹ฑ ๋ฐฉ์‹ ๊ฒฐ์ • (์˜์กด์„ฑ ์ถ”๊ฐ€: ์˜ˆ open-graph-scraper/metascraper/cheerio, ๋˜๋Š” ๊ฒฝ๋Ÿ‰ ์ •๊ทœ์‹ ํŒŒ์„œ). ํ˜„์žฌ ๋ ˆํฌ์—” OG ํŒŒ์„œ ์˜์กด์„ฑ ์—†์Œ
  • ๋นŒ๋“œ ์Šคํฌ๋ฆฝํŠธ ์‹ ์„ค/ํ™•์žฅ: ๋“ฑ๋ก๋œ url ๋ชฉ๋ก์„ fetch โ†’ OG ํŒŒ์‹ฑ โ†’ public/og/showcase.json(๋˜๋Š” ์ฝ˜ํ…์ธ  ์บ์‹œ)๋กœ ์ €์žฅ. generate-og.mts์˜ manifest ํ•ด์‹œ ์บ์‹œ ํŒจํ„ด ์ฐธ๊ณ 
  • fetch ์‹คํŒจยทOG ๋ˆ„๋ฝ ์‹œ fallback ์ฒ˜๋ฆฌ (๋นŒ๋“œ๋Š” ๊นจ์ง€์ง€ ์•Š๊ฒŒ, ๊ธฐ๋ณธ ์นด๋“œ๋กœ ๋Œ€์ฒด)
  • src/content/showcase/schema.ts zod ์Šคํ‚ค๋งˆ ์ •์˜ (์œ„ ํ‘œ)
  • ์‡ผ์ผ€์ด์Šค ๋ชฉ๋ก ๋ผ์šฐํŠธ(showcase._index.tsx)๋ฅผ ์‹ค์ œ ๊ตฌํ˜„์œผ๋กœ ๊ต์ฒด (ํ˜„์žฌ UnderConstruction) โ€” ์นด๋“œ ๊ทธ๋ฆฌ๋“œ
  • ์นด๋“œ ์ปดํฌ๋„ŒํŠธ (DS-02 ์‹œ์•ˆ ๊ธฐ๋ฐ˜, ์ธ๋„ค์ผยท์ œ๋ชฉยท์„ค๋ช…ยท์™ธ๋ถ€ ๋งํฌ)
  • ํŽ˜์ด์ง€ ์ž์ฒด์˜ SEO ๋ฉ”ํƒ€๋Š” ๊ธฐ์กด SeoMeta ์žฌ์‚ฌ์šฉ (showcase ์ •์  OG ์ด๋ฏธ์ง€)
  • ๋ฐ˜์‘ํ˜•ยท์ด๋ฏธ์ง€ ์ตœ์ ํ™” (์™ธ๋ถ€ og:image ๋กœ๋”ฉ ์‹คํŒจ/์‚ฌ์ด์ฆˆ ๋Œ€๋น„)

์ฐธ๊ณ 

  • ๋นŒ๋“œ ํƒ€์ž„ ์‚ฐ์ถœ๋ฌผ ์ƒ์„ฑ ํŒจํ„ด: scripts/generate-og.mts (manifest ํ•ด์‹œ ์บ์‹œ)
  • SEO ๋ฉ”ํƒ€ ์ปดํฌ๋„ŒํŠธ: src/components/SeoMeta.tsx, OG URL ํ—ฌํผ: src/og/ogImage.ts
  • ์žฌ์‚ฌ์šฉํ•  ์ฝ˜ํ…์ธ  ์ปฌ๋ ‰์…˜ ํŒจํ„ด: src/content/blog/{schema,loader}.ts
  • ํ˜„์žฌ ํ”Œ๋ ˆ์ด์Šคํ™€๋”: src/routes/showcase._index.tsx

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

Status
In Progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions