# 템플릿 검색

## 개요

템플릿 검색은 [저장된 검색](/ko/search/scheduled-searches.md) (SQL로 작성됨)이며 변수를 포함합니다. 템플릿 매크로는 다른 저장된 검색으로 가져올 수 있고 인수와 함께 호출할 수 있는 템플릿 검색입니다(함수 호출과 유사).

템플릿 검색을 템플릿 매크로로 정의하지 않고 저장할 수도 있습니다. 이 경우 쿼리는 다른 곳에서 실행할 수 없으며, 변수 값은 동일한 저장된 검색 내에서 제공됩니다.

자주 실행되는 SQL 표현식을 하나의 라이브러리 같은 저장된 검색에 템플릿 매크로로 저장할 수 있으므로, 복잡한 SQL 코드를 더 쉽게 관리하고 재사용할 수 있습니다. 예를 들어, 아래 영역에 대해 관련 쿼리의 "라이브러리"를 정의할 수 있습니다:

* 직원 매크로
* 상관관계 매크로
* 보강 매크로

템플릿 검색은 Panther에서 다음을 포함하여 정의됩니다 `-- pragma: template` 를 SQL의 첫 줄로 둡니다.

{% hint style="info" %}
Panther는 [Django 템플릿 언어](https://django.readthedocs.io/en/1.7.x/topics/templates.html)를 사용하며, 이는 [Jinja 템플릿](https://jinja.palletsprojects.com/en/3.1.x/)과 매우 유사합니다. 이는 대부분의 [DBT](https://www.getdbt.com/) 템플릿이 상호 운용 가능함을 의미합니다.

Panther의 템플릿 엔진은 [pongo2](https://github.com/flosch/pongo2?tab=readme-ov-file)를 기반으로 하므로, 모든 Django 문법이 지원되는 것은 아닙니다. 다음을 참조하세요 [pongo2에 대해 나열된 주의사항](https://github.com/flosch/pongo2?tab=readme-ov-file#caveats) 를 참조하세요.
{% endhint %}

### 예시 사용 사례

템플릿 매크로의 유용성을 보여주기 위해, 날짜 범위와 사용자 이름이 필요한 복잡한 쿼리(SQL 50줄 정도에 걸친다고 가정)를 가지고 있다고 상상해 보세요. 템플릿 매크로가 없다면, 이 검색을 실행할 때마다 특정 날짜 범위와 사용자 이름을 입력하도록 쿼리를 수정해야 하며, 이는 번거롭고 오류가 발생하기 쉽습니다.

대신 이 복잡한 쿼리는 템플릿 매크로(이름은 `user_activity_profile` 이며 아래 예시에서)로 템플릿 검색(이름은 `user queries` 이며 아래 예시에서) 안에 생성될 수 있고, 날짜 범위와 사용자 이름을 위한 변수를 가질 수 있습니다.

그런 다음 아래와 같은 새 쿼리를 만들 수 있으며, 이 쿼리는 템플릿 매크로(`user_activity_profile`)를 템플릿 검색(`user queries`)에서 가져오고 매크로를 호출하여 사용자 이름 및 날짜/시간 값을 전달합니다. 그런 다음 *이* 검색을 저장할 수 있으며(예를 들어 이름을 `run_user_activity_profile`로 지정), 더 빠르게 접근할 수 있습니다.

```sql
-- pragma: template

--저장된 쿼리 'user queries'에서 쿼리 user_activity_profile을 로드합니다
{% import 'user queries' user_activity_profile %}

{{user_activity_profile('bob_smith', '2023-01-01 00:00:00', '2023-01-02 00:00:00')}}
```

## 템플릿 검색 사용 방법

매크로로 정의하지 않고 변수를 사용하는 템플릿 검색을 만들 수 있습니다. 이 경우 쿼리를 다른 저장된 검색으로 가져올 수는 없지만, 모든 변수 값이 파일 상단에 정의되므로 향후 쿼리 실행은 더 간단해집니다.

### 템플릿 검색 만들기

Panther Console 내 Data Explorer에서 또는 로컬의 CLI 워크플로에서 템플릿 검색을 만들 수 있습니다.

{% tabs %}
{% tab title="콘솔" %}
**Panther Console에서 템플릿 검색을 만드는 방법**

1. Panther Console의 왼쪽 탐색 표시줄에서 **조사** > **Data Explorer**.
2. SQL 편집기에서 다음을 추가합니다 `-- pragma: template` 를 맨 위에.
3. 다음을 사용하여 변수를 선언하는 SQL 쿼리를 만듭니다 `{{}}` (중괄호 두 개).
   * 예시:

     ```sql
     -- pragma: template
     select {{p}}, {{q}}
     ```
4. 변수 값을 설정하려면 파일 상단에 다음과 같은 문을 추가합니다:

   ```sql
   {% set <variable one name> = <variable one value> %}
   {% set <variable two name> = <variable two value> %}
   ```

   * 예시:

     ```sql
     -- pragma: template
     {% set p = "1" %}
     {% set q = "'queue'" %}

     select {{p}}, {{q}}
     ```
5. 을 클릭합니다 **다른 이름으로 저장,** 그리고 다음 필드에 값을 제공합니다:
   * **쿼리 이름**: 설명이 포함된 이름을 추가합니다.
   * **태그**: 유사한 쿼리를 함께 그룹화하는 데 도움이 되도록 태그를 추가합니다.
   * **설명**: 쿼리의 목적을 설명합니다.
   * **기본 데이터베이스**: 쿼리할 데이터베이스를 선택합니다.
   * **이것이 예약된 쿼리입니까?**: 이것을 전환합니다 `ON` 이 쿼리가 정의된 간격으로 실행되기를 원하는 경우.
     * 이것을 전환하면 `ON`, 시간 간격을 제공합니다.
6. 을 클릭합니다 **쿼리 저장**.
   {% endtab %}

{% tab title="CLI" %}
**CLI 워크플로에서 템플릿 검색을 만드는 방법**

CLI 워크플로에서 템플릿 검색을 만들려면 다음을 따르세요 [CLI 워크플로 지침에서 저장된 검색을 만드는 방법](/ko/search/scheduled-searches.md#how-to-create-a-saved-search-in-the-cli-workflow).

다음에 SQL을 작성할 때 `쿼리` 키:

* 포함합니다 `-- pragma: template` 를 맨 위에.
* 중괄호 두 개로 둘러싸인 변수가 있는 쿼리를 추가합니다.

예시:

```yaml
Query: |-
    -- pragma: template
    {% set p = "1" %}
    {% set q = "'queue'" %}
    select '{{p}}', '{{q}}'
```

{% endtab %}
{% endtabs %}

### Data Explorer에서 템플릿 검색 실행하기

이전에 정의한 템플릿 검색을 열고 변수 값을 제공하여 Data Explorer에서 실행할 수 있습니다.

1. Panther Console의 왼쪽 탐색 표시줄에서 **조사** > **Data Explorer**.
2. 오른쪽 상단에서 다음을 클릭합니다 **저장된 쿼리 열기**.
3. 실행하려는 템플릿 검색을 선택한 다음 **쿼리 열기**.
4. SQL 식의 모든 변수에 대해 파일 상단에 다음과 같은 문으로 값이 정의되어 있는지 확인합니다:

   ```sql
   {% set <variable one name> = <variable one value> %}
   {% set <variable two name> = <variable two value> %}
   ```
5. 을 클릭합니다 **쿼리 실행**.

**예제**

아래 예에서 `p` Run Panther AI `q` 변수에는 각각 다음 값이 주어집니다 `1` Run Panther AI `'queue'`.

```sql
-- pragma: template
{% set p = "1" %}
{% set q = "'queue'" %}

select {{p}}, {{q}}
```

## 템플릿 매크로 사용 방법

템플릿 매크로는 내보내기된 하나 이상의 템플릿 검색이며, 즉 다른 검색에서 가져올 수 있습니다. 여러 매크로를 하나의 템플릿 쿼리에 그룹화하여 관련 매크로의 "라이브러리"를 효과적으로 만드는 것이 특히 유용할 수 있습니다.

### 템플릿 매크로 만들기

Panther Console 내 Data Explorer에서 또는 로컬의 CLI 워크플로에서 템플릿 매크로를 만들 수 있습니다.

{% tabs %}
{% tab title="콘솔" %}
**Panther Console에서 템플릿 매크로를 만드는 방법**

1. Panther Console의 왼쪽 탐색 표시줄에서 **조사** > **Data Explorer**.
2. SQL 편집기에서 다음을 추가합니다 `-- pragma: template` 를 맨 위에.
3. 다음을 사용하여 변수를 선언하는 하나 이상의 SQL 쿼리를 만듭니다 `{{}}` (중괄호 두 개).
4. 각 템플릿 쿼리를 다음으로 감쌉니다:
   * 쿼리 앞: `{% macro <macro name>(<variable_one>, <variable_two>) export %}`
   * 쿼리 뒤: `{% endmacro %}`
5. 을 클릭합니다 **다른 이름으로 저장,** 그리고 다음 필드에 값을 제공합니다:
   * **쿼리 이름**: 설명이 포함된 이름을 추가합니다.
     * 이 값은 나중에 가져올 때 사용됩니다.
   * **태그**: 유사한 쿼리를 함께 그룹화하는 데 도움이 되도록 태그를 추가합니다.
   * **설명**: 쿼리의 목적을 설명합니다.
   * **기본 데이터베이스**: 쿼리할 데이터베이스를 선택합니다.
   * **이것이 예약된 쿼리입니까?**: 이것을 켠 상태로 둡니다 `OFF`.
6. 을 클릭합니다 **쿼리 저장**.

**예제**

```sql
-- pragma: template
{% macro my_query1(p, q) export %}
select '{{p}}', '{{q}}'
{% endmacro %}

{% macro my_query2(x) export %}
select {{x}}}
{% endmacro %}
```

{% endtab %}

{% tab title="CLI" %}
**CLI 워크플로에서 템플릿 매크로를 만드는 방법**

CLI 워크플로에서 템플릿 검색을 만들려면 다음을 따르세요 [CLI 워크플로 지침에서 저장된 검색을 만드는 방법](/ko/search/scheduled-searches.md#how-to-create-a-saved-search-in-the-cli-workflow).

다음에 SQL을 작성할 때 `쿼리` 키:

* 포함합니다 `-- pragma: template`를 맨 위에.
* 중괄호 두 개로 둘러싸인 변수가 있는 하나 이상의 쿼리를 추가합니다.
* 각 템플릿 쿼리를 다음으로 감쌉니다:
  * 쿼리 앞: `{% macro <macro name>(<variable_one>, <variable_two>) export %}`
  * 쿼리 뒤: `{% endmacro %}`

예시:

```yaml
Query: |-
    -- pragma: template
    {% macro my_query1(p, q) export %}
    select '{{p}}', '{{q}}'
    {% endmacro %}

    {% macro my_query2(x) export %}
    select {{x}}}
    {% endmacro %}
```

{% endtab %}
{% endtabs %}

### 다른 쿼리에서 템플릿 매크로 호출하기

이전에 만든 템플릿 매크로를 가져오고 변수 값을 전달하여 실행할 수 있습니다.

1. Panther Console의 왼쪽 탐색 표시줄에서 **조사** > **Data Explorer**.
2. SQL 편집기에서 `-- pragma: template` 문을 맨 위에 추가합니다.

{% hint style="info" %}
확장된 SQL이 표시되기를 원한다면(아마도 디버깅에 도움이 되도록) 다음을 포함하세요 `-- pragma: show macro expanded`.
{% endhint %}

3. 이전에 정의한 매크로를 다음과 같은 구조의 문으로 가져옵니다:

   ```sql
   {% import '<name of Saved Search>' <name of macro> %}
   ```
4. 다음과 같은 구조의 문으로 매크로를 호출하고, 인수 값들을 전달합니다:

   ```sql
   {{<name of macro>('<value of variable one>', '<value of variable two>')}}
   ```
5. 을 클릭합니다 **쿼리 실행**.
   * 선택적으로 다음을 클릭하여 쿼리를 저장합니다 **다른 이름으로 저장**.

#### 전체 예시

```sql
-- pragma: template

--저장된 검색 'example macros'에서 my_query1을 로드합니다
{% import 'example macros' my_query1 %}

{{my_query1('1.1.1.1', 'test')}}
```

### 템플릿 매크로 디버깅

Data Explorer에서 템플릿 매크로를 실행할 때, 다음을 추가하면 템플릿 코드만이 아니라 확장된 SQL 문을 볼 수 있습니다 `-- pragma: show macro expanded` 아래에 `-- pragma: template` 문.\
\
예를 들어, 아래 내용을 Data Explorer에서 실행하면:

```sql
-- pragma: template
-- pragma: show macro expanded
{% set p = "1" %}
{% set q = "'queue'" %}

select {{p}}, {{q}}
```

템플릿은 확장된 SQL로 대체됩니다:

```sql
-- pragma: template
-- pragma: show macro expanded

select 1, 'queue'
```

### 사용자 지정 함수

Panther는 템플릿 작성을 더 쉽게 하기 위해 사용자 지정 함수를 구현했습니다.

#### `split`

Django는 문자열을 리스트로 분할하는 것을 지원하지 않습니다. Panther는 `split` 와 함께 작업할 때 유용할 수 있는 이 기능을 제공하기 위해 함수를 추가했습니다 `for` 루프.

예를 들어, 테이블 간에 쉽게 union하기 위해 다음 쿼리를 고려해 보세요:

```jinja
{% for table_name in split("aws_cloudtrail,panther_audit", ",") %}
    {% if not forloop.First %} union {% endif %}
    select
        '{{ table_name | upper }}' as p_table_name,
        p_event_time,
        p_log_type,
        p_any_ip_addresses,
        p_row_id,
    from panther_logs.public.{{table_name}}
    where p_occurs_since(1d)
        and ARRAY_CONTAINS('142.161.78.139'::variant, p_any_ip_addresses)
{% endfor %}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.panther.com/ko/search/scheduled-searches/templated-searches.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
