파이썬 requests 라이브러리로 API 호출하기
지난 글에서 멀티스레딩으로 여러 작업을 동시에 처리하는 법을 봤잖아요. 그때 마지막에 "여러 API를 동시에 호출할 때 진짜 빛난다"는 말을 살짝 흘렸는데, 그 떡밥을 오늘 회수하려고요.
근데 그 전에 한 가지. 그래서 그 API라는 게 도대체 뭐냐, 그게 오늘의 진짜 주제예요.
API가 뭐예요? (파이썬 크롤링과는 좀 달라요)
처음 프로그래밍 배우면 슬슬 이런 욕심이 생기거든요. "내 컴퓨터 안에 있는 데이터 말고, 인터넷에 있는 진짜 데이터로 뭐 좀 해보고 싶다." 날씨 정보를 가져온다거나, 주식 시세를 받아본다거나요.
그럴 때 쓰는 게 바로 API예요.
비유로 설명드릴게요. API는 식당의 주문 창구 같은 거예요. 손님(내 파이썬 코드)이 메뉴를 보고 "이거 주세요" 하고 주문을 넣으면, 주방(서버)에서 음식(데이터)을 만들어서 돌려주는 구조죠. 우리는 주방이 어떻게 생겼는지 몰라도 돼요. 창구에 어떻게 주문하면 되는지만 알면 끝이에요.
가끔 헷갈리는 게 파이썬 크롤링과의 차이인데요. 크롤링은 사람 보라고 만든 웹페이지(HTML)를 코드로 긁어오는 거예요. API는 서버가 아예 "코드용 데이터 통로"를 따로 열어둔 거고요. 정제된 데이터가 깔끔하게 나오니까, 가능하면 API를 먼저 찾아보시는 게 좋아요.
파이썬 requests 설치하고 첫 호출
requests는 파이썬에서 API를 호출할 때 거의 표준처럼 쓰는 라이브러리예요. 의외로 파이썬 기본에 포함된 게 아니라서 따로 설치해 줘야 해요.
pip install requests
설치했으면 가장 단순한 예제부터 가볼게요. 오늘 내내 쓸 주소는 JSONPlaceholder라는 곳인데, 회원가입이나 API 키 없이 누구나 연습용으로 쓸 수 있는 공짜 서버예요.
import requests # requests 라이브러리 불러오기
# 1번 게시글을 달라고 요청
response = requests.get("https://jsonplaceholder.typicode.com/posts/1")
print(response.status_code) # 응답 상태 확인
print(response.json()) # 본문을 딕셔너리로 받기
실행하면 이렇게 나와요.
200
{'userId': 1, 'id': 1, 'title': 'sunt aut facere...', 'body': '...'}
requests.get(...) 한 줄로 인터넷 너머의 데이터를 가져온 거예요. 처음 이거 돌려보면 좀 신기하실 거예요.
python API 호출 응답 뜯어보기
위에서 본 response에서 자주 쓰는 게 두 가지 있어요.
response.status_code: 영수증에 찍힌 결과 코드예요.response.json(): 응답 본문을 파이썬 딕셔너리로 바꿔줘요.
여기서 status_code가 핵심인데, 200이면 성공, 그 외는 다 실패라고 보시면 돼요.
- 200: 잘 나왔어요
- 404: 그런 메뉴 없어요 (주소가 잘못됐거나 데이터가 없음)
- 500: 주방에서 사고났어요 (서버 오류)
그래서 보통 이렇게 분기를 태워요.
response = requests.get("https://jsonplaceholder.typicode.com/posts/9999")
if response.status_code == 200:
print(response.json()) # 성공일 때만 본문 파싱
else:
print(f"실패했어요. 코드: {response.status_code}") # 404 출력
참고로 JSON이 아닌 응답에 .json()을 부르면 에러가 나요. HTML이나 일반 텍스트가 오면 response.text를 쓰셔야 합니다.
쿼리 파라미터와 POST 요청
URL 뒤에 붙는 ?userId=1 같은 거 보신 적 있으시죠. 이걸 직접 문자열로 이어붙이면 한글이나 공백에서 에러가 잘 나요. params= 인자에 딕셔너리로 넘기는 게 훨씬 안전합니다.
params = {"userId": 1} # 1번 사용자가 쓴 글만 달라는 조건
response = requests.get(
"https://jsonplaceholder.typicode.com/posts",
params=params
)
posts = response.json()
print(f"글 개수: {len(posts)}") # 글 개수: 10
서버에 새 데이터를 보낼 때는 POST를 써요. 식당으로 치면 새 주문을 넣는 거죠.
new_post = {"title": "첫 글", "body": "안녕", "userId": 1}
# json= 인자에 딕셔너리를 넣으면 자동으로 JSON으로 변환해줘요
response = requests.post(
"https://jsonplaceholder.typicode.com/posts",
json=new_post
)
print(response.status_code) # 201 (생성됨)
타임아웃과 에러 처리는 진짜 중요해요
여기는 꼭 짚고 가야 해요. 안 챙기면 코드가 진짜로 멈춰버리거든요.
서버가 죽어 있거나 인터넷이 느리면 requests는 그냥 영원히 기다려요. 그래서 항상 timeout을 줘야 합니다.
import requests
url = "https://jsonplaceholder.typicode.com/posts/1"
headers = {"User-Agent": "MyApp/1.0"} # 어떤 서버는 이게 없으면 차단해요
try:
response = requests.get(url, headers=headers, timeout=5) # 5초 제한
response.raise_for_status() # 200대가 아니면 예외 발생
data = response.json()
print(data["title"])
except requests.exceptions.Timeout:
print("응답이 너무 늦어요")
except requests.exceptions.ConnectionError:
print("연결이 안 돼요. 와이파이 확인해보세요")
except requests.exceptions.HTTPError as e:
print(f"서버 응답 코드 문제: {e}")
raise_for_status()가 편한 게, 200대가 아닐 때 알아서 예외를 던져줘요. 매번 if status_code == 200 안 써도 돼서 코드가 깔끔해집니다.
멀티스레딩으로 여러 API 동시에 (떡밥 회수)
자, 약속한 부분이에요. 게시글 10개를 받아와야 한다고 해볼게요. 하나씩 받으면 10번 왕복하니까 시간이 꽤 걸려요. 근데 동시에 받으면요?
import requests
from concurrent.futures import ThreadPoolExecutor
def fetch_title(post_id):
url = f"https://jsonplaceholder.typicode.com/posts/{post_id}"
response = requests.get(url, timeout=5) # 여기도 timeout은 필수
return response.json()["title"]
# 1번~10번을 동시에 가져오기
with ThreadPoolExecutor(max_workers=5) as executor:
titles = list(executor.map(fetch_title, range(1, 11)))
for title in titles:
print(title)
하나씩 받으면 몇 초 걸릴 게, 거의 한 번 호출하는 시간으로 끝나요. 지난 글에서 배운 멀티스레딩이 이렇게 빛을 발하는 거예요.
처음에 자주 하는 실수들
저도 처음에 다 겪어봤거든요.
- status_code 확인 안 하고 바로
.json()호출: 404면 서버가 HTML 에러 페이지를 줘서 파싱 에러 나요. timeout안 줘서 코드가 한참 멈춤: 무조건 5초든 10초든 넣으세요.- URL에 한글이나 공백을 직접 박기:
params=쓰면 알아서 인코딩해 줘요. - API 키를 코드에 그대로 박고 깃허브에 올리기: 이건 진짜 사고로 이어져요. 환경변수에 넣어두세요.
실습 과제
JSONPlaceholder에는 /users라는 주소도 있어요. 거기서 사용자 목록을 받아서, 이름과 이메일만 한 줄씩 출력해 보세요. 힌트는 한 줄짜리예요.
response = requests.get("https://jsonplaceholder.typicode.com/users", timeout=5)
# 받은 리스트를 돌면서 user["name"], user["email"] 출력
여기서 막히시면 댓글로 남겨주세요.
이제 API로 데이터를 받아올 줄 알게 되셨는데, 받고 보면 보통 리스트 안에 딕셔너리가 줄줄이 들어 있을 거예요. 이걸 엑셀처럼 표로 보고 싶어지거든요. 그래서 다음에 다룰 게 pandas라는 라이브러리예요. API로 받은 데이터를 데이터프레임으로 다루기 시작하면 진짜 재밌어져요.
제 글이 도움이 되셨다면 댓글 & 공감 부탁드려요 😀
'Application > Python' 카테고리의 다른 글
| [Python] 파이썬 프로젝트 구조, 한 파일에서 졸업하기 (0) | 2026.06.05 |
|---|---|
| [Python] 파이썬 pandas 입문 — 엑셀처럼 데이터 다루기 (0) | 2026.06.04 |
| [Python] 파이썬 멀티스레딩으로 작업 속도 확 줄이기 (0) | 2026.05.29 |
| [Python] 파이썬 비동기 프로그래밍, async와 await 기초부터 (0) | 2026.05.27 |
| [Python] 파이썬 타입 힌팅, 모르고 쓰면 손해예요 (0) | 2026.05.26 |