내가 현재 재직 중인 그렙에서는 대회와 채용을 기반으로 한 코딩 테스트 솔루션을 개발하고 있다.

재직 중인 회사의 코딩 테스트 서비스가 작년에 이어 카카오 블라인드 채용 솔루션으로 채택되어서 대회를 준비하면서 있었던 일을 정리하고자 한다.

AWS 인프라 준비

내가 입사하기 전에 있었던 전년도 대회에서 AWS의 인스턴스가 예상과 다르게 capacity가 떨어지고 미리 요청하지 않아 제한된 리소스 개수에 의해 고생했었다는 이야기를 들었다.

마침 대회가 있기 두 달전쯤 AWS 코리아에서 자문을 해주었고 대회 전에 서울 리전에서 제공 가능한 리소스 용량을 확인해줘서 대응을 편하게 할 수 있었다. 하지만 원하는 만큼의 사양(m5.large)의 인스턴스를 서울 리전에서 할당받을 수가 없다는 답변을 받고 도쿄 리전을 함께 쓸 것을 권장 받았다. 그리하여 급하게 VPC Peering을 통해서 채점 서버를 준비할 수 있었다.

하지만 VPC Peering이라고 완벽하지는 않았다. 채점 서버의 취약점을 막기 위해 외부 인터넷망을 격리하는데 VPC 피어링의 경우에 제약사항이 많아서 애를 먹었다. 예를 들면 내부의 S3의 접속만 허용하기 위해서 S3의 라우팅 테이블을 매칭해야 했지만 피어링은 가능하지만 라우팅 테이블이 공유가 되지 않아서 S3 IP RANGE를 참조해서 허용해주도록 준비를 했다.

대회 당일 사용할 인스턴스가 다 합하여 1200대 정도로 예상되어 DB Connection을 생각해 DB의 인스턴스 사양도 올렸다. DB의 경우 AWS의 멀티 AZ를 사용하고 있어서 약간의 성능 저하는 있지만 문제없이 서비스 중에도 사양 변경이 가능했다.

부하 테스트 (Load Test)

대회 당일 순식간에 몰릴 사용자를 대비하기 위해서 부하 테스트를 통해서 병목 지점을 판단하고 서비스를 제공할 수 있도록 하기 위해서 노력했다. 부하 테스트를 위해서 사용되었던 wrk라는 벤치마킹 툴은 Lua 코드로 개발되어 있었다. Lua로 구현되어있는 코드를 올해는 Ruby-Jmeter를 이용하여 다시 작성하였다.

Lua로 짜여진 코드가 속도가 빠르고 병렬로 돌렸을 때 부하를 더 효과적으로 낼 수 있다는 점의 장점은 있었지만 내부적 로직이 변경될 때마다 서로 다른 언어로 된 코드를 참고한다는 것은 인원이 적은 개발팀에 있어서는 큰 비용을 지불한다고 판단했다. 우리는 이미 레일즈를 사용하고 있었기 때문에 Ruby-Jmeter를 사용하는 게 적합했다.

Ruby-Jmeter는 Ruby 코드를 이용하여 Jmeter 설정 파일을 만들어주고 테스트를 실행해주는 라이브러리다. 추가 플러그인 등을 함께 사용하면 일괄적으로 스레드를 모아서 부하 테스트를 할 수 있는 기능이 제공된다.

간단하게 짜여진 부하 테스트 시나리오는 아래와 같다.

  1. 코딩 테스트를 위해 홈페이지에 접속을 한다.
  2. 접수한 아이디로 로그인을 한다.
  3. 일괄적으로 시험을 시작한다.
  4. 명시적으로 시험을 종료한다.

이 시나리오를 만여 명이 일괄적으로 1분씩의 간격을 주고 진행하도록 했다.

테스트 진행을 위해 BMT용 로드밸런스를 세팅하고, 별도의 격리된 인스턴스를 준비해서 연결했다. 테스트에 사용한 웹서버만 100대 정도를 이용했다.

ELB Pre-Wramup

부하 테스트에서 의미 있는 데이터를 얻었는데 ELB가 클라이언트의 리퀘스트를 받아줄 수 있는 양이 점진적으로 늘어나기 때문에 (Scale UP을 하고 이후에 Scale Out을 한다고 들었음) 웜업 타임 동안 리퀘스트를 받아줄 수 없는 문제가 발생했다. 이를 대응하기 위해서는 꼭 AWS Support Center 플랜을 BASIC에서 유료 플랜으로 올린 후 elb pre warming을 요청해야 한다.

하지만 우리는 그렇게 대응하지 않고 동일한 인스턴스를 바라보는 여러 개의 ELB를 생성하고 이걸 도메인에 DNS Pooling 하는 방식으로 해결했다.

우리 서비스에 접속하면 라운드 로빈으로 임의의 ELB가 서빙되어 서비스를 제공하도록 했고 그렇게 리퀘스트를 분리시키면 이미 접속중인 사용자가 있기 때문에 급격한 워밍업은 필요 없을 거라는 이유였다. 또 언제고 폭발적으로 늘어날 수 있는 트래픽이라면 항시 대응이 가능하도록 설계가 되어있는게 좋을 것 같다는 판단도 있었다.

값진 경험

한달 정도 여유롭게 덕분에 500에러가 현저히 줄었고 무사히 대회를 종료할 수 있었던 것 같다.

준비하는 동안엔 정말 토나오게 힘들고 대회 당일까지도 긴장이 많이 돼서 힘들었지만 이번 경험을 통해서 AWS 인프라 세팅이나 부하 테스트의 경험을 쌓을 수 있었고, 불필요한 쿼리를 줄이는 등 고민을 할 수 있었던 기회였던 것 같다.

특히 이전 회사들의 규모에선 경험해볼 수 없는 1000대가 넘어가는 서버를 준비하고 대응한다는 경험이 무엇보다 값졌다. 물론 더 큰 회사에서는 이 정도 서버 규모를 가지고 비웃을 수도 있겠지만(이전에 면접에서 비웃던 분이 생각나서 하는 말은 아니고) 그래도 이런 경험은 항상 값지고 고맙다.