Skip to main content

Docs

이 문서는 프로젝트의 인프라 구성 및 서비스 배포 방법에 대해 설명합니다.

문서 서버 배포 현황

Main 브랜치 (Production) - AWS

현재 AWS 기반의 문서 서버 배포가 완료되었습니다.

  • 접속 주소: https://d27m5suuea0hki.cloudfront.net/
  • 배포 방식: docs 서브모듈 Github 레포지토리의 main 브랜치에 Push가 발생하면, Github Actions가 자동으로 빌드 및 S3 배포, CloudFront 캐시 무효화를 수행합니다. (CI/CD 적용 완료)

Development 브랜치 (Preview) - Vercel

개발 및 테스트를 위한 development 브랜치의 Preview 배포가 Vercel을 통해 새로 구성되었습니다.

  • 접속 주소: (Vercel 배포 후 확인된 주소로 업데이트 예정)
  • 배포 방식: docs 서브모듈 Github 레포지토리의 development 브랜치에 Push가 발생하면, Vercel이 자동으로 빌드 및 배포를 수행합니다.

문서 사이트 아키텍처 (AWS)

문서 사이트는 S3 + CloudFront 조합의 아키텍처를 사용합니다.

  • AWS S3 (스토리지 및 호스팅): Docusaurus 빌드 결과물(HTML, CSS, JS 등 정적 파일)을 저장하고, 정적 웹사이트 호스팅을 담당합니다.

  • Amazon CloudFront (CDN 및 보안): 사용자의 모든 요청을 받는 단일 진입점입니다. HTTPS 보안을 적용하고, 전 세계 사용자에게 콘텐츠를 빠르게 전송(CDN)하며, OAC(Origin Access Control) 설정을 통해 S3 버킷에 대한 접근을 CloudFront로만 제한하여 보안을 강화합니다.


배포 방법

자동 배포 (Github Actions 권장)

docs 레포지토리의 main 브랜치에 변경사항을 Push하는 것만으로 배포의 모든 과정이 자동으로 처리됩니다.

  • 트리거: docs Github 레포지토리의 main 브랜치에 코드가 Push될 때마다 파이프라인이 자동으로 실행됩니다.
  • 실행 과정:
    1. Github Actions 워크플로우가 실행됩니다. (docs/.github/workflows/deploy.yml)
    2. Docusaurus 사이트를 빌드합니다. (npm run build)
    3. 빌드 결과물을 S3 버킷(vivid-ai-docs-dev)에 업로드합니다.
    4. CloudFront 캐시를 무효화(Invalidation)하여 사용자가 즉시 최신 내용을 볼 수 있도록 합니다.
  • 확인: 배포 과정은 docs 레포지토리의 Actions 탭에서 실시간으로 확인할 수 있습니다.

구현 시나리오

  1. IAM 사용자 및 권한 설정: Github Actions가 AWS 리소스에 접근할 수 있도록, 최소한의 권한(s3:PutObject, cloudfront:CreateInvalidation 등)을 가진 전용 IAM 사용자를 생성합니다.

  2. Github Secrets 등록: 생성된 IAM 사용자의 액세스 키(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)를 docs 레포지토리의 Settings > Secrets에 안전하게 등록합니다.

  3. 워크플로우 실행:

    • 트리거: docs Github 레포지토리의 main 브랜치에 코드가 Push될 때마다 .github/workflows/deploy.yml 파일에 정의된 파이프라인이 자동으로 실행됩니다.
    • 실행 과정:
      1. Docusaurus 사이트를 빌드합니다. (npm run build)
      2. 빌드 결과물을 S3 버킷(vivid-ai-docs-dev)에 업로드합니다.
      3. CloudFront 캐시를 무효화(Invalidation)하여 사용자가 즉시 최신 내용을 볼 수 있도록 합니다.

수동 배포

자동 배포 과정에 문제가 발생했거나, 긴급하게 직접 배포해야 할 경우 다음 절차를 따릅니다.

  1. 로컬에서 빌드: 로컬 PC의 docs-vivid-ai/website 폴더로 이동하여 다음 명령어를 실행합니다.

    npm run build
  2. S3에 업로드: AWS CLI가 설치되어 있다면 다음 명령어를 사용해 build 폴더의 내용물을 S3 버킷에 업로드합니다.

    aws s3 sync ./build s3://vivid-ai-docs-dev --delete
    • 만약 AWS CLI가 없다면, AWS S3 콘솔에 접속하여 vivid-ai-docs-dev 버킷에 build 폴더의 모든 내용물을 직접 드래그 앤 드롭하여 업로드합니다.
  3. CloudFront 캐시 무효화 (필수): 수동으로 S3 파일만 변경하면 CloudFront는 변경 사실을 모르고 이전 버전의 캐시를 계속 보여줍니다. 따라서 반드시 캐시를 수동으로 무효화해야 합니다.

    • AWS CloudFront 콘솔 > 해당 배포 선택 > "무효화(Invalidations)" 탭으로 이동합니다.
    • **"무효화 생성(Create invalidation)"**을 클릭하고, 객체 경로에 /* 를 입력하여 전체 캐시를 삭제합니다.

애플리케이션 배포 (EKS)

이 섹션에서는 EKS(Elastic Kubernetes Service) 클러스터에 애플리케이션 컴포넌트(예: 백엔드, 프론트엔드, 후처리 워커)를 배포하는 방법에 대해 설명합니다.

Docker 이미지 빌드 및 관리

EKS 클러스터에 배포될 애플리케이션은 Docker 이미지 형태로 제공됩니다.

  • 이미지 아키텍처 고려사항: EKS 워커 노드는 일반적으로 linux/amd64 (x86_64) 아키텍처를 사용합니다. 로컬 개발 환경(예: Apple Silicon Mac)에서 이미지를 빌드할 경우, 기본적으로 arm64 아키텍처용 이미지가 생성될 수 있습니다. 이 경우 EKS 노드에서 이미지를 가져오지 못하는 no match for platform in manifest 에러가 발생할 수 있습니다.

    • 해결책: 이미지를 빌드할 때 --platform linux/amd64 옵션을 명시하여 amd64 아키텍처용으로 빌드해야 합니다.
      docker build --platform linux/amd64 -t \<your-ecr-repository-uri\>:latest .
  • 보안 모범 사례 (.dockerignore): Docker 이미지를 빌드할 때 로컬 개발 환경의 민감한 파일(예: .env, secrets.yaml)이 이미지 내부에 포함되지 않도록 주의해야 합니다.

    • 위험성: .env 파일에 포함된 AWS 자격 증명이나 DB 비밀번호가 이미지 레이어에 평문으로 저장되면, 이미지를 풀(pull) 할 수 있는 누구든지 해당 정보를 열람할 수 있습니다.
    • 해결책: 프로젝트 루트에 .dockerignore 파일을 생성하고, .env 및 기타 민감한 파일을 명시하여 빌드 컨텍스트에서 제외합니다.
      .env
      .git
      *.yaml
  • 프라이빗 레지스트리: 빌드된 Docker 이미지는 AWS ECR(Elastic Container Registry)과 같은 프라이빗 컨테이너 레지스트리에 푸시하여 관리합니다. ECR은 Kubernetes 파드가 이미지를 안전하게 가져올 수 있도록 통합 인증 기능을 제공합니다.

EKS 컴포넌트 배포 (Kubernetes YAML)

애플리케이션 컴포넌트는 Kubernetes Deployment, Service, Secret 등의 YAML 파일을 통해 EKS 클러스터에 배포됩니다.

1. 시크릿 관리 및 인증 (IRSA)

애플리케이션이 AWS 리소스(S3, SQS 등)에 접근할 때, 환경에 따라 두 가지 인증 방식을 사용합니다.

  • Development (Dev) 환경: 간편한 구성을 위해 Kubernetes Secret에 AWS Access Key를 저장하여 환경 변수로 주입하는 방식을 사용할 수 있습니다.
    env:
    - name: AWS_ACCESS_KEY_ID
    valueFrom:
    secretKeyRef:
    name: post-processing-worker-secrets-dev
    key: AWS_ACCESS_KEY_ID
  • Production (Prod) 환경 (권장): 보안을 위해 장기(Long-term) 자격 증명을 저장하지 않는 IRSA (IAM Roles for Service Accounts) 방식을 사용합니다.
    • 장점: Access Key 노출 위험이 없으며, 권한을 IAM Role 단위로 세밀하게 제어할 수 있습니다.
    • 구성: Deployment YAML에 serviceAccountName을 명시하고, 해당 ServiceAccount에 IAM Role을 어노테이션으로 연결합니다. (상세 내용은 post-processing-worker 문서 참조)

2. ECR 이미지 풀 인증 (IRSA)

EKS 클러스터의 파드가 ECR 프라이빗 레지스트리에서 이미지를 가져오려면 인증이 필요합니다. EKS에서는 **IRSA (IAM Role for Service Accounts)**를 사용하는 것이 가장 권장되는 방법입니다.

  • 작동 방식: Kubernetes Service Account에 ECR 이미지를 가져올 수 있는 권한을 가진 AWS IAM Role을 연결합니다. 파드는 해당 Service Account를 사용함으로써 IAM Role의 권한을 자동으로 상속받아 ECR에 인증합니다.
  • 설정 단계:
    1. IAM Policy 생성: ECR에서 이미지를 가져올 수 있는 권한을 가진 IAM Policy를 생성하거나(AmazonEC2ContainerRegistryReadOnly 관리형 정책 사용).
    2. IAM Role 생성 및 Service Account 연결: eksctl 명령어를 사용하여 Service Account에 IAM Role을 연결합니다.
      eksctl create iamserviceaccount \
      --name \<your-service-account-name\> \
      --namespace \<your-namespace\> \
      --cluster \<your-eks-cluster-name\> \
      --attach-policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly \
      --approve
      (파드가 default Service Account를 사용한다면 --name default를 사용합니다.)
    3. Deployment에 Service Account 지정: Deployment YAML 파일의 spec.template.spec 아래에 serviceAccountName: <your-service-account-name>을 추가합니다. (만약 default Service Account를 사용한다면 이 필드를 생략할 수 있습니다.)
  • 확인 사항:
    • EKS 클러스터에 OIDC Provider가 활성화되어 있어야 합니다.
    • 연결된 IAM Role의 Trust Policy가 Service Account가 Role을 가정할 수 있도록 올바르게 구성되어 있어야 합니다.

3. 네트워크 구성 (VPC Endpoint)

EKS 워커 노드가 프라이빗 서브넷에 배포된 경우, ECR 및 S3와 같은 AWS 서비스에 안전하게 접근하려면 VPC Endpoint 생성이 필수적입니다. VPC Endpoint가 없으면 image can't be pulled 또는 connection timed out과 같은 네트워크 관련 에러가 발생할 수 있습니다.

  • 필수 Endpoint:
    • com.amazonaws.<your-region>.ecr.api (ECR API)
    • com.amazonaws.<your-region>.ecr.dkr (ECR Docker)
    • com.amazonaws.<your-region>.s3 (S3 Gateway 또는 Interface)
  • 설정 확인: 각 Endpoint의 상태, VPC, 서브넷, 보안 그룹, 라우팅 테이블 설정이 올바른지 확인해야 합니다.

자세한 시스템 아키텍처는 아키텍처 문서를 참조하십시오.