> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-trino-dialect.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

> ClickHouse Connect의 고급 사용법

# 고급 사용법

<div id="raw-api">
  ## Raw API
</div>

ClickHouse 데이터와 네이티브 또는 서드파티 데이터 타입 및 구조 간 변환이 필요하지 않은 사용 사례를 위해, ClickHouse Connect 클라이언트는 ClickHouse 연결을 직접 사용할 수 있는 메서드를 제공합니다.

<div id="client-rawquery-method">
  ### Client `raw_query` 메서드
</div>

`Client.raw_query` 메서드를 사용하면 클라이언트 connection을 통해 ClickHouse HTTP 쿼리 인터페이스를 직접 사용할 수 있습니다. 반환값은 가공되지 않은 `bytes` 객체입니다. 이 메서드는 최소한의 인터페이스로 매개변수 바인딩, 오류 처리, 재시도, 설정 관리를 제공하는 편리한 래퍼입니다.

| 매개변수                 | 유형               | 기본값    | 설명                                                                                                                |
| -------------------- | ---------------- | ------ | ----------------------------------------------------------------------------------------------------------------- |
| `query`              | str              | 필수     | 유효한 모든 ClickHouse 쿼리입니다.                                                                                          |
| `parameters`         | dict or sequence | `None` | [매개변수 인수](/ko/integrations/language-clients/python/driver-api#parameters-argument)을 참조하십시오.                       |
| `settings`           | dict             | `None` | [설정 인수](/ko/integrations/language-clients/python/driver-api#settings-argument-1)을 참조하십시오.                         |
| `fmt`                | str              | `None` | 반환되는 bytes에 사용할 ClickHouse 출력 형식입니다. 지정하지 않으면 ClickHouse는 TSV를 사용합니다.                                             |
| `use_database`       | bool             | `True` | 클라이언트에 구성된 데이터베이스를 포함합니다.                                                                                         |
| `external_data`      | `ExternalData`   | `None` | 외부 파일 또는 바이너리 데이터입니다. [외부 데이터](/ko/integrations/language-clients/python/advanced-querying#external-data)를 참조하십시오. |
| `transport_settings` | dict             | `None` | 이 요청에 추가되는 HTTP headers입니다.                                                                                       |

반환된 `bytes` 객체는 호출자가 직접 처리해야 합니다. `Client.query_arrow`는 ClickHouse `Arrow` 출력 형식을 사용하는 이 메서드의 얇은 래퍼일 뿐이라는 점에 유의하십시오.

<div id="client-rawstream-method">
  ### Client `raw_stream` 메서드
</div>

동기식 `Client.raw_stream` 메서드는 `raw_query`와 동일한 API를 사용하지만, 바이트 청크로 이루어진 `io.IOBase` 스트림을 반환합니다. 처리가 완료되면 스트림을 닫으십시오. `AsyncClient.raw_stream`은 await해야 하며, `async with` 및 `async for`와 함께 사용할 수 있는 비동기 `StreamContext`를 반환합니다.

<div id="client-rawinsert-method">
  ### Client `raw_insert` 메서드
</div>

`Client.raw_insert` 메서드를 사용하면 클라이언트 연결을 통해 `bytes` 객체 또는 `bytes` 객체 생성기를 직접 삽입할 수 있습니다. 이 메서드는 삽입 payload를 별도로 처리하지 않으므로 성능이 매우 뛰어납니다. 또한 설정과 삽입 포맷을 지정하는 옵션을 제공합니다:

| 매개변수                 | 유형                                   | 기본값      | 설명                                                                                        |
| -------------------- | ------------------------------------ | -------- | ----------------------------------------------------------------------------------------- |
| `table`              | str                                  | Required | 단순 테이블 이름 또는 데이터베이스를 포함한 정규화된 대상 테이블입니다.                                                  |
| `column_names`       | Sequence\[str]                       | `None`   | 삽입 block의 컬럼 이름입니다. `fmt`에 이름이 포함되지 않으면 필요합니다.                                            |
| `insert_block`       | str, bytes, generator, or `BinaryIO` | Required | 삽입할 데이터입니다. 문자열은 클라이언트 인코딩을 사용해 인코딩됩니다.                                                   |
| `settings`           | dict                                 | `None`   | [설정 인수](/ko/integrations/language-clients/python/driver-api#settings-argument-1)를 참조하십시오. |
| `fmt`                | str                                  | `None`   | `insert_block` payload의 ClickHouse 입력 형식입니다. 포맷을 지정하지 않으면 `네이티브`가 사용됩니다.                  |
| `compression`        | str                                  | `None`   | `"gzip"`, `"lz4"`, `"zstd"`와 같이 `insert_block`에 이미 적용된 압축 방식입니다.                          |
| `transport_settings` | dict                                 | `None`   | 이 요청에 추가되는 HTTP headers입니다.                                                               |

호출자는 `insert_block`이 지정한 포맷이며 지정한 compression method를 사용하도록 보장할 책임이 있습니다. ClickHouse Connect는 파일 업로드와 PyArrow Tables에 이러한 원시 삽입을 사용하며, parsing은 ClickHouse 서버에 위임합니다.

<div id="saving-query-results-as-files">
  ## 쿼리 결과를 파일로 저장하기
</div>

`raw_stream` 메서드를 사용하면 ClickHouse에서 로컬 파일 시스템으로 파일을 직접 스트리밍할 수 있습니다. 예를 들어, 쿼리 결과를 CSV 파일로 저장하려면 다음 코드 예시를 사용할 수 있습니다.

```python theme={null}
import clickhouse_connect

if __name__ == "__main__":
    client = clickhouse_connect.get_client()
    query = (
        "SELECT number, toString(number) AS number_as_str "
        "FROM system.numbers LIMIT 5"
    )
    stream = client.raw_stream(query=query, fmt="CSVWithNames")
    try:
        with open("output.csv", "wb") as file:
            for chunk in stream:
                file.write(chunk)
    finally:
        stream.close()
        client.close()
```

위 코드를 실행하면 다음 내용이 담긴 `output.csv` 파일이 생성됩니다:

```csv theme={null}
"number","number_as_str"
0,"0"
1,"1"
2,"2"
3,"3"
4,"4"
```

마찬가지로 [TabSeparated](/ko/reference/formats/TabSeparated/TabSeparated) 및 기타 포맷으로도 데이터를 저장할 수 있습니다. 사용 가능한 모든 포맷 옵션의 개요는 [입력 및 출력 데이터 포맷](/ko/reference/formats)에서 확인할 수 있습니다.

<div id="multithreaded-multiprocess-and-asyncevent-driven-use-cases">
  ## 멀티스레드, 멀티프로세스 및 async/이벤트 기반 사용 사례
</div>

ClickHouse Connect는 멀티스레드, 멀티프로세스, 이벤트 루프 기반/비동기 애플리케이션에서 잘 작동합니다. 모든 쿼리 및 삽입 처리는 단일 스레드에서 이루어지므로, 작업은 일반적으로 스레드 안전합니다. (일부 작업을 하위 수준에서 병렬로 처리해 단일 스레드에 따른 성능 저하를 완화하는 기능이 향후 개선 사항으로 추가될 수 있지만, 그 경우에도 스레드 안전성은 유지됩니다.)

각 쿼리 또는 삽입 실행은 각각 자체 `QueryContext` 또는 `InsertContext` 객체에 상태를 유지하므로, 이러한 도우미 객체는 스레드 안전하지 않으며 여러 처리 스트림 간에 공유해서는 안 됩니다. context 객체에 대한 추가 설명은 [QueryContexts](/ko/integrations/language-clients/python/advanced-querying#querycontexts) 및 [InsertContexts](/ko/integrations/language-clients/python/advanced-inserting#insertcontexts) 섹션을 참조하십시오.

또한 애플리케이션에서 2개 이상의 쿼리 및/또는 삽입이 동시에 "진행 중"인 경우에는 추가로 고려해야 할 사항이 2가지 있습니다. 첫 번째는 쿼리/삽입에 연결된 ClickHouse "세션"이고, 두 번째는 ClickHouse Connect Client 인스턴스에서 사용하는 HTTP 연결 풀입니다.

<div id="asyncclient">
  ## AsyncClient
</div>

ClickHouse Connect는 asyncio 애플리케이션용 네이티브 aiohttp 기반 클라이언트를 제공합니다. 사용하기 전에 선택적 종속성을 설치하십시오:

```bash theme={null}
pip install "clickhouse-connect[async]"
```

`get_async_client`를 await하여 클라이언트를 생성하고 초기화하십시오. `query`, `command`, `insert`와 같은 I/O 메서드는 코루틴입니다:

```python theme={null}
import asyncio

import clickhouse_connect


async def main():
    async with await clickhouse_connect.get_async_client() as client:
        result = await client.query(
            "SELECT name FROM system.databases ORDER BY name LIMIT 1"
        )
        print(result.result_rows)


asyncio.run(main())
```

비동기 클라이언트는 동기 클라이언트와 동일한 쿼리, 삽입, raw, Arrow, 스트리밍 인터페이스를 따릅니다. 네트워크 I/O에는 aiohttp를 사용합니다. CPU 바운드인 네이티브 포맷 파싱은 이벤트 루프를 차단하지 않도록 실행기에서 처리될 수 있습니다.

반환된 컨텍스트에 들어가기 전에 비동기 스트리밍 메서드를 await해야 합니다:

```python theme={null}
async with await client.query_rows_stream(
    "SELECT number FROM numbers(100000)"
) as stream:
    async for row in stream:
        process(row)
```

동기 팩터리와 달리 `get_async_client`는 여러 코루틴이 동시에 하나의 클라이언트를 공유할 수 있도록 기본적으로 자동 세션 ID를 비활성화합니다. 세션 상태가 필요하고 해당 세션에서 동시 쿼리를 피할 때만 명시적인 `session_id` 또는 `autogenerate_session_id=True`를 전달하십시오.

<div id="managing-clickhouse-session-ids">
  ## ClickHouse 세션 ID 관리
</div>

각 ClickHouse 쿼리는 ClickHouse "세션" 컨텍스트에서 실행됩니다. 현재 세션은 두 가지 용도로 사용됩니다.

* 여러 쿼리에 특정 ClickHouse 설정을 연결하는 데 사용됩니다([user settings](/ko/reference/settings/session-settings) 참조). 사용자 세션 범위의 설정을 변경하려면 ClickHouse `SET` 명령을 사용합니다.
* [임시 테이블](/ko/reference/statements/create/table#temporary-tables)을 추적하는 데 사용됩니다.

기본적으로 동기 `Client`는 생성된 세션 ID를 사용합니다. 따라서 `SET` SQL 문과 임시 테이블은 해당 클라이언트의 요청 간에 유지됩니다. async 팩토리는 기본적으로 세션 ID를 생성하지 않습니다. ClickHouse는 동일한 세션에서 동시 쿼리를 허용하지 않으며, 이를 시도하면 클라이언트에서 `ProgrammingError`가 발생하므로 다음 패턴 중 하나를 사용하세요.

1. 세션 격리가 필요한 각 스레드/프로세스/이벤트 핸들러마다 별도의 `Client` 인스턴스를 생성합니다. 이렇게 하면 클라이언트별 세션 상태(임시 테이블 및 `SET` 값)가 유지됩니다.
2. 공유 세션 상태가 필요하지 않다면, `query`, `command`, 또는 `insert`를 호출할 때 `settings` 인수를 통해 각 쿼리에 고유한 `session_id`를 사용합니다.
3. 공유 클라이언트에서 세션을 비활성화하려면 클라이언트를 생성하기 전에 `autogenerate_session_id=False`로 설정합니다(또는 이를 `get_client`에 직접 전달합니다).

```python theme={null}
import clickhouse_connect
from clickhouse_connect import common

common.set_setting("autogenerate_session_id", False)
client = clickhouse_connect.get_client(
    host="somehost.com",
    username="dbuser",
    password="password",
)
```

또는 `autogenerate_session_id=False`를 `get_client(...)`에 직접 전달할 수 있습니다.

이 경우 ClickHouse Connect는 `session_id`를 전송하지 않으며, server는 개별 요청을 동일한 세션에 속한 것으로 처리하지 않습니다. 임시 테이블과 세션 수준 설정은 요청 간에 유지되지 않습니다.

<div id="customizing-the-http-connection-pool">
  ## HTTP 연결 풀 사용자 지정
</div>

ClickHouse Connect는 서버와의 기본 HTTP 연결을 처리하기 위해 `urllib3` 연결 풀을 사용합니다. 기본적으로 모든 클라이언트 인스턴스는 동일한 연결 풀을 공유하며, 이는 대부분의 사용 사례에 충분합니다. 이 기본 풀은 애플리케이션에서 사용하는 각 ClickHouse 서버에 대해 최대 8개의 HTTP Keep Alive 연결을 유지합니다.

대규모 멀티스레드 애플리케이션에서는 별도의 연결 풀이 더 적합할 수 있습니다. 사용자 지정 연결 풀은 기본 `clickhouse_connect.get_client` 함수에 `pool_mgr` 키워드 인수로 전달할 수 있습니다:

```python theme={null}
import clickhouse_connect
from clickhouse_connect.driver import httputil

big_pool_mgr = httputil.get_pool_manager(maxsize=16, num_pools=12)

client1 = clickhouse_connect.get_client(pool_mgr=big_pool_mgr)
client2 = clickhouse_connect.get_client(pool_mgr=big_pool_mgr)
```

클라이언트는 풀 관리자를 공유할 수도 있고, 각 클라이언트가 별도의 관리자를 사용할 수도 있습니다. 자세한 내용은 [`urllib3` PoolManager 문서](https://urllib3.readthedocs.io/en/stable/advanced-usage.html#customizing-pool-behavior)를 참조하십시오.

async 클라이언트는 `urllib3` 대신 aiohttp 풀을 사용합니다. `get_async_client`의 `connector_limit`, `connector_limit_per_host`, `keepalive_timeout`을 통해 이를 구성하십시오. `await async_client.close_connections()`를 호출하면 진행 중인 요청을 중단하지 않고 풀이 순환됩니다.
