HTTPS 사용자 지정 Domain을 사용하여 CloudFront에 React App 배포하기

holang-i·2023년 8월 4일
0
post-thumbnail

http에서 https로 배포하려는 이유

http는 보안에 취약하기 때문에 https를 통해 보안성을 올리고, https 배포에 대해 알아보려고 합니다.
S3, Route 53, CloudFront, Certificate Manager, SSL 인증서 발급, 도메인을 적용하는 방법에 대해서 자세하게 정리하였습니다.

참고 영상 - Deploy React App to CloudFront with HTTPS Custom Domain

프로젝트 세팅 환경

Vite + React + TypeScript로 프로젝트를 진행하고 있습니다.



S3

aws S3는 클라우드에 파일을 저장할 수 있는 서비스이다.



CloudFront

Amazon CloudFront 주요 기능
cloudfront는 s3 버킷에 저장된 파일을 가져와서 전 세계에 배포하여 사람들이 우리 파일을 요청할 때 대기 시간을 크게 줄일 수 있는 고급 서비스이다.
s3보다 cloudfront에 대해 훨씬 더 많은 권한을 얻고,
사용자 지정 도메인 이름과 SSL 인증서를 추가하고, CloudFront에서 다른 많은 작업을 수행할 수 있다.

CloudFront를 사용하여 React App을 호스팅하고, https를 통해 사이트에 액세스할 수 있도록 SSL 인증서로 사용자 지정 도메인 이름을 설정할 것이다. 예) https://customdomain



Step 1 - build & S3 bucket 생성

cloudfront와 함께 호스팅하게 될 것이므로 html, css, javascript 파일을 가져올 수 있도록 프로젝트를 빌드하는 작업이 필요하다.

npm run build

위 명령어를 실행하면 작업 디렉토리 내에 dist 폴더가 생성되어 있을 것이다. (CRA의 경우는 build 폴더 생성)
dist 폴더 내 파일 및 기타 정적 assets css, javascript 등을 cloudfront를 사용하려면 먼저 s3 버킷을 생성해야 된다.


생성한 버킷 객체에 dist 폴더 안에 있는 파일, 폴더를 업로드 한다.



Step 2 - CloudFront

react app을 s3 버킷에 올려놓았으니 CloudFront 배포를 생성할 수 있고, 이 CloudFront 배포의 원본은 위에서 설정한 s3 버킷이 된다.

서비스 검색에서 cloudfront 를 검색하고 메뉴 선택을 하면 아래와 같은 화면이 뜬다.


배포 생성 버튼을 클릭하면 아래와 같은 화면이 뜨는데
원본 도메인 검색창에 클릭을 하면 만들어져 있는 s3 버킷의 리스트들을 확인할 수 있다. (원하는 버킷을 지정하면 된다.)


원본 액세스 설정

  • Legacy access identities을 클릭하면 인터넷을 통해 액세스할 수 있는 방법을 구성할 수 있다. 원본 액세스 ID인 OAI를 사용한다.
  • 새 OAI 생성 버튼을 클릭하면 새로운 OAI를 만들 수 있다.

이 과정을 선택하면 기본적으로 s3 버킷을 비공개로 남겨둘 수 있기 때문에 버킷 자체에 아무것도 액세스 할 수가 없고 웹사이트 파일에 대한 모든 액세스는 cloudfront를 통해 수행되어야 하므로 생성 버튼을 클릭한다.


버킷 정책 업데이트

버킷 정책을 업데이트하여 이 cloudfront 배포를 생성하면 이런 방식으로 s3 버킷이 업데이트되어 cloudfront 액세스 권한만 부여하고 다른 것은 제공하지 않는다.


뷰어 프로토콜 정책

HTTP를 HTTPS로 리디렉션하여 누구든 HTTP를 통해 웹사이트에 접근할 경우 HTTPS로 바로 전달하도록 설정을 변경한다.


허용된 HTTP 방법

http를 통한 액세스를 절대로 허용하지 않도록 해야된다. 정적 웹사이트일 뿐이기 때문에 HEAD만 있으면 된다.



설정

설정에서 s3 버킷의 파일을 복사할 위치를 선택할 수 있다.
모든 엣지 로케이션에서 사용(최고의 성능) 는 세계 곳곳 어디에 있든 상관이 없다. 가장 가까운 위치에서 웹사이트를 가져오도록 요청하면 가장 가까운 위치에서 웹사이트를 얻을 수 있지만 비용을 절약하고 싶다면 북미 및 유럽만 사용, 북미, 유럽, 아시아, 중동 및 아프리카에서 사용인 다른 옵션을 사용할 수 있다.


도메인 설정

사용자 정의 도메인 이름을 설정한다. 이것이 없으면 cloudfront에서 도메인 이름(매우 길고 의미없는 긴 이름)을 가져온다.
내가 원하는 고유의 사용자 정의 도메인을 원하므로 항목 추가 버튼을 클릭해서 도메인 이름을 추가할 수 있다.
(route 53에 도메인 이름 설정 과정 필요 -> cloudfront 설정 페이지를 끄지 마세요!)




Step 3 - Route 53 Domain Name

Route 53 이란?

Route 53은 AWS에서 제공하는 강력한 DNS 서비스이다.


사용자 지정 도메인 이름에 대한 간단한 경로 만들기

제 3자 도메인 공급자로부터 도메인을 구입하고 이를 route 53에 연결하여 서비스로 트래픽 라우팅을 시작할 수 있는 방법을 알아볼것이다.

Route 53 - 호스팅 영역

호스팅 영역단일 도메인 이름을 관리하는 방법이다.
호스팅 영역을 설정하지 않은 경우 아무것도 표시되지 않을 것이다.


Route 53 사용하기 위해 호스팅 영역 만들기

route 53을 사용하기 시작하려면 호스팅 영역을 만들어야 하며 각 호스팅 영역 비용은 한 달에 대략 50센트 정도라고 한다. (프리티어 기준)

호스팅 영역 생성

호스팅 영역 생성 버튼 클릭을 하면 아래와 같은 설정 창이 뜬다.
(이 설정창도 끄지 마세요. 도메인을 산 후 다시 돌아와서 설정을 적용합니다.)

도메인 이름 지정, 설명 및 기타 사항을 제공할 수 있다.

aws를 통해 도메인 이름을 구매할 수 있지만 aws를 통해 구매하게 될 경우 조금 더 비싼 금액과 제한적인 것들이 있고 훨씬 저렴한 .xyz, .site, .online과 같은 도메인 이름을 얻을 수 없다.

namecheap에서 도메인을 사려고 했는데 생각보다 원하는 게 없어서 gabia에서 도메인을 샀다.


Custom Domain Name - 가비아에서 도메인 서비스 신청하기

사용하고자하는 도메인을 먼저 검색하고

리스트에 나오는 것들 중 원하는 것을선택 버튼 클릭 후 신청하기 버튼을 클릭하면 서비스 신청 창으로 이동된다.


신청 정보, 소유자 정보, 약관 동의 부분만 설정하고 그 외 부분의 설정은 건드리지 않았다.

부가서비스 추가가 무엇인지 궁금해서 마우스를 올려보았다.

동시 신청 가능 서비스가 무엇인지 궁금해서 마우스를 올려보았다.

아래 약관 동의를 모두 체크 해야 다음 단계로 넘어갈 수 있다.
ICANN 약관 동의


도메인 등록 완료 후 My가비아에서 도메인 관련 정보 보기

My가비아 를 클릭하면

전체 대시보드를 통해 정보들을 확인할 수 있다.


도메인 관리로 들어가보기

이용중인 서비스에서 도메인 부분을 클릭하면 아래와 같은 창이 뜨는데
관리 버튼을 클릭해보자.

네임서버에서 1~4차 부분에서 내용이 변경되기 때문에 한번 살펴보면 좋다.



Domain Name Server - 네임 서버

현재 도메인 이름이 gabia 기본 DNS 서버를 사용하고 있기때문에
위 캡쳐에 있는 네임서버 옆 설정 버튼을 눌러 설정 페이지로 이동해야한다.


사용자 지정 DNS를 설정

네임서버 설정 페이지에서 사용자 지정 DNS를 설정해야 된다.

여기서 해야 될 것은 aws의 네임 서버에서 이 도메인 이름을 가리키는 것이다. 이는 누가 어디서 언제든지 내가 설정한 도메인 이름으로 갈 수 있음을 의미한다.

접속한 사람들이 실제로 인터넷에서 끝나는 최종 위치는 aws에 의해 결정되었으므로 여기에 aws의 네임서버를 입력해야 된다.

그렇게 하려면 먼저 aws에 해당 호스팅 영역을 생성해야 된다.

이제 아까 Route 53 -> 호스팅 영역 -> 호스팅 영역 생성 페이지를 띄워뒀을텐데 여기서 원하는 호스팅 영역과 도메인 이름을 생성해야 된다.



Route 53 - 호스팅 영역 생성하기

도메인 이름

  • 도메인 이름에는 가비아에서 구입한 도메인 이름을 적어 준다.
  • 사람들이 공용 인터넷을 통해 액세스할 수 있기를 원하기 때문에 퍼블릭 호스팅 영역이 된다.

그리고 나서 호스팅 영역 생성 버튼을 클릭하면 된다.


gabia의 기존 네임 서버 값을 aws의 네임 서버값으로 변경하기

첫 번째 레코드 NS 레코드에 값/트래픽 라우팅 대상에는 이 모든 작업을 수행하기 위헤 gabia에 입력해야 하는 aws의 네임 서버목록이 있다.

위 라우팅 대상 목록값들을 하나씩 복사해서 gabia의 네임 서버 값들(1~4차)을 변경해 줄 것이다. (마지막에 있는 .은 지워주기, 복사 순서는 상관 없다.)

네임 서버를 변경한 사항이 바로 반영되면 좋겠지만 실제로 route 53 서비스를 사용할 수 있을 때까지 하루정도 걸릴 수 있다고 한다.


Route 53에 하위 도메인 생성 & Route 53에서 CloudFront 레코드 추가하기

이 부분에서 많이 헤맸기 때문에 이 글을 읽는 분들은 한 번에 https로 잘 성공하셨으면 좋겠습니다. 🐯

  • 우선 Route 53에서 호스팅 영역 생성을 처음에 했으면 NS 레코드, SOA 레코드 2개의 목록이 떴을 것이다.

  • 그리고 나중에 SSL 인증서를 발급할 때 추가되는 CNAME 레코드 1개(뒤에서 나오니 크게 신경쓰지 않아도 됩니다.)


  • 가장 중요한 CloudFront를 연동할 A 레코드 2개가 있다.

레코드 생성 버튼을 눌러서 빠른 레코드 생성 페이지에서 레코드를 추가하면 된다.


레코드 이름:
루트 도메인으로 접속 or www.루트 도메인으로 접속했을 때 CloudFront로 연동되도록 설정해 줘야 된다.

별칭:
별칭을 활성화하고, 별칭을 통해서 CloudFront 배포에 대한 별칭을 지정해줄 수 있다.

트래픽 라우팅 대상:
CloudFront 배포에 대한 별칭을 선택하고, 아래 배포선택에서 CloudFront 배포를 선택한다.


  1. 트래픽 라우팅 대상을 CloudFront 배포에 대한 별칭으로 선택한다.
    그리고, 배포 선택에서 나오는 값을 선택한다.

  1. 트래픽 라우팅 대상을 S3 웹 사이트 엔드포인트에 대한 별칭으로 설정하고, 지역은 아시아 태평양(서울), 배포 선택에 나온 값을 지정해준다.
    레코드 이름에 www를 붙여준다. (레코드 이름을 먼저 작성하고, 배포 선택 부분을 클릭하면 값을 못 읽어왔었기 때문에 저는 적어놓은 순서대로 진행해서 문제해결을 할 수 있었습니다.)



Step 4 - SSL Certificate

이제 도메인 이름과 호스팅 영역이 설정되어 있는 것을 확인할 수 있다.

이제 다시 CloudFront로 와서 설정 부분을 봅니다.

대체 도메인 이름(CNAME) - 선택사항
대체 도메인 이름(CNAME)에서 항목 추가 버튼을 클릭하고 루트 도메인 이름을 적습니다. (가비아에서 산 도메인)

이제 루트 도메인 이름을 사용할 것이므로 대체 도메인 이름으로 추가한다음 이것이 https에서 작동하는 지 확인해야 된다.


https에서 작동하는 지 확인 - 사용자 지정 SSL 인증서가 필요

새 인증서를 요청해야 하므로인증서 요청 을 클릭한다.


주의점

인증서 요청 클릭 후 열린 페이지에서 상단에 메뉴부분을 보면 위치가 기본으로 버지니아 북부로 설정되어 있는데 이 부분은 다른 것으로 변경하면 안 됩니다. (서울로 변경했다가 아래 사용자 정의 SSL 인증서 불러오는 부분에서 가져오질 못 했습니다.)


AWS Certificate Manager (ACM)에서 SSL 인증서를 관리하려면 CloudFront 배포에 사용하는 인증서는 "US East (N. Virginia) us-east-1(미국 동부(버지니아 북부))" 리전으로 생성해야 합니다.
  1. Global service:
  • Amazon CloudFront는 글로벌 서비스이며, 가장 최적의 엣지 로케이션에 요청을 자동으로 라우팅합니다.
  • 인증서를 사용할 수 있도록 적절한 엣지 로케이션에 인증서를 전파해야 합니다. "US East (N. Virginia) us-east-1"로 생성된 인증서는 다른 리전으로 여러 복제본을 복사하지 않고 사용할 수 있습니다.
  1. 정책 및 일관성:
  • AWS는 미국 동부(N. Virginia) 리전에서 인증서를 발급받도록 요구하는 일관된 정책을 통해, 사용자가 이용하는 시스템 성능 및 안정성을 보장합니다.
  • 이 규칙을 준수함으로써, AWS는 높은 신뢰성의 인프라를 유지하고 이러한 서비스를 원활하게 구축합니다.


    정리
  • AWS CloudFront에서 SSL 인증서를 사용하기 위해서는 "US East (N. Virginia) us-east-1" 리전에서 ACM을 이용해 인증서를 생성하고 이를 CloudFront 배포에 적용해야 합니다.
  • 이 방법으로 CloudFront와 연동되며 지정한 도메인에서 SSL 인증서가 HTTPS 통신에 정상적으로 사용되도록 할 수 있습니다.

퍼블릭 인증서 요청이 기본으로 선택되어 있고, 다음 버튼을 클릭한다.


완전히 정규화된 도메인 이름에 aws 인증서 관리자를 통해 요청하려는 도메인 이름을 입력한다.


검증 방법
DNS 유효성 검사를 원하므로 route 53을 통해 유효성을 검사한다.


키 알고리즘, 태그는 기본값을 그대로 두고 요청 버튼을 클릭한다.


확인 대기 중 상태의 인증서 요청이 생성되었고, 우측에 인증서 보기 버튼을 클릭해서 해당 페이지로 이동해야 된다.


도메인에서 Route 53에서 레코드 생성 버튼을 클릭해야 실제로 해당 레코드를 생성하고, 내 도메인 이름을 확인할 수 있다.


이제 다시 돌아와서 레코드 생성 버튼을 클릭하면

유효성 검사 대기중이며 빠르면 1~2분 내에 SSL 인증서가 발급된다고 하던데
(15분정도 걸린 거 같아용...)


다시 CloudFront로 돌아와서 새로고침 버튼을 클릭해보면
설정한 ACM 인증서 목록이 뜨는 것을 확인할 수 있다.


보안 정책은 기본 권장값으로 둔다.


기본값 루트 객체 - 선택 사항에는 cloudfront 배포쪽에 index.html 파일을 제공하도록 요청하고 React App의 진입점은 index.html 파일이므로 이것을 제공한다.


표준 로깅, IPv6는 기본값으로 둔다.
배포 생성 버튼을 클릭한다.


Custom ErrorPage for React

오류 페이지 탭에서 사용자 정의 오류 응답 생성 버튼을 클릭해서 사용자 지정 오류 응답을 생성해야된다.

사용자 정의 오류 페이지를 만드는 이유

SPA인 React App을 호스팅할 때 실제로 index.html 파일을 제공하고 모든 것이 index.html에서 완료되기 때문이다.
존재하지 않는 경로, 파일등을 요청했을 때 오류가 발생하게되는데 기본적으로 cloudfront는 존재하지 않는 페이지는 403 status code로 응답을 하므로 403으로 응답하지 않도록 설정할 것이다.

아래와 같이 설정해주면 된다.
이렇게 하는 이유는 프론트에서 필요한 모든 작업을 수행할 수 있도록 하기위해 사용자 정의 오류 응답을 생성하는 것이다.



Step 5 - 웹사이트 업데이트

웹사이트를 업데이트 해야되는 경우 build -> s3 bucket에 업로드 그러면 기존의 s3파일이 새로운 파일들로 덮어씌워져서 업데이트가 된다.
하지만, 배포된 웹사이트에서는 업데이트가 반영되지 않는데 이것은 cloudfront가 많은 캐싱을 수행하기 때문에 잠시동안 해당 업데이트된 것들을 볼수가 없다. 해당 업데이트가 실제로 반영되기까지 24시간이 걸릴 수 있다.

그렇기 때문에 캐시를 무효화하는 작업이 필요하다.

캐시 무효화

무효화 생성 버튼을 클릭하고 모든 파일을 무효화해야 한다고 알려줘야 된다.

정적 웹사이트이므로 파일이 그렇게 많지 않기때문에 전체 파일로 설정했다.

무효화 설정을 했기 때문에 cloudfront에 배포하려는 업데이트가 있을 때 마다
1. 해당 파일을 s3에 업로드
2. coludfront 내에서 해당 업데이트를 볼 수 있도록 파일 무효화 작업이 필요하다.


마무리

설정한 도메인 주소로 잘 접근이 잘 되는 것을 확인할 수 있다.
http로 접근을 해도 https로 리다이렉트되게 설정한 것도 잘 작동되는 것까지 확인할 수 있었다.





남은 작업

CI/CD & Github Action 적용






https를 적용하는 것이 너무 막연하고 어렵게 느껴졌기 때문에 두려운 영역이었는데 해당 개념들이 무엇이고, 어떤 과정을 통해 환경을 설정해야되는지 자세하게 짚으면서 했더니 고생한만큼 개념이 잘 적립된거 같습니다.
단계별로 진행하면서 쓴 글이라 흐름이 뒤죽박죽인것처럼 느껴질 수도 있을 거 같아서 글을 조금 더 수정해봐야겠습니다.

profile
🌿 주니어 프론트엔드 개발자입니다! 부족하거나 잘못된 정보가 있다면 알려주세요:)

2개의 댓글

comment-user-thumbnail
2023년 8월 4일

감사합니다. 이런 정보를 나눠주셔서 좋아요.

1개의 답글