5.1 HttpClient과의 만남
Python에서는 많은 프로그래밍 언어처럼 표준 HttpClient가 있어. Python에서는 http.client라고 불리고, HTTP 요청을 낮은 수준에서 만들고 그 응답을 처리할 수 있게 해줘. HTTP 서버와 연결을 만들고 그들과 상호작용할 수 있어.
http.client처럼 낮은 수준의 모듈은 HTTP 작업에 대해 더 세부적인 제어를 제공하지만, 작업을 수행하기 위해 더 많은 코드가 필요해. 이에 비해, requests 같은 높은 수준의 모듈은 많은 구현 세부 사항을 숨기고 더 간단한 인터페이스를 제공해.
http.client의 주요 기능들
http.client 모듈은 다음과 같은 주요 기능을 제공해:
- HTTP 연결 만들기.
- HTTP 요청 보내기.
- HTTP 응답 읽기.
- 요청 및 응답의 헤더와 본문 처리.
requests 모듈과 달리, http.client는 더 낮은 수준이며 HTTP 요청 작업에 있어 많은 세부 사항에 주의를 기울여.
주요 클래스 및 메서드 http.client
| 클래스/메서드 | 설명 |
|---|---|
HTTPConnection |
HTTP 연결 만들기. |
HTTPSConnection |
HTTPS 연결 만들기. |
request(method, url, ...) |
HTTP 요청 보내기. |
getresponse() |
요청에 대한 응답 받기. |
response.status |
응답의 상태 코드. |
response.reason |
응답 상태의 설명 텍스트. |
response.read() |
응답 데이터 읽기. |
response.getheaders() |
모든 응답 헤더 받기. |
response.getheader(name) |
특정 헤더의 값 받기. |
일부를 자세히 살펴볼게.
5.2 GET 요청 실행하기
http.client 라이브러리를 사용하여 요청을 실행하려면, 다음과 같은 절차를 따라야 해:
연결 설정
요청 보내기
응답 받기
연결 종료
사용 후 연결을 종료하는 것은 메모리 누수를 방지하고 리소스를 해제하기 위해 중요해. 특히 많은 요청을 처리하거나 오래 실행되는 응용 프로그램을 사용할 때 중요해.
일반 HTTP 요청에 HTTPConnection을 사용하는 예시:
import http.client
# HTTP 연결 만들기
conn = http.client.HTTPConnection("example.com")
# GET 요청 보내기
conn.request("GET", "/")
# 응답 받기
response = conn.getresponse()
print(response.status, response.reason)
# 연결 종료
conn.close()
HTTPSConnection 사용 예시:
import http.client
# 연결 만들기
conn = http.client.HTTPSConnection("jsonplaceholder.typicode.com")
# GET 요청 보내기
conn.request("GET", "/posts/1")
# 응답 받기
response = conn.getresponse()
print(response.status, response.reason)
# 응답 데이터 읽고 디코딩하기
data = response.read().decode('utf-8')
print(data)
# 모든 응답 헤더 받기
headers = response.getheaders()
for header in headers:
print(f"{header[0]}: {header[1]}")
# 연결 종료
conn.close()
requests를 사용하는 것보다 조금 길다, 그치?
5.3 POST 요청 실행하기
http.client을 사용한 POST 요청은 GET 요청과 매우 비슷하지만, 데이터를 json 문자열로 직접 포장해야 하고, 전송되는 데이터 타입을 명시적으로 지정해야 해 — Content-Type 헤더 추가 필요.
예시:
import http.client
import json
# POST 요청 보내기
conn.request("POST", "/posts", body=payload, headers=headers)
body에는 문자열로 직렬화된 json 객체를 전달하고, headers에는 데이터 유형 정보를 포함하는 딕셔너리를 전달해야 해.
예를 들면, 이렇게 생길 수 있어:
# 전송할 데이터
payload = json.dumps({
"title": "foo",
"body": "bar",
"userId": 1
})
# 헤더 – 전송 컨텐츠 타입
headers = {
'Content-Type': 'application/json'
}
그래서 전체 POST 요청 코드는 이렇게 생길 거야:
import http.client
import json
# 전송할 데이터
payload = json.dumps({
"title": "foo",
"body": "bar",
"userId": 1
})
# 헤더
headers = {
'Content-Type': 'application/json'
}
# 연결 만들기
conn = http.client.HTTPSConnection("jsonplaceholder.typicode.com")
# POST 요청 보내기
conn.request("POST", "/posts", body=payload, headers=headers)
# 응답 받기
response = conn.getresponse()
print(response.status, response.reason)
# 응답 데이터 읽고 디코딩하기
data = response.read().decode('utf-8')
print(data)
# 연결 종료
conn.close()
5.4 요청 실행 중 오류 처리
오류 처리 예시도 들어두는 게 좋을 것 같아, requests 모듈과는 다르게 작동하니까. http.client 모듈에서는, 연결 문제나 다른 HTTP 오류가 있을 때 자동으로 예외가 발생해.
예시:
import http.client
try:
# 연결 만들기
conn = http.client.HTTPSConnection("jsonplaceholder.typicode.com")
# GET 요청 보내기
conn.request("GET", "/posts/1")
# 응답 받기
response = conn.getresponse()
print(response.status, response.reason)
# 응답 데이터 읽고 디코딩하기
data = response.read().decode('utf-8')
print(data)
except http.client.HTTPException as e:
print("HTTP error occurred:", e)
except Exception as e:
print("An error occurred:", e)
finally:
# 연결 종료
conn.close()
뭐라 해야 할까? requests 모듈을 사용하는 게 확실히 더 간단해. 하지만! 많은 모듈과 프레임워크가 사실상 http.client 같은 낮은 수준의 모듈을 내부에서 사용해. 그들이 어떻게 작동하는지 알고 있어야 올바르게 설정할 수 있어.
GO TO FULL VERSION