교재 홈: 바이브 코더를 위한 코딩 기초 학습
**웹(web)**은 인터넷 등 연결된 환경에서 주소를 통해 문서와 기능을 제공하고 이용하는 체계입니다. **브라우저(browser)**는 웹 문서를 열어 보는 프로그램입니다. Python 코드는 실행한 컴퓨터에서, JavaScript(자바스크립트) 코드는 이 실습의 경우 브라우저 안에서 동작합니다. 같은 프로젝트의 코드라도 어디에서 실행되는지에 따라 접근할 수 있는 파일과 값이 달라집니다. 이 장에서는 다른 서비스에 자료를 요청하고 받은 답을 화면에 표시하는 흐름을 읽습니다.
**요청(request)**은 자료나 작업을 달라고 보내는 것이고, **응답(response)**은 그 요청에 대해 돌려받는 답입니다. 요청하는 쪽을 클라이언트(client), 요청을 받아 답하는 프로그램이나 컴퓨터를 **서버(server)**라고 합니다. 브라우저도 클라이언트가 될 수 있고 Python 프로그램도 될 수 있습니다.
**API(Application Programming Interface)**는 다른 프로그램이 정해진 형식으로 기능이나 자료를 요청하도록 마련한 통로입니다. **인터페이스(interface)**는 두 대상이 만나 정보를 주고받는 접점이라는 뜻입니다. **HTTP(Hypertext Transfer Protocol)**는 웹에서 요청과 응답을 주고받는 규칙입니다. 통신 규칙을 **프로토콜(protocol)**이라고 부릅니다. 모든 API가 웹 API인 것은 아니며, 이 장에서는 HTTP를 이용하는 API를 다룹니다.
**URL(Uniform Resource Locator)**은 자료나 기능이 있는 위치와 접근 방법을 적은 주소입니다. http://127.0.0.1:8000/summary.json에서 http는 통신 방식이고, **호스트(host)**는 접속할 컴퓨터나 서비스를 가리키는 부분입니다. 숫자로 기기의 주소를 표시하는 것을 IP 주소라고 하며 여기의 127.0.0.1은 자기 컴퓨터를 가리키는 특별한 주소입니다. 이렇게 자기 자신으로 연결하는 것을 **루프백(loopback)**이라고 합니다.
**포트(port)**는 같은 컴퓨터의 여러 통신 창구를 구별하는 번호이며 예제에서는 8000입니다. /summary.json은 요청할 자료의 경로입니다. ?page=2처럼 붙여 보내는 추가 조건을 **질의 매개변수(query parameter)**라고 하며 page라는 이름에 2를 전달하는 뜻입니다. **토큰(token)**이나 API 키는 서비스를 사용할 주체나 접근 범위를 확인하는 데 쓰이는 문자열입니다. 이런 비밀값을 URL에 넣으면 기록에 남을 수 있으며 보호 방법은 12. 보안과 개인정보 — 실행 권한과 데이터 이동을 읽기에서 다룹니다.
HTTPS는 HTTP 통신에 암호화를 적용한 방식입니다. **암호화(encryption)**는 정해진 열쇠에 해당하는 정보 없이는 내용을 읽기 어렵게 바꾸는 기술입니다. HTTPS가 연결을 보호하더라도, 받은 자료가 올바른지나 해당 사람이 작업을 해도 되는지까지 자동 확인하지는 않습니다.
**HTTP 메서드(method)**는 조회·추가·수정처럼 요청의 의도를 나타내는 이름입니다. Python 객체에 붙은 함수인 메서드와 같은 단어를 쓰지만 여기서는 통신 규칙 안의 이름입니다. **상태 코드(status code)**는 서버가 처리 상황을 알려 주는 숫자입니다. 숫자를 전부 외우기보다 성공인지, 요청 문제인지, 서버 문제인지 나누어 읽습니다.
| 요소 | 대표 값 | 읽는 관점 |
|---|---|---|
| 메서드 | GET |
조회 요청입니다. |
| 메서드 | POST |
생성 또는 처리 요청에 흔히 사용됩니다. |
| 메서드 | PUT, PATCH |
각각 대체·일부 수정에 흔히 쓰이지만 서비스 명세가 우선합니다. |
| 메서드 | DELETE |
삭제 요청입니다. |
| 상태 코드 | 200, 201, 204 |
성공 계열입니다. 204 No Content 응답은 본문을 포함하지 않아야 합니다. |
| 상태 코드 | 400, 401, 403, 404 |
요청 문제, 인증 문제, 접근 거부, 대상 없음 등을 나타냅니다. |
| 상태 코드 | 429 |
요청 제한에 걸린 상황입니다. |
| 상태 코드 | 500 계열 |
서버 쪽 처리 실패입니다. |
HTTP 응답은 상태 코드, 헤더(header), 본문(body) 등으로 이루어집니다. 헤더는 자료 종류나 처리 조건을 설명하는 부가 정보이고, 본문은 실제로 돌려준 내용입니다. CSV의 첫 행을 부르는 헤더와 역할이 다르므로 문맥을 구별합니다. 본문이 JSON인지, 필요한 항목과 값 종류가 맞는지 각각 확인합니다. 상태 200을 받았다는 사실만으로 원하는 데이터가 모두 올바르다고 결론 내리지는 않습니다.
실패한 요청을 다시 보내는 **재시도(retry)**를 할 때에는 같은 작업이 여러 번 적용되는지 확인합니다. 조회와 달리 추가·결제 같은 작업은 반복하면 중복 결과를 만들 수 있습니다. 구체적인 판단은 해당 API의 공식 문서에 따릅니다.
아래 예제에서 공개 API는 문서에 정한 조건으로 누구나 조회할 수 있는 API라는 뜻입니다. Request는 보낼 요청을 구성하고, urlopen은 연결해 응답을 받는 Python 기능입니다. timeout=10은 연결 시도나 응답 데이터를 기다리는 개별 대기 작업에 10초의 제한을 둡니다. 요청을 시작한 때부터 응답 전체를 받을 때까지의 총 소요시간이 반드시 10초 이내라는 뜻은 아닙니다. 제한시간이 지나기 전에 응답 조각이 계속 도착하면 전체 수신은 더 오래 걸릴 수 있습니다. User-Agent는 요청을 보낸 프로그램을 설명하는 헤더 이름이고 Accept는 받고 싶은 자료 형식을 알리는 헤더입니다. HTTPError와 URLError는 통신 실패를 구분하는 예외 종류이며 실제 처리는 코드 아래에서 다시 읽습니다.
GitHub의 공식 문서에 있는 ‘지원하는 API 버전 목록 조회’를 이용합니다. 이 요청에는 개인 자료를 보내지 않고 인증 키도 사용하지 않습니다. api_versions.py에 저장합니다.
import json
from urllib.request import Request, urlopen
from urllib.error import HTTPError, URLError
def get_versions():
request = Request(
"<https://api.github.com/versions>",
headers={
"Accept": "application/vnd.github+json",
"User-Agent": "vibe-basics-learning",
},
)
with urlopen(request, timeout=10) as response:
data = json.load(response)
if not isinstance(data, list) or not all(isinstance(item, str) for item in data):
raise ValueError("예상한 버전 문자열 목록이 아닙니다")
return data
def main():
try:
versions = get_versions()
print("버전 수:", len(versions))
for version in versions:
print(version)
except HTTPError as error:
print("HTTP 오류:", error.code)
return 1
except (URLError, TimeoutError):
print("연결 또는 제한시간 문제입니다")
return 1
except (ValueError, UnicodeError):
print("응답 형식을 확인해야 합니다")
return 1
return 0
if __name__ == "__main__":
raise SystemExit(main())
python api_versions.py를 실행합니다. 반환되는 버전 목록은 서비스가 바꾸므로 정해진 개수나 날짜를 정답으로 외우지 않습니다. 상태, JSON 구조, 버전 문자열 목록이 확인되면 기본 조회가 성공한 것입니다. 네트워크가 차단된 환경에서 연결 실패가 난 것은 곧바로 문법 오류를 뜻하지 않습니다.
하위 종류란 더 넓은 종류에 포함되는 구체적인 종류입니다. HTTPError는 URLError에 포함되므로 넓은 오류를 먼저 잡으면 HTTP 상태를 따로 처리할 기회를 놓칠 수 있습니다. 그래서 구체적인 경우부터 검사합니다. except로 예외를 처리하는 방식은 07. 오류 처리 — 메시지에서 원인 후보로 가기의 「예외를 처리할 때 남겨야 하는 정보」절에 있습니다.