얼마 전에 드디어 Ohys-fe를 Super fast한 AWS Cloudfront로 이전했습니다. Vercel에서도 AWS 망이 그나마 제일 쾌적했는데 말이죠. 이제는 항상 쾌적하게 되었습니다.


낮은 지연 시간은 여러분의 스트레스 절감을 위해 매우 중요합니다. 하지만 개인이 CDN을 구축하기란 쉽지 않습니다. CDN의 주 목적은 전세계에서 에셋 로드 시간을 평준화하기 위한 것이고 그렇기 위해서는 물리적으로 최소한 3곳에 서버를 두어야 한다고 생각합니다.

  • 미국 서부: 미국과 남미 지역 담당
  • APAC: 아시아 지역 담당
  • 유럽: 미국 동부까지도 담당

그렇기 때문에 재정적인 여유 그리고 관리할 시간까지 1명으로는 하기가 약간 벅찬 작업입니다. 하지만 클라우드 서비스의 가격은 전혀 그렇지 않습니다. 정말 저렴한 편이죠.

애플리케이션 구조

여기에서 만들 애플리케이션의 구조는 다음과 같은 구조를 가지게 됩니다.

  • AWS S3: 여러분의 정적 웹 사이트를 저장합니다.
  • Let's Encrypt: CloudFront에서 SSL을 위해 사용할 인증서입니다.
  • AWS CloudFront: 여러분의 웹 사이트를 전 세계에 CDN으로 배포해줍니다.
  • React.JS*: 프론트엔트 프레임워크 React.JS에 React router를 끼얹을 때는 모든 라우팅 경로를 index.html로 맞춰주어야 합니다.

여기에서는 주제와 관련되지 않은 세부적인 사항에 관해서는 다루지 않습니다. 기본적인 AWS와 React.JS의 스택이 필요합니다.

프로젝트 시작하기

먼저 자칫 요금 폭탄을 맞지 않도록 AWS에서 비용을 미리 지정해두어야 합니다. 물론 저렴하지만 저희에게만 저렴한게 아니니깐요. 언제 누가 AWS Lambda로 여러분에게 수십만원을 부과해줄지 몰라요.

최대 예산 설정하기

AWS 콘솔을 열고 먼저 결제 대시보드로 이동합니다.

그리고 왼쪽의 메뉴에서 Budgets를 클릭하여 예산을 설정해주도록 합니다.

React.JS 빌드하기

package.jsonhomepage 값을 적절히 조정해주시는 것을 잊지 마세요. 혹시 무언가 괜찮은 도메인 이름이 떠오르지 않는다면 일단 ./로 맞추어주는 것도 전혀 나쁘지 않은 방법이에요. 여기에서는 기본적인 템플릿을 사용하겠습니다.

AWS에 프로젝트 올리기

이제 시작하기 전에 기본적인 것들이 준비되었으니 AWS에 하나하나 올려주면 됩니다.

AWS S3에 프로젝트 파일 업로드하고 호스팅 시작하기

가장 먼저 정적 웹사이트가 보관될 프로젝트 파일을 AWS S3에 업로드해주어야 합니다. AWS S3 콘솔에서 새로운 버킷을 만들고 체크박스를 모두 해제하여 퍼블릭 액세스를 허용해주세요.

그리고 버킷을 생성하여 생성한 ID를 목록에서 클릭하고 좌측 상단의 업로드 버튼을 통해 빌드된 파일들을 업로드합니다.

그 다음 속성 탭에서 정적 웹 사이트 호스팅을 활성화해야 합니다. 만약 React router를 사용하고 있다면 index.html로 모든 라우팅을 설정해야 합니다. 라우팅을 모두 프론트엔드에서 결정하는 동시에 모든 들어오는 주소 모두 프론트엔드에서 결정을 해야 하기 때문입니다. 그러므로 들어오는 주소는 /somewhere이라도 실제 로드되는 파일은 언제나 index.html이 되어야 합니다.

다음으로 몇 가지 권한 설정을 해주시면 되겠습니다. 첫 번째는 익명 사용자에게 버킷 읽기 권한을 부여하는 것입니다.

그리고 버킷 정책 메뉴로 이동해주신 다음 아래에 있는 스니펫을 통해서 접근 제어를 허용해야 합니다. Statement.Resource<BukkitName> 값은 설정하신 버킷의 ID로 변경해주세요.

{
    "Version": "2012-10-17",
    "Id": "Policy1590373528714",
    "Statement": [
        {
            "Sid": "Stmt1590373528714",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<bukkitID>/*"
        }
    ]
}

Let's Encrypt 인증서 발급하기

여기에서는 Let's Encrypt를 Cloudfront 공용 인증서 대신 사용하기 때문에 그에 대한 부분은 서술하고 있지 않습니다. 아래의 명령어로 DNS Verification을 진행할 수 있습니다.

letsencrypt --manual --preferred-challenges dns certonly -d domain.tld -d ...another.domain.tld
  • Let's Encrypt의 CAA 레코드는 letsencrypt.org입니다.

AWS Certificate Manager에 인증서 가져오기

다시 AWS 콘솔로 돌아가서 ACM 패널을 열어주세요. Cloudfront 패널은 기본적으로 글로벌 지역에서 열리는데 이는 기본적으로 미국 동부 지역(버니지아 북부)을 나타냅니다. 그렇기 때문에 미리 우측 상단에서 지역을 변경해주셔야 합니다. 제 경험 상 서울 리전에서 추가된 인증서는 표시되지 않더라고요. 그리고 인증서 프로비저닝을 선택하고 인증서 가져오기 버튼을 누릅니다.

그리고 발급받은 Let's Encrypt 인증서에서 다음 파일들의 내용을 붙여넣으면 됩니다.

  • 인증서 본문: cert.pem
  • 인증서 프라이빗 키: privkey.pem
  • 인증서 체인: chain.pem

AWS Cloudfront에 배포하기

AWS 콘솔에서 Cloudfront 관리자에 연결하고 파란색 Create distribution 버튼을 클릭해 새 웹 사이트 배포 플랜을 작성합니다. 여기에서 저희가 필요한 것은 Web 형식입니다.

그리고 아래와 같이 폼을 작성해주신 다음 우측 하단의 Create distribution 버튼을 클릭해주세요.

  • Origin Domain Name: AWS S3의 버킷 ID
  • Viewer Protocol Policy: Redirect HTTP to HTTPS
  • Alternative Domain Names (CNAMEs): example.com
  • SSL Certificate: Custom SSL Certificate (Let's Encrypt)
  • Default Root Object: /index.html

그리고 마지막으로 위에서도 설명했듯이 모든 요청을 ./index.html 파일로 Fallback하도록 설정해주면 됩니다. 배포 플랜의 ID를 누르고 Error Pages 탭에서 Create custom error response 버튼으로 새로운 에러 핸들러를 작성해주세요.

  • HTTP Error Code: 404
  • Error Caching M. TTL (seconds)*
  • Customize Error Response: Yes
  • Response Page Path: /index.html
  • HTTP Response Code: 200: OK

그럼 이제 Cloudfront 도메인에서 여러분의 React.JS 애플리케이션이 작동하는 것을 볼 수 있습니다. CNAME 레코드를 설정하신 분께서는 DNS 레코드에 CNAME으로 Cloudfront 도메인(*.cloudfront.net)을 추가해주시면 되겠습니다.

네, 여기까지입니다.