파이썬 스케줄링: schedule 모듈로 정기 실행하기
그동안 뉴스 요약 메일 봇도 만들고, AI 요약 봇도 만들었잖아요. 근데 솔직히 좀 귀찮으셨죠? 매일 아침마다 컴퓨터 앞에 앉아서, 파일 열고, 실행 버튼 누르고. 봇을 만들었는데 정작 실행은 사람이 손으로 하고 있으니까요.
사실 지난 몇 편 동안 제가 계속 미뤄뒀던 게 하나 있어요. "이건 나중에 자동으로 돌리는 법 알려드릴게요" 하고 넘어갔던 거요. 이번에 그 약속을 지킬 차례예요.
오늘 배울 건 파이썬 스케줄링이에요. 쉽게 말해 "매일 아침 9시에 이 함수 좀 실행해줘" 라고 예약을 걸어두는 거예요. 그럼 정해진 시각에 알아서 돌아가거든요. schedule이라는 모듈 하나면 끝나요.
python schedule 모듈 설치와 기본 사용법
이 모듈은 파이썬에 기본으로 들어있는 게 아니에요. 그래서 먼저 설치를 해줘야 해요.
pip install schedule
설치가 끝났으면 가장 단순한 형태부터 볼게요.
import schedule # pip install schedule 로 먼저 설치해야 해요
def job():
print("실행됐어요!") # 예약된 시간에 이 문구가 출력됩니다
# 매일 오전 9시에 job 함수를 실행하도록 예약
schedule.every().day.at("09:00").do(job)
여기서 잠깐, 이 한 줄 좀 소리 내서 읽어보세요.
every().day.at("09:00").do(job)
"every day at 09:00 do job" — 그대로 영어 문장이에요. "매일 9시에 job 실행해줘." 이게 이 모듈이 사랑받는 이유예요. 코드가 그냥 문장처럼 읽히거든요.
이걸 저는 알람 시계라고 생각해요. 정해진 시간에 울리도록 맞춰둔 알람이요. 몇 시에 울릴지 딱 정해두는 것까지가 방금 한 일이에요.
정기 실행을 위한 감시 루프 (이게 진짜 핵심이에요)
근데 여기서 처음 배우는 분들이 거의 100% 막혀요. 위 코드를 실행하면요...
아무 일도 안 일어나요.
9시가 돼도 조용해요. "어? 예약 걸었는데 왜 안 돌아요?" 하고 당황하시거든요. 저도 처음에 그랬어요.
이유는 이거예요. every().day.at("09:00").do(job)은 "예약만 걸어둔 것"이에요. 알람 시간을 맞춰만 놓은 상태예요. 근데 정작 그 시간이 됐는지 지켜보는 사람이 없어요.
그 지켜보는 사람 역할을 하는 게 바로 이 루프예요.
import schedule
import time # time.sleep 을 쓰려면 필요해요
def job():
print("실행됐어요!")
# 테스트용: 3초마다 실행 (실전에선 every().day.at("09:00") 로 바꾸세요)
schedule.every(3).seconds.do(job)
while True: # 프로그램이 계속 돌면서
schedule.run_pending() # 지금 실행할 예약이 있으면 실행하고
time.sleep(1) # 1초 쉬었다가 다시 확인해요
실행 결과 (3초마다 한 줄씩):
실행됐어요!
실행됐어요!
실행됐어요!
이 while True 루프가 바로 알람을 지켜보는 사람이에요. "지금 울릴 시간인가?" 하고 1초마다 시계를 힐끔거리는 거죠. run_pending()이 "지금 실행할 예약 있어?" 하고 확인하는 함수예요.
이 사람이 자리를 뜨면(=루프가 멈추면) 아무도 알람을 봐주지 않아요. 그래서 예약(do)만 있고 이 루프가 없으면 절대 안 돌아가요. 이거 하나만 기억하셔도 오늘 반은 성공이에요.
참고로 time.sleep(1)도 꼭 넣으세요. 이걸 빼면 컴퓨터가 쉬지도 않고 계속 시계만 확인하느라 CPU를 엄청 잡아먹어요. 1초 쉬어주는 게 배려예요.
do(job)이랑 do(job())은 완전 달라요
이건 진짜 많이들 하시는 실수라 따로 짚을게요. 괄호 하나 차이인데 결과가 완전히 달라져요.
schedule.every().day.at("09:00").do(job) # O 이렇게!
schedule.every().day.at("09:00").do(job()) # X 괄호 붙이면 안 돼요
do(job)은 "이 심부름 좀 해줘" 하고 할 일 자체를 맡기는 거예요. do(job())은 내가 지금 그 심부름을 다 해버리고 결과만 넘기는 거고요.
job()처럼 괄호를 붙이면 그 자리에서 함수가 즉시 한 번 실행돼버려요. 그리고 예약에는 job의 실행 결과(보통 None)가 걸려서 이후로는 아무것도 안 돌아가요. 증상이 딱 이래요. "프로그램 켜자마자 한 번 실행되고, 그 뒤론 감감무소식이에요." 이러면 십중팔구 괄호 범인이에요. 빼주면 해결돼요.
다양한 주기로 예약하기
매일 9시 말고도 원하는 대로 걸 수 있어요.
schedule.every().day.at("09:00").do(morning_job) # 매일 오전 9시
schedule.every().hour.do(hourly_job) # 매 시간마다
schedule.every(30).minutes.do(check_job) # 30분마다
schedule.every().monday.at("08:30").do(weekly_job) # 매주 월요일 8시 30분
schedule.every(3).seconds.do(test_job) # 3초마다 (테스트용)
시간은 꼭 24시간제 문자열로 써야 해요. 오후 2시 30분은 "14:30"이에요. "2:30 PM"이나 "2:30"은 안 돼요. 그리고 앞자리 0도 빼먹으면 안 돼요. 9시는 "9:00"이 아니라 "09:00"이에요.
그리고 팁 하나. 테스트할 땐 every(3).seconds처럼 짧은 주기로 걸어서 진짜 도는지 먼저 확인하세요. 매일 9시로 걸어놓고 하루 기다릴 순 없잖아요. 잘 돌면 그때 진짜 시각으로 바꾸면 돼요.
함수에 값을 넘겨줘야 할 때
함수에 인자가 필요하면 어떻게 할까요? do() 뒤에 함수랑 인자를 따로 넘겨주면 돼요.
def send_report(name):
print(f"{name} 님께 보고서 발송!") # 넘겨받은 이름으로 출력
# do() 뒤에 함수와 인자를 따로! (send_report("김철수") 아니에요)
schedule.every().day.at("18:00").do(send_report, "김철수")
여기서도 위에서 말한 괄호 규칙이 그대로예요. do(send_report, "김철수")처럼 쉼표로 나눠서 넘겨요. do(send_report("김철수"))가 아니고요.
실전: 뉴스 메일 봇을 매일 아침 자동으로
자, 이제 진짜 써먹어 볼게요. 20편에서 만들었던 뉴스 요약 메일 봇 기억나세요? 그걸 매일 아침 7시에 자동으로 보내지도록 얹어볼게요.
import schedule
import time
# from news_bot import send_news_mail # 지난 뉴스 메일 편에서 만든 함수 가져오기
def send_news_mail():
# 뉴스 수집 + 요약 + 메일 발송을 하는 함수라고 생각하세요
print("오늘의 뉴스 요약 메일을 보냈어요.")
# 매일 아침 7시에 뉴스 메일 자동 발송
schedule.every().day.at("07:00").do(send_news_mail)
print("스케줄러 시작. 이 창을 켜두면 매일 아침 7시에 메일이 나가요.")
while True:
schedule.run_pending()
time.sleep(1)
이제 이 프로그램만 켜두면 아침마다 알아서 메일이 나가요. 손 안 대도 돼요. 그동안 매일 아침 손으로 실행하던 게 이렇게 한 번에 정리되는 거예요.
솔직히 짚고 넘어갈 한계 하나
근데 여기서 저 방금 문장에 함정이 숨어 있어요. "이 프로그램만 켜두면"이라고 했잖아요.
바로 그게 이 방식의 한계예요.
schedule 모듈은 내 컴퓨터에서 이 파이썬 프로그램이 켜져서 while 루프를 돌고 있을 때만 작동해요. 다시 알람 시계 비유로 돌아가면, 시계에 배터리가 들어 있어야 울리는 거랑 같아요. 배터리를 빼면 아무리 시간이 돼도 안 울리잖아요.
여기서 배터리를 빼는 행동이 뭐냐면요.
- 컴퓨터를 끄면 → 멈춰요
- 절전(잠자기) 모드로 들어가면 → 멈춰요
- 터미널 창을 닫으면 → 멈춰요
- 노트북 덮으면 → 멈춰요
그러니까 "매일 아침 7시 뉴스 메일"을 진짜로 받으려면, 그 시각에 컴퓨터가 켜져 있고 이 프로그램이 돌고 있어야 해요. 밤에 노트북 덮고 자면? 아침에 메일 안 와요. 이게 처음엔 배신감(?) 들 수 있는데, 원래 그런 거예요.
진짜 24시간 무인 운영, 그러니까 내 컴퓨터를 꺼놔도 알아서 돌아가는 건 이 방법만으로는 부족해요. 그건 나중에 클라우드에 올리는 편에서 제대로 다룰 거예요. 지금은 "내 컴퓨터가 켜져 있는 동안 자동으로"까지가 우리 목표예요.
참고: 컴퓨터가 대신 켜주는 방식도 있어요
방금 한계 얘기를 들으면서 "그럼 프로그램을 계속 켜두는 것 말고 다른 방법은 없나?" 싶으실 수 있어요. 있긴 있어요. 접근 방식이 좀 달라요.
schedule 모듈은 "파이썬 프로그램이 스스로 시계를 보며 기다리는" 방식이에요. 반대로 운영체제가 정해진 시각에 스크립트를 대신 켜주는 방식도 있어요. 일종의 건물 관리인 같은 거예요. 내가 프로그램을 안 띄워놔도 관리인(운영체제)이 시간 맞춰 문 열고 켜주는 거죠.
윈도우에는 작업 스케줄러라는 게 있어요. "매일 오전 9시에 이 파이썬 파일을 실행" 이런 걸 등록해두는 도구예요. 맥이나 리눅스에는 cron이라는 게 같은 역할을 하고요. 이건 프로그램을 계속 켜둘 필요가 없다는 장점이 있는 대신, 설정이 코드 밖 OS 영역이라 처음엔 살짝 번거로워요. 오늘은 "이런 방식도 있구나" 정도만 알아두시면 충분해요.
처음에 많이 하는 실수들
- while 루프를 안 넣음: 예약만 걸고 프로그램이 그냥 끝나버려요. 가장 흔한 좌절 포인트예요.
while True: schedule.run_pending(); time.sleep(1)꼭 붙이세요. do(job())처럼 괄호 붙임: 등록하는 순간 함수가 한 번 실행돼버리고 예약은 안 걸려요. 괄호 빼세요.import time빠뜨림:time.sleep(1)쓰는데import time을 안 하면NameError: name 'time' is not defined에러가 나요. 맨 위에 추가해주세요.time.sleep(1)을 뺌: 루프가 쉬지 않고 돌면서 CPU를 100% 가까이 써요. 컴퓨터가 뜨거워지고 팬이 돌아가죠.- 시각 표기 오류:
"09:00"두 자리 24시간제로."9:00","09:00 AM"다 안 돼요.
직접 해보세요
지금까지 만든 봇 중에 하나 골라보세요. 뉴스 메일이든 AI 요약이든 뭐든요. 그걸 원하는 시각에 매일 자동 실행되도록 스케줄을 걸어보는 거예요.
바로 진짜 시각으로 걸지 말고, 먼저 every(5).seconds로 5초마다 잘 도는지 확인부터 하세요. 콘솔에 결과가 5초마다 찍히면 성공이에요. 그다음에 every().day.at("09:00")처럼 진짜 시각으로 바꾸면 돼요.
힌트: import schedule이랑 import time 둘 다 맨 위에 있는지, 그리고 맨 아래 while True 루프가 있는지 이 두 개만 확인하면 거의 다 돌아가요.
이제 봇을 자동으로 돌릴 수 있게 됐어요. 근데 자동으로 굴러가다 보면 새로운 문제가 생겨요. 밤중에 봇이 조용히 죽어 있는 거예요. 에러가 나서 멈췄는데, 언제 왜 죽었는지 알 수가 없어요. 아침에 "어? 메일이 왜 안 왔지?" 하고서야 알게 되죠.
그래서 다음 편에서는 봇이 죽어도 바로 알아채고 기록을 남기는 방법, 그러니까 로깅이랑 에러 알림을 다뤄볼 거예요. 자동화의 진짜 안정성은 여기서부터 시작이거든요.
제 글이 도움이 되셨다면 댓글 & 공감 부탁드려요 😀
'Application > Python' 카테고리의 다른 글
| [Python] 25. 파이썬 Pillow로 이미지 일괄 처리하기 (리사이즈와 워터마크) (0) | 2026.08.14 |
|---|---|
| [Python] 24. 파이썬 로깅과 에러 알림: 봇이 죽지 않게 지키기 (0) | 2026.08.13 |
| [Python] 22. 파이썬으로 AI 문서 요약과 번역 봇 만들기 - 긴 문서도 통째로 (0) | 2026.08.07 |
| [Python] 21. 파이썬으로 ChatGPT API 호출하기 - AI에게 텍스트 처리 자동으로 시키기 (0) | 2026.08.04 |
| [Python] 20. 파이썬 뉴스 봇 만들기 - 매일 아침 관심 뉴스 요약 메일 받기 (1) | 2026.08.03 |