개발일지

React 프로젝트 AWS 이용해서 CI / CD 구축하기

FE 2023. 3. 10. 15:16

이번에 새로운 프로젝트에 투입되면서 초기 단계에서 개발을 진행중이다.

 

아직 CI CD 구축이 되어 있지 않았는데 항상 백엔드 팀에서 해주셨는데 이번에는 내가 맡게 되었다.

같이 일하시던 백엔드 팀원분이 이직을 하게되었는데, 인수인계 및 잔여 업무들이 많은 것 같아 CI / CD 작업을 가져왔다. 해보고 싶었던 작업이기도 했고 여러모로 좋은 경험이 될 것 같아서 흔쾌히 진행하게 되었다.

 

현재 프로젝트는 리액트로 진행하고 있고 Git Action과 AWS를 이용해서 CI / CD를 구축할 계획으로 서치를 했다.

 

출처 : https://velog.io/@rycando/%EA%B0%9C%EB%B0%9C-%EC%9D%BC%EC%A7%80-Github-Action-AWS-codedeploy%EB%A1%9C-%EB%A1%A4%EB%B0%B1-%EA%B0%80%EB%8A%A5%ED%95%9C-CI-CD%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0

 

위 과정을 간략하게 설명해보자면

 

  1. 코드를 Push 하면 Git Action이 실행되어 CI (빌드) 작업을 수행
  2. 빌드 작업을 통해 zip 파일과 사전에 작성한 배포 스크립트 파일을 압축해 AWS S3에게 전달되어 저장
  3. S3에 저장되면 EC2에 설치한 CodeDeploy Agent가 S3에 저장된 파일 (zip 파일, 스크립트 파일)을 가져와 실행시키면서 CD(배포) 수행

처음에는 이 방식을 생각하고 시도를 해보다가 위 과정으로 프론트를 배포하는 것은 해줘야 할 작업들이 너무 많고 큰 리소스가 든다고 생각하였다. 

 

목적성을 생각해봤을 때 나는 트래픽이 많지 않고 단순 리소스를 불러와 프론트 배포만 하면된다. S3 정적 배포에서 많은 처리를 도와주기 때문에 오버엔지니어링과 추가적인 작업을 단순화 하는 것과 서버자원을 사용하지 않고 독립적으로 호스팅이 가능한 S3 정적배포와 클라우드 프론트를 이용하면 훨씬 더 간단하고 편리하게 CI / CD를 구축할 수 있기 때문에 이러한 방향성으로 수정했다.

 

그럼 왜 Spiring이 나올때마다 다 EC2로 하지? S3는 안되나?라고 순간 생각이 들어 백엔드 동료분께 여쭤보니 백엔드는 S3로 배포가 불가능 하다고 얘기해주셨다. 정적 소스가 아니고, 요청에 따라 프로세스가 변하거나 커넥션 정보 등 사용해야 하는 것들이 많기 때문에 EC2로 해야 한다고 얘기해주셨다.

 

그럼 우리는?

 

AWS의 서비스를 이용할건데 AWS S3, CloudFront, Route 53을 이용해서 CI / CD를 구축할 수 있다.

 

여기서 간단하게 각 개념의 대해서 간단하게 짚고 넘어가보자.

 

AWS S3 (Simple Storage Service) - 객체 스토리지 서비스 

 

AWS CloudFront - HTML, CSS, JS 및 이미지 파일과 같은 정적 및 동적 웹 컨텐츠를 사용자에게 더 빠르게 배포할 수 있도록 지원하는 CDN(Content Delivery Network)서비스, 여기서 CDN은 콘텐츠를 효율적으로 전달하기 위해 여러 노드를 가진 네트워크에 데이터를 저장해 제공하는 시스템을 말한다.

 

AWS Route 53 - 가용성과 확장성이 뛰어난 DNS(도메인 이름 시스템) 웹 서비스

 

그럼 여기서 한 가지 질문을 할 수 있는데 왜 AWS S3와 CloudFront를 같이 써야 하지? 라는 의문이 들 수 있다. 일반적으로 가장 많이 알고 있는 이유는 사용자가 Origin Server로부터 Contents를 다운받을 때 응답시간을 줄이기 위해 CloudFront와 같은 CDN (Content Delivery Network) 서비스를 이용해 사용자에게 더 빠르게 응답을 해준다.

 

근데 여기서 추가적인 이유가 있다. 우리는 React로 프로젝트를 진행하고 있고, React는 SPA(Single Page Application)다. 이 말은 리액트는 SPA기 때문에 각각 경로에 대한 static 파일이 존재하지 않는다. (전체 페이지가 하나의 index.html에 담겨져 있음) 따라서, CloudFront는 존재하지 않는 S3 객체를 요청하게 된다. 그러나 CloudFront는 버킷에 있는 파일만 액세스 할 수 있고 존재하지 않는 개체가 요청되면 403을 반환한다. 이 상황에서 CloudFront의 사용자 정의 오류 응답을 설정해줄 수 있는데 403에러를 사용자 정의 오류 응답으로 /index.html과 200 코드를 반환해주면 index.html이 반환되어 URL과 React Router는 원래의 작업을 할 수 있게 된다.

 

처음에는 S3만 가지고는 안될까? 라고 생각하다가 403 Error를 만나보니 더 명확한 이유를 알 수 있게 되었다.

 

그러면 과정에 대해서 살펴보자

 

User -> Route 53 -> Cloud Front -> S3 정적 배포된 페이지 -> index.html (도메인)

 

좀 더 풀어서 설명해보면, 

 

  1. 사용자가 도메인을 입력해 요청 보냄
  2. DNS 서버는 도메인 이름의 IP 주소를 찾기 위해 Route 53을 쿼리
  3. Route 53은 도메인 이름과 연결된 CloudFront 서비스에 대한 IP 주소를 반환
  4. 사용자 요청이 CloudFront 서비스로 전달되고 이 서비스 요청을 S3 버킷으로 라우팅 함
  5. S3 버킷에서 정적 파일이나 데이터를 가져와서 응답으로 반환
  6. CloudFront는 S3에서 받은 응답을 캐시하고, 클라이언트에게 응답을 반환

결국, Route 53은 DNS 서비스로서 도메인 이름을 IP 주소로 매핑하는 역할을 하고 CloudFront S3는 정적 파일과 데이터를 서비스하는 역할이라고 생각하면 된다.

 

이제 기본적인 개념과 큰 틀의 과정을 알았으니 CI / CD를 구축해보자!