Python으로 애플리케이션을 개발하다 보면 외부 서드파티 서비스와 연동해야 하는 순간이 찾아옵니다. 예를 들어 피트니스 도구를 만든다면 Fitbit API에 연결해 운동 데이터를 확인할 수 있고, 문자 메시지를 전송하는 앱이라면 Twilio API를 활용할 수 있습니다.
Python에서는 requests 라이브러리를 사용해 이러한 서드파티 웹 서비스를 애플리케이션에 손쉽게 연결할 수 있습니다. 이 가이드에서는 Python requests 라이브러리의 기본 개념과 HTTP 요청을 보내는 방법을 단계별로 알아보겠습니다.
웹 요청(Web Request) 기본 개념 복습
요청(Request)은 인터넷의 핵심입니다. 지금 이 글을 클릭하는 순간에도 여러분의 브라우저는 웹 서버로 HTTP 요청을 전송했습니다. 이 요청에는 어떤 웹 페이지를 보고 싶은지에 대한 정보가 담겨 있으며, 서버는 해당 페이지를 찾아 브라우저로 되돌려줍니다. 바로 이 과정 덕분에 우리는 지금 이 튜토리얼을 볼 수 있는 것입니다.
웹 요청은 다양한 형태로 존재합니다. 이 웹 페이지를 열기 위해 사용된 요청 유형은 GET 요청입니다. GET 요청은 서버에서 데이터를 조회할 때 사용됩니다. 그 외에도 서버의 리소스를 수정할 때 사용하는 POST나 PUT 같은 요청 유형이 있습니다. 이번 튜토리얼에서는 가장 널리 쓰이는 GET과 POST 요청에 집중해 살펴보겠습니다.
requests 라이브러리 설치 방법
requests는 Python에서 웹 요청(HTTP 통신)을 처리할 수 있게 해주는 대표적인 HTTP 라이브러리입니다.
Python으로 웹 요청을 보내기 전에 먼저 requests 라이브러리를 설치해야 합니다. 아래 명령어로 간단히 설치할 수 있습니다:
pip install requests
패키지 설치가 완료되면 이제 웹 요청을 보낼 준비가 끝난 것입니다.
GET 요청 보내는 방법
가장 많이 사용되는 웹 요청 유형은 GET 요청입니다. GET 요청을 사용하면 서버에서 데이터를 가져올 수 있습니다.
예를 들어 고양이 상식(cat facts) 목록을 불러오는 앱을 만든다고 가정해 보겠습니다. 이때 공개 API인 cat-facts를 활용할 수 있습니다. 이 API는 누구나 접근 가능하므로 별도의 로그인 정보(자격 증명)가 필요하지 않습니다. 다음 코드로 API에 요청을 보낼 수 있습니다:
import requests
res = requests.get('https://cat-fact.herokuapp.com/facts')
print(res.status_code)
이 코드를 실행하면 200이 출력됩니다. 코드를 하나씩 살펴보겠습니다.
첫 번째 줄에서는 requests 라이브러리를 임포트해 이후 코드에서 사용할 기능에 접근할 수 있게 했습니다. 그다음 requests.get() 메서드를 사용해 웹 요청을 보냈습니다. .put()이나 .post() 같은 메서드로 다른 유형의 요청을 보낼 수도 있지만, 이 경우에는 cat-facts API에서 데이터를 조회하기만 하면 되므로 GET 요청이면 충분합니다.
마지막으로 웹 요청의 상태 코드(status code)를 출력했습니다. 200이 반환되었다는 것은 요청이 성공적으로 완료되었다는 의미입니다. 상태 코드의 의미에 대해서는 뒤에서 자세히 다루겠습니다.
응답 데이터 확인하기
앞선 예제에서는 요청의 상태 코드만 출력했습니다. 그렇다면 실제로 가져온 데이터는 어떻게 확인할 수 있을까요? 고양이 상식은 어디에 있을까요? 이때 .text와 .json() 메서드가 유용하게 사용됩니다.
텍스트 응답 확인하기
.text 메서드를 사용하면 웹 요청의 결과를 텍스트 형태로 확인할 수 있습니다:
import requests
res = requests.get('https://cat-fact.herokuapp.com/facts')
print(res.text)
이 코드는 고양이 상식 목록을 반환합니다. 하지만 일반 텍스트 형태로는 데이터 구조를 파악하거나 내용을 읽기가 쉽지 않습니다. API 응답을 다룰 때는 더 나은 방법이 필요합니다.
JSON 응답 확인하기
API 데이터를 다루기에 가장 적합한 형식은 JSON입니다. 다음 코드로 요청 결과를 JSON 형태로 받아올 수 있습니다:
print(res.json())
코드를 실행하면 긴 고양이 상식 목록이 반환됩니다. 목록의 첫 번째 레코드는 다음과 같습니다:
{'_id': '58e009550aac31001185ed12', 'text': 'The oldest cat video on YouTube dates back to 1894.', 'type': 'cat', 'user': {'_id': '58e007480aac31001185ecef', 'name': {'first': 'Kasimir', 'last': 'Schulz'}}, 'upvotes': 6, 'userUpvoted': None}
성공입니다! 고양이 상식 목록을 무사히 가져왔습니다.
POST 요청 보내는 방법
requests 라이브러리는 POST 요청에도 사용할 수 있습니다. POST 요청을 사용하면 웹 서버에 저장된 데이터를 생성하거나 수정할 수 있습니다.
이번 예제에서는 Airtable API를 사용해 보겠습니다. POST 요청을 지원하는 API가 필요한데, 앞서 사용한 cat-facts API는 읽기 전용이기 때문입니다.
마신 차(tea)를 모두 기록하는 데이터베이스가 있다고 가정해 보겠습니다. 방금 한 잔의 차를 더 마셨고, 이 기록을 데이터베이스에 추가하고 싶습니다. 다음 코드로 이를 처리할 수 있습니다:
import requests
headers = {
'Authorization': 'Bearer API_KEY',
'Content-Type': 'application/json',
}
data = '{"records": [{"fields": {"Drink": "Black Decaf Tea"}}]}'
res = requests.post('https://api.airtable.com/v0/YOUR_BASE_ID/YOUR_TABLE_NAME', headers=headers, data=data)
print(res.json())
코드 실행 결과:
{'records': [{'id': 'recqUEPuXEAXaNl1L', 'fields': {'Drink': 'Black Decaf Tea', 'Date': '2020-06-16T08:53:02.000Z'}, 'createdTime': '2020-06-16T08:53:02.000Z'}]}
이 결과는 HTTP 요청이 성공했다는 것을 의미합니다. Airtable API를 통해 데이터베이스에 새 레코드를 추가한 것입니다. 코드를 좀 더 자세히 살펴보겠습니다.
먼저 requests 라이브러리를 임포트해 코드에서 HTTP 요청을 보낼 수 있도록 준비했습니다.
그다음 두 개의 키-값 쌍을 담은 딕셔너리를 정의했습니다. 하나는 인증 키(API 키)를 저장하고, 다른 하나는 웹 서버로 전송하는 콘텐츠 유형(Content-Type)을 지정합니다. Airtable API에 요청을 보내려면 반드시 이 헤더(headers)들을 함께 전송해야 합니다.
다음으로 data라는 변수를 선언해 POST 요청과 함께 보낼 데이터를 저장했습니다. 여기서는 "Black Decaf Tea"라는 음료 기록을 데이터베이스에 추가했습니다. 이후 requests.post() 메서드를 호출하면서 헤더와 데이터를 매개변수로 지정해 Airtable API로 POST 요청을 보냈습니다.
마지막으로 res.json()을 사용해 요청 결과를 JSON 형식으로 출력했습니다.
HTTP 상태 코드 이해하기
HTTP 프로토콜은 웹 요청이 이루어질 때마다 고유한 상태 코드를 반환합니다. 이를 통해 요청이 성공했는지, 오류가 발생했는지 확인할 수 있습니다. 이미 몇 가지는 익숙할 텐데요, 대표적으로 404가 있습니다.
Python requests로 요청을 보낼 때 마주칠 수 있는 주요 상태 코드 범위는 다음과 같습니다:
- 1XX: 정보성 응답
- 2XX: 요청 성공
- 3XX: 요청 리다이렉션(다른 주소로 이동)
- 4XX: 클라이언트 측 오류
- 5XX: 서버 측 오류
상태 코드를 제대로 이해하고 있으면 프로그램에 디버깅 로직을 추가할 수 있습니다. 앞서 살펴본 cat-facts API 예제의 GET 요청을 활용해 보겠습니다. 접근하려는 리소스를 찾지 못했을 때 메시지를 출력하고 싶다면 다음과 같이 작성할 수 있습니다:
import requests
res = requests.get('https://cat-fact.herokuapp.com/facts')
if res.status_code == 200:
print("Success")
else :
print("Error")
이 코드는 Success를 출력합니다. 요청의 상태 코드가 200이므로 콘솔에 "Success" 메시지가 표시된 것입니다. 반대로 요청이 실패했다면, 예를 들어 잘못된 URL을 지정했다면 "Error" 메시지가 출력됩니다.
마무리
Python requests 라이브러리를 사용하면 Python 코드에서 HTTP 요청을 손쉽게 보낼 수 있습니다. 이 가이드에서는 requests 라이브러리로 GET과 POST 요청을 보내는 방법을 살펴봤는데, 이 라이브러리로 PUT이나 DELETE 요청도 보낼 수 있습니다.
requests.get()이나 requests.post() 같은 메서드를 호출하면 Python이 해당 웹 리소스로 요청을 전송합니다. 요청에 헤더와 데이터를 첨부할 수도 있어, 소유한 웹 리소스를 변경하고 싶을 때 필요한 정보를 함께 보낼 수 있습니다.
이제 여러분도 전문가처럼 Python requests 라이브러리를 활용할 준비가 되었습니다!