AI·

매일 아침 슬랙으로 오는 데일리 스크럼 봇

위키에 쌓인 Jira 데이터를 바탕으로 매일 아침 팀원에게 DM으로 스크럼을 보내는 슬랙봇을 만든 기록. 담당자별 데이터 정리, Block Kit 메시지, 그리고 흩어진 설정을 config 하나로 합친 과정을 정리합니다.

위키가 채워졌으니(지난 글), 이제 이 지식을 실제로 써먹을 차례였습니다. 첫 번째로 만든 건 데일리 스크럼 봇입니다. 매일 아침, 팀원 각자에게 슬랙 DM으로 "당신의 오늘 스크럼"을 보내 주는 봇이죠.

스크럼을 자동화하고 싶었다

원하는 그림은 단순했습니다.

매일 아침, 각 팀원에게 DM으로 — 진행 중인 이슈, 진행 예정, 최근 완료를 정리해서 보내 준다.

스크럼 회의 전에 "내가 뭘 하고 있었지?"를 스스로 떠올리게 해 주는 리마인더입니다. 매번 Jira를 뒤지지 않아도 되게요.

데이터는 이미 있다 — 위키를 재활용

처음엔 스크럼용으로 Jira를 따로 조회하려 했는데, 곧 착오를 깨달았습니다. 우리는 이미 1시간마다 Jira를 수집해서 위키에 넣고 있었습니다. 스크럼봇이 Jira API를 또 부를 이유가 없었죠.

그래서 스크럼봇은 위키 데이터만 읽습니다. 별도 조회 없이, 이미 정리된 지식 베이스를 근거로 브리핑을 만듭니다. 파이프라인을 한 번 잘 만들어 두니, 그 위에 얹는 기능이 이렇게 가벼워졌습니다.

담당자별로 나눠 담기

각 사람에게 "그 사람의" 이슈를 보내려면, 위키가 담당자 기준으로 정리돼 있어야 편합니다. 그래서 요약(ingest) 단계에서 Jira를 담당자별로 미리 나눠 두게 했습니다.

wiki/
└── assignees/
    ├── 담당자-A.md
    ├── 담당자-B.md
    └── ...

스크럼을 보낼 때는 이 담당자 파일을 읽어 그 사람의 진행 중·예정·완료를 추립니다. 팀 전체로 확대할 때도 사람마다 설정을 새로 쓸 필요가 없습니다 — 담당자 목록에서 자동으로 대상이 정해지고, 설정 파일에는 제외할 사람만 관리합니다. (막 합류한 사람이나 봇 대상이 아닌 계정을 빼는 용도죠.)

봇 채널 말고 DM으로

처음엔 채널에 봇 메시지를 올렸는데, 스크럼은 개인적인 내용이라 DM이 맞았습니다. 슬랙 API로 사용자에게 직접 메시지를 보내도록 바꿨습니다.

한 가지 현실적인 제약도 알게 됐습니다. 담당자 목록에 이름이 있어도, 슬랙 워크스페이스에 없는 사람에겐 보낼 수 없습니다. 그래서 전송 결과를 "몇 명 중 몇 명 성공"으로 로그에 남겨, 누락을 바로 알 수 있게 했습니다.

메시지는 Block Kit으로

밋밋한 텍스트 대신, 슬랙의 Block Kit으로 구조를 줬습니다. 섹션을 나누고, 진행 중·진행 예정·최근 완료(5건)를 구획해서 한눈에 읽히게요.

{
  "blocks": [
    { "type": "header", "text": { "type": "plain_text", "text": "오늘의 스크럼" } },
    { "type": "section", "text": { "type": "mrkdwn", "text": "*진행 중*\n• PROJ-000 …" } },
    { "type": "section", "text": { "type": "mrkdwn", "text": "*진행 예정*\n• PROJ-000 …" } },
    { "type": "section", "text": { "type": "mrkdwn", "text": "*최근 완료*\n• PROJ-000 …" } }
  ]
}

처음엔 각 이슈 옆에 "Jira로 이동" 버튼도 달았는데, 결국 뺐습니다. 이슈 키 자체에 링크가 걸려 있으니 버튼은 군더더기였습니다. 필요 없는 UI는 덜어내는 게 메시지를 더 깔끔하게 만들었습니다.

설정 지옥 탈출: config.json 하나로

기능이 늘면서 설정 파일이 우후죽순 늘었습니다. 스크럼 설정 따로, 수집 설정 따로, .env에 토큰 따로… 서버에 배포할 때마다 어디에 뭘 넣어야 하는지 헷갈렸습니다.

그래서 흩어진 *_config.json.env 값을 하나의 config.json으로 통합했습니다. 앱은 이 파일 하나만 읽고, 민감한 값(토큰 등)만 환경 변수로 덮어쓸 수 있게 남겨 뒀습니다.

{
  "slack":  { "bot_token": "<슬랙 봇 토큰>", "scrum_enabled": true, "scrum_hour": 9 },
  "scrum":  { "exclude": ["제외할-담당자"] },
  "sync":   { "interval_hours": 1 }
}

설정이 한곳에 모이니, "서버에 새로 깔 때 뭘 채워야 하나"라는 질문에 파일 하나로 답할 수 있게 됐습니다.

운영에서 배운 것

  • 새 기능은 기존 파이프라인 위에 얹으면 가벼워진다. 스크럼봇은 위키를 읽기만 했다.
  • 개인적인 알림은 채널이 아니라 DM.
  • 버튼 하나라도, 없어도 되면 뺀다.
  • 설정은 흩어질수록 배포가 지옥이 된다. 한곳으로 모으자.

스크럼봇은 "위키가 사람에게 먼저 말을 거는" 첫 사례였습니다. 다음은 반대 방향입니다 — 사람이 위키에게 물어보면 답하는 QA 봇다음 글에서 만듭니다.