NyamNyam WeDu — Cafeteria Menu Alert Bot
2026-01-01 — present
Bot that crawls weekly cafeteria menus from Kakao Channel via Playwright and auto-delivers to Slack — Clean Architecture + TSyringe DI, Slack Bot API slash command, up to 6 retries, DeliveryHistory duplicate prevention
Problem Solving
Inconvenience of manually checking cafeteria menus on Kakao Channel
Playwright headless Kakao Channel crawling, @slack/bolt Socket Mode + node-cron weekly Monday 09:00 auto-delivery
Weekly menu auto-delivered to Slack, up to 6 retries at 1-hour intervals on failure
Same menu being sent multiple times to channels
DeliveryHistory table for per-channel delivery tracking, duplicate send prevention
Zero duplicate sends, /식단 slash command for instant lookup
Project Description
A bot that automatically collects weekly cafeteria menus from Pangyo InnoValley and delivers them to Slack channels. Crawls menu image URLs and metadata from Kakao Channel posts using Playwright headless Chrome, and auto-delivers to designated channels via @slack/bolt Socket Mode. Scheduled every Monday at 9 AM (KST) via node-cron, with up to 6 retries at 1-hour intervals on failure. Manages per-channel delivery history through a DeliveryHistory table to prevent duplicate sends, and provides instant menu lookup via the /식단 slash command. Separates domain, application, and infrastructure layers with Clean Architecture, manages dependencies through TSyringe DI container, and implements explicit error handling with Result<T, E> pattern instead of exceptions.
Highlights
- Playwright headless Chrome crawling for Kakao Channel menus
- Slack Bot Socket Mode + /식단 slash command implementation
- Up to 6 retries (1h interval) + DeliveryHistory duplicate prevention
- Clean Architecture + TSyringe DI + Result<T, E> error handling
- Docker container deployment (bundled Playwright browser)
Performance Metrics
| Performance Metrics | Before | After |
|---|---|---|
| Retry attempts | 0 | 최대 6회 (1시간 간격) (신뢰성) |
| Duplicate sends | - | 0건 (DeliveryHistory) |
Tech Decisions
- ▶ Clean Architecture + TSyringe DI: decouples crawler/Slack dependencies, only infra layer changes on external service swap
- ▶ Playwright over Cheerio: Kakao Channel requires JS rendering — static HTML parsing with Cheerio cannot capture dynamic content
- ▶ Result<T, E> pattern: explicit error types instead of exceptions force callers to handle errors, improving code predictability
Lessons Learned
- • Learned wait strategies and selector stability for dynamic content crawling by scraping JavaScript-rendered Kakao Channel pages with Playwright headless browser
- • Experienced Slack platform integration patterns including slash command handling and Block Kit message formatting by implementing a Slack Bot with @slack/bolt Socket Mode
- • Learned reliability strategies for external service integration by designing idempotency guarantees via DeliveryHistory table and retry mechanism (up to 6 times at 1-hour intervals)
- • Internalized how functional error handling improves code predictability and testability by returning explicit error types via Result<T, E> pattern instead of exceptions