회사에서 기존에 개발된 웹페이지를 대규모로 업데이트 하기로했었다. 기존에 플라스크 프레임워크 Jinja를 기반으로 back-end 와 front-end 가 함께 개발되어 있었고, 백과 프론트를 분리개발을 진행하기로 했고, 프론트는 react.js로 개발을 진행하기로 했다.
프론트 코드를 배포하기 위해서 AWS를 통해 배포하는 방법을 how to적으로 작성해보려고한다.
또한 코드 원격저장소로 github를 사용하기에 github에 코드를 배포함과 동시에 자동으로 설명된 aws 설정에 의해 배포고 웹페이지가 업데이트 될 수 있게 한다.
*S3란? Amazon Simple Storage Service(Amazon S3)는 업계 최고의 확장성, 데이터 가용성, 보안 및 성능을 제공하는 객체 스토리지 서비스입니다.
S3 버킷을 통해 원하는 양의 데이터를 저장합니다.
React 코드를 저장해서 보여주기 위해서 AWS S3 서비스를 이용해 S3 버킷에 Build합니다.






{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity 클라우드 프론트 설정 후 입력"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::s3 name/*"
}
]
}
총 9단계를 거치면 S3 버킷을 만들수 있습니다.
설정을 하는 방법은 구글링을 통해서 충분히 가능하고, 아마 권한에 따른 버킷 정책을 설정하는 부분이 생각보다 까다롭스니다. 클라우드프론트로 서빙해서 배포를 진행할 예정이라 클라우드 프론트에서 s3접근할 수 있는 권한을 설정해줘야 합니다.
*역할 : 사용자의 위치에 따라 최단 경로로 웹페이지에 접속할 수 있게 도와줍니다.


-*OAI 설정하는 것이 지금은 다른 방법으로도 할 수 있는 것으로 압니다. 참고

Http 와 Https 프로토콜을 모두 허용합니다.
캐시 키 및 원본 요청은 기본 AWS 추천 정책을 따릅니다.
캐시 정책을 사용해서 TTL(Time To Live)를 설정해줄 수 있습니다.
이 부분은 얼마나 오랫동안 콘텐츠들이 캐시에 저장되는지를 나타내는 부분입니다.


*Route 53을 통해 설정한 도메인 주소값을 입력합니다.(대체도메인 CNAME)
*HTTP를 HTTPS로 전환시켜주기 위한 SSL인증서를 설정합니다.

Customize error response - Yes 선택
Response page path - /index.html 선택 (이전 Default root object 와 같은 파일 선택)
HTTP Response code - 200: OK 선택

-*DNS란? example.com을 IP 주소로 변환하는 역할
도메인 또는 하위 도메인의 트래픽을 라우팅할 방법을 정의하는 데 사용되는 호스팅 영역 내 객체를 의미합니다.
원하는 DNS주소값을 이용하기 위한 설정을 해줍니다. 저 같은 경우는 회사 주소값을 이용해서 설정합니다.




github Actions을 활용하는 대표적인 예시 중 하나이다.
로컬 레포에서 원격 레포로 푸쉬하고 난 후, Actions에서는 이벤트 발생에 따라 자동으로
빌드 및 배포하는 스크립트를 실행시켜준다.
*스크립트 설정하는 자세한 방법과 실행원리는 구글링을 통해서 자세하게 알 수 있다. 내가 설정했던 것을 기반의로 스크립트를 노출 가능한 부분만 공유한다.
*아래 스크립트에 주석을 통해 설명을 추가했고, E2E 테스트와 jest test를 위한 설정도 포함
name: 리액트 빌드 / 배포 Actions # workflow 이름
on: # workflow 실행 조건
push:
branches: [main, dev] # 메인, 데브 브랜치에 푸쉬된 경우
pull_request:
branches: [main, dev] # 메인, 데브 브랜치에 pr 생성한 경우
jobs: # job 설정
test-dev-pr_push:
runs-on: ubuntu-20.04
if: github.base_ref == 'dev' || github.ref == 'refs/heads/dev'
steps:
- name: Checkout
uses: actions/checkout@v3
# Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v4
with:
start: yarn start-dev
wait-on: 'http://localhost:3000' #yarn start 완료까지 기다림
browser: chrome # test browser 환경
config: baseUrl=http://localhost:3000
env: CYPRESS_URL=http://localhost:3000
test-prod-push:
runs-on: ubuntu-20.04
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@v3
# Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v4
with:
start: yarn start-prod
wait-on: 'http://localhost:3000' #yarn start 완료까지 기다림
browser: chrome # test browser 환경
config: baseUrl=http://localhost:3000
env: CYPRESS_URL=http://localhost:3000
deploy-dev: # job id
name: 리액트 Develop build & deploy
runs-on: ubuntu-20.04
if: github.ref == 'refs/heads/dev'
needs: test-dev-pr_push
environment: Develop
env:
# Treating warnings as errors because process.env.CI = true. 에러 나올경우 고려
CI: false
steps: #react build
- uses: actions/checkout@v3
- name: Get yarn cache
id: yarn-cache-dir
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v3
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
# yarn 패키지 설치
- name: yarn
run: yarn
- name: React Dev build
run: yarn build-dev
# aws user 연결
- 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: ap-northeast-2
# react 빌드한 /build를 s3로 업로드
- name: Upload to S3
env:
BUCKET_NAME_DEV: ${{ secrets.AWS_S3_BUCKET_NAME_DEV}}
run: |
aws s3 sync \
./build s3://$BUCKET_NAME_DEV
# 업로드한 s3 파일을 각 CDN 캐시 무효화하여 리프레시 하기
- name: CloudFront Invalidation
env:
CLOUD_FRONT_ID_DEV: ${{ secrets.AWS_CLOUDFRONT_ID_DEV}}
run: |
aws cloudfront create-invalidation --distribution-id $CLOUD_FRONT_ID_DEV --paths / /index.html /error.html /service-worker.js /manifest.json /favicon.ico
deploy-prod: # job id
name: 리액트 Production build & deploy
runs-on: ubuntu-20.04
if: github.ref == 'refs/heads/main'
needs: test-prod-push
environment: Production
env:
# Treating warnings as errors because process.env.CI = true. 에러 나올경우 고려
CI: false
steps: #react build
- uses: actions/checkout@v3
- name: Get yarn cache
id: yarn-cache-dir
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v3
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
# yarn 패키지 설치
- name: yarn
run: yarn
- name: React Prod build
run: yarn build-prod
# aws user 연결
- 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: ap-northeast-2
# react 빌드한 /build를 s3로 업로드
- name: Upload to S3
env:
BUCKET_NAME_PROD: ${{ secrets.AWS_S3_BUCKET_NAME_PROD}}
run: |
aws s3 sync \
./build s3://$BUCKET_NAME_PROD
# 업로드한 s3 파일을 각 CDN 캐시 무효화하여 리프레시 하기
- name: CloudFront Invalidation
env:
CLOUD_FRONT_ID_PROD: ${{ secrets.AWS_CLOUDFRONT_ID_PROD}}
run: |
aws cloudfront create-invalidation --distribution-id $CLOUD_FRONT_ID_PROD --paths / /index.html /error.html /service-worker.js /manifest.json /favicon.ico
test-dev:
runs-on: ubuntu-20.04
if: github.ref == 'refs/heads/dev'
needs: deploy-dev
steps:
- name: Checkout
uses: actions/checkout@v3
# Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v4
with:
browser: chrome # test browser 환경
config: baseUrl=https://dev-axcloudv4.axchange.co
env: CYPRESS_URL=https://dev-internal-api.axchange.co/
test-prod:
runs-on: ubuntu-20.04
if: github.ref == 'refs/heads/main'
needs: deploy-prod
steps:
- name: Checkout
uses: actions/checkout@v3
# Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v4
with:
browser: chrome # test browser 환경
config: baseUrl=https://ax-cloud.com
env: CYPRESS_URL=https://internal-api.axchange.co/
git secrets를 설정하기 위해서는 관리자 권한이 필요하다. 회사에서는 권한이 분리되어 있어서 아무나 접근할수 없으니 참고!
yml스크립트에를 실행할때 필요한 secrets key와 value를 설정하느 것 쉽게 ENV 역할을 한다고 생각하된다.

모든 레포에서 사용 가능하도록 설정되어 있음
AWS_SECRET_ACCESS_KEY
모든 레포에서 사용 가능하도록 설정되어 있음
AWS_S3_BUCKET_NAME_DEV
dev 서버 S3 버킷으로 설정한 이름 확인
prod 서버 S3 버킷으로 설정한 이름 확인
dev 서버 에 접속하면 확인가능
prod 서버에 접속하면 확인가능

이렇게 모든 설정을 완료했다.
모든 설정이 그렇듯 처음에는 많이 낯설어서 시간도 오래걸리고 이해도 잘안가지만, 설정을 한번 경험해보면.... 무척 간단하다. 처음에 이것을 설정하는... 무척 고생을 많이했다. 따로 설명을 해주는 사람이 없어서 스스로 설정을해서 잘 작동하는지 알아야했기때문에이다. 하지만 정말 많은 공부가 되서 지금은 나에게 아주 특별한 경험이다.