본문으로 건너뛰기
개인Slack Bot + Playwright 크롤러 · 주간 단일 배치

냠냠위듀 — 구내식당 식단 알림 봇

2026-01-01 — present

판교 이노밸리 구내식당 주간 식단표를 카카오 채널에서 Playwright로 크롤링하여 Slack으로 자동 발송하는 봇 — Clean Architecture + TSyringe DI, Slack Bot API 슬래시 커맨드, 재시도 최대 6회, DeliveryHistory 중복 방지

냠냠위듀 — 구내식당 식단 알림 봇 project cover image

문제 해결 과정

1

구내식당 주간 식단표를 카카오 채널에서 직접 확인해야 하는 불편

해결 과정

Playwright 헤드리스로 카카오 채널 게시물 크롤링, @slack/bolt Socket Mode + node-cron으로 매주 월요일 09:00 자동 발송

결과

주간 식단표 Slack 자동 발송, 실패 시 1시간 간격 최대 6회 재시도

2

동일 식단표가 여러 채널에 중복 발송되는 문제

해결 과정

DeliveryHistory 테이블로 채널별 발송 이력 관리, 중복 발송 차단 로직 구현

결과

중복 발송 0건, /식단 슬래시 커맨드로 즉시 조회 가능

프로젝트 설명

판교 이노밸리 구내식당의 주간 식단표를 자동으로 수집하여 Slack 채널에 발송하는 봇이다. Playwright 헤드리스 Chrome으로 카카오 채널 게시물에서 식단표 이미지 URL과 메타데이터를 크롤링하고, @slack/bolt Socket Mode 기반으로 지정 채널에 자동 발송한다. 매주 월요일 오전 9시(KST) node-cron으로 스케줄링하며, 발송 실패 시 1시간 간격으로 최대 6회 재시도한다. DeliveryHistory 테이블로 채널별 발송 이력을 관리하여 동일 식단표의 중복 발송을 방지하고, /식단 슬래시 커맨드로 이번 주 식단표를 즉시 조회할 수 있다. Clean Architecture로 도메인·애플리케이션·인프라 계층을 분리하고, TSyringe DI 컨테이너로 의존성을 관리하며, Result<T, E> 패턴으로 예외 대신 명시적 에러 처리를 구현했다.

주요 내용

  • Playwright 헤드리스 Chrome으로 카카오 채널 크롤링
  • Slack Bot Socket Mode + /식단 슬래시 커맨드 구현
  • 재시도 최대 6회(1시간 간격) + DeliveryHistory 중복 방지
  • Clean Architecture + TSyringe DI + Result<T, E> 패턴
  • Docker 컨테이너 배포 (Playwright 브라우저 포함)

성과 지표

성과 지표이전이후
재시도 횟수0최대 6회 (1시간 간격) (신뢰성)
중복 발송-0건 (DeliveryHistory)

기술 선택 근거

  • Clean Architecture + TSyringe DI: 크롤러·Slack 의존성 분리, 외부 서비스 교체 시 인프라 계층만 수정
  • Playwright 선택: 카카오 채널이 JS 렌더링 필요 — Cheerio(정적 HTML 파싱)로는 동적 콘텐츠 수집 불가
  • Result<T, E> 패턴: 예외 대신 명시적 에러 타입 반환으로 호출부에서 에러 처리 강제, 코드 예측 가능성 향상

깨달은 점

  • Playwright 헤드리스 브라우저로 JavaScript 렌더링이 필요한 카카오 채널 페이지를 크롤링하며, 동적 콘텐츠 크롤링에서의 대기 전략과 셀렉터 안정성 확보 방법을 학습
  • @slack/bolt Socket Mode로 Slack Bot을 구현하며, 슬래시 커맨드 핸들링과 메시지 포맷팅(Block Kit) 등 Slack 플랫폼 연동 패턴을 경험
  • DeliveryHistory 테이블 기반 멱등성 보장과 1시간 간격 최대 6회 재시도 메커니즘을 설계하며, 외부 서비스 연동에서의 신뢰성 확보 전략을 학습
  • Result<T, E> 패턴으로 예외 대신 명시적 에러 타입을 반환하며, 함수형 에러 처리가 코드의 예측 가능성과 테스트 용이성을 높이는 것을 체득

기술 스택

TypeScriptPlaywrightSlack Bot APIExpressPrismaSQLiteTSyringeDockerVitest