DevOps

Daily로 Flex 일정 Slack에 메시지 전송 자동화 하기 (개발부터 배포까지)

차니 ☻ 2025. 4. 17. 15:41

회사에서 근태 관리 툴로 `Flex`를 쓰고 있는데요.

내가 찾는 사람이 휴가, 재택근무, 출장, 외근 등의 사유로 사무실에 사람이 없을 때가 있잖아요?

그럴때마다 flex "일정"에 들어가서 해당 인원이 오늘 출근하는지를 확인했었거든요.

그 부분이 불편? 귀찮?아서 매일 특정 시간에 Slack으로 알림 받을 수 있도록 자동화하였습니다.

아래는 개발했던 과정 등을 정리합니다.

근무 유령 사내 공지
근무 유령 미리 보기

1. flex에서 일정 가져오기

일정을 슬랙에 쏴주기 위해 첫 번째로 필요했던게 `일정` 데이터인데요.

Flex에서 공식적으로 제공하고 있는 API는 없더라구요. 구글링해보니 flex 페이지를 분석해서 가져오시는 분들도 계셨는데, 그렇게까지 하고 싶진 않아서... 다른 방법으로 데이터를 가져오도록 했습니다.

flex에 구글 캘린더 연동하기

flex - 연결 설정 - Google Calendar

flex에서 Google Calendar를 연동하면, flex에서 등록한 일정(휴가, 재택, 출장, 외근 등 회사에서 설정한 근무 유형들)이 구글 캘린더에도 저장이 됩니다. 그런 점을 활용하여 Flex가 아닌 Google Calendar에서 데이터를 가져오도록 적용하였습니다.

제가 없어도 잘 돌아갈 수 있게 회사 대표 구글 계정으로 연동해주었습니다.
연동 전에 이미 등록되어 있는 일정은 Google Calendar에 등록되지 않아서
Flex 일정을 Google Calendar로 옮기는 작업을 1회 해주었습니다.

2. Python으로 Google Calendar에서 일정 가져오기

1. 서비스 계정 만들기

  1. Google Cloud Console 접속
  2. IAM 및 관리자 → 서비스 계정 → + 만들기
    • 이름: 예) calendar-bot
    • 역할: 프로젝트 > 편집자 (또는 최소한 Calendar API 쓸 수 있는 권한)
  3. 서비스 계정 완료되면
    • 새 키 만들기 → JSON 형식으로 다운로드 (service_account.json)

2. 구글 캘린더 공유 설정

  1. 구글 캘린더 들어가서
  2. 좌측 "캘린더 설정" → "특정 사용자와 공유" 섹션
  3. 아까 만든 서비스 계정 이메일 주소 추가 (ex: calendar-bot@your-project.iahttp://m.gserviceaccount.com)
  4. 권한 부여:
    • 보기(모든 세부정보) → 조회만
    • 변경 및 공유 관리 → 생성/수정까지 하고 싶으면

2. Python 패키지 설치

pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

3. Python 코드

import os
import datetime
from google.auth.transport.requests import Request
from google_auth_oauthlib.flow import InstalledAppFlow
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build

# 📌 사용할 권한 설정
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']

# 📁 인증 및 서비스 객체 생성 함수
def get_calendar_service():
    creds = None
    if os.path.exists('token.json'):
        creds = Credentials.from_authorized_user_file('token.json', SCOPES)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file('client_id.json', SCOPES)
            creds = flow.run_local_server(port=0)
        with open('token.json', 'w') as token:
            token.write(creds.to_json())
    return build('calendar', 'v3', credentials=creds)

# 📅 이벤트 조회 함수
def list_upcoming_events():
    service = get_calendar_service()

    # 현재 시간 기준으로 조회
    now = datetime.datetime.utcnow().isoformat() + 'Z'  # 'Z'는 UTC timezone 표시
    print('Getting the upcoming 10 events')

    events_result = service.events().list(
        calendarId='primary', timeMin=now,
        maxResults=10, singleEvents=True,
        orderBy='startTime'
    ).execute()
    events = events_result.get('items', [])

    if not events:
        print('No upcoming events found.')
    for event in events:
        start = event['start'].get('dateTime', event['start'].get('date'))
        print(start, event['summary'])

# 🚀 메인 실행
if __name__ == '__main__':
    list_upcoming_events()

여기까지 진행했다면 Google Calendar에서 일정을 가져올 수 있을 것이다.

3. 배포 - 슬랙에 매일 오전 9시에 푸시 보내기

아래 2가지 과정으로 배포 과정을 마쳤다.

  1. 파이썬 스크립트 도커로 image 빌드하기
  2. 해당 image 특정 시간에 실행 시키기(평일 오전 9시)
    • 추가적으로 공휴일에도 불필요하게 알림을 보내지 않도록 예외처리하였다.
    • 구글 캘린더 중 `대한민국 공휴일` 데이터를 가져와서 오늘 날짜가 포함되면, 수행하지 않도록했다.
def send_slack_message(message: str):
    log.info(f'\n오늘 사라진 사람들입니다 👻\n{message}')

    payload = {
        "attachments": [
            {
                "pretext": "*오늘 사라진 사람들입니다 👻*",
                "color": "#FF6B6B",
                "text": message
            }
        ]
    }

    headers = {"Content-Type": "application/json"}
    response = requests.post(WEBHOOK_URL, headers=headers, data=json.dumps(payload))

    if response.status_code == 200:
        print(f"✅ Slack 메시지 전송 성공!")
    else:
        print(f"❌ 슬랙 메시지 전송 오류 발생: {response.status_code}, {response.text}")

구글 캘린더에서 가져온 데이터를 가공하여 슬랙 웹훅으로 메시지를 보내도록 하였고,

#!/bin/bash

CRON_CMD="0 9 * * 1-5 docker run --rm flex-automation >> /tmp/flex.log 2>&1"

# 이미 등록돼 있는지 확인
(crontab -l 2>/dev/null | grep -qF "$CRON_CMD") && {
  echo "🌀 이미 등록되어 있어요!"
  exit 0
}

# 없으면 추가 등록
(crontab -l 2>/dev/null; echo "$CRON_CMD") | crontab -

echo "✅ 크론탭 등록 완료!"
crontab -l | grep flex-automation

매일 오전 9시에 파이썬 스크립트를 실행하도록 `crontab`을 등록하였다.

데이터가 없을 때도 처리를 해두었다!