Insupanda 프로젝트는 다음과 같은 단계로 진화했습니다:
처음에는 간단한 구성으로 쿠버네티스의 EmptyDir 볼륨을 사용했습니다:
volumes:
- name: data-volume
emptyDir: {}
문제점:
2-Tier 구조로 전환하면서 영구 스토리지가 필요해졌고, EBS를 선택했습니다:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: vector-db-pvc
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp2
resources:
requests:
storage: 10Gi
장점:
한계:
"EBS 볼륨이 EC2 인스턴스에 연결되지 않음"
3-Tier 아키텍처 완성과 함께 S3로 전환한 이유:
가용성 영역 제약 극복
확장성 향상
비용 효율성
분산 시스템 지원
class RAGService:
def __init__(self):
# S3 연결 설정
self.use_s3 = os.getenv("USE_S3", "false").lower() == "true"
self.s3_bucket = os.getenv("S3_BUCKET_NAME")
self.s3_prefix = os.getenv("S3_PREFIX", "vector_db")
if self.use_s3:
import boto3
self.s3_client = boto3.client('s3')
def load_collection(self, collection_name):
if self.use_s3:
# S3에서 데이터 로드
s3_path = f"{self.s3_prefix}/{collection_name}"
# S3 처리 로직...
else:
# 로컬 파일시스템 로직...
apiVersion: v1
kind: ConfigMap
metadata:
name: insupanda-config
data:
USE_S3: "true"
S3_PREFIX: "vector_db"
AWS_REGION: "ap-northeast-2"
apiVersion: v1
kind: Secret
metadata:
name: insupanda-secrets
type: Opaque
data:
AWS_ACCESS_KEY_ID: "<base64_encoded>"
AWS_SECRET_ACCESS_KEY: "<base64_encoded>"
S3_BUCKET_NAME: "<base64_encoded>"
# 이전: 볼륨 마운트 포함
spec:
containers:
- name: backend
volumeMounts:
- name: vector-db
mountPath: /app/vector_db
volumes:
- name: vector-db
persistentVolumeClaim:
claimName: vector-db-pvc
# 이후: 볼륨 마운트 제거, S3 사용
spec:
containers:
- name: backend
# 볼륨 마운트 없음, S3에서 직접 로드
apiVersion: batch/v1
kind: Job
metadata:
name: vector-db-init
spec:
template:
spec:
containers:
- name: init
command: ["/bin/sh", "-c"]
args:
- |
# S3 버킷 확인 및 초기화
if ! aws s3 ls s3://${S3_BUCKET_NAME}/${S3_PREFIX}/; then
# 초기 데이터 S3에 업로드
aws s3 sync /app/initial_data/ s3://${S3_BUCKET_NAME}/${S3_PREFIX}/
fi
최종적으로 Insupanda 프로젝트는 다음과 같은 3-Tier 아키텍처로 완성되었습니다:
프론트엔드 계층
백엔드 계층
데이터 계층
이 문서는 3-Tier 프로젝트의 스토리지 전략 진화와 3-Tier 아키텍처 구현에 관한 가이드입니다. 프로젝트 초기 단계에서는 단순한 구성으로 시작했지만, 운영 경험을 통해 점진적으로 개선되었습니다. EBS의 한계를 경험한 후 S3로 전환함으로써 보다 견고하고 확장 가능한 시스템을 구축할 수 있었습니다.