3-2 외부 API 연동 방법

3-2 외부 API 연동 방법

← 목차로 돌아가기

썸네일

프로그래밍을 하다 보면 우리 프로그램만으로 모든 것을 해결할 수 없을 때가 많습니다. 외부의 다양한 서비스와 데이터를 내 프로그램으로 가져와 활용해야 할 때가 바로 ‘외부 API 연동’이 필요한 순간입니다. 이 챕터에서는 파이썬으로 외부 API와 소통하는 핵심 방법을 쉽고 명확하게 알려드리겠습니다.

핵심 요약

  • API는 프로그램 간의 약속된 소통 방식입니다.
  • 파이썬의 requests 라이브러리가 API 호출의 표준입니다.
  • GET 요청으로 데이터를 조회하고, 응답은 주로 JSON 형태로 받습니다.
  • params를 사용해 요청 매개변수를 쉽게 전달할 수 있습니다.
  • try-except와 상태 코드 확인으로 안정적인 API 연동이 필수입니다.

안녕하세요! 여러분의 바이브 코더, 현업 3년 차 개발자입니다. 제가 취미로 프로그래밍을 시작한 지 벌써 10년이 넘었는데요, 파이썬을 처음 공부할 때 외부 API 연동만큼 재미있고 활용도가 높았던 주제도 드물었던 것 같습니다. 내 프로그램 안에서만 동작하던 코드가 세상 밖으로 나가 다른 서비스와 연결되는 경험은 정말 새로운 세계를 열어주었죠. 예를 들어, 날씨 정보를 실시간으로 가져오거나, 주식 시세를 확인하고, 심지어 다른 AI 모델의 기능을 내 프로그램에 붙여 사용하는 등 그 가능성은 무궁무진합니다.

이번 챕터에서는 외부 API와 파이썬을 연동하는 핵심적인 방법을 쉽고 실용적인 예제 코드를 통해 살펴보겠습니다. 특히 제가 현업에서 데이터 분석과 자동화 스크립트를 짤 때 가장 많이 사용하는 requests 라이브러리를 중심으로 설명드릴 예정입니다. 이 챕터를 마치면 여러분은 직접 파이썬으로 외부 데이터를 가져와 활용하는 자신만의 스크립트를 만들 수 있을 것입니다.

사전 준비: 파이썬과 requests 라이브러리

외부 API 연동을 시작하기 전에 파이썬이 설치되어 있는지 확인하고, requests 라이브러리를 설치해야 합니다.

먼저, 파이썬 3.11 버전 이상이 설치되어 있어야 합니다. 파이썬 공식 웹사이트에서 다운로드하여 설치할 수 있습니다. 설치가 완료되었다면, 터미널(또는 명령 프롬프트)을 열고 다음 명령어를 입력하여 requests 라이브러리를 설치합니다. requests는 파이썬에서 HTTP 요청을 보낼 때 가장 널리 사용되고 강력한 라이브러리입니다. 제가 현업에서 데이터 연동 작업의 약 90% 이상을 이 라이브러리로 처리한다고 해도 과언이 아닐 정도로 그 활용성이 높습니다.

pip install requests

이 명령어를 입력하면 requests 라이브러리가 자동으로 다운로드되어 설치됩니다. 이제 모든 준비가 끝났으니, 본격적으로 API의 세계로 뛰어들어 봅시다.

API란 무엇인가요?

API(Application Programming Interface)는 소프트웨어 애플리케이션들이 서로 통신할 수 있도록 해주는 규칙과 절차의 집합입니다.

API는 쉽게 말해, 서로 다른 프로그램이나 서비스가 약속된 방식으로 정보를 주고받을 수 있게 해주는 ‘소통 창구’라고 생각하시면 됩니다. 마치 식당에서 손님(클라이언트)이 종업원(API)에게 메뉴(요청)를 주문하고, 종업원은 주방(서버)에 주문을 전달하여 요리(데이터 처리)를 가져다주는 과정과 유사합니다. 손님은 주방 안에서 요리가 어떻게 만들어지는지 몰라도 종업원을 통해 원하는 음식을 받을 수 있죠. 이처럼 API를 통해 우리는 복잡한 서버 로직을 알 필요 없이, 정해진 규칙에 따라 요청만 보내면 원하는 데이터를 얻을 수 있습니다.

웹 환경에서는 주로 HTTP 프로토콜을 기반으로 하는 RESTful API가 많이 사용됩니다. 여기서 주로 사용하는 요청 방식으로는 데이터를 ‘가져오는’ GET, 데이터를 ‘생성하는’ POST, 데이터를 ‘수정하는’ PUT, 데이터를 ‘삭제하는’ DELETE 등이 있습니다. 이 챕터에서는 주로 데이터를 조회하는 GET 요청을 중심으로 다룰 것입니다.

파이썬으로 API 호출을 시작하는 방법은 무엇인가요?

requests 라이브러리를 활용하면 파이썬에서 HTTP GET 요청을 보내고 응답을 처리하는 것이 매우 간단합니다.

가장 기본적인 API 호출은 데이터를 읽어오는 GET 요청입니다. 제가 개인 프로젝트에서 다른 서비스의 공개 데이터를 가져올 때 가장 먼저 시도하는 방법이 바로 이 GET 요청입니다. 여기서는 간단한 테스트용 API인 JSONPlaceholder를 사용하여 사용자 목록을 가져오는 예제를 살펴보겠습니다.

단계 1: requests 라이브러리 임포트 및 GET 요청 보내기

이 코드는 requests 라이브러리를 임포트하고, JSONPlaceholder의 /users 엔드포인트로 GET 요청을 보냅니다.

import requests

# API 엔드포인트 URL
url = "https://jsonplaceholder.typicode.com/users"

# GET 요청 보내기
response = requests.get(url)

print(f"응답 상태 코드: {response.status_code}")
print(f"응답 내용 (일부): {response.text[:100]}...")

이 코드는 requests 모듈을 불러온 후, 특정 URL에 GET 요청을 보내고, 서버로부터 받은 응답의 상태 코드와 내용을 출력합니다. response.status_code는 HTTP 응답 코드를 나타내며, 200은 성공을 의미합니다.

단계 2: JSON 응답 데이터 다루기

대부분의 웹 API는 데이터를 JSON(JavaScript Object Notation) 형식으로 응답합니다. 파이썬 requests 라이브러리는 이 JSON 응답을 파이썬 딕셔너리나 리스트 형태로 쉽게 변환해주는 강력한 기능을 제공합니다. 저도 데이터를 가져와서 분석할 때 이 기능 덕분에 시간 절약을 많이 합니다. 변수와 데이터 타입 다루기 챕터에서 다루었듯이, 딕셔너리와 리스트는 파이썬에서 데이터를 구조화하고 접근하는 데 매우 유용합니다.

import requests

url = "https://jsonplaceholder.typicode.com/users"
response = requests.get(url)

if response.status_code == 200:
    users = response.json() # JSON 응답을 파이썬 객체로 변환
    print("첫 번째 사용자 이름:", users[0]['name'])
    print("모든 사용자 수:", len(users))
else:
    print("API 요청 실패.")

이 코드는 응답 상태 코드가 200일 경우, response.json() 메서드를 사용하여 응답 본문을 파이썬 리스트(이 경우 사용자 목록)로 변환합니다. 변환된 데이터에서 첫 번째 사용자의 이름과 전체 사용자 수를 쉽게 확인할 수 있습니다. 데이터의 구조를 파악하면 원하는 정보를 정확히 추출할 수 있습니다.

API 요청에 매개변수를 추가하는 방법은 무엇인가요?

API 요청에 쿼리 매개변수(query parameters)를 추가하여 원하는 조건의 데이터를 필터링하거나 정렬할 수 있습니다.

많은 API는 특정 조건을 만족하는 데이터만 가져오기 위해 쿼리 매개변수를 제공합니다. 예를 들어, 게시물 목록에서 특정 사용자 ID의 게시물만 가져온다거나, 검색어를 포함하는 게시물만 가져올 때 사용합니다. requests 라이브러리는 params 인자를 통해 딕셔너리 형태로 매개변수를 전달하는 편리한 방법을 제공합니다.

import requests

# 특정 사용자 ID의 게시물 가져오기
url = "https://jsonplaceholder.typicode.com/posts"
params = {
    'userId': 1 # 사용자 ID가 1인 게시물만 요청
}

response = requests.get(url, params=params)

if response.status_code == 200:
    posts = response.json()
    print(f"사용자 ID 1의 게시물 수: {len(posts)}")
    if posts:
        print("첫 번째 게시물 제목:", posts[0]['title'])
else:
    print("API 요청 실패.")

이 코드는 userId가 1인 게시물만 요청하도록 params 딕셔너리를 설정하고, 이를 requests.get() 함수의 params 인자로 전달합니다. requests 라이브러리가 자동으로 URL 뒤에 ?userId=1과 같은 형태로 쿼리 문자열을 추가해주므로, 개발자는 복잡한 URL 인코딩에 신경 쓸 필요가 없습니다. 제가 현업에서 수많은 데이터를 필터링하고 조회할 때 이 params 기능을 정말 많이 사용합니다.

API 응답 데이터를 효과적으로 처리하려면 어떻게 해야 하나요?

API 응답을 받은 후에는 status_code를 확인하고, json() 메서드로 데이터를 파싱하여 필요에 맞게 가공하는 것이 중요합니다.

API로부터 데이터를 성공적으로 받았다고 해서 모든 작업이 끝난 것은 아닙니다. 받은 데이터를 프로그램이 이해하고 활용할 수 있는 형태로 처리해야 합니다. 특히 중요한 것은 응답의 상태 코드를 확인하여 요청이 성공했는지, 아니면 어떤 문제가 발생했는지 파악하는 것입니다. 제 경험상, 예상치 못한 API 오류는 대부분 상태 코드 확인을 소홀히 해서 발생했습니다.

import requests

url = "https://jsonplaceholder.typicode.com/todos"
response = requests.get(url)

if response.status_code == 200:
    todos = response.json() # To-do 목록 데이터를 파싱

    # 완료된 To-do 개수 세기
    completed_todos_count = sum(1 for todo in todos if todo['completed'])
    print(f"전체 To-do 항목 수: {len(todos)}")
    print(f"완료된 To-do 항목 수: {completed_todos_count}")

    # 첫 5개 미완료 To-do 항목 출력
    print("\n미완료 To-do 항목 (첫 5개):")
    uncompleted_count = 0
    for todo in todos:
        if not todo['completed']:
            print(f"- {todo['title']}")
            uncompleted_count += 1
        if uncompleted_count >= 5:
            break

elif response.status_code == 404:
    print("요청한 리소스를 찾을 수 없습니다. URL을 확인하세요.")
elif response.status_code == 500:
    print("서버 내부 오류가 발생했습니다. 잠시 후 다시 시도해주세요.")
else:
    print(f"알 수 없는 오류 발생: {response.status_code}")

이 코드는 /todos 엔드포인트에서 To-do 목록을 가져와 성공적으로 응답받았을 경우, 완료된 To-do 항목의 개수를 세고 미완료된 항목 중 일부를 출력합니다. response.status_code를 통해 다양한 상황에 유연하게 대처하는 것을 볼 수 있습니다. 이처럼 데이터를 파싱한 후에는 파이썬의 리스트와 딕셔너리 조작 기능을 활용하여 원하는 정보를 추출하고 분석할 수 있습니다. 데이터 분석 파이프라인 구축 시 API 연동은 가장 첫 단계를 담당하는 경우가 많습니다.

API 연동 시 발생할 수 있는 오류는 어떻게 처리해야 하나요?

try-except 문을 사용하여 네트워크 오류를 방지하고, response.raise_for_status()로 HTTP 오류를 명확하게 처리해야 안정적인 프로그램을 만들 수 있습니다.

API 연동은 네트워크를 통해 이루어지므로, 다양한 문제가 발생할 수 있습니다. 네트워크 연결 문제, 서버 오류, 잘못된 요청 등 예외 상황은 항상 존재합니다. 제가 처음 API 연동 코드를 짤 때 가장 많이 실수했던 부분이 바로 이 에러 핸들링이었습니다. 오류 처리가 제대로 되어 있지 않으면 프로그램이 갑자기 멈춰버리거나 예상치 못한 동작을 할 수 있습니다. 에러 핸들링 기본기 챕터에서 다루었듯이, try-except 구문은 이러한 문제를 해결하는 핵심 도구입니다.

흔한 실수와 해결법

  • 네트워크 연결 끊김: requests.exceptions.ConnectionError 발생. try-except로 처리합니다.
  • 잘못된 URL: requests.exceptions.MissingSchema 또는 requests.exceptions.InvalidURL 발생. URL을 정확히 확인합니다.
  • API 키 누락/잘못됨: 401(Unauthorized) 또는 403(Forbidden) 상태 코드 응답. API 문서 확인 및 키 재발급을 고려합니다.
  • 요청 시간 초과: requests.exceptions.Timeout 발생. timeout 인자를 사용하여 적절한 시간 제한을 설정합니다.
import requests

url = "https://jsonplaceholder.typicode.com/non_existent_path" # 의도적으로 잘못된 URL 설정

try:
    # 요청 시간 제한을 5초로 설정
    response = requests.get(url, timeout=5)
    
    # HTTP 오류 발생 시 예외 발생 (4xx, 5xx 에러)
    response.raise_for_status()
    
    data = response.json()
    print("데이터를 성공적으로 가져왔습니다:", data)

except requests.exceptions.HTTPError as e:
    print(f"HTTP 오류 발생: {e}")
    print(f"상태 코드: {response.status_code}")
except requests.exceptions.ConnectionError as e:
    print(f"네트워크 연결 오류 발생: {e}")
except requests.exceptions.Timeout as e:
    print(f"요청 시간 초과 오류 발생: {e}")
except requests.exceptions.RequestException as e:
    print(f"알 수 없는 요청 오류 발생: {e}")
except ValueError: # response.json() 파싱 실패 시
    print("응답 JSON 파싱 실패.")
except Exception as e:
    print(f"예상치 못한 오류 발생: {e}")

이 코드는 다양한 종류의 requests 관련 예외를 처리하여 프로그램의 안정성을 높입니다. 특히 response.raise_for_status() 메서드는 응답 상태 코드가 4xx (클라이언트 오류) 또는 5xx (서버 오류)일 경우 HTTPError 예외를 자동으로 발생시켜주므로, 일일이 if response.status_code != 200:과 같은 코드를 작성할 필요 없이 깔끔하게 오류를 처리할 수 있습니다. 제가 현업에서 자동화 스크립트 작성 시 이 에러 핸들링 패턴을 거의 공식처럼 사용하고 있습니다.

실제 공개 API를 활용한 데이터 수집 예제를 보여주시겠어요?

날씨 API를 호출하여 현재 서울의 날씨 정보를 가져오는 실제 예제를 통해 API 연동의 전 과정을 이해할 수 있습니다.

이제 JSONPlaceholder를 넘어 실제 공개 API를 사용해 데이터 수집 스크립트를 만들어 보겠습니다. 여기서는 OpenWeatherMap의 Current Weather Data API를 사용해 서울의 현재 날씨 정보를 가져와 출력하는 예제를 만들 것입니다. 이 API는 간단한 사용을 위해 무료 계정으로도 API 키를 발급받을 수 있습니다.

참고: OpenWeatherMap API를 사용하려면 OpenWeatherMap 웹사이트에서 무료 계정을 생성하고 API 키(App ID)를 발급받아야 합니다. 발급받은 키를 아래 코드의 YOUR_API_KEY 부분에 넣어주세요. (2026년 기준)

전체 코드: 서울 날씨 정보 가져오기

import requests

def get_weather(city_name, api_key):
    base_url = "http://api.openweathermap.org/data/2.5/weather"
    params = {
        'q': city_name,
        'appid': api_key,
        'units': 'metric', # 섭씨 온도를 위해 metric 사용
        'lang': 'kr' # 한국어 응답을 위해 lang=kr 추가
    }

    try:
        response = requests.get(base_url, params=params, timeout=10)
        response.raise_for_status() # HTTP 오류 발생 시 예외 발생
        
        weather_data = response.json()
        
        # 필요한 정보 추출
        city = weather_data['name']
        temperature = weather_data['main']['temp']
        feels_like = weather_data['main']['feels_like']
        description = weather_data['weather'][0]['description']
        humidity = weather_data['main']['humidity']
        wind_speed = weather_data['wind']['speed']
        
        print(f"--- {city}의 현재 날씨 --- ")
        print(f"기온: {temperature}°C (체감: {feels_like}°C)")
        print(f"날씨: {description}")
        print(f"습도: {humidity}%")
        print(f"풍속: {wind_speed} m/s")
        print("----------------------")
        
    except requests.exceptions.HTTPError as e:
        print(f"HTTP 오류 발생: {e.response.status_code} - {e.response.text}")
    except requests.exceptions.ConnectionError:
        print("네트워크 연결에 문제가 있습니다.")
    except requests.exceptions.Timeout:
        print("요청 시간 초과.")
    except requests.exceptions.RequestException as e:
        print(f"API 요청 중 알 수 없는 오류 발생: {e}")
    except KeyError as e:
        print(f"날씨 데이터 파싱 오류: 예상치 못한 키: {e}")
        print("응답 데이터 전체: ", weather_data)


# --- 프로그램 실행 --- #
YOUR_API_KEY = "YOUR_API_KEY_HERE" # 여기에 발급받은 API 키를 넣어주세요!

if YOUR_API_KEY == "YOUR_API_KEY_HERE":
    print("오류: OpenWeatherMap API 키를 설정해주세요!\n")
    print("OpenWeatherMap 웹사이트에서 무료 계정을 생성하고 API 키(App ID)를 발급받아야 합니다.")
    print("자세한 내용은 본문 내용을 참고해주세요.")
else:
    get_weather("Seoul", YOUR_API_KEY)
    get_weather("Busan", YOUR_API_KEY)

이 코드는 get_weather 함수를 정의하여 도시 이름과 API 키를 인자로 받아 날씨 정보를 조회하고 출력합니다. try-except 블록을 사용하여 발생할 수 있는 모든 예외를 처리하고 있으며, 응답 데이터를 파싱하여 핵심 정보만 추출하고 보기 좋게 출력합니다. 여러분도 이 코드를 바탕으로 다른 도시의 날씨를 조회하거나, 추가 정보를 가져오는 등 다양하게 확장해볼 수 있습니다. 제가 처음 API를 연동해서 날씨 정보를 가져왔을 때의 성취감은 정말 잊을 수 없습니다. 여러분도 이 경험을 통해 프로그래밍의 즐거움을 더 깊이 느껴보시길 바랍니다.

결론

외부 API 연동은 여러분의 파이썬 프로그램이 ‘세상과 소통’하게 만드는 강력한 도구입니다. requests 라이브러리를 통해 간단한 GET 요청부터 복잡한 에러 처리까지, 여러분은 이제 외부 데이터를 가져와 원하는 방식으로 활용할 수 있는 기초를 다지게 되었습니다. 제 경험상, API 연동 능력이 프로그램의 활용도를 몇 배 이상 높여준다고 단언할 수 있습니다. AI 프로그래밍 트렌드를 보면, 점점 더 많은 서비스들이 API 형태로 제공되고 있으며, 이들과의 연동 능력은 앞으로 더욱 중요해질 것입니다.

이제 여러분은 이 지식을 바탕으로 더욱 복잡한 데이터 분석 파이프라인을 구축하거나, 웹 애플리케이션 개발 사례에서 볼 수 있듯이 다양한 외부 서비스와 연동하여 새로운 기능을 만들어낼 수 있을 것입니다. 궁금한 점이나 막히는 부분이 있다면 언제든 직접 코드를 바꿔가며 실험해보세요. 그것이 가장 좋은 학습 방법입니다!

자주 묻는 질문 (FAQ)

Q1: API 키는 왜 필요한가요?

A1: API 키는 서비스 제공자가 사용자를 식별하고, 사용량을 추적하며, 보안을 유지하기 위해 사용됩니다. 대부분의 상업용 또는 특정 기능의 API는 무단 사용을 방지하고 서비스 남용을 막기 위해 API 키를 요구합니다.

Q2: requests 말고 다른 라이브러리도 있나요?

A2: 네, 파이썬 표준 라이브러리인 urllib.request 모듈도 HTTP 요청을 보낼 수 있습니다. 하지만 requests 라이브러리는 urllib.request보다 훨씬 간편하고 직관적인 API를 제공하여 사용하기 편리합니다. 그래서 대부분의 파이썬 개발자들이 requests를 선호합니다.

Q3: GET 요청 외에 POST 요청은 어떻게 사용하나요?

A3: POST 요청은 주로 서버에 데이터를 생성하거나 전송할 때 사용됩니다. requests.post(url, data=payload) 또는 requests.post(url, json=payload_json) 형태로 데이터를 바디에 담아 보낼 수 있습니다. HTTP Methods (W3Schools)와 같은 문서를 참고하시면 더 자세히 알 수 있습니다.

Q4: API 호출 시 속도 제한(Rate Limit)에 걸리면 어떻게 해야 하나요?

A4: API 속도 제한은 짧은 시간 안에 너무 많은 요청을 보낼 경우 발생합니다. 이때는 time.sleep() 함수를 사용하여 요청 사이에 지연 시간을 두거나, API 문서에 명시된 제한 정책을 따라야 합니다. 때로는 requests-cache와 같은 라이브러리를 사용해 응답을 캐싱하여 요청 횟수를 줄일 수도 있습니다.

Q5: 제가 만든 파이썬 프로그램에서 API 키를 안전하게 관리하는 방법이 있나요?

A5: API 키를 코드에 직접 하드코딩하는 것은 보안상 좋지 않습니다. 환경 변수, 설정 파일(예: .env 파일), 또는 파이썬의 configparser 모듈을 사용하여 키를 분리하고, 프로그램을 배포할 때는 해당 파일을 .gitignore에 추가하여 버전 관리에 포함되지 않도록 하는 것이 일반적인 방법입니다.

참고 자료

  1. [1] Python 공식 문서 — https://docs.python.org/ko/3/
  2. [2] Claude Code 공식 문서 — https://docs.claude.com/en/docs/claude-code/overview

#파이썬API, #requests라이브러리, #API연동, #파이썬프로그래밍, #웹스크래핑, #데이터수집, #자동화스크립트, #OpenWeatherMap, #API키관리, #HTTP요청

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다