2026년 파이썬으로 API 호출하는 방법

현대적인 GET/POST 기법을 익히고, JSON을 파싱하며, 효율적인 Python API 호출을 위해 SDK를 활용하십시오.
4 분 읽기
How to make API calls using Python blog image

이 가이드에서는 Python을 사용한 API 활용에 관한 다음 개념들을 살펴보겠습니다:

  1. HTTP란 무엇인가?
  2. REST API란 무엇인가요?
  3. GET 요청을 보내는 방법
  4. POST 요청 수행 방법
  5. SDK 사용 방법

HTTP란 무엇인가요?

HTTP(Hypertext Transfer Protocol)는 대부분의 데이터가 웹을 통해 전송되는 방식을 규정하는 표준입니다. 대부분의 웹사이트 백엔드는 데이터베이스로 구성되어 있다는 말을 들어보셨을 텐데, 이는 사실입니다. 하지만 클라이언트(브라우저나 Python 스크립트)가 실제로 데이터베이스와 상호작용하는 방식에는 미묘한 차이가 있습니다. HTTP는 클라이언트와 백엔드 서버 사이의 통신 계층입니다.

스크래핑 및 웹 API에 HTTP를 사용할 때 가장 자주 사용하는 메서드는 다음과 같습니다.

  • GET: 가장 흔히 사용되는 메서드입니다. 사이트를 방문할 때마다 브라우저는 HTML을 가져오기 위해 GET을 수행한 후 페이지를 렌더링하여 표시합니다.
  • POST: 두 번째로 흔한 메서드입니다. POST는 대량의 데이터를 안전하게 전송하는 데 사용되며, 특히 데이터베이스에 무언가를 추가할 때 주로 활용됩니다. 양식이나 설문조사를 완료하거나 소셜 미디어에 게시물을 올릴 때 POST 요청을 수행하는 것입니다.
  • PUT: PUT 요청은 데이터베이스 내 기존 항목을 업데이트하는 데 사용됩니다. 소셜 미디어 게시물을 수정할 때 내부적으로 PUT이 사용됩니다.
  • DELETE: 소셜 미디어 게시물(또는 데이터베이스의 다른 항목)을 삭제하려면 브라우저가 서버에 DELETE 요청을 보내 제거합니다.

HTTP와 반환 표준의 부재

간결함에도 불구하고 HTTP는 보편적인 반환 표준이 부족합니다. 일부 서버는 기본적으로 HTML을 반환하는 반면, 다른 서버는 JSON이나 XML, 일반 텍스트 같은 구식 데이터 구조를 반환하기도 합니다.

먼저 기본적인 GET 요청을 만들어 보겠습니다. Python Requests가 아직 설치되어 있지 않다면 pip를 통해 설치할 수 있습니다.

pip install requests

Requests 설치 후 다음 코드를 실행하여 간단한 GET 요청을 수행할 수 있습니다. 터미널 출력에 주목하세요.

import requests

response = requests.get("https://quotes.toscrape.com", verify=False)

print(response.text)

코드를 실행하면 HTML 페이지가 반환된다는 것을 알 수 있습니다. 브라우저에서 보기에는 좋지만 터미널에서는 보기 흉합니다. 아래 출력은 일부 생략되었지만 대략적인 모습을 알 수 있습니다.

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <title>스크래핑할 인용문</title>
    <link rel="stylesheet" href="/static/bootstrap.min.css">
    <link rel="stylesheet" href="/static/main.css">


</head>
<body>
    <div class="container">
        <div class="row header-box">
            <div class="col-md-8">
                <h1>
                    <a href="/" style="text-decoration: none">스크래핑할 인용문</a>
                </h1>
            </div>
            <div class="col-md-4">
                <p>

                    <a href="/login">로그인</a>

                </p>
            </div>
        </div>


<div class="row">
    <div class="col-md-8">

    <div class="quote" itemscope itemtype="http://schema.org/CreativeWork">
        <span class="text" itemprop="text">“우리가 창조한 세상은 우리의 사고 과정이다. 우리의 사고를 바꾸지 않고서는 세상을 바꿀 수 없다.”</span>
        <span>by <small class="author" itemprop="author">알버트 아인슈타인</small>
        <a href="/author/Albert-Einstein">(소개)</a>
        </span>
        <div class="tags">
            태그:
            <meta class="keywords" itemprop="keywords" content="변화,깊은-사유,사고,세계" /    >

            <a class="tag" href="/tag/change/page/1/">변화</a>

            <a class="tag" href="/tag/deep-thoughts/page/1/">깊은 생각</a>

            <a class="tag" href="/tag/thinking/page/1/">사고</a>

            <a class="tag" href="/tag/world/page/1/">세계</a>

        </div>
    </div>

    <div class="quote" itemscope itemtype="http://schema.org/CreativeWork">
        <span class="text" itemprop="text">“해리, 우리의 능력보다 훨씬 더 중요한 것은 우리의 선택이야. 그 선택이 우리가 진정 어떤 사람인지를 보여주는 거지.”</span>
        <span>J.K. 롤링 <small class="author" itemprop="author">저자</small>
        <a href="/author/J-K-Rowling">(소개)</a>
        </span>
        <div class="tags">
            태그:
            <meta class="keywords" itemprop="keywords" content="abilities,choices" /    >

            <a class="tag" href="/tag/abilities/page/1/">능력</a>

            <a class="tag" href="/tag/choices/page/1/">선택</a>

        </div>
    </div>

HTML 페이지는 브라우저가 읽고 렌더링하도록 설계되었습니다. 여러분이 읽거나 코드에 통합하기 위한 것이 아닙니다.

REST(표현적 상태 전달)가 이를 해결하는 방법

REST API는 데이터 파이프라인을 위한 설계 표준을 제공합니다. JSON은 REST API에서 가장 널리 사용되는 반환 형식입니다. 유연하고 읽기 쉽습니다. 이 명확하고 가독성 높은 구문은 프로그래밍 환경에서 파싱하기도 용이합니다.

아래에서 JSON이 실제로 어떻게 보이는지 확인해 보세요. 이 유형의 데이터 구조를 얻기 위해 REST API를 사용한다는 점을 기억하세요.

{
    "name": "Jake",
    "age": 34,
    "professions": ["writing", "coding"]
}

REST API는 반환 데이터와 그 형식을 제어하기 위해 엔드포인트, 매개변수 및 HTTP 메서드를 사용합니다.

첫 번째 API 요청 수행하기

REST API의 기능을 이해했으니 이제 실제로 사용해 보겠습니다. Quotes to Scrape에도 REST API가 있습니다. 단순히 홈페이지를 불러오는 대신, 이제 그들의 API에 접근해 보겠습니다. 우리는 엔드포인트를 통해 서버와 통신합니다.

전체 엔드포인트 /api/quotes는 두 부분으로 나눌 수 있습니다.

  1. /api: HTML 페이지가 아닌 구조화된 API 데이터를 원한다는 것을 서버에 알립니다.
  2. /quotes: API가 quotes 엔드포인트의 데이터를 반환하기를 원합니다.

요청 실행

이전과 동일하게 코드를 실행해 보세요.

import requests
import json

response = requests.get("https://quotes.toscrape.com/api/quotes")

print(json.dumps(response.json(), indent=4))

이제 데이터가 깔끔하고 구조화된 형태로 반환됩니다. 파싱이 쉬우며, 이를 바탕으로 거의 모든 작업을 수행할 수 있습니다.

{
    "has_next": true,
    "page": 1,
    "quotes": [
        {
            "author": {
                "goodreads_link": "/author/show/9810.Albert_Einstein",
                "name": "Albert Einstein",
                "slug": "Albert-Einstein"
            },
            "tags": [
                "change",
                "deep-thoughts",
                "thinking",
                "world"
            ],
            "text": "u201c우리가 창조한 세상은 우리의 사고 과정이다. 사고를 바꾸지 않고서는 세상을 바꿀 수 없다.u201d"    
        },
        {
            "author": {
                "goodreads_link": "/author/show/1077326.J_K_Rowling",
                "name": "J.K. Rowling",
                "slug": "J-K-Rowling"
            },
            "tags": [
                "abilities",
                "choices"
            ],
            "text": "u201c우리의 선택이야, 해리. 우리의 선택이 우리의 능력을 훨씬 뛰어넘어 우리가 진정 어떤 존재인지를 보여주는 거야.u201d"
        },
        {
            "author": {
                "goodreads_link": "/author/show/9810.Albert_Einstein",
                "name": "Albert Einstein",
                "slug": "Albert-Einstein"
            },
            "tags": [
                "영감",
                "삶",
                "살다",
                "기적",
                "기적들"
            ],
            "text": "u201c인생을 사는 방법은 두 가지뿐이다. 하나는 아무것도 기적처럼 여기지 않는 삶이다. 다른 하나는 모든 것을 기적처럼 여기는 삶이다."
        },
        {
            "author": {
                "goodreads_link": "/author/show/1265.Jane_Austen",
                "name": "Jane Austen",
                "slug": "Jane-Austen"
            },
            "tags": [
                "aliteracy",
                "books",
                "classic",
                "humor"
            ],
            "text": "u201c신사든 숙녀든, 좋은 소설에서 즐거움을 느끼지 못하는 사람은 참을 수 없을 만큼 무식한 사람일 것이다.u201d"
        },
        {
            "author": {
                "goodreads_link": "/author/show/82952.Marilyn_Monroe",
                "name": "Marilyn Monroe",
                "slug": "Marilyn-Monroe"
            },
            "tags": [
                "be-yourself",
                "inspirational"
            ],
            "text": "u201c불완전함은 아름다움이고, 광기는 천재성이다. 그리고 완전히 우스꽝스러운 것이 완전히 지루한 것보다 낫다.u201d"        
        },
        {
            "author": {
                "goodreads_link": "/author/show/9810.Albert_Einstein",
                "name": "Albert Einstein",
                "slug": "Albert-Einstein"
            },
            "tags": [
                "adulthood",
                "success",
                "value"
            ],
            "text": "u201cTry not to become a man of success. 차라리 가치 있는 사람이 되라."
        },
        {
            "author": {
                "goodreads_link": "/author/show/7617.Andr_Gide",
                "name": "Andru00e9 Gide",
                "slug": "Andre-Gide"
            },
            "tags": [
                "life",
                "love"
            ],
            "text": "u201c진정한 자신이 아닌 모습으로 사랑받는 것보다, 진정한 자신의 모습으로 미움받는 것이 낫다.u201d"
        },
        {
            "author": {
                "goodreads_link": "/author/show/3091287.Thomas_A_Edison",
                "name": "Thomas A. Edison",
                "slug": "Thomas-A-Edison"
            },
            "tags": [
                "edison",
                "failure",
                "inspirational",
                "paraphrased"
            ],
            "text": "u201c나는 실패한 것이 아니다. 단지 10,000가지 안 되는 방법을 발견했을 뿐이다.u201d"
        },
        {
            "author": {
                "goodreads_link": "/author/show/44566.Eleanor_Roosevelt",
                "name": "엘리너 루스벨트",
                "slug": "Eleanor-Roosevelt"
            },
            "tags": [
                "misattributed-eleanor-roosevelt"
            ],
            "text": "u201c여성은 티백과 같습니다. 뜨거운 물에 담그기 전까지는 그 강도를 알 수 없지요.u201d"
        },
        {
            "author": {
                "goodreads_link": "/author/show/7103.Steve_Martin",
                "name": "Steve Martin",
                "slug": "Steve-Martin"
            },
            "tags": [
                "humor",
                "obvious",
                "simile"
            ],
            "text": "u201c햇빛 없는 하루는, 말하자면, 밤과 같습니다.u201d"
        }
    ],
    "tag": null,
    "top_ten_tags": [
        [
            "사랑",
            14
        ],
        [
            "영감",
            13
        ],
        [
            "삶",
            13
        ],
        [
            "유머",
            12
        ],
        [
            "책",
            11
        ],
        [
            "독서",
            7
        ],
        [
            "우정",
            5
        ],
        [
            "친구",
            4
        ],
        [
            "진실",
            4
        ],
        [
            "비유",
            3
        ]
    ]
}

인증된 요청 수행하기

공개 데이터 요청 방법을 살펴보았으니, 이제 인증된 API를 살펴보겠습니다. 대부분의 경우 데이터를 가져오려면 API 키가 필요합니다. 대부분의 API 서버는 요청을 인증하기 위해 API 키가 포함된 Authorization 헤더를 요구합니다.

기본적인 GET 요청은 매우 간단합니다. 이제 POST 요청을 시도해 보겠습니다. POST 요청은 더 큰 정보 페이로드를 안전하게 처리하는 데 사용됩니다. 아래 코드에서는 Web Unlocker API를 사용하여 페이지를 파싱하고 마크다운을 반환합니다.

import requests

API_KEY = "your-api-key"
ZONE = "web_unlocker1"

url = "https://api.brightdata.com/request"
headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}
payload = {
    "url": "https://quotes.toscrape.com/",
    "zone": ZONE,
    "format": "raw",
    "data_format": "markdown"
}

response = requests.post(url, headers=headers, json=payload)

print(response.text)

이번 요청은 https://api.brightdata.com/request 로 전송됩니다. 모든 것은 헤더와 페이로드로 제어됩니다.

헤더는 다음과 같습니다:

  • "Authorization": f"Bearer {API_KEY}": 이 헤더는 요청을 귀하의 Bright Data 계정에 연결합니다.
  • "Content-Type": "application/json": 서버에 JSON 형식으로 데이터를 전송함을 알립니다.

이제 페이로드를 살펴보겠습니다:

  • "url": Web Unlocker로 접근하려는 URL입니다.
  • "zone": 웹 언락커 인스턴스에 부여한 존 이름입니다.
  • "format": 원하는 응답 형식(이 경우 raw)
  • "data_format": “markdown”을 사용합니다. 이는 Bright Data에 페이지를 마크다운 형식으로 파싱해 달라는 요청입니다. JSON만큼 유연하지는 않지만, JSON으로 쉽게 변환할 수 있습니다.

페이지가 마크다운으로 변환된 후의 터미널 출력 결과는 다음과 같습니다.

# [스크래핑할 인용문](/) 

[로그인](/login)

“우리가 창조한 세상은 우리의 사고 과정이다. 사고를 바꾸지 않고서는 세상을 바꿀 수 없다.” - 알버트 아인슈타인 [(소개)](/author/Albert-Einstein)

 태그: [변화](/tag/change/page/1/) [깊은 생각](/tag/deep-thoughts/page/1/) [사고](/tag/thinking/page/1/) [세계](/tag/world/page/1/)

“해리, 우리의 진정한 모습을 드러내는 것은 능력보다 선택이다.” - J.K. 롤링 [(소개)](/author/J-K-Rowling)

 태그: [능력](/tag/abilities/page/1/) [선택](/tag/choices/page/1/)

“인생을 사는 방법은 단 두 가지뿐이다. 하나는 아무것도 기적처럼 여기지 않는 삶이고, 다른 하나는 모든 것을 기적처럼 여기는 삶이다.” - 알버트 아인슈타인 [(소개)](/author/Albert-Einstein)

 태그: [영감](/tag/inspirational/page/1/) [삶](/tag/life/page/1/) [살다](/tag/live/page/1/) [기적](/tag/miracle/page/1/) [기적들](/tag/miracles/page/1/)

“좋은 소설에서 즐거움을 느끼지 못하는 사람은, 신사든 숙녀든, 참을 수 없을 만큼 어리석은 사람일 것이다.” - 제인 오스틴 [(about)](/author/Jane-Austen) 

 태그: [문맹](/tag/aliteracy/page/1/) [책](/tag/books/page/1/) [고전](/tag/classic/page/1/) [유머](/tag/humor/page/1/)

“불완전함은 아름다움이고, 광기는 천재성이다. 그리고 완전히 지루한 것보다 완전히 우스꽝스러운 편이 낫다.” - 마릴린 먼로 [(about)](/author/Marilyn-Monroe)

 태그: [자기다움](/tag/be-yourself/page/1/) [영감](/tag/inspirational/page/1/)

“성공한 사람이 되려 하지 마라. 차라리 가치 있는 사람이 되라.” - 알베르트 아인슈타인 [(소개)](/author/Albert-Einstein)

 태그: [성인기](/tag/adulthood/page/1/) [성공](/tag/success/page/1/) [가치](/tag/value/page/1/)

“있는 그대로의 모습으로 미움받는 것이 없는 모습으로 사랑받는 것보다 낫다.” - 앙드레 지드 [(about)](/author/Andre-Gide)

 태그: [삶](/tag/life/page/1/) [사랑](/tag/love/page/1/)

"나는 실패한 것이 아니다. 단지 1만 가지 안 되는 방법을 발견했을 뿐이다." - 토머스 A. 에디슨 [(소개)](/author/Thomas-A-Edison)

 태그: [에디슨](/tag/edison/page/1/) [실패](/tag/failure/page/1/) [영감](/tag/inspirational/page/1/) [의역](/tag/paraphrased/page/1/)

“여자는 티백과 같습니다. 뜨거운 물에 담그기 전까지는 그 강도를 알 수 없죠.” - 엘리너 루스벨트 [(about)](/author/Eleanor-Roosevelt)        

 태그: [misattributed-eleanor-roosevelt](/tag/misattributed-eleanor-roosevelt/page/1/)

“햇빛 없는 날은, 알다시피, 밤과 같아.” - 스티브 마틴 [(정보)](/author/Steve-Martin)

 태그: [유머](/tag/humor/page/1/) [당연한](/tag/obvious/page/1/) [비유](/tag/simile/page/1/)

* [다음 →](/page/2/)

## 상위 10개 태그

[사랑](/tag/love/) [영감](/tag/inspirational/) [삶](/tag/life/) [유머](/tag/humor/) [책](/tag/books/) [독서](/tag/reading/) [우정](/tag/friendship/) [친구들](/tag/friends/) [진실](/tag/truth/) [비유](/tag/simile/)

 인용 출처: [GoodReads.com](https://www.goodreads.com/quotes)

 M

인증에는 고유 식별자(일반적으로 API 키)가 사용됩니다. 이 경우 Web Unlocker에 접근했지만, 사용하는 API 서비스에 관계없이 원리는 동일합니다.

응답 처리

각 응답에는 상태 코드가 포함됩니다. 상태 코드는 클라이언트에게 다양한 메시지를 전달하는 데 사용됩니다. 이상적인 상황에서는 항상 200 상태 코드를 받게 됩니다.

안타깝게도 세상은 완벽하지 않습니다. 200이 아닌 코드를 받으면 문제가 있다는 뜻입니다.

  • 400-499: 이 코드들은 일반적으로 클라이언트 측의 오류를 의미합니다. API 키와 요청 형식을 다시 한번 확인하세요.
  • 500-599: 이 범위는 서버 오류를 나타냅니다. 요청 자체는 정상이었으나, 서버가 어떤 이유로든 요청을 완료하지 못한 경우입니다.

상태 코드에 대한 자세한 내용은 여기에서 확인할 수 있습니다. Python에서 이러한 상태 코드를 처리하는 방법을 배우고 싶다면, 재시도 로직에 대한 이 가이드를 참고하세요.

SDK로 반복적인 코드 작업 생략하기

SDK(소프트웨어 개발 키트)를 사용하면 오류 처리 및 재시도 로직을 위한 반복적인 코드 작성 없이 REST API에 연결할 수 있습니다. OpenAI API도 완전한 REST API를 제공합니다. 여기에서 확인해 보세요.

SDK를 설치하고 HTTP 요청을 생략하려면 다음 명령어를 실행하세요.

pip install openai

이제 OpenAI SDK를 임포트합니다. 처음에 했던 것처럼 평범한 HTML 페이지를 가져옵니다. HTML을 수동으로 파싱하는 데 관심이 있다면 Requests와 BeautifulSoup 사용법을 배울 수 있습니다. HTML 페이지를 가져온 후에는 SDK를 사용하여 해당 페이지를 ChatGPT로 전달해 파싱합니다.

from openai import OpenAI
import requests

OPENAI_API_KEY = "sk-your-openai-api-key"

response = requests.get("https://quotes.toscrape.com")
html_page = response.text

client = OpenAI(api_key=OPENAI_API_KEY)

chat = client.chat.completions.create(
    messages=[
        {
            "role": "user",
            "content": f"다음 페이지에서 인용문을 파싱하세요. JSON만 원합니다—당신의 설명은 전혀 필요 없습니다. 페이지 주소: {html_page}",
        }
    ],
    model="gpt-4o-mini",)


reply = chat.choices[0].message.content
print(f"ChatGPT: {reply}")

이번 출력 결과를 살펴보세요. 파싱이 전혀 필요하지 않습니다—단순히 json 블록 안에 데이터가 들어 있을 뿐입니다.

[
    {
        "text": "우리가 창조한 세상은 우리의 사고 과정이다. 우리의 사고를 바꾸지 않고서는 세상을 바꿀 수 없다.",
        "author": "Albert Einstein",
        "tags": ["change", "deep-thoughts", "thinking", "world"]
    },
    {
        "text": "해리, 우리의 진정한 모습을 보여주는 것은 능력보다 선택이다.",
        "author": "J.K. Rowling",
        "tags": ["abilities", "choices"]
    },
    {
        "text": "인생을 사는 방법은 두 가지뿐이다. 하나는 아무것도 기적처럼 여기지 않는 삶이다. 다른 하나는 모든 것을 기적처럼 여기는 삶이다.",   
        "author": "Albert Einstein",
        "tags": ["영감", "삶", "살다", "기적", "기적들"]
    },
    {
        "text": "좋은 소설에서 즐거움을 느끼지 못하는 사람은 신사든 숙녀든 참을 수 없을 만큼 어리석은 사람이다.",
        "author": "Jane Austen",
        "tags": ["문학", "책", "고전", "유머"]
    },
    {
        "text": "불완전함은 아름다움이고, 광기는 천재성이다. 그리고 완전히 지루한 것보다 완전히 우스꽝스러운 편이 낫다.",
        "author": "Marilyn Monroe",
        "tags": ["be-yourself", "inspirational"]
    },
    {
        "text": "성공한 사람이 되려 하지 마라. 차라리 가치 있는 사람이 되라.",
        "author": "Albert Einstein",
        "tags": ["adulthood", "success", "value"]
    },
    {
        "text": "있는 그대로의 모습으로 미움받는 것이, 없는 모습으로 사랑받는 것보다 낫다.",
        "author": "앙드레 지드",
        "tags": ["삶", "사랑"]
    },
    {
        "text": "나는 실패한 것이 아니다. 단지 1만 가지 안 되는 방법을 발견했을 뿐이다.",
        "author": "Thomas A. Edison",
        "tags": ["edison", "failure", "inspirational", "paraphrased"]
    },
    {
        "text": "여자는 티백과 같습니다; 뜨거운 물에 담그기 전까지는 그 강도를 알 수 없지요.",
        "author": "엘리너 루즈벨트",
        "tags": ["엘리너 루즈벨트에게 잘못 귀속된 명언"]
    },
    {
        "text": "햇빛 없는 하루는, 말하자면, 밤과 같습니다.",
        "author": "Steve Martin",
        "tags": ["humor", "obvious", "simile"]
    }
]

SDK는 수동 HTTP 관리 없이도 REST API의 모든 기능을 제공합니다. AI를 활용한 스크래핑 방법을 배우고 싶다면, Claude와 DeepSeek 가이드를 참고하세요.

결론

이제 Python으로 기본적인 API 요청을 하는 방법을 알았으니, 더 큰 프로젝트로 넘어갈 수 있습니다. API를 사용해 다양한 서비스와 상호작용하며 데이터를 가져올 수 있으며, SDK를 활용해 해당 데이터를 자동으로 파싱할 수도 있습니다. 이 튜토리얼에서는 Web Unlocker를 사용했지만, Bright Data는 여러분의 데이터 요구를 지원하기 위한 다양한 다른 제품들도 제공합니다.

  • 주거용 프록시: 실제 기기의 주거용 IP 주소로 HTTP 트래픽을 라우팅합니다.
  • 스크레이퍼 API: 스크레이핑을 완전히 자동화하고 결과를 프로그래밍 환경에 바로 다운로드하세요.
  • 스크래핑 브라우저: CAPTCHA를 우회하고 Python 스크립트 내에서 직접 실제 헤드리스 브라우저를 제어하세요.

무료 체험판에 가입하고 지금 바로 시작하세요!