Here's my dents in the universe

회고 팀의 개발환경 세팅을 마무리하며


내가 속한 베이글코드는 전세계 200개국을 대상으로 소셜 카지노 게임을 서비스하고 있다. 현재 서비스 중인 게임은 5가지이고, 추가로 2종류의 캐쥬얼 게임을 개발중이다. 서비스하는 게임의 가짓수가 늘어나고 회사의 규모도 커지면서, 자사 게임들을 하나로 연결해줄 플랫폼의 필요성 대두되었다. 지난 8월, Task force로 시작된 ‘플랫폼 TF’가 지금은 ‘플랫폼 팀’으로 승격되어 4명으로 구성된 어엿한 팀이 되었다.

플랫폼 팀은 로그인/인증, 결제 검증, PUSH, 지표/통계, 게임 운영툴 등의 서비스를 개발해 사내에 API 형태로 제공하는 것을 목표로 한다. 현재까지 로그인/인증, 결제 검증에 해당하는 서비스를 개발 완료한 상태로, 사내 신작 게임에 성공적으로 적용된 상태다. 프로젝트를 진행하면서 주안점을 두었던 부분에 대한 회고(postmortem)를 진행하며, 다음 프로젝트 진행에 도움을 얻고자 한다.

플랫폼 TF의 출범

플랫폼 TF 출범이 결정되고, 회사 C-level 밑 시니어들이 모여 플랫폼 서버가 맡아야할 역할을 나열했다. 이를 중요도, 긴급도 순으로 정렬했고, 그 중 가장 중요하고 급한 것으로 평가된 로그인/인증 서버 개발을 시작으로 플랫폼 TF의 첫 삽을 뜨기로 결정되었다. 플랫폼 TF 장으로 선발된 시니어 분이 로그인/인증 서버가 제공해야할 요구사항을 명문화했고, 아키텍쳐와 API 설계를 시작했다.

TF 합류 결정

내가 플랫폼 TF에 합류한 것은 이 시점이다. 슬랙을 통해 플랫폼 TF가 발족되었음이 알려졌고, TF에 합류할 사람을 자원받았다. 기존에 Club Vegas라는 게임의 서버 개발을 담당하고 있던 나는, ‘서버, 인프라의 가장 처음을 경험해보는 것’에 대한 갈증이 있었다. 내가 개발하고 있던 게임 서버는 몇 해 전의 초기 개발자들이 인프라부터 세팅을 완료해놓은 상태였고, 내가 할 수 있는 일은 버그를 고쳐 안정성을 높이거나, 새로운 피쳐를 추가하는 것에 그쳤다. 새롭게 발족되는 TF라면 분명 많은 경험을 해볼 수 있을 것이라는 생각에 곧바로 플랫폼 TF에 자원했다. 며칠 후 TF를 리드하시는 시니어분과 1:1 면담을 진행했고 합류가 결정되었다.

기술 스택 선택의 기준들

Typescript/Node.js

내가 합류한 시점까지는 개발 언어와 프레임워크가 정해져있지 않았다. 결국 Java/Spring과 Typescript/Node.js 중 선택하게 되었는데, 기존 사내 주요 개발 스택이 Typescript와 Node.js 였던 만큼, 사내 자원을 최대한 활용하기 위해 Typescript/Node.js를 사용하기로 결정하였다. Node.js가 가진 퍼포먼스에 대한 우려도 있었지만, 이는 서버 대수를 조절함으로써 충분히 커버 가능한 범위였으므로, 우리팀은 개발 생산성에 더 높은 가중치를 두었다. (Java vs. Node.js)

NestJS

현재 회사에서 서비스하고 있는 게임인 Club Vegas(이하 CVS)는 초창기에 Javascript와 Node.js 로 개발이 시작되었다. 이후 Typescript를 도입해 타입 안정성은 높일 수 있었지만, 절차지향적인 레거시 아키텍쳐 구조는 수정하기가 어려웠다. 기존 CVS 서버를 개발하던 나는, 코드 베이스가 커질수록 절차지향적 코드의 유지/보수 비용이 크게 증가함을 느꼈고, 로그인/인증 서버만큼은 시작부터 OOP적으로 구현해, 수정하기 용이한 아키텍쳐 구조를 만들고 싶은 욕심이 있었다.

NestJS is a framework for building efficient, scalable Node.js server-side applications.

NestJS는 Node.js의 가장 큰 장점이자 단점인 ‘제약 없음’을 해결하는 프레임워크다. Angular 프레임워크의 아키텍쳐에 영향을 받은 NestJS는 아키텍쳐 구조를 OOP적으로 제한해, 확장하기 쉽고 모듈 간 의존도를 줄인 코드를 작성하도록 돕는다.

프레임워크는 한 번 도입하면 제거하기 어렵기 때문에 망설이기도 했지만, NestJS를 사용하고 있는 기업이 늘어나고 있었고, **랜딩 프로젝트로 간단한 API 서버를 만들어본 결과, 개발 생산성이 높다고 판단되어 도입을 결정하게 되었다. **(당근마켓의 NestJS 포스팅)

TypeORM

개발 생산성을 위해 ORM을 도입할 필요가 있었다. 관계형 데이터베이스에서 받아온 오브젝트를 일일이 parsing/deserializing할 필요없이 ORM 기능에 맡길 수 있기 때문이다. 프로그래머는 마치 테이블에 object를 저장하는 것처럼 object만 다루면 되었다.

Node.js 진영에서 가장 많이 쓰는 ORM 툴은 Sequelize와 TypeORM이 있었다. Sequelize가 보다 긴 히스토리를 가지고 있었지만, 후발주자인 TypeORM이 빠르게 사용자층이 늘고****있다는 점, 코드 베이스가 Typescript로만 구현되어 유지/보수가 쉽다는 점, 그리고 NestJS 프레임워크가 공식적으로 권장하는 ORM이라는 점에서 TypeORM을 선택하게 되었다. (NestJS documentation)

Jest

테스트 프레임워크를 선정하던 당시, 팀에 Javascript 용 테스팅 프레임워크를 사용해본 사람이 없었고, 특정 프레임워크에 대한 선호도가 없는 상태였다. 각종 테스팅 프레임워크에 대한 도입 후기를 찾아보던 중, Airbnb Engineering팀에서 mocha로 짜여진 테스트 코드를 Jest로 전환하고 테스트 런타임이 1/3로 줄었다는 글을 읽고 Jest를 도입하기로 결정했다. (Migrating from Mocha to Jest)

CI/CD

기존 속했던 CVS 팀에서는 Jenkins를 이용해 빌드와 디플로이를 진행했다. Jenkins는 오픈소스이고, 오래된 히스토리를 가진 만큼 두터운 커뮤니티와 많은 종류의 플러그인을 제공한다. 하지만 사내에서 사용중인 코드 버전 관리 시스템(GitLab)과 분리된 서드파티 툴을 관리해야 한다는 점이 단점로 다가왔다. 반면 GitLab CI/CD 는 소스코드와 같은 웹사이트에서 CI/CD를 관리할 수 있다는 점gitlab_ci.yml을 이용해 CI/CD 스크립트의 버전을 코드처럼 관리할 수 있다는 점, 브랜치 별로 동작을 분리할 수 있다는 점이 매력적으로 다가왔다. Jenkins에서만 가능한 기능이 생길 때까지 GitLab CI/CD 툴을 사용하기로 결정했고, 현재까지 만족스럽게 사용하고 있다.

마치며

이렇게 플랫폼 TF에서 맡은 첫번째 프로젝트를 성공적으로 마무리했다. 그 사이 플랫폼 TF는 플랫폼 팀으로 승격되었고, 나는 리드 분의 제안을 받아 플랫폼 팀으로 소속을 옮기게 되었다. 애초에 목표했던 것처럼 플랫폼 TF에 속해 일하면서, 서버/인프라의 가장 처음을 경험해볼 수 있었다. **기존 팀에서는 당연하게 생각했던 자동화된 빌드와 배포, AWS 인프라 세팅, 슬랙 integration, 커스텀 로거, ORM 연동 등이 왜 필요하고, 어떻게 동작하는지 더 깊이 이해할 수 있었다. **(이 과정에서 겪은 시행착오는 별도의 포스팅으로 분리해 다룰 예정이다)