오늘은 CodePipeline을 사용하여 React CI / CD 환경을 구축해보겠습니다.
0. React 서비스 구축
React 서비스는 S3와 CloudFront를 이용하여 구축했습니다.
S3에는 build 디렉토리 안에 있는 파일들을 업로드 하였습니다. 정적 웹 호스팅 기능은 사용하지 않았습니다.

CloudFront를 사용할 때 OAC를 통해 S3에 접근하고, Default root object를 index.html로 설정해야 합니다.

또한, React에서 BrowserRouter을 사용한다면 Error pages 설정을 바꿔줘야 합니다. 403 & 404 에러가 발생했을 때 /index.html 경로로 200 코드 응답을 하게 해야합니다.


이제 CloudFront Domain에 접속하면 성공적으로 서비스가 배포된 것을 확인할 수 있습니다.

1. CodeCommit
Codecommit은 프라이빗 Git 리포지토리를 안전하게 호스팅하여 코드 협업을 지원합니다. 쉽게 말해, AWS에서 지원하는 Github라고 할 수 있습니다.
먼저, CodeCommit 리포지토리를 생성합니다.

Linux에서는 다음 명령어를 입력하면 aws credentials를 사용하여 CodeCommit 리포지토리에 액세스 할 수 있습니다.
git config --global credential.helper '!aws codecommit credential-helper $@'
git config --global credential.UseHttpPath true
Windows는 IAM User을 생성하는 것을 추천합니다.
저는 codecommit 이라는 이름의 유저를 생성하며 AWSCodeCommitPowerUser Policy를 부착하겠습니다.

User를 클릭하여 Security credentials 메뉴를 클릭하고 HTTPS Git credentials를 발급합니다.
User name과 Password를 기록하여 git push 할 때 사용하면 됩니다.

이제 CodeCommit에 코드를 push 해보겠습니다.
git add .
git commit -m "commit message"
git branch -M main
git remote add origin <codecommit repository url>
git push origin main

main 브랜치에 파일들이 잘 올라간 것을 볼 수 있습니다.


참고로, 다음 코드를 사용했습니다.
https://github.com/ArcoKim/Demo-App/tree/main
GitHub - ArcoKim/Demo-App: App for testing cloud services
App for testing cloud services. Contribute to ArcoKim/Demo-App development by creating an account on GitHub.
github.com
2. CodeBuild
CodeBuild는 소스 코드를 컴파일하고 테스트를 실행한 다음 바로 배포 가능한 소프트웨어 패키지를 생성할 수 있는 완전관리형의 지속적 통합 서비스입니다.
CodeBuild는 빌드 과정을 기록하기 위해서 buildspec.yml을 작성해야 합니다. 저는 report를 내보내는 과정까지 포함하여 다음과 같이 작성했습니다.
version: 0.2
phases:
install:
runtime-versions:
nodejs: 16
pre_build:
commands:
- npm install # package.json 파일의 의존성 설치
build:
commands:
- npm run build # react 앱 빌드
post_build:
commands:
- npm test -- --testResultsProcessor="jest-junit" --watchAll=false --ci --coverage # test report, coverage report 생성
reports:
arn:aws:codebuild:ap-northeast-2:073813292468:report-group/react-test-report:
files:
- junit.xml
file-format: JUNITXML
arn:aws:codebuild:ap-northeast-2:073813292468:report-group/react-coverage-report:
files:
- coverage/clover.xml
file-format: CLOVERXML
artifacts:
files:
- '**/*' # 빌드 파일 내보내기
base-directory: 'build'
cache:
paths:
- node_modules/**/* # 빠른 빌드를 위해 node_modules 캐싱
그럼 buildspec.yml까지 commit & push 하겠습니다.

이제 build project를 생성하겠습니다. 먼저, 프로젝트 설정에서 프로젝트 이름을 정합니다.

Source로는 생성했던 CodeCommit을 지정합니다.

Environment image로는 Amazon Linux 2 버전 4.0을 사용하겠습니다.

Service role은 새로 발급합니다.

Artifact는 사용하지 않지만, Additional configuration을 눌러 캐싱 정보를 저장할 Bucket을 지정합니다.

CloudWatch logs Group, Stream 이름을 적고 프로젝트를 생성하면 됩니다.

저는 report도 내보내기 때문에 Report group 두 개를 추가로 생성하겠습니다.

참고로, CodeBuild에서 report를 내보내려면 codebuild service role에 다음과 같은 Policy가 있어야 합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": [
"*"
],
"Action": [
"codebuild:CreateReportGroup",
"codebuild:CreateReport",
"codebuild:UpdateReport",
"codebuild:BatchPutTestCases",
"codebuild:BatchPutCodeCoverages"
]
}
]
}
3. Lambda
S3 Bucket이 업데이트 되어도 CloudFront 캐시가 만료되지 않으면 기존 콘텐츠가 남아있게 됩니다. 따라서 S3 Bucket이 업데이트 되면 Lambda를 통해 CloudFront Invalidations를 해줘서 캐시를 갱신시켜야 합니다.
저는 다음과 같이 코드를 짰습니다.
import boto3
import botocore
from time import time
cf = boto3.client('cloudfront')
code_pipeline = boto3.client('codepipeline')
def create_invalidation():
DISTRIBUTION_ID = 'E3V00GOB0EULV5' # 사용자에 따라 변경
try:
res = cf.create_invalidation(
DistributionId=DISTRIBUTION_ID,
InvalidationBatch={
'Paths': {
'Quantity': 1,
'Items': [
'/*'
]
},
'CallerReference': str(time()).replace(".", "")
}
)
return True
except botocore.exceptions.ClientError as e:
print(e)
return False
def lambda_handler(event, context):
job_id = event['CodePipeline.job']['id']
if create_invalidation():
code_pipeline.put_job_success_result(jobId=job_id)
else:
code_pipeline.put_job_failure_result(jobId=job_id, failureDetails={'message': "Check CloudWatch Logs.", 'type': 'JobFailed'})
Lambda 함수에도 Deploy 해줬습니다. Lambda에 부착된 IAM Role에는 다음과 같은 Policy가 있어야 합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"codepipeline:PutJobSuccessResult",
"codepipeline:PutJobFailureResult",
"cloudfront:CreateInvalidation"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
4. CodePipeline
CodePipeline은 빠르고 안정적인 애플리케이션 및 인프라 업데이트를 위해 릴리스 파이프라인을 자동화하는 데 도움이 되는 완전관리형의 지속적 전달 서비스입니다. CodePipeline은 생성했던 서비스들을 이어주는 역할을 할 것입니다.
먼저, Pipeline과 Service role의 이름을 정합시다.

Source로는 생성했던 CodeCommit의 리포지토리와 브랜치를 선택합시다.

Build로는 생성했던 CodeBuild 프로젝트를 선택합시다.

Deploy로는 현재 서비스하고 있는 S3 Bucket을 선택합니다.

Create pipeline을 눌러 pipeline을 생성합니다.

pipeline을 생성하면 처음 자동 실행이 되는데 한 단계를 더 추가해야 하므로 Stop execution을 눌러 멈춥니다.
Stop and abandon 옵션을 선택해야 합니다.

Edit을 누르고 Deploy stage 아래에 Add stage를 눌러 stage를 추가합니다. stage 이름은 Invalidations으로 하겠습니다.

Add action group을 누르고 생성했던 Lambda 함수를 선택합니다.

Done, Save를 눌러 저장합니다. 이제 코드에 변동을 주고 commit & push 해서 CodePipeline이 잘 동작하고 변동 사항이 잘 반영됐는지 확인합니다.

Pipeline Stage가 모두 성공하며 끝났습니다.


report 두 개가 잘 생성되었습니다.


웹 페이지에도 반영이 잘 되었습니다.

오늘의 글은 여기까지입니다. 감사합니다!
'AWS' 카테고리의 다른 글
[AWS] aws-nuke로 모든 리소스 삭제 (0) | 2023.09.24 |
---|---|
[AWS] EKS Node Metadata (IMDS) - EC2 (0) | 2023.09.22 |
[AWS] ArgoCD를 통한 애플리케이션 배포 (with CodeCommit) (0) | 2023.09.19 |
[AWS] EKS AutoScaling - HPA, Cluster Autoscaler (2) | 2023.09.18 |
[AWS] EKS Fargate로 Pod 배포와 로깅 (0) | 2023.09.16 |
오늘은 CodePipeline을 사용하여 React CI / CD 환경을 구축해보겠습니다.
0. React 서비스 구축
React 서비스는 S3와 CloudFront를 이용하여 구축했습니다.
S3에는 build 디렉토리 안에 있는 파일들을 업로드 하였습니다. 정적 웹 호스팅 기능은 사용하지 않았습니다.

CloudFront를 사용할 때 OAC를 통해 S3에 접근하고, Default root object를 index.html로 설정해야 합니다.

또한, React에서 BrowserRouter을 사용한다면 Error pages 설정을 바꿔줘야 합니다. 403 & 404 에러가 발생했을 때 /index.html 경로로 200 코드 응답을 하게 해야합니다.


이제 CloudFront Domain에 접속하면 성공적으로 서비스가 배포된 것을 확인할 수 있습니다.

1. CodeCommit
Codecommit은 프라이빗 Git 리포지토리를 안전하게 호스팅하여 코드 협업을 지원합니다. 쉽게 말해, AWS에서 지원하는 Github라고 할 수 있습니다.
먼저, CodeCommit 리포지토리를 생성합니다.

Linux에서는 다음 명령어를 입력하면 aws credentials를 사용하여 CodeCommit 리포지토리에 액세스 할 수 있습니다.
git config --global credential.helper '!aws codecommit credential-helper $@'
git config --global credential.UseHttpPath true
Windows는 IAM User을 생성하는 것을 추천합니다.
저는 codecommit 이라는 이름의 유저를 생성하며 AWSCodeCommitPowerUser Policy를 부착하겠습니다.

User를 클릭하여 Security credentials 메뉴를 클릭하고 HTTPS Git credentials를 발급합니다.
User name과 Password를 기록하여 git push 할 때 사용하면 됩니다.

이제 CodeCommit에 코드를 push 해보겠습니다.
git add .
git commit -m "commit message"
git branch -M main
git remote add origin <codecommit repository url>
git push origin main

main 브랜치에 파일들이 잘 올라간 것을 볼 수 있습니다.


참고로, 다음 코드를 사용했습니다.
https://github.com/ArcoKim/Demo-App/tree/main
GitHub - ArcoKim/Demo-App: App for testing cloud services
App for testing cloud services. Contribute to ArcoKim/Demo-App development by creating an account on GitHub.
github.com
2. CodeBuild
CodeBuild는 소스 코드를 컴파일하고 테스트를 실행한 다음 바로 배포 가능한 소프트웨어 패키지를 생성할 수 있는 완전관리형의 지속적 통합 서비스입니다.
CodeBuild는 빌드 과정을 기록하기 위해서 buildspec.yml을 작성해야 합니다. 저는 report를 내보내는 과정까지 포함하여 다음과 같이 작성했습니다.
version: 0.2
phases:
install:
runtime-versions:
nodejs: 16
pre_build:
commands:
- npm install # package.json 파일의 의존성 설치
build:
commands:
- npm run build # react 앱 빌드
post_build:
commands:
- npm test -- --testResultsProcessor="jest-junit" --watchAll=false --ci --coverage # test report, coverage report 생성
reports:
arn:aws:codebuild:ap-northeast-2:073813292468:report-group/react-test-report:
files:
- junit.xml
file-format: JUNITXML
arn:aws:codebuild:ap-northeast-2:073813292468:report-group/react-coverage-report:
files:
- coverage/clover.xml
file-format: CLOVERXML
artifacts:
files:
- '**/*' # 빌드 파일 내보내기
base-directory: 'build'
cache:
paths:
- node_modules/**/* # 빠른 빌드를 위해 node_modules 캐싱
그럼 buildspec.yml까지 commit & push 하겠습니다.

이제 build project를 생성하겠습니다. 먼저, 프로젝트 설정에서 프로젝트 이름을 정합니다.

Source로는 생성했던 CodeCommit을 지정합니다.

Environment image로는 Amazon Linux 2 버전 4.0을 사용하겠습니다.

Service role은 새로 발급합니다.

Artifact는 사용하지 않지만, Additional configuration을 눌러 캐싱 정보를 저장할 Bucket을 지정합니다.

CloudWatch logs Group, Stream 이름을 적고 프로젝트를 생성하면 됩니다.

저는 report도 내보내기 때문에 Report group 두 개를 추가로 생성하겠습니다.

참고로, CodeBuild에서 report를 내보내려면 codebuild service role에 다음과 같은 Policy가 있어야 합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Resource": [
"*"
],
"Action": [
"codebuild:CreateReportGroup",
"codebuild:CreateReport",
"codebuild:UpdateReport",
"codebuild:BatchPutTestCases",
"codebuild:BatchPutCodeCoverages"
]
}
]
}
3. Lambda
S3 Bucket이 업데이트 되어도 CloudFront 캐시가 만료되지 않으면 기존 콘텐츠가 남아있게 됩니다. 따라서 S3 Bucket이 업데이트 되면 Lambda를 통해 CloudFront Invalidations를 해줘서 캐시를 갱신시켜야 합니다.
저는 다음과 같이 코드를 짰습니다.
import boto3
import botocore
from time import time
cf = boto3.client('cloudfront')
code_pipeline = boto3.client('codepipeline')
def create_invalidation():
DISTRIBUTION_ID = 'E3V00GOB0EULV5' # 사용자에 따라 변경
try:
res = cf.create_invalidation(
DistributionId=DISTRIBUTION_ID,
InvalidationBatch={
'Paths': {
'Quantity': 1,
'Items': [
'/*'
]
},
'CallerReference': str(time()).replace(".", "")
}
)
return True
except botocore.exceptions.ClientError as e:
print(e)
return False
def lambda_handler(event, context):
job_id = event['CodePipeline.job']['id']
if create_invalidation():
code_pipeline.put_job_success_result(jobId=job_id)
else:
code_pipeline.put_job_failure_result(jobId=job_id, failureDetails={'message': "Check CloudWatch Logs.", 'type': 'JobFailed'})
Lambda 함수에도 Deploy 해줬습니다. Lambda에 부착된 IAM Role에는 다음과 같은 Policy가 있어야 합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"codepipeline:PutJobSuccessResult",
"codepipeline:PutJobFailureResult",
"cloudfront:CreateInvalidation"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
4. CodePipeline
CodePipeline은 빠르고 안정적인 애플리케이션 및 인프라 업데이트를 위해 릴리스 파이프라인을 자동화하는 데 도움이 되는 완전관리형의 지속적 전달 서비스입니다. CodePipeline은 생성했던 서비스들을 이어주는 역할을 할 것입니다.
먼저, Pipeline과 Service role의 이름을 정합시다.

Source로는 생성했던 CodeCommit의 리포지토리와 브랜치를 선택합시다.

Build로는 생성했던 CodeBuild 프로젝트를 선택합시다.

Deploy로는 현재 서비스하고 있는 S3 Bucket을 선택합니다.

Create pipeline을 눌러 pipeline을 생성합니다.

pipeline을 생성하면 처음 자동 실행이 되는데 한 단계를 더 추가해야 하므로 Stop execution을 눌러 멈춥니다.
Stop and abandon 옵션을 선택해야 합니다.

Edit을 누르고 Deploy stage 아래에 Add stage를 눌러 stage를 추가합니다. stage 이름은 Invalidations으로 하겠습니다.

Add action group을 누르고 생성했던 Lambda 함수를 선택합니다.

Done, Save를 눌러 저장합니다. 이제 코드에 변동을 주고 commit & push 해서 CodePipeline이 잘 동작하고 변동 사항이 잘 반영됐는지 확인합니다.

Pipeline Stage가 모두 성공하며 끝났습니다.


report 두 개가 잘 생성되었습니다.


웹 페이지에도 반영이 잘 되었습니다.

오늘의 글은 여기까지입니다. 감사합니다!
'AWS' 카테고리의 다른 글
[AWS] aws-nuke로 모든 리소스 삭제 (0) | 2023.09.24 |
---|---|
[AWS] EKS Node Metadata (IMDS) - EC2 (0) | 2023.09.22 |
[AWS] ArgoCD를 통한 애플리케이션 배포 (with CodeCommit) (0) | 2023.09.19 |
[AWS] EKS AutoScaling - HPA, Cluster Autoscaler (2) | 2023.09.18 |
[AWS] EKS Fargate로 Pod 배포와 로깅 (0) | 2023.09.16 |