백엔드 (Backend)

백엔드는 ahttp_client 가 여러 서드파티 HTTP 클라이언트 라이브러리를 하나의 인터페이스로 다룰 수 있게 하는 어댑터 계층입니다. 백엔드를 직접 만들 일은 없고, 세션에 사용할 HTTP 클라이언트 클래스를 넘기면 알아서 맞는 백엔드가 선택됩니다.

import aiohttp
import httpx

# Selects AiohttpBackend
aiohttp_service = GithubService("https://api.github.com", aiohttp.ClientSession)

# Selects HttpXAsyncSession
httpx_service = GithubService("https://api.github.com", httpx.AsyncClient)

지원되는 백엔드

라이브러리

세션 클래스

백엔드 클래스

추가 의존성

aiohttp

aiohttp.ClientSession

ahttp_client.backend.AiohttpBackend

pip install aiohttp

httpx (비동기)

httpx.AsyncClient

ahttp_client.backend.HttpXAsyncSession

pip install httpx

httpx (동기)

httpx.Client

ahttp_client.backend.HttpXSyncSession

pip install httpx

requests (동기)

requests.Session

ahttp_client.backend.RequestsBackend

pip install requests

AsyncSession 은 aiohttp.ClientSession, httpx.AsyncClient 등 등록된 비동기 세션 클래스라면 뭐든 받습니다. Session 은 httpx.Client, requests.Session 등 등록된 동기 세션 클래스를 받습니다.

참고

aiohttp, httpx, requests 같은 선택적 의존성이 설치되어 있지 않으면 그냥 건너뜁니다. ahttp_client.backend 는 해당 서드파티 패키지를 import할 수 있는 백엔드만 골라서 내보냅니다.

백엔드 선택 방식

BaseBackend 는 서드파티 세션 클래스와 백엔드 클래스를 매핑하는 레지스트리를 갖고 있습니다. 구체적인 백엔드 클래스는 session_cls 와 response_cls 가 둘 다 정의되는 순간 __init_subclass__ 를 통해 알아서 자기 자신을 등록합니다.

AsyncSession(base_url, aiohttp.ClientSession) 처럼 세션을 만들면 내부적으로 AsyncBackend.from_session(aiohttp.ClientSession, base_url=base_url, **kwargs) 가 호출되어, 그 세션 클래스에 등록된 백엔드를 찾아 인스턴스화합니다. 그래서 AsyncSession/Session 에 넘기는 session=… 인자는 백엔드 인스턴스가 아니라 그냥 서드파티 클라이언트 클래스입니다.

커스텀 백엔드 작성하기

커스텀 HTTP 클라이언트 라이브러리를 지원하려면 비동기 클라이언트는 AsyncBackend, 동기 클라이언트는 SyncBackend 를 서브클래싱해서 session_cls/response_cls 를 정의하고, 아래 역할을 하는 추상 메소드를 구현하면 됩니다:

  • RequestCore 를 해당 클라이언트의 요청 keyword arguments로 변환합니다 (get_request_kwargs).

  • response_status, response_headers, response_url, response_data, response_text, response_json, response_closed 는 그 클라이언트의 응답 객체에서 상태 코드, 헤더, URL, 본문, 닫힘 상태를 읽어옵니다.

  • response_close 와 session_close/session_closed 는 응답과 세션 자체를 닫는 역할을 맡습니다.

  • 내부 세션에 각 HTTP 메소드를 요청합니다 (session_request, session_get, session_post, session_options, session_delete, session_patch, session_put).

 1from ahttp_client.backend import AsyncBackend
 2
 3class MyClientBackend(AsyncBackend):
 4    session_cls = my_client.Session
 5    response_cls = my_client.Response
 6
 7    def get_request_kwargs(self, request_obj):
 8        ...
 9
10    def response_status(self, response_obj) -> int:
11        return response_obj.status_code
12
13    # ... remaining abstract methods

MyClientBackend 를 import하고 나면 AsyncSession(base_url, my_client.Session) 이 자동으로 이 백엔드에 연결됩니다. 따로 등록할 필요는 없습니다.

Reference

class BaseBackend

지원되는 HTTP 클라이언트 라이브러리를 위한 기본 어댑터입니다.

백엔드는 클라이언트 세션을 만들고, RequestCore 값을 클라이언트별 keyword arguments로 바꾸고, 공통된 응답 인터페이스를 제공합니다. session_cls 와 response_cls 를 둘 다 정의한 서브클래스는 자동으로 등록됩니다.

classmethod from_session(session: type[Any], **kwargs: Any) → _BackendT

HTTP 클라이언트 세션 클래스에 등록된 백엔드를 생성합니다.

매개변수:
  • session (type) – 지원되는 HTTP 클라이언트 세션 클래스입니다.

  • **kwargs – 백엔드 생성자로 전달되는 keyword arguments입니다.

예외 발생:

TypeError – session 이 어떤 백엔드에도 등록되어 있지 않은 경우 발생합니다.

abstractmethod get_request_kwargs(request_obj: RequestCore[Any, Any]) → dict[str, Any]

request 디스크립터를 클라이언트별 요청 인자로 변환합니다.

abstractmethod response_close(response_obj: Any) → None | Awaitable[None]

클라이언트 응답 객체를 닫습니다.

abstractmethod response_closed(response_obj: Any) → bool | None

응답의 닫힘 상태를 반환하며, 알 수 없는 경우 None 을 반환합니다.

abstractmethod response_data(response_obj: Any) → bytes

응답 본문을 bytes 형태로 반환합니다.

abstractmethod response_headers(response_obj: Any) → dict[str, Any]

응답 헤더를 딕셔너리로 반환합니다.

abstractmethod response_json(response_obj: Any, json_parser: Callable[..., Any] | None = None, json_kwargs: dict[str, Any] | None = None) → Any | None

선택적인 커스텀 파서를 이용해 응답 본문을 JSON으로 파싱합니다.

abstractmethod response_status(response_obj: Any) → int

클라이언트 응답에서 HTTP 상태 코드를 반환합니다.

abstractmethod response_text(response_obj: Any) → str

응답 본문을 텍스트로 디코딩하여 반환합니다.

abstractmethod response_url(response_obj: Any) → str

클라이언트 응답과 연관된 URL을 반환합니다.

abstract property session_closed: bool

내부의 HTTP 클라이언트 세션이 닫혔는지 여부를 반환합니다.

class AsyncBackend

기반 클래스: BaseBackend, ABC

비동기 HTTP 클라이언트 라이브러리를 위한 기본 어댑터 계약(contract)입니다.

async pre_read_response(response_obj: Any) → None

Response 로 노출되기 전에 응답을 미리 읽습니다.

즉시 읽기(eager read)가 필요한 백엔드는 이 메소드를 오버라이딩할 수 있습니다.

abstractmethod async session_close() → None

내부의 비동기 HTTP 클라이언트 세션을 닫습니다.

abstractmethod async session_delete(path: str, **kwargs: Any) → Any

비동기 DELETE 요청을 만듭니다.

abstractmethod async session_get(path: str, **kwargs: Any) → Any

비동기 GET 요청을 만듭니다.

abstractmethod async session_options(path: str, **kwargs: Any) → Any

비동기 OPTIONS 요청을 만듭니다.

abstractmethod async session_patch(path: str, **kwargs: Any) → Any

비동기 PATCH 요청을 만듭니다.

abstractmethod async session_post(path: str, **kwargs: Any) → Any

비동기 POST 요청을 만듭니다.

abstractmethod async session_put(path: str, **kwargs: Any) → Any

비동기 PUT 요청을 만듭니다.

abstractmethod async session_request(method: str, path: str, **kwargs: Any) → Any

주어진 메소드와 경로로 비동기 HTTP 요청을 만듭니다.

class SyncBackend

기반 클래스: BaseBackend, ABC

동기 HTTP 클라이언트 라이브러리를 위한 기본 어댑터 계약(contract)입니다.

abstractmethod session_close() → None

내부의 동기 HTTP 클라이언트 세션을 닫습니다.

abstractmethod session_delete(path: str, **kwargs: Any) → Any

동기 DELETE 요청을 만듭니다.

abstractmethod session_get(path: str, **kwargs: Any) → Any

동기 GET 요청을 만듭니다.

abstractmethod session_options(path: str, **kwargs: Any) → Any

동기 OPTIONS 요청을 만듭니다.

abstractmethod session_patch(path: str, **kwargs: Any) → Any

동기 PATCH 요청을 만듭니다.

abstractmethod session_post(path: str, **kwargs: Any) → Any

동기 POST 요청을 만듭니다.

abstractmethod session_put(path: str, **kwargs: Any) → Any

동기 PUT 요청을 만듭니다.

abstractmethod session_request(method: str, path: str, **kwargs: Any) → Any

주어진 메소드와 경로로 동기 HTTP 요청을 만듭니다.

class AiohttpBackend

기반 클래스: AsyncBackend

aiohttp.ClientSession 을 위한 백엔드 어댑터입니다.

aiohttp 패키지가 필요합니다 (pip install aiohttp). aiohttp.ClientSession 에 등록되어 있고, 응답 타입으로 aiohttp.ClientResponse 를 그대로 감쌉니다.

class HttpXAsyncSession

기반 클래스: AsyncBackend, CommonHttpXBackend

httpx.AsyncClient 를 위한 백엔드 어댑터입니다.

httpx 패키지가 필요합니다 (pip install httpx). httpx.AsyncClient 에 등록되어 있으며, AsyncSession(base_url, httpx.AsyncClient) 로 세션을 생성할 때 사용됩니다.

class HttpXSyncSession

기반 클래스: SyncBackend, CommonHttpXBackend

httpx.Client 를 위한 백엔드 어댑터입니다.

httpx 패키지가 필요합니다 (pip install httpx). httpx.Client 에 등록되어 있으며, Session(base_url, httpx.Client) 로 세션을 생성할 때 사용됩니다.

class RequestsBackend

기반 클래스: SyncBackend

requests.Session 을 위한 백엔드 어댑터입니다.

requests 패키지가 필요합니다 (pip install requests). requests.Session 에 등록되어 있으며, Session(base_url, requests.Session) 으로 세션을 생성할 때 사용됩니다.

requests.Response 에는 닫힘 상태가 내장되어 있지 않으므로, 이 백엔드는 오직 session_close() 에서만 설정되는 내부 _closed 플래그로 이를 직접 추적합니다.