안녕하세요 피플에서 백엔드를 맡고 있는 고지훈입니다.
대학생분들이 모여서 운영하다보니 항상 금전적인 측면에서 힘든 상황을 겪고 있습니다.
그나마 여러분들의 성원과 도움으로 만들어진 AWS 크레딧과 후원금으로 운영되고 있습니다.
하지만 이또한 지속가능하다고 하기엔 불확실성이 짙기 때문에 서비스 운영에 들어가는 비용 자체를 줄일 필요성을 많이 느끼게 된것같아요
그중에 운영비용 중 AWS 서버비가 가장 많은 금액을 차지했었습니다.
피플을 사용하신 분들 중 공지사항을 한번이라도 보셨다면 저희 서버비용이 상당히 많이 나오는데요
비용 최적화 이전 평균 370~380달러 정도로 지출되고 있었습니다.
원화로 480,000원 정도로 매우 부담스러운 금액이었습니다.
저희 서비스는 AWS에서 운영되며 실제 운영서버는 다음의 서비스들로 구성되어 있었습니다.
ECS Fargate와 ELB를 통해서 고가용성을 보장해주었고
NAT Gateway로 보안성을 높였습니다.
이러한 구성으로 운영환경에는 총 150~200 달러가 지출되고 있었습니다.
하지만 가장 큰 문제는 개발에 활용하게되는 개발서버들이었습니다.
크레딧이 있고 시간이 없다는 이유로 Elastic Beanstalk, Amplify 등을 막 생성하다보니
개발환경에 들어가는 돈이 운영환경보다 더 많아져버리는 배보다 배꼽이 더 큰상황이 와버린거죠
이를 해결하기 위해
AWS 서비스 중 저렴하고 금액이 일정하게 발생하는 서비스를 찾고 있던 도중
Lightsail이라는 서비스를 발견하게 됩니다.
아마존 Lightsail은 AWS에서 만든 가상 프라이빗 서버로
프로젝트를 빠르게 시작하는 데 필요한 가상머신, 스토리지, Networking, 로드밸런서, DNS, 고정IP, OS 등 모두 포함하고 있어 웹서비스를 빠르고 쉽게 구축하는데 특화되어 있는 서비스 입니다.
즉 EC2와 비슷하지만 애플리케이션에 대한 구성을 빠르게 할 수 있고 금액또한 제일 저렴한 모델로 1달 고정 3.5달러에 구성할 수 있는 매우 저렴한 이용할 수 있는 서비스입니다.
사이드 프로젝트나 개발 환경을 구성할 때 둘도 없는 서비스라고 볼 수 있습니다.
자 일단 어떤 서비스를 이용할지는 정해졌습니다.
이제 뿔뿔이 흩어져 있는 서버들을 Lightsail로 옮겨야 합니다.
저는 이를 위하여 Nginx와 Docker를 사용하기로 했습니다.
Nginx는 적은 자원을 갖고 고성능, 고가용성을 자랑하는 웹 서버 소프트웨어 입니다.
리버스 프록시, 로드밸런서, 캐싱, SSL등 여러 기능을 최소한의 자원을 사용하기 때문에 현재 가장 사랑받는 웹 서버 중 하나 입니다.
저희는 여러 서버를 하나로 옮기기 위하여 Nginx의 리버스 프록시 기능과 SSL을 사용하기로 결정했습니다.
오늘날의 복잡한 웹 환경에서 리버스 프록시는 중요한 역할을 합니다. 이 기술은 웹 서비스의 성능, 보안, 그리고 확장성을 크게 향상시킬 수 있는 도구로 널리 사용되고 있습니다. 이 글에서는 리버스 프록시가 무엇인지, 어떻게 작동하는지, 그리고 왜 중요한지에 대해 살펴보겠습니다.
리버스 프록시는 클라이언트와 서버 사이에서 요청과 응답을 중계하는 역할을 하는 서버입니다. 클라이언트가 서버에 직접 요청을 보내는 대신, 리버스 프록시 서버를 통해 요청이 전달됩니다. 이는 일반적인 프록시 서버와 반대 방향으로 작동하며, 여러 가지 이유로 매우 유용합니다.
클라이언트가 웹 페이지나 서비스에 접속을 시도할 때, 리버스 프록시 서버가 이 요청을 받아 실제 서버로 전달합니다. 그 후 서버의 응답을 다시 클라이언트에게 전달합니다. 이 과정에서 리버스 프록시는 요청을 조절하고, 필요한 보안 조치를 취하며, 캐싱 정책에 따라 콘텐츠를 저장합니다.
물론 리버시 프록시는 여러대의 서비스를 한 웹서버내에서 컨트롤 할 수 있다는 점에 대해서 MSA 아키텍처에서 많이 사용되는 기술입니다.
하지만 저희는 개발 서버의 단일화를 위한 작업이기 때문에 리버스 프록시와 함께 쓸 기술로 도커를 선정하였습니다.
도커란 컨테이너 가상화 기술을 사용하여 응용프로그램을 더 쉽게 배포, 실행 할 수 있도록 설계된 툴이며 컨테이너 기반의 기술 및 오픈소스라는 특징을 갖고있습니다.
서버에서의 컨테이너 기술은 자신이 필요한 프로그램 혹은 실행환경 등 여러 리소스들을 한곳에 모아놓고 관리 할 수 있습니다.
VM(Virtual Machine) 보다 경량화 되고 Docker Engin을 통해 커널 등 컴퓨터 리소스를 공유하기 때문에 서버 하나에 자원을 공유하기 때문에 어플리케이션 배포에 있어서는 거의 표준이 된 기술이라고 할 수 있습니다.
물론 배포가 끝이 아니기 때문에 이 컨테이너를 관리하기 위해선 k8s,Docker Swarm 등 추가적인 라이브러리, 프레임워크를 조합하여 사용하여야 하지만
저희는 개발 환경을 구성하는 것이기 때문에 오버엔지니어링 이라는 판단하에 멀티 컨테이너를 구성하기 위해 가장 간단한 Docker-Compose를 사용하였습니다.
Docker Compose는 여러 컨테이너로 구성된 애플리케이션을 정의하고 실행하기 위한 도구입니다. 하나의 YAML 파일(docker-compose.yml)을 사용하여 서비스, 네트워크, 볼륨과 같은 애플리케이션의 모든 컴포넌트를 구성할 수 있습니다.
version: '3.8' # Docker Compose 파일 버전
services:
api-server:
container_name: api-server # 컨테이너 이름 설정
build: # 빌드 설정
context: ./pple-api # 빌드 컨텍스트(도커 파일 위치)
image: api-server # 생성될 이미지 이름
restart: unless-stopped # 컨테이너가 정지되지 않는 한 재시작
env_file: # 환경 변수 파일 지정
- ./pple-api/.env
redis-master:
container_name: redis-master # 컨테이너 이름 설정
image: 'emibgo/redis' # 사용할 이미지
ports: # 포트 매핑
- '6379:6379' # 호스트의 6379 포트를 컨테이너의 6379 포트에 연결
admin:
container_name: admin # 컨테이너 이름 설정
build: ./pple-admin2 # 빌드 경로
image: admin # 생성될 이미지 이름
restart: unless-stopped # 컨테이너가 정지되지 않는 한 재시작
pple-web:
container_name: pple-web # 컨테이너 이름 설정
build: ./pple-main-web-v2 # 빌드 경로
image: pple-web # 생성될 이미지 이름
restart: unless-stopped # 컨테이너가 정지되지 않는 한 재시작
networks:
default:
external:
name: nginx_default # 외부 네트워크에 연결, nginx_default 네트워크 사용
저희 개발환경에서 돌아갈 service 들을 docker-compose.yml 파일에 작성해줍니다.
docker-compose.yml에 있는 컨테이너들은 컨테이너의 이름에 따라 서로 통신이 가능하게 되며 docker network를 추가로 생성하고
newtorks external을 통해서 연결시켜 주면 다른 yml에 적혀있는 컨테이너와도 통신이 가능하게 됩니다.
이를 통하여 nginx 등 기반이 되는 몇몇 애플리케이션과 직접 개발하는 애플리케이션을 분리 시켜 관리의 용이성 또한 증대 시킬 수 있습니다.
이후 nginx.conf 파일을 수정 해줍니다.
http {
server {
listen 80;
location /api/ {
proxy_pass http://api-server:8080; # api-server 서비스의 포트
}
location /admin/ {
proxy_pass http://admin:3000; # admin 서비스의 포트
}
location / {
proxy_pass http://pple-web:3000; # pple-web 서비스의 포트
}
}
}
이런식으로 설정해주게 되면 서브 도메인으로 api가 요청으로 들어오면 api 컨테이너에 요청이 가도록 구성할 수 있습니다.
※ Docker에서 각 컨테이너는 독립된 네트워크 네임스페이스를 가지고 있습니다. 이는 각 컨테이너가 마치 별도의 물리적 호스트인 것처럼 자신만의 IP 주소, 포트, 네트워크 스택을 가질 수 있음을 의미합니다. 따라서, 서로 다른 컨테이너는 동일한 포트 번호(예: 80, 8080)를 사용해도 서로 간섭하지 않습니다.
이렇게 해서 저희는 nginx & docker-compose로 개발환경을 구축해서 Lightsail에 배포하였는데요
이를 통해서 기존의 400$ 정도 나가던 AWS 비용을
50~60% 절감하여 200$ 정도로 축소 시킬 수 있었습니다.
운영 환경에 대한 최소 비용을 180~90$ 잡고 있었기 때문에
운영 환경의 5~10%에 해당하는 비용만으로도 개발환경을 구성할 수 있게 되었습니다.
간혹 백엔드 개발자 분들 중 개발까지만을 본인의 역할로 치부하고 배포 및 AWS 관리에 대해서는 소홀히 하는 경우가 있는데요 (과거의 본인 포함..)
인프라 구성을 어떻게 하는지에 따라 큰 금액차가 나는 만큼 인프라에 대한 학습도 빠지지 않고 하시는것을 권장드립니다.
저도 이번에 비용 최적화를 하면서 본인의 예산,구성해야할 환경에 따라 알맞는 아키텍처로 구상하는지에 따라 비용이 천차 만별이라는 것을 느낀 계기가 된것 같습니다.
2024년 새해가 밝았는데 모두 새해복 많이 받으시고 즐거운 한해 보내시길 바라겠습니다!
감사합니다! 😊