MinIO AIStor S3 API를 통해 S3 호환 SDK(boto3, s3fs, minio-py 등)로 Parquet 파일 스트림을 로컬 디스크 다운로드 없이 메모리상에서 바로 Pandas DataFrame으로 읽어올 수 있습니다.
방법 A. s3fs + pandas 조합 (가장 간결한 방식)
별도 임시 파일 저장 없이 MinIO 엔드포인트에 직접 연결하여 pd.read_parquet()으로 즉시 로드합니다.
import pandas as pd
# AIStor S3 접속 정보 설정
storage_options = {
"key": "YOUR_MINIO_ACCESS_KEY",
"secret": "YOUR_MINIO_SECRET_KEY",
"client_kwargs": {
"endpoint_url": "http://minio-aistor.example.com:9000", # AIStor S3 Endpoint
"verify": False # SSL 검증 필요 여부
}
}
# AIStor에 저장된 인벤토리 Parquet S3 경로
s3_parquet_path = "s3://system-inventory-bucket/2026-08-07/inventory.parquet"
# 메모리로 직접 읽기
df_inv = pd.read_parquet(s3_parquet_path, storage_options=storage_options)
방법 B. minio-py SDK + io.BytesIO 조합
import io
from minio import Minio
import pandas as pd
client = Minio(
"minio-aistor.example.com:9000",
access_key="YOUR_MINIO_ACCESS_KEY",
secret_key="YOUR_MINIO_SECRET_KEY",
secure=False
)
# AIStor 버킷 내 인벤토리 오브젝트 가져오기
response = client.get_object("system-inventory-bucket", "2026-08-07/inventory.parquet")
# 메모리 버퍼(BytesIO)에 담아 Pandas로 처리
df_inv = pd.read_parquet(io.BytesIO(response.read()))
response.close()
response.release_conn()
MinIO AIStor/S3 Standard Inventory Report Parquet 파일에는 아래와 같은 컬럼들이 포함되어 있으며, Reconciliation(동기화) 스크립트에서는 3가지 필수 컬럼이 필요합니다.
| 컬럼명 | 타입 | Reconciliation 필수 여부 | 설명 |
|---|---|---|---|
key (또나 name) | String | 필수 | 객체의 전체 경로 (photos/2026/img.png) |
size | Int64 | 필수 | 객체 용량 (Bytes) |
etag | String | 선택 (권장) | 객체의 ETag/MD5 Hash 값 |
last_modified | Timestamp | 선택 | 객체 최종 수정 시각 (주로 epoch/nanosecond) |
bucket | String | 선택 | 버킷 이름 (인벤토리가 버킷별로 생성된 경우 생략 가능) |
is_latest | Boolean | 선택 | 버저닝 사용 시 최신 버전 여부 (True/False) |
is_delete_marker | Boolean | 선택 | 버저닝 삭제 마커 여부 |
AIStor 인벤토리 설정에 따라 key가 name으로 나오거나 etag가 e_tag로 나오는 경우를 대비해 스크립트 상단에 아래 변환 로직을 추가하면 안정적입니다.
# 컬럼명 유연화 매핑 처리
column_mapping = {
'name': 'key',
'object_name': 'key',
'e_tag': 'etag',
'last_modified_date': 'last_modified'
}
df_inv = df_inv.rename(columns=column_mapping)
# 필수 컬럼 존재 여부 체크
required_cols = ['key', 'size']
for col in required_cols:
if col not in df_inv.columns:
raise ValueError(f"Inventory Parquet missing required column: '{col}'")