본문 바로가기

FE&BE

[수면TI 프로젝트] AWS를 이용하여 웹 사이트 호스팅해보기

정적웹사이트 호스팅하게 된 배경..

최근에 친구 프로젝트를 도와주게 되었는데 제가 맡은 역할은 정적 웹사이트를 AWS를 이용해서 호스팅하여 배포 하는 것이었습니다. 요새 굉장히 많이 쓰이는 리액트, 뷰, 노드 등 여러 프레임워크들과는 다르게 정적 웹사이트는 html, css, js로만 이루어져 있고 이를 어떤 서버에 올리고 어떻게 돌리지? 라는 생각이 들었고 구글링부터 시작하였습니다. 왜냐하면 정적 웹사이트는 index.html에 접속하면 실행되는 형식으로 되어있고, 제가 잘 아는 AWS EC2 인스턴스를 빌려 그곳에 올려두어도 어떤 형식으로 웹 사이트를 돌리는지, index.html에 접근하게 하는지 문제가 많았기 때문입니다.. ㅠㅠ

 

아래부터는 구글링을 통해 알게 된 지식입니다. 따로 AWS 책을 공부하지는 않았지만 AWS공식문서와 몇몇의 블로그들을 읽으며 진행해보면서 방법들을 아주 간단하게 정리하고 마주친 이슈들을 정리해보려고 합니당

AWS 서비스 - S3, Route53, Cloudfront, EC2 

1️⃣ Amazon S3 정적 웹 사이트 호스팅

먼저, S3 버킷을 생성하고 필요한 html, js, css 파일들을 올렸습니다. 그리고 속성 탭의 가장 하단 부분에 위치한 정적 웹사이트를 활성화 시켜주고 호스팅 유형은 정적 웹 사이트 호스팅, 인덱스 문서는 기본 홈 페이지로 index.html를 선택해주었습니다. 그럼 엄청 긴 URL이 나올거예요. 하지만 이렇게 끝나게 되면 URL에 모두가 접속을 할 수 없습니다. 퍼블릭 접근 권한을 모두에게 주기 위해서 권한 탭에 들어가 모든 퍼블릭 엑세스 차단 체크를 해제하고 버킷 정책도 자동으로 생성해주는 정책 생성기에 가서 아래와 같이 만들어줍니다. 중요한 부분은 삭제했습니다. 이 부분은 구글링해서 검색하면 많이 나오기 떄문에 넘어 가도록 하겠습니다! (구글에 S3 정적 웹 호스팅이라고 치면 많이 나와요)

👉 AWS 문서 : https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/EnableWebsiteHosting.html

 

2️⃣ 가비아에서 구매한 URL, S3 버킷 웹 사이트 엔드포인트와 연결하기

가비아에서 구매한 URL을 AWS에 등록이 우선입니다. AWS 콘솔에서 Route 53 서비스에 들어가 호스팅 영역을 생성해준 후, 생성된 4가지 NS를 가비아 도메인 관리 메뉴에 들어가 복붙해주면 됩니다! (구글에 가비아 AWS 도메인 연결이라고 치면 방법이 많이 나와요) 저는 이곳을 참고했습니다.

여기까지 하신다면 AWS에 URL 등록은 되었습니다. 이제 위에 생성된 긴 URL, S3 버킷 웹 사이트 엔드포인트와 연결을 시켜주어야 합니다. 아래 몇가지 작업을 해주시면 돼요!

 

  1. 정책 생성기를 누르고 단순라우팅을 선택합니다.
  2. 단순 레코드 정의를 선택하고 레코드 이름에는 하위 도메인을 적어주고, 아래와 같이 선택해줍니다. 이럼 생성해놓은 S3 엔드포인트가 자동으로 뜹니다. 그것을 선택해줍니다.
  3. 레코드 생성을 눌러줍니다. 이렇게 되면 연결이 완료됩니다.

S3 버킷 웹 사이트 엔드포인트는 위와 같이 입력하면 되는데 EC2인스턴스의 IPv4 도메인같은 경우도 위와 비슷하게 연결해줄 수 있습니다. (검색어: EC2 인스턴스 도메인 연결) 여기까지만 해도 정적 웹 사이트 호스팅은 마친 겁니다. 하지만 후에 http를 https 설정으로 바꾸는 작업에서 정말 많은 이슈들을 만나고 말았어요 ㅠㅠ

 

3️⃣ https 설정

http에서 https로 바꾸는 설정은 S3 버킷을 이용할 때와 EC2 인스턴스를 이용할 때 약간 다릅니다. S3 버킷을 이용할 때는 CloudFront라는 서비스를 이용했고, EC2 인스턴스를 보안화 시키는 작업은 EC2의 로드 밸런싱 서비스를 이용했습니다. 하지만 공통적으로 사용한 서비스는 AWS Certificate Manager 인증서입니다. 제가 알기로는 이 인증서를 발급받을 수 있는 곳이 여러곳들이 있는데 다른 곳들은 3개월마다 한번씩 계속 갱신을 해줘야 하는 반면 AWS에서는 1년동안 지속된다고 알고 있습니다! 그리고 AWS 서비스를 이용하는데 AWS에서 인증서를 발급받으면 연결도 편하고 좋습니다. ㅎㅎ

 

Certificate Manager 인증서를 발급받는데 중요한 점은 도메인을 *.원하는 URL 이라는 것을 추가해주는 것입니다. 이것을 추가하지 않는다면 서브 도메인들을 연결 시키고 싶어도 그 URL에 대한 보안 인증서가 없기 때문에 연결이 안 될 수 있습니다!

 

1) S3 https 설정 - CloudFront 서비스 이용

발급을 받은 후, CloudFront 서비스를 사용했습니다. 생성하는 방법은 구글링에 굉장히 많이 나와있어요! 하지만 AWS문서가 가장 정확한 것 같습니다 ㅎㅎ CloudFront는 사실 https 설정을 위한 서비스가 아니라 .html, .css, .js 및 이미지 파일과 같은 정적 및 동적 웹 콘텐츠를 사용자에게 더 빨리 배포하도록 지원하는 웹 서비스입니다. 사용자가 콘텐츠를 요청하면 지연 시간이 가장 낮은 엣지 로케이션으로 요청이 라우팅되기 떄문에 더 빨리 배포할 수 있습니다. 하지만 이 서비스 때문에 제가 한참을 헤맸던 배포 시 S3 버킷 웹 사이트 엔드포인트에는 바로 적용이 되는데 CloudFront를 이용해 연결해놓은 엔드포인트에는 적용이 한참 후에 되는 이슈가 발생하게 됩니다... (서비스를 잘 이해하지 않고 구글링만으로 사용하게 되면 저랑 비슷하게 헤맬거예요ㅠ) 이건 마지막에 다시 설명하겠습니다!

CloudFront 서비스를 이용해서 https 설정을 하고 Route53에 돌아가 엔드포인트를 S3가 아닌 CloudFront로 라우팅을 시켜줍니다. 그렇게 된다면 설정이 완료됩니다. (이에 대해서도 구글에 아주 자세히 나와있습니다.)

 

2) EC2 https 설정 - Load Balancer 서비스 이용

이것은 이 블로그에 굉장히 자세히 나와있어요 🙃 S3 정적 웹사이트 호스팅만 다루려다 보니 생략~ 하지만 주의할 사항이 한가지가 있는데 EC2 인스턴스를 생성하실 때 https의 443포트도 보안 그룹에 넣어주어야 합니다!

자동 배포 (Automated Deployment) - Github Actions

로컬에서 작업하고 이를 다시 AWS 콘솔에 들어가 S3 버킷을 전부 다 지우고 다시 드래그해서 올려야하는 번거로움이 있었어요. 그래서 이를 자동화시키고 싶어 찾아보다 Github Actions라는 것을 발견하게 됩니다. 이를 적용시키면 아래와 같이 동작합니다.

 

  1. 로컬에서 작업 후 깃헙 develop에 푸쉬 (main에 바로 푸퓌해도 됨)
  2. develop에서 작업하다 main에 합친다. (Pull Request)
  3. main 브랜치에 새로운 내용이 업데이트가 된다면 자동으로 S3 버킷으로 보내진다.

정말 편했습니다. ㅎㅎ 이를 설정하기 위해서 아래의 단계를 거쳐주었습니다.

 

  1. Github Actions를 위한 AWS IAM 을 생성하기
  2. Github에 암호화시켜서 등록해놓기
  3. .github/workflows라는 디렉토리를 만들고 그 안에 deploy.yml 파일을 생성하여 자동 배포 내용 적기

이는 여기를 참고했어요. 너무 잘 정리되어 있더라구요. 👍

그리고 따로 빌드할 필요없이 S3 버킷에 올려놓기만 하면 되기 때문에 아래처럼 파일 내용을 적으면 됩니다.

name: Deploy

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Cache modules
        uses: actions/cache@v1
        id: yarn-cache
        with:
          path: node_modules
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: ${{ runner.os }}-yarn-
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2
      - name: Deploy
        run: aws s3 sync ./YOUR-BUILD-DIR s3://YOUR-BUCKET-NAME

이슈 정리

1. CORS 이슈

이건 정말 웹을 조금만 다루다보면 맞닥뜨리는 문제라고 생각이 드네요.. 이 문제는 간단하게 정리하자면 현재 제 URL에서는 보안 상의 이유로 자신의 출처(URL)와 동일한 리소스만 불러올 수 있다는 것입니다. 즉, dddd.com에서는 dddd.com에 있는 리소스만 불러올 수 있게 된다는 것이죠. 만약 다른 출처의 리소스를 불러오려면 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 해요. 사실 헤더에 한가지만 추가해주면 되서 Get통신은 해결이 되었지만 Post통신이 해결이 안되더라구요 ㅠㅠ 그래서 이틀동안 머리를 꽁꽁 싸맸던 것 같네요..

Get통신 해결 : Get통신은 제가 API를 만들었기 때문에 헤더에 'Access-Control-Allow-Origin: * ' 을 추가해서 쉽게 해결할 수 있었습니다.

Post통신 해결 : Post통신을 보내기 전에 OPTION이라는 Restful API를 먼저 보내서 현재 End-point가 제공 가능한 API method인지 확인을 먼저 한다고 합니다. 저는 Post와 Get 통신의 헤더에만 추가해주었기 때문에 오류가 나는 것이었습니다. 그래서 Option에도 추가해주었더니 이슈가 해결되었습니다.

 

2. https 보안 설정된 웹 사이트 내에서 Restful API 통신은 전부 https로 이루어져야 한다.

웹 사이트를 https 보안 설정을 하고 배포를 시켜보니 원래 되던 통신들이 갑자기 안되었습니다. 폰트를 받아온다던지, 유저 등록을 한다던지 등등,,, 콘솔창에는 아래와 같은 오류가 나왔습니다. 알아보니 https내에서는 https 통신만 가능해야합니다. 따라서 API들도 전부 https로 수정해주었습니다.

 

 

3. S3 버킷 웹 호스팅 엔드포인트에는 바로 적용이 되지만 CloudFront 서비스를 이용해서 https로 설정한 URL은 반영이 24시간 뒤에 되는 이슈

CloudFront라는 서비스에 대해서 자세히 알아볼 필요가 있습니다. CloudFront는 웹 콘텐츠를 사용자에게 더 빠르게 제공하기 위한 서비스로 사용자에게 더 가까운 지역에 위치한 곳에 라우팅시켜 그곳에서 콘텐츠들을 가져오는 것입니다. 즉, S3 저장소는 미국에 있다고 치면, CloudFront 서비스를 이용해 우리 한국 라우터에 콘텐츠들을 저장시켜놓고 거기에서 꺼내오는 것입니다. 따라서 미국에 위치한 S3 저장소를 업데이트시켜도 한국에 위치한 라우터는 내용이 업데이트가 안되었기 때문에 바로 반영이 안되는 것이었습니다. 또한 CloudFront 설정을 할 때 TTL 설정을 24시간으로 해놓았기 때문에 하루가 지난 후에야 다시 S3 저장소에서 콘텐츠를 가져오는 것이라 반영이 늦어지는 것이었습니다.

 

이를 해결하기 위해 Invalidation 탭에 들어가 파일들을 강제로 업데이트 시켜주었습니다. 이것도 한달에 1000번은 프리티어로 무료로 사용 가능하다고 하네요! ㅎㅎ

정리

iOS를 공부하고 개발하면서 뜻밖에 백 작업과 AWS를 발만 담가보는 공부를 하게 되었는데 정말 소중한 경험을 한 거 같아요. iOS에서 요새 코드분리, 아키텍처 등과 같은 고민을 하고 연구하고 있었는데 AWS에서는 또 다른 의미의 아키텍쳐를 설계하고 이용하다보니 더욱 구조의 중요성을 느끼게 되었습니다 😿 언넝 공부해야지...

AWS 작업을 하면서 많은 이슈들을 만났고 그 이슈들을 해결해 나가며 CS의 중요성을 새삼 느꼈네요... 컴퓨터 네트워크를 전혀 몰랐다면 Name Server가 무엇인지, TTL이 뭔지 등 원인도 찾지 못해 오류에 대해 찾아보지도 못 했을 겁니다 ㅎㅎ 학교 수업 열심히 들읍시다~!!! 🔥