본문 바로가기
카테고리 없음

파이썬으로 구글 스프레드시트 자동 업데이트하기 (gspread 실전)

by First Adventure 2026. 4. 20.
반응형

엑셀은 내 PC에만 있지만, 구글 시트는 어디서든 열립니다.

  데이터를 업데이트할 때마다 파일을 열고, 수정하고, 공유하는 과정이 번거롭다면 구글 스프레드시트가 답입니다. 링크 하나로 누구나 실시간으로 볼 수 있고, 파이썬으로 자동 업데이트까지 연결하면 수동으로 손댈 일이 사라집니다.

  이 글에서는 파이썬 라이브러리 gspread를 사용해 구글 스프레드시트를 자동으로 읽고 쓰는 방법을 다룹니다. 인증 설정부터 데이터 읽기·쓰기, 행 추가·삭제, 실전 자동화 예제까지 단계별로 설명합니다.

 

사전 준비

필요한 라이브러리 설치

pip install gspread google-auth
  • gspread: 구글 스프레드시트를 파이썬으로 제어하는 핵심 라이브러리입니다. 셀 읽기·쓰기, 행·열 추가, 시트 생성 등을 지원합니다.
  • google-auth: Google API 인증을 처리하는 라이브러리입니다. gspread가 내부적으로 사용합니다.

 

Google API 인증 설정 (서비스 계정 방식)

  gspread로 구글 스프레드시트에 접근하려면 Google Cloud에서 서비스 계정을 만들고 인증 키를 발급받아야 합니다. 처음 한 번만 설정하면 이후에는 키 파일만 있으면 됩니다.

  1. Google Cloud Console에 접속해 새 프로젝트를 생성합니다.
  2. 왼쪽 메뉴에서 API 및 서비스 → 라이브러리로 이동해 Google Sheets APIGoogle Drive API를 검색해 각각 활성화합니다.
  3. API 및 서비스 → 사용자 인증 정보에서 서비스 계정 만들기를 선택합니다.
  4. 생성된 서비스 계정 이메일을 복사해둡니다. (예: my-bot@project-id.iam.gserviceaccount.com)
  5. 서비스 계정 → 키 탭 → 키 추가 → JSON을 선택해 키 파일을 다운로드합니다.
  6. 다운로드한 JSON 파일을 프로젝트 폴더에 credentials.json으로 저장합니다.
  7. 연동할 구글 스프레드시트를 열고, 공유 버튼을 눌러 위에서 복사한 서비스 계정 이메일을 편집자로 추가합니다.

  이 단계가 가장 번거롭지만, 한 번만 하면 됩니다. 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개 한번에 합치기를, 집계 후 차트로 정리하고 싶다면 파이썬으로 엑셀 데이터 자동 집계 및 차트 생성하기를 함께 참고해 보세요. 세 가지를 연결하면 수집 → 집계 → 공유까지 하나의 파이프라인으로 완성됩니다.

 

관련 내용

 


본 포스팅의 코드는 자유롭게 수정 및 배포가 가능하나, 상업적 이용 시에는 출처를 반드시 밝혀주시기 바랍니다.

 

반응형