aws

S3, Cloud Front

Posted by yunki kim on December 8, 2022

S3 (Simple Storage Service)

  S3는 여러 곳에서 파일에 접근할 수 있게 만들어진 서비스다. 웹 서비스에서 많이 사용하며 다양한 목적을 가진 파일들을 보관하는 데 사용된다.

  S3는 내구성, 가용성, 확장성에 대해 강점을 가진다. 내구성은 99.999999999%이며 파일 수와 용량에  제한이 없다(단, 하나의 파일(객체) 용량은 5TB로 제한돼 있다.). 또 한, 액세스 패턴과 사용 사례에 따라 다양한 스토리지 클래스를 이용해 데이터를 저장할 수 있다.

  파일 보안에 대해서도 IAM, ACL 등의 방식을 혼용해 다양한 유저가 다양한 파일에 접근하는 권한을 유연하게 제어할 수 있다. 또 한, 누나 어떤 데이터에 액세스 했는지를 알 수 있게 S3 리소스에 대한 요청 목록을 표시하는 감사 로그를 지원한다. S3 

  S3는 웹 콘솔을 지원하기 때문에 반드시 EC2를 통해서 접속하지 않아도 된다. 따라서 큰 데이터를 S3에 업로드하면서 동시에 AWS의 다른 서비스를 이용해 해당 파일들을 쿼리하고 분석할 수 있다.

  S3에는 버킷과 객체라는 개념이 존재한다. 버킷은 리소스다. S3는 데이터를 버킷이라는 리소스에 객체로 저장한다. S3는 디렉터리라는 개념이 존재하지 않기 때문에 필요하다면 객체 이름에 "/" 문자를 포함해 디렉터리를 조회하는 것처럼 이용할 수 있다.

  S3는 위와 같이 파일 스토리지의 역할뿐만 아니라 파일 제공 역할도 수행할 수 있다. 클라이언트에게 제공해야 하는  파일 중 코드와 같이 서버에 배포되지 않은 파일들은 모두 S3에 업로드하는 것이 좋다. 그러면 DB에 S3에 업로드된 객체 URL을 보관하는 것으로 클라이언트가 파일을 요청해 내려받을 수 있다. 이 방식을 채택한다면, 용량 확장, 파일 유식, 트래픽 등 운영에 필요한 내용을 걱정할 필요가 없다.

  S3는 정적 호스팅도 지원한다. S3 정적 호스팅을 사용하면 서버의 트래픽에 대해 걱정할 필요가 없다. 또 한, AWS 웹 콘솔 클릭 몇 번으로 새로운 버전의 파일을 올릴 수 있다.

  S3에 대한 더 자세한 설명은 링크를 참고하자.

S3로 리액트 앱 배포하기

  터미널을 통해 S3에 리액트 앱을 배포하기 위해 IAM 권한 설정을 먼저 하자. IAM 사용자에서 사용자 추가를 클릭해 사용자 생성 화면으로 이동하자.

  여기서 원하는 사용자 이름을 입력하고, 액세스 유형은 프로그래밍 방식 액세스를 선택하자.

다음 페이지에서는 기존 정책 직접 연걸을 선택하고 AmazoneS3FullAccess를 선택하자. AmazoneS3FullAccess는 S3의 모든 사용 권한을 부여해준다. S3 정책과 권한에 대한 기본 요소 내역은 링크를 참고하자.

  이제 태그 선택과 확인 절차를 거치면 아래와 같이 액세스 키가 생성된다. 여기서. csv 다운로드를 클릭해 파일을 다운로드하고 안전하게 저장하자.

  이제 AWS CLI를 설치하자.

  AWS CLI를 맥에서 터미널로 설치하기 위해서는 다음과 같은 명령어를 입력하면 된다.

1
2
3
4
5
6
7
8
# curl 명령어를 이용해 파일 다운로드. -o는 다운로드할 패키지가 기록되는 파일 이름을 지정한다.
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -"AWSCLIV2.pkg"
# 다운로드한 파일을 소스로 지겅해 표준 macos installer 프로그램을 실행한다.
# -pkg는 설치할 패키지 이름을 지정한다 . -target은 패키지를 설치할 드라이브를 지정한다
# 파일은 /usr/local/aws-cli에 설치되고, /usr/local/bin에 symlink가 자동으로 만들어진다
# 해당 폴더에 쓰기 원한 부여를 위해선 sudo를 포함해야 한다.
# 디버그 로그는 /var/log/install.log에 기록된다.
sudo installer -pkg AWSCLIV2.pkg -target /
cs

  AWS CLI를 설치하는 다양한 방법은 링크를 참고하자.

  설치 완료 후 다음 명령어를 입력해 설치가 올바르게 되었는지를 확인해보자.

1
2
3
4
which aws
# /usr/local/bin/aws
aws --version
# aws-cli/2.9.3 Python/3.9.11 Darwin/20.3.0 exe/x86_64 prompt/off
cs

   만약 위와 같은 결과가 나오지 않았다면 링크를 참고해 문제를 해결하자.

  이제 아래 명령어를 입력해 CLI 유저를 생성하자. 아래 커맨드에서 요구하는 Access Key ID와  Secret Access Key는 위에서 다운로드한. csv 파일에 존재한다.

1
aws configure --profile {user_name}
cs

  이제 S3 버킷을 생성하자. 다음과 같이 버킷 이름을 입력하고, 퍼블릭 액세스 차단을 해제하자.

버킷을 생성한 후 해당 버킷의 정책으로 가자.

여기서 버킷 정책에 다음과 같이 입력하자. 여기서 bucket-name에는 자신의 버킷 이름을 입력하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"AddPerm",
      "Effect":"Allow",
      "Principal""*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::bucket-name/*"]
    }
  ]
}
cs

  정책을 변경한 뒤 해당 버킷 속성에 있는 "정적 웹 사이트 호스팅"에서 웹 사이트를 호스팅 하자.

이제 배포를 시작해보자. 패키지 매니저는 yarn을 기준으로 한다. 우선 package.json의 scripts 부분에 "deploy"항목을 추가하자.

1
2
3
"scripts": {
    "deploy""aws s3 sync ./dist s3://{bucket_name} --profile={user_name}"
}
cs

  bucket_name과 user_name은 자신에게 맞는 세팅으로 변경해주자.

  그 후 yarn bulild를 통해 빌드 파일을 생성하자. 만약 빌드 파일 이름이 dist가 아닌 build라면, 위 "deploy"의 "./dist"를 "./build"로 바꾸고 다시 빌드하자. 그 후, yarn deploy를 입력하면 파일이 업로드된다.

  이제 Clould Front를 이용해 HTTPS와 커스텀 도메인을 연동해보자.

Cloud Front

  Cloud Front는 AWS에서 제공하는 CDN이다. CDN은 클라이언트가 데이터를 요청했을 때 오리진 서버까지 요청을 보내지 않고, 물리적으로 가까운 위치에서 대신 응답을 해주는 역할을 한다. 이를 통해 응답 시간을 단축할 수 있다. 이 덕분에 오리진 서버가 모든 요청을 처리하지 않아 오리진 서버의 부하를 분산시키는 효과도 누릴 수 있다. 

  Cloud Front는 S3를 오리진 서버로 두고 이미지, JS와 같은 정적 파일, 스트리밍 같은 콘텐츠도 전달할 수 있다. 이 경우 Cloud Front는 요청을 가장 가까이 있는 엣지 로케이션에 전달한다. 만약 응답할 데이터가 엣지 로케이션에 없다면 오리진 서버에서 데이터를 가져와 임시 보관하고 응답한다. 이후의 요청부터는 임시 저장한 데이터를 이용해 응답한다. S3의 원본 데이터가 변경된 경우 역시 모든 CDN 서버의 데이터를 업데이트하거나 삭제할 수 있다.

  Cloud Frontsms API 가속화 역할도 한다. 클라이언트가 물리적으로 멀리 있는 오리진 서버와 TLS 연결을 하지 않고, 엣지 로케이션과 연결을 하고, 그 뒷단은 AWS 백본 네트워크를 통해 API 서버에 빠르게 도달할 수 있다.

Cloud Front에 S3 연결 및 프론트 커스텀 도메인, HTTPS 적용하기

  cloud front에서 배포 생성을 클릭하고 위에서 생성한 S3의 버킷 웹 사이트 엔드포인트를 선택하자. 버킷 웹 사이트 엔드포인트는 해당 S3 버킷 속성 맨 아래에서 확인할 수 있다. 그 후 원하는 이름을 입력하고 뷰어 프로토콜 정책은 Redirect HTTP to HTTPS를 선택하자.

그 후 배포 생성을 클릭해 Cloud Front를 생성하자.

이제 커스텀 도메인을 사용하기 전에, ACM(Amazon Certificate Manager)에서 SSL 인증서를 발급해야 한다. ACM을 방문해 퍼블릭 인증서를 요청하자. 여기서 주의할 점은 Clouf Front에 ACM을 통해 발급한 SSL 인증서를 연동하기 위해선 반드시 버지니아 북부 리전에 존재하는 ACM에서 SSL 인증서를 발급받아야 한다.

  위와 같이 원하는 도메인 이름을 입력하고 요청을 클릭하면 된다. 그리고 검증 방법은 "이메일 검증"을 선택하자. DNS 검증을 하는 것이 권장되나, 이를 이용하려면 가비아에서 구매한 도메인을 Route53에서 호스팅 역역을 만들고 관리해 주어야 한다. 비용이 청구되므로 여기선 이 방식을 사용하지 않겠다. 이제 다음과 같이 생성된 인증서 상태가 "검증 대기 중" 인것을 볼 수 있다.

  생성됨과 동시에 해당 도메인 구입 시 사용한 이메일로 다음과 같은 검증 메일이 올 거다. 이 메일을 클릭해 검증을 완료하자.

  이메일 검증을 완료하면 다음과 같이 인증서 발금이 완료된 것을 알 수 있다.

  이제 다시 CloudFront로 돌아가서 커스텀 도메인을 연결하길 원하는 cloudFront를 선택하자. 그리고 일반 - 설정 부분에서 설정을 편집하자. 다음과 같이 AWS Certificate Manager로 인증서를 발급한 도메인을 "대체 도메인 이름(CNAME) - 선택 사항"에 입력해주고 위에서 발급한 인증서를 "사용자 정의 SSL 인증서 - 선택사항"에서 선택한 뒤 설정을 저장하자.

  이제 백엔드도 원하는 도메인으로 접근할 수 있게 Cloud Front를 설정하면 된다. 설정 방법은 Cloud Front 설정 시 위 방식에서 원본 도메인을 S3 대신 ELB를 선택하면 된다(ELB를 이용했다면).

  위 과정을 모두 마치면 다음과 같은 아키텍처를 가지게 된다.

  여기서 클라이언트는 무조건 Cloud Front와 커뮤니케이션을 한다는 것에 주목해야 한다. 즉, 클라이언트는 최초 접속 때 S3에서 페이지를 응답으로 받고, 페이지에서 요청을 보내면 Cloud Front가 받아서 Backend로 전달한다. 따라서 Cloud Front에서 설정한 Backend 배포에 CORS 정책을 추가해야 한다.

  Cloud Front는 간단한 설정이 된 정책을 제공하고 있다. 미리 설정된 응답 정책을 보고 싶다면 링크를 참고하자. 관리형 오리진 요청 정책을 보고 싶다면 링크를 참고하자.

  여기서는 직접 요청과 응답 정책을 커스텀해서 사용할 것이다. CloudFront에서 정책 - 원본 요청 부분에서 "사용자 정의 정책" 부분의 "원본 요청 정책 생성"을 클릭해 요청 정책을 생성하자.

  여기서 각자 상황에 맞게 헤더, 쿼리 문자열, 쿠키를 선택하면 된다.

  이제 응답 헤더 정책을 만들어보자. CloudFront-정책-응답 헤더에서 "사용자 정의 정책"의 "응답 헤더 정책 생성"을 클릭해 응답 헤더 정책을 생성하자. 여기서 "CORS 구성"을 선택하고 각자 상황에 맞게 세팅한 뒤 생성하면 된다.

 

  이제 CloudFront에 매핑한 커스텀 도메인을 통해 외부에서 CloudFront에 접근할 수 있도록 DNS 설정을 해주자. 설정한 CloudFront는 아래와 같이 "배포 도메인 이름"을 가지게 된다. 

  이 "배포 도메인 이름"을 통해 클라이언트는 CloudFront에 접근할 수 있다. 커스텀 도메인을 활용해 CloudFront로 접근하게 하려면 커스텀 도메인을 CloudFront "배포 도메인 이름"의 별칭(CNAME)으로 사용하는 레코드가 존재해야 한다. 나는 가비아에서 도메인을 구매했으므로 다음과 같이 가비아에서 DNS 설정을 바꾸어주자.

  다음과 같이 타입을 CNAME, 값/위치에 CloudFront의 "배포 도메인 이름"을 넣어주면 된다.