Azure Cloud로 은는이가 서버 개발하기

은는이가의 서버는 구름 속에 산다. 사용자 데이터와 다양한 프로세스는 우리가 소유하는 기계에서 돌아가는 것이 아니라 클라우드로 돌아간다. 클라우드 컴퓨팅(Cloud Computing)이란 나의 컴퓨터가 아니라 인터넷으로 연결된 다른 컴퓨터로 작업을 처리하는 것을 뜻한다. 일종의 컴퓨터 렌털 혹은 구독 서비스라고 할 수 있다. 덕분에 직접 비싼 장비를 사지 않아도 됐고, 손쉽게 한국과 미국 사용자들에서 안정적인 서비스를 제공할 수 있었다.

이미지 출처: networkencyclopedia.com

왜 굳이 빌려서 쓰는 걸까? 제일 큰 장점은 클라우드의 유연성이다. 소프트웨어 비스는 사용도가 급격하게 바뀌기 마련인데 이에 맞춰 언제든지 기계를 바꿔 쓸 수 있다. 사용자가 백 명에서 만 명으로 늘거나, 지구 반대편에서 서비스를 론칭하거나, 컴퓨팅 파워가 많이 필요한 머신러닝을 도입하거나-그때 상황에 맞는 기계를 빌리면 된다. 또 클라우드는 저렴하고 직접 유지보수 작업을 안 해도 된다. 스타트업이라면 특히 자금도 인력도 부족하기 때문에 손쉽게 빌리는 것을 선호한다. 집과 비교해보자. 만약에 내가 20대 사회초년생이고 아이가 계속 늘어나는 상황이라면 매매보다 월세를 택하는 게 현명하다.

은는이가는 올해 2월에 본격적으로 개발에 들어갔다. 이번 달 베타 테스팅을 끝낸 기념으로 은는이가가 어떻게 클라우드를 활용했는지 기록해보려 한다. 은는이가는 Microsoft가 운영하는 Azure Cloud를 사용했고, 총 5가지 서비스(App Service, SQL Database, Functions, Application Insights, Keyvault)를 활용했다.

1. Azure App Service

은는이가 서버는 HTTP 형식의 API 요청에 응답하는 Web Application이다. 이 웹앱을 Azure App Service에 호스트를 하면 프런트엔드가 손쉽게 요청을 할 수 있게 된다. 개발을 할 때에는 공짜로 쓸 수 있는 F1 인스턴스를 사용하였고, 베타 테스팅의 경우에만 한 달에 $51의 S1 인스턴스로 업그레이드하였다. 사용하는 인스턴스에 여러 앱을 호스트 할 수 있어서, Production과 Dev버전의 웹앱을 똑같은 인스턴스를 사용해 비용을 절감할 수 있었다.

App Service가 제공하는 다양한 인스턴스

Azure App Service의 많은 기능들 중에 내가 좋아하는 기능은 Staging slot deployment이다. 새로운 코드를 클라우드에 디플로이를 하면 이미 돌아가고 있는 웹앱이 멈췄다 다시 켜져야 한다. 이 같은 콜드 스타트가 있을 경우 짧은 시간 동안 모든 요청에 503 에러가 난다. Staging slot은 이 downtime 문제를 방지할 수 있다. 트래픽을 받고 있는 웹앱에 바로 디플로이 하는 것이 아니라 staging slot에 디플로이를 한 후, 성공적으로 앱이 시작했을 경우 슬롯을 스왑 시켜 새로운 웹앱에 트래픽이 가게 하는 것이다.

2. Azure SQL Database

은는이가 데이터는 Azure SQL Database으로 관리한다. 처음에는 경험이 없는 Document DB를 도전해보고 싶어서 Azure Cosmos DB으로 시작하였는데 가격이 감당이 안 됐다. 각 Table마다 월 $16를 내야 하는데, 처음에는 2개였던 Table이 나중에 기능이 서서히 추가돼 하나씩 늘어나기 시작했다. 할 수 없이 Table 개수와는 상관없이 전체 퍼포먼스로 가격을 책정하는 Azure SQL로 바꾸었다. 앱의 Data layer를 다 뜯어고쳐야 하는 큰 공사였다. Azure Table Storage라는 서비스를 사용할까 고민도 했었는데, 다큐멘테이션을 훑어보니 금방 deprecate 될 것 같다는 쎄-한 느낌이 와서 바로 노선을 바꾸었다.

Azure SQL로 바꾸고 나서 체한 게 내려간 듯이 개발이 편해졌다. Relational Database라 서로 연관이 되어있는 데이터를 쉽게 로딩할 수 있었다. 나의 주 전공이 아닌 SQL query를 매번 써야 돼서 귀찮을까 했는데, Entity Framework Core이라는 라이브러리를 통해 object oriented 방식으로 코드를 짤 수 있어서 간편했다. Dotnet Core — EF Core — Azure SQL. 정말 추천하는 조합이다.

은는이가의 SQL Database. 테이블이 처음보다 훨씬 많아졌다.

3. Azure Functions

프런트엔드는 어플 사용자의 요청만 전달한다. 은는이가 서비스에는 글이 개봉되는 시간에 사용자한테 노티를 보내고 다른 사람들의 글을 읽을 수 있게끔 해야 하는데, 이는 사용자의 요청이 아니라 벡엔드가 자체적으로 요청해야 하는 것이다.

이런 테스크는 Azure Functions가 적합하다. Functions는 Serverless Application이다. Azure App Service에서 인프라를 뺀 엄청 가벼운 웹앱이라고 생각하면 된다. 이는 특정한 시간에 돌아가는 프로그램을 만들 때 찰떡이다. 글 개봉 시간은 항상 정시에 있기 때문에, 매 정시마다 functions가 작동하게 해서 글이 개봉하게끔 만들었다.

4. Azure Application Insights

개발을 할 때는 테스트 케이스를 써서 원하는 기능들 잘 동작하는지 확인을 하였지만, 실제 베타 테스팅을 할 때는 어떤 버그가 나타날지 모른다. Azure Application Insights는 나의 앱이 잘 돌아가는지 모니터를 할 수 있는 서비스이다. 우선 나의 웹앱이 application insights로 사용하도록 설정을 하면 로그들이 다음과 같이 기록된다.

  • traces: ASP.NET Core에서 사용되는 Logger<T>를 통한 로그들이 기록된다.
  • requests: incoming http request에 대한 정보가 기록된다 (e.g. response code, duration).
  • exceptions: 앱 안에서 던져지는 exception이 기록된다.

기록을 남겼으니 에러가 낫을 때 나한테 알림이 오게끔 해야 한다. 이는 Application Insights의 Alerts를 통해서 손쉽게 설정할 수 있다. 가격은 Alert마다 매달 $0.5~1. 다음은 베타 테스팅을 위해 세팅한 알림들이다.

  • Response code가 500 이상일 경우
  • Traces에 level ≤ 3 로그가 발견된 경우 (Critical, Error, Warning)
  • 사용자에게 노티를 보내는 게 실패한 경우
  • Any exceptions within the app
  • Top 10 slowest request every day (그냥 궁금해서)

5. Azure Keyvault

앱을 안전하게 만들려면 여러 가지 secret을 관리해야 한다. 예를 들어 프런트엔드가 요청할 때 사용하는 api-key라는 시크릿, 데이터베이스와 연결할 때 사용하는 Connection String이라는 시크릿, 사용자가 안전하게 로그인할 수 있는 token를 발급할 때는 signing key라는 시크릿이 필요하다. 이것들은 숨겨진 장소에서 관리해야 한다는 점이 까다로운데 Azure Keyvault를 사용하면 간단하게 관리할 수 있다. Version control이 굉장히 잘 돼있어서 secret이 노출돼도 rotate 하면 된다. 가격은 $0.03 per 10,000 transaction으로 거의 공짜라고 생각하면 된다. $3을 내야 하는 Certificate Rotation만 조심하자.

상단 왼쪽에 있는 New Version를 누르면 바로 새로운 시크릿을 생성할 수 있다.

오늘은 우리가 사용한 5가지 Azure Cloud 서비스에 대해서 간단하게 요약해보았다. 결론적으로 클라우드는 짱이다. 덕분에 나 같이 원룸에 사는 24살도 아무 투자금 없이 성공적으로 어플을 론칭할 수 있었다. 클라우드를 통해 앞으로 더 창의적이고 다양한 아이디어들이 서비스되는 것을 기대한다.

Software Engineer @ Microsoft Azure Compute — To be or not to be. That's not really a question.

Software Engineer @ Microsoft Azure Compute — To be or not to be. That's not really a question.