콘텐츠로 이동
🗓️ 기록기존 내용은 절대 지우지 말고, 새 항목만 날짜와 함께 추가하세요(포맷: templates/log).작성 Claude · 2026-06-01 · v12 재편·raw 컴파일·인간화

ADR-0014 — 자동화 인프라 디자인

Context

ADR-0013은 협업 wiki 진입점 정책을 박제했다 — "Slack @wiki-bot 멘션 → raw 박제 → GitHub Issue 게이트 → 본인 라벨 클릭 → wiki PR". 그러나 실제 동작에 필요한 인프라가 미존재:

  • Slack bot 라이브러리·호스팅 미선택
  • GitHub Action 구조·라벨·시크릿 미정
  • PII redact·dedupe·서명 검증 등 보안 정책 미정
  • 월 비용·구현 공수 미추정

본 ADR은 ADR-0013 정책을 동작시킬 인프라 결정. 외부 조사 1라운드 기반(2026-05-25) — Slack Bolt SDK / Cloudflare Workers / AWS Lambda / Vercel / n8n / Zapier / Slack Workflow Builder / GitHub Action 패턴 / claude-code-action / NIST AI RMF GenAI Profile / Slack 2025-05-29 rate limit 변경 등.

본 ADR은 결정 ADR — 실제 코드(.github/workflows/wiki-ingest-from-issue.yml, Slack bot 코드, 라벨 생성)는 별도 구현 라운드.

Decision

§A — 스택 (5축 단일 결정)

항목 채택 핵심 이유
Slack bot 라이브러리 Slack Bolt JS 공식 SDK / app_mention·reactions_added·message 풀 지원 / 서명 검증 자동
봇 호스팅 Cloudflare Workers V8 isolate 콜드스타트 0ms (Slack 3초 SLA 안전) / 100K req/일 free / 전 세계 edge PoP
GitHub Action 트리거 Stage1 repository_dispatch + Stage2 issues.labeled ADR-0013 2단계 분리와 정확 일치
Claude 진입 anthropics/claude-code-action@beta 공식 GitHub Action / 기존 Claude Code OAuth 시크릿 재사용 / allowed_tools로 권한 제한
GitHub 인증 GitHub App + actions/create-github-app-token@v1 Rate limit 15K/h / fine-grained PAT의 "Resource not accessible" 403 이슈 회피 / 팀 확장 안정

§B — 흐름도 (ADR-0013 §A 인프라 구체화)

[팀원] Slack `@wiki-bot` 멘션 또는 `#wiki-inbox` 게시
   ↓ HTTPS POST (Slack Events API, X-Slack-Signature)
[Cloudflare Workers — Slack Bolt JS]
   ↓ HMAC SHA256 서명 검증 (Bolt 자동, ±300s timestamp)
   ↓ Workers KV로 event_id dedupe (1분 TTL)
   ↓ 3초 안에 200 OK ack
   ↓ 비동기:
      ├─ Notion 링크 추출 → Notion API fetch
      ├─ PII redact (정규식·presidio 패턴)
      └─ GitHub repository_dispatch (event_type: "wiki-inbox", client_payload)
[GitHub Action: wiki-stage1.yml]
   on: repository_dispatch (types: [wiki-inbox])
   - raw/notion/<page>.md 또는 raw/meetings/<yyyy-mm-dd>-<slug>.md 박제
   - Issue 자동 생성 (제목 + 본문 + 자동 분류 라벨)
   - 자동 라벨링 (LLM 본문 분석 → wiki:반영 / wiki:참고 / wiki:금지)
   ↓ Slack chat.postMessage → #wiki-notify
   "raw/<...> 박제 완료 / Issue #N / 자동 분류: {반영|참고|금지}"
[본인] Issue review (GitHub 웹·앱)
   - 라벨 재분류 가능
   - `wiki:컴파일` 라벨 부착
[GitHub Action: wiki-stage2.yml]
   on: issues: types: [labeled]
   if: github.event.label.name == 'wiki:컴파일'
   - actions/create-github-app-token@v1로 App token 발급
   - anthropics/claude-code-action@beta 호출
     allowed_tools: Read, Edit, Write, Bash (제한)
   - Claude agent가 Issue 본문·코멘트·라벨 읽어 wiki PR 생성
   ↓ Slack chat.postMessage → #wiki-notify "wiki PR #M 생성됨"
[본인] PR review + merge
[GitHub Action: wiki-stage3.yml] (선택)
   on: pull_request: types: [closed], if: merged
   - /log-append 자동
   - Issue auto-close
   ↓ Slack chat.postMessage → #wiki-notify
   "wiki/<...> 갱신 완료 / Issue #N close / log entry +1 / PR 링크"

wiki:금지 라벨이 붙은 Issue는 Stage2 트리거 X — auto-close + Slack 알림으로 "PR 생성 X" 통지.

§C — Issue 라벨 (색·자동/수동)

라벨 색 (hex) 의미 부착 주체
wiki:raw #ededed ⚪ light Stage1 기본 category (미분류 raw 박제) 자동 (Stage1 기본값)
wiki:반영 #0e8a16 🟢 green 정식 wiki 페이지 갱신 후보 자동 (Stage1 LLM 분류)
wiki:참고 #fbca04 🟡 yellow wiki/inbox/ draft만 자동
wiki:금지 #d93f0b 🔴 red/orange PII·기밀 — 반영 금지 자동 (Stage1 PII 룰)
wiki:컴파일 #1d76db 🔵 blue 본인 review 후 Stage2 trigger (wiki PR 생성) 수동 (본인)
wiki:auto #c5def5 🔵 light Stage2가 만든 wiki PR 표식 (Stage3 게이트) 자동 (Stage2)
wiki:stale #cccccc ⚪ gray 1주+ 미반영 알림 (별도 cron, 미구현) 자동 (예정)

실제 구현값 기준(wiki-stage1~3.yml): Stage2 트리거 = wiki:컴파일, Stage2 산출 PR = wiki:auto, Stage1 기본 category = wiki:raw. (구 설계의 wiki:ready-to-ingestwiki:컴파일로 대체됨.)

라벨 생성은 GitHub repo 설정에서 1회 (또는 actions/labels@v2로 declarative 관리).

§D — 시크릿 매트릭스

시크릿 이름 신규/재사용 출처 권한
SLACK_BOT_TOKEN 신규 api.slack.com (App 생성) app_mentions:read, reactions:read, chat:write, channels:history
SLACK_SIGNING_SECRET 신규 api.slack.com (App 생성) HMAC 검증 전용
WIKI_BOT_APP_ID 신규 github.com/settings/apps App 식별
WIKI_BOT_APP_PRIVATE_KEY 신규 동상 App 인증
NOTION_API_KEY 재사용 기존 .mcp.json·NOTION_API_KEY env 페이지 read
CLAUDE_CODE_OAUTH_TOKEN 재사용 기존 claude.yml 시크릿 claude-code-action 표준

GitHub App 권한: contents:write + issues:write + pull_requests:write + metadata:read. Repo는 idealstudy/mvp-mono만 설치 (구 mvp-back에서 rename).

§E — 보안 (4축)

  1. Slack 서명 검증 — Bolt JS가 X-Slack-Signature HMAC SHA256 + X-Slack-Request-Timestamp ±300s 자동 검증. SLACK_SIGNING_SECRET만 환경변수로 주입.
  2. PII auto-redact — Workers 함수 진입 시 정규식 패턴(이메일·전화·주민번호·카드번호) + (선택) presidio·AWS Comprehend 호출. redact 후 raw 박제·Issue 생성. NIST AI RMF GenAI Profile (AI 600-1) 준수.
  3. 권한 escalation 차단repository_dispatch client_payload는 화이트리스트 필드(source·raw_path·category·slack_thread_url)만. Stage2의 claude-code-action allowed_tools를 Read·Edit·Write·Bash 등 제한, --max-turns 10 명시.
  4. Rate limit·idempotency — Slack Events API 워크스페이스당 30K/h (충분). Workers KV로 event_id 1분 TTL dedupe. 실패 시 exponential backoff 재시도. Stage2 GitHub Action timeout-minutes: 15.

§F — 비용 (월 추정, 1인 + 3~5명 합류 기준)

항목 비용 비고
Cloudflare Workers $0 free tier 100K req/일 (예상 1500~3K req/월의 200배 마진)
Slack Free plan $0 Bolt SDK 무료, Events API 사용
GitHub Actions $0 private repo 2000분/월 free (Stage1·2·3 합쳐 50~200분 추정)
Workers KV (dedupe) $0 1K write/일 free
Anthropic Claude (Max OAuth) 기존 claude.yml 이미 운영 — 증분 0
Notion API $0 기존 계정
합계 $0 증분

확장 시 (수십명·일 1만 req+): Workers Paid $5/월 + Slack Pro $7.25/user/월 검토.

§G — 구현 공수 (6 인일, 약 1~1.5주)

단계 인일
Slack App 생성·OAuth scope·signing secret 발급 0.5
Cloudflare Workers 프로젝트 + Bolt JS 보일러플레이트·서명 검증·ack 1.0
Stage1 wiki-stage1.yml: repository_dispatch + Notion fetch + raw 박제 + Issue·자동 라벨 1.5
Stage2 wiki-stage2.yml: issues.labeled → claude-code-action wiki PR 1.0
라벨 5개 repo 생성 + #wiki-notify broadcast (Bolt → chat.postMessage) 0.5
PII redact 정규식·Workers KV dedupe·timeout·재시도 1.0
E2E QA (Slack 멘션 → PR merge 1회 통과) 0.5
합계 6.0 인일

§H — 왜 "서버리스"인가 (전용 백엔드 상시 서버 대비)

§A는 여러 서버리스 중 Workers를 택한 이유(0ms 콜드스타트·free·edge)를 정했다. 그러나 d-edu는 이미 상시 백엔드(mvp-back Spring Boot, EC2/온프레 — ADR-0017)를 운영 중이다. 따라서 진짜 물어야 할 것은 "왜 거기 엔드포인트 하나 붙이지 않고 별도 서버리스를 두는가?"다.

서버리스 (Cloudflare Workers) 운영 백엔드(mvp-back)에 붙이기 / 상시 서버
장애 격리 (blast radius) 봇의 장애·배포가 운영 서비스와 완전 분리 봇 트래픽·버그·배포가 학생이 쓰는 학습 서비스에 전파. 실제로 2026-05-31 온프레 bridge 통신 단절로 dev 백엔드 502 발생 — 봇을 결합했다면 동반 사망
관심사·스택 분리 Slack·GitHub glue = JS/TS, 도메인과 격리 Java/Spring 도메인 코드에 Slack SDK·glue 의존성 오염, 빌드·배포 결합
워크로드 적합성 간헐적·무상태·짧은 이벤트(월 1.5~3K req) = 서버리스 정석. 평소 0 → 6모 스파이크 자동 스케일 간헐 트래픽에 24/7 구동 = 낭비. 스케일·가용성 수동 부담
비용·운영 $0(free tier) + 인프라 관리 0(wrangler deploy 한 방) 상시 컴퓨트 비용 + OS·런타임·모니터링·배포 파이프라인
SLA V8 isolate 0ms → Slack 3초 ACK 안전 상시 서버면 콜드스타트는 없으나 위 비용을 치름

원칙: 운영 서비스(학생 트래픽·학습 데이터)와 사내 자동화(wiki-bot)는 생명주기·장애 도메인을 섞지 않는다. glue·이벤트성·무상태 워크로드는 서버리스로, 도메인·상태성 워크로드는 백엔드로 — 워크로드 성격으로 가른다.

트레이드오프(§부정과 동일): Workers는 JS/TS·짧은 실행 전용. 무겁거나 장기 실행·Java 로직이 필요해지면 그 부분만 mvp-back 또는 Lambda로 분리.

Consequences

긍정

  • 월 $0 증분 — 모든 인프라 free tier 내. 학습·실험에 부담 0
  • 콜드스타트 0ms — Workers V8 isolate가 Slack 3초 SLA 안전
  • 기존 자산 100% 재사용NOTION_API_KEY, CLAUDE_CODE_OAUTH_TOKEN, GitHub Actions 11개 인프라
  • 2단계 분리로 LLM 환각 사고 차단ADR-0013 §G 정책 인프라로 1:1 매핑
  • provenance 3겹 — Slack thread + GitHub Issue + wiki/log.md
  • edge computing·서버리스 학습 효과 — d-edu 자동화가 첫 프로젝트로 적절

부정

  • 초기 셋업 일회성 공수 — Slack App·Cloudflare 계정·GitHub App 발급 등 6 인일 (1~1.5주)
  • Workers JS·TypeScript만 지원 — Python·Java 코드 필요 시 Lambda로 이전
  • Bolt JS + Workers + claude-code-action 학습 ramp (1주 정도)
  • GitHub App 발급 30분~1시간 (PAT는 5분)
  • Slack workspace 권한 관리 — 비-CLI 팀원 변동 시 추가 운영
  • PII redact 정규식 의존 — 한국어 PII(주민번호·전화) 외 케이스 누락 가능 → 실제 사고 발생 시 presidio·Bedrock Guardrails 업그레이드 필요

Alternatives 거부

옵션 거부 사유
AWS Lambda + API Gateway 콜드스타트 100~500ms (Java/Python)로 Slack 3초 SLA 위험. ack 패턴으로 우회 가능하나 복잡도 ↑. IAM 학습 비용
Vercel Edge Functions Hobby tier non-commercial 전용. 상용 시 Pro $20/user/월 발생
n8n self-host (Docker) DigitalOcean/EC2 월 $5~$15 비용. 워크플로 JSON export로 git과 비대칭 버전 관리. UI는 빠르나 PII redact·dedupe는 코드 노드로 우회 필요
n8n Cloud / Zapier / Make task 한도 빠르게 소진 (Zapier 100/월, Make 1K ops/월). PII redact 어려움. lock-in ↑
Slack Workflow Builder 유료 플랜 전용. 키워드 trigger 채널 20개 제약. 코드 hook 한계
Slack outgoing webhook only reactions_added event 불가 (ADR-0013 §F 알림 정책 위반). legacy 카테고리 — Slack이 Events API 마이그레이션 권고
GitHub Action만 (outgoing webhook → repo_dispatch) Slack 3초 SLA 위반 — Actions 부팅 30~60s. ack 레이어 필요 → Workers와 동일 구조
fine-grained PAT "Resource not accessible" 403 빈번. Rate limit 5K/h. 사용자 권한 종속 (회사 떠나면 토큰 죽음)

향후 검토 항목

  1. 실제 구현 라운드 (Track Wiki-Bot, 6 인일)
  2. Slack App 생성 + OAuth scope + Bolt JS Workers 보일러플레이트
  3. GitHub App 발급 + WIKI_BOT_APP_ID·WIKI_BOT_APP_PRIVATE_KEY 시크릿 등록
  4. Cloudflare 계정 + Workers 프로젝트 + KV namespace
  5. wiki-stage1.yml·wiki-stage2.yml·wiki-stage3.yml 작성
  6. 라벨 5개 GitHub repo 생성
  7. PII redact 정규식·dedupe·timeout 구현
  8. E2E 검증 (Slack 멘션 → PR merge 1회)
  9. ADR-0015 디자이너·마케터 워크플로 — 본 인프라 그대로 재사용 (멘션 태그만 #design·#marketing 추가)
  10. 확장 시 Workers Paid·Slack Pro — 월 1만 req 이상 도달 시
  11. PII redact 업그레이드 — 정규식 → presidio·AWS Bedrock Guardrails (실제 PII 사고·법적 요구 발생 시)
  12. GitHub App → Slack App marketplace 등록 (오픈소스화·외부 사용 시)

Status

  • 2026-05-25: accepted

Date

2026-05-25