엑셀은 내 PC에만 있지만, 구글 시트는 어디서든 열립니다.
데이터를 업데이트할 때마다 파일을 열고, 수정하고, 공유하는 과정이 번거롭다면 구글 스프레드시트가 답입니다. 링크 하나로 누구나 실시간으로 볼 수 있고, 파이썬으로 자동 업데이트까지 연결하면 수동으로 손댈 일이 사라집니다.
이 글에서는 파이썬 라이브러리 gspread를 사용해 구글 스프레드시트를 자동으로 읽고 쓰는 방법을 다룹니다. 인증 설정부터 데이터 읽기·쓰기, 행 추가·삭제, 실전 자동화 예제까지 단계별로 설명합니다.
사전 준비
필요한 라이브러리 설치
pip install gspread google-auth
- gspread: 구글 스프레드시트를 파이썬으로 제어하는 핵심 라이브러리입니다. 셀 읽기·쓰기, 행·열 추가, 시트 생성 등을 지원합니다.
- google-auth: Google API 인증을 처리하는 라이브러리입니다. gspread가 내부적으로 사용합니다.
Google API 인증 설정 (서비스 계정 방식)
gspread로 구글 스프레드시트에 접근하려면 Google Cloud에서 서비스 계정을 만들고 인증 키를 발급받아야 합니다. 처음 한 번만 설정하면 이후에는 키 파일만 있으면 됩니다.
- Google Cloud Console에 접속해 새 프로젝트를 생성합니다.
- 왼쪽 메뉴에서 API 및 서비스 → 라이브러리로 이동해 Google Sheets API와 Google Drive API를 검색해 각각 활성화합니다.
- API 및 서비스 → 사용자 인증 정보에서 서비스 계정 만들기를 선택합니다.
- 생성된 서비스 계정 이메일을 복사해둡니다. (예:
my-bot@project-id.iam.gserviceaccount.com) - 서비스 계정 → 키 탭 → 키 추가 → JSON을 선택해 키 파일을 다운로드합니다.
- 다운로드한 JSON 파일을 프로젝트 폴더에
credentials.json으로 저장합니다. - 연동할 구글 스프레드시트를 열고, 공유 버튼을 눌러 위에서 복사한 서비스 계정 이메일을 편집자로 추가합니다.
이 단계가 가장 번거롭지만, 한 번만 하면 됩니다. credentials.json은 절대 GitHub 등 외부에 공개하지 마세요.
Case 1. 스프레드시트 연결하고 데이터 읽기
인증 후 스프레드시트에 연결하고, 시트의 데이터를 읽어오는 기본 방법입니다.
# read_sheet.py
import gspread
from google.oauth2.service_account import Credentials
# 인증 범위 설정
SCOPES = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive",
]
# 서비스 계정 키 파일로 인증
creds = Credentials.from_service_account_file("credentials.json", scopes=SCOPES)
client = gspread.authorize(creds)
# 스프레드시트 열기 (URL 또는 이름으로 접근 가능)
# 방법 1: URL로 열기
spreadsheet = client.open_by_url("https://docs.google.com/spreadsheets/d/스프레드시트_ID/edit")
# 방법 2: 파일 이름으로 열기
# spreadsheet = client.open("스프레드시트_이름")
# 첫 번째 시트 선택
ws = spreadsheet.sheet1
# 전체 데이터 읽기
all_data = ws.get_all_values() # 모든 행을 리스트로 반환
print(f"전체 행 수: {len(all_data)}")
print(f"헤더: {all_data[0]}")
# 딕셔너리 형태로 읽기 (헤더를 키로 사용)
records = ws.get_all_records()
for record in records[:3]: # 처음 3개만 출력
print(record)
# 특정 셀 읽기
cell_value = ws.acell("B2").value
print(f"B2 셀 값: {cell_value}")
# 특정 범위 읽기
range_data = ws.get("A1:C10")
print(f"A1:C10 범위: {range_data}")
Case 2. 데이터 쓰기 및 업데이트하기
특정 셀에 값을 쓰거나, 범위 전체를 한 번에 업데이트하는 방법입니다. API 호출 횟수를 줄이려면 셀 하나씩 쓰는 것보다 범위 단위로 한 번에 쓰는 방식이 훨씬 효율적입니다.
# write_sheet.py
import gspread
from google.oauth2.service_account import Credentials
SCOPES = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive",
]
creds = Credentials.from_service_account_file("credentials.json", scopes=SCOPES)
client = gspread.authorize(creds)
ws = client.open_by_url("스프레드시트_URL").sheet1
# 단일 셀 업데이트
ws.update_acell("A1", "업데이트된 값")
# 범위 단위로 한 번에 업데이트 (권장)
# 2행부터 데이터 작성
data = [
["2024-01", "A항목", 120000],
["2024-01", "B항목", 85000],
["2024-02", "A항목", 200000],
]
ws.update("A2:C4", data)
print("범위 업데이트 완료")
# 마지막 행 다음에 새 행 추가
ws.append_row(["2024-03", "C항목", 60000])
print("행 추가 완료")
# 여러 행 한 번에 추가
new_rows = [
["2024-04", "A항목", 180000],
["2024-04", "B항목", 95000],
]
ws.append_rows(new_rows)
print(f"{len(new_rows)}개 행 추가 완료")
Case 3. 시트 관리 (생성·삭제·복사)
월별 시트를 자동으로 만들거나, 오래된 시트를 삭제하는 등 시트 자체를 관리하는 방법입니다.
# manage_sheets.py
import gspread
from google.oauth2.service_account import Credentials
from datetime import datetime
SCOPES = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive",
]
creds = Credentials.from_service_account_file("credentials.json", scopes=SCOPES)
client = gspread.authorize(creds)
spreadsheet = client.open_by_url("스프레드시트_URL")
# 현재 월 이름으로 새 시트 생성
month_name = datetime.now().strftime("%Y-%m")
existing_titles = [ws.title for ws in spreadsheet.worksheets()]
if month_name not in existing_titles:
new_ws = spreadsheet.add_worksheet(title=month_name, rows=1000, cols=20)
print(f"시트 생성 완료: {month_name}")
else:
new_ws = spreadsheet.worksheet(month_name)
print(f"기존 시트 사용: {month_name}")
# 헤더 작성
new_ws.update("A1:C1", [["날짜", "항목", "금액"]])
# 특정 시트 삭제
# spreadsheet.del_worksheet(spreadsheet.worksheet("삭제할_시트명"))
# 전체 시트 목록 확인
for ws in spreadsheet.worksheets():
print(f" 시트명: {ws.title}, 행 수: {ws.row_count}")
Case 4. 실전 자동화 — 매일 데이터를 시트에 자동 기록하기
매일 특정 데이터를 구글 시트에 자동으로 추가하는 실전 예제입니다. 파이썬 스크립트를 윈도우 작업 스케줄러나 cron에 등록해두면 사람이 손대지 않아도 데이터가 쌓입니다.
# daily_update.py
import gspread
from google.oauth2.service_account import Credentials
from datetime import datetime
import random # 예제용 — 실제로는 수집한 데이터로 교체하세요
SCOPES = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive",
]
SPREADSHEET_URL = "스프레드시트_URL"
def get_client():
creds = Credentials.from_service_account_file("credentials.json", scopes=SCOPES)
return gspread.authorize(creds)
def get_or_create_sheet(spreadsheet, title: str):
"""시트가 없으면 생성, 있으면 기존 시트 반환"""
titles = [ws.title for ws in spreadsheet.worksheets()]
if title not in titles:
ws = spreadsheet.add_worksheet(title=title, rows=1000, cols=10)
ws.update("A1:D1", [["날짜", "항목A", "항목B", "합계"]])
print(f" 새 시트 생성: {title}")
else:
ws = spreadsheet.worksheet(title)
return ws
def collect_data() -> dict:
"""
실제로는 이 부분에서 원하는 데이터를 수집합니다.
예: 파일 읽기, API 호출, DB 조회 등
"""
return {
"항목A": random.randint(100, 500),
"항목B": random.randint(50, 300),
}
def main():
today = datetime.now()
date_str = today.strftime("%Y-%m-%d %H:%M")
month_str = today.strftime("%Y-%m")
client = get_client()
spreadsheet = client.open_by_url(SPREADSHEET_URL)
ws = get_or_create_sheet(spreadsheet, month_str)
data = collect_data()
total = data["항목A"] + data["항목B"]
new_row = [date_str, data["항목A"], data["항목B"], total]
ws.append_row(new_row)
print(f"[{date_str}] 기록 완료: {new_row}")
if __name__ == "__main__":
main()
실전에서 바로 쓰는 완성 코드
인증 연결을 한 번만 처리하고, 읽기·쓰기·행 추가를 모두 지원하는 완성본입니다. --mode로 원하는 동작을 선택해 실행합니다.
실행 예시
# 전체 데이터 읽기
python gsheet.py --url "스프레드시트_URL" --mode read
# CSV 파일 내용을 시트에 쓰기
python gsheet.py --url "스프레드시트_URL" --mode write --csv data.csv
# 새 행 추가
python gsheet.py --url "스프레드시트_URL" --mode append --row "2024-05,A항목,120000"
# gsheet.py
import gspread
import argparse
import csv
from google.oauth2.service_account import Credentials
SCOPES = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive",
]
def get_client(cred_file: str = "credentials.json"):
creds = Credentials.from_service_account_file(cred_file, scopes=SCOPES)
return gspread.authorize(creds)
def get_args():
p = argparse.ArgumentParser(description="구글 스프레드시트 자동화")
p.add_argument("--url", required=True, help="스프레드시트 URL")
p.add_argument("--sheet", default=None, help="시트 이름 (없으면 첫 번째 시트)")
p.add_argument("--creds", default="credentials.json", help="서비스 계정 키 파일 경로")
p.add_argument("--mode", required=True,
choices=["read", "write", "append"],
help="동작 선택: read / write / append")
p.add_argument("--csv", default=None, help="[write] 쓸 CSV 파일 경로")
p.add_argument("--row", default=None, help="[append] 추가할 행 (쉼표 구분)")
return p.parse_args()
def main():
args = get_args()
client = get_client(args.creds)
ss = client.open_by_url(args.url)
ws = ss.worksheet(args.sheet) if args.sheet else ss.sheet1
print(f"[INFO] 시트: {ws.title}")
# 읽기
if args.mode == "read":
records = ws.get_all_records()
print(f"[INFO] 총 {len(records)}행\n")
for i, record in enumerate(records, start=1):
print(f" {i}: {record}")
# CSV 파일 내용을 시트에 쓰기
elif args.mode == "write":
if not args.csv:
print("[오류] --csv 파일 경로를 지정하세요.")
return
with open(args.csv, encoding="utf-8") as f:
rows = list(csv.reader(f))
ws.clear()
ws.update(f"A1:{chr(64 + len(rows[0]))}{len(rows)}", rows)
print(f"[완료] {len(rows)}행 작성 완료")
# 새 행 추가
elif args.mode == "append":
if not args.row:
print("[오류] --row 값을 지정하세요.")
return
new_row = [v.strip() for v in args.row.split(",")]
ws.append_row(new_row)
print(f"[완료] 행 추가 완료: {new_row}")
if __name__ == "__main__":
main()
코드 핵심 옵션 설명
- --url: 구글 스프레드시트의 전체 URL을 입력합니다. 브라우저 주소창에서 그대로 복사하면 됩니다.
- --sheet: 작업할 시트 이름을 지정합니다. 지정하지 않으면 첫 번째 시트를 사용합니다.
- --mode read: 시트의 전체 데이터를 읽어 출력합니다.
- --mode write: 시트 내용을 전부 지우고 CSV 파일 내용으로 덮어씁니다.
- --mode append: 기존 데이터 아래에 새 행을 추가합니다. 값은 쉼표로 구분해 입력합니다.
- --creds: 서비스 계정 키 파일 경로를 지정합니다. 기본값은
credentials.json입니다.
자주 발생하는 문제와 해결법
문제 1. APIError: [403] The caller does not have permission
스프레드시트에 서비스 계정 이메일을 공유하지 않았거나, Google Sheets API / Google Drive API가 활성화되지 않은 경우입니다. 사전 준비 단계의 6~7번을 다시 확인하세요.
# 서비스 계정 이메일 확인 방법
import json
with open("credentials.json") as f:
creds_data = json.load(f)
print(creds_data["client_email"]) # 이 이메일을 스프레드시트에 편집자로 추가해야 합니다
문제 2. APIError: [429] Quota exceeded
Google Sheets API는 100초당 100회 요청 제한이 있습니다. 반복문 안에서 셀을 하나씩 업데이트하면 금방 한도에 걸립니다. 반드시 범위 단위로 한 번에 처리하세요.
# 느린 방식 (API 호출이 행 수만큼 발생)
for i, row in enumerate(data, start=2):
ws.update_acell(f"A{i}", row[0])
ws.update_acell(f"B{i}", row[1])
# 빠른 방식 (API 호출 1회)
ws.update("A2:B100", data)
문제 3. credentials.json을 실수로 공개했을 때
GitHub에 올리거나 외부에 노출됐다면 즉시 Google Cloud Console에서 해당 키를 삭제하고 새 키를 발급받아야 합니다. 프로젝트에 .gitignore 파일을 만들어 키 파일이 포함되지 않도록 반드시 설정해두세요.
# .gitignore
credentials.json
*.json # 또는 키 파일만 명시적으로 제외
문제 4. 한글이 깨져서 시트에 저장될 때
CSV 파일을 읽을 때 인코딩을 명시하지 않으면 발생합니다. 파일을 열 때 반드시 encoding="utf-8"을 지정하세요. Windows에서 만든 CSV는 encoding="utf-8-sig"가 필요할 수 있습니다.
# Windows에서 저장한 CSV는 utf-8-sig로 열기
with open("data.csv", encoding="utf-8-sig") as f:
rows = list(csv.reader(f))
마치며..
오늘은 gspread로 구글 스프레드시트를 파이썬으로 자동 제어하는 방법을 살펴보았습니다. 기술의 목적은 결국 인간의 시간을 더 가치 있는 곳에 쓰게 하는 것입니다. 데이터를 복사하고 붙여넣는 일은 파이썬에게 맡기고, 여러분은 그 데이터가 보여주는 흐름에 집중하시길 바랍니다.
시트에 기록할 데이터를 엑셀에서 가져와야 한다면 이전 글 파이썬으로 엑셀 파일 100개 한번에 합치기를, 집계 후 차트로 정리하고 싶다면 파이썬으로 엑셀 데이터 자동 집계 및 차트 생성하기를 함께 참고해 보세요. 세 가지를 연결하면 수집 → 집계 → 공유까지 하나의 파이프라인으로 완성됩니다.
관련 내용
- [VS Code/Anaconda] Visual Studio Code 프로젝트에 conda 가상환경 적용
- [Anaconda/Windows] Anaconda 다운로드 및 설치
- [Pytorch] ImportError: No module named 'torch' (라이브러리 인식 문제 해결법)
본 포스팅의 코드는 자유롭게 수정 및 배포가 가능하나, 상업적 이용 시에는 출처를 반드시 밝혀주시기 바랍니다.