중복 파일 삭제 스크립트를 돌렸다가 식은땀 흘린 날
"거래처와 잡힌 미팅 10건을 엑셀로 정리했는데 캘린더에는 또 하나씩 입력해야 한다", "프로젝트 마감일 목록을 팀원 전체 캘린더에 동시에 등록해야 한다", "정기 점검 일정을 매달 캘린더에 반복 입력하는 게 번거롭다"…
이 블로그의 구글 스프레드시트 자동화 편에서 소개한 것과 같은 방식의 구글 API 인증을 활용하면, 엑셀에 정리된 일정 목록을 구글 캘린더에 자동으로 등록할 수 있습니다. 참석자 초대, 알림 시간 설정까지 코드 한 번 실행으로 처리됩니다.
구글 스프레드시트 연동 편과 마찬가지로 구글 클라우드에서 API를 활성화해야 합니다. 이미 이전 게시글에서 서비스 계정을 만들어보셨다면 아래 3~4번만 추가하면 됩니다.
client_email 값)을 "일정 변경 권한"으로 공유합니다.⚠️ 마지막 설정이 가장 중요합니다: 캘린더 공유 설정을 빠뜨리면 API는 정상 작동하지만 "권한 없음" 오류가 발생합니다. 반드시 캘린더 설정에서 서비스 계정 이메일을 추가하고 "일정 변경" 권한까지 부여해야 합니다.
터미널(윈도우: CMD 또는 파워셸)을 열고 아래 명령어를 실행하세요:
pip install google-api-python-client google-auth pandas openpyxl
google-api-python-client는 구글 캘린더 API를 호출하는 라이브러리입니다. google-auth는 서비스 계정 인증을 처리하고, pandas와 openpyxl은 엑셀 일정 목록을 읽는 데 사용합니다.
아래처럼 일정 정보를 엑셀로 정리합니다.
제목 날짜 시작시간 종료시간 장소 참석자이메일 A사 미팅 2026-07-01 14:00 15:00 본사 3층 partner@example.com 프로젝트 마감 2026-07-05 09:00 09:00 - team@example.com 정기 점검 2026-07-10 10:00 11:00 서버실 -
아래 코드를 그대로 복사해서 메모장에 붙여넣고, calendar_add.py로 저장하세요. 저장 시 파일 형식은 "모든 파일", 인코딩은 UTF-8로 설정합니다.
from googleapiclient.discovery import build
from google.oauth2.service_account import Credentials
import pandas as pd
from datetime import datetime, timedelta
# ① 설정
CREDENTIALS_FILE = "credentials.json" # ← 구글 스프레드시트 편에서 만든 JSON 키
EXCEL_PATH = r"C:\Users\내이름\Desktop\일정표.xlsx" # ← 일정 목록 엑셀
CALENDAR_ID = "내이메일@gmail.com" # ← 등록할 캘린더 ID (보통 본인 이메일)
REMINDER_MIN = 30 # ← 일정 시작 몇 분 전에 알림을 받을지
# ② 구글 API 인증
SCOPES = ["https://www.googleapis.com/auth/calendar"]
creds = Credentials.from_service_account_file(CREDENTIALS_FILE, scopes=SCOPES)
service = build("calendar", "v3", credentials=creds)
print(" ✔ 구글 캘린더 API 인증 완료")
# ③ 엑셀 일정 목록 읽기
df = pd.read_excel(EXCEL_PATH, engine="openpyxl")
print(f" ✔ 일정 목록 로드: {len(df)}건")
# ④ 각 행을 캘린더 일정으로 등록
success = 0
failed = 0
for _, row in df.iterrows():
try:
date_str = pd.to_datetime(row["날짜"]).strftime("%Y-%m-%d")
start_str = f"{date_str}T{row['시작시간']}:00"
end_str = f"{date_str}T{row['종료시간']}:00"
event = {
"summary": str(row["제목"]),
"location": str(row["장소"]) if pd.notna(row.get("장소")) else "",
"start": {"dateTime": start_str, "timeZone": "Asia/Seoul"},
"end": {"dateTime": end_str, "timeZone": "Asia/Seoul"},
"reminders": {
"useDefault": False,
"overrides": [{"method": "popup", "minutes": REMINDER_MIN}],
},
}
# 참석자 이메일이 있으면 추가
if pd.notna(row.get("참석자이메일")) and str(row["참석자이메일"]).strip() not in ("", "-"):
event["attendees"] = [{"email": str(row["참석자이메일"]).strip()}]
created = service.events().insert(
calendarId=CALENDAR_ID, body=event, sendUpdates="all"
).execute()
print(f" ✔ 등록 완료: {row['제목']} ({date_str})")
success += 1
except Exception as e:
print(f" ✘ 등록 실패: {row['제목']} → {e}")
failed += 1
print(f"\n✅ 완료! 성공: {success}건 / 실패: {failed}건")
EXCEL_PATH에 일정 목록 엑셀 경로를 입력합니다.CALENDAR_ID에 등록할 캘린더 ID를 입력합니다. 본인 기본 캘린더라면 구글 계정 이메일을 그대로 입력합니다.credentials.json 파일을 코드와 같은 폴더에 저장합니다.python calendar_add.py
정상 실행 시 터미널에 이렇게 출력됩니다:
✔ 구글 캘린더 API 인증 완료 ✔ 일정 목록 로드: 3건 ✔ 등록 완료: A사 미팅 (2026-07-01) ✔ 등록 완료: 프로젝트 마감 (2026-07-05) ✔ 등록 완료: 정기 점검 (2026-07-10) ✅ 완료! 성공: 3건 / 실패: 0건
구글 캘린더를 열어보면 엑셀에 정리했던 일정이 모두 등록되어 있고, 참석자 이메일을 입력한 일정은 해당 참석자에게 초대 메일도 자동으로 발송됩니다.
오류 1: 403 Forbidden 오류
1단계 마지막 설정에서 캘린더에 서비스 계정 이메일을 공유하지 않은 경우입니다. 구글 캘린더 설정에서 서비스 계정 이메일을 "일정 변경 권한"으로 다시 추가하세요.
오류 2: 시간이 9시간씩 어긋나서 등록됨
시간대(timeZone) 설정이 빠졌거나 잘못된 경우입니다. 코드에 이미 "timeZone": "Asia/Seoul"이 포함되어 있는지 확인하세요. 이 설정이 없으면 구글이 기본값(UTC)으로 처리해 9시간 차이가 발생합니다.
오류 3: 참석자에게 초대 메일이 안 감
sendUpdates="all" 옵션이 코드에 포함되어 있는지 확인하세요. 이 옵션이 없거나 "none"으로 설정되어 있으면 일정은 등록되지만 참석자에게 알림이 가지 않습니다.
매달 같은 날짜에 반복되는 일정(정기 점검, 월간 보고 등)은 반복 규칙을 추가하면 한 번만 등록해도 계속 반복됩니다.
event["recurrence"] = ["RRULE:FREQ=MONTHLY;COUNT=12"] # 매달, 12회 반복
💡 이전 게시글과 결합하면: 구글 스프레드시트 자동화 편과 결합하면 팀원들이 공유 시트에 입력한 일정을 자동으로 읽어와 캘린더에 등록하는 것도 가능하고, 텔레그램 자동 발송 편과 결합하면 일정 등록 완료 알림을 함께 받을 수 있습니다.
이 코드를 응용하면 등록 전 기존 일정과 겹치는지 자동으로 확인하거나, 일정 취소·수정도 코드로 처리하는 것이 가능합니다.