

# S3 Tables에서 액세스 로그 쿼리
<a name="sal-cw-querying-s3tables"></a>

Amazon S3 Tables 통합을 활성화하면 Amazon CloudWatch Logs는 서버 액세스 로그를 Apache Iceberg 형식으로 `aws-cloudwatch` 관리형 테이블 버킷에 전달합니다. 데이터는 Iceberg 형식이므로 다음을 포함하여 Apache Iceberg를 지원하는 모든 도구를 사용하여 쿼리할 수 있습니다.
+ **Amazon Athena** - S3 Tables 카탈로그를 사용하여 Athena 콘솔에서 직접 SQL 쿼리를 실행합니다.
+ **Amazon SageMaker Unified Studio** - 내장된 SQL 편집기를 사용하여 다른 분석 워크로드와 함께 로그 데이터를 쿼리합니다.
+ **Amazon Redshift** - Redshift Spectrum 또는 직접 통합을 통해 Iceberg 테이블을 쿼리합니다.
+ **Amazon EMR의 Apache Spark** - Iceberg 커넥터와 함께 Spark SQL 또는 DataFrame API를 사용합니다.
+ **오픈 소스 도구** - Trino, DuckDB 또는 PyIceberg와 같이 Apache Iceberg REST 카탈로그를 지원하는 모든 도구입니다.

**참고**  
CloudWatch Logs Insights(SQL 제외)에서 대화식으로 로그를 쿼리하려면 [CloudWatch Logs Insights로 로그 쿼리](sal-cw-querying-insights.md) 섹션을 참조하세요.

## 사전 조건
<a name="sal-cw-s3tables-prerequisites"></a>

S3 Tables에서 액세스 로그를 쿼리하려면 먼저 다음을 완료해야 합니다.

1. **S3 Tables 통합을 활성화합니다.** [S3 Tables 통합 활성화(선택 사항)](sal-cw-enabling.md#sal-cw-tables-integration)을(를) 참조하세요.

1. **분석 서비스와 S3 Tables 통합을 활성화합니다.** Amazon S3 콘솔에서 **테이블 버킷**으로 이동하여 **통합 활성화**를 선택합니다. 이렇게 하면 Data Catalog에 `s3tablescatalog` 연합 카탈로그가 생성되고 분석 서비스에 테이블이 표시됩니다. 기본적으로 액세스는 IAM 권한을 통해 제어됩니다. 필요에 따라 AWS Lake Formation을 사용하여 세분화된 액세스 제어를 수행할 수 있습니다. 자세한 내용은 [S3 Tables와 AWS 분석 서비스 통합](https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-tables-integrating-aws.html)을 참조하세요.

1. **데이터가 채워질 때까지 기다립니다.** 데이터는 일반적으로 CloudWatch Logs에 처음 전송한 후 1시간 이내에 표시됩니다.

## Amazon Athena 연결
<a name="sal-cw-s3tables-athena-setup"></a>

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

1. 쿼리 편집기의 데이터 소스 드롭다운에서 **Amazon S3 Tables** 카탈로그를 선택합니다.

1. 로그 테이블은 `logs` 네임스페이스 아래의 데이터베이스 목록에 나타납니다.

서버 액세스 로그의 테이블 이름은 `amazon_s3__server_access`입니다. 정규화된 테이블 참조는 다음과 같습니다.

```
"s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
```

## 트래픽 분석
<a name="sal-cw-s3tables-traffic"></a>

**Example 시간 경과에 따른 요청 볼륨**  

```
SELECT date_trunc('minute', request_time) AS interval,
  COUNT(*) AS requests
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
GROUP BY date_trunc('minute', request_time)
ORDER BY interval ASC;
```

**Example 작업 유형별 요청 혼합**  

```
SELECT operation, COUNT(*) AS cnt
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
GROUP BY operation
ORDER BY cnt DESC;
```

**Example 버킷별 트래픽**  

```
SELECT bucket_arn, COUNT(*) AS requests, SUM(bytes_sent_size) AS bytes_out
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
GROUP BY bucket_arn
ORDER BY requests DESC;
```

## 오류 해결
<a name="sal-cw-s3tables-errors"></a>

**Example 오류율 분석**  

```
SELECT http_status, error_code, operation, COUNT(*) AS error_count
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE http_status >= 400
GROUP BY http_status, error_code, operation
ORDER BY error_count DESC;
```

**Example 403 액세스 거부 요청**  

```
SELECT key_name, remote_ip, requester, COUNT(*) AS denied_count
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE http_status = 403
GROUP BY key_name, remote_ip, requester
ORDER BY denied_count DESC;
```

**Example 404 요청을 찾을 수 없음**  

```
SELECT key_name, error_code, remote_ip, COUNT(*) AS miss_count
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE http_status = 404
GROUP BY key_name, error_code, remote_ip
ORDER BY miss_count DESC;
```

**Example 503 속도 저하(스로틀링) 이벤트**  

```
SELECT key_name, remote_ip, COUNT(*) AS throttle_count
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE http_status = 503
GROUP BY key_name, remote_ip
ORDER BY throttle_count DESC;
```

## 액세스 패턴
<a name="sal-cw-s3tables-access"></a>

**Example 소스 IP별 트래픽**  

```
SELECT remote_ip,
  COUNT(*) AS total_requests,
  SUM(CASE WHEN http_status >= 400 THEN 1 ELSE 0 END) AS errors,
  SUM(bytes_sent_size) AS bytes_transferred
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
GROUP BY remote_ip
ORDER BY total_requests DESC;
```

**Example 요청자별 작업**  

```
SELECT requester, operation, COUNT(*) AS requests
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
GROUP BY requester, operation
ORDER BY requests DESC;
```

**Example 가장 많이 액세스한 키**  

```
SELECT key_name, COUNT(*) AS access_count, SUM(bytes_sent_size) AS bytes_out
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE operation IN ('REST.GET.OBJECT', 'REST.PUT.OBJECT')
GROUP BY key_name
ORDER BY access_count DESC
LIMIT 10;
```

## 지연 시간 분석
<a name="sal-cw-s3tables-latency"></a>

**Example 작업 유형별 지연 시간**  

```
SELECT operation,
  AVG(total_duration) AS avg_ms,
  APPROX_PERCENTILE(total_duration, 0.5) AS p50_ms,
  APPROX_PERCENTILE(total_duration, 0.95) AS p95_ms,
  MAX(total_duration) AS max_ms,
  COUNT(*) AS requests
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE operation IN ('REST.GET.OBJECT', 'REST.PUT.OBJECT')
GROUP BY operation;
```

**Example p95 지연 시간 기준으로 가장 느린 키**  

```
SELECT key_name,
  AVG(total_duration) AS avg_ms,
  APPROX_PERCENTILE(total_duration, 0.95) AS p95_ms,
  COUNT(*) AS requests
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE operation = 'REST.GET.OBJECT'
GROUP BY key_name
ORDER BY p95_ms DESC
LIMIT 10;
```

**Example 시간 경과에 따른 지연 시간**  

```
SELECT date_trunc('minute', request_time) AS interval,
  AVG(total_duration) AS avg_ms,
  APPROX_PERCENTILE(total_duration, 0.95) AS p95_ms
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE operation IN ('REST.GET.OBJECT', 'REST.PUT.OBJECT')
GROUP BY date_trunc('minute', request_time)
ORDER BY interval ASC;
```

## 비용 분담
<a name="sal-cw-s3tables-cost"></a>

**Example 작업별 데이터 전송**  

```
SELECT operation,
  SUM(bytes_sent_size) AS total_bytes_out,
  SUM(object_size) AS total_object_bytes,
  COUNT(*) AS request_count
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE operation IN ('REST.GET.OBJECT', 'REST.PUT.OBJECT', 'REST.DELETE.OBJECT')
GROUP BY operation
ORDER BY total_bytes_out DESC;
```

**Example 제공되는 가장 큰 객체**  

```
SELECT key_name, MAX(object_size) AS max_size, AVG(object_size) AS avg_size, COUNT(*) AS reads
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE operation = 'REST.GET.OBJECT' AND bytes_sent_size > 0
GROUP BY key_name
ORDER BY max_size DESC
LIMIT 10;
```

## 보안 분석
<a name="sal-cw-s3tables-security"></a>

**Example 오류율이 높은 IP**  

```
SELECT remote_ip,
  COUNT(*) AS total,
  SUM(CASE WHEN http_status >= 400 THEN 1 ELSE 0 END) AS errors
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
GROUP BY remote_ip
HAVING SUM(CASE WHEN http_status >= 400 THEN 1 ELSE 0 END) > 10
ORDER BY errors DESC;
```

**Example 키별 액세스 시도 실패**  

```
SELECT remote_ip, key_name, operation, http_status, COUNT(*) AS attempts
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
WHERE http_status >= 400
GROUP BY remote_ip, key_name, operation, http_status
ORDER BY attempts DESC
LIMIT 20;
```

**Example TLS 버전 배포**  

```
SELECT tls_version, COUNT(*) AS cnt
FROM "s3tablescatalog/aws-cloudwatch"."logs"."amazon_s3__server_access"
GROUP BY tls_version
ORDER BY cnt DESC;
```

## AI 에이전트를 사용하여 Amazon S3 서버 액세스 로그 쿼리
<a name="sal-cw-s3tables-ai-agents"></a>

MCP 호환 AI 에이전트는 Amazon S3 서버 액세스 로그가 포함된 S3 Tables를 검색하고, SQL 쿼리를 생성하며, 결과를 분석할 수 있습니다. Amazon S3 서버 액세스 로그는 `aws-cloudwatch` 테이블 버킷의 Iceberg 테이블로 내보내기 때문에 에이전트는 Amazon Athena, Amazon EMR, Amazon Redshift 또는 Iceberg 호환 도구와 함께 사용하는 것과 동일한 S3 Tables 카탈로그를 통해 쿼리할 수 있습니다.

[AWS용 에이전트 툴킷](https://github.com/aws/agent-toolkit-for-aws)은 에이전트가 AWS 데이터를 다룰 때 검증된 절차를 적용할 수 있도록 지원하는 스킬을 제공합니다. [CloudWatch Logs 시스템 테이블 쿼리](https://github.com/aws/agent-toolkit-for-aws/tree/main/skills/specialized-skills/system-table-skills/querying-aws-cloudwatch) 스킬은 `aws-cloudwatch` 테이블 버킷의 Amazon S3 서버 액세스 로그를 포함하여 S3 Tables로 내보낸 CloudWatch Logs 데이터에 대해 SQL 쿼리를 실행합니다. 이를 사용하려면 GitHub의 리포지토리에서 스킬을 다운로드하여 에이전트의 스킬 디렉터리에 추가합니다.

예를 들어 에이전트에게 지난 24시간 동안 S3 서버 액세스 로그에 요청 수별로 상위 10개의 소스 IP 주소를 표시하도록 요청할 수 있습니다. 에이전트는 스킬을 사용하여 액세스 로그 테이블을 찾고 Athena에서 쿼리를 실행합니다.