1 Azure Blob Storage란?
Azure Blob Storage는 Microsoft Azure에서 제공하는 객체 스토리지 서비스로, RAG 시스템의 문서 저장소로 사용된다. 비정형 데이터(PDF, Word, 이미지 등)를 대용량으로 저장하고 관리할 수 있는 확장 가능한 클라우드 스토리지다.
RAG 파이프라인에서의 역할:
- 원본 문서 저장 (PDF, DOCX, PPTX, 이미지 등)
- 전처리된 텍스트 저장
- 메타데이터 및 인덱스 백업
- 대용량 데이터셋 관리
주요 특징:
- 확장성: EB(Exabyte) 규모까지 자동 확장
- 내구성: 99.999999999% (11 nine’s) 데이터 내구성
- 비용 효율성: 계층형 스토리지로 비용 최적화
- 보안: 암호화, RBAC, Private Endpoint 지원
2 Blob Storage 계층
Azure Blob Storage는 데이터 액세스 패턴에 따라 3가지 계층을 제공한다:
| 계층 | 용도 | 가격 (GB/월) | 읽기 비용 | 적합한 시나리오 |
|---|---|---|---|---|
| Hot | 자주 액세스 | $0.0184 | 낮음 | RAG 운영 문서, 활성 데이터셋 |
| Cool | 가끔 액세스 | $0.01 | 중간 | 아카이브 문서, 백업 |
| Archive | 거의 없음 | $0.002 | 높음 | 장기 보관, 규정 준수 데이터 |
RAG 시스템 권장 사항:
- Hot 계층: 현재 RAG에서 사용 중인 문서
- Cool 계층: 3개월 이상 미사용 문서
- Archive 계층: 법적 보관 의무만 있는 문서
3 Storage Account 생성
3.1 Azure Portal에서 생성
1. Azure Portal 접속:
- portal.azure.com → “리소스 만들기”
- “Storage Account” 검색 및 선택
2. 기본 설정:
- 구독: 사용할 구독 선택
- 리소스 그룹: 새로 만들기 또는 기존 선택 (예: rg-rag-prod)
- Storage Account 이름: 전역적으로 고유한 이름 (예: stragdocs2025)
- 지역: Korea Central 또는 Korea South
- 성능: Standard (대부분의 경우 충분)
- 중복성:
- LRS (Locally Redundant Storage): 단일 데이터센터 내 3개 복제
- GRS (Geo-Redundant Storage): 다른 리전에 자동 복제 (권장)
3. 고급 설정:
- 보안:
- Require secure transfer (HTTPS 강제)
- Enable blob public access (나중에 제어 가능)
- Data Lake Storage Gen2: RAG에서는 불필요
- Blob soft delete: 7일 (실수로 삭제 방지)
4. 네트워킹:
- 연결 방법:
- Public endpoint (개발): 모든 네트워크에서 액세스
- Private endpoint (프로덕션): VNet 내에서만 액세스
5. 검토 + 만들기 → 생성 완료 (약 1분 소요)
3.2 Azure CLI로 생성
# Azure CLI 로그인
az login
# 리소스 그룹 생성
az group create \
--name rg-rag-prod \
--location koreacentral
# Storage Account 생성
az storage account create \
--name stragdocs2025 \
--resource-group rg-rag-prod \
--location koreacentral \
--sku Standard_GRS \
--kind StorageV2 \
--https-only true \
--allow-blob-public-access false
# 생성 확인
az storage account show \
--name stragdocs2025 \
--resource-group rg-rag-prod \
--query "[name, location, sku.name]" 4 컨테이너 생성
Blob Storage에서 컨테이너는 파일 시스템의 폴더와 유사한 개념이다.
4.1 Azure Portal에서 생성
- Storage Account → “컨테이너” 메뉴
- “+ 컨테이너” 클릭
- 설정:
- 이름:
rag-documents(소문자, 하이픈만 허용)
- Public access level: Private (권장)
- 이름:
- “만들기” 클릭
4.2 Python SDK로 생성
from azure.storage.blob import BlobServiceClient
from dotenv import load_dotenv
import os
load_dotenv()
# 환경 변수에서 연결 문자열 가져오기
connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING")
# BlobServiceClient 생성
blob_service_client = BlobServiceClient.from_connection_string(connection_string)
# 컨테이너 생성
container_name = "rag-documents"
container_client = blob_service_client.create_container(container_name)
print(f"컨테이너 '{container_name}' 생성 완료") 환경 변수 설정 (.env 파일):
AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=stragdocs2025;AccountKey=xxx;EndpointSuffix=core.windows.net
5 문서 업로드
5.1 단일 파일 업로드
5.2 여러 파일 일괄 업로드
import os
from pathlib import Path
def upload_directory(container_name, local_directory):
"""디렉토리 내 모든 파일을 Blob Storage에 업로드"""
container_client = blob_service_client.get_container_client(container_name)
# 로컬 디렉토리의 모든 파일 탐색
for root, dirs, files in os.walk(local_directory):
for file in files:
file_path = os.path.join(root, file)
# Blob 이름 생성 (디렉토리 구조 유지)
blob_name = os.path.relpath(file_path, local_directory).replace("\\", "/")
# 파일 업로드
with open(file_path, "rb") as data:
blob_client = container_client.get_blob_client(blob_name)
blob_client.upload_blob(data, overwrite=True)
print(f"업로드: {blob_name}")
# 사용 예시
upload_directory("rag-documents", "./documents") 5.3 메타데이터와 함께 업로드
from datetime import datetime
# 메타데이터 정의
metadata = {
"author": "Kwangmin Kim",
"category": "AI",
"upload_date": datetime.now().isoformat(),
"version": "1.0"
}
# 메타데이터와 함께 업로드
with open("report.pdf", "rb") as data:
blob_client = blob_service_client.get_blob_client(
container="rag-documents",
blob="report.pdf"
)
blob_client.upload_blob(
data,
metadata=metadata,
overwrite=True
)
print("메타데이터와 함께 업로드 완료") 6 문서 다운로드
6.1 단일 파일 다운로드
6.2 스트리밍 다운로드 (대용량 파일)
7 문서 목록 조회
7.1 컨테이너 내 모든 Blob 나열
7.2 메타데이터 포함 조회
7.3 특정 접두사로 필터링
8 문서 삭제
8.1 단일 파일 삭제
8.2 조건부 삭제 (오래된 파일만)
from datetime import datetime, timedelta
# 30일 이상 된 파일 삭제
threshold_date = datetime.now() - timedelta(days=30)
container_client = blob_service_client.get_container_client("rag-documents")
blob_list = container_client.list_blobs()
for blob in blob_list:
if blob.last_modified < threshold_date:
blob_client = container_client.get_blob_client(blob.name)
blob_client.delete_blob()
print(f"삭제: {blob.name} (수정일: {blob.last_modified})") 10 RAG 파이프라인 통합
10.1 문서 로딩 함수
from typing import List
from langchain_core.documents import Document
def load_documents_from_blob(
container_name: str,
prefix: str = ""
) -> List[Document]:
"""Azure Blob Storage에서 문서 로딩"""
container_client = blob_service_client.get_container_client(container_name)
blob_list = container_client.list_blobs(
name_starts_with=prefix,
include=['metadata']
)
documents = []
for blob in blob_list:
# 지원 파일 형식만 처리
if blob.name.endswith(('.pdf', '.txt', '.docx')):
# Blob 다운로드
blob_client = container_client.get_blob_client(blob.name)
content = blob_client.download_blob().readall()
# Document 객체 생성
doc = Document(
page_content=content.decode('utf-8', errors='ignore'),
metadata={
"source": blob.name,
"size": blob.size,
"last_modified": blob.last_modified.isoformat(),
**blob.metadata # Blob 메타데이터 추가
}
)
documents.append(doc)
return documents
# 사용 예시
documents = load_documents_from_blob("rag-documents", prefix="reports/")
print(f"로딩된 문서 수: {len(documents)}") 10.2 LangChain AzureBlobStorageLoader 사용
from langchain_community.document_loaders import AzureBlobStorageFileLoader
# Azure Blob Storage에서 파일 로딩
loader = AzureBlobStorageFileLoader(
conn_str=os.getenv("AZURE_STORAGE_CONNECTION_STRING"),
container="rag-documents",
blob_name="sample.pdf"
)
documents = loader.load()
print(f"로딩된 문서: {len(documents)}")
print(f"첫 번째 문서 내용 (앞 200자):\n{documents[0].page_content[:200]}") 11 비용 최적화
11.1 수명 주기 관리 정책
Azure Portal에서 설정:
1. Storage Account → “수명 주기 관리”
2. “+ 규칙 추가”
3. 규칙 정의:
예시: 자동 계층 전환
{
"rules": [
{
"name": "move-to-cool",
"enabled": true,
"type": "Lifecycle",
"definition": {
"filters": {
"blobTypes": ["blockBlob"],
"prefixMatch": ["rag-documents/"]
},
"actions": {
"baseBlob": {
"tierToCool": {
"daysAfterModificationGreaterThan": 90
},
"tierToArchive": {
"daysAfterModificationGreaterThan": 365
},
"delete": {
"daysAfterModificationGreaterThan": 730
}
}
}
}
}
]
} 의미:
- 90일 미사용 → Cool 계층 전환
- 365일 미사용 → Archive 계층 전환
- 730일(2년) 후 → 자동 삭제
11.2 압축 저장
import gzip
# 텍스트 파일 압축 후 업로드
with open("large_document.txt", "rb") as f:
content = f.read()
compressed = gzip.compress(content)
blob_client = blob_service_client.get_blob_client(
container="rag-documents",
blob="large_document.txt.gz"
)
blob_client.upload_blob(
compressed,
metadata={"compressed": "gzip"},
overwrite=True
)
print(f"원본 크기: {len(content)} bytes")
print(f"압축 크기: {len(compressed)} bytes ({len(compressed)/len(content)*100:.1f}%)") 12 보안 설정
12.1 Managed Identity로 인증
from azure.identity import DefaultAzureCredential
# Managed Identity 사용 (키 노출 없음)
credential = DefaultAzureCredential()
blob_service_client = BlobServiceClient(
account_url="https://stragdocs2025.blob.core.windows.net",
credential=credential
)
# 이후 동일하게 사용
container_client = blob_service_client.get_container_client("rag-documents") Managed Identity 설정:
1. Azure Function/Container App → “ID” → “시스템 할당 관리 ID” 활성화
2. Storage Account → “액세스 제어(IAM)” → “역할 할당 추가”
3. 역할: “Storage Blob Data Contributor”
4. 할당 대상: 생성된 Managed Identity
12.2 Private Endpoint 설정
- Storage Account → “네트워킹” → “프라이빗 엔드포인트 연결”
- “+ 프라이빗 엔드포인트” 클릭
- 설정:
- 리소스 그룹 선택
- 이름:
pe-storage-rag
- 대상 하위 리소스:
blob
- 가상 네트워크 및 서브넷 선택
- 리소스 그룹 선택
- “만들기” → VNet 내에서만 액세스 가능
13 모니터링
13.1 Storage Analytics 활성화
from azure.storage.blob import BlobAnalyticsLogging, Metrics, RetentionPolicy
# Analytics 설정
logging = BlobAnalyticsLogging(
version="1.0",
delete=True,
read=True,
write=True,
retention_policy=RetentionPolicy(enabled=True, days=7)
)
metrics = Metrics(
version="1.0",
enabled=True,
include_apis=True,
retention_policy=RetentionPolicy(enabled=True, days=7)
)
# 설정 적용
blob_service_client.set_service_properties(
analytics_logging=logging,
hour_metrics=metrics,
minute_metrics=metrics
)
print("Storage Analytics 활성화 완료") 13.2 주요 메트릭
Azure Portal → Storage Account → “메트릭”:
- Transactions: 요청 수 (GET, PUT, DELETE)
- Ingress/Egress: 업로드/다운로드 데이터량
- Availability: 가동률
- Success E2E Latency: 종단 간 응답 시간
14 문제 해결
14.1 일반적인 오류
1. AuthorizationPermissionMismatch
오류: 권한 없음
해결: Storage Account IAM에서 "Storage Blob Data Contributor" 역할 추가
2. ContainerNotFound
# 컨테이너 존재 확인 후 생성
try:
container_client = blob_service_client.get_container_client("rag-documents")
container_client.get_container_properties()
except Exception:
container_client.create_container() 3. BlobNotFound
15 참고 자료
15.1 공식 문서
15.2 샘플 코드
16 다음 단계
문서 저장이 완료되었다면, 이제 OCR 및 레이아웃 분석 단계로 넘어가자:
👉 02-Document-Intelligence.qmd - Azure Document Intelligence를 활용한 문서 분석