[Python 시리즈 7편] requests로 API 호출하고 자동화하기

English version

6편에서 파일과 JSON으로 데이터를 저장하는 기반을 만들었다면, 이제는 외부 서비스와 데이터를 주고받을 차례입니다. Python의 requests 라이브러리는 HTTP 요청을 간단한 코드로 표현할 수 있어서 스크립트 자동화의 핵심 도구로 자리잡았습니다. 이번 글에서는 requests 설치부터 GET/POST 호출, 응답 검증, 파일 저장, 간단한 예약 실행 아이디어까지 다뤄봅니다.

이번 글에서 새로 나오는 용어

  1. HTTP: 웹에서 데이터를 주고받는 규약으로 GET·POST 같은 메서드와 상태 코드로 동작
  2. 상태 코드: 서버가 요청을 어떻게 처리했는지 숫자로 알려 주는 값으로 200은 성공, 400·500대는 오류
  3. 쿼리 파라미터: URL 뒤에 ?key=value 형태로 붙어 추가 조건을 전달하는 데이터
  4. 웹훅(Webhook): 특정 이벤트가 발생했을 때 URL로 HTTP 요청을 보내 자동 알림을 전달하는 방식

핵심 개념

학습 메모

  • 소요 시간: 60분
  • 준비물: 파일·JSON 처리 경험, 기본 함수 분리
  • 학습 목표: GET/POST 호출을 만들고 결과를 파일에 저장하며 오류를 처리하기

HTTP는 GET과 POST 같은 메서드로 동작합니다. 상태 코드가 200이면 성공, 400·500대면 오류입니다. 이런 규칙을 코드로 옮기기 위해 requests를 사용합니다.

코드로 따라하기

🌐 HTTP 빠른 정리

  • GET: 서버에서 정보를 읽어 올 때 쓰는 요청 방식
  • POST: 서버에 데이터를 전송하거나 새 리소스를 만들 때 쓰는 방식
  • 상태 코드: 200이면 성공, 400대/500대는 오류를 의미합니다.

requests 설치

프로젝트 폴더에서 아래 명령을 실행합니다.

uv add requests

이제 코드에서 import requests로 불러올 수 있습니다.

기본 GET 요청


response = requests.get("https://api.github.com/repos/python/cpython")
response.raise_for_status()

data = response.json()
print(data["stargazers_count"])

raise_for_status()는 HTTP 에러(400 이상)가 발생하면 예외를 던져 즉시 문제를 알려줍니다.

쿼리 파라미터와 헤더

params = {"q": "python", "per_page": 5}
headers = {"Accept": "application/vnd.github+json"}

response = requests.get("https://api.github.com/search/repositories", params=params, headers=headers)
response.raise_for_status()

items = response.json()["items"]
for repo in items:
    print(repo["full_name"], repo["stargazers_count"])

params 딕셔너리를 사용하면 URL 인코딩을 직접 할 필요가 없습니다.

POST 요청과 JSON 바디

payload = {"text": "오늘의 배포 성공"}

response = requests.post(
    "https://httpbin.org/post",
    json=payload,
)
response.raise_for_status()

print(response.json()["json"])

json=... 인자를 사용하면 자동으로 JSON 직렬화와 Content-Type: application/json 헤더 설정이 이루어집니다.

응답 검증과 예외 처리

네트워크나 인증 오류가 발생할 수 있으므로 try/except로 감싸고, 제한 시간을 지정하는 것이 좋습니다.

from requests import RequestException

try:
    response = requests.get("https://status.mathbong.com", timeout=5)
    response.raise_for_status()
except RequestException as exc:
    print("모니터링 실패", exc)
else:
    print("상태 페이지 정상", response.text[:80])

결과를 파일에 저장하기

파일과 JSON 글에서 배운 내용을 합쳐 응답 데이터를 저장해 봅니다.

from pathlib import Path

reports_dir = Path("reports")
reports_dir.mkdir(exist_ok=True)

response = requests.get("https://api.coindesk.com/v1/bpi/currentprice.json")
response.raise_for_status()

data = response.json()
file_path = reports_dir / "btc-price.json"

file_path.write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")
print("저장 완료", file_path)

데이터 흐름을 그림으로 보면 아래처럼 한 줄로 이어집니다.

launchd/cron예약 실행fetch_price.pyrequests.getresponse.raise_for_status예외 처리reports/btc-price.jsonwrite_textSlack/Webhook선택 알림 명령 실행HTTP 요청JSON 저장변경 감지 시 전송

시각화를 해두면 새 요구사항이 생겼을 때 어느 구간을 확장해야 하는지 빠르게 알 수 있습니다.

기대 출력 확인

자동화 글에서는 "어떤 로그가 보이면 정상인가"를 함께 아는 것이 중요합니다.

:::terminal{title="requests 자동화 실행 예시", showFinalPrompt="false"}

[
  { "cmd": "uv run python scripts/weather.py", "output": "[INFO] GET https://api.weatherapi.com/v1/current.json?q=Seoul\n[INFO] status=200\n{\"location\":\"Seoul\",\"temp_c\":24.1,\"condition\":\"Cloudy\"}\n[INFO] data/weather-cache.json 저장 완료\n[INFO] Slack 알림 전송 완료", "delay": 500 }
]

:::

  • 확인할 점: 요청 주소와 상태 코드가 먼저 보이는지
  • 확인할 점: 필요한 핵심 데이터만 추려서 출력하는지
  • 확인할 점: 저장과 알림 결과가 마지막 줄에 분명히 남는지

간단한 예약 실행 아이디어

여기서 예약 실행은 정해진 시간마다 스크립트를 자동으로 실행하는 방법을 뜻합니다. Python 문법만으로 예약 자체를 만드는 것이 아니라, 보통 운영체제의 스케줄러나 외부 실행 환경을 함께 사용합니다.

  • macOS launchdcronuv run scripts/check_status.py를 등록
  • GitHub Actions나 Railway Cron Job으로 서버에서 주기적으로 호출
  • 노션이나 Slack에 결과를 전송해 알림 자동화

스크립트에 로그 출력을 추가하면 파일 누적 기록과 함께 실패 시점을 빠르게 파악할 수 있습니다.

실전 예시: 날씨 요약 알리미

from pathlib import Path

API_URL = "https://api.weatherapi.com/v1/current.json"
WEBHOOK_URL = "https://hooks.slack.com/services/..."
API_KEY = "YOUR_KEY"
cache_file = Path("data/weather-cache.json")

params = {"key": API_KEY, "q": "Seoul"}
response = requests.get(API_URL, params=params, timeout=4)
response.raise_for_status()

weather = response.json()
cache_file.write_text(json.dumps(weather, ensure_ascii=False, indent=2), encoding="utf-8")

message = {
    "text": f"현재 기온 {weather['current']['temp_c']}℃ / 체감 {weather['current']['feelslike_c']}℃"
}

notify = requests.post(WEBHOOK_URL, json=message, timeout=3)
notify.raise_for_status()

API에서 받아온 데이터를 파일로 캐싱하고, Slack으로 알림을 보내면 팀 채널이나 개인 메신저에 실시간 정보를 전달할 수 있습니다.

왜 중요한가

API 자동화를 익히면 학교 일정 데이터, 급식 정보, 동아리 출석 현황처럼 외부 시스템에 있는 자료를 내 작업 흐름으로 끌어올 수 있습니다. 또 raise_for_status()와 예외 처리를 붙여 놓으면 실패 지점을 금방 찾을 수 있어 운영 안정성이 높아집니다.

실습

  • 따라 하기: requests.get 예제를 그대로 작성하고 response.raise_for_status() 동작을 확인합니다.
  • 확장하기: 날씨 요약 알리미를 응용해 다른 무료 API를 호출하고 응답을 reports/ 폴더에 날짜별로 저장합니다.
  • 디버깅: 타임아웃을 0.001로 줄여 RequestException을 일부러 발생시키고 예외 메시지를 읽어 복구 전략을 세웁니다.
  • 완료 기준: 한 스크립트에서 GET→파일 저장→Slack POST까지 이어지는 흐름을 실행해 로그로 검증했을 때입니다.

마무리

requests는 외부 API를 호출하고 결과를 자동으로 처리하는 가장 단순하면서 강력한 도구입니다. 이제 데이터를 가져와 저장하고, 조건에 따라 알림을 보내는 기본 자동화 흐름까지 만들 수 있게 되었습니다. 다음 글에서는 이렇게 모은 데이터를 객체로 구조화하기 위해 클래스와 dataclasses를 활용하는 방법을 살펴봅니다.

💬 댓글

이 글에 대한 의견을 남겨주세요