Skip to main content
ClickHouse에 연결하기 위한 공식 JS 클라이언트입니다. 이 클라이언트는 TypeScript로 작성되었으며, 클라이언트의 공개 API에 대한 타입 정의를 제공합니다. 의존성이 전혀 없으며, 최고 성능을 위해 최적화되어 있고, 다양한 ClickHouse 버전과 구성(온프레미스 single node, 온프레미스 클러스터, ClickHouse Cloud)에서 테스트되었습니다. 서로 다른 환경에 맞는 두 가지 버전의 클라이언트를 사용할 수 있습니다:
  • @clickhouse/client - Node.js 전용
  • @clickhouse/client-web - 브라우저(Chrome/Firefox), Cloudflare workers
TypeScript를 사용하는 경우, version 4.5 이상인지 확인하십시오. 이 버전부터 inline import and export syntax를 사용할 수 있습니다. 클라이언트 소스 코드는 ClickHouse-JS GitHub 리포지토리에서 확인할 수 있습니다.
AI agent skillsJS 클라이언트에는 코딩 에이전트가 클라이언트를 사용하는 데 도움이 되는 AI agent 스킬이 함께 제공됩니다. 다음과 같이 설치하십시오:

환경 요구 사항 (node.js)

클라이언트를 실행하려면 환경에서 Node.js를 사용할 수 있어야 합니다. 이 클라이언트는 현재 유지보수되는 모든 Node.js 릴리스를 지원합니다. Node.js 버전이 지원 종료에 가까워지면 더 이상 최신 버전이 아니고 보안상 안전하지 않은 것으로 간주되므로, 클라이언트는 해당 버전에 대한 지원을 중단합니다. 현재 Node.js 버전 지원 범위는 다음과 같습니다.

환경 요구 사항 (웹)

클라이언트의 웹 버전은 최신 Chrome/Firefox 브라우저에서 공식적으로 테스트되었으며, React/Vue/Angular 애플리케이션이나 Cloudflare workers에서 의존성으로 포함해 사용할 수 있습니다.

설치

최신 안정 버전의 Node.js 클라이언트를 설치하려면 다음을 실행하십시오:
웹 버전 설치:

ClickHouse와의 호환성

클라이언트는 이전 버전에서도 작동할 가능성이 높지만, 이는 최선 노력 수준의 지원으로 보장되지는 않습니다. ClickHouse 버전이 23.3보다 낮다면 ClickHouse security policy를 참조하고 업그레이드를 고려하십시오.

예시

클라이언트 리포지토리의 예시에서는 클라이언트 사용과 관련된 다양한 시나리오를 다룹니다. 개요는 예시 README에서 확인할 수 있습니다. 예시 또는 아래 문서에서 명확하지 않거나 누락된 내용이 있으면 언제든지 문의해 주세요.

클라이언트 API

별도로 명시하지 않는 한, 대부분의 예시는 클라이언트의 Node.js 버전과 web version 모두에서 호환됩니다.

클라이언트 인스턴스 만들기

createClient 팩터리를 사용해 필요한 만큼 클라이언트 인스턴스를 만들 수 있습니다.
사용 중인 환경에서 ESM 모듈을 지원하지 않으면, 대신 CJS 구문을 사용할 수 있습니다:
클라이언트 인스턴스는 생성 시 사전 구성할 수 있습니다.

구성

클라이언트 인스턴스를 생성할 때 다음 연결 설정을 조정할 수 있습니다:

Node.js 전용 구성 매개변수

URL 구성

URL 구성은 항상 하드코딩된 값을 덮어쓰며, 이 경우 경고가 로그에 기록됩니다.
대부분의 클라이언트 인스턴스 매개변수는 URL로 구성할 수 있습니다. URL 형식은 http[s]://[username:password@]hostname:port[/database][?param1=value1&param2=value2]입니다. 일부 예외를 제외하면, 대부분의 매개변수 이름은 구성 옵션 인터페이스에서의 경로를 반영합니다. 다음 매개변수를 지원합니다:
  • (1) 불리언의 유효한 값은 true/1false/0입니다.
  • (2) clickhouse_setting_ 또는 ch_ 접두사가 붙은 모든 매개변수는 이 접두사가 제거된 뒤, 나머지 부분이 클라이언트의 clickhouse_settings에 추가됩니다. 예를 들어 ?ch_async_insert=1&ch_wait_for_async_insert=1는 다음과 같습니다:
참고: URL에서는 clickhouse_settings의 Boolean 값을 1/0으로 전달해야 합니다.
  • (3) http_header 구성에도 (2)와 비슷하게 적용됩니다. 예를 들어 ?http_header_x-clickhouse-auth=foobar는 다음과 같습니다:

연결

연결 정보를 준비하십시오

HTTP(S)로 ClickHouse에 연결하려면 다음 정보가 필요합니다. ClickHouse Cloud 서비스의 연결 정보는 ClickHouse Cloud 콘솔에서 확인할 수 있습니다. 서비스를 선택한 다음 Connect를 클릭하십시오.
ClickHouse Cloud 서비스 연결 버튼
HTTPS를 선택하십시오. 연결 정보가 예시 curl 명령으로 표시됩니다.
ClickHouse Cloud HTTPS 연결 정보
자가 관리형 ClickHouse를 사용하는 경우 연결 정보는 ClickHouse 관리자가 설정합니다.

연결 개요

이 클라이언트는 HTTP 또는 HTTPS 프로토콜을 통한 연결을 지원합니다. RowBinary 지원도 예정대로 진행 중입니다. 자세한 내용은 관련 issue를 참조하십시오. 다음 예시는 ClickHouse Cloud에 연결을 설정하는 방법을 보여줍니다. url(프로토콜 및 포트 포함)과 password 값은 환경 변수로 지정되어 있으며, default 사용자를 사용한다고 가정합니다. 예시: 구성에 환경 변수를 사용하여 Node.js Client 인스턴스를 생성합니다.
클라이언트 리포지토리에는 환경 변수를 사용하는 여러 예시가 포함되어 있으며, 예를 들어 ClickHouse Cloud에서 테이블을 생성하는 예시, async 삽입을 사용하는 예시, 그 밖에도 많은 예시가 있습니다.

연결 풀 (Node.js 전용)

모든 요청마다 연결을 설정하는 오버헤드를 피하기 위해 클라이언트는 Keep-Alive 메커니즘을 활용하여 재사용 가능한 ClickHouse 연결 풀을 생성합니다. 기본적으로 Keep-Alive는 활성화되어 있으며 연결 풀 크기는 10으로 설정되어 있지만, max_open_connections 구성 옵션으로 변경할 수 있습니다. 사용자가 max_open_connections: 1을 설정하지 않는 한, 풀에 있는 동일한 연결이 이후 쿼리에도 사용된다고 보장할 수는 없습니다. 이런 설정이 필요한 경우는 드물지만, 임시 테이블을 사용하는 경우에는 필요할 수 있습니다. 관련 항목: Keep-Alive 구성.

쿼리 ID

쿼리 또는 SQL 문(command, exec, insert, select)을 전송하는 모든 메서드는 결과에 query_id를 제공합니다. 이 고유 식별자는 클라이언트가 각 쿼리마다 할당하며, 서버 구성에서 활성화되어 있다면 system.query_log에서 데이터를 조회하거나, 장시간 실행되는 쿼리를 취소하는 데 유용할 수 있습니다(예시 참조). 필요한 경우 사용자가 command/query/exec/insert 메서드의 파라미터에서 query_id를 재정의할 수 있습니다.
query_id 매개변수를 재정의하는 경우, 호출마다 고유성이 보장되도록 해야 합니다. 임의의 UUID를 사용하는 것이 좋습니다.

모든 클라이언트 메서드의 기본 매개변수

모든 클라이언트 메서드(query/command/insert/exec)에 공통으로 적용할 수 있는 매개변수가 몇 가지 있습니다.

쿌리 메서드

응답이 있는 대부분의 SQL 문(예: SELECT)에 사용하며, CREATE TABLE과 같은 DDL을 전송할 때도 사용합니다. 이 메서드는 await해야 하며, 반환된 결과 집합는 애플리케이션에서 소비하는 것을 전제로 합니다.
데이터 삽입에는 전용 메서드인 insert를 사용하고, DDL에는 command를 사용합니다.
관련 항목: 모든 클라이언트 메서드의 기본 매개변수.
query에 FORMAT 절을 지정하지 말고, 대신 format 매개변수를 사용하세요.

결과 집합 및 행 추상화

ResultSet은 애플리케이션에서 데이터를 처리할 때 사용할 수 있는 여러 편의 메서드를 제공합니다. Node.js ResultSet 구현은 내부적으로 Stream.Readable을 사용하며, 웹 버전은 Web API ReadableStream을 사용합니다. ResultSet에서 text 또는 json 메서드를 호출해 ResultSet을 소비하고, 쿼리가 반환한 전체 행 집합을 메모리에 로드할 수 있습니다. ResultSet은 응답 스트림을 열린 상태로 유지하므로 그동안 기본 연결이 계속 사용 중 상태로 남습니다. 따라서 가능한 한 빨리 ResultSet 소비를 시작해야 합니다. 클라이언트는 애플리케이션의 과도한 메모리 사용량을 방지하기 위해 들어오는 데이터를 버퍼링하지 않습니다. 또는 한 번에 메모리에 담기 어려울 정도로 크다면 stream 메서드를 호출해 스트리밍 모드로 데이터를 처리할 수 있습니다. 이 경우 각 응답 청크는 상대적으로 작은 행 배열로 변환되며(이 배열의 크기는 클라이언트가 server로부터 받는 특정 청크의 크기와 개별 행의 크기에 따라 달라질 수 있습니다), 청크별로 하나씩 처리됩니다. 환경에 따라 스트리밍에 가장 적합한 포맷을 결정하려면 지원되는 데이터 포맷 목록을 참조하십시오. 예를 들어 JSON 객체를 스트리밍하려는 경우 JSONEachRow를 선택하면 각 행이 JS 객체로 파싱됩니다. 또는 더 압축된 JSONCompactColumns 포맷을 선택하면 각 행이 값의 간결한 배열이 됩니다. 관련 항목: 스트리밍 파일.
ResultSet 또는 해당 스트림이 끝까지 완전히 소비되지 않으면, 비활성 상태가 request_timeout 기간 동안 지속된 후 폐기됩니다.
예시: (Node.js/Web) 결과 데이터셋을 JSONEachRow 포맷으로 반환하는 쿼리로, 전체 스트림을 읽어 JS 객체로 파싱합니다. 소스 코드.
예시: (Node.js 전용) 기존 on('data') 방식을 사용해 JSONEachRow 포맷의 스트리밍 쿼리 결과를 처리합니다. 이는 for await const 구문으로도 대체해 사용할 수 있습니다. 소스 코드.
예시: (Node.js only) 기존 on('data') 방식을 사용해 CSV 포맷의 스트리밍 쿼리 결과를 처리합니다. 이는 for await const 구문과 서로 대체하여 사용할 수 있습니다. 소스 코드
예시: (Node.js 전용) for await const 구문을 사용하여 JSONEachRow 포맷의 JS 객체 형태로 스트리밍 쿼리 결과를 소비하는 방식입니다. 이는 기존의 on('data') 방식과도 서로 바꾸어 사용할 수 있습니다. 소스 코드.
for await const 구문은 on('data') 방식보다 코드량이 조금 적지만, 성능에 부정적인 영향을 줄 수 있습니다. 자세한 내용은 Node.js 리포지토리의 해당 이슈를 참조하십시오.
예시: (웹 전용) 객체 ReadableStream을 순회합니다.

삽입 메서드

데이터를 삽입할 때 사용하는 주요 메서드입니다.
반환 유형은 최소한으로 구성되어 있습니다. 서버에서 반환되는 데이터는 없을 것으로 예상하며 응답 스트림을 즉시 비우기 때문입니다. 빈 배열이 삽입 메서드에 제공되면 삽입 statement는 서버로 전송되지 않습니다. 대신 메서드는 즉시 { query_id: '...', executed: false }로 확인됩니다. 이 경우 메서드 파라미터에 query_id가 제공되지 않았다면 결과에서는 빈 문자열이 됩니다. 클라이언트가 생성한 임의의 UUID를 반환하면 혼동을 줄 수 있기 때문입니다. 해당 query_id를 가진 쿼리는 system.query_log 테이블에 존재하지 않기 때문입니다. 삽입 statement가 서버로 전송되었다면 executed flag는 true가 됩니다.

Node.js에서의 삽입 메서드와 스트리밍

insert 메서드에 지정한 data format에 따라 Stream.Readable 또는 일반 Array<T>와 함께 사용할 수 있습니다. file streaming에 대한 이 섹션도 참고하십시오. 삽입 메서드는 일반적으로 await하여 사용합니다. 하지만 입력 스트림을 지정해 두고, 스트림이 완료된 뒤에 나중에 insert 작업을 await할 수도 있습니다(이 경우 insert promise도 함께 resolve됩니다). 이는 이벤트 리스너와 비슷한 시나리오에서 유용할 수 있지만, 클라이언트 측 오류 처리는 다양한 예외 상황 때문에 간단하지 않을 수 있습니다. 대신 async inserts 사용을 고려하십시오. 사용 방법은 this example에서 확인할 수 있습니다.
이 메서드로 표현하기 어려운 사용자 지정 INSERT 문이 있다면, command method 사용을 고려하십시오.사용 방법은 INSERT INTO … VALUES 또는 INSERT INTO … SELECT 예시에서 확인할 수 있습니다.
관련 항목: 모든 클라이언트 메서드의 기본 매개변수.
abort_signal로 취소된 요청이라고 해서 데이터 삽입이 이루어지지 않았다고 보장할 수는 없습니다. 취소되기 전에 서버가 스트리밍된 데이터의 일부를 이미 수신했을 수 있기 때문입니다.
예시: (Node.js/Web) 배열 형태의 값을 삽입합니다. 소스 코드.
예시: (Node.js 전용) CSV 파일 스트림을 삽입합니다. 소스 코드. 관련 항목: 파일 스트리밍.
예시: 삽입 구문에서 특정 컬럼을 제외합니다. 다음과 같은 테이블 정의가 있다고 가정합니다:
특정 컬럼에만 삽입합니다:
특정 컬럼 제외하기:
자세한 내용은 소스 코드를 참고하십시오. 예시: 클라이언트 인스턴스에 지정한 데이터베이스와 다른 데이터베이스에 삽입하는 예시입니다. 소스 코드.

웹 버전 제한 사항

현재 @clickhouse/client-web에서 삽입은 Array<T>JSON* 포맷에서만 지원됩니다. 브라우저 호환성이 충분하지 않기 때문에 웹 버전에서는 아직 스트림 삽입이 지원되지 않습니다. 따라서 웹 버전용 InsertParams 인터페이스는 Node.js 버전과 약간 다르며, valuesReadonlyArray<T> 유형으로만 제한됩니다:
이는 향후 변경될 수 있는 사항입니다. 관련 항목: 모든 클라이언트 메서드의 기본 매개변수.

command 메서드

출력이 없는 SQL 문, 포맷 절을 적용할 수 없는 경우, 또는 응답 자체가 필요하지 않은 경우에 사용할 수 있습니다. 이러한 SQL 문의 예시로는 CREATE TABLE 또는 ALTER TABLE이 있습니다. 반드시 await해야 합니다. 응답 스트림은 즉시 폐기되며, 이에 따라 내부 소켓이 해제됩니다.
관련 항목: 모든 클라이언트 메서드의 기본 매개변수. 예시: (Node.js/Web) ClickHouse Cloud에서 테이블을 생성합니다. 소스 코드.
예시: (Node.js/Web) 자체 호스팅된 ClickHouse 인스턴스에서 테이블을 생성합니다. 소스 코드.
예시: (Node.js/Web) INSERT FROM SELECT
abort_signal로 취소된 요청이라도 해당 statement가 server에서 실행되지 않았다고 단정할 수는 없습니다.

Exec 메서드

query/insert에 맞지 않는 사용자 정의 쿼리가 있고 결과를 받아야 한다면 command 대신 exec를 사용할 수 있습니다. exec는 애플리케이션 측에서 반드시 소비하거나 폐기해야 하는 readable stream을 반환합니다.
관련 항목: 모든 클라이언트 메서드의 기본 매개변수. Stream의 반환 유형은 Node.js 버전과 Web 버전에서 다릅니다. Node.js:
웹:

Ping

연결 상태를 확인하는 데 사용되는 ping 메서드는 서버에 연결할 수 있으면 true를 반환합니다. 서버에 연결할 수 없는 경우 결과에는 원인이 된 오류도 함께 포함됩니다.
애플리케이션이 시작될 때 서버를 사용할 수 있는지 확인하는 데 Ping이 유용할 수 있습니다. 특히 ClickHouse Cloud에서는 인스턴스가 유휴 상태였다가 ping 후에 다시 활성화될 수 있으므로, 이런 경우에는 중간에 지연 시간을 두고 몇 차례 재시도하는 것이 좋습니다. 기본적으로 Node.js 버전은 /ping 엔드포인트를 사용하고, 웹 버전은 /ping 엔드포인트가 CORS를 지원하지 않기 때문에 비슷한 결과를 얻기 위해 간단한 SELECT 1 쿼리를 사용합니다. 예시: (Node.js/Web) ClickHouse 서버 인스턴스에 보내는 간단한 ping입니다. 참고: 웹 버전에서는 포착되는 오류가 다릅니다. 소스 코드.
예시: ping 메서드를 호출할 때 자격 증명도 함께 확인하거나 query_id와 같은 추가 파라미터를 지정하려면, 다음과 같이 사용할 수 있습니다:
Ping 메서드에서는 표준 query 메서드의 매개변수 대부분을 사용할 수 있습니다. 자세한 내용은 PingParamsWithSelectQuery 타입 정의를 참조하십시오.

닫기 (Node.js 전용)

열려 있는 모든 연결을 닫고 리소스를 해제합니다. 웹 버전에서는 no-op입니다.

파일 스트리밍 (Node.js 전용)

클라이언트 리포지토리에는 널리 사용되는 데이터 포맷(NDJSON, CSV, Parquet)에 대한 여러 파일 스트리밍 예시가 있습니다. 다른 포맷의 파일로 스트리밍하는 방법도 Parquet와 비슷합니다. 차이점은 query 호출에 사용하는 포맷(JSONEachRow, CSV 등)과 출력 파일 이름뿐입니다.

지원되는 데이터 포맷

클라이언트는 JSON 또는 텍스트 데이터 포맷을 처리합니다. format을 JSON 계열 포맷(JSONEachRow, JSONCompactEachRow 등) 중 하나로 지정하면, 클라이언트는 wire를 통한 통신 중 데이터를 serialize 및 deserialize합니다. “raw” 텍스트 포맷(CSV, TabSeparated, CustomSeparated 계열)으로 제공된 데이터는 추가 변환 없이 wire를 통해 전송됩니다.
일반적인 포맷으로서의 JSON과 ClickHouse JSON format은 혼동될 수 있습니다.클라이언트는 JSONEachRow와 같은 포맷에서 JSON 객체 스트리밍을 지원합니다(다른 스트리밍 친화적인 포맷은 표 개요를 참조하고, select_streaming_ client 리포지토리의 예시도 함께 참조하십시오).다만 ClickHouse JSON과 일부 다른 포맷은 응답에서 단일 객체로 표현되므로 클라이언트에서 스트리밍할 수 없습니다.
Parquet의 경우, select의 주요 사용 사례는 결과 스트림을 파일로 저장하는 것일 가능성이 높습니다. 클라이언트 리포지토리의 예시를 참조하십시오. JSONEachRowWithProgress는 스트림에서 진행 상황 보고를 지원하는 출력 전용 포맷입니다. 자세한 내용은 이 예시를 참조하십시오. ClickHouse의 전체 입력 및 출력 형식 목록은 여기에서 확인할 수 있습니다.

지원되는 ClickHouse 데이터 타입

대응되는 JS 타입은 모든 값을 문자열로 나타내는 포맷(예: JSONStringEachRow)을 제외한 모든 JSON* 포맷에 적용됩니다.
지원되는 ClickHouse 포맷의 전체 목록은 여기에서 확인할 수 있습니다. 관련 항목:

Date/Date32 타입 관련 주의사항

클라이언트가 값을 삽입할 때 추가적인 타입 변환을 수행하지 않으므로, Date/Date32 타입 컬럼에는 문자열만 삽입할 수 있습니다. 예시: Date 타입 값을 삽입하는 예시입니다. 소스 코드
하지만 DateTime 또는 DateTime64 컬럼을 사용하는 경우에는 문자열과 JS Date 객체를 모두 사용할 수 있습니다. JS Date 객체는 date_time_input_formatbest_effort로 설정하면 insert에 그대로 전달할 수 있습니다. 자세한 내용은 이 예시를 참조하십시오.

Decimal* 타입 유의사항

JSON* 계열 포맷을 사용해 Decimal을 삽입할 수 있습니다. 다음과 같이 정의된 테이블이 있다고 가정합니다.
문자열 형식으로 정밀도 손실 없이 값을 삽입할 수 있습니다:
하지만 JSON* 포맷으로 데이터를 쿼리할 때 ClickHouse는 기본적으로 Decimal을 숫자로 반환하므로 정밀도가 손실될 수 있습니다. 이를 방지하려면 쿼리에서 Decimal을 문자열로 CAST할 수 있습니다:
자세한 내용은 이 예시를 확인하십시오.

정수 타입: Int64, Int128, Int256, UInt64, UInt128, UInt256

server는 이를 숫자로 받을 수 있지만, 이러한 타입의 최댓값이 Number.MAX_SAFE_INTEGER보다 크기 때문에 정수 오버플로우를 방지하기 위해 JSON* 계열 출력 형식에서는 문자열로 반환됩니다. 하지만 이 동작은 output_format_json_quote_64bit_integers 설정 으로 변경할 수 있습니다. 예시: 64비트 숫자에 대한 JSON 출력 형식을 조정합니다.

ClickHouse 설정

클라이언트는 settings 메커니즘을 통해 ClickHouse의 동작을 조정할 수 있습니다. 설정은 클라이언트 인스턴스 수준에서 지정할 수 있으며, 이렇게 하면 ClickHouse로 전송되는 모든 요청에 적용됩니다:
또는 설정을 요청 수준에서 구성할 수 있습니다:
지원되는 모든 ClickHouse 설정이 포함된 타입 선언 파일은 여기에서 확인할 수 있습니다.
쿼리를 실행하는 사용자에게 해당 설정을 변경할 수 있는 충분한 권한이 있는지 확인하십시오.

심화 주제

매개변수가 있는 쿼리

매개변수가 있는 쿼리를 만들고 클라이언트 애플리케이션에서 해당 매개변수에 값을 전달할 수 있습니다. 이렇게 하면 클라이언트 측에서 특정 동적 값으로 쿼리를 포맷할 필요가 없습니다. 평소처럼 쿼리를 작성한 다음, 앱 매개변수에서 쿼리로 전달할 값을 중괄호로 묶어 다음 형식으로 넣습니다:
여기서:
  • name — 플레이스홀더 식별자입니다.
  • data_type - 앱 매개변수 값의 데이터 타입입니다.
예시:: 매개변수를 사용하는 쿼리입니다. 소스 코드 .
자세한 내용은 https://clickhouse.com/docs/interfaces/cli#cli-queries-with-parameters-syntax를 참조하십시오.

압축

참고: 요청 압축은 현재 Web 버전에서 사용할 수 없습니다. 응답 압축은 정상적으로 작동합니다. Node.js 버전에서는 둘 다 지원합니다. wire를 통해 대규모 데이터셋을 처리하는 데이터 애플리케이션은 압축을 활성화하면 이점을 얻을 수 있습니다. 현재는 zlib을 사용하는 GZIP만 지원됩니다.
구성 매개변수는 다음과 같습니다.
  • response: true는 ClickHouse 서버가 압축된 응답 본문을 반환하도록 합니다. 기본값: response: false
  • request: true는 클라이언트 요청 본문의 압축을 활성화합니다. 기본값: request: false

로깅 (Node.js 전용)

로깅은 실험적 기능이며, 향후 변경될 수 있습니다.
기본 로거 구현은 console.debug/info 메서드를 통해 로그 레코드를 stdout에 출력하고, console.warn/error 메서드를 통해 stderr에 출력합니다. LoggerClass를 제공해 로깅 로직을 사용자 지정할 수 있으며, level 매개변수로 원하는 로그 레벨을 선택할 수 있습니다(기본값은 WARN입니다):
현재 클라이언트는 다음 이벤트를 로그로 남깁니다:
  • TRACE - Keep-Alive 소켓의 수명 주기에 대한 저수준 정보
  • DEBUG - 응답 정보(authorization headers 및 host 정보 제외)
  • INFO - 대부분 사용되지 않으며, 클라이언트가 초기화될 때 현재 로그 레벨을 출력합니다
  • WARN - 치명적이지 않은 오류입니다. 실패한 ping 요청은 경고로 기록되는데, 반환된 결과에 기본 오류가 포함되기 때문입니다
  • ERROR - 실패한 요청과 같은 query/insert/exec/command 메서드의 치명적 오류
기본 로거 구현은 여기에서 확인할 수 있습니다.

TLS 인증서 (Node.js 전용)

Node.js 클라이언트는 선택적으로 basic(인증 기관(Certificate Authority)만 사용하는) 및 mutual(인증 기관(Certificate Authority)과 클라이언트 인증서를 사용하는) TLS를 모두 지원합니다. 인증서가 certs 폴더에 있고 CA 파일 이름이 CA.pem이라고 가정할 때의 basic TLS 구성 예시는 다음과 같습니다:
클라이언트 인증서를 사용하는 상호 인증 TLS 구성 예시:
리포지토리에서 기본상호 TLS에 대한 전체 예시를 확인하세요.

Keep-alive 설정 (Node.js 전용)

클라이언트는 기본적으로 하위 HTTP agent에서 Keep-Alive를 활성화합니다. 즉, 연결된 소켓은 이후 request에 재사용되며 Connection: keep-alive header가 전송됩니다. 유휴 상태인 소켓은 기본적으로 2500밀리초 동안 연결 풀에 유지됩니다(이 옵션 조정에 관한 참고 사항 참조). keep_alive.idle_socket_ttl 값은 server/LB 구성보다 상당히 낮게 설정해야 합니다. 주된 이유는 HTTP/1.1에서는 server가 클라이언트에 알리지 않고 소켓을 닫을 수 있으므로, server 또는 load balancer가 클라이언트보다 먼저 연결을 닫으면 클라이언트가 닫힌 소켓을 재사용하려고 시도할 수 있고, 그 결과 socket hang up 오류가 발생할 수 있기 때문입니다. keep_alive.idle_socket_ttl을 수정하는 경우, 이 값은 server/LB의 Keep-Alive 구성과 항상 맞춰 두어야 하며, server가 열린 연결을 먼저 닫지 않도록 반드시 그보다 항상 낮아야 합니다.

idle_socket_ttl 조정

클라이언트는 keep_alive.idle_socket_ttl을 2500밀리초로 설정합니다. 이는 가장 안전한 기본값으로 볼 수 있기 때문입니다. 서버 측 keep_alive_timeoutconfig.xml을 수정하지 않아도 ClickHouse 23.11 이전 버전에서는 3초까지 낮게 설정될 수 있습니다.
성능에 만족하고 있고 문제가 발생하지 않는다면 keep_alive.idle_socket_ttl 설정값을 늘리지 않는 것이 좋습니다. 값을 늘리면 “Socket hang-up” 오류가 발생할 수 있기 때문입니다. 또한 애플리케이션이 많은 쿼리를 보내고 쿼리 사이의 다운타임이 길지 않다면, 소켓이 충분히 오래 유휴 상태로 머물지 않으므로 기본값으로도 충분하며 클라이언트는 해당 소켓을 풀에 유지합니다.
다음 명령을 실행하면 서버 응답 헤더에서 올바른 Keep-Alive timeout 값을 확인할 수 있습니다.
응답의 ConnectionKeep-Alive 헤더 값을 확인하십시오. 예시:
이 경우 keep_alive_timeout은 10초이므로, 기본값보다 조금 더 오래 유휴 소켓을 열린 상태로 유지하려면 keep_alive.idle_socket_ttl을 9000 또는 9500밀리초로 높여볼 수 있습니다. 서버가 클라이언트보다 먼저 연결을 닫고 있음을 의미하는 “Socket hang-up” 오류가 발생하는지 주의 깊게 확인하고, 오류가 사라질 때까지 값을 낮추십시오.

문제 해결

최신 버전의 클라이언트를 사용 중인데도 socket hang up 오류가 발생한다면, 다음 방법으로 문제를 해결할 수 있습니다.
  • 최소 WARN 로그 레벨(기본값)로 로그를 활성화하십시오. 그러면 application code에 소비되지 않았거나 처리되지 않은 채 남아 있는 스트림이 있는지 확인할 수 있습니다. 이러한 경우 전송 계층에서 WARN 수준으로 로그를 남기며, 이 상태가 서버에서 소켓을 닫는 원인이 될 수 있습니다. 로깅은 다음과 같이 클라이언트 구성에서 활성화할 수 있습니다.
  • 원하는 구성이 올바른 클라이언트 인스턴스에 적용되었는지 확인하십시오. 애플리케이션에 클라이언트 인스턴스가 여러 개 있다면, 쿼리에 사용하는 인스턴스에 올바른 keep_alive.idle_socket_ttl 값이 설정되어 있는지 다시 확인하십시오.
  • 클라이언트 구성에서 keep_alive.idle_socket_ttl 설정값을 500밀리초 줄이십시오. 특정 상황에서는, 예를 들어 클라이언트와 서버 사이의 네트워크 지연 시간이 높은 경우, 서버가 곧 닫으려는 소켓을 송신 요청이 할당받는 상황을 피하는 데 도움이 될 수 있습니다.
  • 이 오류가 데이터 입출력이 없는 장시간 실행 쿼리 중 발생한다면(예: 장시간 실행되는 INSERT FROM SELECT), 로드 밸런서(load balancer) 또는 다른 네트워크 구성 요소가 장시간 유지되는 연결이나 오래 실행되는 요청을 닫고 있기 때문일 수 있습니다. 다음 ClickHouse 설정을 조합해 사용하면, 장시간 실행 쿼리 중에도 일부 데이터가 들어오도록 강제해 볼 수 있습니다.
    다만 최근 Node.js 버전에서는 수신한 헤더의 총 크기가 16KB로 제한된다는 점을 유의하십시오. 일정 수 이상의 progress 헤더를 받으면(테스트에서는 약 70~80개), 예외가 발생합니다. 전송 중 대기 시간을 완전히 피하는 전혀 다른 접근 방식도 사용할 수 있습니다. 연결이 끊겨도 mutation이 취소되지 않는 HTTP 인터페이스 “기능”을 활용하는 방식입니다. 자세한 내용은 이 예시(2부)를 참조하십시오.
  • Keep-Alive 기능은 완전히 비활성화할 수도 있습니다. 이 경우 클라이언트는 모든 요청에 Connection: close 헤더도 추가하며, 기반 HTTP 에이전트는 연결을 재사용하지 않습니다. 유휴 소켓이 없으므로 keep_alive.idle_socket_ttl 설정은 무시됩니다. 이 방식은 모든 요청마다 새 연결을 설정하므로 추가 오버헤드가 발생합니다.
  • curl을 사용한 간단한 명령줄 테스트를 동일한 ClickHouse 인스턴스와 동일한 네트워크 경로(즉, 같은 머신 또는 네트워크 세그먼트, 예: Kubernetes pod)에서 실행하여, Node.js 자체를 포함한 나머지 네트워크 스택의 잠재적 문제를 배제해 보십시오.
    몇 분 동안 반복 실행해 보는 것이 좋습니다. curl에서도 비슷한 오류가 보인다면, 문제는 클라이언트 구성이 아니라 네트워크 스택이나 서버 구성과 관련되어 있을 가능성이 높습니다.
  • 순수 Node.js 기능으로 연결을 테스트하려면, 내장 fetch API를 사용해 ClickHouse 서버에 간단한 HTTP 요청을 보내 볼 수 있습니다.
  • 경우에 따라 애플리케이션 코드나 프레임워크 어댑터가 실제 쿼리 실행 전에 선행 ping()을 추가할 수 있습니다. 이 경우 유휴 연결과 관련된 동일한 근본 원인으로 인해 ping() 요청은 성공하지만, 바로 뒤따르는 쿼리 요청은 “socket hang up” 오류와 함께 실패할 수 있습니다. 로그에서 이러한 패턴이 보이면 프레임워크 또는 애플리케이션 코드에서 선행 ping을 비활성화하는 옵션이 있는지 확인하십시오. 이렇게 하면 중간 네트워크 구성 요소에서 속도 제한이 적용될 가능성을 줄이는 데에도 도움이 됩니다.
  • 애플리케이션 자체에 충분한 CPU 시간이 할당되고 있는지, 그리고 호스팅 제공업체가 네트워크를 제한하고 있지 않은지 확인하십시오. GC 일시 중지 메트릭, 이벤트 루프 지연 메트릭 등 다양한 모니터링 수단도 잠재적인 리소스 고갈 문제를 배제하는 데 도움이 될 수 있습니다.
  • no-floating-promises ESLint 규칙을 활성화한 상태에서 애플리케이션 코드를 점검해 보십시오. 이렇게 하면 처리되지 않은 Promise를 식별하는 데 도움이 되며, 이러한 Promise는 정리되지 않은 스트림과 소켓으로 이어질 수 있습니다.

읽기 전용 사용자

readonly=1 사용자와 함께 클라이언트를 사용하는 경우, enable_http_compression 설정이 필요하므로 응답 압축을 활성화할 수 없습니다. 다음 구성은 오류를 발생시킵니다:
readonly=1 사용자의 제한 사항을 더 자세히 보여 주는 예시를 참조하십시오.

경로명이 포함된 프록시

ClickHouse instance가 프록시 뒤에 있고 URL에 경로명이 포함되어 있는 경우(예: http://proxy:8123/clickhouse&#95;server)에는 pathname 구성 옵션에 clickhouse_server를 지정하십시오(앞에 슬래시가 있어도 되고 없어도 됩니다). 그렇지 않고 이를 url에 직접 지정하면 database 옵션으로 간주됩니다. 여러 세그먼트도 지원합니다. 예: /my_proxy/db.

인증이 적용된 리버스 프록시

ClickHouse 배포 앞단에 인증이 적용된 리버스 프록시가 있는 경우, 해당 리버스 프록시에 필요한 헤더를 전달하도록 http_headers 설정을 사용할 수 있습니다:

사용자 지정 HTTP/HTTPS 에이전트(실험적, Node.js 전용)

이는 실험적 기능이며 향후 릴리스에서 하위 호환되지 않는 방식으로 변경될 수 있습니다. 클라이언트가 제공하는 기본 구현 및 설정으로도 대부분의 사용 사례에는 충분합니다. 이 기능은 꼭 필요하다고 확신하는 경우에만 사용하세요.
기본적으로 클라이언트는 클라이언트 구성에 지정된 설정(max_open_connections, keep_alive.enabled, tls 등)을 사용해 내부 HTTP 또는 HTTPS 에이전트를 구성하며, 이 에이전트가 ClickHouse 서버와의 연결을 처리합니다. 또한 TLS 인증서를 사용하는 경우 내부 에이전트는 필요한 인증서로 구성되며, 올바른 TLS 인증 header가 적용됩니다. 1.2.0 이후에는 기본 내부 에이전트를 대체하는 사용자 지정 HTTP 또는 HTTPS 에이전트를 클라이언트에 제공할 수 있습니다. 이는 복잡한 네트워크 구성에서 유용할 수 있습니다. 사용자 지정 에이전트를 제공하면 다음 조건이 적용됩니다.
  • max_open_connectionstls 옵션은 내부 에이전트 구성의 일부이므로 아무런 효과가 없으며 클라이언트에서 무시됩니다.
  • keep_alive.enabledConnection header의 기본값만 제어합니다(true -> Connection: keep-alive, false -> Connection: close).
  • 유휴 keep-alive socket 관리는 계속 동작하지만(에이전트가 아니라 특정 socket 자체에 종속되기 때문입니다), 이제 keep_alive.idle_socket_ttl 값을 0으로 설정해 이를 완전히 비활성화할 수 있습니다.

사용자 지정 Agent 사용 예시

인증서 없이 사용자 지정 HTTP 또는 HTTPS Agent를 사용하는 예시:
basic TLS와 CA certificate를 사용하는 custom HTTPS Agent:
mutual TLS와 함께 사용자 지정 HTTPS Agent 사용:
인증서 사용자 지정 HTTPS Agent를 사용하는 경우, TLS 헤더와 충돌할 수 있으므로 set_basic_auth_header 설정(1.2.0에 도입됨)으로 기본 Authorization 헤더를 비활성화해야 할 가능성이 높습니다. 모든 TLS 헤더는 수동으로 지정해야 합니다.

알려진 제한 사항 (Node.js/web)

  • 결과 집합에 대한 데이터 매퍼가 없으므로 언어 기본 타입만 사용됩니다. 일부 데이터 타입 매퍼는 RowBinary 포맷 지원과 함께 추가될 예정입니다.
  • 일부 Decimal* 및 Date* / DateTime* 데이터 타입 관련 유의 사항이 있습니다.
  • JSON* 계열 포맷을 사용할 때 Int32보다 큰 숫자는 문자열로 표현됩니다. Int64+ 타입의 최댓값이 Number.MAX_SAFE_INTEGER보다 크기 때문입니다. 자세한 내용은 Integral types 섹션을 참조하십시오.

알려진 제한 사항 (web)

  • select 쿼리의 스트리밍은 작동하지만, 삽입에는 사용할 수 없습니다(타입 수준에서도 마찬가지입니다).
  • 요청 압축은 비활성화되어 있고 구성은 무시됩니다. 응답 압축은 작동합니다.
  • 아직 로깅을 지원하지 않습니다.

성능 최적화를 위한 팁

  • 애플리케이션 메모리 사용량을 줄이려면, 해당되는 경우 대용량 삽입(예: 파일에서)과 select 쿼리에 스트림을 사용하는 방안을 고려하십시오. 이벤트 listener 및 이와 유사한 사용 사례에서는 async inserts도 좋은 선택지가 될 수 있으며, 클라이언트 측 배칭을 최소화하거나 완전히 없앨 수도 있습니다. Async insert 예시는 client 리포지토리에서 확인할 수 있으며, 파일 이름 prefix는 async_insert_입니다.
  • 클라이언트는 기본적으로 request 또는 response 압축(Compression)을 활성화하지 않습니다. 하지만 대용량 데이터셋을 select하거나 삽입할 때는 ClickHouseClientConfigOptions.compression을 통해 이를 활성화하는 것을 고려할 수 있습니다(request 또는 response만, 혹은 둘 다 설정 가능).
  • 압축(Compression)에는 상당한 성능 비용이 따릅니다. 이를 request 또는 response에 활성화하면 각각 삽입 또는 select 속도에 부정적인 영향을 주지만, 애플리케이션이 전송하는 네트워크 트래픽 양은 줄일 수 있습니다.

문의하기

질문이 있거나 도움이 필요하면 Community Slack의 (#clickhouse-js 채널) 또는 GitHub issues를 통해 편하게 문의하세요.
마지막 수정일 2026년 7월 23일