Skip to main content
서버 설정 파일을 편집하지 않고 SQL에서 정의한 사용자 정의 HTTP handler를 생성합니다. SQL로 정의한 handler는 구성 기반 HTTP 인터페이스 handler를 대체할 수 있습니다.

구문

지정된 name으로 handler를 생성합니다. 이 이름은 SQL 쿼리를 통해 handler를 관리하고, 진단 메시지에 표시하며, handler의 순서를 정하는 데 사용됩니다.

  • PROTOCOL — 선택 사항입니다. 프로토콜 이름을 지정하면 핸들러는 지정된 조합형 프로토콜에서만 활성화됩니다. 그렇지 않으면 핸들러는 내장 http/https 포트와 모든 HTTP 유형의 조합형 프로토콜 리스너를 비롯한 모든 HTTP 엔드포인트에서 활성화됩니다. PROTOCOL ANY는 후자의 기본 동작을 명시적으로 선택하며, ALTER HANDLER에서는 이전에 설정된 프로토콜 제한을 제거합니다. 문자 그대로 any라는 이름의 프로토콜은 백쿼트로 참조할 수 있습니다: PROTOCOL `any` .
  • URL — 필수입니다. 정확한 URL, URL PREFIX 또는 URL REGEXP 형식으로 지정할 수 있습니다. 정확한 URL과 접두사는 생성 또는 변경 시점에 모호성을 검사하며, 모호성이 있으면 예외가 발생합니다. 정규식은 모호성을 검사할 수 없습니다. URL은 ? 쿼리 문자열과 # 프래그먼트 식별자를 제외하고 일치시킵니다. URL PREFIX는 기본 경로로서 경로 세그먼트 경계에서 일치합니다. 이는 구성으로 정의된 핸들러url_prefix 규칙과 동일한 의미입니다. URL PREFIX '/api/v1'/api/v1, /api/v1/, /api/v1/write와 일치하지만 /api/v1beta와는 일치하지 않습니다. 접두사 끝의 /는 무시되므로 '/api/v1/''/api/v1'는 동일하게 동작합니다.
  • METHODS — 선택 사항입니다. 허용되는 HTTP 메서드 목록입니다. 기본값은 GET뿐입니다. 지원되는 메서드는 GET, POST, PUT, DELETE입니다. 데이터를 변경하는 메서드인 POST, PUT, DELETE는 수정 쿼리를 실행할 수 있으며, GET, HEAD와 같은 안전한 메서드는 항상 readonly 모드에서 실행됩니다. 따라서 데이터를 수정하는 쿼리(예: INSERT 또는 DDL)를 실행하는 핸들러는 최소 하나의 데이터 변경 메서드를 허용해야 합니다. 읽기 전용 메서드만(예: 기본값인 GET) 허용하는 이러한 핸들러를 생성하면 예외가 발생합니다. readonly 모드에서도 부수 효과가 유지되는 쿼리는 특수한 경우입니다. BACKUPRESTORE는 지속적인 부수 효과를 발생시키며, 세션을 변경하는 SQL 문 SET, SET ROLE, USE, BEGIN TRANSACTION, COMMIT, ROLLBACK, SET TRANSACTION SNAPSHOTsession_id 사용 시 요청 간에 유지되는 세션 또는 트랜잭션 상태를 변경합니다. 또한 CREATE TEMPORARY TABLE / CREATE TEMPORARY VIEW는 세션 내에서 유지되는 객체를 생성하지만, 안전한 메서드의 readonly 모드는 이들 중 어느 것도 차단하지 않습니다. 기존 임시 테이블에 대한 변경도 readonly 모드에서 차단되지 않으므로, 이를 대상으로 할 수 있는 쿼리도 동일하게 처리됩니다. 데이터베이스로 한정되지 않은 대상 테이블을 가진 INSERT(한정되지 않은 이름은 세션 임시 테이블로 해석될 수 있음), DROP TEMPORARY TABLE, 데이터베이스로 한정되지 않은 테이블의 DROP TABLE / TRUNCATE TABLE, 데이터베이스로 한정되지 않은 테이블의 ALTER이 이에 해당합니다(ALTER TEMPORARY TABLE은 동일한 SQL 문입니다). 데이터베이스로 한정된 대상은 임시 테이블일 수 없으므로 이러한 쿼리에는 이 규칙이 적용되지 않습니다. HTTP는 안전한 메서드에 부수 효과가 없을 것을 요구합니다(GET에 대해 선언된 핸들러는 응답 본문이 억제되어 효과를 확인할 수 없는 HEAD에도 제공됩니다). 따라서 이러한 쿼리를 실행하는 핸들러는 데이터 변경 메서드만 나열해야 하며, 안전한 메서드를 포함하도록 생성하거나 변경하면 예외가 발생합니다. 복합 SQL 문은 내부 SQL 문까지 검사합니다. statement1 PARALLEL WITH statement2 ...EXECUTE AS <user> <statement>에서는 실제로 실행되는 래핑된 SQL 문에 위 규칙이 적용됩니다(각 SQL 문은 readonly 모드를 유지하는 핸들러 컨텍스트의 복사본에서 실행됨). 단독 EXECUTE AS <user>는 전체 세션을 다른 사용자로 실행하므로 자체적으로 세션 변경으로 간주됩니다. 또한 단독이거나 SQL 문을 래핑하는 모든 EXECUTE AS 핸들러는 최소 하나의 데이터 변경 메서드를 허용해야 합니다. 가장에는 IMPERSONATE 권한이 필요하며, 안전한 메서드의 readonly 모드는 이를 거부합니다.
  • TYPE — 선택 사항입니다. 현재 지원되는 유일한 유형은 query입니다.
  • AS — 이 핸들러가 호출할 SQL 쿼리입니다. 쿼리는 매개변수화할 수 있습니다. 쿼리는 핸들러를 생성하거나 변경할 때 구문적 정확성만 검사하며, 분석하지는 않습니다. 예를 들어 핸들러 생성 시점에 쿼리에서 참조하는 테이블이 없을 수 있습니다. FORMAT 및 유사한 절은 전체 CREATE/ALTER SQL 문이 아니라 쿼리에 속합니다. 모호성을 피하기 위해 쿼리를 괄호로 묶을 수 있습니다. INSERT 쿼리에는 VALUES 또는 FORMAT 절 뒤에 인라인 데이터가 포함되어서는 안 됩니다. 인라인 페이로드는 핸들러 정의에 보존할 수 없으므로, 이러한 핸들러를 생성하거나 변경하면 예외가 발생합니다. 데이터는 HTTP 본문에서 제공하거나 INSERT ... SELECT로 계산해야 합니다. 본문을 읽는 쿼리가 있는 핸들러에 대한 요청, 즉 본문에서 데이터를 가져오는 INSERT 또는 _request_body 매개변수를 사용하는 쿼리는 길이를 선언해야 합니다. Content-Length 헤더가 없는 청크되지 않은 요청에는 411 Length Required로 응답합니다. 그렇지 않으면 본문을 스트림 끝까지 읽게 되어 연결이 끊긴 경우도 완전한 요청으로 받아들여질 수 있기 때문입니다. 이러한 핸들러의 모든 메서드도 본문을 포함하는 메서드(POST, PUT 또는 DELETE)여야 합니다. METHODS 절에서 안전한 메서드(예: 기본값인 GET)로 생성하면 예외가 발생합니다. 안전한 메서드는 요청 본문을 제공하지 않으므로 쿼리가 빈 본문을 조용히 읽게 되기 때문입니다. 선언된 GETHEAD 요청에도 제공되므로, 안전한 메서드와 본문을 포함하는 메서드를 혼합하면 해당 호출을 계속 사용할 수 있습니다. INSERT ... SELECT는 본문을 읽지 않습니다(데이터는 SELECT에서 가져옵니다). 따라서 SELECT가 요청 본문에서 공급되는 input 테이블 함수를 읽는 경우를 제외하면 이러한 요구 사항이 적용되지 않습니다. 본문을 읽는 INSERT는 핸들러 자체의 쿼리여야 합니다. EXECUTE ASPARALLEL WITH는 자신이 감싼 SQL 문을 요청 본문 없이 실행하므로, 모든 업로드를 조용히 버리는 대신 이러한 구문으로 감싼 쿼리는 생성 시 거부됩니다. 본문을 읽는 쿼리는 _request_body 매개변수도 사용해서는 안 됩니다. 요청 본문은 하나뿐이며, _request_body를 바인딩하면 쿼리가 입력 데이터를 읽기 전에 본문을 소비하므로 모든 업로드가 조용히 손실되는 대신 이러한 핸들러는 생성 시 거부됩니다. 쿼리 자체의 본문 입력 또는 _request_body 중 하나만 사용하고 둘 다 사용하지 마십시오. 본문을 읽지 않는 핸들러에는 이러한 요구 사항이 없습니다. 이러한 핸들러에 대한 요청 본문은 무시되며 핸들러 쿼리에 절대 추가되지 않습니다. 저장된 쿼리 텍스트는 핸들러를 다시 로드하거나 호출할 때마다 서버에서 파서 깊이와 역추적 횟수 제한 없이 다시 구문 분석됩니다. 따라서 max_parser_depth / max_parser_backtracks를 높인 세션에서 생성된 핸들러도 일반적인 세션 제한에서 계속 로드하고 호출할 수 있습니다.

우선순위

서버 구성에 정의된 핸들러가 SQL로 정의된 핸들러보다 우선합니다. SQL로 정의된 핸들러는 이름의 사전식 순서대로 일치합니다.

매개변수

매개변수화된 쿼리의 쿼리 매개변수는 구성으로 정의된 handler와 마찬가지로 다음에서 제공됩니다.
  • 쿼리 문자열의 HTTP URL 매개변수에서 param_<name> 규칙을 사용합니다(예: ?param_id=42{id:Type}에 바인딩됩니다).
  • URL REGEXP의 이름 지정 캡처 그룹을 사용합니다(예: URL REGEXP '/users/(?P<id>\d+)'{id:Type}에 바인딩됩니다).
  • 쿼리에서 매개변수를 선언하는 handler의 요청 본문 양식 필드를 사용합니다. application/x-www-form-urlencoded 본문(예: curl -d 'param_id=42') 및 multipart/form-data 본문의 필드는 본문을 포함하는 메서드 POST, PUT, DELETE에서 URL 매개변수와 동일한 방식으로 {name:Type} 매개변수에 바인딩됩니다. URL과 본문 모두에 있는 매개변수는 URL의 값을 사용합니다. 양식으로 파싱된 본문은 handler 계층에서 소비되므로 INSERT 데이터로 쿼리에 전달되지 않습니다. 본문을 _request_body로만 사용하는 handler는 양식 파싱 대신 원시 본문을 받습니다. 다른 매개변수와 함께 _request_body를 선언하는 handler는 둘 다 받습니다. 즉, 본문이 양식으로 파싱되기 전에 원시 본문의 복사본이 _request_body에 보존됩니다(http_max_request_param_data_size의 제한을 따름).
handler를 호출할 때 표준 ClickHouse HTTP 헤더(예: X-ClickHouse-Database, X-ClickHouse-User, X-ClickHouse-Key)는 일반적인 방식으로 적용됩니다. 함수 currentHandlercurrentRequestURL을 사용하면 호출된 handler와 요청 URL에 따라 쿼리 동작을 사용자 정의할 수 있습니다.

액세스 제어

CREATE HANDLER, DROP HANDLER, ALTER HANDLER를 사용하려면 각각 CREATE HANDLER, DROP HANDLER, ALTER HANDLER 권한이 필요합니다. system.handlers 테이블을 읽으려면 SHOW HANDLERS 권한이 필요합니다. 핸들러 쿼리에 포함될 수 있는 시크릿은 사용자가 시크릿을 볼 수 있는 추가 권한을 갖고 있지 않으면 해당 테이블에서 마스킹됩니다(system.handlers 참조). 핸들러를 호출하는 데는 별도의 권한이 필요하지 않지만, 쿼리를 호출할 때는 일반적인 방식으로 권한을 확인하며 인증도 정상적으로 적용됩니다. 특정 쿼리에 대한 액세스를 캡슐화하려면 SQL SECURITY DEFINER가 포함된 VIEW를 생성하고 해당 뷰를 SELECT하는 핸들러를 정의하십시오.

스토리지

핸들러는 이름이 지정된 컬렉션과 마찬가지로 설정 파일의 query_rules_storage 섹션에서 구성하는 로컬 또는 Keeper 스토리지에 저장됩니다:
Keeper Storage를 사용하면 handler가 모든 레플리카에서 자동으로 동기화됩니다. 따라서 명시적인 ON CLUSTER 절은 불필요하며, 지정하면 모든 레플리카가 동일한 handler를 생성하려고 시도합니다. Storage가 복제된 경우 CREATE, ALTER, DROP HANDLER에서 ON CLUSTER를 무시하도록 ignore_on_cluster_for_replicated_handler_queries 설정을 활성화하십시오. 이는 ignore_on_cluster_for_replicated_named_collections_queries와 동일한 방식입니다.

ALTER HANDLER

handler를 새 handler로 교체합니다. ALTER 쿼리에는 일부 절만 포함할 수 있으므로, 예를 들어 URL 또는 쿼리만 변경할 수 있습니다. 지정하지 않은 절은 기존 값을 유지합니다. PROTOCOL ANY는 기존 protocol 제한을 제거하여 handler가 다시 모든 HTTP endpoint에서 활성화되도록 합니다.

DROP HANDLER

지정한 이름의 handler를 삭제합니다.

내부 검사

system.handlers 테이블에는 SQL로 정의된 모든 handler가 나열됩니다. system.query_log 테이블은 각 쿼리의 handler 이름과 HTTP 요청 경로(쿼리 문자열 제외)를 http_handler_namehttp_request_url 컬럼에 기록합니다.

예시

정규식 URL을 사용하는 매개변수화된 handler:
CREATE HANDLERCREATE SQL 문 계열에 속하며, ALTERDROP과 관련이 있습니다.
마지막 수정일 2026년 8월 27일