๐Ÿ’ญ Minji's Archive

[Side Project] ๐Ÿช„ Velog ๊ธ€์„ ์ž๋™์œผ๋กœ GitHub Pages ๋ธ”๋กœ๊ทธ๋กœ ๋™๊ธฐํ™”ํ•˜๊ธฐ (with Jekyll + GitHub Actions) + Discord ์•Œ๋ฆผ๊นŒ์ง€ ์ „์†กํ•˜๊ธฐ!

October 28, 2025

๋‚ด๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ์ž‘์„ฑํ•œ ๊ฐœ๋ฐœ ๋ธ”๋กœ๊ทธ + ํฌํŠธํด๋ฆฌ์˜ค + ๊ธฐํƒ€ ๋‚ด ์†Œ๊ฐœ๋ฅผ ํ•œ ๊ณณ์—์„œ ๋ณด์—ฌ์ฃผ๊ณ  ์‹ถ์–ด์„œ Jekyll ๋ธ”๋กœ๊ทธ๋ฅผ ๋งŒ๋“ค์–ด์•ผ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Velog์— ์˜ฌ๋ฆฐ ๊ธ€์ด ์ž๋™์œผ๋กœ ๋‚ด ๊ฐœ์ธ ๋ธ”๋กœ๊ทธ(GitHub Pages)์— ๋ฐ˜์˜๋œ๋‹ค๋ฉด ์–ด๋–จ๊นŒ? ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” Velog โ†’ Jekyll โ†’ GitHub Pages ์ž๋™ ๋ฐฐํฌ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ณธ ๊ณผ์ •์„ ์ •๋ฆฌํ–ˆ๋‹ค. ํ•œ ๋ฒˆ ์„ค์ •ํ•˜๋ฉด ์ดํ›„์—” Velog์— ๊ธ€์„ ์˜ฌ๋ฆฌ๋Š” ๊ฒƒ๋งŒ์œผ๋กœ ๋ธ”๋กœ๊ทธ๊ฐ€ ์ž๋™ ๊ฐฑ์‹ ๋œ๋‹ค.

๐Ÿ“Œ ๋ชฉํ‘œ ๊ตฌ์กฐ Velog โ†’ (RSS ํŒŒ์‹ฑ) โ†ณ Python ๋ณ€ํ™˜ ์Šคํฌ๋ฆฝํŠธ (์ด๋ฏธ์ง€ ํฌํ•จ) โ†ณ GitHub Push โ†ณ GitHub Actions โ†’ Jekyll ๋นŒ๋“œ & ๋ฐฐํฌ

โš™๏ธ 1. Jekyll ๋ธ”๋กœ๊ทธ ์ดˆ๊ธฐ ์„ธํŒ…

๋จผ์ € GitHub Pages์šฉ Jekyll ๋ธ”๋กœ๊ทธ๋ฅผ ์ƒ์„ฑํ–ˆ๋‹ค.

gem install jekyll bundler
jekyll new myblog
cd myblog
bundle exec jekyll serve

๋กœ์ปฌ ์„œ๋ฒ„(http://127.0.0.1:4000/)์—์„œ ํ…Œ๋งˆ์™€ ๊ตฌ์„ฑ์„ ํ™•์ธํ•œ ๋’ค, aneomagig.github.io๋ผ๋Š” GitHub ์ €์žฅ์†Œ๋ฅผ ๋งŒ๋“ค์–ด ์—ฐ๊ฒฐํ–ˆ๋‹ค.

git init
git remote add origin https://github.com/aneomagig/aneomagig.github.io
git branch -M main
git push -u origin main

๐Ÿงฉ 2. Velog ๊ธ€์„ ์ž๋™์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” Python ์Šคํฌ๋ฆฝํŠธ ์ž‘์„ฑ

Velog๋Š” RSS ํ”ผ๋“œ๋ฅผ ์ œ๊ณตํ•˜๋ฏ€๋กœ, ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํฌ์ŠคํŠธ๋ฅผ Markdown์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

import feedparser, os, re, requests
from bs4 import BeautifulSoup
from datetime import datetime

USERNAME = "hosooinmymind"
RSS_URL = f"https://v2.velog.io/rss/@{USERNAME}"
POSTS_DIR = "_posts"
IMG_DIR = f"assets/images/{USERNAME}"
HEADERS = {"User-Agent": "Mozilla/5.0", "Referer": "https://velog.io/"}

os.makedirs(POSTS_DIR, exist_ok=True)
os.makedirs(IMG_DIR, exist_ok=True)

feed = feedparser.parse(RSS_URL)

for entry in feed.entries:
    title = entry.title.strip()
    slug = re.sub(r'[^a-zA-Z0-9๊ฐ€-ํžฃ]+', '-', title).strip('-')
    date_parsed = datetime(*entry.published_parsed[:6])
    date_filename = date_parsed.strftime("%Y-%m-%d")
    date_str = date_parsed.strftime("%Y-%m-%d %H:%M:%S +0900")

    filename = f"{POSTS_DIR}/{date_filename}-{slug}.md"
    soup = BeautifulSoup(entry.description, "html.parser")

    # ์ด๋ฏธ์ง€ ๋กœ์ปฌ ์ €์žฅ
    for img in soup.find_all("img"):
        img_url = img.get("src")
        if not img_url or not img_url.startswith("http"):
            continue
        rel_path = img_url.split("https://velog.velcdn.com/")[-1]
        local_path = os.path.join(IMG_DIR, rel_path)
        os.makedirs(os.path.dirname(local_path), exist_ok=True)

        if not os.path.exists(local_path):
            r = requests.get(img_url, headers=HEADERS)
            if r.status_code == 200:
                with open(local_path, "wb") as f:
                    f.write(r.content)
        img["src"] = f"/{local_path.replace(os.sep, '/')}"

    markdown = f"""---
layout: post
title: "{title}"
date: {date_str}
categories: velog
---
{str(soup)}
"""
    with open(filename, "w", encoding="utf-8") as f:
        f.write(markdown)

์ด ์Šคํฌ๋ฆฝํŠธ๋Š”

  • RSS์—์„œ ํฌ์ŠคํŠธ ๋‚ด์šฉ์„ ํŒŒ์‹ฑ
  • Velog ์ด๋ฏธ์ง€(velcdn.com)๋ฅผ ๋กœ์ปฌ๋กœ ๋‹ค์šด๋กœ๋“œ
  • Jekyll์šฉ _posts/YYYY-MM-DD-title.md ํŒŒ์ผ๋กœ ์ €์žฅ ๊นŒ์ง€ ์ž๋™ ์ˆ˜ํ–‰ํ•œ๋‹ค.

โš™๏ธ 3. GitHub Actions๋กœ ์™„์ „ ์ž๋™ํ™”

๋งค์ผ ์ƒˆ๋ฒฝ์— ์ด ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์‹คํ–‰๋˜๋„๋ก GitHub Actions๋ฅผ ์„ค์ •ํ–ˆ๋‹ค. ์•„๋ž˜ ํŒŒ์ผ์„ ์ƒ์„ฑํ•œ๋‹ค.

๐Ÿ“ .github/workflows/velog-sync.yml

name: ๐Ÿช„ Velog โ†’ Jekyll Auto Sync

on:
  schedule:
    - cron: '0 9 * * *'   # ๋งค์ผ ํ•œ๊ตญ์‹œ๊ฐ„ ์˜คํ›„ 6์‹œ ์‹คํ–‰
  workflow_dispatch:       # ์ˆ˜๋™ ์‹คํ–‰๋„ ๊ฐ€๋Šฅ

jobs:
  sync:
    runs-on: ubuntu-latest

    steps:
      - name: ๐Ÿ“ฆ Checkout repository
        uses: actions/checkout@v4

      - name: ๐Ÿ Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: โš™๏ธ Install dependencies
        run: pip install feedparser requests beautifulsoup4

      - name: ๐Ÿ”„ Run Velog sync script
        run: python velog_to_jekyll_images_fixed.py

      - name: ๐Ÿงพ Commit & Push changes
        run: |
          git config user.name "Velog Sync Bot"
          git config user.email "actions@github.com"
          git add .
          git diff --quiet && git diff --staged --quiet || git commit -m "๐Ÿช„ Auto-sync Velog posts"
          git push

์ด์ œ ๋งค์ผ ์ง€์ •๋œ ์‹œ๊ฐ„๋งˆ๋‹ค

  • RSS โ†’ ํฌ์ŠคํŠธ ๋ณ€ํ™˜
  • ์ž๋™ ์ปค๋ฐ‹ & push
  • GitHub Pages ์ž๋™ ๋นŒ๋“œ ๊ฐ€ ์ „๋ถ€ ํด๋ผ์šฐ๋“œ์—์„œ ๋Œ์•„๊ฐ„๋‹ค.

๐Ÿงฉ ์ด๋ฏธ์ง€ ๊นจ์ง ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ ๊ณผ์ •

์ฒ˜์Œ์—” Velog์—์„œ ๊ฐ€์ ธ์˜จ ๊ธ€๋“ค์ด Jekyll ๋ธ”๋กœ๊ทธ์— ์ž˜ ํ‘œ์‹œ๋˜์—ˆ์ง€๋งŒ, ๋ณธ๋ฌธ์— ํฌํ•จ๋œ ์ด๋ฏธ์ง€๋“ค์ด ์ „๋ถ€ ๊นจ์ ธ ์žˆ์—ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ € ์ฝ˜์†”์„ ์—ด์–ด๋ณด๋‹ˆ ๊ฒฝ๋กœ๊ฐ€ ์ด๋ ‡๊ฒŒ ๋˜์–ด ์žˆ์—ˆ๋‹ค. /assets/images/hosooinmymind/image.png โ†’ 404 (Not Found)

์ด์œ ๋ฅผ ๋ถ„์„ํ•ด๋ณด๋‹ˆ Velog RSS์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ฒฝ๋กœ๊ฐ€ ์ ˆ๋Œ€์ฃผ์†Œ(https://velog.velcdn.com/โ€ฆ)์ธ๋ฐ, RSS ๋ณ€ํ™˜ ํ›„ ๋‹จ์ˆœํžˆ Markdown๋งŒ ์ €์žฅํ•˜๋ฉด Jekyll์ด ๋นŒ๋“œ ์‹œ ์ด ์™ธ๋ถ€ ์ด๋ฏธ์ง€๋ฅผ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒŒ ์›์ธ์ด์—ˆ๋‹ค.

โŒ ์ž˜๋ชป๋œ ๋ฐฉ์‹

์ฒ˜์Œ์—” ๋‹จ์ˆœํžˆ ๋ฅผ ์œ ์ง€ํ–ˆ์ง€๋งŒ, GitHub Pages๋Š” velog.velcdn.com ๋„๋ฉ”์ธ์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ CORS ์ •์ฑ…์ด๋‚˜ HTTPSโ†’HTTP ํ˜ผํ•ฉ ์ฝ˜ํ…์ธ  ์ฐจ๋‹จ์œผ๋กœ ์ธํ•ด ์ด๋ฏธ์ง€๋ฅผ ๋ Œ๋”๋งํ•˜์ง€ ๋ชปํ–ˆ๋‹ค.

โœ… ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•: ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ & ๊ฒฝ๋กœ ๋ณ€ํ™˜

๊ฒฐ๊ตญ Python ์Šคํฌ๋ฆฝํŠธ์—์„œ ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๋กœ์ปฌ๋กœ ๋‹ค์šด๋กœ๋“œํ•œ ๋’ค, ๋ชจ๋“  ์˜ src๋ฅผ ๋ธ”๋กœ๊ทธ ๋‚ด๋ถ€ ๊ฒฝ๋กœ๋กœ ๋ฐ”๊พธ๋Š” ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐํ–ˆ๋‹ค.

๋ณ€๊ฒฝ๋œ ํ•ต์‹ฌ ๋ถ€๋ถ„์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค ๐Ÿ‘‡

for img in soup.find_all("img"):
    img_url = img.get("src")
    if not img_url or not img_url.startswith("http"):
        continue

    # Velog ์ด๋ฏธ์ง€ ๋„๋ฉ”์ธ ๊ธฐ์ค€์œผ๋กœ ํŒŒ์ผ ๊ฒฝ๋กœ ์žฌ๊ตฌ์„ฑ
    rel_path = img_url.split("https://velog.velcdn.com/")[-1]
    local_path = os.path.join(IMG_DIR, rel_path)
    os.makedirs(os.path.dirname(local_path), exist_ok=True)

    # ์ด๋ฏธ์ง€ ํŒŒ์ผ ์ €์žฅ
    if not os.path.exists(local_path):
        r = requests.get(img_url, headers={"User-Agent": "Mozilla/5.0"})
        if r.status_code == 200:
            with open(local_path, "wb") as f:
                f.write(r.content)

    # HTML ๊ฒฝ๋กœ ์ˆ˜์ •
    img["src"] = f"/{local_path.replace(os.sep, '/')}"

์ด ์ฝ”๋“œ๋Š” ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค: โ‘  RSS์˜ ํƒœ๊ทธ์—์„œ ์›๋ณธ src ์ถ”์ถœ https://velog.velcdn.com/โ€ฆ โ‘ก ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ assets/images/USERNAME/ ์•„๋ž˜์— ์ €์žฅ ๋กœ์ปฌ ์ •์  ํŒŒ์ผ๋กœ ๋ณ€ํ™˜ โ‘ข HTML ๋‚ด src ๊ฒฝ๋กœ๋ฅผ /assets/โ€ฆ ๋กœ ๊ต์ฒด Jekyll์—์„œ ๋กœ๋“œ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋ณ€๊ฒฝ

๊ฒฐ๊ณผ์ ์œผ๋กœ GitHub Pages์—์„œ๋„ ๋ชจ๋“  ์ด๋ฏธ์ง€๊ฐ€ ๊นจ์ง€์ง€ ์•Š๊ณ  ํ‘œ์‹œ๋˜์—ˆ๋‹ค. ํŠนํžˆ requests.get()์— User-Agent ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•œ ๊ฒƒ์ด ์ค‘์š”ํ–ˆ๋‹ค. Velog์˜ CDN์ด ๊ธฐ๋ณธ ์š”์ฒญ(ํ—ค๋” ์—†๋Š” ์š”์ฒญ)์„ ์ฐจ๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๐Ÿง  ๋ฐฐ์šด ์ 

๋‹จ์ˆœํ•œ RSS ํฌ๋กค๋ง๋งŒ์œผ๋กœ๋Š” ์™„์ „ํ•œ ๋ธ”๋กœ๊ทธ ๋ฐฑ์—…์ด ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด๋ฏธ์ง€ ๋ฆฌ์†Œ์Šค๋ฅผ ํ•จ๊ป˜ ๊ด€๋ฆฌํ•ด์•ผ โ€œ์˜คํ”„๋ผ์ธ์—์„œ๋„ ๋…๋ฆฝ์ ์ธ ๋ธ”๋กœ๊ทธโ€๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. Jekyll๊ณผ ๊ฐ™์€ ์ •์  ๋ธ”๋กœ๊ทธ๋Š” ๋ชจ๋“  ๋ฆฌ์†Œ์Šค๊ฐ€ /assets ๊ฒฝ๋กœ์— ํฌํ•จ๋˜์–ด์•ผ ํ•จ์„ ๊ธฐ์–ตํ•˜์ž.

๐Ÿ’ก 4. ์™„์„ฑ๋œ ์ž๋™ํ™” ํ๋ฆ„

๐Ÿ•“ ๋งค์ผ 1ํšŒ GitHub Actions ํŠธ๋ฆฌ๊ฑฐ ๐Ÿช„ Python ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ -> Velog RSS ํŒŒ์‹ฑ & ์ด๋ฏธ์ง€ ๋กœ์ปฌ ์ €์žฅ ๐Ÿ’พ _posts/ ๊ฐฑ์‹  -> ์ƒˆ ๊ธ€ ์ž๋™ ์ถ”๊ฐ€ ๐Ÿš€ GitHub Pages ๋นŒ๋“œ -> Jekyll ์‚ฌ์ดํŠธ ์žฌ๋ฐฐํฌ ์™„๋ฃŒ

๐ŸŽ‰ ๊ฒฐ๊ณผ

์ด์ œ Velog์— ์ƒˆ ๊ธ€์„ ์˜ฌ๋ฆฌ๋ฉด ๋‹ค์Œ ๋‚  ์ž๋™์œผ๋กœ ๋‚ด Jekyll ๋ธ”๋กœ๊ทธ์—๋„ ์˜ฌ๋ผ์˜จ๋‹ค. ์ด๋ฏธ์ง€๋„ ๊นจ์ง€์ง€ ์•Š๊ณ , ์›๋ฌธ ๊ตฌ์กฐ ๊ทธ๋Œ€๋กœ ์œ ์ง€๋œ๋‹ค. Velog์™€ GitHub Pages๋ฅผ ํ•จ๊ป˜ ์šด์˜ํ•˜๋‹ˆ ๊ฐœ๋ฐœ ๊ธฐ๋ก๊ณผ ๊ฐœ์ธ ๋ธ”๋กœ๊ทธ๋ฅผ ํ•˜๋‚˜์˜ ์ƒํƒœ๊ณ„์ฒ˜๋Ÿผ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

Part 2. Discord ์•Œ๋ฆผ ์„ค์ •

๋Œ€ ์ž๋™ํ™” ์‹œ๋Œ€์— ๋งค์ผ ๋‚ด๊ฐ€ ๋ฒจ๋กœ๊ทธ๋ฅผ ๋™๊ธฐํ™”ํ•˜๋Š” ๊ฑด ๋ง์ด ์•ˆ ๋œ๋‹ค๊ณ  ์ƒ๊ฐ ์ž๋™์œผ๋กœ ํ•˜๋ฃจ์— ํ•œ ๋ฒˆ์”ฉ ๋™๊ธฐํ™”ํ•˜๊ณ  ๋””์Šค์ฝ”๋“œ ์•Œ๋ฆผ๊นŒ์ง€ ์˜ค๋„๋ก ์„ค์ •ํ–ˆ๋‹ค.

1๏ธโƒฃ ๋ชฉํ‘œ

  • Velog RSS ํ”ผ๋“œ๋ฅผ ์ด์šฉํ•ด ์ž๋™์œผ๋กœ ํฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑ
  • ๊ฐ ๊ธ€์˜ ์ด๋ฏธ์ง€๋„ ํ•จ๊ป˜ ๋‹ค์šด๋กœ๋“œํ•˜์—ฌ _posts ํด๋”์— ์ €์žฅ
  • GitHub Actions๋กœ ๋งค์ผ ์ž๋™ ์‹คํ–‰
  • ๋งˆ์ง€๋ง‰์œผ๋กœ ๋””์Šค์ฝ”๋“œ ์›นํ›… ์•Œ๋ฆผ์„ ๋ณด๋‚ด๋„๋ก ์„ค์ •

2๏ธโƒฃ Velog RSS ํฌ๋กค๋ง ์Šคํฌ๋ฆฝํŠธ

RSS ์ฃผ์†Œ ์˜ˆ์‹œ ๐Ÿ‘‰ https://v2.velog.io/rss/hosooinmymind ์ด ํ”ผ๋“œ๋ฅผ ์ฝ์–ด์™€ Jekyll์šฉ ๋งˆํฌ๋‹ค์šด ํฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค.

velog_to_jekyl_images.py
import feedparser, os, re, requests
from datetime import datetime
from bs4 import BeautifulSoup

VELG_FEED_URL = "https://v2.velog.io/rss/hosooinmymind"
SAVE_DIR = "_posts"
IMAGE_DIR = "assets/images/hosooinmymind"

os.makedirs(SAVE_DIR, exist_ok=True)
os.makedirs(IMAGE_DIR, exist_ok=True)

feed = feedparser.parse(VELG_FEED_URL)
for entry in feed.entries:
    title = re.sub(r'[\\/*?:"<>|]', '', entry.title.strip())
    date = datetime(*entry.published_parsed[:6])
    filename = f"{SAVE_DIR}/{date.strftime('%Y-%m-%d')}-{title.replace(' ', '-')}.md"

    soup = BeautifulSoup(entry.description, "html.parser")
    for img in soup.find_all("img"):
        src = img["src"]
        if src.startswith("https://velog.velcdn.com"):
            img_name = src.split("/")[-2] + ".png"
            save_path = f"{IMAGE_DIR}/{img_name}"
            if not os.path.exists(save_path):
                with open(save_path, "wb") as f:
                    f.write(requests.get(src).content)
            img["src"] = f"/{save_path}"

    post = f"""---
layout: post
title: "{entry.title}"
date: {date.strftime('%Y-%m-%d %H:%M:%S')} +0900
categories: velog
---

{soup}
"""
    with open(filename, "w", encoding="utf-8") as f:
        f.write(post)

3๏ธโƒฃ GitHub Actions ์ž๋™ ์‹คํ–‰ ์„ธํŒ…

.github/workflows/velog-sync.yml ์ž๋™์œผ๋กœ ์œ„ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์›Œํฌํ”Œ๋กœ ํŒŒ์ผ์ด๋‹ค.

name: Sync Velog posts

permissions:
  contents: write  # โœ… ์ €์žฅ์†Œ์— ํ‘ธ์‹œํ•  ๊ถŒํ•œ ๋ถ€์—ฌ

on:
  workflow_dispatch:
  schedule:
    - cron: "0 15 * * *"  # ๋งค์ผ 00์‹œ KST ์‹คํ–‰

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - name: ๐Ÿ“ฆ Checkout repository
        uses: actions/checkout@v3

      - name: ๐Ÿ Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.x'

      - name: โš™๏ธ Install dependencies
        run: |
          pip install feedparser requests beautifulsoup4

      - name: ๐Ÿ”„ Run Velog sync script
        run: python velog_to_jekyl_images.py

      - name: ๐Ÿช„ Commit & Push changes
        run: |
          git config user.name "Velog Sync Bot"
          git config user.email "actions@github.com"
          git add .
          git commit -m "๐Ÿช„ Auto-sync Velog posts" || echo "No changes to commit"
          git push

      - name: ๐Ÿ”” Send Discord notification
        if: success()
        run: |
          curl -H "Content-Type: application/json" \
            -d '{"content": "โœ… Velog ๋™๊ธฐํ™” ์™„๋ฃŒ! ์ƒˆ๋กœ์šด ํฌ์ŠคํŠธ๊ฐ€ ๋ธ”๋กœ๊ทธ์— ๋ฐ˜์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค."}' \
            $

5๏ธโƒฃ Discord Webhook ์„ค์ •

๋””์Šค์ฝ”๋“œ ์„œ๋ฒ„์—์„œ โ†’ ์„œ๋ฒ„ ์„ค์ • โ†’ ํ†ตํ•ฉ โ†’ Webhook โ†’ ์ƒˆ ์›นํ›… ๋งŒ๋“ค๊ธฐ ๋ณต์‚ฌํ•œ URL์„ GitHub Secrets์— ์ถ”๊ฐ€ ๐Ÿ”น GitHub โ†’ Settings โ†’ Secrets โ†’ Actions โ†’ New repository secret

6๏ธโƒฃ ํ…Œ์ŠคํŠธ ์‹คํ–‰

Actions โ†’ Velog Sync โ†’ Run workflow ํด๋ฆญ ๋ชจ๋“  ๋‹จ๊ณ„๊ฐ€ ์ดˆ๋ก์ƒ‰ โœ… ์ด๋ฉด ์„ฑ๊ณต. ๋””์Šค์ฝ”๋“œ์—๋Š” ์ด๋Ÿฐ ์•Œ๋ฆผ์ด ๋„์ฐฉํ•œ๋‹ค:

โœจ ๋งˆ๋ฌด๋ฆฌ

์ด์ œ Velog์— ๊ธ€์„ ์˜ฌ๋ฆฌ๋ฉด GitHub Pages์— ์ž๋™ ๋ฐ˜์˜๋˜๊ณ , ๋งค์ผ ์ž์ •์—” ์ƒˆ ๊ธ€์ด ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ๋œ๋‹ค.