공부일지/클라우드 SA 교육

[2차 세미 프로젝트] AWS 위에 Miniflix

박수빈98 2025. 6. 17. 16:46

2차 세미가 진행되었다.

기간은 9일 정도이다.

이번 주제는 1차 세미에서 진행했던 Netfilx like 스트리밍 서비스를 온프레미스에서 구축해보는 것이다.

2차 세미는 이걸 발전시켜 퍼블릭 클라우드와 프라이빗 클라우드 위에서 동작하게 바꾸는 것이다.

 

수업에서 배운 오픈스택과 AWS를 이용해 하이브리드 클라우드 환경에서 구현하는 것이다.

 

넷플릭스는 유명한 클라우드 네이티브 서비스이다.

모든 물리 데이터센터를 종료하고 전부를 AWS에 올려 서비스하고 있는 상황이다.

 

여기서 우리는 변형을 줘 비교적 저렴한 저장장치관련 파일서버와 트랜스코딩 서버만 오픈스택를 이용해 사내에서 운영하고,
나머지는 AWS에 올려 서비스하는 구조를 설계했다.

 

과정에서 오픈스택과 AWS VPC 사이에 VPN을 통해 더욱 안전하고, 안정적인 연결을 할 수 있게 구상했다.

 

나는 웹서버와 오픈스택 위에 파일서버, 트랜스코딩 서버 구축을 메인으로 맡게 됐다.

 

웹서버는 Vue.js로 구현하고, AWS 위로 올리기

파일서버는 NFS로 트랜스코딩서버와 마운트

트랜스코딩 서버는 FFMPEG을 통해 MP4 -> m3u8, ts 로 변환 후 S3로 전송

 

 

 

4일 정도가 지난 상태에서 지금까지는

 

웹서버

별도의 EC2 없이 CloudFront + S3 조합으로 정적파일 서버 역할 할 수 있게 구성

또한 아래와 같이 npm run build 하면 빌드파일을 바로 S3에 업로드해 배포되어 적용 + CloudFront 캐시를 무효해 새롭게 빌드된 화면 볼 수 있게 했다.

	"deploy": "npm run build && aws s3 sync dist/ s3://miniflix-bucket --delete --region ap-northeast-2 
    		&& aws cloudfront create-invalidation --distribution-id E24EN8HJLVTKUC --paths '/*'"

 

또한 CloudFront에서 오리진을 하나 더 추가했다.

백엔드 요청처리를 위한 백엔드 연결된 ALB를 추가했따.

Behavior에 /api/* 요청이 들어올 때 해당 ALB로 보내주게 된다.

 

현재는 로그 관련 작업 때문에 백엔드 서버가 내려간 상탠데 작업이 끝나면 작성한 프론트 코드와 연결해보면서 
프론트 완성해 가면 될 거 같다.

트랜스코딩서버

fileserver에서 저장된 곳 보고 업로드 안된 영상 변환 후 S3에 업로드 스크립트로 업로드 가능하게 만듬

# NFS 클라이언트 설치 (Ubuntu 기준)
sudo apt install -y nfs-common

# 마운트 디렉토리 생성
sudo mkdir -p /mnt/nfs_shared

# 마운트 수행
sudo mount -t nfs <서버IP>:/srv/nfs/shared /mnt/nfs_shared

# 영구 마운트하려면 /etc/fstab 추가
echo "<서버IP>:/srv/nfs/shared /mnt/nfs_shared nfs defaults 0 0" | sudo tee -a /etc/fstab

NFS 연결완료

FFMPEG 설치

sudo apt update
sudo apt install -y ffmpeg python3-pip unzip jq

AWS-CLI 설치

sudo apt install -y python3-venv

# 1. venv 생성
python3 -m venv ~/.venv/awscli

# 2. 활성화
source ~/.venv/awscli/bin/activate

# 3. awscli 설치
pip install --upgrade awscli

# 4. 경로 추가 (bashrc에)
echo 'export PATH=$PATH:$HOME/.venv/awscli/bin' >> ~/.bashrc
source ~/.bashrc

# 5. 확인
aws --version

AWS 자격증명

엑세스 키 생성(CLI용)

엑세스 키 + 비밀 엑세스 키 생성 후 접속

S3 업로드 자동화 스크립트

INPUT_ROOT="/mnt/nfs_shared/videos"
BUCKET="버킷명"
REGION="ap-northeast-2"

for dir in "$INPUT_ROOT"/*; do
    if [[ -d "$dir" && -f "$dir/source.mp4" ]]; then
        movie_id=$(basename "$dir")
        uploaded_flag="$dir/.uploaded"

        if [[ -f "$uploaded_flag" ]]; then
            echo "⏩ [$movie_id] 이미 완료됨 (.uploaded 있음). 건너뜀"
            continue
        fi

        outdir="/tmp/hls/$movie_id"
        mkdir -p "$outdir"

        echo "▶️ [$movie_id] 트랜스코딩 시작..."
        ffmpeg -y -i "$dir/source.mp4" \\
            -codec: copy \\
            -start_number 0 \\
            -hls_time 10 \\
            -hls_list_size 0 \\
            -f hls "$outdir/index.m3u8"

        if [[ $? -ne 0 ]]; then
            echo "❌ [$movie_id] 트랜스코딩 실패. 스킵됨"
            continue
        fi

        echo "☁️ [$movie_id] S3 업로드 중..."
        aws s3 cp "$outdir" "s3://$BUCKET/hls/$movie_id/" --recursive --region "$REGION"

        if [[ $? -eq 0 ]]; then
            touch "$uploaded_flag"
            echo "✅ [$movie_id] 업로드 완료 (.uploaded 생성)"
        else
            echo "❌ [$movie_id] S3 업로드 실패"
        fi
    else
        echo "⚠️ [$dir] 'source.mp4' 없음. 건너뜀"
    fi
done

생성 후 실행 권한 적용

chmod +x ~/transcode_with_done_file.sh

스크립트로 생성된 모습

이미 업로드 된 상태면 스킵 → S3를 확인하는 것이 아닌 업로드 로직 수행 후 touch로 .uploaded를 통해 체크

ubuntu@transcodingserver:/mnt/nfs_shared/videos/100$ ~/transcode_with_done_file.sh
⏩ [100] 이미 완료됨 (.uploaded 있음). 건너뜀
⏩ [102] 이미 완료됨 (.uploaded 있음). 건너뜀
⏩ [103] 이미 완료됨 (.uploaded 있음). 건너뜀

 

스트리밍 서버

S3 + CloudFront

여기서 S3 단일로도 충분히 스트리밍 서버 느낌을 줄 수 있음

S3가 사실 AWS가 운영하는 서버기 때문이다.

하지만 CloudFront를 사용하는 이유는 버킷 자체

S3로 직접 접근 시 퍼블릭 설정 위험하고 리소스 마다 presigned URL을 관리해야해서 불편하다

또한 매번 요청하면 비용이 발생할 수 있다.

반면 CloudFron의 경우 별도의 보안이 존재하고 캐싱을 통해 비용을 절약할 수 있다.

과정

  1. S3 버킷 만들기
  2. CloudFront 만들기
    1. 오리진 도메인에 스트리밍 버킷을 넣으면 됨
  3. 버킷에 영상 넣기

스트리밍 버킷 구조 버킷 구조(Cloudfront)

https://d1234.cloudfront.net/videos/{movie_id}/index.m3u8

이런 식으로 movie_id를 프리픽스에 넣기

 

이제 GET https://dxxxxx.cloudfront.net/hls/100/index.m3u8

로 요청보내면 영상을 출력할 수 있다.

<https://d2qz0geqyx3cqt.cloudfront.net/hls/${props.movieId}/index.m3u8>

 

 

막혔던 부분

OAC 설정이 잘못되어있었음

OAC가 하는일

CloudFront가 S3 오리진에 접근할 때:

  • 클라이언트는 CloudFront URL에 요청
  • CloudFront는 S3에 GET 요청을 보냄
  • 이때 S3는 CloudFront의 요청을 받아들일지 버킷 정책을 보고 판단함

이때 OAC는 CloudFront가 사용하는 IAM 역할처럼 동작해서 S3 버킷 정책에서 Principal: cloudfront.amazon.com + SourceArn 조건으로 인증 받는 구조

버킷 정책

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "AllowCloudFrontServicePrincipal",
            "Effect": "Allow",
            "Principal": {
                "Service": "cloudfront.amazonaws.com"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::miniflix-video-stream-bucket/*",
            "Condition": {
                "StringEquals": {
                    "AWS:SourceArn": "arn:aws:cloudfront::"
                }
            }
        }
    ]
}

 

이게 클라우드프론트에서 오는 접근이 내가 지정한 CloudFront인지 확인하는 정책을 추가한다.

이 부분이 IAM과 같이 내가 지정한 CloudFront 외는 거부할 수 있는 것이다.

 

먼저 CloudFront와 버킷을 연결하는 곳에서 설정하는 것이

Origin Domain: CloudFront가 어디에 있는 컨텐츠를 가져올지 지정함

Origin Access: CloudFront가 그 오리진에 접근할 수 있는 권한을 어떻게 획득할지 지정하는 것

  • 공개: 아무런 인증 없이 누구나 S3에 접근 가능 즉, S3 버킷의 객체에 “퍼블릭 읽기 권한”이 있어야 작동함
    • 이건 굉장히 열려있는 상태라서 위험
  • Origin Access Control(OAC): 버킷에 정책을 통해 CloudFront를 허용해주는 방식(IAM 역할)
    • 이게 권장 방식임
  • Legacy Access Identities: CloudFront가 OAI라는 가짜 IAM 사용자처럼 S3에 접근하는 것
    • 이제 역할 기반의 OAC가 나와 잘 사용 안함

앞으로 해야할 것

1. 프론트, 백엔드 연결 완성

2. VPN 연결