
requests는 Python에서 HTTP 요청을 간단하고 직관적으로 보낼 수 있게 해주는 가장 널리 쓰이는 라이브러리임.
- 복잡한 소켓 프로그래밍이나 urllib 모듈보다 훨씬 쉬운 인터페이스를 제공
- GET/POST/PUT/PATCH/DELETE 등 주요 HTTP 메서드를 한 줄 코드로 처리할 수 있음.
- 또한 쿼리 파라미터, 헤더, 쿠키, 파일 업로드, 인증, 세션 관리 등 웹 API와 상호작용하는 데 필요한 기능을 모두 지원함.
다음의 URL을 한번 살펴보길 꼭 권함:
Official Quick Start: https://requests.readthedocs.io/en/latest/user/quickstart/
1. Pre-requisite: HTTP
HTTP는 클라이언트(브라우저, 프로그램)와 서버가 통신하는 protocol (규약).
클라이언트는 메서드(method), URL, 헤더(headers), 본문(body) 을 포함한 request(요청)을 보내고, 서버는 상태 코드와 response(응답)을 반환함.
다음은 HTTP의 주요 메서드임:
- GET: 조회 (데이터 읽기)
- 서버의 resource(html 파일 등)를 다운로드하는데 주로 사용됨.
- POST: 생성·전송 (데이터 추가)
- 서버에 새로운 resource를 업로드하는데 사용됨: idempotent(멱등성) 미보장.
- PUT: 전체 갱신 (리소스 교체, idempotent)
- 서버의 기존 resource를 전체 갱신: idempotent 보장!
- PATCH: 부분 수정 (필드 일부만 변경)
- 서버의 기존 resource의 일부만 갱신: idempotent 미보장
- DELETE: 삭제
다음은 주요 상태 코드임:
200OK: 성공201Created: 새 리소스 생성됨202Accepted: 요청이 수락되었으나 완료되지 않았음.204No Content: 내용없음400Bad Request: 잘못된 요청401Unauthorized: 인증 필요404Not Found: 리소스 없음409Conflict: 충돌500Internal Server Error: 서버 오류
2. Response Object (응답 객체)
requests 라이브러리에서 모든 request에 해당하는 함수들(get, post, put, patch 등)의 결과는 Response 객체로 반환됨.
Response 객체는 요청/응답에 대한 다양한 속성과 메서드를 제공하여, requests 라이브러리를 다룰 때 핵심적으로 사용되는 객체임
주요 attributes
response.request: 실제 전송된 요청(헤더, URL, 바디 등)response.status_code: HTTP 상태 코드response.raise_for_status(): 상태코드가 4xx/5xx일 때 예외 발생response.json(): JSON 응답을 Pythondict로 변환response.content: 응답 원문 (bytes객체)response.text: 문자열 (encoding 적용됨)response.encoding: 문자열 해석 시 사용할 문자셋 (자동 추정되나 필요시 수동 지정 가능)response.cookies: 서버에서 설정한 쿠키들 (RequestsCookieJar객체, 딕셔너리처럼 접근 가능)response.headers: 응답 헤더들 (대소문자 구분 없는 dictionary 형태,CaseInsensitiveDict객체)
import requests
r = requests.get("https://httpbin.org/get", params={"검색어": "파이썬"})
# 요청 객체
print("요청 메서드:", r.request.method) # GET
print("요청 URL:", r.request.url) # 최종 요청된 URL
print("요청 헤더:", r.request.headers) # 보낸 헤더
# 상태 코드
print("응답 코드:", r.status_code) # 200 등
# 예외 발생 (4xx/5xx일 때)
try:
r.raise_for_status()
except requests.exceptions.HTTPError as e:
print("HTTP 오류:", e)
# JSON 응답
print("JSON keys:", list(r.json().keys()))
# 원문 바이트열
print("content 타입:", type(r.content))
# 문자열 변환
print("본문 일부:", r.text[:80], "...")
# 인코딩
print("자동 인코딩:", r.encoding)
# r.encoding = "euc-kr" # 필요시 수동 지정
https://httpbin.org/get은 HTTP GET 요청을 테스트할 수 있는 웹 서비스 URL.- 이 URL로 요청을 보내면 헤더 정보, IP 주소, URL 등의 요청 세부사항을 JSON 형태로 반환.
- 개발자들이 HTTP 클라이언트나 API 요청이 올바르게 작동하는지 확인하는 데 자주 사용되는 도구
3. GET Request (조회)
GET은 서버에서 데이터를 가져올(download) 때 사용.
- Query Parameters 는
params파라미터를 사용하여dict로 지정하면 자동 인코딩됨. - 최종 URL은 반환값이
response에서response.request.urlattribute로 확인할 수 있음.
r = requests.get("https://httpbin.org/get", params={"page": 2, "검색어": "python"})
print("최종 URL:", r.request.url) # 200이면 정상
print("상태 코드:", r.status_code)
print("본문 일부:", r.text[:100], "...")
# JSON 응답일 때는 dict로 파싱
try:
print("JSON 응답:", r.json())
except ValueError:
print("JSON 변환 실패(응답이 JSON이 아님)")
다운로드 대상이 image나 pdf등의 특정 file인 경우엔 response.content를 이용한다.
r = requests.get("https://httpbin.org/image/png")
with open("image.png", "wb") as f:
f.write(r.content)
- 작은 파일의 경우
r.content로 전체 바이트 데이터를 한번에 읽을 수 있음.
다음과 같이 stream=true 인자를 주면 데이터를 chunk로 나누어서 읽어들이므로 대용량 파일을 다운로드 하는데 적합함.
with requests.get(url, stream=True) as r:
r.raise_for_status() # 4xx/5xx 상태코드시 시 exception을 raise
with open(tarball_path, "wb") as f:
for chunk in r.iter_content(chunk_size=8192):
if chunk: # keep-alive 용으로 보내지는 비어있는 chunk는 if문을 통해 건너뜀.
f.write(chunk)
iter_content()는 응답 스트림을chunk_size단위로 잘라서 바이트 덩어리를 yield 함.- HTTP/1.1에서는 keep-alive 연결 때문에 중간에 빈 바이트 문자열 (b"")이 전달될 수 있음: keep-alive chunk라고 불림.
- 이는 연결확인용 신호에 불과하므로
if chunk:로 무시할 수 있음. r.raise_for_status()는 아래에 나오는 Error Handling 절을 참고할 것.
4. POST Request (생성·전송)
POST는 서버에 데이터를 전송하거나 새 리소스를 만들 때 사용함.
- form 데이터는
data파라미터에 대한 인자로 넘겨주고 - JSON은
json파라미터에 대한 인자로 설정함.
# Form 전송: 전통적인 웹 로그인/제출 폼과 유사
form = {"username": "kim", "password": "1234"}
r1 = requests.post("https://httpbin.org/post", data=form)
print("Form 전송 결과:", r1.json().get("form"))
# JSON 전송: 현대 REST/JSON API에서 일반적
payload = {"id": 1, "value": "abc"}
r2 = requests.post("https://httpbin.org/post", json=payload)
print("JSON 전송 결과:", r2.json().get("json"))
- https://httpbin.org/post은 HTTP POST 요청을 테스트할 수 있는 웹 서비스 URL.
- 클라이언트가 전송한 form data, json, files 등의 내용을 그대로 응답 JSON 안에 에코해 줌: 전송 데이터 확인 및 디버깅에 유용함.
주의할 것은 위의 예제에서 넘겨지는 form에 하나의 키에 list 객체로 여러 값을 지정할 수도 있음.
payload_tuples = [('key1', 'value1'), ('key1', 'value2')]
response_1 = requests.post('https://httpbin.org/post', data=payload_tuples)
payload_dict = {'key1': ['value1', 'value2']}
response_2 = requests.post('https://httpbin.org/post', data=payload_dict)
파일업로드에 POST를 사용하는 경우는 files파라미터에 업로드할 파일들의 이름과 파일들의 경로를 dict로 설정하면 됨: 뒤의 File Upload 절을 참고.
5. PUT Request (전체 갱신)
PUT은 리소스를 전체적으로 교체할 때 사용되는 HTTP 메서드임.
같은 요청을 여러 번 보내도 결과가 동일한 멱등성(idempotent)을 가짐.
# 리소스 전체 상태를 한 번에 대체한다는 가정
full_state = {
"id": 101,
"name": "Alice",
"role": "dentist",
"active": True
}
r = requests.put("https://httpbin.org/put", json=full_state)
print("상태 코드:", r.status_code) # 보통 200 또는 204
print("요청 바디(JSON):", resp.request.body) # 디버깅: 보낸 페이로드 확인
print("서버가 받은 JSON:", r.json().get("json")) # httpbin은 에코해 줌
https://httpbin.org/put은 HTTP PUT 요청을 테스트하기 위한 엔드포인트 URL.- PUT 메서드로 데이터를 전송하면 요청 헤더, 본문 내용, IP 주소 등의 정보를 JSON 형태로 반환함.
requests에서 json 파라미터를 사용하면 헤더의 Content-Type이 Application/json으로 변경됨.
6. PATCH Request (부분 수정)
PATCH는 리소스의 일부 속성만 수정할 때 사용되는 HTTP 메서드임.
- 보통 바꾸고 싶은 필드만 JSON에 담아 전송함.
- 단, 파일 변경은 JSON 대신 multipart를 쓰거나 별도 업로드 엔드포인트를 둔다
partial = {"role": "oral_surgeon"}
r = requests.patch("https://httpbin.org/patch", json=partial)
print("상태 코드:", r.status_code) # 보통 200 또는 204
print("서버가 받은 JSON:", r.json().get("json")) # httpbin은 에코
- https://httpbin.org/patch는 클라이언트가 전송한 데이터를 “수정 요청(PATCH 방식)” 형태로 받아, 그 내용을 다시 JSON으로 돌려주는 에코(echo) 서비스임.
7. File Upload (파일 업로드)
파일 업로드는 post() 함수에서 files 인자를 사용하면 자동으로 multipart/form-data로 인코딩됨.
# 단일 파일
with open("test.txt", "rb") as f:
files = {"file": f}
r = requests.post("https://httpbin.org/post", files=files)
print("업로드된 파일:", r.json().get("files"))
# 복수 파일 + 추가 필드
with open("report.pdf", "rb") as f1, open("photo.png", "rb") as f2:
files = {
"doc": ("report.pdf", f1, "application/pdf"),
"image": ("photo.png", f2, "image/png"),
# "doc": ("report.pdf", f1), #content type을 지정하지 않을 수도 있음.
# "image": ("photo.png", f2), #content type을 지정하지 않을 수도 있음.
}
data = {"작성자": "김만용", "설명": "임플란트 자료"}
r = requests.post("https://httpbin.org/post", files=files, data=data)
print("서버 form:", r.json().get("form")) # data 필드
print("서버 files:", r.json().get("files")) # 업로드된 파일 미러
8. Error Handling (예외 처리)
반환된 response 객체에서 raise_for_status()메서드를 호출하면 응답의 상태코드를 체크하고,
응답코드가 4xx/5xx인 경우 예외를 발생시킴.
try:
r = requests.get("https://httpbin.org/status/404")
r.raise_for_status()
except requests.exceptions.HTTPError as e:
print("HTTP 오류:", e)
9. Timeout (타임아웃)
무한 대기를 방지하기 위해 timeout을 지정을 할 수도 있음.timeout 파라미터에 (connect, read) 튜플을 설정하여 처리함.
connect: 서버와 연결(TCP소켓연결)되는데 기다리는 최대 대기시간 (sec)read: 서버와 연결된 이후 응답에 대한 read 연산이 완료될 때까지 최대 대기시간 (sec)stream=True로 chunk로 나누어 read될 경우, 각각의 최대 대기시간임.
timeout=10 처럼 단일 값으로도 지정가능한데 이경우 connnect와 read 모두 10임.
import requests
try:
# 연결은 2초 안에 맺어져야 하고, 응답 바디는 5초 안에 시작되어야 함
r = requests.get("https://httpbin.org/delay/10", timeout=(2, 5))
except requests.exceptions.ConnectTimeout:
print("연결(connect) 타임아웃 발생")
except requests.exceptions.ReadTimeout:
print("읽기(read) 타임아웃 발생")
10. Headers & Cookies (헤더와 쿠키)
API 서버는 헤더와 쿠키를 통해 사용자와 상태를 구분함.
headers와 cookies 인자를 이용하여 요청에 추가가 가능하며,
reponse의 headers와 cookies 속성을 통해 응답된 헤더와 쿠기에 접근 가능함.
import requests
# -------------------
# 1. 사용자 정의 헤더 전송
custom_headers = {"User-Agent": "MyApp/1.0"}
r1 = requests.get("https://httpbin.org/headers", headers=custom_headers)
print("=== 요청에 보낸 헤더 ===")
print(custom_headers)
print("\n=== 서버 응답 헤더 ===")
# 응답 헤더는 dict 비슷한 객체 (대소문자 구분 없음)
print(r1.headers)
print("Content-Type:", r1.headers.get("Content-Type"))
print("\n=== 서버 응답 쿠키 ===")
# 서버가 내려준 쿠키 (RequestsCookieJar 객체)
print(r1.cookies)
# -----------
# 2. 쿠키 전송
custom_cookies = {"session_id": "abc123"}
r2 = requests.get("https://httpbin.org/cookies", cookies=custom_cookies)
print("\n=== 요청에 보낸 쿠키 ===")
print(custom_cookies)
print("\n=== 서버 응답 헤더 ===")
print(r2.headers)
print("\n=== 서버 응답 쿠키 ===")
# 반복문으로 개별 쿠키 접근
for c in r2.cookies:
print(f"{c.name} = {c.value}")
headers=...,cookies=...: 요청에 포함시킨 헤더/쿠키r.headers: 서버가 돌려준 응답 헤더r.cookies: 서버가 내려준 쿠키 (RequestsCookieJar)
11. Authentication & Session (로그인/인증)
일부 resource 접근은 단순 요청만으로 가능하지만, 인증을 요구하기도 함.
requests는 다양한 로그인/인증 방식을 지원하며, 대표적으로 다음을 지원:
- 세션 기반 로그인,
- HTTP Basic 인증
- Bearer 토큰 인증
11-1. 세션 로그인 (쿠키 기반)
웹사이트 로그인은 주로 폼(form) 제출 후 서버가 인증용 쿠키(세션ID를 포함)를 발급하는 방식임.
이 경우 requests.Session()을 사용하여 Session객체를 얻고 이의 post 메서드를 통해 로그인 한다.
이후 해당 Session 객체의 메서드들을 통해 이루어지는 요청들은 인증을 위한 로그인 세션 쿠키가 자동으로 포함됨.
import requests
# 세션 생성
s = requests.Session()
# 로그인 (폼 데이터 전송)
login_data = {"username": "kim", "password": "secret"}
login_resp = s.post("https://example.com/login", data=login_data)
print("로그인 상태 코드:", login_resp.status_code)
# 세션을 유지한 채 프로필 페이지 접근 (쿠키 자동 포함)
profile = s.get("https://example.com/profile")
print("프로필 길이:", len(profile.text))
s.post("/login")했을 때 서버가 Set-Cookie 헤더를 내려주고,- 그걸
requests.Session객체s가 저장해 두었다가 이후s.get("/profile")에 자동으로 포함시켜 주는 방식
실제 서비스에선 위와 같이 단순한 경우는 거의 없음.
실전에서는 CSRF, action URL, 헤더, 리다이렉트, 성공 판정, 타임아웃/예외 처리까지 챙겨야 안정적으로 로그인 유지가 됨.
이는 이 문서에서 다룰 범위를 넘어서는 내용임.
참고로, Token 기반 인증 (OAuth2/JWT)의 경우엔 로그인 페이지 응답으로 access token을 얻어서 이후 인증에 사용.
import requests
s = requests.Session()
# 예시: 로그인 응답이 {"access_token": "abc123"} 형태라고 가정
# login_data = {"username": "kim", "password": "secret"}
# login_resp = s.post("https://example.com/login", data=login_data)
# token = login_resp.json()["access_token"]
fake_resp = {"access_token": "abc123"}
token = fake_resp["access_token"]
# 세션에 Bearer 토큰 추가
s.headers.update({"Authorization": f"Bearer {token}"})
# httpbin은 토큰 값을 그대로 돌려줌
r = s.get("https://httpbin.org/bearer")
print(r.json())
s.get,s.post등 모든 요청에Authorization: Bearer <토큰>헤더가 자동으로 포함됨
로그인 및 인증 동작을 정리하면 다음과 같음:
s.post("/login", data=login_data)- 쿠키 기반 인증이라면 서버가 Set-Cookie를 내려줌.
- Token 기반 인증(OAuth2/JWT)이라면 서버가 {"access_token": "...", ...} 같은 JSON을 내려줌.
token = login_resp.json()["access_token"]- 응답 JSON에서 액세스 토큰 문자열을 추출.
s.headers.update({"Authorization": f"Bearer {token}"})- 세션 객체의 헤더에
Authorization: Bearer <토큰>을 등록합니다.
- 세션 객체의 헤더에
- 이후
s.get(),s.post()등 모든 요청에 자동으로 해당 헤더가 포함됨.
11-2. HTTP Basic 인증
Basic 인증은 요청마다 "Authorization: Basic <base64(user:pass)>" 헤더를 붙여 서버에 아이디/비밀번호를 전달하는 방식임.
보안상 반드시 HTTPS와 함께 사용해야 함: 아닌 경우, 패스워드와 같은 민감 정보가 평문(Base64 인코딩)으로 노출될 수 있음.
from requests.auth import HTTPBasicAuth
# Basic Auth 예제 (httpbin은 테스트용 엔드포인트 제공)
r1 = requests.get("https://httpbin.org/basic-auth/user/pass",
auth=HTTPBasicAuth("user", "pass"))
print("Basic 인증:", r1.status_code, r1.json())
11-3. Bearer 토큰 인증
Bearer 토큰은 주로 OAuth2나 JWT(JSON Web Token) 기반 인증 시스템에서 사용됨.
서버가 클라이언트에게 토큰 문자열을 발급하면, 이후 요청에서 Authorization 헤더에 "Bearer <토큰값>"을 넣어 인증을 수행합니다.
비밀번호보다 안전하게 설계되었으며, 만료 시간(expiry)을 두어 재발급 절차를 거치게 하는 경우가 많음.
token = "YOUR_TOKEN"
# 단일 요청에만 Bearer 토큰 사용
r2 = requests.get("https://httpbin.org/bearer",
headers={"Authorization": f"Bearer {token}"})
print("Bearer 인증:", r2.status_code, r2.json())
여러 요청에서 동일한 토큰을 반복적으로 사용해야 한다면, 앞서 본 것처럼 Session.headers.update()를 이용해 세션 전체에 토큰을 설정할 수 있음.
s = requests.Session()
# 세션에 공통 헤더 등록 (모든 요청에 자동 포함)
s.headers.update({"Authorization": f"Bearer {token}"})
# 이후 요청들은 자동으로 Bearer 토큰을 포함
r3 = s.get("https://httpbin.org/bearer")
print("세션 Bearer 인증:", r3.status_code, r3.json())
r4 = s.get("https://httpbin.org/get")
print("r4 Authorization 헤더:", r4.request.headers["Authorization"])
- "YOUR_TOKEN" 은 Bearer Token (Access Token)을 의미.
참고: Token (Access Token, Bearer Token)
- 주로 OAuth2나 JWT(JSON Web Token) 기반 인증에서 사용
- API 키와 달리 로그인/인증 과정을 거쳐 동적으로 발급됨
- 짧은 만료 시간(expiry)을 가지고, Refresh Token으로 갱신 가능
- 반드시 헤더에
Authorization: Bearer <token>형태로 사용: (RFC 6750, Bearer Token Usage).
Bearer Token은 서비스마다 다른 이름으로 불림.
- GitHub Personal Access Token : 사실상 API Key처럼 쓰이지만
Authorization: Bearer ...로 헤더에 추가됨. - Google OAuth2 Access Token : 전형적인 Bearer Token.
참고: API Key vs. Bearer Token
- API Key
- 고정 문자열 (발급 후 장기간 유효하거나 무제한)
- 사용자/애플리케이션을 식별하는 “정적 인증 수단”
- 보통 Authorization 헤더나 쿼리 파라미터(?key=...)로 전달
- Bearer Token
- 로그인이나 권한 부여 과정을 거쳐 동적으로 발급
- (짧은) 만료 시간이 있음
- 반드시
Authorization: Bearer ...형태로 사용
같이보면 좋은 자료
https://requests.readthedocs.io/en/latest/user/quickstart/
2025.08.28 - [Python] - [urllib] request 모듈
'Python' 카테고리의 다른 글
| Isolation Forest : (0) | 2025.09.17 |
|---|---|
| [Ex] 사칙연산기 (CLI) 간단 구현하기-입력받기. (0) | 2025.09.15 |
| [urllib] request 모듈 (1) | 2025.08.28 |
| Exceptions and Debugging Tools (1) | 2025.08.18 |
| CLI Program에서의 arguments - argparse모듈 (1) | 2025.08.12 |