Github Action: 빌드, 테스트 및 파이프라인을 자동화 할 수 있는 CI/CD 플랫폼으로, repository에서 이벤트가 발생할 때 workflow를 실행
S3: 정적 웹 호스팅 제공
CloudFront (CDN 서비스): S3 Bucket 오리진 서버로부터 콘텐츠를 효율적으로 캐싱하고, 사용자에게 가장 가까운 엣지 로케이션에서 콘텐츠를 제공
GitHub Action 실행: GitHub 리포지토리에서 푸시가 발생하면, 설정된 GitHub Action이 실행
빌드 및 테스트: GitHub Action은 정적 리소스를 빌드하고 실행 (정적 파일을 생성)
S3 업로드: 빌드된 정적 파일은 Amazon S3 버킷으로 업로드
CloudFront 캐싱 갱신: 업로드된 새로운 정적 파일은 CloudFront 캐시의 오리진으로 설정된 S3 버킷에서 가져와 엣지 로케이션에 배포
S3 버킷 생성: 정적 파일을 저장하기 위해 새로운 S3 버킷을 생성
퍼블릭 엑세스 차단 설정: 생성한 S3 버킷의 설정에서 '모든 퍼블릭 엑세스 차단' 옵션 선택
객체 소유권 설정에서 'ACL(액세스 제어 목록) 비활성화'를 선택
CloudFront
Action: CloudFront가 S3 버킷의 객체를 읽을 수 있도록 s3:GetObject 작업이 허용
Resource: arn:aws:s3:::reservation.genesis-airport.com/*으로 지정하여 S3 버킷의 모든 객체에 대한 액세스를 허용합니다.
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "AllowCloudFrontServicePrincipal",
"Effect": "Allow",
"Principal": {
"Service": "cloudfront.amazonaws.com"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::reservation.genesis-airport.com/*"
}
]
}
name: Deploy Frontend-user to S3
on:
push:
branches: [ "main", "develop" ]
paths:
- 'client/**'
env:
AWS_REGION: ap-northeast-2
S3_BUCKET_NAME: reservation.genesis-airport.com
permissions:
contents: read
jobs:
deploy-frontend:
name: Deploy Frontend
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install dependencies
run: npm install
working-directory: ./client
- name: .env setting
run: |
echo "REACT_APP_REDIRECT_URI_CLIENT=${{ secrets.REACT_APP_REDIRECT_URI_CLIENT }}" >> .env
echo "REACT_APP_CLIENT_ID=${{ secrets.REACT_APP_CLIENT_ID }}" >> .env
echo "REACT_APP_CLIENT_SECRET=${{ secrets.REACT_APP_CLIENT_SECRET }}" >> .env
echo "REACT_APP_SERVER_URL=${{ secrets.REACT_APP_SERVER_URL }}" >> .env
working-directory: ./client
- name: Build React app
run: npm run build
working-directory: ./client
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Upload to AWS S3
run: aws s3 sync ./client/build/ s3://$S3_BUCKET_NAME/ --delete
name: Deploy Frontend-admin to S3
on:
push:
branches: [ "main", "develop" ] # main 또는 develop 브랜치에 푸시될 때만 이벤트가 발생
paths:
- 'admin/**' # admin 폴더 내용이 변경될 때만 이벤트가 발생
env:
AWS_REGION: ap-northeast-2
S3_BUCKET_NAME: admin.genesis-airport.com
permissions:
contents: read # Git 리포지토리의 컨텐츠를 읽을 권한 부여
jobs:
deploy-frontend:
name: Deploy Frontend
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4 # 리포지토리 체크아웃을 수행
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: '20' # Node.js 버전 20을 설치
- name: Install dependencies
run: npm install
working-directory: ./admin
- name: .env setting
run: |
echo "REACT_APP_REDIRECT_URI_ADMIN=${{ secrets.REACT_APP_REDIRECT_URI_ADMIN }}" >> .env
echo "REACT_APP_CLIENT_ID=${{ secrets.REACT_APP_CLIENT_ID }}" >> .env
echo "REACT_APP_CLIENT_SECRET=${{ secrets.REACT_APP_CLIENT_SECRET }}" >> .env
echo "REACT_APP_SERVER_URL=${{ secrets.REACT_APP_SERVER_URL }}" >> .env
working-directory: ./admin
- name: Build React app
run: npm run build
working-directory: ./admin
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # AWS 액세스 키 ID를 설정
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # AWS 시크릿 액세스 키를 설정
aws-region: ${{ env.AWS_REGION }} # AWS 지역을 설정
- name: Upload to AWS S3
run: aws s3 sync ./admin/build/ s3://$S3_BUCKET_NAME/ --delete # admin 폴더의 빌드된 파일을 S3 버킷으로 업로드
Origin Domain Name (원본 도메인): 클라우드프론트 배포에서 원본으로 사용될 서버의 도메인 주소
Origin Path (원본 경로): 원본 도메인 뒤에 붙는 경로로, 원본 서버에서 클라우드프론트로 전송할 파일이나 데이터의 위치를 지정
Origin Access ID (원본 액세스 ID, OAI): 클라우드프론트가 S3 버킷 또는 사용자 정의 원본에 접근할 때 사용하는 IAM 역할의 ID
Alternate Domain Name (CNAME, 대체 도메인): 클라우드프론트에 연결할 대체 도메인 이름(CNAME)
SSL Certificate (사용자 정의 SSL 인증서): 클라우드프론트에 연결할 사용자 정의 SSL/TLS 인증서의 정보
🚀 Trouble Shooting
OAI 설정: OAI 설정을 통해 S3 버킷에 직접 액세스하는 것이 아니라 CloudFront를 통해서만 콘텐츠에 액세스할 수 있도록 할 수 있다.
그러나, CloudFront에 대한 원본 액세스 제어(OAI)가 올바르게 구성되지 않아서 CloudFront는 S3 버킷의 콘텐츠에 접근할 수 없었다.
CloudFront Caching: 클라우드프론트 캐싱이 예상한 대로 작동하지 않았다.
본인의 서비스가 전세계를 대상으로 하는것이 아니라면 CloudFront 보다는 region replica 로 보다 낮은 지연시간을 보장받을수 있답니다. 근데 왜 자꾸 제가 공부하는거 따라하는거죠?