서버를 직접 사서 기계실에 놓아야만 서비스를 운영할 수 있다고 생각하는 분들도 여전히 계십니다. 그런데 저는 이번에 AWS 하나로 프론트엔드 배포부터 HTTPS 인증서 발급까지 전부 처리해봤고, 솔직히 이건 예상 밖이었습니다. 설정 단계마다 헷갈리는 부분이 꽤 있었고, 잘못 건드리면 요금이 청구된다는 긴장감도 있었지만, 그 과정에서 클라우드 인프라 구조가 어떻게 맞물려 돌아가는지 꽤 명확하게 이해할 수 있었습니다.

EC2와 S3, 각 서비스가 하는 일
AWS는 퍼블릭 클라우드(Public Cloud) 플랫폼입니다. 여기서 퍼블릭 클라우드란 아마존이 전 세계에 구축해 놓은 물리 서버 인프라를 인터넷을 통해 누구나 빌려 쓸 수 있는 구조를 의미합니다. 직접 서버를 구매하지 않아도 필요한 만큼 컴퓨팅 자원을 사용하고 그만큼만 비용을 지불하는 방식입니다.
이 안에서 제가 이번에 주로 다룬 서비스는 세 가지였습니다.
- EC2(Elastic Compute Cloud): 운영체제까지 설치된 가상머신을 제공하는 서비스. 쉽게 말해 남의 컴퓨터에 우분투를 깔아 쓰는 것과 같습니다.
- S3(Simple Storage Service): 파일을 저장하고 꺼내 쓸 수 있는 스토리지 서비스. 웹 서비스는 결국 파일을 주고받는 구조이기 때문에, 빌드된 프론트엔드 파일을 여기에 올려두면 정적 웹 호스팅이 가능합니다.
- CloudFront: CDN(Content Delivery Network) 서비스입니다. CDN이란 S3에 올린 파일을 전 세계 각지에 흩어진 엣지 서버로 복사해두고, 접속자와 가장 가까운 서버에서 파일을 내려주는 방식입니다. 미국 사용자가 접속하면 미국 서버에서, 한국 사용자가 접속하면 한국 서버에서 파일을 받아가는 구조입니다.
EC2 인스턴스를 처음 만들 때 키 페어(Key Pair) 설정이 나옵니다. 키 페어란 비대칭 암호화 방식으로 생성된 개인키와 공개키 한 쌍을 말하며, 개인키 파일(.pem)을 가진 사람만 해당 서버에 SSH로 접속할 수 있습니다. 이 파일을 잃어버리면 서버에 접속할 방법이 없으니 따로 잘 보관해야 합니다. 저도 처음에 대충 바탕화면에 저장해뒀다가 폴더 정리하면서 경로가 바뀌어서 접속 명령어를 다시 입력해야 했던 경험이 있습니다.
인스턴스 생성 후 nginx를 설치하고 퍼블릭 IP로 접속해봤는데 TIME_OUT이 뜨는 것을 경험했습니다. 이건 AWS의 보안 그룹(Security Group) 설정 때문입니다. 보안 그룹이란 인스턴스 단위로 적용되는 방화벽으로, 인바운드(외부 → 서버로 들어오는 트래픽)와 아웃바운드(서버 → 외부로 나가는 트래픽)를 각각 제어합니다. HTTP 포트인 80번 포트를 인바운드 규칙에 추가하지 않으면 브라우저에서 접속 자체가 차단됩니다. 이 부분은 처음 할 때 왜 안 되는지 한참 헤맸습니다. 제 경험상 이건 좀 다릅니다, 보안 그룹 설정은 단순히 넘어갈 부분이 아니라 배포 단계에서 반드시 점검해야 할 항목입니다.
S3 버킷 설정도 처음에는 헷갈렸습니다. CloudFront를 함께 쓸 경우와 그렇지 않을 경우 설정 방향이 달라지기 때문입니다. S3 단독으로 쓴다면 퍼블릭 액세스를 차단 해제하고 정적 웹 사이트 호스팅을 활성화해야 하지만, CloudFront와 함께 쓴다면 오히려 퍼블릭 액세스를 차단하고 호스팅 설정도 비활성화하는 것이 맞습니다. 저는 처음에 이 구분을 몰라서 설정을 두 번 뒤집었습니다.
CloudFront와 ACM으로 HTTPS 도메인 연결하기
CloudFront를 설정할 때 한 가지 꼭 주의해야 할 부분이 있습니다. WAF(Web Application Firewall), 즉 웹 애플리케이션 방화벽은 활성화하면 별도 요금이 청구됩니다. 여기서 WAF란 SQL 인젝션이나 XSS 같은 웹 공격을 애플리케이션 레이어에서 필터링해주는 보안 서비스인데, 기능은 유용하지만 비용이 발생하므로 프리티어 환경에서는 반드시 비활성화해야 합니다. 제가 직접 체크하면서 이 항목을 놓칠 뻔했는데, AWS 과금 구조가 익숙하지 않은 분들은 특히 주의가 필요합니다.
오류 페이지 설정도 빠뜨리기 쉬운 부분입니다. Vue나 React 같은 SPA(Single Page Application) 구조에서는 라우팅이 클라이언트 사이드에서 처리됩니다. 여기서 CSR(Client Side Rendering)이란 서버가 최초에 기본 HTML과 JavaScript만 보내고, 이후 모든 페이지 구성과 데이터 처리는 브라우저에서 JavaScript를 실행해 처리하는 방식입니다. 이 구조에서 /member/login처럼 특정 경로로 직접 접속하면 CloudFront가 해당 파일을 찾지 못해 403이나 404 오류를 반환합니다. 이를 해결하려면 오류 응답 설정에서 403과 404 모두 응답 페이지를 /index.html로 지정하고 HTTP 응답 코드를 200으로 설정해야 합니다.
HTTPS를 적용하려면 ACM(AWS Certificate Manager)에서 인증서를 발급받아야 합니다. ACM은 SSL/TLS 인증서를 무료로 발급하고 관리해주는 서비스입니다. 단, CloudFront에서 인증서를 사용하려면 반드시 리전을 버지니아 북부(us-east-1)로 설정해야 합니다. CloudFront가 글로벌 서비스이기 때문에 특정 리전 인증서를 인식하지 못하고, 전 세계 서비스를 관장하는 본사 리전에서 발급된 인증서만 연동할 수 있는 구조입니다. 서울로 설정해서 발급받으면 CloudFront 배포 설정에서 아예 인증서 목록에 뜨지 않습니다. 저도 이 부분 때문에 한 번 처음부터 다시 발급받은 적이 있습니다.
도메인 연결은 CNAME 레코드를 이용합니다. CNAME이란 특정 도메인 이름을 다른 도메인 이름으로 매핑해주는 DNS 레코드 유형입니다. 내도메인.한국 같은 무료 도메인 서비스에서 www에 해당하는 CNAME 값을 CloudFront 배포 도메인 이름(예: d3jb****.cloudfront.net)으로 설정해주면, www.내도메인 으로 접속했을 때 CloudFront를 거쳐 S3의 파일을 받아가는 전체 흐름이 완성됩니다. AWS 공식 문서에 따르면 CloudFront는 현재 전 세계 600개 이상의 엣지 로케이션을 운영하고 있어, 지리적으로 분산된 사용자에게도 빠른 응답 속도를 제공합니다(출처: AWS 공식 문서).
백엔드가 아직 준비되지 않은 상황에서 EC2에 nginx를 설치하고 /var/www/html/api 경로 아래에 JSON 파일을 만들어두는 방법도 써봤습니다. 이 방식은 실제 백엔드 서버가 아니라, 프론트엔드가 API 요청을 보냈을 때 미리 작성해둔 JSON 형태의 응답만 돌려주는 구조입니다. 일반적으로 nginx는 정적 파일을 제공하는 웹 서버 용도로 주로 쓰이고 백엔드 서버로 보기는 어렵지만, 실습 환경에서 스프링 같은 실제 백엔드 서버가 없을 때 임시방편으로 활용하기에는 충분했습니다. AWS Well-Architected Framework 문서에서도 마이크로서비스 아키텍처를 구성할 때 각 컴포넌트의 역할을 분리하는 것을 권장하고 있는 만큼, 이번 실습에서 nginx, S3, CloudFront의 역할을 구분하며 설정한 경험이 앞으로의 구조 설계에 도움이 될 것 같습니다(출처: AWS Well-Architected Framework).
전체 흐름을 정리하면 다음과 같습니다.
- S3에 빌드 파일(dist 폴더 내 파일) 업로드 후 버킷 정책 설정
- CloudFront 배포 생성, 원본을 S3로 지정, WAF 비활성화, 오류 페이지 설정
- ACM에서 버지니아 북부 리전으로 인증서 발급
- CloudFront에 인증서와 대체 도메인 추가
- DNS 서비스에서 CNAME 레코드 설정
파일을 다시 배포할 때 CloudFront 캐시 문제가 생기면 무효화(Invalidation) 기능에서 /index.html을 추가해주면 됩니다. 단, 이건 배포 중에만 쓰고 안정화되면 지우는 게 맞습니다. 무효화란 CloudFront가 전 세계 엣지 서버에 저장해둔 캐시를 강제로 삭제하고 원본 파일을 다시 가져오도록 명령하는 기능인데, CDN의 장점인 캐싱을 역으로 끄는 것이기 때문에 상시 적용해두는 건 좋지 않습니다.
이번 배포 과정을 전체적으로 경험해보니, AWS의 각 서비스는 독립적으로 설명하면 단순해 보여도 실제로 연결할 때는 생각보다 꼼꼼하게 챙겨야 할 설정들이 많았습니다. WAF 비용, 리전 선택, 보안 그룹, 오류 페이지 처리까지 하나라도 놓치면 접속이 안 되거나 요금이 청구되는 상황이 생깁니다. 처음 배포를 시도하는 분이라면 설정 하나하나를 단계별로 확인하면서 진행하는 것이 결과적으로 훨씬 빠릅니다.