26Y05a

Young-Kyoo Kim·2026년 7월 5일

기존에 계획하셨던 무거운 이벤트 기반 아키텍처(Kafka + Redis + 대규모 Meta DB) 대신, "기존 API Server 기능을 일부 확장하고 MinIO AIStor의 순정 API 및 엔터프라이즈 기능을 최대한 활용하는 방향(Thin API + Fat Storage)"으로의 선회는 매우 현명한 결정입니다. 500~1,000개 노드 규모의 에어갭 환경에서 운영 오버헤드를 극적으로 줄일 수 있는 현실적인 접근입니다.

제시해주신 26가지 요구사항을 분석하여 [AIStor 순정 기능으로 즉시 진행 가능한 부분]과 [순정 기능만으로는 안 되어 최소한의 가벼운 로직/DB 보완이 필요한 부분]으로 명확히 분류하고, 이에 따른 한계와 구체적인 대안을 가이드해 드립니다.


1. 요구사항별 AIStor 매핑 및 가능 여부 분류

① AIStor 순정 기능 및 최소한의 API 래핑으로 진행 가능한 부분 (Feasible)

스토리지 고유의 기능이거나 표준 S3 API 규격 내에서 해결되는 요건들입니다. 복잡한 비동기 이벤트 파이프라인 없이 기존 API Server가 MinIO SDK를 호출하는 것만으로 구현 가능합니다.

분류ID요구사항명AIStor 순정 기능 대응 및 가이드
Prefix 라이프사이클REQ-01-01

REQ-01-02
Prefix 동적 생성

플레이스홀더 자동 생성
S3 규격상 폴더는 실존하지 않으므로, API Server가 새 프리픽스 경로 끝에 .placeholder (또는 .keep) 이름의 빈 객체를 PutObject로 생성해 주면 가상 디렉터리가 즉시 유지됩니다.
REQ-01-05하위 객체 리스트 조회표준 S3 ListObjectsV2 API의 Prefix, Delimiter, ContinuationToken을 사용하면 AIStor 자체 엔진이 페이징 처리를 수행하므로 API Server는 단순 전달만 하면 됩니다.
REQ-01-08하위 객체 일괄 삭제S3 표준 DeleteObjects (Multi-Object Delete) API를 호출하거나, MinIO 내장 Batch Jobs (Batch Delete) 기능을 트리거하여 스토리지 백엔드에 삭제 연산을 위임합니다.
REQ-01-09소프트 삭제 및 보존 정책AIStor의 Bucket Versioning을 활성화하고 ILM (Lifecycle) Policy 규칙을 설정합니다. 삭제 시 DeleteMarker가 생성되며, 설정한 기간(예: 30일) 후 NoncurrentVersionExpiration에 의해 백그라운드에서 자동 영구 삭제됩니다.
인증 및 인가REQ-02-01

REQ-02-02

REQ-02-03

REQ-02-04
테넌트별 인증/인가 및 권한 분리AIStor IAM 엔진 고유 기능입니다. 사내 AD/LDAP을 연동하고, 정책 변수(${aws:username})가 포함된 단 하나의 글로벌 Policy만 등록해 두면, STS AssumeRole을 통해 발급된 임시 토큰으로 AIStor가 알아서 타인 경로 접근을 차단(Access Denied)하고 Read/Write 권한을 격리합니다.
모니터링REQ-04-01전체 Bucket 메트릭 수집AIStor가 자체 노출하는 Prometheus v3 메트릭 프리미티브(minio_cluster_usage_buckets_...)를 연동하여 즉시 수집 가능합니다.
안정성 및 로그REQ-06-02행위 추적을 위한 LoggingAIStor의 Audit Log 기능이 내부 API 호출 내역(사번 계정, 출발지 IP, 수행 API 종류)을 자체 수집하므로, 이를 기존 웹훅/카프카 타겟으로 지정하여 사내 로그 솔루션(Opensearch 등)으로 쏘아주기만 하면 됩니다.
REQ-06-03정기 동기화 보정 배치AIStor의 Inventory API를 활성화하면 매일 새벽 전체 객체 상태를 Parquet 파일로 덤프해 줍니다. 이 파일을 배치 프로세스가 읽어 정합성을 검증하면 됩니다.

② AIStor 순정 기능만으로는 진행 불가능한 부분 (Infeasible / Alternative Needed)

S3 아키텍처 특성상 'Prefix(가상 경로)' 단위로는 지원하지 않는 영역입니다. 가장 치명적인 부분은 Prefix 단위의 저장 용량(Byte) 규제 기능이 없다는 점입니다.

분류ID요구사항명미지원 사유 및 한계
Prefix 라이프사이클REQ-01-03

REQ-01-04
Prefix 목록 및 상태 조회S3 규격상 Prefix 자체에는 생성일, 소유자, 상태 등의 메타데이터(Timestamp)가 존재하지 않아 조회가 불가능합니다.
REQ-01-06

REQ-01-07
Prefix 메타데이터(별칭) 수정AIStor에는 Prefix에 별칭(Alias을 부여하는 기능이 없습니다.
용량 쿼터 관리REQ-03-01

REQ-03-02

REQ-03-03
Prefix 단위 쿼터 설정 및 쓰기 제한AIStor의 최대 제약 사항. AIStor는 버킷 단위 쿼터(mc quota set)Prefix 단위 요청 속도/동시성 제한(mc qos)은 지원하지만, Prefix 단위의 누적 저장 용량(Byte) 하드 제한 기능은 존재하지 않습니다.
모니터링 & 알람REQ-04-02

REQ-05-01~04
Prefix별 시계열 가공 및 쿼터 임계치 알람AIStor 내장 메트릭은 버킷 중심이므로 Prefix 단위의 일일 용량 증가율이나 쿼터 임계치(80%, 100%) 도달 여부를 AIStor 스스로 판단하여 알람을 보낼 수 없습니다.

2. 핵심 블록별 한계 극복을 위한 최소화 대안 (Lightweight Workarounds)

원래 계획했던 'Kafka + Redis + 복잡한 Consumer 파이프라인'을 전면 전개하지 않고, 기존 API Server에 아주 가벼운 RDB(예: 단일 PostgreSQL 또는 MariaDB) 테이블 1~2개만 추가하여 위 한계들을 우아하게 해결하는 아키텍처 슬리밍(Slimming) 대안입니다.

대안 A: Prefix 메타 및 별칭 관리 (REQ-01-03, 04, 06, 07 해결)

  • 한계: Prefix 자체의 생성일, 소유자, 별칭을 스토리지에서 알 방법이 없음.
  • 대안: 기존 API Server가 바라보는 DB에 Object 단위가 아닌, 오직 [Prefix 마스터 테이블] 하나만 가볍게 생성합니다.

    테이블 스키마 필드 예시: id, prefix_path, owner_sabun, alias_name, created_at, hard_quota_bytes, current_usage_bytes

  • 동작: 사용자가 API Server를 통해 Prefix를 조회/수정할 때, AIStor를 찌르는 것이 아니라 이 가벼운 마스터 테이블만 CRUD 합니다. Object 단위의 메타데이터가 아니므로 데이터양이 극히 적어 별도의 캐시(Redis)조차 필요 없습니다.

대안 B: Prefix 단위 용량 쿼터(Byte) 제어 및 알람 (REQ-03-01~03, REQ-05-01~04 해결)

  • 한계: AIStor는 Prefix별 저장 용량(Byte) 제한 및 실시간 차단 기능이 없음. (mc qos는 RPS/동시성만 제어 가능).
  • 대안 (Inventory API 기반 일괄 집계 + API URL 발급 차단):
  1. 야간 배치 싱크: AIStor가 매일 새벽 자동으로 떨어뜨려 주는 Inventory Parquet 리포트를 백엔드 크론잡(Batch)이 읽어 들입니다. DuckDB나 가벼운 스크립트를 쓰면 수억 건의 레코드라도 단 몇 분 만에 Prefix별 SUM(size)을 계산할 수 있습니다. 계산된 값을 위 마스터 테이블의 current_usage_bytes 컬럼에 하루에 한 번 업데이트합니다.
  2. API Server 진입점 차단: 유저가 파일 업로드를 위해 API Server에 Pre-signed URL을 요청할 때, API Server는 DB 마스터 테이블에서 해당 Prefix의 [어제 자 누적 용량 + 현재 업로드하려는 파일 크기]를 더해 hard_quota_bytes를 초과하는지 체크합니다. 초과 시 URL 발급을 거부(403 Deny)합니다.
  3. 알람 처리: 야간 배치 도중 current_usage_bytes가 설정된 soft_limit(80%)이나 hard_limit을 넘은 테넌트들을 골라내어 사내 알람 시스템(큐브)으로 웹훅을 한 번에 쏘아줍니다.

3. 추천하는 '최소 다이어트' 아키텍처 요약

이 방식을 채택하면 시스템 구조가 아래와 같이 극적으로 단순해집니다.

[유저 요청] ──> [ 기존 API Server ] ─── (Pre-signed URL 발급) ───> [ 유저 ]
                       │                                             │
             (1. DB에서 어제 자 용량                                   (2. AIStor로 
              기반 쿼터 고속 체크)                                     직접 업로드)
                       │                                             │
                       ▼                                             ▼
            [ 초경량 Prefix 마스터 DB ]                       [ MinIO AIStor ]
                       ▲                                             │
                       │                                  (새벽마다 전체 스캔 자동 덤프)
                 (3. 일일 용량 갱신)                                   │
                       │                                             ▼
            [ 야간 Inventory 분석 Batch ] <── (Parquet 읽기) ── [ Inventory 버킷 ]
  • 포기하는 것: 실시간 바이트 단위 용량 규제 (수 분 내에 수백 GB를 동시에 몰아서 올리는 경우 하루 동안은 쿼터를 초과하여 업로드될 수 있음).
  • 얻는 것: Kafka 클러스터 구축 취소, Redis 클러스터 구축 취소, 실시간 이벤트 컨슈머 개발 취소. 이로 인해 1차년도 개발 공수(M/M)를 최소 60~70% 이상 절감할 수 있으며, 인프라 안전성은 수십 배 올라갑니다.

현재 인프라를 이용할 현업 부서나 유저들의 업로드 패턴을 고려했을 때, '실시간 바이트 차단'을 양보하고 위와 같은 '야간 배치 정합성 기반의 하루 주기 쿼터 규제 및 차단 방식'으로 현업 요구사항 유관 부서와 타협할 수 있는 여지가 있으신가요?

===

정확하고 아주 날카로운 지적입니다. 인프라와 스토리지의 보안 메커니즘을 깊게 이해하고 계셔야만 잡을 수 있는 핵심 허점입니다.

사용자가 API Server를 우회하여 MinIO Console(Object Browser) UI나 mc CLI 툴을 통해 S3 엔드포인트로 직접 PutObject API를 호출하면, 앞서 말씀드린 Pre-signed URL 기반의 진입점 차단 방식은 무력화됩니다.

하지만 MinIO AIStor의 강력한 IAM 정책 엔진과 Admin API를 ‘스위치’처럼 활용하면, Kafka나 Redis 같은 무거운 대량 트래픽 처리 인프라 없이도 이 직통 경로를 아주 효과적으로 틀어막을 수 있습니다. 크게 3가지 현실적인 대응 전략을 제시해 드립니다.


전략 1. 가벼운 웹훅(Webhook) + Admin API 동적 정책 매핑 (추천)

"첫 발은 허용하되, 연사(Continuous Upload)는 수초 내에 즉시 차단하는 방식"

Kafka 클러스터를 구축하지 않더라도, MinIO 내부의 이벤트 서브시스템은 API Server의 특정 HTTP Endpoint로 직접 이벤트를 던지는 순정 Webhook 드라이버를 제공합니다.

  • 동작 매커니즘:
  1. 유저가 mc나 웹 UI로 파일 업로드를 시작합니다.
  2. 파일 하나가 올라갈 때마다 MinIO가 API Server의 가벼운 웹훅 URL(/api/v1/event-webhook)로 파일 크기 정보를 던집니다.
  3. API Server는 가벼운 메타 DB의 현재 용량 값을 올리고 쿼터 초과 여부를 검사합니다.
  4. [핵심] 만약 쿼터가 초과되었다면, API Server는 MinIO의 Admin Go SDK(또는 mc admin policy attach)를 호출하여 해당 유저나 AD 그룹에 명시적 쓰기 금지(Deny PutObject) 정책을 실시간으로 강제 바인딩해 버립니다.
  • 효과: 사용자가 mc mirror나 대용량 폴더 업로드를 걸어두었더라도, 몇 개 파일이 올라간 직후(수초 내)에 전체 권한이 Access Denied로 동결되므로 스토리지 폭발을 막을 수 있습니다.

전략 2. 권한 격리를 통한 'Direct Write' 원천 차단

"직접 접속(Console/mc)은 Read-Only만 허용하고, Write는 오직 API Server만 가능하게 분리"

엔터프라이즈 데이터 레이크하우스에서 거버넌스를 유지하기 위해 가장 흔히 쓰는 패러다임입니다. 유저의 접속 경로에 따라 권한을 다르게 부여하는 방식입니다.

  • 동작 매커니즘:
  • Direct 경로 (Console UI / mc CLI): 이 경로로 로그인할 때는 전사 AD 권한에 의해 오직 s3:ListBuckets3:GetObject (읽기 전용) 권한만 가진 STS 토큰이 발급되도록 MinIO IAM Policy를 고정합니다.
  • Write 경로 (데이터 업로드): 데이터를 적재하거나 업로드할 때는 무조건 기존 API Server가 발행한 Pre-signed URL을 통해서만 PutObject가 가능하게 제한합니다.
  • 효과: 사용자가 mc나 웹 UI를 아무리 조작해도 파일 업로드 버튼 자체가 비활성화되거나 권한 에러가 나므로, 우회 업로드 가능성이 원천 봉쇄됩니다.

전략 3. Policy Condition을 통한 단일 파일 최대 크기 규제 (보완책)

"한 번의 우회 업로드로 수 TB를 밀어 넣어 시스템을 마비시키는 상황 방지"

배치나 가벼운 웹훅이 돌기 전, 단 한 번의 직접 호출(mc cp)로 수백 GB나 수 TB짜리 대형 압축 파일을 밀어 넣어 쿼터를 대규모로 초과하는 엣지 케이스를 방지하는 안전장치입니다.

  • 동작 매커니즘:
  • MinIO IAM 글로벌 정책에 s3:object-size-less-than 조건을 추가하여, 직접 권한으로 올릴 수 있는 단일 파일의 최대 크기를 엄격하게 제한합니다 (예: 단일 파일은 최대 5GB까지만 허용).
"Condition": {
    "NumericLessThan": {
        "s3:object-size-less-than": [5368709120]
    }
}
  • 효과: 사용자가 우회를 하더라도 시스템에 치명적인 수준의 대용량 데이터를 한 번에 박아 넣는 행위 자체가 스토리지 자체 규칙에 의해 거부됩니다.

요약 및 권장 가이드

가장 현실적이고 완벽한 조합은 [전략 1 (가벼운 웹훅 기반 동적 Deny 정책 부여)] + [전략 3 (단일 파일 크기 제한)]의 결합입니다.

이렇게 구성하시면 Kafka/Redis 클러스터라는 거대한 인프라 부채를 전혀 지지 않고도, 기존 API Server에 '이벤트 수신 엔드포인트 1개'와 'MinIO Admin SDK를 통한 Policy Attach 로직 1개'만 추가하여 mc와 Object Browser 우회 경로까지 완벽하게 통제권 안에 넣을 수 있습니다.

혹시 사내 유저들이 mc나 Console UI를 통해 데이터를 '직접 업로드(Write)' 해야만 하는 필수적인 비즈니스 요구사항이나 워크플로우가 존재하나요?

==

0개의 댓글