Skip to content

joocy75-hash/Naver-Blog

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

20 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ ์ž๋™ํ™” ์‹œ์Šคํ…œ

์ตœ์ข… ์—…๋ฐ์ดํŠธ: 2025-12-29 ํ˜„์žฌ ์ƒํƒœ: โœ… ํ”„๋กœ๋•์…˜ ๋ฐฐํฌ ์™„๋ฃŒ (Vultr ์„œ์šธ ์„œ๋ฒ„) GitHub: https://github.com/mr-joo/naver-blog-bot


๋ชฉ์ฐจ

  1. ํ”„๋กœ์ ํŠธ ๊ฐœ์š”
  2. ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜
  3. ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ
  4. ์„ค์น˜ ๋ฐ ์‹คํ–‰
  5. ์„œ๋ฒ„ ๋ฐฐํฌ (Vultr ์„œ์šธ)
  6. CI/CD ์ž๋™ ๋ฐฐํฌ
  7. ์šด์˜ ๊ฐ€์ด๋“œ
  8. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •
  9. ์•Œ๋ ค์ง„ ์ด์Šˆ ๋ฐ ํ•ด๊ฒฐ์ฑ…
  10. ํ–ฅํ›„ ๊ฐœ์„  ์‚ฌํ•ญ

1. ํ”„๋กœ์ ํŠธ ๊ฐœ์š”

1.1 ๋ชฉ์ 

AI ๊ธฐ๋ฐ˜ ๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ ์ž๋™ ํฌ์ŠคํŒ… ์‹œ์Šคํ…œ

  • ์‹ค์‹œ๊ฐ„ ๋‰ด์Šค/ํŠธ๋ Œ๋“œ ์ˆ˜์ง‘ โ†’ AI ๊ธ€ ์ƒ์„ฑ โ†’ ์ด๋ฏธ์ง€ ์ƒ์„ฑ โ†’ ์ž๋™ ๋ฐœํ–‰
  • 24์‹œ๊ฐ„ ๋ฌด์ธ ์šด์˜ (1-2์‹œ๊ฐ„ ๊ฐ„๊ฒฉ, ์ผ์ผ ์ตœ๋Œ€ 12๊ฐœ)
  • ๋ณธ๋ฌธ ์ค‘๊ฐ„์— ์ด๋ฏธ์ง€ 3-4๊ฐœ ์ž๋™ ์‚ฝ์ž…

1.2 ํŽ˜๋ฅด์†Œ๋‚˜

  • ์Šค๋งˆํŠธ๊ฐœ๋ฏธ ์ฝ”์ธ๋ด‡: ์•”ํ˜ธํ™”ํ/ํˆฌ์ž ์ „๋ฌธ ๋ธ”๋กœ๊ฑฐ
  • ์นด์นด์˜คํ†ก ์˜คํ”ˆ์ฑ„ํŒ… ์œ ๋„ ๋งˆ์ผ€ํŒ…

1.3 ๊ธฐ์ˆ  ์Šคํƒ

๊ตฌ์„ฑ์š”์†Œ ๊ธฐ์ˆ 
์–ธ์–ด Python 3.11+
๋ธŒ๋ผ์šฐ์ € ์ž๋™ํ™” Playwright (Chromium)
์ฝ˜ํ…์ธ  ์ƒ์„ฑ Claude API (Haiku/Sonnet)
๋ฆฌ์„œ์น˜ Perplexity API
์ด๋ฏธ์ง€ ์ƒ์„ฑ Google Gemini Imagen 3
์Šค์ผ€์ค„๋ง APScheduler
์•Œ๋ฆผ Telegram Bot API
์ปจํ…Œ์ด๋„ˆ Docker + Docker Compose
CI/CD GitHub Actions
์„œ๋ฒ„ Hetzner CPX31 (4 vCPU / 8 GB RAM)

1.4 ๊ณ„์ • ์ •๋ณด

๋„ค์ด๋ฒ„ ID: wncksdid0750
๋ธ”๋กœ๊ทธ URL: https://blog.naver.com/pakrsojang

2. ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜

2.1 ์ „์ฒด ํ๋ฆ„

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                        ์ž๋™ ์Šค์ผ€์ค„๋Ÿฌ                              โ”‚
โ”‚                   (scheduler/auto_scheduler.py)                  โ”‚
โ”‚                     1-2์‹œ๊ฐ„ ๊ฐ„๊ฒฉ ์‹คํ–‰                             โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                โ”‚
                                โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                      ํŒŒ์ดํ”„๋ผ์ธ (pipeline.py)                     โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”              โ”‚
โ”‚  โ”‚ ๋ฆฌ์„œ์น˜      โ”‚โ†’โ”‚ ์ฝ˜ํ…์ธ  ์ƒ์„ฑ  โ”‚โ†’โ”‚ ์ด๋ฏธ์ง€ ์ƒ์„ฑ  โ”‚              โ”‚
โ”‚  โ”‚ (Perplexity)โ”‚  โ”‚ (Claude)    โ”‚  โ”‚ (Gemini)    โ”‚              โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜              โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                โ”‚
                                โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    ๋ธ”๋กœ๊ทธ ํฌ์Šคํ„ฐ (auto_post.py)                   โ”‚
โ”‚  ์„ธ์…˜ ๋กœ๋“œ โ†’ ๊ธ€์“ฐ๊ธฐ โ†’ ์ด๋ฏธ์ง€ ์‚ฝ์ž… โ†’ ๋ฐœํ–‰                          โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                โ”‚
                                โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                    ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ (utils/telegram_notifier.py)     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

2.2 AI ์—์ด์ „ํŠธ ๊ตฌ์„ฑ

์—์ด์ „ํŠธ ํŒŒ์ผ ์—ญํ• 
Research Agent agents/research_agent.py Perplexity API๋กœ ์‹ค์‹œ๊ฐ„ ๋‰ด์Šค/ํŠธ๋ Œ๋“œ ์ˆ˜์ง‘
Content Agent agents/content_agent.py Claude Haiku/Sonnet์œผ๋กœ ๋ธ”๋กœ๊ทธ ๊ธ€ ์ƒ์„ฑ
Visual Agent agents/visual_agent.py ์ด๋ฏธ์ง€ ํ”„๋กฌํ”„ํŠธ ์ƒ์„ฑ
QA Agent agents/qa_agent.py ์ฝ˜ํ…์ธ  ํ’ˆ์งˆ ๊ฒ€์ฆ (70์  ๋ฏธ๋งŒ ์žฌ์ƒ์„ฑ)
Upload Agent agents/upload_agent.py ๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ ์—…๋กœ๋“œ

3. ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ

๋„ค์ด๋ฒ„๋ธ”๋กœ๊ทธ๋ด‡/
โ”œโ”€โ”€ main.py                      # ๋ฉ”์ธ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ดํ„ฐ
โ”œโ”€โ”€ pipeline.py                  # ํ†ตํ•ฉ ํŒŒ์ดํ”„๋ผ์ธ (ํ•ต์‹ฌ)
โ”œโ”€โ”€ auto_post.py                 # ๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ… (ํ•ต์‹ฌ)
โ”œโ”€โ”€ manual_login_clipboard.py    # ์ˆ˜๋™ ๋กœ๊ทธ์ธ (์„ธ์…˜ ์ €์žฅ์šฉ)
โ”‚
โ”œโ”€โ”€ agents/                      # AI ์—์ด์ „ํŠธ
โ”‚   โ”œโ”€โ”€ research_agent.py        # ๋ฆฌ์„œ์น˜ (Perplexity)
โ”‚   โ”œโ”€โ”€ content_agent.py         # ์ฝ˜ํ…์ธ  ์ƒ์„ฑ (Claude)
โ”‚   โ”œโ”€โ”€ visual_agent.py          # ๋น„์ฃผ์–ผ ์ƒ์„ฑ
โ”‚   โ”œโ”€โ”€ qa_agent.py              # ํ’ˆ์งˆ ๊ฒ€์ฆ
โ”‚   โ”œโ”€โ”€ upload_agent.py          # ์—…๋กœ๋“œ
โ”‚   โ”œโ”€โ”€ marketing_content.py     # ๋งˆ์ผ€ํŒ… ์ฝ˜ํ…์ธ 
โ”‚   โ””โ”€โ”€ blog_content_generator.py # ๋‹ค๋ชฉ์  ์ƒ์„ฑ๊ธฐ
โ”‚
โ”œโ”€โ”€ scheduler/                   # ์Šค์ผ€์ค„๋ง
โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚   โ”œโ”€โ”€ auto_scheduler.py        # 24์‹œ๊ฐ„ ์ž๋™ ์Šค์ผ€์ค„๋Ÿฌ (์—”ํŠธ๋ฆฌํฌ์ธํŠธ)
โ”‚   โ””โ”€โ”€ topic_rotator.py         # ์ฃผ์ œ ์ˆœํ™˜
โ”‚
โ”œโ”€โ”€ utils/                       # ์œ ํ‹ธ๋ฆฌํ‹ฐ
โ”‚   โ”œโ”€โ”€ gemini_image.py          # Imagen ์ด๋ฏธ์ง€ ์ƒ์„ฑ
โ”‚   โ”œโ”€โ”€ telegram_notifier.py     # ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ
โ”‚   โ”œโ”€โ”€ clipboard_input.py       # ํด๋ฆฝ๋ณด๋“œ ์ž…๋ ฅ (ํ—ค๋“œ๋ฆฌ์Šค ํ˜ธํ™˜)
โ”‚   โ”œโ”€โ”€ human_behavior.py        # ์ธ๊ฐ„ ํ–‰๋™ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
โ”‚   โ”œโ”€โ”€ cost_optimizer.py        # API ๋น„์šฉ ์ตœ์ ํ™”
โ”‚   โ””โ”€โ”€ error_recovery.py        # ์—๋Ÿฌ ๋ณต๊ตฌ
โ”‚
โ”œโ”€โ”€ security/                    # ๋ณด์•ˆ
โ”‚   โ”œโ”€โ”€ credential_manager.py    # API ํ‚ค ๊ด€๋ฆฌ (macOS ํ‚ค์ฒด์ธ)
โ”‚   โ””โ”€โ”€ session_manager.py       # ์„ธ์…˜ ๊ด€๋ฆฌ (์•”ํ˜ธํ™”)
โ”‚
โ”œโ”€โ”€ config/                      # ์„ค์ •
โ”‚   โ”œโ”€โ”€ settings.py              # ํ™˜๊ฒฝ ์„ค์ •
โ”‚   โ””โ”€โ”€ human_timing.py          # ํƒ€์ด๋ฐ ์„ค์ •
โ”‚
โ”œโ”€โ”€ models/                      # ๋ฐ์ดํ„ฐ
โ”‚   โ””โ”€โ”€ database.py              # SQLite DB
โ”‚
โ”œโ”€โ”€ monitoring/                  # ๋ชจ๋‹ˆํ„ฐ๋ง
โ”‚   โ”œโ”€โ”€ health_checker.py        # ํ—ฌ์Šค์ฒดํฌ
โ”‚   โ””โ”€โ”€ reporter.py              # ํ†ต๊ณ„ ๋ฆฌํฌํ„ฐ
โ”‚
โ”œโ”€โ”€ deploy/                      # ๋ฐฐํฌ ์Šคํฌ๋ฆฝํŠธ
โ”‚   โ”œโ”€โ”€ server-init.sh           # ์„œ๋ฒ„ ์ดˆ๊ธฐํ™”
โ”‚   โ”œโ”€โ”€ setup-github-secrets.sh  # GitHub Secrets ์„ค์ •
โ”‚   โ”œโ”€โ”€ deploy-to-server.sh      # ์›ํด๋ฆญ ๋ฐฐํฌ
โ”‚   โ””โ”€โ”€ setup-env-interactive.sh # ๋Œ€ํ™”ํ˜• .env ์„ค์ •
โ”‚
โ”œโ”€โ”€ .github/workflows/
โ”‚   โ””โ”€โ”€ deploy.yml               # CI/CD ํŒŒ์ดํ”„๋ผ์ธ
โ”‚
โ”œโ”€โ”€ Dockerfile                   # Docker ์ด๋ฏธ์ง€ (Playwright ๊ธฐ๋ฐ˜)
โ”œโ”€โ”€ docker-compose.yml           # Docker Compose ์„ค์ •
โ”œโ”€โ”€ requirements.txt             # Python ์˜์กด์„ฑ
โ”œโ”€โ”€ .env.example                 # ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์˜ˆ์‹œ
โ””โ”€โ”€ .gitignore                   # Git ์ œ์™ธ ๋ชฉ๋ก

4. ์„ค์น˜ ๋ฐ ์‹คํ–‰

4.1 ๋กœ์ปฌ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ

# ์ €์žฅ์†Œ ํด๋ก 
git clone https://github.com/joocy75-hash/Naver-Blog.git
cd Naver-Blog

# ๊ฐ€์ƒํ™˜๊ฒฝ ์ƒ์„ฑ
python -m venv venv
source venv/bin/activate  # macOS/Linux
# or: venv\Scripts\activate  # Windows

# ์˜์กด์„ฑ ์„ค์น˜
pip install -r requirements.txt

# Playwright ๋ธŒ๋ผ์šฐ์ € ์„ค์น˜
playwright install chromium

# ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ •
cp .env.example .env
# .env ํŒŒ์ผ ํŽธ์ง‘ํ•˜์—ฌ API ํ‚ค ์ž…๋ ฅ

4.2 ์„ธ์…˜ ๋กœ๊ทธ์ธ (์ตœ์ดˆ 1ํšŒ)

python manual_login_clipboard.py
# ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์—ด๋ฆฌ๋ฉด ๋„ค์ด๋ฒ„ ๋กœ๊ทธ์ธ ์ˆ˜ํ–‰
# ๋กœ๊ทธ์ธ ํ›„ ์ž๋™์œผ๋กœ ์„ธ์…˜ ์ €์žฅ๋จ

4.3 ์‹คํ–‰ ๋ฐฉ๋ฒ•

# 1ํšŒ ํ…Œ์ŠคํŠธ (๋ฐœํ–‰ ์•ˆ ํ•จ)
python pipeline.py research --dry

# ์‹ค์ œ ๋ฐœํ–‰
python pipeline.py research

# 24์‹œ๊ฐ„ ์ž๋™ ์Šค์ผ€์ค„๋Ÿฌ
python -m scheduler.auto_scheduler

# ์ปค์Šคํ…€ ์„ค์ • (1-2์‹œ๊ฐ„ ๊ฐ„๊ฒฉ, ์ผ์ผ 10๊ฐœ)
python -m scheduler.auto_scheduler --interval 1 2 --limit 10

5. ์„œ๋ฒ„ ๋ฐฐํฌ (Vultr ์„œ์šธ)

5.1 ์„œ๋ฒ„ ์ •๋ณด

ํ•ญ๋ชฉ ๊ฐ’
์„œ๋ฒ„ IP 141.164.55.245
์„œ๋ฒ„ ์ œ๊ณต์‚ฌ Vultr
์œ„์น˜ Seoul, South Korea ๐Ÿ‡ฐ๐Ÿ‡ท
์‚ฌ์–‘ vc2-1c-1gb (1 vCPU / 1 GB RAM / 25 GB SSD)
OS Ubuntu 24.04 LTS
๋ฐฐํฌ ๊ฒฝ๋กœ /root/naver-blog-bot
์›” ๋น„์šฉ $5.00
ํŠน์ด์‚ฌํ•ญ ํ•œ๊ตญ IP๋กœ ๋„ค์ด๋ฒ„ ๋ธ”๋กœ๊ทธ ๋ฐœํ–‰ ์ œํ•œ ์šฐํšŒ

5.2 ์„œ๋ฒ„ ๋ฐฐํฌ ์™„๋ฃŒ ์ƒํƒœ (2025-12-29)

โœ… ํ˜„์žฌ ๋ฐฐํฌ ์ƒํƒœ:

  • Docker ์ปจํ…Œ์ด๋„ˆ naver-blog-bot ์‹คํ–‰ ์ค‘ (healthy)
  • ๋‹ค์Œ ์ž๋™ ํฌ์ŠคํŒ… ์˜ˆ์•ฝ๋จ (1-2์‹œ๊ฐ„ ๊ฐ„๊ฒฉ)
  • ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ ์ž‘๋™ ์ค‘
  • ํ—ฌ์Šค์ฒดํฌ ํ†ต๊ณผ

5.3 SSH ์ ‘์† ๋ฐฉ๋ฒ•

# ๋น„๋ฐ€๋ฒˆํ˜ธ ์ ‘์† (ํ˜„์žฌ ์„ค์ •)
ssh root@141.164.55.245
# ๋น„๋ฐ€๋ฒˆํ˜ธ: [Br76r(6mMDr%?ia

# SSH ํ‚ค ์ ‘์† (GitHub Actions์šฉ)
ssh -i ~/.ssh/vultr_naver_bot root@141.164.55.245

5.4 ์ˆ˜๋™ ๋ฐฐํฌ ํ”„๋กœ์„ธ์Šค

์„œ๋ฒ„์— ์ฒ˜์Œ ๋ฐฐํฌํ•˜๋Š” ๊ฒฝ์šฐ:

# 1. SSH ์ ‘์†
ssh root@141.164.55.245

# 2. Docker ์„ค์น˜
curl -fsSL https://get.docker.com | sh
systemctl start docker
systemctl enable docker

# 3. Git ์„ค์น˜
apt-get update && apt-get install -y git

# 4. ํ”„๋กœ์ ํŠธ ํด๋ก  (๋ฐฉ๋ฒ• A: GitHub - private repo์˜ ๊ฒฝ์šฐ ํ† ํฐ ํ•„์š”)
git clone https://github.com/mr-joo/naver-blog-bot.git /root/naver-blog-bot

# ๋˜๋Š” (๋ฐฉ๋ฒ• B: ๋กœ์ปฌ์—์„œ tar๋กœ ์ „์†ก)
# ๋กœ์ปฌ์—์„œ ์‹คํ–‰:
cd /Users/mr.joo/Desktop/๋„ค์ด๋ฒ„๋ธ”๋กœ๊ทธ๋ด‡
tar czf - --exclude='.git' --exclude='__pycache__' . | ssh root@141.164.55.245 'mkdir -p /root/naver-blog-bot && cd /root/naver-blog-bot && tar xzf -'

# 5. ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ •
cd /root/naver-blog-bot
cp .env.example .env
vim .env  # API ํ‚ค, ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ

# 6. Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ ๋ฐ ์‹คํ–‰
docker build -t naver-blog-bot:latest .
docker run -d \
  --name naver-blog-bot \
  --restart unless-stopped \
  -v $(pwd)/data:/app/data \
  -v $(pwd)/logs:/app/logs \
  -v $(pwd)/secrets:/app/secrets \
  -v $(pwd)/config:/app/config \
  -v $(pwd)/.env:/app/.env:ro \
  --shm-size=2gb \
  naver-blog-bot:latest

# 7. ์ƒํƒœ ํ™•์ธ
docker ps
docker logs naver-blog-bot --tail 50

5.5 ์„œ๋ฒ„ ์ด์ „ ์‹œ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

์ƒˆ ์„œ๋ฒ„๋กœ ์ด์ „ํ•˜๋Š” ๊ฒฝ์šฐ:

  1. ์„œ๋ฒ„ ์ค€๋น„:

    • Docker ์„ค์น˜
    • Git ์„ค์น˜
    • SSH ํ‚ค ์ƒ์„ฑ (GitHub Actions์šฉ)
  2. ์ฝ”๋“œ ๋ฐฐํฌ:

    • ์†Œ์Šค ์ฝ”๋“œ ํด๋ก  ๋˜๋Š” ์ „์†ก
    • .env ํŒŒ์ผ ์„ค์ • (API ํ‚ค, ๋„ค์ด๋ฒ„ ๊ณ„์ •)
    • Docker ์ด๋ฏธ์ง€ ๋นŒ๋“œ
    • ์ปจํ…Œ์ด๋„ˆ ์‹คํ–‰
  3. GitHub Secrets ์—…๋ฐ์ดํŠธ:

    • HETZNER_HOST โ†’ ์ƒˆ ์„œ๋ฒ„ IP
    • HETZNER_USER โ†’ root
    • HETZNER_SSH_KEY โ†’ ์ƒˆ ์„œ๋ฒ„ SSH private key
  4. ์„ธ์…˜ ํŒŒ์ผ ์ „์†ก (์ค‘์š”!):

    # ๋กœ์ปฌ โ†’ ์ƒˆ ์„œ๋ฒ„
    scp -r data/sessions/*.encrypted root@141.164.55.245:/root/naver-blog-bot/data/sessions/
  5. ํ…Œ์ŠคํŠธ:

    • ์ปจํ…Œ์ด๋„ˆ ์ •์ƒ ์‹คํ–‰ ํ™•์ธ
    • ๋กœ๊ทธ ํ™•์ธ
    • ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ ์ˆ˜์‹  ํ™•์ธ
    • GitHub Actions ๋ฐฐํฌ ํ…Œ์ŠคํŠธ

5.6 ๋„ค์ด๋ฒ„ IP ์ฐจ๋‹จ ํ•ด๊ฒฐ (์ค‘์š”!)

๋ฌธ์ œ ์ƒํ™ฉ: ๋„ค์ด๋ฒ„๋Š” ์™ธ๊ตญ IP์—์„œ ๋ธ”๋กœ๊ทธ ๋ฐœํ–‰์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. ๋ฏธ๊ตญ/์œ ๋Ÿฝ ์„œ๋ฒ„์—์„œ ๋ฐœํ–‰ ์‹œ "ํŽ˜์ด์ง€๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค" ์˜ค๋ฅ˜ ๋ฐœ์ƒ.

ํ•ด๊ฒฐ์ฑ…: โœ… Vultr ์„œ์šธ ์„œ๋ฒ„ ์‚ฌ์šฉ (ํ˜„์žฌ ์„ค์ •)

  • ํ•œ๊ตญ IP (141.164.55.245)๋กœ ๋„ค์ด๋ฒ„ ์ฐจ๋‹จ ์šฐํšŒ
  • ๋ฐœํ–‰ ์„ฑ๊ณต๋ฅ  100%
  • ์ถ”๊ฐ€ ํ”„๋ก์‹œ ์„ค์ • ๋ถˆํ•„์š”

์ด์ „ ์‹œ๋„ํ–ˆ๋˜ ๋ฐฉ๋ฒ•๋“ค:

  • โŒ Hetzner (๋…์ผ/๋ฏธ๊ตญ): ๋ฐœํ–‰ ์ฐจ๋‹จ๋จ
  • โŒ HTTP ํ”„๋ก์‹œ: ๋ณต์žกํ•˜๊ณ  ๋น„์šฉ ๋ฐœ์ƒ
  • โœ… ํ•œ๊ตญ ์„œ๋ฒ„ (Oracle Cloud ๋˜๋Š” Vultr): ์„ฑ๊ณต

5.7 ์„œ๋ฒ„ ๋น„์šฉ ์ตœ์ ํ™”

ํ˜„์žฌ ์„ค์ • (Vultr):

  • ์›” $5.00
  • 1GB RAM (์ถฉ๋ถ„ - ํ˜„์žฌ ์‚ฌ์šฉ๋Ÿ‰ 47%)
  • 25GB SSD (์ถฉ๋ถ„ - ํ˜„์žฌ ์‚ฌ์šฉ๋Ÿ‰ 55%)

๋ฌด๋ฃŒ ๋Œ€์•ˆ (์„ ํƒ์‚ฌํ•ญ):

  • Oracle Cloud Always Free: 4 vCPU, 24GB RAM (์„œ์šธ ๋ฆฌ์ „)
    • ์„ค์ • ๋ณต์žก (VCN, ๋ณด์•ˆ ๋ชฉ๋ก ๋“ฑ)
    • ๋ฌด๋ฃŒ์ง€๋งŒ ์ดˆ๊ธฐ ์„ค์ • ์‹œ๊ฐ„ ์†Œ์š”
    • ์ด๋ฏธ Vultr๋กœ ๋ฐฐํฌ ์™„๋ฃŒ๋˜์–ด ๊ถŒ์žฅํ•˜์ง€ ์•Š์Œ

6. CI/CD ์ž๋™ ๋ฐฐํฌ

6.1 ์›Œํฌํ”Œ๋กœ์šฐ ๊ตฌ์กฐ

main ๋ธŒ๋žœ์น˜ Push
        โ”‚
        โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Test & Lint      โ”‚  flake8, black, mypy (1๋ถ„ 30์ดˆ)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        โ”‚
        โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Build Docker     โ”‚  ์ด๋ฏธ์ง€ ๋นŒ๋“œ (6๋ถ„)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        โ”‚
        โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Deploy to Server โ”‚  SSH๋กœ ์„œ๋ฒ„ ๋ฐฐํฌ (2๋ถ„)
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
        โ”‚
        โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Send Notificationโ”‚  Telegram ์•Œ๋ฆผ
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

6.2 GitHub Secrets ์„ค์ • (ํ•„์ˆ˜!)

Settings โ†’ Secrets and variables โ†’ Actions์—์„œ ์„ค์ •:

Secret ์ด๋ฆ„ ๊ฐ’ ์„ค๋ช…
HETZNER_HOST 141.164.55.245 Vultr ์„œ๋ฒ„ IP
HETZNER_USER root SSH ์‚ฌ์šฉ์ž
HETZNER_SSH_KEY (์•„๋ž˜ SSH ํ‚ค) SSH ๊ฐœ์ธํ‚ค ์ „์ฒด
TELEGRAM_BOT_TOKEN (์„ ํƒ) ์•Œ๋ฆผ์šฉ
TELEGRAM_CHAT_ID (์„ ํƒ) ์•Œ๋ฆผ์šฉ

HETZNER_SSH_KEY์— ์ž…๋ ฅํ•  ๊ฐ’:

-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----

โš ๏ธ ์ฃผ์˜: ์ด SSH ํ‚ค๋Š” ์„œ๋ฒ„ ์ „์šฉ์ž…๋‹ˆ๋‹ค. ์ ˆ๋Œ€ GitHub ์ €์žฅ์†Œ์— ์ปค๋ฐ‹ํ•˜์ง€ ๋งˆ์„ธ์š”!

6.3 ๋ฐฐํฌ ํŠธ๋ฆฌ๊ฑฐ

# ์ฝ”๋“œ ์ˆ˜์ • ํ›„ Pushํ•˜๋ฉด ์ž๋™ ๋ฐฐํฌ
git add .
git commit -m "Fix: something"
git push origin main

# GitHub Actions ์ƒํƒœ ํ™•์ธ
gh run list --repo joocy75-hash/Naver-Blog

7. ์šด์˜ ๊ฐ€์ด๋“œ

7.1 ์„œ๋น„์Šค ๊ด€๋ฆฌ ๋ช…๋ น์–ด

# SSH ์ ‘์†
ssh root@141.164.55.245

# ์ปจํ…Œ์ด๋„ˆ ์ƒํƒœ ํ™•์ธ
docker ps

# ๋กœ๊ทธ ํ™•์ธ (์‹ค์‹œ๊ฐ„)
docker logs naver-blog-bot -f

# ์žฌ์‹œ์ž‘
cd /root/naver-blog-bot
docker restart naver-blog-bot

# ์ค‘์ง€
docker stop naver-blog-bot

# ์‹œ์ž‘
docker start naver-blog-bot

# ์ปจํ…Œ์ด๋„ˆ ์‚ญ์ œ ๋ฐ ์žฌ์ƒ์„ฑ
docker stop naver-blog-bot
docker rm naver-blog-bot
docker run -d \
  --name naver-blog-bot \
  --restart unless-stopped \
  -v $(pwd)/data:/app/data \
  -v $(pwd)/logs:/app/logs \
  -v $(pwd)/secrets:/app/secrets \
  -v $(pwd)/config:/app/config \
  -v $(pwd)/.env:/app/.env:ro \
  --shm-size=2gb \
  naver-blog-bot:latest

# ์ด๋ฏธ์ง€ ์žฌ๋นŒ๋“œ
docker build -t naver-blog-bot:latest . && docker restart naver-blog-bot

7.2 ๋กœ๊ทธ ํ™•์ธ

# Docker ๋กœ๊ทธ (์‹ค์‹œ๊ฐ„)
docker logs naver-blog-bot -f

# Docker ๋กœ๊ทธ (์ตœ๊ทผ 100์ค„)
docker logs naver-blog-bot --tail 100

# ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊ทธ
tail -f /root/naver-blog-bot/logs/*.log

# ํŠน์ • ์‹œ๊ฐ„๋Œ€ ๋กœ๊ทธ ๊ฒ€์ƒ‰
docker logs naver-blog-bot --since "2025-12-29T00:00:00"

7.3 ๋ชจ๋‹ˆํ„ฐ๋ง

# Docker ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๋Ÿ‰
docker stats naver-blog-bot

# ์‹œ์Šคํ…œ ๋ฆฌ์†Œ์Šค (top)
top

# ๋ฉ”๋ชจ๋ฆฌ ํ™•์ธ
free -h

# ๋””์Šคํฌ ์‚ฌ์šฉ๋Ÿ‰
df -h

# Docker ๋””์Šคํฌ ์‚ฌ์šฉ๋Ÿ‰
docker system df

7.4 ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ ์‹œ์Šคํ…œ (๊ฐ•ํ™” ๋ฒ„์ „)

7.4.1 ์•Œ๋ฆผ ๋ ˆ๋ฒจ

๋ ˆ๋ฒจ ์ด๋ชจ์ง€ ์„ค๋ช… ์ฟจ๋‹ค์šด
INFO โ„น๏ธ ์ •๋ณด์„ฑ ์•Œ๋ฆผ 30๋ถ„
SUCCESS โœ… ์„ฑ๊ณต ์•Œ๋ฆผ ์ฆ‰์‹œ
WARNING โš ๏ธ ๊ฒฝ๊ณ  ์•Œ๋ฆผ 10๋ถ„
ERROR โŒ ์˜ค๋ฅ˜ ์•Œ๋ฆผ 5๋ถ„
CRITICAL ๐Ÿšจ ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜ ์ฆ‰์‹œ

7.4.2 ์•Œ๋ฆผ ์ข…๋ฅ˜

์ƒํ™ฉ ์•Œ๋ฆผ ๋ฉ”์„œ๋“œ ํŠธ๋ฆฌ๊ฑฐ
ํฌ์ŠคํŒ… ์„ฑ๊ณต/์‹คํŒจ send_post_success/failure() ํฌ์ŠคํŒ… ์™„๋ฃŒ ์‹œ
์‹œ์Šคํ…œ ๋ฆฌ์†Œ์Šค send_system_status() CPU/๋ฉ”๋ชจ๋ฆฌ/๋””์Šคํฌ ๊ฒฝ๊ณ  ์‹œ
API ์ƒํƒœ send_api_status() ์‘๋‹ต ๋А๋ฆผ ๋˜๋Š” ์˜ค๋ฅ˜ ์‹œ
์„ธ์…˜ ๋งŒ๋ฃŒ send_session_warning() ์„ธ์…˜ ๋งŒ๋ฃŒ 1~3์ผ ์ „
์—๋Ÿฌ ๋ถ„์„ send_error_analysis() ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ (๊ถŒ์žฅ ์กฐ์น˜ ํฌํ•จ)
ํ—ฌ์Šค์ฒดํฌ send_health_check_result() WARNING/CRITICAL ๊ฐ์ง€ ์‹œ
Rate Limit send_rate_limit_warning() ์‚ฌ์šฉ๋Ÿ‰ 80%/95% ๋„๋‹ฌ ์‹œ
์ผ์‹œ์ •์ง€ send_alert() ์—ฐ์† 3ํšŒ ์—๋Ÿฌ ์‹œ
๋ณต๊ตฌ ์„ฑ๊ณต send_recovery_notification() ์ž๋™ ๋ณต๊ตฌ ์™„๋ฃŒ ์‹œ
์‹œ์ž‘/์ข…๋ฃŒ send_startup/shutdown_alert() ๋ด‡ ์‹œ์ž‘/์ข…๋ฃŒ ์‹œ

7.4.3 ๋ชจ๋‹ˆํ„ฐ๋ง ์ฃผ๊ธฐ

์ฃผ๊ธฐ ์ž‘์—… ์•Œ๋ฆผ ์กฐ๊ฑด
15๋ถ„ ๋น ๋ฅธ ๋ฆฌ์†Œ์Šค ์ฒดํฌ CPU 70%โ†‘, ๋ฉ”๋ชจ๋ฆฌ 80%โ†‘, ๋””์Šคํฌ 85%โ†‘
1์‹œ๊ฐ„ ์ „์ฒด ํ—ฌ์Šค์ฒดํฌ API/DB/์„ธ์…˜ ๋ฌธ์ œ ๊ฐ์ง€ ์‹œ
3์‹œ๊ฐ„ ์„ธ์…˜ ์ƒํƒœ ์ฒดํฌ ๋งŒ๋ฃŒ 3์ผ ์ „๋ถ€ํ„ฐ ๊ฒฝ๊ณ 
๋งค์ผ 21:00 ์ผ๊ฐ„ ๋ฆฌํฌํŠธ ํ•ญ์ƒ (ํ†ต๊ณ„)
๋งค์ฃผ ์ผ์š”์ผ 20:00 ์ฃผ๊ฐ„ ๋ฆฌํฌํŠธ ํ•ญ์ƒ (ํ†ต๊ณ„)

7.4.4 ์•Œ๋ฆผ ์˜ˆ์‹œ

์‹œ์ž‘ ์•Œ๋ฆผ:

๐Ÿš€ ๋ธ”๋กœ๊ทธ ๋ด‡ ์‹œ์ž‘

๐Ÿ‘ค ๊ณ„์ •: wncksdid0750
โฐ ํฌ์ŠคํŒ… ๊ฐ„๊ฒฉ: 1-2์‹œ๊ฐ„
๐Ÿ“Š ์ผ์ผ ์ œํ•œ: 12๊ฐœ
๐Ÿค– ๋ชจ๋ธ: haiku

๐Ÿ“Š ์‹œ์Šคํ…œ ์ƒํƒœ:
  โ€ข CPU: 15.2%
  โ€ข ๋ฉ”๋ชจ๋ฆฌ: 45.3%
  โ€ข ๋””์Šคํฌ: 32.1%

โœ… ํ—ฌ์Šค์ฒดํฌ: HEALTHY

์—๋Ÿฌ ๋ถ„์„ ์•Œ๋ฆผ:

โš ๏ธ ์—๋Ÿฌ ๋ฐœ์ƒ

์—๋Ÿฌ ์œ ํ˜•: session_expired
๋‚ด์šฉ: ๋„ค์ด๋ฒ„ ๋กœ๊ทธ์ธ ์„ธ์…˜์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค
๋ฐœ์ƒ ํšŸ์ˆ˜: 2ํšŒ
์ตœ์ดˆ ๋ฐœ์ƒ: 14:23:45

๐Ÿ’ก ๊ถŒ์žฅ ์กฐ์น˜:
์„ธ์…˜ ์žฌ๋กœ๊ทธ์ธ
๋„ค์ด๋ฒ„ ์„ธ์…˜์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ˆ˜๋™์œผ๋กœ ์žฌ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
โš ๏ธ ์ˆ˜๋™ ์กฐ์น˜๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ผ์‹œ์ •์ง€ ์•Œ๋ฆผ:

๐Ÿšจ ์ž๋™ ํฌ์ŠคํŒ… ์ผ์‹œ์ •์ง€

์—ฐ์† ์—๋Ÿฌ 3ํšŒ ๋ฐœ์ƒ์œผ๋กœ ์ผ์‹œ์ •์ง€๋ฉ๋‹ˆ๋‹ค.

โฑ ์ฟจ๋‹ค์šด: 30๋ถ„
๐Ÿ• ์žฌ๊ฐœ ์˜ˆ์ •: 15:30:00

๐Ÿ“Š ์—๋Ÿฌ ์œ ํ˜•๋ณ„ ํ†ต๊ณ„:
  โ€ข session_expired: 2ํšŒ
  โ€ข network_error: 1ํšŒ

๐Ÿ“‹ ์ตœ๊ทผ ์—๋Ÿฌ:
1. [session_expired] ์„ธ์…˜ ๋งŒ๋ฃŒ...
2. [network_error] ์—ฐ๊ฒฐ ์‹คํŒจ...
3. [session_expired] ๋กœ๊ทธ์ธ ํ•„์š”...

๐Ÿ’ก ๊ถŒ์žฅ ์กฐ์น˜:
์„ธ์…˜ ์žฌ๋กœ๊ทธ์ธ
๋„ค์ด๋ฒ„ ์„ธ์…˜์ด ๋งŒ๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ˆ˜๋™์œผ๋กœ ์žฌ๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ํ—ฌ์Šค์ฒดํฌ ๊ฒฝ๊ณ :

๐ŸŸก ์‹œ์Šคํ…œ ํ—ฌ์Šค์ฒดํฌ ๊ฒฝ๊ณ 

์ปดํฌ๋„ŒํŠธ ์ƒํƒœ:
  โœ… claude_api: Claude API ์—ฐ๊ฒฐ ์ •์ƒ (245ms)
  โœ… perplexity_api: Perplexity API ํ‚ค ์„ค์ •๋จ
  โš ๏ธ memory: ๋ฉ”๋ชจ๋ฆฌ ๋†’์Œ: 82.5% ์‚ฌ์šฉ ์ค‘
  โœ… disk_space: ๋””์Šคํฌ ๊ณต๊ฐ„ ์ •์ƒ (45.2GB ๋‚จ์Œ)
  โœ… database: ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ ์ •์ƒ (12ms)

โŒ ๋ฌธ์ œ ์ปดํฌ๋„ŒํŠธ: memory

8. ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ •

8.1 ํ•„์ˆ˜ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ (.env)

# ===================
# Naver ๊ณ„์ • ์ •๋ณด
# ===================
NAVER_ID=your_naver_id
NAVER_PW=your_naver_password

# ===================
# AI API Keys
# ===================
ANTHROPIC_API_KEY=sk-ant-xxxxx
GOOGLE_API_KEY=AIzaSyxxxxx
GCP_PROJECT_ID=your-project-id
GCP_LOCATION=us-central1
PERPLEXITY_API_KEY=pplx-xxxxx

# ===================
# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค
# ===================
DATABASE_URL=sqlite:///./data/blog_bot.db

# ===================
# ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ
# ===================
TELEGRAM_BOT_TOKEN=1234567890:ABCdefGHI
TELEGRAM_CHAT_ID=your_chat_id

# ===================
# Rate Limiting
# ===================
MAX_DAILY_POSTS=12
MIN_POST_INTERVAL_HOURS=1
API_COOLDOWN_SECONDS=60

# ===================
# ํ”„๋กœ๋•์…˜ ์„ค์ •
# ===================
DEBUG=False
TEST_MODE=False
HEADLESS=True
LOG_LEVEL=INFO

8.2 ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์ˆ˜์ • (์„œ๋ฒ„)

ssh root@141.164.55.245
cd /root/naver-blog-bot
vim .env
docker restart naver-blog-bot

9. ์•Œ๋ ค์ง„ ์ด์Šˆ ๋ฐ ํ•ด๊ฒฐ์ฑ…

9.1 AsyncIOScheduler ๋น„๋™๊ธฐ ์‹คํ–‰ ๋ฌธ์ œ (ํ•ด๊ฒฐ๋จ - 2025-12-27)

์ฆ์ƒ: ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ 24์‹œ๊ฐ„ ๊ฐ€๋™๋˜์—ˆ์œผ๋‚˜ ํฌ์ŠคํŒ… 0๊ฐœ, ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ 0๊ฐœ

  • ๋กœ๊ทธ์— RuntimeWarning: coroutine was never awaited ๊ฒฝ๊ณ  ๋‹ค์ˆ˜ ๋ฐœ์ƒ
  • _post_job, _run_health_check ๋“ฑ async ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Œ

์›์ธ: BackgroundScheduler(๋™๊ธฐ์‹)๋กœ async def ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ํ˜ธ์ถœ

  • APScheduler์˜ BackgroundScheduler๋Š” ๋™๊ธฐ ์Šค์ผ€์ค„๋Ÿฌ
  • async ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ๋“ฑ๋กํ•˜๋ฉด ์ฝ”๋ฃจํ‹ด ๊ฐ์ฒด๋งŒ ๋ฐ˜ํ™˜๋˜๊ณ  ์‹ค์ œ ์‹คํ–‰์ด ์•ˆ ๋จ

ํ•ด๊ฒฐ: AsyncIOScheduler๋กœ ๋ณ€๊ฒฝ (async ํ•จ์ˆ˜ ๋„ค์ดํ‹ฐ๋ธŒ ์ง€์›)

# ๋ณ€๊ฒฝ ์ „
from apscheduler.schedulers.background import BackgroundScheduler
self.scheduler = BackgroundScheduler()

# ๋ณ€๊ฒฝ ํ›„
from apscheduler.schedulers.asyncio import AsyncIOScheduler
self.scheduler = AsyncIOScheduler()

์ˆ˜์ •๋œ ํŒŒ์ผ:

  • scheduler/auto_scheduler.py: AsyncIOScheduler ์ ์šฉ, ๋น„๋™๊ธฐ ๋ฉ”์ธ ๋ฃจํ”„ ๊ตฌํ˜„
  • utils/error_recovery.py: asyncio.create_task() ์•ˆ์ „ ํ˜ธ์ถœ ์ฒ˜๋ฆฌ

9.2 ์ทจ์†Œ์„  ๋ฒ„๊ทธ (ํ•ด๊ฒฐ๋จ)

์ฆ์ƒ: ๋ณธ๋ฌธ ์ž…๋ ฅ ์‹œ ์ทจ์†Œ์„  ์„œ์‹์ด ์ ์šฉ๋จ

ํ•ด๊ฒฐ: se-is-selected ํด๋ž˜์Šค๋กœ ํ™œ์„ฑํ™” ์ƒํƒœ ๊ฐ์ง€

const btn = document.querySelector('button.se-strikethrough-toolbar-button');
if (btn && btn.classList.contains('se-is-selected')) {
    btn.click();
}

9.2 pyautogui DISPLAY ์˜ค๋ฅ˜ (ํ•ด๊ฒฐ๋จ)

์ฆ์ƒ: ํ—ค๋“œ๋ฆฌ์Šค ์„œ๋ฒ„์—์„œ KeyError: 'DISPLAY'

ํ•ด๊ฒฐ: utils/clipboard_input.py์—์„œ ์กฐ๊ฑด๋ถ€ import

_headless_mode = os.environ.get('HEADLESS', 'False').lower() == 'true' or 'DISPLAY' not in os.environ
if _headless_mode:
    pyautogui = None

9.3 ๋„ค์ด๋ฒ„ IP ์ฐจ๋‹จ ๋ฌธ์ œ (ํ•ด๊ฒฐ๋จ - 2025-12-29)

์ฆ์ƒ: ๋ฐœํ–‰ ๋ฒ„ํŠผ ํด๋ฆญ ํ›„ "ํŽ˜์ด์ง€๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค" ์˜ค๋ฅ˜

์›์ธ: ๋„ค์ด๋ฒ„๊ฐ€ ์™ธ๊ตญ IP์—์„œ ๋ธ”๋กœ๊ทธ ๋ฐœํ–‰์„ ์ฐจ๋‹จ

ํ•ด๊ฒฐ: Vultr ์„œ์šธ ์„œ๋ฒ„๋กœ ์ด์ „ (ํ•œ๊ตญ IP ์‚ฌ์šฉ)

  • ์ด์ „ ์„œ๋ฒ„: Hetzner (๋ฏธ๊ตญ) - ๋ฐœํ–‰ ์‹คํŒจ
  • ํ˜„์žฌ ์„œ๋ฒ„: Vultr Seoul (ํ•œ๊ตญ 141.164.55.245) - ๋ฐœํ–‰ ์„ฑ๊ณต

9.4 ์„ธ์…˜ ๋งŒ๋ฃŒ

์ฆ์ƒ: ๋กœ๊ทธ์ธ ์‹คํŒจ, ์„ธ์…˜ ๋ฌดํšจ

ํ•ด๊ฒฐ: ๋กœ์ปฌ์—์„œ ์ˆ˜๋™ ๋กœ๊ทธ์ธ ํ›„ ์„ธ์…˜ ํŒŒ์ผ ์„œ๋ฒ„๋กœ ์ „์†ก

# ๋กœ์ปฌ์—์„œ
python manual_login_clipboard.py

# ์„œ๋ฒ„๋กœ ์ „์†ก
scp -r data/sessions/*.encrypted root@141.164.55.245:/root/naver-blog-bot/data/sessions/

9.5 ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ

์ฆ์ƒ: ์ปจํ…Œ์ด๋„ˆ OOMKilled

ํ•ด๊ฒฐ:

# ๋ถˆํ•„์š”ํ•œ ์ด๋ฏธ์ง€ ์ •๋ฆฌ
docker system prune -a

# Swap ํ™•์ธ
swapon --show

# ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰ ํ™•์ธ
free -h
docker stats naver-blog-bot

10. ํ–ฅํ›„ ๊ฐœ์„  ์‚ฌํ•ญ

10.1 ์šฐ์„ ์ˆœ์œ„ ๋†’์Œ

  • ์„ธ์…˜ ์ž๋™ ๊ฐฑ์‹  ์‹œ์Šคํ…œ
  • ์—๋Ÿฌ ๋ณต๊ตฌ ๋กœ์ง ๊ฐ•ํ™”
  • ์ค‘๋ณต ์ฃผ์ œ ๋ฐฉ์ง€

10.2 ์šฐ์„ ์ˆœ์œ„ ์ค‘๊ฐ„

  • ์›น ๋Œ€์‹œ๋ณด๋“œ (๋ชจ๋‹ˆํ„ฐ๋ง UI)
  • ํ…”๋ ˆ๊ทธ๋žจ ์›๊ฒฉ ์ œ์–ด
  • ๋‹ค์ค‘ ๊ณ„์ • ์ˆœํ™˜ ํฌ์ŠคํŒ…

10.3 ์šฐ์„ ์ˆœ์œ„ ๋‚ฎ์Œ

  • SEO ์ตœ์ ํ™”
  • ํ†ต๊ณ„ ๋ฐ ๋ถ„์„ ๊ธฐ๋Šฅ
  • ๋‹ค์–‘ํ•œ ์ฝ˜ํ…์ธ  ์นดํ…Œ๊ณ ๋ฆฌ ์ถ”๊ฐ€

๋ถ€๋ก: ์ฃผ์š” ํŒŒ์ผ ์š”์•ฝ

ํŒŒ์ผ ์—ญํ•  ํ•ต์‹ฌ ํ•จ์ˆ˜
auto_post.py ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ… ์ž๋™ํ™” NaverBlogPoster.post()
pipeline.py ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ run_marketing(), run_research()
scheduler/auto_scheduler.py 24์‹œ๊ฐ„ ์Šค์ผ€์ค„๋Ÿฌ AutoPostingScheduler.start()
utils/gemini_image.py ์ด๋ฏธ์ง€ ์ƒ์„ฑ generate_image()
manual_login_clipboard.py ์„ธ์…˜ ์ €์žฅ ์ˆ˜๋™ ๋กœ๊ทธ์ธ

๋ถ€๋ก: ๋น ๋ฅธ ๋ช…๋ น์–ด ์ฐธ์กฐ

# SSH ์ ‘์†
ssh root@141.164.55.245

# ์ปจํ…Œ์ด๋„ˆ ์ƒํƒœ
docker ps

# ๋กœ๊ทธ (์‹ค์‹œ๊ฐ„)
docker logs naver-blog-bot -f

# ์žฌ์‹œ์ž‘
docker restart naver-blog-bot

# ์ค‘์ง€/์‹œ์ž‘
docker stop naver-blog-bot
docker start naver-blog-bot

# ์ด๋ฏธ์ง€ ์žฌ๋นŒ๋“œ
cd /root/naver-blog-bot
docker build -t naver-blog-bot:latest .
docker restart naver-blog-bot

# ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ˆ˜์ •
vim /root/naver-blog-bot/.env
docker restart naver-blog-bot

# GitHub Actions ์ƒํƒœ
gh run list --repo mr-joo/naver-blog-bot

# ๋ฆฌ์†Œ์Šค ๋ชจ๋‹ˆํ„ฐ๋ง
docker stats naver-blog-bot
free -h
df -h

๋ฒ•์  ๊ณ ์ง€

๋ณธ ์‹œ์Šคํ…œ์€ ๊ต์œก ๋ฐ ์—ฐ๊ตฌ ๋ชฉ์ ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋„ค์ด๋ฒ„ ์ด์šฉ์•ฝ๊ด€์„ ์ค€์ˆ˜ํ•ด์•ผ ํ•˜๋ฉฐ, ์ž๋™ํ™”๋กœ ์ธํ•œ ๊ณ„์ • ์ •์ง€ ๋ฆฌ์Šคํฌ๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ์žˆ์Šต๋‹ˆ๋‹ค.



๋ฌธ์„œ ๋ | ๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ: 2025-12-29

๋ณ€๊ฒฝ ์ด๋ ฅ

2025-12-29 (2์ฐจ ์—…๋ฐ์ดํŠธ) - ์›๊ฒฉ ์„œ๋ฒ„ ์ž๋™๋ฐฐํฌ ์•ˆ์ •ํ™”

๐Ÿ”ง ํ•ด๊ฒฐ๋œ ๋ฌธ์ œ์ 

1. ์„ธ์…˜ ๋งŒ๋ฃŒ ๋ฌธ์ œ (7์ผ ๊ณ ์ • ๋งŒ๋ฃŒ)

  • ๋ฌธ์ œ: ์„ธ์…˜์ด ์ƒ์„ฑ์ผ ๊ธฐ์ค€ 7์ผ ํ›„ ๋ฌด์กฐ๊ฑด ๋งŒ๋ฃŒ๋˜์–ด ์žฌ๋กœ๊ทธ์ธ ํ•„์š”
  • ํ•ด๊ฒฐ: ํฌ์ŠคํŒ… ์„ฑ๊ณต ์‹œ ์„ธ์…˜ ์ž๋™ ๊ฐฑ์‹  ๊ธฐ๋Šฅ ์ถ”๊ฐ€
  • ์ˆ˜์ • ํŒŒ์ผ: security/session_manager.py
  • ์ƒˆ ๋ฉ”์„œ๋“œ:
    • renew_session(): ์„ธ์…˜ ๊ฐฑ์‹  (last_renewed_at ํƒ€์ž„์Šคํƒฌํ”„ ์—…๋ฐ์ดํŠธ)
    • get_days_until_expiry(): ๋งŒ๋ฃŒ๊นŒ์ง€ ๋‚จ์€ ์ผ์ˆ˜ ๊ณ„์‚ฐ
    • check_expiry_warning(): ๋งŒ๋ฃŒ ๊ฒฝ๊ณ  ํ•„์š” ์—ฌ๋ถ€ ํ™•์ธ (1, 2, 3์ผ ์ „ ๊ฒฝ๊ณ )
    • renew_playwright_session(): Playwright ์„ธ์…˜ ๊ฐฑ์‹  ํ—ฌํผ ํ•จ์ˆ˜

2. Docker ํ™˜๊ฒฝ ํ‚ค์ฒด์ธ ์ ‘๊ทผ ์‹คํŒจ

  • ๋ฌธ์ œ: Docker ์ปจํ…Œ์ด๋„ˆ์—์„œ macOS ํ‚ค์ฒด์ธ ์ ‘๊ทผ ๋ถˆ๊ฐ€๋กœ API ํ‚ค ๋กœ๋“œ ์‹คํŒจ
  • ํ•ด๊ฒฐ: Docker ํ™˜๊ฒฝ ์ž๋™ ๊ฐ์ง€ ๋ฐ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์šฐ์„  ๋ชจ๋“œ ์ถ”๊ฐ€
  • ์ˆ˜์ • ํŒŒ์ผ: security/credential_manager.py
  • ์ƒˆ ํ•จ์ˆ˜/๋ณ€์ˆ˜:
    • is_docker_environment(): Docker ํ™˜๊ฒฝ ์ž๋™ ๊ฐ์ง€ (/.dockerenv, cgroup, ํ™˜๊ฒฝ๋ณ€์ˆ˜ ํ™•์ธ)
    • IS_DOCKER: ๋ชจ๋“ˆ ๋กœ๋“œ ์‹œ Docker ์—ฌ๋ถ€ ์บ์‹œ
    • KEYRING_AVAILABLE: Docker์—์„œ๋Š” ์ž๋™์œผ๋กœ False

3. CDP ์—ฐ๊ฒฐ ํƒ€์ž„์•„์›ƒ (10์ดˆ ๋Œ€๊ธฐ)

  • ๋ฌธ์ œ: ์„œ๋ฒ„ ํ™˜๊ฒฝ์—์„œ CDP ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์—†์–ด ๋งค๋ฒˆ 10์ดˆ ํƒ€์ž„์•„์›ƒ ๋ฐœ์ƒ
  • ํ•ด๊ฒฐ:
    • use_cdp ๊ธฐ๋ณธ๊ฐ’์„ True โ†’ False๋กœ ๋ณ€๊ฒฝ
    • CDP ํƒ€์ž„์•„์›ƒ์„ 10์ดˆ โ†’ 3์ดˆ๋กœ ๋‹จ์ถ•
    • ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์ œ์–ด ๊ฐ€๋Šฅํ•˜๋„๋ก ์ˆ˜์ •
  • ์ˆ˜์ • ํŒŒ์ผ: agents/upload_agent.py

๐Ÿ“ ์ˆ˜์ •๋œ ํŒŒ์ผ ์ƒ์„ธ

ํŒŒ์ผ ๋ณ€๊ฒฝ ๋‚ด์šฉ
security/session_manager.py ์„ธ์…˜ ์ž๋™ ๊ฐฑ์‹  ๊ธฐ๋Šฅ, ๋งŒ๋ฃŒ ๊ฒฝ๊ณ  ์‹œ์Šคํ…œ, ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ง€์›
security/credential_manager.py Docker ํ™˜๊ฒฝ ์ž๋™ ๊ฐ์ง€, ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์šฐ์„  ๋ชจ๋“œ
agents/upload_agent.py CDP ๊ธฐ๋ณธ๊ฐ’ False, ํƒ€์ž„์•„์›ƒ 3์ดˆ, ์„ธ์…˜ ์ž๋™ ๊ฐฑ์‹  ํ˜ธ์ถœ
Dockerfile ์ƒˆ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋ฌธ์„œํ™” ๋ฐ ๊ธฐ๋ณธ๊ฐ’ ์„ค์ •
.env.example USE_CDP, CDP_TIMEOUT, SESSION_MAX_AGE_DAYS ์ถ”๊ฐ€

๐Ÿ†• ์ƒˆ๋กœ์šด ํ™˜๊ฒฝ ๋ณ€์ˆ˜

# CDP (Chrome DevTools Protocol) ์„ค์ •
USE_CDP=False              # CDP ์‚ฌ์šฉ ์—ฌ๋ถ€ (๋กœ์ปฌ: True, ์„œ๋ฒ„/Docker: False)
CDP_TIMEOUT=3              # CDP ์—ฐ๊ฒฐ ํƒ€์ž„์•„์›ƒ (์ดˆ)

# ์„ธ์…˜ ๊ด€๋ฆฌ
SESSION_MAX_AGE_DAYS=7     # ์„ธ์…˜ ์ตœ๋Œ€ ์œ ํšจ ๊ธฐ๊ฐ„ (์ผ)

๐Ÿ”„ ์„ธ์…˜ ๊ฐฑ์‹  ํ๋ฆ„

ํฌ์ŠคํŒ… ์„ฑ๊ณต
    โ”‚
    โ–ผ
renew_playwright_session() ํ˜ธ์ถœ
    โ”‚
    โ–ผ
session_manager.renew_session()
    โ”‚
    โ”œโ”€ last_renewed_at ํƒ€์ž„์Šคํƒฌํ”„ ์—…๋ฐ์ดํŠธ
    โ”œโ”€ storage_state ๊ฐฑ์‹  (์ฟ ํ‚ค/์Šคํ† ๋ฆฌ์ง€)
    โ””โ”€ ์•”ํ˜ธํ™”ํ•˜์—ฌ ์ €์žฅ
    โ”‚
    โ–ผ
์„ธ์…˜ ์œ ํšจ๊ธฐ๊ฐ„ 7์ผ ์—ฐ์žฅ (๊ฐฑ์‹  ์‹œ์  ๊ธฐ์ค€)

๐Ÿ“Š Docker ํ™˜๊ฒฝ ๊ฐ์ง€ ๋กœ์ง

def is_docker_environment() -> bool:
    # 1. /.dockerenv ํŒŒ์ผ ์กด์žฌ ํ™•์ธ
    # 2. /proc/1/cgroup์—์„œ docker ๋ฌธ์ž์—ด ํ™•์ธ
    # 3. RUNNING_IN_DOCKER ํ™˜๊ฒฝ๋ณ€์ˆ˜ ํ™•์ธ

2025-12-29 (1์ฐจ ์—…๋ฐ์ดํŠธ)

  • โœ… Vultr ์„œ์šธ ์„œ๋ฒ„๋กœ ์ด์ „ (141.164.55.245)
    • ๋„ค์ด๋ฒ„ IP ์ฐจ๋‹จ ๋ฌธ์ œ ํ•ด๊ฒฐ (ํ•œ๊ตญ IP ์‚ฌ์šฉ)
    • ์„œ๋ฒ„ ์ •๋ณด ๋ฐ ๋ชจ๋“  ๋ช…๋ น์–ด ์—…๋ฐ์ดํŠธ
    • GitHub Actions Secrets ์ •๋ณด ์—…๋ฐ์ดํŠธ
    • SSH ํ‚ค ์ƒ์„ฑ ๋ฐ ๋ฌธ์„œํ™”

2025-12-27

  • AsyncIOScheduler ๋น„๋™๊ธฐ ์‹คํ–‰ ๋ฌธ์ œ ํ•ด๊ฒฐ
  • ์ทจ์†Œ์„  ๋ฒ„๊ทธ ํ•ด๊ฒฐ
  • Hetzner ์„œ๋ฒ„ ๋ฐฐํฌ ์™„๋ฃŒ

๋‹ค์Œ ์ž‘์—… ํ•„์š” ์‚ฌํ•ญ (TODO)

๐Ÿ”ด ์šฐ์„ ์ˆœ์œ„ ๋†’์Œ

  1. ์Šค์ผ€์ค„๋Ÿฌ์—์„œ ์„ธ์…˜ ๊ฐฑ์‹  ํ˜ธ์ถœ ์ถ”๊ฐ€

    • ํŒŒ์ผ: scheduler/auto_scheduler.py
    • ๋‚ด์šฉ: ํฌ์ŠคํŒ… ์„ฑ๊ณต ์‹œ session_manager.renew_session() ๋ช…์‹œ์  ํ˜ธ์ถœ
    • ํ˜„์žฌ: upload_agent.py์—์„œ๋งŒ ๊ฐฑ์‹  ํ˜ธ์ถœ๋จ
    • ํ•„์š”: ์Šค์ผ€์ค„๋Ÿฌ ๋ ˆ๋ฒจ์—์„œ๋„ ์„ธ์…˜ ์ƒํƒœ ์ฒดํฌ ๋ฐ ๊ฐฑ์‹ 
  2. ์„ธ์…˜ ๋งŒ๋ฃŒ ๊ฒฝ๊ณ  ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ ์—ฐ๋™

    • ํŒŒ์ผ: scheduler/auto_scheduler.py, utils/telegram_notifier.py
    • ๋‚ด์šฉ: check_expiry_warning() ๊ฒฐ๊ณผ๋ฅผ ํ…”๋ ˆ๊ทธ๋žจ์œผ๋กœ ์ „์†ก
    • ๊ตฌํ˜„: ๋งค์ผ ๋˜๋Š” ํฌ์ŠคํŒ… ์ „ ์„ธ์…˜ ๋งŒ๋ฃŒ D-3, D-2, D-1 ๊ฒฝ๊ณ 
  3. ์„œ๋ฒ„์—์„œ ์‹ค์ œ ๋ฐฐํฌ ํ…Œ์ŠคํŠธ

    • Docker ์ด๋ฏธ์ง€ ์žฌ๋นŒ๋“œ ๋ฐ ๋ฐฐํฌ
    • ์„ธ์…˜ ๊ฐฑ์‹  ๊ธฐ๋Šฅ ๋™์ž‘ ํ™•์ธ
    • ๋กœ๊ทธ ๋ชจ๋‹ˆํ„ฐ๋ง

๐ŸŸก ์šฐ์„ ์ˆœ์œ„ ์ค‘๊ฐ„

  1. ์ž๋™ ์žฌ๋กœ๊ทธ์ธ ์‹œ์Šคํ…œ ๊ตฌ์ถ•

    • ์„ธ์…˜ ๋งŒ๋ฃŒ ์‹œ ์ž๋™์œผ๋กœ ์žฌ๋กœ๊ทธ์ธ ์‹œ๋„
    • 2FA/์บก์ฑ  ๊ฐ์ง€ ์‹œ ํ…”๋ ˆ๊ทธ๋žจ ์•Œ๋ฆผ + ์ˆ˜๋™ ๊ฐœ์ž… ์š”์ฒญ
  2. ํ—ฌ์Šค์ฒดํฌ์— ์„ธ์…˜ ์ƒํƒœ ์ถ”๊ฐ€

    • ํŒŒ์ผ: monitoring/health_checker.py
    • ๋‚ด์šฉ: ์„ธ์…˜ ์œ ํšจ์„ฑ ๋ฐ ๋‚จ์€ ์ผ์ˆ˜๋ฅผ ํ—ฌ์Šค์ฒดํฌ ํ•ญ๋ชฉ์— ํฌํ•จ
  3. requirements.txt ๋ฒ„์ „ ๊ณ ์ •

    • ํ˜„์žฌ ์ผ๋ถ€ ํŒจํ‚ค์ง€ ๋ฒ„์ „ ๋ฏธ์ง€์ •
    • ํ”„๋กœ๋•์…˜ ์•ˆ์ •์„ฑ์„ ์œ„ํ•ด ๋ชจ๋“  ํŒจํ‚ค์ง€ ๋ฒ„์ „ ๊ณ ์ • ๊ถŒ์žฅ

๐ŸŸข ์šฐ์„ ์ˆœ์œ„ ๋‚ฎ์Œ

  1. ์„ธ์…˜ ๋ฐฑ์—… ์‹œ์Šคํ…œ

    • ์„ธ์…˜ ํŒŒ์ผ ์ž๋™ ๋ฐฑ์—… (์ผ์ผ/์ฃผ๊ฐ„)
    • ๋ณต๊ตฌ ์Šคํฌ๋ฆฝํŠธ ์ž‘์„ฑ
  2. ๋‹ค์ค‘ ์„ธ์…˜ ์ง€์›

    • ์—ฌ๋Ÿฌ ๋„ค์ด๋ฒ„ ๊ณ„์ • ์„ธ์…˜ ๊ด€๋ฆฌ
    • ๊ณ„์ •๋ณ„ ์„ธ์…˜ ๊ฐฑ์‹  ๋ฐ ๋ชจ๋‹ˆํ„ฐ๋ง
  3. ์›น ๋Œ€์‹œ๋ณด๋“œ

    • ์„ธ์…˜ ์ƒํƒœ ์‹œ๊ฐํ™”
    • ์ˆ˜๋™ ๊ฐฑ์‹  ๋ฒ„ํŠผ
    • ๋กœ๊ทธ ๋ทฐ์–ด

๐Ÿ“‹ ๋ฐฐํฌ ์ „ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

# 1. ์„œ๋ฒ„ ์ ‘์†
ssh root@141.164.55.245

# 2. ์ฝ”๋“œ ์—…๋ฐ์ดํŠธ
cd /root/naver-blog-bot
git pull origin main  # ๋˜๋Š” ํŒŒ์ผ ์ „์†ก

# 3. Docker ์ด๋ฏธ์ง€ ์žฌ๋นŒ๋“œ
docker build -t naver-blog-bot:latest .

# 4. ์ปจํ…Œ์ด๋„ˆ ์žฌ์‹œ์ž‘
docker stop naver-blog-bot
docker rm naver-blog-bot
docker run -d \
  --name naver-blog-bot \
  --restart unless-stopped \
  -v $(pwd)/data:/app/data \
  -v $(pwd)/logs:/app/logs \
  -v $(pwd)/secrets:/app/secrets \
  -v $(pwd)/config:/app/config \
  -v $(pwd)/.env:/app/.env:ro \
  --shm-size=2gb \
  naver-blog-bot:latest

# 5. ๋กœ๊ทธ ํ™•์ธ
docker logs naver-blog-bot -f

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors