AWS 기반 백앤드 구축

모바일 서비스의 백앤드 개발을 위해 AWS가 제공하는 다양한 서비스를 이용한 인프라 구축 경험을 공유합니다

Kim, min tae
ibare story
Published in
14 min readDec 18, 2013

--

팀 구성, 그리고 개발 시작

약 5개월 전 최소한의 구성원(5명)으로 조직된 서비스 개발팀은 개발할 서비스의 컨셉을 확정하고 본격적인 개발을 진행했습니다. 팀의 목표는 명확했습니다. 애자일과 프로토타이핑 개발 방식을 기반으로 단기간에 MVP를 구현하는 것이었습니다. 2주 이터레이션 주기마다 실행되는 결과물이 나와야했고 개발된 기능은 다음 이터레이션에 완전히 다른 형태가 될 수도 있었습니다.

한 명의 개발자가 백앤드와 웹 프론트앤드 모두를 개발해야하는 상황에서 이런 조건을 충족시킬 수 있는 방법이 필요했고 웹과 백앤드 모두 같은 언어인 Javascript로 빠르게 개발할 수 있는 NodeJS와 인기있는 NoSQL DB 솔루션인 MongoDB 를 선택했습니다.

최소한의 자원으로 빠르고 다양한 실험을 위해 불필요한 시간낭비를 줄이는 방법이 필요했습니다. 예를 들면 서버를 세팅하고, 패키지를 설치하는 등의 일 말이죠. 조직 규모가 일정 수준 이상의 기업이라면 내부 인프라를 할당받고 사용하는 일도 개발자에게는 꽤나 고단한 일이 될 수 있습니다.

그래서 개발 단계에서 사용할 적절한 PaaS 서비스를 찾았고, Ruby on Rails 를 시작으로 Node 등 많은 플랫폼을 지원하는 Heroku 를 선택했습니다.

http://www.heroku.com

Heroku는 계정을 만들고 Heroku Toolbelt 을 설치하면 즉시 무료 프로젝트를 구성하고 사용할 수 있습니다. 최소한의 무료 인스턴스만 사용한다면 돈 한푼 쓰지 않고도 충분한 프로토타이핑 환경을 제공합니다.

Getting Started with Heroku

간단한 Node 앱을 만들고 Heroku Toolbelt 설치후 터미널에서 다음과 같은 명령 만으로 순식간에 앱이 배포됩니다.

(~/myapp) $ heroku create my-first-app

이렇게 만들어진 앱은 http://my-first-app.herokuapp.com 으로 접근할 수 있습니다. 무료 MongoDB 데이타베이스가 필요하다면 다음과 같이 입력합니다.

(~/myapp) $ heroku addons:add mongolab

즉시 MongoDB 를 연결하여 사용할 수 있게됩니다. Heroku 가 제공하는 수 많은 에드온들은 다음의 링크에서 확인해 볼 수 있습니다. 거의 대부분의 에드온들이 최소 자원의 무료 플랜을 지원합니다. 개발 단계에서 어지간한 규모의 프로젝트라면 충분히 활용해서 테스트 해볼 수 있고, 개발 시간을 단축할 수 있습니다.

https://addons.heroku.com

저희 팀에선 최종적으로 AWS 에 인프라를 구성하기 전인 프로젝트 막바지까지 Heroku 를 사용했습니다. Close BETA 서비스를 위해 제한된 사용자에게 오픈했을 때도 beta1.herokuapp.com, beta2.herokuapp.com, dev.herokuapp.com 등으로 세분화하여 배포판을 유지했습니다. 모두 무료로 말이지요.

Heroku 사용시 주의사항

  1. PaaS 서비스는 앱이 배포될 때 배포판의 스냅샷 이미지를 생성합니다. 이는 마치 읽기 전용의 CD를 굽는 것과 유사합니다. 즉, Heroku 앱은 파일을 쓸 수 없다는 얘기입니다. 파일 업로드 등을 구현하여 배포했을 경우 파일 시스템에 Write 할 때 오류가 발생합니다. 이를 해결하기 위해 클라우드 저장소를 활용하는 방법이 필요합니다. 예를 들면 AWS 의 S3나 Dropbox 등과 연동시키는 부가작업이 필요할 수 도 있습니다. 테스트 목적이라면 연동이 손쉽고 적당한 무료 용량을 제공하는 S3 사용을 추천합니다.
  2. 서버에서 무언가 필요한 리소스가 있을 때 (예를 들면 한글 폰트) 특별한 작업이 필요합니다. 저희가 개발하는 프로젝트에서는 웹사이트의 스크린샷을 생성하여 저장하는 모듈이 있는데 Heroku 에서 실행할 경우 한글 폰트가 없어 한글이 랜더링되지 못하는 현상이 발생했습니다. 이 경우 Heroku는 BuildPack 을 추가로 지정하여 해결할 수 있는데 다음의 링크를 참조하세요.
    https://github.com/nanha/heroku-buildpack-nodejs-phantomjs

AWS 인프라 구축 계획

위 그림은 일반적으로 서비스를 아마존에 구축하게될 때 기본적으로 참조할 수 있는 구성입니다. AWS는 실제 200여개가 넘는 서비스를 제공하고 있어 매우 복잡해 보일 수 있으나 최소한의 필요한 형태로 구성한 후 상황에 따라 하나씩 확장해 나가면 비교적 손 쉽게 인프라를 구축할 수 있습니다.

저희 팀에서 사용하는 AWS 서비스는 다음과 같습니다.

  1. EC2 (가상 머신 서비스)
  2. Elastic Load Balancing (트래픽 분산 서비스)
  3. Auto Scaling
  4. Route 53 (DNS 서비스)
  5. S3 (클라우드 스토리지 서비스)

계획

B2C 서비스가 대부분 같은 문제를 지니고 있습니다. 서비스 사용자의 증가가 어떤 패턴으로 늘어날지 전혀 예측할 수 없다는 것입니다. 그리고 예상을 넘어서 과도한 트래픽이 집중되면 환호는 잠시 뿐, 서버의 응답은 하염없이 늦어질 수 있습니다. 서비스 초기 응답 품질 문제는 서비스가 성장할 수 있는데 결정적인 장애요소이기도 합니다. 따라서 다음의 목표는 최소 필요 조건이 됩니다.

  1. 서비스 시작은 최소의 자원으로
  2. 트래픽이 증가하면 자동으로 서버 확장

이 두 가지 목표는 AWS 가 제공하는 ELB와 Auto Scaling 서비스로 아주 간단하게 해결할 수 있습니다.

EC2

AWS의 계정을 생성한 후 아마도 제일 처음 하는 일은 EC2 인스턴스를 생성하는 일일 것입니다. 많은 인스턴스 타입이 있지만 t1.micro 타입은 한달간 무료로 사용해 볼 수 있기 때문에 즉시 생성하여 여러가지 테스트를 해볼 수 있습니다.

EC2 인스턴스도 다른 서비스와 마찮가지로 손쉽게 생성하고 삭제할 수 있습니다만 인스턴스의 종류와 Zone 의 위치 그리고 시간당 비용이 청구되기 때문에 다른 서비스와 달리 생성에 신중을 기해야합니다. 비용 관련해서 아래 awsnow.info 사이트에서 비교적 간단히 참조해볼 수 있습니다.

http://www.awsnow.info/

아래 그림을 통해 전체 구성중 EC2 인스턴스가 금액적으로 차지하는 비중이 압도적으로 크다는 것을 알 수 있습니다. (이는 서비스의 특성에 따라 차이가 클 수도 있습니다.)

EC2 인스턴스 생성시 가장 중요한 포인트는 어떤 운영 플랫폼을 선택하는가 일 것입니다. 흔히 알고 있는 Linux 계열, Amazon Linux, Windows 등을 기본으로 다양한 소프트웨어가 이미 설치되어 세팅까지 되어있는 이미지들 중에 선택하여 EC2 인스턴스를 만들수 있습니다. Amazon Linux 는 AWS 서비스를 구성하는데 있어 필요한 다양한 도구들이 비교적 잘 정리되어 설치되어 있는 AMI 입니다. 구성 요구사항에서 운영체제 환경이 크리티컬하지 않다면 Amazon Linux AMI 선택은 환결 설정의 스트레스에서 조금이나마 벗어날 수 있게 해 주는 것 같습니다. 저희는 MongoDB 인스턴스들이 Amazon Linux 로 구성되어 있습니다.

인스턴스 생성시 생각하고있어야하는 것은 AMI라는 인스턴스 이미지와 CPU, RAM 등 서버의 자원 크기를 결정하는 t1.micro, m1.small, m1.large 등의 인스턴스 타입은 분리되어있다는 것입니다. [1]생성된 EC2 인스턴스의 인스턴스 타입을 변경하지는 못합니다. 대신 동일한 AMI 를 기반으로 원하는 인스턴스 타입으로 인스턴스를 새로 생성할 수 있습니다. 여기서 중요한 점은 실행중인 인스턴스를 사용자 AMI 로 만들어 놓는다는 것입니다.

[1] #수정 인스턴스의 실행을 Stop 시킨 후 인스턴스 타입을 변경할 수 있습니다. EBS-optimized 옵션 지정과 함께 수정 가능하네요.

사용자의 EC2 인스턴스를 AMI 로 만들기

설정이 끝난 인스턴스를 사용자 AMI 로 만들어 놓으면 향후 Scale Up (인스턴스 타입 변경)을 하거나 Auto Scaling 할 때의 확장 단위로 활용할 수 있는 등 여러모로 편리하고 필수적인 요소입니다. 초기에는 가격이 저렴한 t1.micro 인스턴스에서 작업 후 실제 운영할 땐 만들어 놓은 AMI 를 기반으로 적절한 인스턴스 타입을 선택하시면 됩니다.

Elastic IP

인스턴스가 생성되면 Public IP 와 Private IP 가 할당됩니다. Public IP 는 AWS 외부에서 해당 인스턴스로 접속하기 위한 용도이고 Private IP 는 AWS 서브넷 안쪽에서 통신하기위한 사설 IP 입니다. 인스턴스가 켜져있는 동안 특별한 경우를 제외하면 IP 가 변경되지는 않습니다. 하지만 인스턴스가 리부팅 되면 동일한 IP 를 보장받지 못합니다. 터미널로만 접속하는 서버라면 문제 없겠지만 동일한 IP 를 유지해야하는 서버라면 변경되지 않는 고정 IP 가 필요합니다. 예를 들면 DB 서버 같은 경우겠죠. 이런 서버는 Elastic IP 를 생성하여 할당해 주시면 됩니다. Elastic IP 도 비용이 청구되기 때문에 꼭 필요한 서버에만 할당하는 것이 좋습니다.

그 외에 AWS의 다른 서비스와 연동은 실제 IP 가 아닌 Instance ID로 이루어지기 때문에 IP 가 변경된다해도 연결을 보장합니다.

ELB (Elastic Load Balancing)

ELB는 클라이언트의 트래픽을 여러대의 서버로 분산시키는 기능을 제공하는 서비스입니다. L4 스위치와 유사한 기능을 제공하는 서비스입니다. ELB는 AWS Console(Web GUI) 의 좌측 메뉴에 존재합니다.

ELB에 트래픽을 분산시킬 타겟 인스턴스를 포함시킬 수 있습니다. 포함된 인스턴스 중 Health Check 하여 서비스 가능한 인스턴스를 대상으로 요청을 전달합니다. 타겟 인스턴스는 여러대의 분리된 인스턴스가 될 수 도 있고, 단일 인스턴스 내에 서로 다른 TCP PORT로 실행중인 서비스일 수 있습니다.

트래픽의 정도에 따라 자동으로 인스턴스의 수를 증감하는 Auto Scaling 은 ELB가 제공하는 기능이 아닙니다. 서비스 구조상 ELB에 옵션으로 Auto Scaling 이 포함되어 있다면 훨씬 직관적이고 편리하겠다고 생각할 수 도 있으나 실제 Auto Scaling 은 별개의 서비스로 제공되며 Inbound 트래픽 소스로 ELB 를 통하여 제공받을 수 있는 옵션을 제공합니다.

Route 53

서비스 진입의 첫 단추는 DNS 일 것입니다. AWS 에서는 Route 53 이라는 DNS 서비스를 제공합니다. 다른 DNS 서비스를 사용해도 문제될 것은 없지만 Route 53 을 사용한다면 AWS 의 다른 서비스와 유기적으로 손쉽게 연결할 수 있습니다. 네임 서버 설정 후 20여분이 되지 않아 해당 도메인에 연결되는 것을 확인했을 땐 조금 놀라기도 했습니다. 보통 짧게는 6시간에서 24시간 넘게 걸리는 경우도 자주 봤었기 때문입니다.

서비스할 DNS 를 생성한 후 Hosted Zone Details

서비스의 도메인을 Route 53 콘솔에서 등록하면 위 그림과 같은 Hosted Zone Details 을 보실 수 있습니다. Delegation Set 의 4개 주소를 구입한 도메인 서비스의 네임서버에 각각 등록하면 간단히 처리됩니다.

서비스할 도메인이 설정되면 호스트별로 A 레코드를 생성해야합니다. A 레코드는 특정 EC2 에 직접 연결시킬 수 도 있으나 이런 경우 고정 IP 가 필요하기 때문에 ELB 를 중간 브리지로 구성하면 쉽게 연결시킬 수 있는 등 많은 장점이 있습니다.

sentry.foo.com A 레코드가 sentryLB 라는 이름의 EBL에 연결시킨 모습

Auto Scaling

서버의 상황에 따라 다양한 조건의 룰을 세팅하여 해당 조건이 충족되면 인스턴스의 수를 증가시키거나 감소시키는 것을 가능하게 해 주는 서비스입니다. Auto Scaling 은 얼마 전까진 AWS CLI 라는 커맨드라인 도구로만 설정이 가능했으나 이제 웹 콘솔에서도 다른 서비스와 마찮가지로 간단하게 설정하고 구성할 수 있습니다.

Auto Scaling 구성을 하기 위해선 먼저 준비해야하는 것이 있습니다. 앞서 잠깐 언급했던 사용자 AMI 입니다. Auto Scaling 해야할 대상이 API 서버라면 부팅과 동시에 API 서버가 동작하기위한 모든 구성이 완료된 AMI 를 만들어 놓아야 합니다. 이 AMI 를 기반으로 다음 두 가지 단계를 거쳐 Auto Scaling 구성을 할 수 있습니다.

  1. Auto scaling Launch Configurations
    사용자 AMI 를 어떤 인스턴스 타입으로 생성할지에 대한 구성 정보를 담고있습니다. Auto Scaling 그룹을 만들게 될 때의 상위 구성 정보입니다.
  2. Auto scaling groups
    구성하고자 하는 Launch Configrations 을 선택한 후 Scaling Group 명, 최소 인스턴스 수, 최대 인스턴스 수, 증감 조건 등을 설정합니다. 요청을 수신할 ELB를 지정할 수 도 있습니다. 설정이 완료되면 조건에 맞는 EC2 인스턴스가 생성됩니다. 증감 인스턴스의 정수와 % 로 지정할 수 있습니다.
    인스턴스의 증감 룰을 결정하는 변수는 몇 가지가 있습니다. 아래 그림을 참고하세요. “해당 조건이 몇 분간 지속되면 인스턴스를 2개 증가시키고, 해당 조건이 몇 분간 지속되면 1개 감소시킴” 과 같이 설정합니다.

남은 일, 그리고 계획

남아있는 일이 아주 많이 있습니다. 서비스가 아직 정식으로 오픈하지 않았기 때문에 이 구성상에서 어떤 예상치 못한 일이 발생할지 감이 잘 안오고, 선택한 인스턴스 타입은 적절한지도 아직 판단이 잘 서지 않습니다. 다만 앞으로 할 일들을 최대한 예측해보고 필요한 시스템을 구축해 나가야겠지요.

참고로 저는 프론트앤드 기반의 개발자입니다. 그래서 더 힘들게 느껴지는지도 모르겠습니다. :-)

To do list

  1. Log Monitoring
    API 서버, Web 서버, Push 서버 등 이것 저것 많은 서비스가 있기 때문에 통합적으로 로그를 모니터링할 필요가 있습니다. 매번 터미널에 들어가 볼 수 없기 때문이죠. 현재는 Sentry 로 구축을 해 놓았는데 굉장히 느리네요. 무언가 문제가 있는듯 하여 튜닝이 필요한 것 같습니다.
  2. Redis
    현재 서비스가 소셜을 기반으로 하고 있기 때문에 사용자의 활동 로그가 매우 많이 쌓입니다. 이 로그를 빠르게 저장할 솔루션으로 Redis 를 생각하고 있는데 AWS 에선 ElastiCache 서비스가 이것을 제공합니다.
  3. Deploy
    Auto Scaling Group 으로 배포되는 API 서버는 PaaS 서비스와 마찮가지로 한번 배포되면 내용 변경을 할 수 없습니다. (할 수 는 있지만 영구적이지 않지요) 운영중인 배포판과 개발중인 배포판사이의 빠른 전환, 그리고 문제 발생시 빠르게 롤백할 수 있는 Deploy Workflow 를 고민중에 있습니다. 여러가지 모델이 있어서 가장 효과적인 것을 선택해야할 것 같습니다.
  4. MongoDB Shared 구축
    현재는 기본적인 Replica set 으로 되어있습니다. 서비스가 많이 성공한다면 Shared 구축을 해야겠지요. 이 작업은 서비스가 흥했다는 거니까 기분좋은 작업이 될 것 같습니다. ^^

에필로그

서비스 오픈전에 잠시 짬이나 그동안 했던 작업들을 개인적으로 정리할 겸 오랜만에 긴 글을 작성해봤습니다. 사실 기초적인 내용들이고 검색하면 모두 나오는 내용입니다만 처음 해보시는 분들에겐 한번에 파편화되지 않은 글이 도움이 될까하여 공유해봅니다.

“프론트앤드 개발자의 백앤드 구축 삽질담” 정도로 가볍게 읽어주시고, 혹시 제가 잘못 생각하고 있거나 이해하고 있는 내용은 언제든 피드백 주시면 감사드리겠습니다.

--

--