

# AWS 서비스 로그 쿼리
<a name="querying-aws-service-logs"></a>

이 단원에는 Amazon Athena를 사용하여 AWS CloudTrail 로그, Amazon CloudFront 로그, Classic Load Balancer 로그, Application Load Balancer 로그, Amazon VPC 흐름 로그, Network Load Balancer 로그 등, 널리 사용되는 데이터 세트를 쿼리하는 다양한 절차가 나와 있습니다.

이 섹션의 작업은 Athena 콘솔을 사용하지만 [Athena JDBC 드라이버](connect-with-jdbc.md), [AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/athena/) 또는 [Amazon Athena API Reference](https://docs.aws.amazon.com/athena/latest/APIReference/) 등의 다른 도구를 사용할 수도 있습니다.

Athena에서 AWS CloudFormation를 사용하여 AWS 서비스 로그 테이블, 파티션, 예제 쿼리를 자동으로 생성하는 방법에 관한 자세한 내용은 AWS Big Data Blog에서 [Automating AWS 서비스 logs table creation and querying them with Amazon Athena](https://aws.amazon.com/blogs/big-data/automating-aws-service-logs-table-creation-and-querying-them-with-amazon-athena/)를 참조하세요. Athena에서 AWS Glue용 Python 라이브러리를 사용해 AWS 서비스 로그를 처리하고 쿼리하기 위한 일반 프레임워크를 생성하는 방법에 대한 자세한 내용은 [Amazon Athena를 사용하여 간단히 AWS 서비스 로그 쿼리](https://aws.amazon.com/blogs/big-data/easily-query-aws-service-logs-using-amazon-athena/)를 참조하세요.

이 단원의 주제에서는 Athena에 액세스할 수 있는 적절한 권한과 쿼리할 데이터가 상주해야 하는 Amazon S3 버킷을 모두 설정했다고 가정합니다. 자세한 내용은 [관리 및 프로그래밍 방식 액세스 설정](setting-up.md) 및 [시작하기](getting-started.md) 단원을 참조하세요.

**Topics**
+ [Application Load Balancer](application-load-balancer-logs.md)
+ [Elastic Load Balancing](elasticloadbalancer-classic-logs.md)
+ [CloudFront](cloudfront-logs.md)
+ [CloudTrail](cloudtrail-logs.md)
+ [Amazon EMR](emr-logs.md)
+ [Global Accelerator](querying-global-accelerator-flow-logs.md)
+ [GuardDuty](querying-guardduty.md)
+ [Network Firewall](querying-network-firewall-logs.md)
+ [Network Load Balancer](networkloadbalancer-classic-logs.md)
+ [Route 53](querying-r53-resolver-logs.md)
+ [Amazon SES](querying-ses-logs.md)
+ [Amazon VPC](vpc-flow-logs.md)
+ [AWS WAF](waf-logs.md)

# Application Load Balancer 로그 쿼리
<a name="application-load-balancer-logs"></a>

Application Load Balancer는 컨테이너를 사용하여 마이크로서비스 분포에서 트래픽 분배를 가능하게 하는, Elastic Load Balancing을 위한 로드 밸런싱 옵션입니다. Application Load Balancer 로그를 쿼리하면 Elastic Load Balancing 인스턴스 및 백엔드 애플리케이션과 주고 받는 트래픽, 지연 시간 및 바이트의 소스를 볼 수 있습니다. 자세한 내용은 **Application Load Balancers 사용 설명서의 [Application Load Balancer에 대한 액세스 로그](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html) 및 [Application Load Balancer에 대한 연결 로그](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html)를 참조하세요.

## 사전 조건
<a name="application-load-balancer-logs-prerequisites"></a>
+ Application Load Balancer 로그를 Amazon S3 버킷에 저장할 수 있도록 [액세스 로깅](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html) 또는 [연결 로깅](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html)을 활성화합니다.
+ Athena용으로 만들 테이블을 보관할 데이터베이스입니다. 데이터베이스를 만들려면 Athena 또는 AWS Glue 콘솔을 사용하세요. 자세한 내용은 이 가이드의 [Athena에서 데이터베이스 생성](creating-databases.md) 또는 *AWS Glue 개발자 안내서*의 [AWS glue 콘솔에서 데이터베이스 관련 작업](https://docs.aws.amazon.com/glue/latest/dg/console-databases.html)을 참조하세요.

**Topics**
+ [사전 조건](#application-load-balancer-logs-prerequisites)
+ [ALB 액세스 로그용 테이블 생성](create-alb-access-logs-table.md)
+ [파티션 프로젝션을 사용하여 Athena에서 ALB 액세스 로그용 테이블 생성](create-alb-access-logs-table-partition-projection.md)
+ [ALB 액세스 로그의 쿼리 예제](query-alb-access-logs-examples.md)
+ [ALB 연결 로그용 테이블 생성](create-alb-connection-logs-table.md)
+ [파티션 프로젝션을 사용하여 Athena에서 ALB 연결 로그용 테이블 생성](create-alb-connection-logs-table-partition-projection.md)
+ [ALB 연결 로그의 쿼리 예제](query-alb-connection-logs-examples.md)
+ [추가 리소스](application-load-balancer-logs-additional-resources.md)

# ALB 액세스 로그용 테이블 생성
<a name="create-alb-access-logs-table"></a>

1. 다음 `CREATE TABLE` 문을 복사하여 Athena 콘솔의 쿼리 편집기에 붙여넣은 다음 자체 로그 항목 요구 사항에 필요한 대로 수정합니다. Athena 콘솔 시작하기에 대한 자세한 내용은 [시작하기](getting-started.md) 섹션을 참조하세요. `LOCATION` 절의 경로를 Amazon S3 액세스 로그 폴더의 위치로 바꿉니다. 액세스 로그 파일 위치에 대한 자세한 내용은 **Application Load Balancer 사용 설명서의 [액세스 로그 파일](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-file-format)을 참조하세요.

   각 로그 파일 필드에 대한 자세한 내용은 *Application Load Balancer 사용 설명서*의 [액세스 로그 항목](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-entry-format)을 참조하세요.
**참고**  
다음 예제 `CREATE TABLE` 문에는 최근에 추가된 `classification`, `classification_reason` 및 `conn_trace_id`('추적성 ID' 또는 TID) 열이 포함되어 있습니다. 이러한 항목을 포함하지 않은 Application Load Balancer 액세스 로그에 대한 테이블을 생성하려면 `CREATE TABLE` 문에서 해당되는 열을 제거하고 그에 따라 정규 표현식을 수정합니다.

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS alb_access_logs (
               type string,
               time string,
               elb string,
               client_ip string,
               client_port int,
               target_ip string,
               target_port int,
               request_processing_time double,
               target_processing_time double,
               response_processing_time double,
               elb_status_code int,
               target_status_code string,
               received_bytes bigint,
               sent_bytes bigint,
               request_verb string,
               request_url string,
               request_proto string,
               user_agent string,
               ssl_cipher string,
               ssl_protocol string,
               target_group_arn string,
               trace_id string,
               domain_name string,
               chosen_cert_arn string,
               matched_rule_priority string,
               request_creation_time string,
               actions_executed string,
               redirect_url string,
               lambda_error_reason string,
               target_port_list string,
               target_status_code_list string,
               classification string,
               classification_reason string,
               conn_trace_id string
               )
               ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
               WITH SERDEPROPERTIES (
               'serialization.format' = '1',
               'input.regex' = 
           '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) (.*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-_]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^ ]*)\" \"([^\\s]+?)\" \"([^\\s]+)\" \"([^ ]*)\" \"([^ ]*)\" ?([^ ]*)? ?( .*)?'
               )
               LOCATION 's3://amzn-s3-demo-bucket/access-log-folder-path/'
   ```
**참고**  
새 ALB 로그 필드가 추가되는 경우 향후 로그 항목을 처리하기 위해 `input.regex` 파라미터 끝에 있는 *`?( .*)?`* 패턴을 항상 유지하는 것이 좋습니다.

1. Athena 콘솔에서 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `alb_access_logs` 테이블을 등록하여 쿼리를 실행할 수 있도록 데이터를 준비합니다.

# 파티션 프로젝션을 사용하여 Athena에서 ALB 액세스 로그용 테이블 생성
<a name="create-alb-access-logs-table-partition-projection"></a>

ALB 액세스 로그에는 미리 지정할 수 있는 파티션 스키마를 가진 알려진 구조가 있기 때문에 Athena 파티션 프로젝션 기능을 사용하여 쿼리 런타임을 줄이고 파티션 관리를 자동화할 수 있습니다. 새 데이터가 추가되면 파티션 프로젝션은 자동으로 새 파티션을 추가합니다. 따라서 `ALTER TABLE ADD PARTITION`을 사용해 파티션을 수동으로 추가할 필요가 없습니다.

다음 `CREATE TABLE` 문 예제에서는 하나의 AWS 리전에 대해 지정된 날짜부터 현재까지의 ALB 액세스 로그에 파티션 프로젝션을 자동으로 사용합니다. 이 문은 이전 섹션의 예제를 기반으로 하지만 파티션 프로젝션을 사용하기 위해 `PARTITIONED BY`과 `TBLPROPERTIES` 절을 추가합니다. `LOCATION` 및 `storage.location.template` 절에서 자리 표시자를 ALB 액세스 로그의 Amazon S3 버킷 위치를 식별하는 값으로 바꿉니다. 액세스 로그 파일 위치에 대한 자세한 내용은 **Application Load Balancer 사용 설명서의 [액세스 로그 파일](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-file-format)을 참조하세요. `projection.day.range`에 대해 *2022*/*01*/*01*을 사용하려는 시작 날짜로 바꿉니다. 쿼리가 성공적으로 실행되면 테이블을 쿼리할 수 있습니다. 파티션을 로드하기 위해 `ALTER TABLE ADD PARTITION`을 실행하지 않아도 됩니다. 각 로그 파일 필드에 대한 자세한 내용은 [액세스 로그 항목](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-log-entry-format)을 참조하세요.

```
CREATE EXTERNAL TABLE IF NOT EXISTS alb_access_logs (
            type string,
            time string,
            elb string,
            client_ip string,
            client_port int,
            target_ip string,
            target_port int,
            request_processing_time double,
            target_processing_time double,
            response_processing_time double,
            elb_status_code int,
            target_status_code string,
            received_bytes bigint,
            sent_bytes bigint,
            request_verb string,
            request_url string,
            request_proto string,
            user_agent string,
            ssl_cipher string,
            ssl_protocol string,
            target_group_arn string,
            trace_id string,
            domain_name string,
            chosen_cert_arn string,
            matched_rule_priority string,
            request_creation_time string,
            actions_executed string,
            redirect_url string,
            lambda_error_reason string,
            target_port_list string,
            target_status_code_list string,
            classification string,
            classification_reason string,
            conn_trace_id string
            )
            PARTITIONED BY
            (
             day STRING
            )
            ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
            WITH SERDEPROPERTIES (
            'serialization.format' = '1',
            'input.regex' = 
        '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \"([^ ]*) (.*) (- |[^ ]*)\" \"([^\"]*)\" ([A-Z0-9-_]+) ([A-Za-z0-9.-]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^\"]*)\" ([-.0-9]*) ([^ ]*) \"([^\"]*)\" \"([^\"]*)\" \"([^ ]*)\" \"([^\\s]+?)\" \"([^\\s]+)\" \"([^ ]*)\" \"([^ ]*)\" ?([^ ]*)? ?( .*)?'
            )
            LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/<ACCOUNT-NUMBER>/elasticloadbalancing/<REGION>/'
            TBLPROPERTIES
            (
             "projection.enabled" = "true",
             "projection.day.type" = "date",
             "projection.day.range" = "2022/01/01,NOW",
             "projection.day.format" = "yyyy/MM/dd",
             "projection.day.interval" = "1",
             "projection.day.interval.unit" = "DAYS",
             "storage.location.template" = "s3://amzn-s3-demo-bucket/AWSLogs/<ACCOUNT-NUMBER>/elasticloadbalancing/<REGION>/${day}"
            )
```

파티션 프로젝션에 대한 자세한 내용은 [Amazon Athena에서 파티션 프로젝션 사용](partition-projection.md) 단원을 참조하세요.

**참고**  
새 ALB 로그 필드가 추가되는 경우 향후 로그 항목을 처리하기 위해 `input.regex` 파라미터 끝에 있는 *?( .\$1)?* 패턴을 항상 유지하는 것이 좋습니다.

# ALB 액세스 로그의 쿼리 예제
<a name="query-alb-access-logs-examples"></a>

다음 쿼리는 클라이언트 IP 주소별로 그룹화된 로드 밸런서가 수신한 HTTP GET 요청의 개수를 계산합니다:

```
SELECT COUNT(request_verb) AS
 count,
 request_verb,
 client_ip
FROM alb_access_logs
GROUP BY request_verb, client_ip
LIMIT 100;
```

다른 쿼리는 Safari 브라우저 사용자가 방문한 URL을 보여줍니다:

```
SELECT request_url
FROM alb_access_logs
WHERE user_agent LIKE '%Safari%'
LIMIT 10;
```

다음 쿼리는 ELB 상태 코드 값이 500보다 크거나 같은 레코드를 보여 줍니다.

```
SELECT * FROM alb_access_logs
WHERE elb_status_code >= 500
```

다음 예에서는 `datetime`을 통해 로그를 구문 분석하는 방법을 보여 줍니다.

```
SELECT client_ip, sum(received_bytes) 
FROM alb_access_logs
WHERE parse_datetime(time,'yyyy-MM-dd''T''HH:mm:ss.SSSSSS''Z') 
     BETWEEN parse_datetime('2018-05-30-12:00:00','yyyy-MM-dd-HH:mm:ss') 
     AND parse_datetime('2018-05-31-00:00:00','yyyy-MM-dd-HH:mm:ss') 
GROUP BY client_ip;
```

다음 쿼리는 지정된 날짜의 모든 ALB 액세스 로그에 대해 파티션 프로젝션을 사용하는 테이블을 쿼리합니다.

```
SELECT * 
FROM alb_access_logs 
WHERE day = '2022/02/12'
```

# ALB 연결 로그용 테이블 생성
<a name="create-alb-connection-logs-table"></a>

1. 다음 예제 `CREATE TABLE` 문을 복사하여 Athena 콘솔의 쿼리 편집기에 붙여넣은 다음 자체 로그 항목 요구 사항에 필요한 대로 수정합니다. Athena 콘솔 시작하기에 대한 자세한 내용은 [시작하기](getting-started.md) 섹션을 참조하세요. `LOCATION` 절의 경로를 Amazon S3 연결 로그 폴더의 위치로 바꿉니다. 연결 로그 파일 위치에 대한 자세한 내용은 **Application Load Balancer 사용 설명서의 [연결 로그 파일](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html#connection-log-file-format)을 참조하세요. 각 로그 파일 필드에 대한 자세한 내용은 [연결 로그 항목](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html#connection-log-entry-format)을 참조하세요.

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS alb_connection_logs (
            time string,
            client_ip string,
            client_port int,
            listener_port int,
            tls_protocol string,
            tls_cipher string,
            tls_handshake_latency double,
            leaf_client_cert_subject string,
            leaf_client_cert_validity string,
            leaf_client_cert_serial_number string,
            tls_verify_status string,
            conn_trace_id string
            ) 
            ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
            WITH SERDEPROPERTIES (
            'serialization.format' = '1',
            'input.regex' =
             '([^ ]*) ([^ ]*) ([0-9]*) ([0-9]*) ([A-Za-z0-9.-]*) ([^ ]*) ([-.0-9]*) \"([^\"]*)\" ([^ ]*) ([^ ]*) ([^ ]*) ?([^ ]*)?( .*)?'
            )
            LOCATION 's3://amzn-s3-demo-bucket/connection-log-folder-path/'
   ```

1. Athena 콘솔에서 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `alb_connection_logs` 테이블을 등록하여 쿼리를 실행할 수 있도록 데이터를 준비합니다.

# 파티션 프로젝션을 사용하여 Athena에서 ALB 연결 로그용 테이블 생성
<a name="create-alb-connection-logs-table-partition-projection"></a>

ALB 연결 로그에는 미리 지정할 수 있는 파티션 스키마를 가진 알려진 구조가 있기 때문에 Athena 파티션 프로젝션 기능을 사용하여 쿼리 런타임을 줄이고 파티션 관리를 자동화할 수 있습니다. 새 데이터가 추가되면 파티션 프로젝션은 자동으로 새 파티션을 추가합니다. 따라서 `ALTER TABLE ADD PARTITION`을 사용해 파티션을 수동으로 추가할 필요가 없습니다.

다음 `CREATE TABLE` 문 예제에서는 하나의 AWS 리전에 대해 지정된 날짜부터 현재까지의 ALB 연결 로그에 파티션 프로젝션을 자동으로 사용합니다. 이 문은 이전 섹션의 예제를 기반으로 하지만 파티션 프로젝션을 사용하기 위해 `PARTITIONED BY`과 `TBLPROPERTIES` 절을 추가합니다. `LOCATION` 및 `storage.location.template` 절에서 자리 표시자를 ALB 연결 로그의 Amazon S3 버킷 위치를 식별하는 값으로 바꿉니다. 연결 로그 파일 위치에 대한 자세한 내용은 **Application Load Balancer 사용 설명서의 [연결 로그 파일](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html#connection-log-file-format)을 참조하세요. `projection.day.range`에 대해 *2023*/*01*/*01*을 사용하려는 시작 날짜로 바꿉니다. 쿼리가 성공적으로 실행되면 테이블을 쿼리할 수 있습니다. 파티션을 로드하기 위해 `ALTER TABLE ADD PARTITION`을 실행하지 않아도 됩니다. 각 로그 파일 필드에 대한 자세한 내용은 [연결 로그 항목](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-connection-logs.html#connection-log-entry-format)을 참조하세요.

```
CREATE EXTERNAL TABLE IF NOT EXISTS alb_connection_logs (
         time string,
         client_ip string,
         client_port int,
         listener_port int,
         tls_protocol string,
         tls_cipher string,
         tls_handshake_latency double,
         leaf_client_cert_subject string,
         leaf_client_cert_validity string,
         leaf_client_cert_serial_number string,
         tls_verify_status string,
         conn_trace_id string
         )
            PARTITIONED BY
            (
             day STRING
            )
            ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
            WITH SERDEPROPERTIES (
            'serialization.format' = '1',
            'input.regex' =
             '([^ ]*) ([^ ]*) ([0-9]*) ([0-9]*) ([A-Za-z0-9.-]*) ([^ ]*) ([-.0-9]*) \"([^\"]*)\" ([^ ]*) ([^ ]*) ([^ ]*) ?([^ ]*)?( .*)?'
            )
            LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/<ACCOUNT-NUMBER>/elasticloadbalancing/<REGION>/'
            TBLPROPERTIES
            (
             "projection.enabled" = "true",
             "projection.day.type" = "date",
             "projection.day.range" = "2023/01/01,NOW",
             "projection.day.format" = "yyyy/MM/dd",
             "projection.day.interval" = "1",
             "projection.day.interval.unit" = "DAYS",
             "storage.location.template" = "s3://amzn-s3-demo-bucket/AWSLogs/<ACCOUNT-NUMBER>/elasticloadbalancing/<REGION>/${day}"
            )
```

파티션 프로젝션에 대한 자세한 내용은 [Amazon Athena에서 파티션 프로젝션 사용](partition-projection.md) 단원을 참조하세요.

# ALB 연결 로그의 쿼리 예제
<a name="query-alb-connection-logs-examples"></a>

다음 쿼리는 `tls_verify_status` 값이 `'Success'`가 아닌 발생 항목 수를 세고, 클라이언트 IP 주소별로 그룹화합니다.

```
SELECT DISTINCT client_ip, count() AS count FROM alb_connection_logs
WHERE tls_verify_status != 'Success'
GROUP BY client_ip
ORDER BY count() DESC;
```

다음 쿼리는 지정된 시간 범위에서 `tls_handshake_latency` 값이 2초를 초과하는 발생 항목을 검색합니다.

```
SELECT * FROM alb_connection_logs
WHERE 
  (
    parse_datetime(time, 'yyyy-MM-dd''T''HH:mm:ss.SSSSSS''Z') 
    BETWEEN 
    parse_datetime('2024-01-01-00:00:00', 'yyyy-MM-dd-HH:mm:ss') 
    AND 
    parse_datetime('2024-03-20-00:00:00', 'yyyy-MM-dd-HH:mm:ss') 
  ) 
  AND 
    (tls_handshake_latency >= 2.0);
```

# 추가 리소스
<a name="application-load-balancer-logs-additional-resources"></a>

ALB 로그 사용에 대한 자세한 내용은 다음 리소스를 참조하세요.
+ *AWS 지식 센터*의 [Amazon Athena를 사용하여 Application Load Balancer 액세스 로그를 분석하려면 어떻게 해야 합니까?](https://repost.aws/knowledge-center/athena-analyze-access-logs)를 참조하세요.
+ Elastic Load Balancing에서 HTTP 상태 코드에 대한 자세한 내용은 *Application Load Balancer 사용 설명서*의 [Application Load Balancer 문제 해결](https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-troubleshooting.html)을 참조하세요.
+ *AWS 빅 데이터 블로그*의 [Catalog and analyze Application Load Balancer logs more efficiently with AWS Glue custom classifiers and Amazon Athena](https://aws.amazon.com/blogs/big-data/catalog-and-analyze-application-load-balancer-logs-more-efficiently-with-aws-glue-custom-classifiers-and-amazon-athena/)를 참조하세요.

# Classic Load Balancer 로그 쿼리
<a name="elasticloadbalancer-classic-logs"></a>

Classic Load Balancer 로그를 사용하여 Elastic Load Balancing 인스턴스 및 백엔드 애플리케이션과의 송수신 트래픽 패턴을 분석하고 이해합니다. 트래픽의 소스, 지연 시간 및 전송된 바이트 수를 확인할 수 있습니다.

Elastic Load Balancing 로그를 분석하기 전에 대상 Amazon S3 버킷에 저장하기 위한 로그를 구성합니다. 자세한 내용은 [Classic Load Balancer 액세스 로그 사용](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/enable-access-logs.html)을 참조하세요.

**Elastic Load Balancing 로그에 대한 테이블을 생성하려면**

1. 다음 DDL 문을 복사하여 Athena 콘솔에 붙여 넣습니다. Elastic Load Balancing 로그 레코드의 [구문](https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/access-log-collection.html#access-log-entry-format)을 확인합니다. 최신 버전 레코드의 열과 Regex 구문을 포함하도록 다음 쿼리를 업데이트해야 할 수 있습니다​.

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS elb_logs (
    
    timestamp string,
    elb_name string,
    request_ip string,
    request_port int,
    backend_ip string,
    backend_port int,
    request_processing_time double,
    backend_processing_time double,
    client_response_time double,
    elb_response_code string,
    backend_response_code string,
    received_bytes bigint,
    sent_bytes bigint,
    request_verb string,
    url string,
    protocol string,
    user_agent string,
    ssl_cipher string,
    ssl_protocol string
   )
   ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
   WITH SERDEPROPERTIES (
    'serialization.format' = '1',
    'input.regex' = '([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*)[:-]([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-.0-9]*) (|[-0-9]*) (-|[-0-9]*) ([-0-9]*) ([-0-9]*) \\\"([^ ]*) ([^ ]*) (- |[^ ]*)\\\" (\"[^\"]*\") ([A-Z0-9-]+) ([A-Za-z0-9.-]*)$'
   )
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/AWS_account_ID/elasticloadbalancing/';
   ```

1. Elastic Load Balancing 로그의 대상을 지정하여 `LOCATION` Amazon S3 버킷을 수정합니다.

1. Athena 콘솔에서 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `elb_logs` 테이블을 등록하여 쿼리를 위한 데이터를 준비합니다. 자세한 내용은 [예제 쿼리](#query-elb-classic-example) 섹션을 참조하세요.

## 예제 쿼리
<a name="query-elb-classic-example"></a>

다음과 비슷한 방식으로 쿼리를 사용합니다. `4XX` 또는 `5XX` 오류 응답 코드를 반환한 백엔드 애플리케이션 서버가 나열됩니다. `LIMIT` 연산자를 사용하여 한 번에 쿼리할 로그 수를 제한합니다.

```
SELECT
 timestamp,
 elb_name,
 backend_ip,
 backend_response_code
FROM elb_logs
WHERE backend_response_code LIKE '4%' OR
      backend_response_code LIKE '5%'
LIMIT 100;
```

후속 쿼리를 사용하여 백엔드 IP 주소 및 Elastic Load Balancing 인스턴스 이름별로 그룹화된 모든 트랜잭션의 응답 시간을 요약합니다.

```
SELECT sum(backend_processing_time) AS
 total_ms,
 elb_name,
 backend_ip
FROM elb_logs WHERE backend_ip <> ''
GROUP BY backend_ip, elb_name
LIMIT 100;
```

자세한 내용은 [Athena를 이용한 S3 데이터 분석](https://aws.amazon.com/blogs/big-data/analyzing-data-in-s3-using-amazon-athena/)을 참조하세요.

# Amazon CloudFront 로그 쿼리
<a name="cloudfront-logs"></a>

Amazon CloudFront CDN을 구성하여 웹 배포 액세스 로그를 Amazon Simple Storage Service로 내보낼 수 있습니다. 이러한 로그를 사용하여 CloudFront가 제공하는 웹 속성 전반에 걸쳐 사용자의 서핑 패턴을 탐색합니다.

로그 쿼리를 시작하기 전에 기본 CloudFront 배포에 따라 웹 배포에서 로그에 액세스할 수 있도록 설정합니다. 자세한 내용은 *Amazon CloudFront 개발자 안내서*의 [액세스 로그](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html)를 참조하세요. 이 로그를 저장할 Amazon S3 버킷을 기록해 둡니다.

**Topics**
+ [CloudFront 표준 로그용 테이블 생성(레거시)](create-cloudfront-table-standard-logs.md)
+ [JSON을 사용한 수동 파티셔닝을 통해 Athena에서 CloudFront 로그용 테이블 생성](create-cloudfront-table-manual-json.md)
+ [Parquet을 사용한 수동 파티셔닝을 통해 Athena에서 CloudFront 로그용 테이블 생성](create-cloudfront-table-manual-parquet.md)
+ [JSON 사용 파티션 프로젝션을 통해 Athena에서 CloudFront 로그용 테이블 생성](create-cloudfront-table-partition-json.md)
+ [Parquet 사용 파티션 프로젝션을 통해 Athena에서 CloudFront 로그용 테이블 생성](create-cloudfront-table-partition-parquet.md)
+ [CloudFront 실시간 로그용 테이블 생성](create-cloudfront-table-real-time-logs.md)
+ [추가 리소스](cloudfront-logs-additional-resources.md)

# CloudFront 표준 로그용 테이블 생성(레거시)
<a name="create-cloudfront-table-standard-logs"></a>

**참고**  
다음 절차는 CloudFront의 웹 배포 액세스 로그에 적용됩니다. RTMP 배포의 스트리밍 로그에는 적용되지 않습니다.

**CloudFront 표준 로그 파일 필드의 테이블 생성**

1. 다음 예제 DDL 문을 복사하여 Athena 콘솔의 쿼리 편집기에 붙여 넣습니다. 예제 명령문은 **Amazon CloudFront 개발자 안내서의 [표준 로그 파일 필드](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#BasicDistributionFileFormat) 섹션에 설명된 로그 파일 필드를 사용합니다. 로그를 저장하는 Amazon S3 버킷의 `LOCATION`을 수정합니다. 쿼리 편집기 사용에 대한 자세한 내용은 [시작하기](getting-started.md) 단원을 참조하세요.

   이 쿼리는 `ROW FORMAT DELIMITED` 및 `FIELDS TERMINATED BY '\t'`를 지정하여 필드가 탭 문자로 구분됨을 나타냅니다. `ROW FORMAT DELIMITED`의 경우 Athena는 기본적으로 [LazySimpleSerDe](lazy-simple-serde.md)를 사용합니다. `date` 열은 Athena에서 예약어이기 때문에 백틱(`) 키를 사용하여 이스케이프됩니다. 자세한 내용은 [쿼리에서 예약어 이스케이프](reserved-words.md) 섹션을 참조하세요.

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS cloudfront_standard_logs (
     `date` DATE,
     time STRING,
     x_edge_location STRING,
     sc_bytes BIGINT,
     c_ip STRING,
     cs_method STRING,
     cs_host STRING,
     cs_uri_stem STRING,
     sc_status INT,
     cs_referrer STRING,
     cs_user_agent STRING,
     cs_uri_query STRING,
     cs_cookie STRING,
     x_edge_result_type STRING,
     x_edge_request_id STRING,
     x_host_header STRING,
     cs_protocol STRING,
     cs_bytes BIGINT,
     time_taken FLOAT,
     x_forwarded_for STRING,
     ssl_protocol STRING,
     ssl_cipher STRING,
     x_edge_response_result_type STRING,
     cs_protocol_version STRING,
     fle_status STRING,
     fle_encrypted_fields INT,
     c_port INT,
     time_to_first_byte FLOAT,
     x_edge_detailed_result_type STRING,
     sc_content_type STRING,
     sc_content_len BIGINT,
     sc_range_start BIGINT,
     sc_range_end BIGINT
   )
   ROW FORMAT DELIMITED 
   FIELDS TERMINATED BY '\t'
   LOCATION 's3://amzn-s3-demo-bucket/'
   TBLPROPERTIES ( 'skip.header.line.count'='2' )
   ```

1. Athena 콘솔에서 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `cloudfront_standard_logs` 테이블을 등록하여 쿼리를 실행할 수 있도록 데이터를 준비합니다.

## 예제 쿼리
<a name="query-examples-cloudfront-logs"></a>

다음 쿼리는 2018년 6월 9일부터 6월 11일까지 CloudFront가 제공한 바이트 수를 합산합니다. 날짜 열 이름은 예약된 단어이므로 큰따옴표로 묶습니다.

```
SELECT SUM(bytes) AS total_bytes
FROM cloudfront_standard_logs
WHERE "date" BETWEEN DATE '2018-06-09' AND DATE '2018-06-11'
LIMIT 100;
```

쿼리 결과에서 중복 행(예: 중복된 빈 행)을 제거하려면 다음 예제와 같이 `SELECT DISTINCT` 문을 사용할 수 있습니다.

```
SELECT DISTINCT * 
FROM cloudfront_standard_logs 
LIMIT 10;
```

# JSON을 사용한 수동 파티셔닝을 통해 Athena에서 CloudFront 로그용 테이블 생성
<a name="create-cloudfront-table-manual-json"></a>

**JSON 형식을 사용해 CloudFront 표준 로그 파일 필드의 테이블 생성**

1. 다음 예제 DDL 문을 복사하여 Athena 콘솔의 쿼리 편집기에 붙여 넣습니다. 예제 명령문은 **Amazon CloudFront 개발자 안내서의 [표준 로그 파일 필드](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#BasicDistributionFileFormat) 섹션에 설명된 로그 파일 필드를 사용합니다. 로그를 저장하는 Amazon S3 버킷의 `LOCATION`을 수정합니다.

   이 쿼리는 다음 SerDe 속성과 함께 OpenX JSON SerDe를 사용하여 Athena에서 JSON 필드를 올바르게 읽습니다.

   ```
   CREATE EXTERNAL TABLE `cf_logs_manual_partition_json`(
     `date` string , 
     `time` string , 
     `x-edge-location` string , 
     `sc-bytes` string , 
     `c-ip` string , 
     `cs-method` string , 
     `cs(host)` string , 
     `cs-uri-stem` string , 
     `sc-status` string , 
     `cs(referer)` string , 
     `cs(user-agent)` string , 
     `cs-uri-query` string , 
     `cs(cookie)` string , 
     `x-edge-result-type` string , 
     `x-edge-request-id` string , 
     `x-host-header` string , 
     `cs-protocol` string , 
     `cs-bytes` string , 
     `time-taken` string , 
     `x-forwarded-for` string , 
     `ssl-protocol` string , 
     `ssl-cipher` string , 
     `x-edge-response-result-type` string , 
     `cs-protocol-version` string , 
     `fle-status` string , 
     `fle-encrypted-fields` string , 
     `c-port` string , 
     `time-to-first-byte` string , 
     `x-edge-detailed-result-type` string , 
     `sc-content-type` string , 
     `sc-content-len` string , 
     `sc-range-start` string , 
     `sc-range-end` string )
   ROW FORMAT SERDE 
     'org.openx.data.jsonserde.JsonSerDe' 
   WITH SERDEPROPERTIES ( 
     'paths'='c-ip,c-port,cs(Cookie),cs(Host),cs(Referer),cs(User-Agent),cs-bytes,cs-method,cs-protocol,cs-protocol-version,cs-uri-query,cs-uri-stem,date,fle-encrypted-fields,fle-status,sc-bytes,sc-content-len,sc-content-type,sc-range-end,sc-range-start,sc-status,ssl-cipher,ssl-protocol,time,time-taken,time-to-first-byte,x-edge-detailed-result-type,x-edge-location,x-edge-request-id,x-edge-response-result-type,x-edge-result-type,x-forwarded-for,x-host-header') 
   STORED AS INPUTFORMAT 
     'org.apache.hadoop.mapred.TextInputFormat' 
   OUTPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION
     's3://amzn-s3-demo-bucket/'
   ```

1. Athena 콘솔에서 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `cf_logs_manual_partition_json` 테이블을 등록하여 쿼리를 실행할 수 있도록 데이터를 준비합니다.

## 예제 쿼리
<a name="query-examples-cloudfront-logs-manual-json"></a>

다음 쿼리는 2025년 1월 15일까지 CloudFront가 제공한 바이트 수를 합산합니다.

```
SELECT sum(cast("sc-bytes" as BIGINT)) as sc
FROM cf_logs_manual_partition_json
WHERE "date"='2025-01-15'
```

쿼리 결과에서 중복 행(예: 중복된 빈 행)을 제거하려면 다음 예제와 같이 `SELECT DISTINCT` 문을 사용할 수 있습니다.

```
SELECT DISTINCT * FROM cf_logs_manual_partition_json
```

# Parquet을 사용한 수동 파티셔닝을 통해 Athena에서 CloudFront 로그용 테이블 생성
<a name="create-cloudfront-table-manual-parquet"></a>

**Parquet 형식을 사용해 CloudFront 표준 로그 파일 필드의 테이블 생성**

1. 다음 예제 DDL 문을 복사하여 Athena 콘솔의 쿼리 편집기에 붙여 넣습니다. 예제 명령문은 **Amazon CloudFront 개발자 안내서의 [표준 로그 파일 필드](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/AccessLogs.html#BasicDistributionFileFormat) 섹션에 설명된 로그 파일 필드를 사용합니다.

   이 쿼리는 다음 SerDe 속성과 함께 ParquetHiveSerDe를 사용하여 Athena에서 Parquet 필드를 올바르게 읽습니다.

   ```
   CREATE EXTERNAL TABLE `cf_logs_manual_partition_parquet`(
     `date` string, 
     `time` string, 
     `x_edge_location` string, 
     `sc_bytes` string, 
     `c_ip` string, 
     `cs_method` string, 
     `cs_host` string, 
     `cs_uri_stem` string, 
     `sc_status` string, 
     `cs_referer` string, 
     `cs_user_agent` string, 
     `cs_uri_query` string, 
     `cs_cookie` string, 
     `x_edge_result_type` string, 
     `x_edge_request_id` string, 
     `x_host_header` string, 
     `cs_protocol` string, 
     `cs_bytes` string, 
     `time_taken` string, 
     `x_forwarded_for` string, 
     `ssl_protocol` string, 
     `ssl_cipher` string, 
     `x_edge_response_result_type` string, 
     `cs_protocol_version` string, 
     `fle_status` string, 
     `fle_encrypted_fields` string, 
     `c_port` string, 
     `time_to_first_byte` string, 
     `x_edge_detailed_result_type` string, 
     `sc_content_type` string, 
     `sc_content_len` string, 
     `sc_range_start` string, 
     `sc_range_end` string)
   ROW FORMAT SERDE 
     'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
   STORED AS INPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
   OUTPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
   LOCATION
     's3://amzn-s3-demo-bucket/'
   ```

1. Athena 콘솔에서 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `cf_logs_manual_partition_parquet` 테이블을 등록하여 쿼리를 실행할 수 있도록 데이터를 준비합니다.

## 예제 쿼리
<a name="query-examples-cloudfront-logs-manual-parquet"></a>

다음 쿼리는 2025년 1월 19일까지 CloudFront가 제공한 바이트 수를 합산합니다.

```
SELECT sum(cast("sc_bytes" as BIGINT)) as sc
FROM cf_logs_manual_partition_parquet
WHERE "date"='2025-01-19'
```

쿼리 결과에서 중복 행(예: 중복된 빈 행)을 제거하려면 다음 예제와 같이 `SELECT DISTINCT` 문을 사용할 수 있습니다.

```
SELECT DISTINCT * FROM cf_logs_manual_partition_parquet
```

# JSON 사용 파티션 프로젝션을 통해 Athena에서 CloudFront 로그용 테이블 생성
<a name="create-cloudfront-table-partition-json"></a>

Athena 파티션 프로젝션 기능을 사용하여 쿼리 런타임을 줄이고 파티션 관리를 자동화할 수 있습니다. 새 데이터가 추가되면 파티션 프로젝션은 자동으로 새 파티션을 추가합니다. 따라서 `ALTER TABLE ADD PARTITION`을 사용해 파티션을 수동으로 추가할 필요가 없습니다.

다음 CREATE TABLE 문 예제에서는 하나의 AWS 리전에 대해 지정된 날짜부터 현재까지의 CloudFront 로그에 파티션 프로젝션을 자동으로 사용합니다. 쿼리가 성공적으로 실행되면 테이블을 쿼리할 수 있습니다.

```
CREATE EXTERNAL TABLE `cloudfront_logs_pp`(
  `date` string, 
  `time` string, 
  `x-edge-location` string, 
  `sc-bytes` string, 
  `c-ip` string, 
  `cs-method` string, 
  `cs(host)` string, 
  `cs-uri-stem` string, 
  `sc-status` string, 
  `cs(referer)` string, 
  `cs(user-agent)` string, 
  `cs-uri-query` string, 
  `cs(cookie)` string, 
  `x-edge-result-type` string, 
  `x-edge-request-id` string, 
  `x-host-header` string, 
  `cs-protocol` string, 
  `cs-bytes` string, 
  `time-taken` string, 
  `x-forwarded-for` string, 
  `ssl-protocol` string, 
  `ssl-cipher` string, 
  `x-edge-response-result-type` string, 
  `cs-protocol-version` string, 
  `fle-status` string, 
  `fle-encrypted-fields` string, 
  `c-port` string, 
  `time-to-first-byte` string, 
  `x-edge-detailed-result-type` string, 
  `sc-content-type` string, 
  `sc-content-len` string, 
  `sc-range-start` string, 
  `sc-range-end` string)
  PARTITIONED BY(
         distributionid string,
         year int,
         month int,
         day int,
         hour int )
ROW FORMAT SERDE 
  'org.openx.data.jsonserde.JsonSerDe'
WITH SERDEPROPERTIES ( 
  'paths'='c-ip,c-port,cs(Cookie),cs(Host),cs(Referer),cs(User-Agent),cs-bytes,cs-method,cs-protocol,cs-protocol-version,cs-uri-query,cs-uri-stem,date,fle-encrypted-fields,fle-status,sc-bytes,sc-content-len,sc-content-type,sc-range-end,sc-range-start,sc-status,ssl-cipher,ssl-protocol,time,time-taken,time-to-first-byte,x-edge-detailed-result-type,x-edge-location,x-edge-request-id,x-edge-response-result-type,x-edge-result-type,x-forwarded-for,x-host-header') 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/CloudFront/'
TBLPROPERTIES (
  'projection.distributionid.type'='enum',
  'projection.distributionid.values'='E2Oxxxxxxxxxxx',
  'projection.day.range'='01,31', 
  'projection.day.type'='integer', 
  'projection.day.digits'='2', 
  'projection.enabled'='true', 
  'projection.month.range'='01,12', 
  'projection.month.type'='integer', 
  'projection.month.digits'='2', 
  'projection.year.range'='2025,2026', 
  'projection.year.type'='integer', 
  'projection.hour.range'='00,23',
  'projection.hour.type'='integer',
  'projection.hour.digits'='2',
  'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/CloudFront/${distributionid}/${year}/${month}/${day}/${hour}/')
```

다음은 이전 예제에서 사용된 속성에 대한 몇 가지 고려 사항입니다.
+ **테이블 이름** - 테이블 이름 *`cloudfront_logs_pp`*을 바꿀 수 있습니다. 원하는 이름으로 변경할 수 있습니다.
+ **위치** - `s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/`가 Amazon S3 버킷을 가리키도록 수정합니다.
+ **배포 ID** - `projection.distributionid.values`의 경우 여러 배포 ID를 쉼표로 구분하여 지정할 수 있습니다. 예: *<distributionID1>*, *<distributionID2>*.
+ **연도 범위** - `projection.year.range`에서 데이터를 기반으로 연도 범위를 정의할 수 있습니다. 예를 들어 *2025년*, *2026년*과 같은 기간으로 조정할 수 있습니다.
**참고**  
미래 날짜(예: 2025\$12040)와 같은 빈 파티션을 포함하면 쿼리 성능에 영향을 미칠 수 있습니다. 그러나 파티션 프로젝션은 향후 날짜를 효과적으로 처리하도록 설계되었습니다. 최적의 성능을 유지하려면 파티션을 신중하게 관리하고 가능한 경우 과도한 빈 파티션을 피해야 합니다.
+ **스토리지 위치 템플릿** - 다음 CloudFront 파티셔닝 구조 및 S3 경로를 기반으로 `storage.location.template`를 올바르게 업데이트해야 합니다.  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/athena/latest/ug/create-cloudfront-table-partition-json.html)

  CloudFront 파티셔닝 구조와 S3 구조가 필요한 패턴과 일치하는지 확인한 후 `storage.location.template`을 다음과 같이 업데이트합니다.

  ```
  'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/account_id/CloudFront/${distributionid}/folder2/${year}/${month}/${day}/${hour}/folder3/'
  ```
**참고**  
올바른 데이터 스토리지 및 검색을 보장하려면 `storage.location.template`을 적절히 구성하는 것이 중요합니다.

# Parquet 사용 파티션 프로젝션을 통해 Athena에서 CloudFront 로그용 테이블 생성
<a name="create-cloudfront-table-partition-parquet"></a>

다음 CREATE TABLE 문 예제에서는 하나의 AWS 리전에 대해 Parquet의 지정된 날짜부터 현재까지의 CloudFront 로그에 파티션 프로젝션을 자동으로 사용합니다. 쿼리가 성공적으로 실행되면 테이블을 쿼리할 수 있습니다.

```
CREATE EXTERNAL TABLE `cloudfront_logs_parquet_pp`(
`date` string, 
`time` string, 
`x_edge_location` string, 
`sc_bytes` string, 
`c_ip` string, 
`cs_method` string, 
`cs_host` string, 
`cs_uri_stem` string, 
`sc_status` string, 
`cs_referer` string, 
`cs_user_agent` string, 
`cs_uri_query` string, 
`cs_cookie` string, 
`x_edge_result_type` string, 
`x_edge_request_id` string, 
`x_host_header` string, 
`cs_protocol` string, 
`cs_bytes` string, 
`time_taken` string, 
`x_forwarded_for` string, 
`ssl_protocol` string, 
`ssl_cipher` string, 
`x_edge_response_result_type` string, 
`cs_protocol_version` string, 
`fle_status` string, 
`fle_encrypted_fields` string, 
`c_port` string, 
`time_to_first_byte` string, 
`x_edge_detailed_result_type` string, 
`sc_content_type` string, 
`sc_content_len` string, 
`sc_range_start` string, 
`sc_range_end` string)
PARTITIONED BY(
 distributionid string,
 year int,
 month int,
 day int,
 hour int )
ROW FORMAT SERDE 
'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe' 
STORED AS INPUTFORMAT 
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
OUTPUTFORMAT 
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION
's3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/CloudFront/'
TBLPROPERTIES (
'projection.distributionid.type'='enum',
'projection.distributionid.values'='E3OK0LPUNWWO3',
'projection.day.range'='01,31',
'projection.day.type'='integer',
'projection.day.digits'='2',
'projection.enabled'='true',
'projection.month.range'='01,12',
'projection.month.type'='integer',
'projection.month.digits'='2',
'projection.year.range'='2019,2025',
'projection.year.type'='integer',
'projection.hour.range'='01,12',
'projection.hour.type'='integer',
'projection.hour.digits'='2',
'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/CloudFront/${distributionid}/${year}/${month}/${day}/${hour}/')
```

다음은 이전 예제에서 사용된 속성에 대한 몇 가지 고려 사항입니다.
+ **테이블 이름** - 테이블 이름 *`cloudfront_logs_pp`*을 바꿀 수 있습니다. 원하는 이름으로 변경할 수 있습니다.
+ **위치** - `s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_ID/`가 Amazon S3 버킷을 가리키도록 수정합니다.
+ **배포 ID** - `projection.distributionid.values`의 경우 여러 배포 ID를 쉼표로 구분하여 지정할 수 있습니다. 예: *<distributionID1>*, *<distributionID2>*.
+ **연도 범위** - `projection.year.range`에서 데이터를 기반으로 연도 범위를 정의할 수 있습니다. 예를 들어 *2025년*, *2026년*과 같은 기간으로 조정할 수 있습니다.
**참고**  
미래 날짜(예: 2025\$12040)와 같은 빈 파티션을 포함하면 쿼리 성능에 영향을 미칠 수 있습니다. 그러나 파티션 프로젝션은 향후 날짜를 효과적으로 처리하도록 설계되었습니다. 최적의 성능을 유지하려면 파티션을 신중하게 관리하고 가능한 경우 과도한 빈 파티션을 피해야 합니다.
+ **스토리지 위치 템플릿** - 다음 CloudFront 파티셔닝 구조 및 S3 경로를 기반으로 `storage.location.template`를 올바르게 업데이트해야 합니다.  
****    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ko_kr/athena/latest/ug/create-cloudfront-table-partition-parquet.html)

  CloudFront 파티셔닝 구조와 S3 구조가 필요한 패턴과 일치하는지 확인한 후 `storage.location.template`을 다음과 같이 업데이트합니다.

  ```
  'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/account_id/CloudFront/${distributionid}/folder2/${year}/${month}/${day}/${hour}/folder3/'
  ```
**참고**  
올바른 데이터 스토리지 및 검색을 보장하려면 `storage.location.template`을 적절히 구성하는 것이 중요합니다.

# CloudFront 실시간 로그용 테이블 생성
<a name="create-cloudfront-table-real-time-logs"></a>

**CloudFront 실시간 로그 파일 필드의 테이블 생성**

1. 다음 예제 DDL 문을 복사하여 Athena 콘솔의 쿼리 편집기에 붙여 넣습니다. 예제 문에서는 **Amazon CloudFront 개발자 안내서의 [실시간 로그](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/real-time-logs.html) 섹션에 설명된 로그 파일 필드를 사용합니다. 로그를 저장하는 Amazon S3 버킷의 `LOCATION`을 수정합니다. 쿼리 편집기 사용에 대한 자세한 내용은 [시작하기](getting-started.md) 단원을 참조하세요.

   이 쿼리는 `ROW FORMAT DELIMITED` 및 `FIELDS TERMINATED BY '\t'`를 지정하여 필드가 탭 문자로 구분됨을 나타냅니다. `ROW FORMAT DELIMITED`의 경우 Athena는 기본적으로 [LazySimpleSerDe](lazy-simple-serde.md)를 사용합니다. `timestamp` 열은 Athena에서 예약어이기 때문에 백틱(`) 키를 사용하여 이스케이프됩니다. 자세한 내용은 [쿼리에서 예약어 이스케이프](reserved-words.md) 섹션을 참조하세요.

   다음 예제에는 사용 가능한 모든 필드가 포함되어 있습니다. 필요하지 않은 필드를 주석 처리하거나 제거할 수 있습니다.

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS cloudfront_real_time_logs ( 
   `timestamp` STRING,
   c_ip STRING,
   time_to_first_byte BIGINT,
   sc_status BIGINT,
   sc_bytes BIGINT,
   cs_method STRING,
   cs_protocol STRING,
   cs_host STRING,
   cs_uri_stem STRING,
   cs_bytes BIGINT,
   x_edge_location STRING,
   x_edge_request_id STRING,
   x_host_header STRING,
   time_taken BIGINT,
   cs_protocol_version STRING,
   c_ip_version STRING,
   cs_user_agent STRING,
   cs_referer STRING,
   cs_cookie STRING,
   cs_uri_query STRING,
   x_edge_response_result_type STRING,
   x_forwarded_for STRING,
   ssl_protocol STRING,
   ssl_cipher STRING,
   x_edge_result_type STRING,
   fle_encrypted_fields STRING,
   fle_status STRING,
   sc_content_type STRING,
   sc_content_len BIGINT,
   sc_range_start STRING,
   sc_range_end STRING,
   c_port BIGINT,
   x_edge_detailed_result_type STRING,
   c_country STRING,
   cs_accept_encoding STRING,
   cs_accept STRING,
   cache_behavior_path_pattern STRING,
   cs_headers STRING,
   cs_header_names STRING,
   cs_headers_count BIGINT,
   primary_distribution_id STRING,
   primary_distribution_dns_name STRING,
   origin_fbl STRING,
   origin_lbl STRING,
   asn STRING
   )
   ROW FORMAT DELIMITED 
   FIELDS TERMINATED BY '\t'
   LOCATION 's3://amzn-s3-demo-bucket/'
   TBLPROPERTIES ( 'skip.header.line.count'='2' )
   ```

1. Athena 콘솔에서 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `cloudfront_real_time_logs` 테이블을 등록하여 쿼리를 실행할 수 있도록 데이터를 준비합니다.

# 추가 리소스
<a name="cloudfront-logs-additional-resources"></a>

Athena를 사용하여 CloudFront 로그를 쿼리하는 방법에 대한 자세한 내용은 [AWS Big Data Blog](https://aws.amazon.com/blogs/big-data/)의 다음 게시물을 참조하세요.

[Easily query AWS 서비스 logs using Amazon Athena](https://aws.amazon.com/blogs/big-data/easily-query-aws-service-logs-using-amazon-athena/)(2019년 5월 29일).

[Analyze your Amazon CloudFront access logs at scale](https://aws.amazon.com/blogs/big-data/analyze-your-amazon-cloudfront-access-logs-at-scale/)(대규모의 Amazon CloudFront 액세스 로그 분석)(2018년 12월 21일).

[Build a serverless architecture to analyze Amazon CloudFront access logs using AWS Lambda, Amazon Athena, and Amazon Managed Service for Apache Flink](https://aws.amazon.com/blogs/big-data/build-a-serverless-architecture-to-analyze-amazon-cloudfront-access-logs-using-aws-lambda-amazon-athena-and-amazon-kinesis-analytics/)(2017년 5월 26일).

# AWS CloudTrail 로그 쿼리
<a name="cloudtrail-logs"></a>

AWS CloudTrail는 AWS API 호출 및 Amazon Web Services 계정 이벤트를 기록하는 서비스입니다.

CloudTrail 로그에는 AWS 서비스(콘솔 포함)에 수행된 API 호출에 대한 세부 정보가 포함됩니다. CloudTrail은 암호화된 로그 파일을 생성하여 Amazon S3에 저장합니다. 자세한 내용은 [AWS CloudTrail 사용 설명서](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html)를 참조하세요.

**참고**  
여러 계정, 리전 및 날짜에 걸쳐 CloudTrail 이벤트 정보에 대한 SQL 쿼리를 수행하려면 CloudTrail Lake 사용을 고려해 보세요. CloudTrail Lake는 기업의 정보를 검색 가능한 단일 이벤트 데이터 스토어로 집계하는 트레일을 생성할 수 있는 또 다른 AWS 솔루션입니다. 이 솔루션은 Amazon S3 버킷 스토리지를 사용하지 않고 대신 이벤트를 데이터 레이크에 저장하므로 더 풍부하고 빠른 쿼리가 가능합니다. 이를 사용하여 여러 조직, 지역 및 사용자 지정 시간 범위 내에서 이벤트를 검색하는 SQL 쿼리를 만들 수 있습니다. CloudTrail 콘솔 자체에서 CloudTrail Lake 쿼리를 수행하므로 CloudTrail Lake를 사용하는 경우 Athena가 필요하지 않습니다. 자세한 내용은 [CloudTrail Lake](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-lake.html) 설명서를 참조하세요.

CloudTrail 로그와 함께 Athena를 사용하면 AWS 서비스 활동에 대한 분석 기능을 확실하게 향상시킬 수 있습니다. 예를 들어 쿼리를 사용하여 트렌드를 식별하고 소스 IP 주소나 사용자 등의 속성별로 활동을 추가로 격리할 수 있습니다.

일반적인 적용 사례는 CloudTrail 로그를 사용해 보안 및 규정 준수를 위한 운영 활동을 분석하는 것입니다. 자세한 예제는 AWS Big Data Blog 게시물 [Analyze Security, Compliance, and Operational Activity Using AWS CloudTrail and Amazon Athena](https://aws.amazon.com/blogs/big-data/aws-cloudtrail-and-amazon-athena-dive-deep-to-analyze-security-compliance-and-operational-activity/)를 참조하세요.

Athena를 사용하여 로그 파일의 `LOCATION`을 지정하면 Amazon S3에서 직접 이러한 로그 파일을 쿼리할 수 있습니다. 이 작업을 두 가지 방법으로 수행할 수 있습니다.
+ CloudTrail 콘솔에서 직접 CloudTrail 로그 파일용 테이블을 생성하는 방법.
+ Athena 콘솔에서 CloudTrail 로그 파일용 테이블을 수동으로 생성하는 방법.

**Topics**
+ [CloudTrail 로그 및 Athena 테이블 이해](create-cloudtrail-table-understanding.md)
+ [CloudTrail 콘솔을 사용하여 CloudTrail 로그용 Athena 테이블 생성](create-cloudtrail-table-ct.md)
+ [수동 분할을 사용하여 Athena에서 CloudTrail 로그용 테이블 생성](create-cloudtrail-table.md)
+ [수동 분할을 사용하여 조직 전체 추적을 위한 테이블 생성](create-cloudtrail-table-org-wide-trail.md)
+ [파티션 프로젝션을 사용하여 Athena에서 CloudTrail 로그용 테이블 생성](create-cloudtrail-table-partition-projection.md)
+ [CloudTrail 로그 쿼리 예제](query-examples-cloudtrail-logs.md)

# CloudTrail 로그 및 Athena 테이블 이해
<a name="create-cloudtrail-table-understanding"></a>

테이블 생성을 시작하기 앞서 CloudTrail과 그 데이터 저장 방식을 자세히 알아봐야 합니다. 이렇게 하면 CloudTrail 콘솔 또는 Athena에서 필요한 테이블을 생성하는 데 도움이 됩니다.

CloudTrail은 압축된 gzip 형식(`*.json.gz`)의 JSON 텍스트 파일로 로그를 저장합니다. 로그 파일의 위치는 추적 설정 방법, AWS 리전 또는 로깅 중인 리전 및 기타 요인에 따라 다릅니다.

로그가 저장되는 위치, JSON 구조 및 레코드 파일 내용에 대한 자세한 내용은 [AWS CloudTrail 사용 설명서](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html)의 다음 주제를 참조하세요.
+  [CloudTrail 로그 파일 찾기](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-find-log-files.html) 
+  [CloudTrail 로그 파일의 예](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-log-file-examples.html) 
+  [CloudTrail 레코드 콘텐츠](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-record-contents.html)
+  [CloudTrail 이벤트 참조](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference.html) 

로그를 수집하여 Amazon S3에 저장하려면 AWS Management Console에서 CloudTrail을 사용하도록 설정합니다. 자세한 내용은 *AWS CloudTrail 사용 설명서*의 [추적 생성](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-create-a-trail-using-the-console-first-time.html)을 참조하세요.

# CloudTrail 콘솔을 사용하여 CloudTrail 로그용 Athena 테이블 생성
<a name="create-cloudtrail-table-ct"></a>

이전 CloudTrail 콘솔에서 직접 CloudTrail 로그를 쿼리하기 위해 분할되지 않은 Athena 테이블을 생성할 수 있습니다. CloudTrail 콘솔에서 Athena 테이블을 생성하려면 Athena에서 테이블을 생성할 수 있는 충분한 권한이 있는 역할로 로그인해야 합니다.

**참고**  
조직 추적 로그에 대한 Athena 테이블은 CloudTrail 콘솔을 사용해 만들 수 없습니다. 대신 Athena 콘솔을 사용하여 테이블을 수동으로 만들고 올바른 저장 위치를 지정할 수 있습니다. 조직 추적에 대한 자세한 내용은 *AWS CloudTrail 사용 설명서*에서 [조직에 대한 추적 생성](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/creating-trail-organization.html)을 참조하세요.
+ Athena 권한 설정에 대한 자세한 내용은 [관리 및 프로그래밍 방식 액세스 설정](setting-up.md) 단원을 참조하세요.
+ 파티션이 있는 테이블 생성에 대한 자세한 내용은 [수동 분할을 사용하여 Athena에서 CloudTrail 로그용 테이블 생성](create-cloudtrail-table.md) 단원을 참조하세요.

**CloudTrail 콘솔을 사용하여 CloudTrail 추적용 Athena 테이블을 생성하려면**

1. [https://console.aws.amazon.com/cloudtrail/](https://console.aws.amazon.com/cloudtrail/)에서 CloudTrail 콘솔을 엽니다.

1. 탐색 창에서 **Event history(이벤트 내역)**를 선택합니다.

1. **Athena 테이블 생성**을 선택합니다.  
![\[Athena 테이블 생성 선택\]](http://docs.aws.amazon.com/ko_kr/athena/latest/ug/images/cloudtrail-logs-create-athena-table.png)

1. **스토리지 위치**에서, 아래쪽 화살표를 사용하여 추적이 쿼리할 로그 파일이 저장되는 Amazon S3 버킷을 선택합니다.
**참고**  
추적과 연결된 버킷의 이름을 찾으려면 CloudTrail 탐색 창에서 **추적**을 선택하고 추적의 **S3 버킷** 열을 표시합니다. 버킷의 Amazon S3 위치를 보려면 **S3 버킷** 열에서 버킷에 대한 링크를 선택합니다. 그러면 Amazon S3 콘솔이 CloudTrail 버킷 위치로 이동합니다.

1. **테이블 생성**을 선택합니다. Amazon S3 버킷 이름을 포함하는 기본 이름을 가진 테이블이 생성됩니다.

# 수동 분할을 사용하여 Athena에서 CloudTrail 로그용 테이블 생성
<a name="create-cloudtrail-table"></a>

Athena 콘솔에서 CloudTrail 로그 파일용 테이블을 수동으로 생성한 다음 Athena에서 쿼리를 실행할 수 있습니다.

**Athena 콘솔을 사용하여 CloudTrail 추적에 대한 Athena 테이블을 만들려면**

1. 다음 DDL 문을 복사하여 Athena 콘솔 쿼리 편집기에 붙여넣은 다음 요구 사항에 맞추어 수정합니다. CloudTrail 로그 파일은 퍼블릭 API 직접 호출에 대한 순서 지정된 스택 추적이 아니기 때문에 로그 파일에 있는 필드가 특정 순서로 표시되지 않음에 유의하십시오.

   ```
   CREATE EXTERNAL TABLE cloudtrail_logs (
   eventversion STRING,
   useridentity STRUCT<
                  type:STRING,
                  principalid:STRING,
                  arn:STRING,
                  accountid:STRING,
                  invokedby:STRING,
                  accesskeyid:STRING,
                  username:STRING,
                  onbehalfof: STRUCT<
                       userid: STRING,
                       identitystorearn: STRING>,
     sessioncontext:STRUCT<
       attributes:STRUCT<
                  mfaauthenticated:STRING,
                  creationdate:STRING>,
       sessionissuer:STRUCT<  
                  type:STRING,
                  principalid:STRING,
                  arn:STRING, 
                  accountid:STRING,
                  username:STRING>,
       ec2roledelivery:string,
       webidfederationdata: STRUCT<
                  federatedprovider: STRING,
                  attributes: map<string,string>>
     >
   >,
   eventtime STRING,
   eventsource STRING,
   eventname STRING,
   awsregion STRING,
   sourceipaddress STRING,
   useragent STRING,
   errorcode STRING,
   errormessage STRING,
   requestparameters STRING,
   responseelements STRING,
   additionaleventdata STRING,
   requestid STRING,
   eventid STRING,
   resources ARRAY<STRUCT<
                  arn:STRING,
                  accountid:STRING,
                  type:STRING>>,
   eventtype STRING,
   apiversion STRING,
   readonly STRING,
   recipientaccountid STRING,
   serviceeventdetails STRING,
   sharedeventid STRING,
   vpcendpointid STRING,
   vpcendpointaccountid STRING,
   eventcategory STRING,
   addendum STRUCT<
     reason:STRING,
     updatedfields:STRING,
     originalrequestid:STRING,
     originaleventid:STRING>,
   sessioncredentialfromconsole STRING,
   edgedevicedetails STRING,
   tlsdetails STRUCT<
     tlsversion:STRING,
     ciphersuite:STRING,
     clientprovidedhostheader:STRING>
   )
   PARTITIONED BY (region string, year string, month string, day string)
   ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
   STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
   OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/Account_ID/';
   ```
**참고**  
예제에 표시된 `org.apache.hive.hcatalog.data.JsonSerDe`를 사용하는 것이 좋습니다. `com.amazon.emr.hive.serde.CloudTrailSerde`가 존재하지만 현재 일부 최신 CloudTrail 필드는 처리하지 않습니다.

1. (선택 사항) 테이블에 필요하지 않은 필드를 제거합니다. 특정 열 집합만 읽어야 하는 경우 테이블 정의에서 다른 열을 제외할 수 있습니다.

1. 쿼리하고자 하는 로그 데이터가 포함된 Amazon S3 버킷을 가리키도록 `s3://amzn-s3-demo-bucket/AWSLogs/Account_ID/`을 수정합니다. 이 예에서는 특정 계정에 대해 로그의 `LOCATION` 값을 사용하지만 애플리케이션에 적합한 정도의 특정성을 사용할 수 있습니다. 다음 예를 참조하세요.
   + 여러 계정의 데이터를 분석하려면 `LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/'`를 이용해 `LOCATION` 범위 지정자를 롤백하여 모든 `AWSLogs`를 표시할 수 있습니다.
   + 특정 날짜, 계정 및 리전의 데이터를 분석하려면 `LOCATION 's3://amzn-s3-demo-bucket/123456789012/CloudTrail/us-east-1/2016/03/14/'.`를 사용합니다.
   + 관리 이벤트 대신 네트워크 활동 데이터를 분석하려면 `LOCATION` 절의 `/CloudTrail/`을(를) `/CloudTrail-NetworkActivity/`(으)로 변경합니다.

   객체 계층 구조에서 최상위 수준을 사용하면 Athena로 쿼리할 때 가장 큰 유연성을 발휘할 수 있습니다.

1. 필드가 올바르게 나열되는지 확인합니다. CloudTrail 레코드의 필드 전체 목록에 대한 자세한 내용은 [CloudTrail 레코드 콘텐츠](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-record-contents.html)를 참조하세요.

   1단계의 예제 `CREATE TABLE` 문은 [Hive JSON SerDe](hive-json-serde.md)를 사용합니다. 이 예에서 `requestparameters`, `responseelements`, `additionaleventdata` 필드는 쿼리에서 `STRING` 형식으로 나열되지만, JSON에 사용되는 `STRUCT` 데이터 형식입니다. 따라서 이러한 필드에서 데이터를 가져오려면 `JSON_EXTRACT` 함수를 사용합니다. 자세한 내용은 [문자열에서 JSON 데이터 추출](extracting-data-from-JSON.md) 섹션을 참조하세요. 성능 향상을 위해 예제에서는 데이터를 AWS 리전, 연도, 월 및 일별로 분할합니다.

1. Athena 콘솔에서 `CREATE TABLE` 문을 실행합니다.

1. 다음 예제와 같이 [ALTER TABLE ADD PARTITION](alter-table-add-partition.md) 명령을 사용하여 파티션을 쿼리할 수 있도록 파티션을 로드합니다.

   ```
   ALTER TABLE table_name ADD 
      PARTITION (region='us-east-1',
                 year='2019',
                 month='02',
                 day='01')
      LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/Account_ID/CloudTrail/us-east-1/2019/02/01/'
   ```

# 수동 분할을 사용하여 조직 전체 추적을 위한 테이블 생성
<a name="create-cloudtrail-table-org-wide-trail"></a>

Athena에서 조직 전체 CloudTrail 로그 파일에 대한 테이블을 생성하려면 [수동 분할을 사용하여 Athena에서 CloudTrail 로그용 테이블 생성](create-cloudtrail-table.md)의 단계를 따르되, 다음 절차에 설명된 대로 수정하세요.

**조직 전체 CloudTrail 로그에 대한 Athena 테이블을 생성하려면**

1. `CREATE TABLE` 문에서 다음 예시와 같이 조직 ID를 포함하도록 `LOCATION` 절을 수정합니다.

   ```
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/organization_id/'
   ```

1. `PARTITIONED BY` 절에서 다음 예시와 같이 계정 ID에 대한 항목을 문자열로 추가합니다.

   ```
   PARTITIONED BY (account string, region string, year string, month string, day string)
   ```

   다음 예시는 결합된 결과를 보여줍니다.

   ```
   ...
   
   PARTITIONED BY (account string, region string, year string, month string, day string) 
   ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
   STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
   OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/organization_id/Account_ID/CloudTrail/'
   ```

1. `ALTER TABLE` 문 `ADD PARTITION` 절에서 다음 예시와 같이 계정 ID를 포함합니다.

   ```
   ALTER TABLE table_name ADD
   PARTITION (account='111122223333',
   region='us-east-1',
   year='2022',
   month='08',
   day='08')
   ```

1. `ALTER TABLE` 문 `LOCATION` 절에서 다음 예시와 같이 조직 ID, 계정 ID 및 추가할 파티션을 포함합니다.

   ```
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/organization_id/Account_ID/CloudTrail/us-east-1/2022/08/08/'
   ```

   다음 예시 `ALTER TABLE` 문은 결합된 결과를 보여줍니다.

   ```
   ALTER TABLE table_name ADD
   PARTITION (account='111122223333',
   region='us-east-1',
   year='2022',
   month='08',
   day='08')
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/organization_id/111122223333/CloudTrail/us-east-1/2022/08/08/'
   ```

대규모 조직에서는 이 방법을 사용하여 각 조직 계정 ID에 대한 파티션을 수동으로 추가하고 유지 관리하는 것이 번거로울 수 있습니다. 이러한 시나리오에서는 Athena가 아닌 CloudTrail Lake를 사용하는 것을 고려하세요. CloudTrail Lake는 이러한 시나리오에서 다음과 같은 이점을 제공합니다.
+ 전체 조직의 로그를 자동으로 집계합니다.
+ 파티션 또는 Athena 테이블을 설정하거나 유지 관리할 필요가 없습니다.
+ CloudTrail 콘솔에서 쿼리를 직접 실행합니다.
+ SQL 호환 쿼리 언어를 사용합니다.

자세한 내용은 *AWS CloudTrail 사용 설명서*의 [Working with AWS Lake](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-lake.html)를 참조하세요.

# 파티션 프로젝션을 사용하여 Athena에서 CloudTrail 로그용 테이블 생성
<a name="create-cloudtrail-table-partition-projection"></a>

CloudTrail 로그에는 미리 지정할 수 있는 파티션 스키마를 가진 알려진 구조가 있기 때문에 Athena 파티션 프로젝션 기능을 사용하여 쿼리 런타임을 줄이고 파티션 관리를 자동화할 수 있습니다. 새 데이터가 추가되면 파티션 프로젝션은 자동으로 새 파티션을 추가합니다. 따라서 `ALTER TABLE ADD PARTITION`을 사용해 파티션을 수동으로 추가할 필요가 없습니다.

다음 `CREATE TABLE` 문 예제에서는 하나의 AWS 리전에 대해 지정된 날짜부터 현재까지의 CloudTrail 로그에 파티션 프로젝션을 자동으로 사용합니다. `LOCATION` 및 `storage.location.template` 절에서 *bucket*, *account-id* 및 *aws-region* 자리 표시자를 상응하는 동일한 값으로 바꿉니다. `projection.timestamp.range`에 대해 *2020*/*01*/*01*을 사용하려는 시작 날짜로 바꿉니다. 쿼리가 성공적으로 실행된면 테이블을 쿼리할 수 있습니다. 파티션을 로드하기 위해 `ALTER TABLE ADD PARTITION`을 실행하지 않아도 됩니다.

```
CREATE EXTERNAL TABLE cloudtrail_logs_pp(
    eventversion STRING,
    useridentity STRUCT<
        type: STRING,
        principalid: STRING,
        arn: STRING,
        accountid: STRING,
        invokedby: STRING,
        accesskeyid: STRING,
        username: STRING,
        onbehalfof: STRUCT<
             userid: STRING,
             identitystorearn: STRING>,
        sessioncontext: STRUCT<
            attributes: STRUCT<
                mfaauthenticated: STRING,
                creationdate: STRING>,
            sessionissuer: STRUCT<
                type: STRING,
                principalid: STRING,
                arn: STRING,
                accountid: STRING,
                username: STRING>,
            ec2roledelivery:string,
            webidfederationdata: STRUCT<
                federatedprovider: STRING,
                attributes: map<string,string>>
        >
    >,
    eventtime STRING,
    eventsource STRING,
    eventname STRING,
    awsregion STRING,
    sourceipaddress STRING,
    useragent STRING,
    errorcode STRING,
    errormessage STRING,
    requestparameters STRING,
    responseelements STRING,
    additionaleventdata STRING,
    requestid STRING,
    eventid STRING,
    readonly STRING,
    resources ARRAY<STRUCT<
        arn: STRING,
        accountid: STRING,
        type: STRING>>,
    eventtype STRING,
    apiversion STRING,
    recipientaccountid STRING,
    serviceeventdetails STRING,
    sharedeventid STRING,
    vpcendpointid STRING,
    vpcendpointaccountid STRING,
    eventcategory STRING,
    addendum STRUCT<
      reason:STRING,
      updatedfields:STRING,
      originalrequestid:STRING,
      originaleventid:STRING>,
    sessioncredentialfromconsole STRING,
    edgedevicedetails STRING,
    tlsdetails STRUCT<
      tlsversion:STRING,
      ciphersuite:STRING,
      clientprovidedhostheader:STRING>
  )
PARTITIONED BY (
   `timestamp` string)
ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
STORED AS INPUTFORMAT 'com.amazon.emr.cloudtrail.CloudTrailInputFormat'
OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://amzn-s3-demo-bucket/AWSLogs/account-id/CloudTrail/aws-region'
TBLPROPERTIES (
  'projection.enabled'='true', 
  'projection.timestamp.format'='yyyy/MM/dd', 
  'projection.timestamp.interval'='1', 
  'projection.timestamp.interval.unit'='DAYS', 
  'projection.timestamp.range'='2020/01/01,NOW', 
  'projection.timestamp.type'='date', 
  'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/account-id/CloudTrail/aws-region/${timestamp}')
```

파티션 프로젝션에 대한 자세한 내용은 [Amazon Athena에서 파티션 프로젝션 사용](partition-projection.md) 단원을 참조하세요.

# CloudTrail 로그 쿼리 예제
<a name="query-examples-cloudtrail-logs"></a>

다음 예제는 CloudTrail 이벤트 로그에 대해 생성된 테이블에서 모든 익명(서명되지 않은) 요청을 반환하는 쿼리의 일부를 보여줍니다. 이 쿼리는 `useridentity.accountid`가 익명이고 `useridentity.arn`이 지정되지 않은 요청을 선택합니다.

```
SELECT *
FROM cloudtrail_logs
WHERE 
    eventsource = 's3.amazonaws.com' AND 
    eventname in ('GetObject') AND 
    useridentity.accountid = 'anonymous' AND 
    useridentity.arn IS NULL AND
    requestparameters LIKE '%[your bucket name ]%';
```

자세한 내용은 AWS Big Data Blog 게시물 [Analyze Security, Compliance, and Operational Activity Using AWS CloudTrail and Amazon Athena](https://aws.amazon.com/blogs/big-data/aws-cloudtrail-and-amazon-athena-dive-deep-to-analyze-security-compliance-and-operational-activity/)를 참조하세요.

## CloudTrail 로그에서 중첩 필드 쿼리
<a name="cloudtrail-logs-nested-fields"></a>

`userIdentity` 및 `resources` 필드는 중첩된 데이터 형식이기 때문에 이를 쿼리하려면 특수한 처리가 필요합니다.

`userIdentity` 객체는 중첩된 `STRUCT` 형식으로 구성됩니다. 다음 예에서처럼 점으로 필드를 구분하여 이 객체들을 쿼리할 수 있습니다.

```
SELECT 
    eventsource, 
    eventname,
    useridentity.sessioncontext.attributes.creationdate,
    useridentity.sessioncontext.sessionissuer.arn
FROM cloudtrail_logs
WHERE useridentity.sessioncontext.sessionissuer.arn IS NOT NULL
ORDER BY eventsource, eventname
LIMIT 10
```

`resources` 필드는 `STRUCT` 객체의 배열입니다. 이러한 배열의 경우 `CROSS JOIN UNNEST`를 사용해 배열의 중첩을 해제함으로써 해당 객체를 쿼리할 수 있습니다.

다음 예제는 리소스 ARN이 `example/datafile.txt`로 끝나는 모든 행을 반환합니다. [replace](https://prestodb.io/docs/current/functions/string.html#replace) 함수는 가독성을 위해 ARN에서 초기 `arn:aws:s3:::` 하위 문자열을 제거합니다.

```
SELECT 
    awsregion,
    replace(unnested.resources_entry.ARN,'arn:aws:s3:::') as s3_resource,
    eventname,
    eventtime,
    useragent
FROM cloudtrail_logs t
CROSS JOIN UNNEST(t.resources) unnested (resources_entry)
WHERE unnested.resources_entry.ARN LIKE '%example/datafile.txt'
ORDER BY eventtime
```

다음 예제에서는 `DeleteBucket` 이벤트를 쿼리합니다. 이 쿼리는 `resources` 객체에서 버킷의 이름 및 버킷이 속한 계정 ID를 추출합니다.

```
SELECT 
    awsregion,
    replace(unnested.resources_entry.ARN,'arn:aws:s3:::') as deleted_bucket,
    eventtime AS time_deleted,
    useridentity.username, 
    unnested.resources_entry.accountid as bucket_acct_id 
FROM cloudtrail_logs t
CROSS JOIN UNNEST(t.resources) unnested (resources_entry)
WHERE eventname = 'DeleteBucket'
ORDER BY eventtime
```

중첩 해제에 대한 자세한 내용은 [배열 필터링](filtering-arrays.md) 단원을 참조하세요.

## CloudTrail 로그 쿼리 팁
<a name="tips-for-querying-cloudtrail-logs"></a>

CloudTrail 로그 데이터를 탐색할 때 다음 사항을 고려하세요.
+ 로그를 쿼리하기 전에 로그 테이블이 [수동 분할을 사용하여 Athena에서 CloudTrail 로그용 테이블 생성](create-cloudtrail-table.md)의 로그 테이블과 동일한 형태인지 확인합니다. 첫 번째 테이블이 아닌 경우 `DROP TABLE cloudtrail_logs` 명령을 사용하여 기존 테이블을 삭제합니다.
+ 기존 테이블을 삭제하고 다시 만드세요. 자세한 내용은 [수동 분할을 사용하여 Athena에서 CloudTrail 로그용 테이블 생성](create-cloudtrail-table.md) 섹션을 참조하세요.

  Athena 쿼리의 필드가 올바르게 나열되는지 확인합니다. CloudTrail 레코드의 필드 전체 목록에 대한 자세한 내용은 [CloudTrail 레코드 콘텐츠](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-event-reference-record-contents.html)를 참조하세요.

  쿼리에 `STRUCT` 같은 JSON 형식의 필드가 포함된 경우, JSON에서 데이터를 추출합니다. 자세한 내용은 [문자열에서 JSON 데이터 추출](extracting-data-from-JSON.md) 섹션을 참조하세요.

  다음은 CloudTrail 테이블에 대해 쿼리를 실행하기 위한 몇 가지 제안 사항입니다.
+ 먼저 어떤 사용자가 어떤 API 작업을 호출했으며 어떤 소스 IP 주소에서 시작되었는지 확인합니다.
+ 다음 기본 SQL 쿼리를 템플릿으로 사용합니다. 쿼리를 Athena 콘솔에 붙여 넣고 실행합니다.

  ```
  SELECT
   useridentity.arn,
   eventname,
   sourceipaddress,
   eventtime
  FROM cloudtrail_logs
  LIMIT 100;
  ```
+ 데이터를 추가 탐색하려면 쿼리를 수정합니다.
+ 성능을 향상시키려면 `LIMIT` 절을 포함시켜 지정한 행 하위 집합을 반환합니다.

# Amazon EMR 로그 쿼리
<a name="emr-logs"></a>

Amazon EMR 및 Amazon EMR에서 실행되는 빅 데이터 애플리케이션은 로그 파일을 생성합니다. 로그 파일은 [프라이머리 노드](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-master-core-task-nodes.html)에 작성되며 로그 파일을 Amazon S3에 자동으로 보관하도록 Amazon EMR을 구성할 수도 있습니다. Amazon Athena를 사용하여 이러한 로그를 쿼리해 애플리케이션 및 클러스터의 이벤트 및 추세를 식별할 수 있습니다. Amazon EMR의 로그 파일 형식 및 Amazon S3에 이를 저장하는 방법에 대한 자세한 내용은 *Amazon EMR 관리 안내서*의 [로그 파일 보기](https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-manage-view-web-log-files.html)를 참조하세요.

**Topics**
+ [Amazon EMR 로그 파일을 기반으로 기본 테이블 생성 및 쿼리](emr-create-table.md)
+ [Amazon EMR 로그를 기반으로 분할된 테이블 생성 및 쿼리](emr-create-table-partitioned.md)

# Amazon EMR 로그 파일을 기반으로 기본 테이블 생성 및 쿼리
<a name="emr-create-table"></a>

다음 예제에서는 `s3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/elasticmapreduce/`에 저장된 로그 파일을 기반으로 기본 테이블 `myemrlogs`를 생성합니다. 아래 예제에 사용된 Amazon S3 위치는 *us-west-2* 리전의 Amazon Web Services 계정 *123456789012*에서 생성한 EMR 클러스터의 기본 로그 위치 패턴을 반영합니다. 사용자 지정 위치를 사용하는 경우 패턴은 s3://amzn-s3-demo-bucket/*ClusterID*입니다.

잠재적으로 쿼리 성능을 향상시키고 데이터 전송을 줄이기 위해 분할된 테이블을 생성하는 방법에 대한 자세한 내용은 [Amazon EMR 로그를 기반으로 분할된 테이블 생성 및 쿼리](emr-create-table-partitioned.md) 단원을 참조하세요.

```
CREATE EXTERNAL TABLE `myemrlogs`(
  `data` string COMMENT 'from deserializer')
ROW FORMAT DELIMITED  
FIELDS TERMINATED BY '|'
LINES TERMINATED BY '\n'
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6'
```

## 예제 쿼리
<a name="emr-example-queries-basic"></a>

다음 예제 쿼리는 이전 예제에서 생성된 `myemrlogs` 테이블에서 실행할 수 있습니다.

**Example - ERROR, WARN, INFO, EXCEPTION, FATAL 또는 DEBUG 발생에 대한 단계 로그 쿼리**  

```
SELECT data,
        "$PATH"
FROM "default"."myemrlogs"
WHERE regexp_like("$PATH",'s-86URH188Z6B1')
        AND regexp_like(data, 'ERROR|WARN|INFO|EXCEPTION|FATAL|DEBUG') limit 100;
```

**Example - ERROR, WARN, INFO, EXCEPTION, FATAL 또는 DEBUG에 대한 특정 인스턴스 로그 i-00b3c0a839ece0a9c 쿼리**  

```
SELECT "data",
        "$PATH" AS filepath
FROM "default"."myemrlogs"
WHERE regexp_like("$PATH",'i-00b3c0a839ece0a9c')
        AND regexp_like("$PATH",'state')
        AND regexp_like(data, 'ERROR|WARN|INFO|EXCEPTION|FATAL|DEBUG') limit 100;
```

**Example - ERROR, WARN, INFO, EXCEPTION, FATAL 또는 DEBUG에 대한 Presto 애플리케이션 로그 쿼리**  

```
SELECT "data",
        "$PATH" AS filepath
FROM "default"."myemrlogs"
WHERE regexp_like("$PATH",'presto')
        AND regexp_like(data, 'ERROR|WARN|INFO|EXCEPTION|FATAL|DEBUG') limit 100;
```

**Example - ERROR, WARN, INFO, EXCEPTION, FATAL 또는 DEBUG에 대한 Namenode 애플리케이션 로그 쿼리**  

```
SELECT "data",
        "$PATH" AS filepath
FROM "default"."myemrlogs"
WHERE regexp_like("$PATH",'namenode')
        AND regexp_like(data, 'ERROR|WARN|INFO|EXCEPTION|FATAL|DEBUG') limit 100;
```

**Example - ERROR, WARN, INFO, EXCEPTION, FATAL 또는 DEBUG에 대해 날짜 및 시간별 모든 로그 쿼리**  

```
SELECT distinct("$PATH") AS filepath
FROM "default"."myemrlogs"
WHERE regexp_like("$PATH",'2019-07-23-10')
        AND regexp_like(data, 'ERROR|WARN|INFO|EXCEPTION|FATAL|DEBUG') limit 100;
```

# Amazon EMR 로그를 기반으로 분할된 테이블 생성 및 쿼리
<a name="emr-create-table-partitioned"></a>

이러한 예제에서는 동일한 로그 위치를 사용하여 Athena 테이블을 생성하지만 테이블은 분할되고 각 로그 위치에 대해 파티션이 생성됩니다. 자세한 내용은 [데이터 파티셔닝](partitions.md) 단원을 참조하세요.

다음 쿼리는 `mypartitionedemrlogs`라는 분할된 테이블을 생성합니다.

```
CREATE EXTERNAL TABLE `mypartitionedemrlogs`(
  `data` string COMMENT 'from deserializer')
 partitioned by (logtype string)
ROW FORMAT DELIMITED  
FIELDS TERMINATED BY '|'
LINES TERMINATED BY '\n'
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6'
```

다음 쿼리 문은 Amazon EMR이 Amazon S3에서 생성하는 다양한 로그 유형에 대한 하위 디렉터리를 기반으로 테이블 파티션을 생성합니다.

```
ALTER TABLE mypartitionedemrlogs ADD
     PARTITION (logtype='containers')
     LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/containers/'
```

```
ALTER TABLE mypartitionedemrlogs ADD
     PARTITION (logtype='hadoop-mapreduce')
     LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/hadoop-mapreduce/'
```

```
ALTER TABLE mypartitionedemrlogs ADD
     PARTITION (logtype='hadoop-state-pusher')
     LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/hadoop-state-pusher/'
```

```
ALTER TABLE mypartitionedemrlogs ADD
     PARTITION (logtype='node')
     LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/node/'
```

```
ALTER TABLE mypartitionedemrlogs ADD
     PARTITION (logtype='steps')
     LOCATION 's3://aws-logs-123456789012-us-west-2/elasticmapreduce/j-2ABCDE34F5GH6/steps/'
```

파티션을 생성한 후 테이블에서 `SHOW PARTITIONS` 쿼리를 실행하여 다음 사항을 확인할 수 있습니다.

```
SHOW PARTITIONS mypartitionedemrlogs;
```

## 예제 쿼리
<a name="emr-example-queries-partitioned"></a>

다음 예제에서는 특정 로그 항목에 대한 쿼리가 위 예제에서 생성된 테이블 및 파티션을 사용한다는 것을 보여줍니다.

**Example - ERROR 또는 WARN에 대한 컨테이너 파티션의 애플리케이션 application\$11561661818238\$10002 로그 쿼리**  

```
SELECT data,
        "$PATH"
FROM "default"."mypartitionedemrlogs"
WHERE logtype='containers'
        AND regexp_like("$PATH",'application_1561661818238_0002')
        AND regexp_like(data, 'ERROR|WARN') limit 100;
```

**Example - 작업 job\$11561661818238\$10004 및 Failed Reduces에 대한 hadoop-Mapreduce 파티션 쿼리**  

```
SELECT data,
        "$PATH"
FROM "default"."mypartitionedemrlogs"
WHERE logtype='hadoop-mapreduce'
        AND regexp_like(data,'job_1561661818238_0004|Failed Reduces') limit 100;
```

**Example - 쿼리 ID 056e0609-33e1-4611-956c-7a31b42d2663에 대한 노드 파티션의 Hive 로그 쿼리**  

```
SELECT data,
        "$PATH"
FROM "default"."mypartitionedemrlogs"
WHERE logtype='node'
        AND regexp_like("$PATH",'hive')
        AND regexp_like(data,'056e0609-33e1-4611-956c-7a31b42d2663') limit 100;
```

**Example - 애플리케이션 1567660019320\$10001\$101\$1000001에 대한 노드 파티션의 resourcemanager 로그 쿼리**  

```
SELECT data,
        "$PATH"
FROM "default"."mypartitionedemrlogs"
WHERE logtype='node'
        AND regexp_like(data,'resourcemanager')
        AND regexp_like(data,'1567660019320_0001_01_000001') limit 100
```

# AWS Global Accelerator 흐름 로그 쿼리
<a name="querying-global-accelerator-flow-logs"></a>

AWS Global Accelerator를 사용하면 AWS 글로벌 네트워크를 통해 네트워크 트래픽을 최적의 엔드포인트로 보내는 액셀러레이터를 생성할 수 있습니다. Global Accelerator에 대한 자세한 내용은 [AWS Global Accelerator란 무엇인가요?](https://docs.aws.amazon.com/global-accelerator/latest/dg/what-is-global-accelerator.html)를 참조하세요.

Global Accelerator 흐름 로그를 사용하면 액셀러레이터의 네트워크 인터페이스에서 송수신되는 IP 주소 트래픽에 대한 정보를 캡처할 수 있습니다. 데이터를 검색하고 확인할 수 있는 흐름 로그 데이터가 Amazon S3에 게시됩니다. 자세한 내용은 [AWS Global Accelerator의 흐름 로그](https://docs.aws.amazon.com/global-accelerator/latest/dg/monitoring-global-accelerator.flow-logs.html)를 참조하세요.

Athena를 사용하여 Amazon S3에서 해당 위치를 지정하는 테이블을 만들어 Global Accelerator 흐름 로그를 쿼리할 수 있습니다.

**Global Accelerator 흐름 로그에 대한 테이블을 생성하려면**

1. 다음 DDL 문을 복사하여 Athena 콘솔에 붙여 넣습니다. 이 쿼리는 *ROW FORMAT DELIMITED*를 지정하고 [SerDe](serde-reference.md)를 지정하지 않습니다(즉, [`LazySimpleSerDe`](lazy-simple-serde.md) 사용). 이 쿼리에서 필드는 공백으로 끝납니다.

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS aga_flow_logs (
     version string,
     account string,
     acceleratorid string,
     clientip string,
     clientport int,
     gip string,
     gipport int,
     endpointip string,
     endpointport int,
     protocol string,
     ipaddresstype string,
     numpackets bigint,
     numbytes int,
     starttime int,
     endtime int,
     action string,
     logstatus string,
     agasourceip string,
     agasourceport int,
     endpointregion string,
     agaregion string,
     direction string,
     vpc_id string,
     reject_reason string
   )
   PARTITIONED BY (dt string)
   ROW FORMAT DELIMITED
   FIELDS TERMINATED BY ' '
   LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/account_id/globalaccelerator/region/'
   TBLPROPERTIES ("skip.header.line.count"="1");
   ```

1. 로그 데이터가 포함된 Amazon S3 버킷을 가리키도록 `LOCATION` 값을 수정합니다.

   ```
   's3://amzn-s3-demo-bucket/prefix/AWSLogs/account_id/globalaccelerator/region_code/'
   ```

1. Athena 콘솔에서 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 데이터를 쿼리에 사용할 수 있도록 `aga_flow_logs` 테이블을 등록합니다.

1. 다음 샘플 쿼리와 같이 데이터를 읽을 수 있도록 파티션을 생성합니다. 이 쿼리는 지정한 날짜에 대한 단일 파티션을 생성합니다. 날짜와 위치의 자리 표시자를 교체합니다.

   ```
   ALTER TABLE aga_flow_logs
   ADD PARTITION (dt='YYYY-MM-dd')
   LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/account_id/globalaccelerator/region_code/YYYY/MM/dd';
   ```

## AWS Global Accelerator 흐름 로그에 대한 쿼리 예제
<a name="querying-global-accelerator-flow-logs-examples"></a>

**Example - 특정 엣지 로케이션을 전달하는 요청 나열**  
다음 예제 쿼리는 LHR 엣지 로케이션을 전달한 요청을 나열합니다. `LIMIT` 연산자를 사용하여 한 번에 쿼리할 로그 수를 제한합니다.  

```
SELECT 
  clientip, 
  agaregion, 
  protocol, 
  action 
FROM 
  aga_flow_logs 
WHERE 
  agaregion LIKE 'LHR%' 
LIMIT 
  100;
```

**Example - 가장 많은 HTTPS 요청을 수신하는 엔드포인트 IP 주소 나열**  
가장 많은 수의 HTTPS 요청을 수신하는 엔드포인트 IP 주소를 확인하려면 다음 쿼리를 사용합니다. 이 쿼리는 HTTPS 포트 443에서 수신한 패킷 수를 계산하고, 대상 IP 주소별로 그룹화한 다음, 상위 10개 IP 주소를 반환합니다.  

```
SELECT 
  SUM(numpackets) AS packetcount, 
  endpointip 
FROM 
  aga_flow_logs 
WHERE 
  endpointport = 443 
GROUP BY 
  endpointip 
ORDER BY 
  packetcount DESC 
LIMIT 
  10;
```

# Amazon GuardDuty 조사 결과 쿼리
<a name="querying-guardduty"></a>

[Amazon GuardDuty](https://aws.amazon.com/guardduty/)는 AWS 환경에서 예상치 못한 활동, 잠재적으로 승인되지 않은 활동 또는 악의적 활동을 식별할 수 있도록 지원하는 보안 모니터링 서비스입니다. GuardDuty는 예상치 못한 활동 및 잠재적으로 악의적인 활동을 탐지할 경우 보안 [결과](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_findings.html)를 생성합니다. 사용자는 이 결과를 Amazon S3에 내보내어 저장하고 분석할 수 있습니다. 또한 결과를 Amazon S3에 내보낸 후 Athena를 사용하여 결과를 쿼리할 수 있습니다. 이 문서에서는 Athena에서 GuardDuty 결과에 대한 테이블을 만들고 쿼리하는 방법을 보여 줍니다.

Amazon GuardDuty에 대한 자세한 내용은 [Amazon GuardDuty 사용 설명서](https://docs.aws.amazon.com/guardduty/latest/ug/)를 참조하세요.

## 사전 조건
<a name="querying-guardduty-prerequisites"></a>
+ 결과를 Amazon S3에 내보내는 GuardDuty 기능을 활성화합니다. 실행 단계는 Amazon GuardDuty 사용 설명서의 [결과 내보내기](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty_exportfindings.html)를 참조하세요.

## Athena에서 GuardDuty 조사 결과용 테이블 생성
<a name="querying-guardduty-creating-a-table-in-athena-for-guardduty-findings"></a>

Athena에서 GuardDuty 결과를 쿼리하려면 해당 결과에 대한 테이블을 생성해야 합니다.

**Athena에서 GuardDuty 결과에 대한 테이블을 생성하려면**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home)에서 Athena 콘솔을 엽니다.

1. 다음 DDL 문을 Athena 콘솔에 붙여 넣습니다. Amazon S3의 GuardDuty 결과를 가리키도록 `LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/account-id/GuardDuty/'`의 값을 수정합니다.

   ```
   CREATE EXTERNAL TABLE `gd_logs` (
     `schemaversion` string,
     `accountid` string,
     `region` string,
     `partition` string,
     `id` string,
     `arn` string,
     `type` string,
     `resource` string,
     `service` string,
     `severity` string,
     `createdat` string,
     `updatedat` string,
     `title` string,
     `description` string)
   ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
    LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/account-id/GuardDuty/'
    TBLPROPERTIES ('has_encrypted_data'='true')
   ```
**참고**  
SerDe는 각 JSON 문서가 레코드의 필드를 구분하는 줄 종료 문자가 없는 한 줄의 텍스트에 있을 것으로 예상합니다. JSON 텍스트가 가독성 좋게 꾸민 형식이면 테이블을 만든 후 쿼리하려고 할 때 HIVE\$1CURSOR\$1ERROR: 행이 유효한 JSON 객체가 아님(HIVE\$1CURSOR\$1ERROR: Row is not a valid JSON Object) 또는 HIVE\$1CURSOR\$1ERROR: JsonParseException: 예기치 않은 입력 종료: OBJECT의 닫기 마커 필요(HIVE\$1CURSOR\$1ERROR: JsonParseException: Unexpected end-of-input: expected close marker for OBJECT) 같은 오류 메시지가 나타날 수 있습니다. 자세한 내용은 GitHub의 OpenX SerDe 문서에서 [JSON 데이터 파일](https://github.com/rcongiu/Hive-JSON-Serde#json-data-files)을 참조하세요.

1. Athena 콘솔에서 `gd_logs` 테이블을 등록하는 쿼리를 실행합니다. 이 쿼리가 완료되면 결과를 Athena에서 쿼리할 수 있습니다.

## 쿼리 예제
<a name="querying-guardduty-examples"></a>

다음 예제에서는 Athena에서 GuardDuty 결과를 쿼리하는 방법을 보여 줍니다.

**Example - DNS 데이터 유출**  
다음 쿼리는 DNS 쿼리를 통해 데이터를 유출할 수 있는 Amazon EC2 인스턴스에 대한 정보를 반환합니다.  

```
SELECT
    title,
    severity,
    type,
    id AS FindingID,
    accountid,
    region,
    createdat,
    updatedat,
    json_extract_scalar(service, '$.count') AS Count,
    json_extract_scalar(resource, '$.instancedetails.instanceid') AS InstanceID,
    json_extract_scalar(service, '$.action.actiontype') AS DNS_ActionType,
    json_extract_scalar(service, '$.action.dnsrequestaction.domain') AS DomainName,
    json_extract_scalar(service, '$.action.dnsrequestaction.protocol') AS protocol,
    json_extract_scalar(service, '$.action.dnsrequestaction.blocked') AS blocked
FROM gd_logs
WHERE type = 'Trojan:EC2/DNSDataExfiltration'
ORDER BY severity DESC
```

**Example - 무단 IAM 사용자 액세스**  
다음 쿼리는 모든 리전에서 IAM 보안 주체에 대한 모든 `UnauthorizedAccess:IAMUser` 결과 유형을 반환합니다.  

```
SELECT title,
         severity,
         type,
         id,
         accountid,
         region,
         createdat,
         updatedat,
         json_extract_scalar(service, '$.count') AS Count, 
         json_extract_scalar(resource, '$.accesskeydetails.username') AS IAMPrincipal, 
         json_extract_scalar(service,'$.action.awsapicallaction.api') AS APIActionCalled
FROM gd_logs
WHERE type LIKE '%UnauthorizedAccess:IAMUser%' 
ORDER BY severity desc;
```

## GuardDuty 결과 쿼리 팁
<a name="querying-guardduty-tips"></a>

쿼리를 작성할 때 다음 사항에 유의하세요.
+ 중첩된 JSON 필드에서 데이터를 추출하려면 Presto `json_extract` 또는 `json_extract_scalar` 함수를 사용합니다. 자세한 내용은 [문자열에서 JSON 데이터 추출](extracting-data-from-JSON.md) 단원을 참조하세요.
+ JSON 필드의 모든 문자가 소문자인지 확인합니다.
+  쿼리 결과 다운로드에 대한 자세한 내용은 [Athena 콘솔을 사용하여 쿼리 결과 파일 다운로드](saving-query-results.md) 단원을 참조하세요.

# AWS Network Firewall 로그 쿼리
<a name="querying-network-firewall-logs"></a>

AWS Network Firewall는 Amazon Virtual Private Cloud 인스턴스를 위한 필수 네트워크 보안을 배포할 수 있는 관리형 서비스입니다. AWS Network Firewall는 AWS Firewall Manager와 함께 작동하기 때문에 AWS Network Firewall 규칙에 기반해 정책을 빌드한 다음 중앙에서 이러한 정책을 VPC 및 계정 전반에 적용할 수 있습니다. AWS Network Firewall에 대한 자세한 내용은 [AWS Network Firewall](https://aws.amazon.com/network-firewall/) 단원을 참조하세요.

방화벽의 상태 저장 규칙 엔진에 전달하는 트래픽에 대해 AWS Network Firewall 로깅을 구성할 수 있습니다. 로깅은 상태 저장 엔진이 패킷을 받은 시간, 패킷에 대한 상세 정보, 패킷에 대해 수행된 상태 저장 규칙 동작을 비롯해 네트워크 트래픽에 대한 자세한 정보를 제공합니다. 로그는 구성한 로그 대상에 게시되며, 여기서 로그를 검색하고 확인할 수 있습니다. 자세한 내용은 *AWS Network Firewall 개발자 안내서*의 [AWS Network Firewall에서 네트워크 트리팩 로깅](https://docs.aws.amazon.com/network-firewall/latest/developerguide/firewall-logging.html)을 참조하세요.

**Topics**
+ [알림 로그용 테이블 생성 및 쿼리](querying-network-firewall-logs-sample-alert-logs-table.md)
+ [넷플로우 로그용 테이블 생성 및 쿼리](querying-network-firewall-logs-sample-netflow-logs-table.md)

# 알림 로그용 테이블 생성 및 쿼리
<a name="querying-network-firewall-logs-sample-alert-logs-table"></a>

1. 다음 샘플 DDL 문을 알림 로그의 구조에 맞게 수정하세요. 최신 버전 로그의 열을 포함하도록 문을 업데이트해야 할 수 있습니다. 자세한 내용은 *AWS Network Firewall 개발자 안내서*의 [방화벽 로그의 내용](https://docs.aws.amazon.com/network-firewall/latest/developerguide/firewall-logging.html#firewall-logging-contents)을 참조하세요.

   ```
   CREATE EXTERNAL TABLE network_firewall_alert_logs (
     firewall_name string,
     availability_zone string,
     event_timestamp string,
     event struct<
       timestamp:string,
       flow_id:bigint,
       event_type:string,
       src_ip:string,
       src_port:int,
       dest_ip:string,
       dest_port:int,
       proto:string,
       app_proto:string,
       sni:string,
       tls_inspected:boolean,
       tls_error:struct<
         error_message:string>,
       revocation_check:struct<
         leaf_cert_fpr:string,
         status:string,
         action:string>,
       alert:struct<
         alert_id:string,
         alert_type:string,
         action:string,
         signature_id:int,
         rev:int,
         signature:string,
         category:string,
         severity:int,
         rule_name:string,
         alert_name:string,
         alert_severity:string,
         alert_description:string,
         file_name:string,
         file_hash:string,
         packet_capture:string,
         reference_links:array<string>
       >, 
       src_country:string, 
       dest_country:string, 
       src_hostname:string, 
       dest_hostname:string, 
       user_agent:string, 
       url:string
      >
   )
    ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
    LOCATION 's3://amzn-s3-demo-bucket/path_to_alert_logs_folder/';
   ```

1. `LOCATION` 절을 수정하여 Amazon S3의 로그 폴더를 지정합니다.

1. Athena 쿼리 편집기에서 사용자의 `CREATE TABLE` 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `network_firewall_alert_logs` 테이블을 등록하여 쿼리 준비를 나타내는 데이터를 만듭니다.

## 예제 쿼리
<a name="querying-network-firewall-logs-alert-log-sample-query"></a>

이 섹션의 샘플 알림 로그 쿼리는 TLS 검사가 수행된 이벤트 중 심각도 수준이 2 이상인 알림이 있는 이벤트를 필터링합니다.

쿼리는 별칭을 사용하여 해당 열이 속한 `struct`를 보여주는 출력 열 제목을 생성합니다. 예를 들어 `event.alert.category` 필드의 열 제목은 `event_alert_category`이며 그냥 `category`가 아닙니다. 열 이름을 추가로 사용자 지정하려면 원하는 대로 별칭을 수정할 수 있습니다. 예를 들어 밑줄이나 기타 구분 기호를 사용하여 `struct` 이름과 필드 이름을 구분할 수 있습니다.

테이블 정의와 쿼리 결과에 표시할 필드를 기반으로 열 이름과 `struct` 참조를 수정해야 합니다.

```
SELECT 
  firewall_name,
  availability_zone,
  event_timestamp,
  event.timestamp AS event_timestamp,
  event.flow_id AS event_flow_id,
  event.event_type AS event_type,
  event.src_ip AS event_src_ip,
  event.src_port AS event_src_port,
  event.dest_ip AS event_dest_ip,
  event.dest_port AS event_dest_port,
  event.proto AS event_protol,
  event.app_proto AS event_app_proto,
  event.sni AS event_sni,
  event.tls_inspected AS event_tls_inspected,
  event.tls_error.error_message AS event_tls_error_message,
  event.revocation_check.leaf_cert_fpr AS event_revocation_leaf_cert,
  event.revocation_check.status AS event_revocation_check_status,
  event.revocation_check.action AS event_revocation_check_action,
  event.alert.alert_id AS event_alert_alert_id,
  event.alert.alert_type AS event_alert_alert_type,
  event.alert.action AS event_alert_action,
  event.alert.signature_id AS event_alert_signature_id,
  event.alert.rev AS event_alert_rev,
  event.alert.signature AS event_alert_signature,
  event.alert.category AS event_alert_category,
  event.alert.severity AS event_alert_severity,
  event.alert.rule_name AS event_alert_rule_name,
  event.alert.alert_name AS event_alert_alert_name,
  event.alert.alert_severity AS event_alert_alert_severity,
  event.alert.alert_description AS event_alert_alert_description,
  event.alert.file_name AS event_alert_file_name,
  event.alert.file_hash AS event_alert_file_hash,
  event.alert.packet_capture AS event_alert_packet_capture,
  event.alert.reference_links AS event_alert_reference_links,
  event.src_country AS event_src_country,
  event.dest_country AS event_dest_country,
  event.src_hostname AS event_src_hostname,
  event.dest_hostname AS event_dest_hostname,
  event.user_agent AS event_user_agent,
  event.url AS event_url
FROM 
  network_firewall_alert_logs 
WHERE 
  event.alert.severity >= 2
  AND event.tls_inspected = true 
LIMIT 10;
```

# 넷플로우 로그용 테이블 생성 및 쿼리
<a name="querying-network-firewall-logs-sample-netflow-logs-table"></a>

1. 다음 샘플 DDL 문을 넷플로우 로그의 구조에 맞게 수정하세요. 최신 버전 로그의 열을 포함하도록 문을 업데이트해야 할 수 있습니다. 자세한 내용은 *AWS Network Firewall 개발자 안내서*의 [방화벽 로그의 내용](https://docs.aws.amazon.com/network-firewall/latest/developerguide/firewall-logging.html#firewall-logging-contents)을 참조하세요.

   ```
   CREATE EXTERNAL TABLE network_firewall_netflow_logs (
     firewall_name string,
     availability_zone string,
     event_timestamp string,
     event struct<
       timestamp:string,
       flow_id:bigint,
       event_type:string,
       src_ip:string,
       src_port:int,
       dest_ip:string,
       dest_port:int,
       proto:string,
       app_proto:string,
       tls_inspected:boolean,
       netflow:struct<
         pkts:int,
         bytes:bigint,
         start:string,
         `end`:string,
         age:int,
         min_ttl:int,
         max_ttl:int,
         tcp_flags:struct<
           syn:boolean,
           fin:boolean,
           rst:boolean,
           psh:boolean,
           ack:boolean,
           urg:boolean
           >
         >
       >
   )
   ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe' 
   LOCATION 's3://amzn-s3-demo-bucket/path_to_netflow_logs_folder/';
   ```

1. `LOCATION` 절을 수정하여 Amazon S3의 로그 폴더를 지정합니다.

1. Athena 쿼리 편집기에서 `CREATE TABLE` 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `network_firewall_netflow_logs` 테이블을 등록하여 쿼리 준비를 나타내는 데이터를 만듭니다.

## 예제 쿼리
<a name="querying-network-firewall-logs-netflow-log-sample-query"></a>

이 섹션의 샘플 넷플로우 로그 쿼리는 TLS 검사가 수행된 이벤트를 필터링합니다.

쿼리는 별칭을 사용하여 해당 열이 속한 `struct`를 보여주는 출력 열 제목을 생성합니다. 예를 들어 `event.netflow.bytes` 필드의 열 제목은 `event_netflow_bytes`이며 그냥 `bytes`가 아닙니다. 열 이름을 추가로 사용자 지정하려면 원하는 대로 별칭을 수정할 수 있습니다. 예를 들어 밑줄이나 기타 구분 기호를 사용하여 `struct` 이름과 필드 이름을 구분할 수 있습니다.

테이블 정의와 쿼리 결과에 표시할 필드를 기반으로 열 이름과 `struct` 참조를 수정해야 합니다.

```
SELECT
  event.src_ip AS event_src_ip,
  event.dest_ip AS event_dest_ip,
  event.proto AS event_proto,
  event.app_proto AS event_app_proto,
  event.tls_inspected AS event_tls_inspected,
  event.netflow.pkts AS event_netflow_pkts,
  event.netflow.bytes AS event_netflow_bytes,
  event.netflow.tcp_flags.syn AS event_netflow_tcp_flags_syn 
FROM network_firewall_netflow_logs 
WHERE event.tls_inspected = true
```

# Network Load Balancer 로그 쿼리
<a name="networkloadbalancer-classic-logs"></a>

Athena를 사용하여 Network Load Balancer의 로그를 분석하고 처리합니다. 이러한 로그는 Network Load Balancer로 전송된 TLS(전송 계층 보안) 요청에 대한 세부 정보를 수신합니다. 이러한 액세스 로그를 사용하여 트래픽 패턴을 분석하고 문제를 해결할 수 있습니다.

Network Load Balancer 액세스 로그를 분석하기 전에 대상 Amazon S3 버킷에 저장하기 위한 로그를 활성화하고 구성합니다. 자세한 내용과 각 Network Load Balancer 액세스 로그 항목에 대한 정보는 [Network Load Balancer의 액세스 로그](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-access-logs.html)를 참조하세요.

**Network Load Balancer 로그에 대한 테이블을 생성하려면**

1. 다음 DDL 문을 복사하여 Athena 콘솔에 붙여 넣습니다. Network Load Balancer 로그 레코드의 [구문](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-access-logs.html#access-log-file-format)을 검사합니다. 필요에 따라 문을 업데이트하여 로그 레코드에 해당하는 열과 정규식을 포함합니다.

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS nlb_tls_logs (
               type string,
               version string,
               time string,
               elb string,
               listener_id string,
               client_ip string,
               client_port int,
               target_ip string,
               target_port int,
               tcp_connection_time_ms double,
               tls_handshake_time_ms double,
               received_bytes bigint,
               sent_bytes bigint,
               incoming_tls_alert int,
               cert_arn string,
               certificate_serial string,
               tls_cipher_suite string,
               tls_protocol_version string,
               tls_named_group string,
               domain_name string,
               alpn_fe_protocol string,
               alpn_be_protocol string,
               alpn_client_preference_list string,
               tls_connection_creation_time string
               )
               ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.RegexSerDe'
               WITH SERDEPROPERTIES (
               'serialization.format' = '1',
               'input.regex' = 
               '([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*):([0-9]*) ([^ ]*):([0-9]*) ([-.0-9]*) ([-.0-9]*) ([-0-9]*) ([-0-9]*) ([-0-9]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ?([^ ]*)?( .*)?'
               )
               LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/AWS_account_ID/elasticloadbalancing/region';
   ```

1. `LOCATION` Amazon S3 버킷을 수정하여 Network Load Balancer 로그의 대상을 지정합니다.

1. Athena 콘솔에서 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `nlb_tls_logs` 테이블을 등록하여 쿼리를 위한 데이터를 준비합니다.

## 쿼리 예제
<a name="query-nlb-example"></a>

인증서가 사용되는 횟수를 확인하려면 이 예제와 비슷한 방식으로 쿼리를 사용합니다.

```
SELECT count(*) AS 
         ct,
         cert_arn
FROM "nlb_tls_logs"
GROUP BY  cert_arn;
```

다음 쿼리는 1.3 이전의 TLS 버전을 사용하고 있는 사용자 수를 보여 줍니다.

```
SELECT tls_protocol_version,
         COUNT(tls_protocol_version) AS 
         num_connections,
         client_ip
FROM "nlb_tls_logs"
WHERE tls_protocol_version < 'tlsv13'
GROUP BY tls_protocol_version, client_ip;
```

다음 쿼리를 사용하여 TLS 핸드셰이크 시간이 오래 걸리는 연결을 식별합니다.

```
SELECT *
FROM "nlb_tls_logs"
ORDER BY  tls_handshake_time_ms DESC 
LIMIT 10;
```

다음 쿼리를 사용하여 지난 30일 동안 협상된 TLS 프로토콜 버전 및 암호 제품군을 식별하고 계산합니다.

```
SELECT tls_cipher_suite,
         tls_protocol_version,
         COUNT(*) AS ct
FROM "nlb_tls_logs"
WHERE from_iso8601_timestamp(time) > current_timestamp - interval '30' day
        AND NOT tls_protocol_version = '-'
GROUP BY tls_cipher_suite, tls_protocol_version
ORDER BY ct DESC;
```

# Amazon Route 53 Resolver 쿼리 로그 쿼리
<a name="querying-r53-resolver-logs"></a>

Amazon Route 53 Resolver 쿼리 로그에 대한 Athena 테이블을 생성하고 Athena에서 쿼리할 수 있습니다.

Route 53 Resolver 쿼리 로깅은 인바운드 해석기(resolver) 엔드포인트를 사용하는 온프레미스 리소스인 VPC 내의 리소스에 의해 수행된 DNS 쿼리, 재귀적 DNS 확인(recursive DNS resolution)을 위해 아웃바운드 해석기 엔드포인트를 사용하는 쿼리, 그리고 도메인 목록을 차단, 허용 또는 모니터링하기 위해 Route 53 Resolver DNS 방화벽 규칙을 사용하는 쿼리를 로그하기 위한 것입니다. Resolver 쿼리 로깅에 대한 자세한 내용은 *Amazon Route 53 개발자 안내서*의 [Resolver 쿼리 로깅](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resolver-query-logs.html)을 참조하세요. 로그의 각 필드에 대한 자세한 내용은 *Amazon Route 53 개발자 안내서*의 [Resolver 쿼리 로그에 표시되는 값](https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resolver-query-logs-format.html)을 참조하세요.

**Topics**
+ [Resolver 쿼리 로그용 테이블 생성](querying-r53-resolver-logs-creating-the-table.md)
+ [파티션 프로젝션 사용](querying-r53-resolver-logs-partitioning-example.md)
+ [예제 쿼리](querying-r53-resolver-logs-example-queries.md)

# Resolver 쿼리 로그용 테이블 생성
<a name="querying-r53-resolver-logs-creating-the-table"></a>

Athena 콘솔에서 쿼리 편집기를 사용하여 Route 53 Resolver 쿼리 로그에 대한 테이블을 만들고 쿼리할 수 있습니다.

**Route 53 Resolver 쿼리 로그에 대해 Athena 테이블을 만들고 쿼리하려면**

1. [https://console.aws.amazon.com/athena/](https://console.aws.amazon.com/athena/home)에서 Athena 콘솔을 엽니다.

1. Athena 쿼리 편집기에 다음 `CREATE TABLE` 문을 입력합니다. `LOCATION` 절의 값을 Amazon S3의 Resolver 로그 위치에 상응하는 값으로 바꿉니다.

   ```
   CREATE EXTERNAL TABLE r53_rlogs (
     version string,
     account_id string,
     region string,
     vpc_id string,
     query_timestamp string,
     query_name string,
     query_type string,
     query_class
       string,
     rcode string,
     answers array<
       struct<
         Rdata: string,
         Type: string,
         Class: string>
       >,
     srcaddr string,
     srcport int,
     transport string,
     srcids struct<
       instance: string,
       resolver_endpoint: string
       >,
     firewall_rule_action string,
     firewall_rule_group_id string,
     firewall_domain_list_id string
    )
        
   ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
   LOCATION 's3://amzn-s3-demo-bucket/AWSLogs/aws_account_id/vpcdnsquerylogs/{vpc-id}/'
   ```

   Resolver 쿼리 로그 데이터는 JSON 형식이기 때문에 CREATE TABLE 문은 [JSON SerDe 라이브러리](json-serde.md)를 사용하여 데이터를 분석합니다.
**참고**  
SerDe는 각 JSON 문서가 레코드의 필드를 구분하는 줄 종료 문자가 없는 한 줄의 텍스트에 있을 것으로 예상합니다. JSON 텍스트가 가독성 좋게 꾸민 형식이면 테이블을 만든 후 쿼리하려고 할 때 HIVE\$1CURSOR\$1ERROR: 행이 유효한 JSON 객체가 아님(HIVE\$1CURSOR\$1ERROR: Row is not a valid JSON Object) 또는 HIVE\$1CURSOR\$1ERROR: JsonParseException: 예기치 않은 입력 종료: OBJECT의 닫기 마커 필요(HIVE\$1CURSOR\$1ERROR: JsonParseException: Unexpected end-of-input: expected close marker for OBJECT) 같은 오류 메시지가 나타날 수 있습니다. 자세한 내용은 GitHub의 OpenX SerDe 문서에서 [JSON 데이터 파일](https://github.com/rcongiu/Hive-JSON-Serde#json-data-files)을 참조하세요.

1. **쿼리 실행**을 선택합니다. 이 문은 `r53_rlogs`라는 Athena 테이블을 만듭니다. 이 테이블의 열은 Resolver 로그 데이터의 각 필드를 나타냅니다.

1. Athena 콘솔 쿼리 편집기에서 다음 쿼리를 실행하여 테이블이 생성되었는지 확인합니다.

   ```
   SELECT * FROM "r53_rlogs" LIMIT 10
   ```

# 파티션 프로젝션 사용
<a name="querying-r53-resolver-logs-partitioning-example"></a>

다음 예제는 파티션 프로젝션을 사용하고 vpc와 날짜를 기준으로 파티셔닝된 Resolver 쿼리 로그에 대한 `CREATE TABLE` 문을 보여줍니다. 파티션 프로젝션에 대한 자세한 내용은 [Amazon Athena에서 파티션 프로젝션 사용](partition-projection.md) 단원을 참조하세요.

```
CREATE EXTERNAL TABLE r53_rlogs (
  version string,
  account_id string,
  region string,
  vpc_id string,
  query_timestamp string,
  query_name string,
  query_type string,
  query_class string,
  rcode string,
  answers array<
    struct<
      Rdata: string,
      Type: string,
      Class: string>
    >,
  srcaddr string,
  srcport int,
  transport string,
  srcids struct<
    instance: string,
    resolver_endpoint: string
    >,
  firewall_rule_action string,
  firewall_rule_group_id string,
  firewall_domain_list_id string
)
PARTITIONED BY (
`date` string,
`vpc` string
)
ROW FORMAT SERDE      'org.openx.data.jsonserde.JsonSerDe'
STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
OUTPUTFORMAT          'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION              's3://amzn-s3-demo-bucket/route53-query-logging/AWSLogs/aws_account_id/vpcdnsquerylogs/'
TBLPROPERTIES(
'projection.enabled' = 'true',
'projection.vpc.type' = 'enum',
'projection.vpc.values' = 'vpc-6446ae02',
'projection.date.type' = 'date',
'projection.date.range' = '2023/06/26,NOW',
'projection.date.format' = 'yyyy/MM/dd',
'projection.date.interval' = '1',
'projection.date.interval.unit' = 'DAYS',
'storage.location.template' = 's3://amzn-s3-demo-bucket/route53-query-logging/AWSLogs/aws_account_id/vpcdnsquerylogs/${vpc}/${date}/'
)
```

# 예제 쿼리
<a name="querying-r53-resolver-logs-example-queries"></a>

다음 예제는 Athena에서 Resolver 쿼리 로그에 대해 수행할 수 있는 몇 가지 쿼리를 보여 줍니다.

## 예제 1 - query\$1timestamp의 내림차순으로 로그 쿼리
<a name="querying-r53-resolver-logs-example-1-query-logs-in-descending-query_timestamp-order"></a>

다음 쿼리는 `query_timestamp`의 내림차순으로 로그 결과를 표시합니다.

```
SELECT * FROM "r53_rlogs"
ORDER BY query_timestamp DESC
```

## 예제 2 - 지정된 시작 및 종료 시간 내에 로그 쿼리
<a name="querying-r53-resolver-logs-example-2-query-logs-within-specified-start-and-end-times"></a>

다음 쿼리는 2020년 9월 24일 자정과 오전 8시 사이의 로그를 쿼리합니다. 자신의 필요에 따라 시작 시간과 종료 시간을 대체합니다.

```
SELECT query_timestamp, srcids.instance, srcaddr, srcport, query_name, rcode
FROM "r53_rlogs"
WHERE (parse_datetime(query_timestamp,'yyyy-MM-dd''T''HH:mm:ss''Z')
     BETWEEN parse_datetime('2020-09-24-00:00:00','yyyy-MM-dd-HH:mm:ss') 
     AND parse_datetime('2020-09-24-00:08:00','yyyy-MM-dd-HH:mm:ss'))
ORDER BY query_timestamp DESC
```

## 예제 3 - 지정된 DNS 쿼리 이름 패턴을 기반으로 로그 쿼리
<a name="querying-r53-resolver-logs-example-3-query-logs-based-on-a-specified-dns-query-name-pattern"></a>

다음 쿼리는 쿼리 이름에 “example.com” 문자열을 포함한 레코드를 선택합니다.

```
SELECT query_timestamp, srcids.instance, srcaddr, srcport, query_name, rcode, answers
FROM "r53_rlogs"
WHERE query_name LIKE '%example.com%'
ORDER BY query_timestamp DESC
```

## 예제 4 - 응답 없는 요청 로그 쿼리
<a name="querying-r53-resolver-logs-example-4-query-log-requests-with-no-answer"></a>

다음 쿼리는 응답이 없는 요청의 로그 항목을 선택합니다.

```
SELECT query_timestamp, srcids.instance, srcaddr, srcport, query_name, rcode, answers
FROM "r53_rlogs"
WHERE cardinality(answers) = 0
```

## 예제 5 - 특정 답변이 포함된 로그 쿼리
<a name="querying-r53-resolver-logs-example-5-query-logs-with-a-specific-answer"></a>

다음 쿼리는 `answer.Rdata` 값에 특정 IP 주소가 있는 로그를 보여 줍니다.

```
SELECT query_timestamp, srcids.instance, srcaddr, srcport, query_name, rcode, answer.Rdata
FROM "r53_rlogs"
CROSS JOIN UNNEST(r53_rlogs.answers) as st(answer)
WHERE answer.Rdata='203.0.113.16';
```

# Amazon SES 이벤트 로그 쿼리
<a name="querying-ses-logs"></a>

Amazon Athena를 사용하여 [Amazon Simple Email Service](https://aws.amazon.com/ses/)(Amazon SES) 이벤트 로그를 쿼리할 수 있습니다.

Amazon SES는 사용자의 이메일 주소와 도메인을 사용해 이메일을 보내고 받기 위한 경제적이고 편리한 방법을 제공하는 이메일 플랫폼입니다. 이벤트, 지표, 통계를 사용하여 세분화된 수준으로 Amazon SES 전송 활동을 모니터링할 수 있습니다.

정의한 특성에 따라 [Amazon CloudWatch](https://aws.amazon.com/cloudwatch/), [Amazon Data Firehose](https://aws.amazon.com/kinesis/data-firehose/) 또는 [Amazon Simple Notification Service](https://aws.amazon.com/sns/)에 Amazon SES 이벤트를 게시할 수 있습니다. Amazon S3에 정보를 저장한 이후 Amazon Athena Athena에서 쿼리할 수 있습니다.

[Amazon SES 이벤트 로그 데이터에서 뷰를 생성하고 중첩된 배열을 평면화하는 방법에 대한 단계를 비롯한 Amazon SES 로그용 Athena `CREATE TABLE` 문의 예시는 AWS 블로그 게시물 AWS 분석 서비스를 통한 Amazon SES 이벤트 데이터 분석](https://aws.amazon.com/blogs/messaging-and-targeting/analyzing-amazon-ses-event-data-with-aws-analytics-services/)의 “3단계: Amazon Athena를 사용하여 SES 이벤트 로그를 쿼리하기”를 참조하세요.

# Amazon VPC 흐름 로그 쿼리
<a name="vpc-flow-logs"></a>

Amazon Virtual Private Cloud 흐름 로그는 VPC의 네트워크 인터페이스에서 송수신되는 IP 트래픽에 대한 정보를 수집합니다. 로그를 사용하여 네트워크 트래픽 패턴을 조사하고 VPC 네트워크에서 위협 및 위험을 식별하세요.

Amazon VPC 흐름 로그를 쿼리하려는 경우 다음 두 가지 옵션이 있습니다.

****
+ **Amazon VPC 콘솔** - Amazon VPC 콘솔의 Athena 통합 기능을 사용하여 분할로 Athena 데이터베이스, 작업 그룹 및 흐름 로그 테이블을 생성하는 CloudFormation 템플릿을 생성합니다. 또한 템플릿에서는 VPC 통해 흐르는 트래픽에 대한 인사이트를 얻기 위해 사용할 수 있는 [미리 정의된 흐름 로그 쿼리](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs-athena.html#predefined-queries) 집합을 생성할 수 있습니다.

  자세한 내용은 *Amazon VPC 사용 설명서*의 [Amazon Athena를 사용하여 흐름 로그 쿼리](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs-athena.html)를 참조하세요.
+ **Amazon Athena 콘솔** - Athena 콘솔에서 직접 테이블과 쿼리를 생성합니다. 자세히 알아보려면 이 페이지를 계속 읽어 보세요.

Athena에서 로그 쿼리를 시작하기 전에 [VPC 흐름 로그를 활성화](https://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/flow-logs.html)하고 Amazon S3 버킷에 저장하도록 구성합니다. 로그를 생성한 후 몇 분 동안 실행하여 일부 데이터를 수집합니다. 로그는 GZIP 압축 형식으로 생성되어 Athena를 이용해 직접 쿼리할 수 있습니다.

VPC 흐름 로그를 생성하는 경우 흐름 로그에서 반환할 필드와 해당 필드가 나타나는 순서를 지정할 때 사용자 지정 형식을 사용할 수 있습니다. 흐롬 로그 레코드에 대한 자세한 내용은 *Amazon VPC 사용 설명서*의 [흐름 로그 레코드](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-log-records)를 참조하세요.

## 고려 사항 및 제한 사항
<a name="vpc-flow-logs-common-considerations"></a>

Athena에서 Amazon VPC 흐름 로그용 테이블을 생성할 때 다음 사항을 기억하세요.
+ 기본적으로 Athena에서 Parquet은 이름으로 열에 액세스합니다. 자세한 내용은 [스키마 업데이트 처리](handling-schema-updates-chapter.md) 섹션을 참조하세요.
+ Athena의 열 이름에 대한 흐름 로그 레코드의 이름을 사용합니다. Athena 스키마의 열 이름은 Amazon VPC 흐름 로그의 필드 이름과 정확히 일치해야 하며 다음과 같은 차이점이 있습니다.
  + Amazon VPC 로그 필드 이름의 하이픈을 Athena 열 이름의 밑줄로 바꿉니다. Athena에서 데이터베이스 이름, 테이블 이름 및 열 이름에 사용할 수 있는 문자에 대한 자세한 내용은 [이름 데이터베이스, 테이블 및 열](tables-databases-columns-names.md) 섹션을 참조하세요.
  + Athena의 [예약 키워드](reserved-words.md)인 흐름 로그 레코드 이름을 백틱(backtick)으로 둘러싸서 이스케이프합니다.
+ VPC 흐름 로그는 AWS 계정에 특정적입니다. 로그 파일을 Amazon S3에 게시할 때 Amazon VPC가 Amazon S3에 생성하는 경로에는 흐름 로그를 생성하는 데 사용된 AWS 계정 ID가 포함됩니다. 자세한 내용은 *Amazon VPC 사용 설명서*의 [Amazon S3에 흐름 로그 게시](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs-s3.html)를 참조하세요.

**Topics**
+ [고려 사항 및 제한 사항](#vpc-flow-logs-common-considerations)
+ [Amazon VPC 흐름 로그용 테이블 생성 및 쿼리](vpc-flow-logs-create-table-statement.md)
+ [Apache Parquet 형식으로 흐름 로그용 테이블 생성](vpc-flow-logs-parquet.md)
+ [파티션 프로젝션을 사용하여 Amazon VPC 흐름 로그용 테이블 생성 및 쿼리](vpc-flow-logs-partition-projection.md)
+ [파티션 프로젝션을 사용하여 Apache Parquet 형식으로 흐름 로그용 테이블 생성](vpc-flow-logs-partition-projection-parquet-example.md)
+ [추가 리소스](query-examples-vpc-logs-additional-resources.md)

# Amazon VPC 흐름 로그용 테이블 생성 및 쿼리
<a name="vpc-flow-logs-create-table-statement"></a>

다음은 VPC 흐름 로그에 대한 Amazon VPC 테이블을 생성하는 절차입니다. 사용자 지정 형식을 사용하여 흐름 로그를 생성하는 경우 흐름 로그를 생성할 때 지정한 필드와 일치하는 필드가 해당 필드를 지정할 때와 동일한 순서로 포함되는 테이블을 생성합니다.

**Amazon VPC 흐름 로그에 대한 Athena 테이블 생성**

1. [고려 사항 및 제한 사항](vpc-flow-logs.md#vpc-flow-logs-common-considerations) 섹션의 다음 지침에 따라 Athena 콘솔 쿼리 편집기에 다음과 같은 DDL 문을 입력합니다. 다음 문 샘플은 [흐름 로그 레코드](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-log-records)에 설명된 대로 Amazon VPC 흐름 로그 버전 2 \$1 5의 열을 갖는 테이블을 생성합니다. 다른 열 집합이나 열 순서를 사용하는 경우 그에 맞게 문을 수정합니다.

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS `vpc_flow_logs` (
     version int,
     account_id string,
     interface_id string,
     srcaddr string,
     dstaddr string,
     srcport int,
     dstport int,
     protocol bigint,
     packets bigint,
     bytes bigint,
     start bigint,
     `end` bigint,
     action string,
     log_status string,
     vpc_id string,
     subnet_id string,
     instance_id string,
     tcp_flags int,
     type string,
     pkt_srcaddr string,
     pkt_dstaddr string,
     region string,
     az_id string,
     sublocation_type string,
     sublocation_id string,
     pkt_src_aws_service string,
     pkt_dst_aws_service string,
     flow_direction string,
     traffic_path int
   )
   PARTITIONED BY (`date` date)
   ROW FORMAT DELIMITED
   FIELDS TERMINATED BY ' '
   LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/{account_id}/vpcflowlogs/{region_code}/'
   TBLPROPERTIES ("skip.header.line.count"="1");
   ```

   다음 사항에 주의하세요.
   + 이 쿼리는 `ROW FORMAT DELIMITED`를 지정하며 SerDe 지정은 생략합니다. 즉, 쿼리는 [CSV, TSV, 사용자 지정 구분 기호로 구분된 파일에 대한 Lazy Simple SerDe](lazy-simple-serde.md)을 사용합니다. 이 쿼리에서 필드는 공백으로 끝납니다.
   + `PARTITIONED BY` 절은 `date` 유형을 사용합니다. 따라서 쿼리에서 수학 연산자를 사용하여 특정 날짜보다 오래되었거나 최신인 항목을 선택할 수 있습니다.
**참고**  
`date`는 DDL 문에 예약된 키워드이므로 백틱 문자로 이스케이프됩니다. 자세한 내용은 [쿼리에서 예약어 이스케이프](reserved-words.md) 섹션을 참조하세요.
   + 다른 사용자 지정 형식을 사용하는 VPC 흐름 로그의 경우 흐름 로그를 생성할 때 지정한 필드와 일치하도록 필드를 수정합니다.

1. 로그 데이터가 포함된 Amazon S3 버킷을 가리키도록 `LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/{account_id}/vpcflowlogs/{region_code}/'`을 수정합니다.

1. Athena 콘솔에서 쿼리를 실행합니다. 쿼리가 완료된 후 Athena는 `vpc_flow_logs` 테이블을 등록하여 쿼리를 실행할 수 있도록 데이터를 준비합니다.

1. 다음 샘플 쿼리와 같이 데이터를 읽을 수 있도록 파티션을 생성합니다. 이 쿼리는 지정한 날짜에 대한 단일 파티션을 생성합니다. 필요하다면 날짜와 위치의 자리 표시자를 교체하세요.
**참고**  
이 쿼리는 사용자가 지정한 날짜에 대한 단일 파티션만 생성합니다. 프로세스를 자동화하려면 이 쿼리를 실행하고 `year/month/day`에 대해 이 방법으로 파티션을 생성하는 스크립트를 사용하거나 [파티션 프로젝션](vpc-flow-logs-partition-projection.md)을 지정하는 `CREATE TABLE` 문을 사용합니다.

   ```
   ALTER TABLE vpc_flow_logs
   ADD PARTITION (`date`='YYYY-MM-dd')
   LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/{account_id}/vpcflowlogs/{region_code}/YYYY/MM/dd';
   ```

## vpc\$1flow\$1logs 테이블에 대한 쿼리 예
<a name="query-examples-vpc-logs"></a>

Athena 콘솔의 쿼리 편집기를 사용하여 생성한 테이블에서 SQL 문을 실행합니다. 쿼리를 저장하거나 이전 쿼리를 보거나 쿼리 결과를 CSV 형식으로 다운로드할 수 있습니다. 다음 예에서는 `vpc_flow_logs`를 테이블의 이름으로 바꿉니다. 사용자의 요구 사항에 따라 열 값과 기타 변수를 수정합니다.

다음 예제 쿼리는 지정된 날짜에 대해 최대 100개의 흐름 로그를 나열합니다.

```
SELECT * 
FROM vpc_flow_logs 
WHERE date = DATE('2020-05-04') 
LIMIT 100;
```

다음 쿼리는 거절된 모든 TCP 연결을 나열하며 새로 생성한 날짜 파티션 열인 `date`를 이용해 이러한 이벤트가 발생한 요일을 추출합니다.

```
SELECT day_of_week(date) AS
  day,
  date,
  interface_id,
  srcaddr,
  action,
  protocol
FROM vpc_flow_logs
WHERE action = 'REJECT' AND protocol = 6
LIMIT 100;
```

어떤 서버가 가장 많은 수의 HTTPS 요청을 수신하는지 알아보려면 다음 쿼리를 사용합니다. 이 쿼리는 지난 주부터 HTTPS 포트 443에서 수신한 패킷 수를 계산하고, 대상 IP 주소별로 그룹화한 다음, 상위 10개를 반환합니다.

```
SELECT SUM(packets) AS
  packetcount,
  dstaddr
FROM vpc_flow_logs
WHERE dstport = 443 AND date > current_date - interval '7' day
GROUP BY dstaddr
ORDER BY packetcount DESC
LIMIT 10;
```

# Apache Parquet 형식으로 흐름 로그용 테이블 생성
<a name="vpc-flow-logs-parquet"></a>

다음은 Apache Parquet 형식으로 Amazon VPC 흐름 로그에 대한 Amazon VPC 테이블을 생성하는 절차입니다.

**Parquet 형식으로 Amazon VPC 흐름 로그에 대한 Athena 테이블 생성**

1. [고려 사항 및 제한 사항](vpc-flow-logs.md#vpc-flow-logs-common-considerations) 섹션의 다음 지침에 따라 Athena 콘솔 쿼리 편집기에 다음과 같은 DDL 문을 입력합니다. 다음 샘플 문은 [흐름 로그 레코드](https://docs.aws.amazon.com/vpc/latest/userguide/flow-logs.html#flow-log-records)에 설명된 대로 Parquet 형식으로 Amazon VPC 흐름 로그 버전 2 \$1 5의 열을 포함하는 테이블을 만들며 Hive는 매시간 분할됩니다. 시간당 파티션이 없는 경우 `hour` 절에서 `PARTITIONED BY`를 제거합니다.

   ```
   CREATE EXTERNAL TABLE IF NOT EXISTS vpc_flow_logs_parquet (
     version int,
     account_id string,
     interface_id string,
     srcaddr string,
     dstaddr string,
     srcport int,
     dstport int,
     protocol bigint,
     packets bigint,
     bytes bigint,
     start bigint,
     `end` bigint,
     action string,
     log_status string,
     vpc_id string,
     subnet_id string,
     instance_id string,
     tcp_flags int,
     type string,
     pkt_srcaddr string,
     pkt_dstaddr string,
     region string,
     az_id string,
     sublocation_type string,
     sublocation_id string,
     pkt_src_aws_service string,
     pkt_dst_aws_service string,
     flow_direction string,
     traffic_path int
   )
   PARTITIONED BY (
     `aws-account-id` string,
     `aws-service` string,
     `aws-region` string,
     `year` string, 
     `month` string, 
     `day` string,
     `hour` string
   )
   ROW FORMAT SERDE 
     'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
   STORED AS INPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat' 
   OUTPUTFORMAT 
     'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
   LOCATION
     's3://amzn-s3-demo-bucket/prefix/AWSLogs/'
   TBLPROPERTIES (
     'EXTERNAL'='true', 
     'skip.header.line.count'='1'
     )
   ```

1. 로그 데이터가 포함된 Amazon S3 경로를 가리키도록 샘플 `LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/'`을 수정합니다.

1. Athena 콘솔에서 쿼리를 실행합니다.

1. 데이터가 Hive 호환 형식인 경우 Athena 콘솔에서 다음 명령을 실행하여 메타스토어의 Hive 파티션을 업데이트 및 로드합니다. 쿼리가 완료되면 `vpc_flow_logs_parquet` 테이블에서 데이터를 쿼리할 수 있습니다.

   ```
   MSCK REPAIR TABLE vpc_flow_logs_parquet
   ```

   Hive 호환 데이터를 사용하지 않는 경우 [ALTER TABLE ADD PARTITION](alter-table-add-partition.md)을 실행하여 파티션을 로드합니다.

Athena를 사용하여 Parquet 형식으로 Amazon VPC 흐름 로그를 쿼리하는 방법에 대한 자세한 내용은 *AWS Big Data Blog*의 [Optimize performance and reduce costs for network analytics with VPC Flow Logs in Apache Parquet format](https://aws.amazon.com/blogs/big-data/optimize-performance-and-reduce-costs-for-network-analytics-with-vpc-flow-logs-in-apache-parquet-format/)을 참조하세요.

# 파티션 프로젝션을 사용하여 Amazon VPC 흐름 로그용 테이블 생성 및 쿼리
<a name="vpc-flow-logs-partition-projection"></a>

다음과 같이 `CREATE TABLE`을 사용하여 테이블을 생성하고, 테이블을 분할하고, [파티션 프로젝션](partition-projection.md)을 사용하여 자동으로 파티션을 채웁니다. 예에서 테이블 이름 `test_table_vpclogs`를 테이블 이름으로 바꿉니다. `LOCATION` 절을 편집하여 Amazon VPC 로그 데이터가 포함된 Amazon S3 버킷을 지정합니다.

다음 `CREATE TABLE` 문은 Hive 스타일이 아닌 분할 형식으로 전달되는 VPC 흐름 로그입니다. 이 예제에서는 다중 계정 집계를 허용합니다. 여러 계정의 VPC 흐름 로그를 하나의 Amazon S3 버킷으로 중앙 집중화하려는 경우 Amazon S3 경로에 계정 ID를 입력해야 합니다.

```
CREATE EXTERNAL TABLE IF NOT EXISTS test_table_vpclogs (
  version int,
  account_id string,
  interface_id string,
  srcaddr string,
  dstaddr string,
  srcport int,
  dstport int,
  protocol bigint,
  packets bigint,
  bytes bigint,
  start bigint,
  `end` bigint,
  action string,
  log_status string,
  vpc_id string,
  subnet_id string,
  instance_id string,
  tcp_flags int,
  type string,
  pkt_srcaddr string,
  pkt_dstaddr string,
  az_id string,
  sublocation_type string,
  sublocation_id string,
  pkt_src_aws_service string,
  pkt_dst_aws_service string,
  flow_direction string,
  traffic_path int
)
PARTITIONED BY (accid string, region string, day string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ' '
LOCATION '$LOCATION_OF_LOGS'
TBLPROPERTIES
(
"skip.header.line.count"="1",
"projection.enabled" = "true",
"projection.accid.type" = "enum",
"projection.accid.values" = "$ACCID_1,$ACCID_2",
"projection.region.type" = "enum",
"projection.region.values" = "$REGION_1,$REGION_2,$REGION_3",
"projection.day.type" = "date",
"projection.day.range" = "$START_RANGE,NOW",
"projection.day.format" = "yyyy/MM/dd",
"storage.location.template" = "s3://amzn-s3-demo-bucket/AWSLogs/${accid}/vpcflowlogs/${region}/${day}"
)
```

## test\$1table\$1vpclogs에 대한 쿼리 예
<a name="query-examples-vpc-logs-pp"></a>

다음 예제 쿼리는 선행하는 `CREATE TABLE` 문에 의해 생성된 `test_table_vpclogs`를 쿼리합니다. 쿼리에서 `test_table_vpclogs`를 자체 테이블 이름으로 바꿉니다. 사용자의 요구 사항에 따라 열 값과 기타 변수를 수정합니다.

지정된 기간 동안 처음 100개의 액세스 로그 항목을 시간순으로 반환하려면 다음과 같은 쿼리를 실행합니다.

```
SELECT *
FROM test_table_vpclogs
WHERE day >= '2021/02/01' AND day < '2021/02/28'
ORDER BY day ASC
LIMIT 100
```

지정된 기간 동안 상위 10개 HTTP 패킷을 수신하는 서버를 보려면 다음과 같은 쿼리를 실행합니다. 이 쿼리는 지난 주부터 HTTPS 포트 443에서 수신한 패킷 수를 계산하고, 대상 IP 주소별로 그룹화한 다음, 상위 10개를 반환합니다.

```
SELECT SUM(packets) AS packetcount, 
       dstaddr
FROM test_table_vpclogs
WHERE dstport = 443
  AND day >= '2021/03/01'
  AND day < '2021/03/31'
GROUP BY dstaddr
ORDER BY packetcount DESC
LIMIT 10
```

지정된 기간 동안 생성된 로그를 반환하려면 다음과 같은 쿼리를 실행합니다.

```
SELECT interface_id,
       srcaddr,
       action,
       protocol,
       to_iso8601(from_unixtime(start)) AS start_time,
       to_iso8601(from_unixtime("end")) AS end_time
FROM test_table_vpclogs
WHERE DAY >= '2021/04/01'
  AND DAY < '2021/04/30'
```

지정된 기간 사이에 소스 IP 주소에 대한 액세스 로그를 반환하려면 다음과 같은 쿼리를 실행합니다.

```
SELECT *
FROM test_table_vpclogs
WHERE srcaddr = '10.117.1.22'
  AND day >= '2021/02/01'
  AND day < '2021/02/28'
```

거부된 TCP 연결을 나열하려면 다음과 같은 쿼리를 실행합니다.

```
SELECT day,
       interface_id,
       srcaddr,
       action,
       protocol
FROM test_table_vpclogs
WHERE action = 'REJECT' AND protocol = 6 AND day >= '2021/02/01' AND day < '2021/02/28'
LIMIT 10
```

`10.117`로 시작하는 IP 주소 범위에 대한 액세스 로그를 반환하려면 다음과 같은 쿼리를 실행합니다.

```
SELECT *
FROM test_table_vpclogs
WHERE split_part(srcaddr,'.', 1)='10'
  AND split_part(srcaddr,'.', 2) ='117'
```

지정된 기간 사이에 대상 IP 주소에 대한 액세스 로그를 반환하려면 다음과 같은 쿼리를 실행합니다.

```
SELECT *
FROM test_table_vpclogs
WHERE dstaddr = '10.0.1.14'
  AND day >= '2021/01/01'
  AND day < '2021/01/31'
```

# 파티션 프로젝션을 사용하여 Apache Parquet 형식으로 흐름 로그용 테이블 생성
<a name="vpc-flow-logs-partition-projection-parquet-example"></a>

VPC 흐름 로그에 대한 다음 파티션 프로젝션 `CREATE TABLE` 문은 Apache Parquet 형식이고 Hive와 호환되지 않으며 일 대신 시간 및 날짜를 기준으로 분할됩니다. 예에서 테이블 이름 `test_table_vpclogs_parquet`를 테이블 이름으로 바꿉니다. `LOCATION` 절을 편집하여 Amazon VPC 로그 데이터가 포함된 Amazon S3 버킷을 지정합니다.

```
CREATE EXTERNAL TABLE IF NOT EXISTS test_table_vpclogs_parquet (
  version int,
  account_id string,
  interface_id string,
  srcaddr string,
  dstaddr string,
  srcport int,
  dstport int,
  protocol bigint,
  packets bigint,
  bytes bigint,
  start bigint,
  `end` bigint,
  action string,
  log_status string,
  vpc_id string,
  subnet_id string,
  instance_id string,
  tcp_flags int,
  type string,
  pkt_srcaddr string,
  pkt_dstaddr string,
  az_id string,
  sublocation_type string,
  sublocation_id string,
  pkt_src_aws_service string,
  pkt_dst_aws_service string,
  flow_direction string,
  traffic_path int
)
PARTITIONED BY (region string, date string, hour string)
ROW FORMAT SERDE
'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT
'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'
LOCATION 's3://amzn-s3-demo-bucket/prefix/AWSLogs/{account_id}/vpcflowlogs/'
TBLPROPERTIES (
"EXTERNAL"="true",
"skip.header.line.count" = "1",
"projection.enabled" = "true",
"projection.region.type" = "enum",
"projection.region.values" = "us-east-1,us-west-2,ap-south-1,eu-west-1",
"projection.date.type" = "date",
"projection.date.range" = "2021/01/01,NOW",
"projection.date.format" = "yyyy/MM/dd",
"projection.hour.type" = "integer",
"projection.hour.range" = "00,23",
"projection.hour.digits" = "2",
"storage.location.template" = "s3://amzn-s3-demo-bucket/prefix/AWSLogs/${account_id}/vpcflowlogs/${region}/${date}/${hour}"
)
```

# 추가 리소스
<a name="query-examples-vpc-logs-additional-resources"></a>

Athena를 사용하여 VPC 흐름 로그를 분석하는 방법에 대한 자세한 내용은 다음 AWS 빅 데이터 블로그 게시물을 참조하세요.
+ [포인트 앤 클릭 방식 Amazon Athena 통합을 통한 VPC 흐름 로그 분석](https://aws.amazon.com/blogs/networking-and-content-delivery/analyze-vpc-flow-logs-with-point-and-click-amazon-athena-integration/) 
+ [Analyzing VPC flow logs using Amazon Athena and Quick](https://aws.amazon.com/blogs/big-data/analyzing-vpc-flow-logs-using-amazon-athena-and-amazon-quicksight/)
+ [Apache Parquet 형식의 VPC 흐름 로그를 사용하여 네트워크 분석 성능을 최적화하고 비용을 절감합니다.](https://aws.amazon.com/blogs/big-data/optimize-performance-and-reduce-costs-for-network-analytics-with-vpc-flow-logs-in-apache-parquet-format/)

# AWS WAF 로그 쿼리
<a name="waf-logs"></a>

AWS WAF는 보호되는 웹 애플리케이션이 클라이언트로부터 수신하는 HTTP 및 HTTPS 요청을 모니터링하고 제어할 수 있는 웹 애플리케이션 방화벽입니다. AWS WAF WAF 웹 액세스 제어 목록(ACL) 내에서 규칙을 구성하여 웹 요청을 처리하는 방법을 정의합니다. 그런 다음 웹 ACL을 연결하여 웹 애플리케이션을 보호합니다. AWS WAF로 보호할 수 있는 웹 애플리케이션 리소스의 예로는 Amazon CloudFront 배포, Amazon API Gateway REST API 및 Application Load Balancer가 있습니다. AWS WAF에 대한 자세한 내용은 **AWS WAF 개발자 안내서의 [AWS WAF](https://docs.aws.amazon.com/waf/latest/developerguide/waf-chapter.html) 섹션을 참조하세요.

AWS WAF 로그에는 AWS WAF가 AWS 리소스로부터 요청을 받은 시간, 요청에 대한 세부 정보 및 각 요청이 부합되는 규칙에 대한 작업과 같이 웹 ACL에 의해 분석되는 트래픽에 대한 정보가 포함됩니다.

로그를 쿼리하고 볼 수 있는 여러 대상 중 하나에 로그를 게시하도록 AWS WAF 웹 ACL을 구성할 수 있습니다. 웹 ACL 로깅 및 AWS WAF 로그 내용 구성에 대한 자세한 내용은 **AWS WAF 개발자 안내서의 [Logging AWS WAF web ACL traffic](https://docs.aws.amazon.com/waf/latest/developerguide/logging.html)을 참조하세요.

Athena를 사용하여 AWS WAF 로그를 분석하여 위협 탐지 및 잠재적 보안 공격에 대한 인사이트를 얻는 방법에 대한 자세한 내용은 AWS 네트워킹 및 콘텐츠 전송 블로그 게시물 Networking & Content Delivery Blog post [How to use Amazon Athena queries to analyze AWS WAF logs and provide the visibility needed for threat detection](https://aws.amazon.com/blogs/networking-and-content-delivery/how-to-use-amazon-athena-queries-to-analyze-aws-waf-logs-and-provide-the-visibility-needed-for-threat-detection/)을 참조하세요.

AWS WAF 로그를 중앙 데이터 레이크 리포지토리에 집계하고 Athena로 쿼리하는 방법의 예시는 AWS Big Data Blog 게시물 [Analyzing AWS WAF logs with OpenSearch Service, Amazon Athena and Quick](https://aws.amazon.com/blogs/big-data/analyzing-aws-waf-logs-with-amazon-es-amazon-athena-and-amazon-quicksight/)을 참조하세요.

이 항목에서는 파티션 프로젝션, 수동 파티셔닝 및 파티셔닝을 사용하지 않는 경우에 대한 예제 `CREATE TABLE` 문을 제공합니다.

**참고**  
이 주제의 `CREATE TABLE` 문은 v1 및 v2 AWS WAF 로그에 모두 사용할 수 있습니다. v1에서는 `webaclid` 필드에 ID가 포함되어 있습니다. v2에서는 `webaclid` 필드에 전체 ARN이 포함되어 있습니다. 이곳의 `CREATE TABLE` 문은 `string` 데이터 유형을 사용하여 애그노스틱 방식으로 이 콘텐츠를 취급합니다.

**Topics**
+ [파티션 프로젝션을 사용하여 Athena에서 AWS WAF S3 로그용 테이블 생성](create-waf-table-partition-projection.md)
+ [수동 파티션을 사용하여 Athena에서 AWS WAF S3 로그용 테이블 생성](create-waf-table-manual-partition.md)
+ [분할 없이 AWS WAF 로그용 테이블 생성](create-waf-table.md)
+ [AWS WAF 로그에 대한 쿼리 예제](query-examples-waf-logs.md)

# 파티션 프로젝션을 사용하여 Athena에서 AWS WAF S3 로그용 테이블 생성
<a name="create-waf-table-partition-projection"></a>

AWS WAF 로그에는 미리 지정할 수 있는 파티션 스키마를 가진 알려진 구조가 있기 때문에 Athena [파티션 프로젝션](partition-projection.md) 기능을 사용하여 쿼리 런타임을 줄이고 파티션 관리를 자동화할 수 있습니다. 새 데이터가 추가되면 파티션 프로젝션은 자동으로 새 파티션을 추가합니다. 따라서 `ALTER TABLE ADD PARTITION`을 사용해 파티션을 수동으로 추가할 필요가 없습니다.

다음 `CREATE TABLE` 문 예제에서는 네 개의 각기 다른 AWS 리전에 대해 지정된 날짜부터 현재까지의 AWS WAF 로그에 대해 파티션 프로젝션을 자동으로 사용합니다. 이 예제의 `PARTITION BY` 절은 리전 및 날짜별로 분할되지만 요구 사항에 따라 수정할 수 있습니다. 필요에 따라 필드를 로그 출력과 일치하도록 수정합니다. `LOCATION` 및 `storage.location.template` 절에서 *amzn-s3-demo-bucket* 및 *AWS\$1ACCOUNT\$1NUMBER* 자리 표시자를 AWS WAF 로그의 Amazon S3 버킷 위치를 식별하는 값으로 바꿉니다. `projection.day.range`에 대해 *2021*/*01*/*01*을 사용하려는 시작 날짜로 바꿉니다. 쿼리가 성공적으로 실행되면 테이블을 쿼리할 수 있습니다. 파티션을 로드하기 위해 `ALTER TABLE ADD PARTITION`을 실행하지 않아도 됩니다.

```
CREATE EXTERNAL TABLE `waf_logs_partition_projection`(
  `timestamp` bigint, 
  `formatversion` int, 
  `webaclid` string, 
  `terminatingruleid` string, 
  `terminatingruletype` string, 
  `action` string, 
  `terminatingrulematchdetails` array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>, 
  `httpsourcename` string, 
  `httpsourceid` string, 
  `rulegrouplist` array<struct<rulegroupid:string,terminatingrule:struct<ruleid:string,action:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>>,nonterminatingmatchingrules:array<struct<ruleid:string,action:string,overriddenaction:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>,challengeresponse:struct<responsecode:string,solvetimestamp:string>,captcharesponse:struct<responsecode:string,solvetimestamp:string>>>,excludedrules:string>>, 
  `ratebasedrulelist` array<struct<ratebasedruleid:string,limitkey:string,maxrateallowed:int>>, 
  `nonterminatingmatchingrules` array<struct<ruleid:string,action:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>,challengeresponse:struct<responsecode:string,solvetimestamp:string>,captcharesponse:struct<responsecode:string,solvetimestamp:string>>>, 
  `requestheadersinserted` array<struct<name:string,value:string>>, 
  `responsecodesent` string, 
  `httprequest` struct<clientip:string,country:string,headers:array<struct<name:string,value:string>>,uri:string,args:string,httpversion:string,httpmethod:string,requestid:string,fragment:string,scheme:string,host:string>,
  `labels` array<struct<name:string>>, 
  `captcharesponse` struct<responsecode:string,solvetimestamp:string,failurereason:string>, 
  `challengeresponse` struct<responsecode:string,solvetimestamp:string,failurereason:string>, 
  `ja3fingerprint` string, 
  `ja4fingerprint` string, 
  `oversizefields` string, 
  `requestbodysize` int, 
  `requestbodysizeinspectedbywaf` int)
  PARTITIONED BY ( 
   `log_time` string)
ROW FORMAT SERDE 
  'org.openx.data.jsonserde.JsonSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_NUMBER/WAFLogs/cloudfront/testui/'
TBLPROPERTIES (
 'projection.enabled'='true',
  'projection.log_time.format'='yyyy/MM/dd/HH/mm',
  'projection.log_time.interval'='1',
  'projection.log_time.interval.unit'='minutes',
  'projection.log_time.range'='2025/01/01/00/00,NOW',
  'projection.log_time.type'='date',
  'storage.location.template'='s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_NUMBER/WAFLogs/cloudfront/testui/${log_time}')
```

**참고**  
예제에서 `LOCATION` 절의 경로 형식은 표준이지만 구현한 AWS WAF 구성에 따라 달라질 수 있습니다. 예를 들어 다음 예제 AWS WAF 로그 경로는 CloudFront 배포에 적용됩니다.  

```
s3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_NUMBER/WAFLogs/cloudfront/cloudfronyt/2025/01/01/00/00/
```
AWS WAF 로그 테이블을 생성하거나 쿼리하는 동안 문제가 발생하는 경우 로그 데이터의 위치를 확인하거나 [지원에 문의](https://console.aws.amazon.com/support/home/)하세요.

파티션 프로젝션에 대한 자세한 내용은 [Amazon Athena에서 파티션 프로젝션 사용](partition-projection.md) 단원을 참조하세요.

# 수동 파티션을 사용하여 Athena에서 AWS WAF S3 로그용 테이블 생성
<a name="create-waf-table-manual-partition"></a>

이 섹션에서는 수동 파티션을 사용하여 AWS WAF 로그용 테이블을 생성하는 방법을 설명합니다.

`LOCATION` 및 `storage.location.template` 절에서 *amzn-s3-demo-bucket* 및 *AWS\$1ACCOUNT\$1NUMBER* 자리 표시자를 AWS WAF 로그의 Amazon S3 버킷 위치를 식별하는 값으로 바꿉니다.

```
CREATE EXTERNAL TABLE `waf_logs_manual_partition`(
  `timestamp` bigint, 
  `formatversion` int, 
  `webaclid` string, 
  `terminatingruleid` string, 
  `terminatingruletype` string, 
  `action` string, 
  `terminatingrulematchdetails` array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>, 
  `httpsourcename` string, 
  `httpsourceid` string, 
  `rulegrouplist` array<struct<rulegroupid:string,terminatingrule:struct<ruleid:string,action:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>>,nonterminatingmatchingrules:array<struct<ruleid:string,action:string,overriddenaction:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>,challengeresponse:struct<responsecode:string,solvetimestamp:string>,captcharesponse:struct<responsecode:string,solvetimestamp:string>>>,excludedrules:string>>, 
  `ratebasedrulelist` array<struct<ratebasedruleid:string,limitkey:string,maxrateallowed:int>>, 
  `nonterminatingmatchingrules` array<struct<ruleid:string,action:string,rulematchdetails:array<struct<conditiontype:string,sensitivitylevel:string,location:string,matcheddata:array<string>>>,challengeresponse:struct<responsecode:string,solvetimestamp:string>,captcharesponse:struct<responsecode:string,solvetimestamp:string>>>, 
  `requestheadersinserted` array<struct<name:string,value:string>>, 
  `responsecodesent` string, 
  `httprequest` struct<clientip:string,country:string,headers:array<struct<name:string,value:string>>,uri:string,args:string,httpversion:string,httpmethod:string,requestid:string,fragment:string,scheme:string,host:string>, 
  `labels` array<struct<name:string>>, 
  `captcharesponse` struct<responsecode:string,solvetimestamp:string,failurereason:string>, 
  `challengeresponse` struct<responsecode:string,solvetimestamp:string,failurereason:string>, 
  `ja3fingerprint` string, 
  `ja4fingerprint` string, 
  `oversizefields` string, 
  `requestbodysize` int, 
  `requestbodysizeinspectedbywaf` int)
  PARTITIONED BY ( `year` string, `month` string, `day` string, `hour` string, `min` string)
ROW FORMAT SERDE 
  'org.openx.data.jsonserde.JsonSerDe' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://amzn-s3-demo-bucket/AWSLogs/AWS_ACCOUNT_NUMBER/WAFLogs/cloudfront/webacl/'
```

# 분할 없이 AWS WAF 로그용 테이블 생성
<a name="create-waf-table"></a>

이 단원에서는 분할이나 파티션 프로젝션 없이 AWS WAF 로그의 테이블을 생성하는 방법을 설명합니다.

**참고**  
성능 및 비용상의 이유로 쿼리에는 파티셔닝되지 않은 스키마를 사용하지 않는 것이 좋습니다. 자세한 내용은 AWS 빅 데이터 블로그의 [Top 10 Performance Tuning Tips for Amazon Athena](https://aws.amazon.com/blogs/big-data/top-10-performance-tuning-tips-for-amazon-athena/)(Amazon Athena의 성능 튜닝을 위한 10가지 팁)를 참조하세요.

**AWS WAF 테이블을 생성하려면**

1. 다음 DDL 문을 복사하여 Athena 콘솔에 붙여 넣습니다. 필요에 따라 필드를 로그 출력과 일치하도록 수정합니다. 로그를 저장하는 것과 일치하도록 Amazon S3 버킷의 `LOCATION`을 수정합니다.

   이 쿼리는 [OpenX JSON SerDe](openx-json-serde.md)를 사용합니다.
**참고**  
SerDe는 각 JSON 문서가 레코드의 필드를 구분하는 줄 종료 문자가 없는 한 줄의 텍스트에 있을 것으로 예상합니다. JSON 텍스트가 가독성 좋게 꾸민 형식이면 테이블을 만든 후 쿼리하려고 할 때 HIVE\$1CURSOR\$1ERROR: 행이 유효한 JSON 객체가 아님(HIVE\$1CURSOR\$1ERROR: Row is not a valid JSON Object) 또는 HIVE\$1CURSOR\$1ERROR: JsonParseException: 예기치 않은 입력 종료: OBJECT의 닫기 마커 필요(HIVE\$1CURSOR\$1ERROR: JsonParseException: Unexpected end-of-input: expected close marker for OBJECT) 같은 오류 메시지가 나타날 수 있습니다. 자세한 내용은 GitHub의 OpenX SerDe 문서에서 [JSON 데이터 파일](https://github.com/rcongiu/Hive-JSON-Serde#json-data-files)을 참조하세요.

   ```
   CREATE EXTERNAL TABLE `waf_logs`(
     `timestamp` bigint,
     `formatversion` int,
     `webaclid` string,
     `terminatingruleid` string,
     `terminatingruletype` string,
     `action` string,
     `terminatingrulematchdetails` array <
                                       struct <
                                           conditiontype: string,
                                           sensitivitylevel: string,
                                           location: string,
                                           matcheddata: array < string >
                                             >
                                        >,
     `httpsourcename` string,
     `httpsourceid` string,
     `rulegrouplist` array <
                         struct <
                             rulegroupid: string,
                             terminatingrule: struct <
                                                 ruleid: string,
                                                 action: string,
                                                 rulematchdetails: array <
                                                                      struct <
                                                                          conditiontype: string,
                                                                          sensitivitylevel: string,
                                                                          location: string,
                                                                          matcheddata: array < string >
                                                                             >
                                                                       >
                                                   >,
                             nonterminatingmatchingrules: array <
                                                                 struct <
                                                                     ruleid: string,
                                                                     action: string,
                                                                     overriddenaction: string,
                                                                     rulematchdetails: array <
                                                                                          struct <
                                                                                              conditiontype: string,
                                                                                              sensitivitylevel: string,
                                                                                              location: string,
                                                                                              matcheddata: array < string >
                                                                                                 >
                                                                      >,
                                                                     challengeresponse: struct <
                                                                               responsecode: string,
                                                                               solvetimestamp: string
                                                                                 >,
                                                                     captcharesponse: struct <
                                                                               responsecode: string,
                                                                               solvetimestamp: string
                                                                                 >
                                                                       >
                                                                >,
                             excludedrules: string
                               >
                          >,
   `ratebasedrulelist` array <
                            struct <
                                ratebasedruleid: string,
                                limitkey: string,
                                maxrateallowed: int
                                  >
                             >,
     `nonterminatingmatchingrules` array <
                                       struct <
                                           ruleid: string,
                                           action: string,
                                           rulematchdetails: array <
                                                                struct <
                                                                    conditiontype: string,
                                                                    sensitivitylevel: string,
                                                                    location: string,
                                                                    matcheddata: array < string >
                                                                       >
                                                                >,
                                           challengeresponse: struct <
                                                               responsecode: string,
                                                               solvetimestamp: string
                                                                >,
                                           captcharesponse: struct <
                                                               responsecode: string,
                                                               solvetimestamp: string
                                                                >
                                             >
                                        >,
     `requestheadersinserted` array <
                                   struct <
                                       name: string,
                                       value: string
                                         >
                                    >,
     `responsecodesent` string,
     `httprequest` struct <
                       clientip: string,
                       country: string,
                       headers: array <
                                   struct <
                                       name: string,
                                       value: string
                                         >
                                    >,
                       uri: string,
                       args: string,
                       httpversion: string,
                       httpmethod: string,
                       requestid: string
                         >,
     `labels` array <
                  struct <
                      name: string
                        >
                   >,
     `captcharesponse` struct <
                           responsecode: string,
                           solvetimestamp: string,
                           failureReason: string
                             >,
     `challengeresponse` struct <
                           responsecode: string,
                           solvetimestamp: string,
                           failureReason: string
                           >,
     `ja3Fingerprint` string,
     `oversizefields` string,
     `requestbodysize` int,
     `requestbodysizeinspectedbywaf` int
   )
   ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
   STORED AS INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat'
   OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
   LOCATION 's3://amzn-s3-demo-bucket/prefix/'
   ```

1. Athena 콘솔 쿼리 편집기에서 `CREATE EXTERNAL TABLE` 문을 실행합니다. 이렇게 하면 `waf_logs` 테이블이 등록되고 Athena에서 그 안의 데이터를 쿼리할 수 있습니다.

# AWS WAF 로그에 대한 쿼리 예제
<a name="query-examples-waf-logs"></a>

이 섹션의 쿼리 예제는 대부분 이전에 생성한 파티션 프로젝션 테이블을 사용합니다. 필요에 따라 예제의 테이블 이름, 열 값 및 기타 변수를 수정합니다. 쿼리 성능을 개선하고 비용을 줄이려면 필터 조건에 파티션 열을 추가합니다.

**Topics**
+ [참조자, IP 주소 또는 일치하는 규칙 개수](query-examples-waf-logs-count.md)
+ [날짜 및 시간을 사용한 쿼리](query-examples-waf-logs-date-time.md)
+ [차단된 요청 또는 주소 쿼리](query-examples-waf-logs-blocked-requests.md)

# 참조자, IP 주소 또는 일치하는 규칙 개수
<a name="query-examples-waf-logs-count"></a>

이 섹션의 예제에서는 관심 있는 로그 항목의 개수를 쿼리합니다.
+ [Count the number of referrers that contain a specified term](#waf-example-count-referrers-with-specified-term)
+ [Count all matched IP addresses in the last 10 days that have matched excluded rules](#waf-example-count-matched-ip-addresses)
+ [Group all counted managed rules by the number of times matched](#waf-example-group-managed-rules-by-times-matched)
+ [Group all counted custom rules by number of times matched](#waf-example-group-custom-rules-by-times-matched)

**Example - 지정된 용어를 포함하는 참조자 수 계산**  
다음 쿼리는 지정된 날짜 범위에서 “amazon”이라는 용어를 포함한 참조자의 수를 셉니다.  

```
WITH test_dataset AS 
  (SELECT header FROM waf_logs
    CROSS JOIN UNNEST(httprequest.headers) AS t(header) WHERE "date" >= '2021/03/01'
    AND "date" < '2021/03/31')
SELECT COUNT(*) referer_count 
FROM test_dataset 
WHERE LOWER(header.name)='referer' AND header.value LIKE '%amazon%'
```

**Example - 지난 10일 동안 제외된 규칙과 일치하는 모든 IP 주소 계산**  
다음 쿼리는 지난 10일 동안 IP 주소가 규칙 그룹에서 제외된 규칙과 일치하는 횟수를 셉니다.  

```
WITH test_dataset AS 
  (SELECT * FROM waf_logs 
    CROSS JOIN UNNEST(rulegrouplist) AS t(allrulegroups))
SELECT 
  COUNT(*) AS count, 
  "httprequest"."clientip", 
  "allrulegroups"."excludedrules",
  "allrulegroups"."ruleGroupId"
FROM test_dataset 
WHERE allrulegroups.excludedrules IS NOT NULL AND from_unixtime(timestamp/1000) > now() - interval '10' day
GROUP BY "httprequest"."clientip", "allrulegroups"."ruleGroupId", "allrulegroups"."excludedrules"
ORDER BY count DESC
```

**Example - 일치하는 횟수를 기준으로 계산된 모든 관리형 규칙 그룹화**  
2022년 10월 27일 이전에 웹 ACL 구성에서 규칙 그룹 규칙 작업을 개수로 설정한 경우 AWS WAF에서는 재정의를 웹 ACL JSON에 `excludedRules`로 저장했습니다. 이제 규칙을 개수로 재정의하기 위한 JSON 설정은 `ruleActionOverrides` 설정에 있습니다. 자세한 내용은 *AWS WAF 개발자 안내서*의 [Action overrides in rule groups](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-rule-group-override-options.html)를 참조하세요. 새 로그 구조에서 개수 모드의 관리형 규칙을 추출하려면 다음 예제와 같이 `excludedRules` 필드 대신 `ruleGroupList` 섹션에서 `nonTerminatingMatchingRules`를 쿼리합니다.  

```
SELECT
 count(*) AS count,
 httpsourceid,
 httprequest.clientip,
 t.rulegroupid, 
 t.nonTerminatingMatchingRules
FROM "waf_logs" 
CROSS JOIN UNNEST(rulegrouplist) AS t(t) 
WHERE action <> 'BLOCK' AND cardinality(t.nonTerminatingMatchingRules) > 0 
GROUP BY t.nonTerminatingMatchingRules, action, httpsourceid, httprequest.clientip, t.rulegroupid 
ORDER BY "count" DESC 
Limit 50
```

**Example - 일치하는 횟수를 기준으로 계산된 모든 사용자 지정 규칙 그룹화**  
다음 쿼리는 일치하는 횟수를 기준으로 계산된 모든 사용자 지정 규칙을 그룹화합니다.  

```
SELECT
  count(*) AS count,
         httpsourceid,
         httprequest.clientip,
         t.ruleid,
         t.action
FROM "waf_logs" 
CROSS JOIN UNNEST(nonterminatingmatchingrules) AS t(t) 
WHERE action <> 'BLOCK' AND cardinality(nonTerminatingMatchingRules) > 0 
GROUP BY t.ruleid, t.action, httpsourceid, httprequest.clientip 
ORDER BY "count" DESC
Limit 50
```

사용자 지정 규칙 및 관리형 규칙 그룹의 로그 위치에 대한 자세한 내용은 *AWS WAF 개발자 안내서*의 [Monitoring and tuning](https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-testing-activities.html)을 참조하세요.

# 날짜 및 시간을 사용한 쿼리
<a name="query-examples-waf-logs-date-time"></a>

이 섹션의 예제에는 날짜 및 시간 값을 사용하는 쿼리가 포함되어 있습니다.
+ [Return the timestamp field in human-readable ISO 8601 format](#waf-example-return-human-readable-timestamp)
+ [Return records from the last 24 hours](#waf-example-return-records-last-24-hours)
+ [Return records for a specified date range and IP address](#waf-example-return-records-date-range-and-ip)
+ [For a specified date range, count the number of IP addresses in five minute intervals](#waf-example-count-ip-addresses-in-date-range)
+ [Count the number of X-Forwarded-For IP in the last 10 days](#waf-example-count-x-forwarded-for-ip)

**Example - 사람이 읽을 수 있는 ISO 8601 형식으로 타임스탬프 필드 반환**  
다음 쿼리는 `from_unixtime` 및 `to_iso8601` 함수를 사용하여 `timestamp` 필드를 사람이 읽을 수 있는 ISO 8601 형식으로 반환합니다(예: `1576280412771`이 아닌 `2019-12-13T23:40:12.000Z`). 쿼리는 HTTP 소스 이름, 소스 ID, 요청도 반환합니다.  

```
SELECT to_iso8601(from_unixtime(timestamp / 1000)) as time_ISO_8601,
       httpsourcename,
       httpsourceid,
       httprequest
FROM waf_logs
LIMIT 10;
```

**Example - 최근 24시간의 레코드 반환**  
다음 쿼리는 `WHERE` 절에 필터를 사용해 최근 24시간의 레코드의 HTTP 소스 이름, HTTP 소스 ID, HTTP 요청 필드를 반환합니다.  

```
SELECT to_iso8601(from_unixtime(timestamp/1000)) AS time_ISO_8601, 
       httpsourcename, 
       httpsourceid, 
       httprequest 
FROM waf_logs
WHERE from_unixtime(timestamp/1000) > now() - interval '1' day
LIMIT 10;
```

**Example - 지정된 날짜 범위 및 IP 주소에 대한 레코드 반환**  
다음 쿼리는 지정된 클라이언트 IP 주소에 대해 지정된 날짜 범위의 레코드를 나열합니다.  

```
SELECT * 
FROM waf_logs 
WHERE httprequest.clientip='53.21.198.66' AND "date" >= '2021/03/01' AND "date" < '2021/03/31'
```

**Example - 지정된 날짜 범위에 대해 5분 간격으로 IP 주소 개수 계산**  
다음 쿼리는 특정 날짜 범위에 대해 5분 간격으로 IP 주소 개수를 셉니다.  

```
WITH test_dataset AS 
  (SELECT 
     format_datetime(from_unixtime((timestamp/1000) - ((minute(from_unixtime(timestamp / 1000))%5) * 60)),'yyyy-MM-dd HH:mm') AS five_minutes_ts,
     "httprequest"."clientip" 
     FROM waf_logs 
     WHERE "date" >= '2021/03/01' AND "date" < '2021/03/31')
SELECT five_minutes_ts,"clientip",count(*) ip_count 
FROM test_dataset 
GROUP BY five_minutes_ts,"clientip"
```

**Example - 지난 10일 동안 X-Forwarded-For IP 수 계산**  
다음 쿼리는 요청 헤더를 필터링하고 지난 10일 동안의 X-Forwarded-For IP 수를 계산합니다.  

```
WITH test_dataset AS
  (SELECT header
   FROM waf_logs
   CROSS JOIN UNNEST (httprequest.headers) AS t(header)
   WHERE from_unixtime("timestamp"/1000) > now() - interval '10' DAY) 
SELECT header.value AS ip,
       count(*) AS COUNT 
FROM test_dataset 
WHERE header.name='X-Forwarded-For' 
GROUP BY header.value 
ORDER BY COUNT DESC
```

날짜 및 시간 함수에 대한 자세한 내용은 Trino 설명서의 [날짜 및 시간 함수와 연산자](https://trino.io/docs/current/functions/datetime.html)를 참조하세요.

# 차단된 요청 또는 주소 쿼리
<a name="query-examples-waf-logs-blocked-requests"></a>

이 섹션의 예제는 차단된 요청 또는 주소를 쿼리합니다.
+ [Extract the top 100 IP addresses blocked by a specified rule type](#waf-example-extract-top-100-blocked-ip-by-rule)
+ [Count the number of times a request from a specified country has been blocked](#waf-example-count-request-blocks-from-country)
+ [Count the number of times a request has been blocked, grouping by specific attributes](#waf-example-count-request-blocks-by-attribute)
+ [Count the number of times a specific terminating rule ID has been matched](#waf-example-count-terminating-rule-id-matches)
+ [Retrieve the top 100 IP addresses blocked during a specified date range](#waf-example-top-100-ip-addresses-blocked-for-date-range)

**Example - 지정된 규칙 유형에 의해 차단된 상위 100개 IP 주소 추출**  
다음 쿼리는 지정된 날짜 범위 동안 `RATE_BASED` 종료 규칙에 의해 차단된 상위 100개 IP 주소를 추출하고 그 횟수를 셉니다.  

```
SELECT COUNT(httpRequest.clientIp) as count,
httpRequest.clientIp
FROM waf_logs
WHERE terminatingruletype='RATE_BASED' AND action='BLOCK' and "date" >= '2021/03/01'
AND "date" < '2021/03/31'
GROUP BY httpRequest.clientIp
ORDER BY count DESC
LIMIT 100
```

**Example - 지정된 국가의 요청이 차단된 횟수 계산**  
다음 쿼리는 아일랜드(IE)에 속하며 `RATE_BASED` 종료 규칙에 의해 차단된 IP 주소에서 요청이 도착한 횟수를 계산합니다.  

```
SELECT 
  COUNT(httpRequest.country) as count, 
  httpRequest.country 
FROM waf_logs
WHERE 
  terminatingruletype='RATE_BASED' AND 
  httpRequest.country='IE'
GROUP BY httpRequest.country
ORDER BY count
LIMIT 100;
```

**Example - 요청이 차단된 횟수 계산(특정 속성별로 그룹화)**  
다음 쿼리는 요청이 차단된 횟수를 계산하여 WebACL, RuleId, ClientIP 및 HTTP 요청 URI별로 결과를 그룹화합니다.  

```
SELECT 
  COUNT(*) AS count,
  webaclid,
  terminatingruleid,
  httprequest.clientip,
  httprequest.uri
FROM waf_logs
WHERE action='BLOCK'
GROUP BY webaclid, terminatingruleid, httprequest.clientip, httprequest.uri
ORDER BY count DESC
LIMIT 100;
```

**Example - 특정 종료 규칙 ID가 일치하는 횟수 계산**  
다음 쿼리는 특정 종료 규칙 ID(`WHERE terminatingruleid='e9dd190d-7a43-4c06-bcea-409613d9506e'`)가 일치하는 횟수를 계산합니다. 이 쿼리는 WebACL, Action, ClientIP 및 HTTP 요청 URI별로 결과를 그룹화합니다.  

```
SELECT 
  COUNT(*) AS count,
  webaclid,
  action,
  httprequest.clientip,
  httprequest.uri
FROM waf_logs
WHERE terminatingruleid='e9dd190d-7a43-4c06-bcea-409613d9506e'
GROUP BY webaclid, action, httprequest.clientip, httprequest.uri
ORDER BY count DESC
LIMIT 100;
```

**Example - 지정된 날짜 범위 동안 차단된 상위 100개 IP 주소 검색**  
다음 쿼리는 지정된 날짜 범위 동안 차단된 상위 100개 IP 주소를 추출합니다. 쿼리에는 IP 주소가 차단된 횟수도 나열됩니다.  

```
SELECT "httprequest"."clientip", "count"(*) "ipcount", "httprequest"."country"
FROM waf_logs
WHERE "action" = 'BLOCK' and "date" >= '2021/03/01'
AND "date" < '2021/03/31'
GROUP BY "httprequest"."clientip", "httprequest"."country"
ORDER BY "ipcount" DESC limit 100
```

Amazon S3 로그 쿼리에 대한 자세한 내용은 다음 주제를 참조하세요.
+ AWS 지식 센터의 [Athena를 사용하여 내 Amazon S3 서버 액세스 로그를 분석하려면 어떻게 해야 합니까?](https://aws.amazon.com/premiumsupport/knowledge-center/analyze-logs-athena/)
+ Amazon Simple Storage Service 개발자 가이드의 [Amazon Athena를 사용하여 요청에 대한 Amazon S3 액세스 로그 쿼리](https://docs.aws.amazon.com/AmazonS3/latest/dev/using-s3-access-logs-to-identify-requests.html#querying-s3-access-logs-for-requests)
+ Amazon Simple Storage Service 사용 설명서의 [AWS CloudTrail를 사용하여 Amazon S3 요청 식별](https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudtrail-request-identification.html)