모노레포의 문화적 의의

2022. 5. 30. 08:55Frontend

 

 

Overview

콴다 프론트엔드 팀에서 최근 효율적인 프로젝트 관리를 위해 "모노레포(monorepo)"를 도입했습니다. (레포 이름도 굉장히 Semantic 한 "qanda-frontend"입니다) 팀 내에서 모노레포를 도입하자는 이야기는 작년 2분기 정도부터 조금씩 나오기 시작했지만, 이런저런 이유들과 고민들로 미뤘었다가 올해 1분기 말부터 본격적으로 리서치를 시작했고, 검색 결과 페이지(search-result-web), 콴다 과외(tutor-web), 콴다 메인 페이지(qanda-ai-web, qanda-ai-user-web)등의 주요 프로젝트들을 마이그레이션 하기 시작하면서 지난주 목요일 "모노레포 레이드(Raid)"를 종료했습니다. 모노레포를 도입하면서 Yarn Workspace와 같은 모노레포 Tool이나 CI / CD Pipeline 구축, TBD(Trunk Based Development) 원칙, TroubleShooting등과 같은 기술적인 고려사항들이 많았지만, 이 내용은 다음 포스팅이 될 "모노레포의 기술적 요구사항"에서 다루도록 하고, 이번 포스팅에서는 콴다 프론트엔드 팀이 "왜 모노레포를 도입하기로 결정했는가?"에 대해서 중점적으로 이야기해보려고 합니다.

 

 

What our team is aiming for

콴다 프론트엔드 팀이 가장 중요하게 생각하고 있는 원칙은 다음 3가지로 정리할 수 있습니다. 여기서 중요한 건 "집중하는 요소를 명시적으로 정리했다는 것"인데, 정말로 팀이 중요하게 생각하는 몇 가지 요소들에 가능한 모든 에너지를 집중하고, 그 외의 것들은 신경 쓰지 않도록 하는 것이  효율적으로 일하면서, 좋은 성과를 가져올 수 있을 것이라고 믿고 있기 때문입니다. 따라서 모노레포를 도입할 때도, 이 3가지 요인들에 모노레포가 충분히 이점을 제공할 수 있는지를 판단하려고 노력했고, "그렇다"라는 결론이 나왔기에 팀에서 모노레포를 도입하기로 결정했습니다. 3가지 요인은 다음과 같습니다.

 

모든 것을 다 잘하려고 하면 아무것도 "잘"할 수 없게 된다.

 

  • "유저 경험(User Experience, UX)"에 집중할 수 있는 환경 만들기
  • "애자일(Agile)" 하게 움직일 수 있는 환경 만들기
  • 구성원들이 "재미있게" 개발 할 수 있는 환경 만들기

 

유저 경험에 집중할 수 있는 환경 만들기

요즘 시대의 프론트엔드 개발자는 갖춰야 하는 역량이 참 많습니다. HTML, CSS, JS에 대한 지식은 물론이고, 브라우저에 대한 이해, 테스트 코드와 방법론에 대한 이해, CI / CD 및 인프라에 대한 이해, 기초적인 CS에 대한 이해 등등 많은 역할이 기대되지만, 실제로 이 모든 것들을 단기간에 습득하는 것은 불가능에 가깝습니다.

 

콴다 프론트엔드 팀에서는 프론트엔드 개발자가 갖추어야 할 요소 중 가장 중요한 요소를 "좋은 유저 경험을 제공하는 것"에 두고, 이를 모든 팀원들이 실천하도록 돕기 위한 여러 기술적, 문화적 지원을 하고 있습니다. 좋은 유저 경험을 제공하기 위해서는 물론 앞서 말한 "프론트엔드 개발자가 갖춰야 하는 여러 역량"들이 기반이 되어야 하지만, 무턱대고 "HTML을 공부한다", "Javascript를 공부한다"와 같은 모호한 개념이 아닌, "더 좋은 유저 경험을 주기 위해 페이지 로드 시간 500ms을 줄이는 것이 필요하고, 이를 위해 Javascript 번들링 사이즈 최적화를 공부한다"와 같이 보다 구체적인 목표모든 팀이 공유하기 때문에 좋은 유저 경험을 제공한다는 팀의 목표를 효율적으로 해결하면서도 팀원 개개인의 성장이 더 잘 일어나게 된다고 생각합니다.

 

애자일 하게 움직일 수 있는 환경 만들기

스타트업의 특성상, "빠르게 시도하고, 이에 대한 피드백을 얻은 뒤, 개선하여 또 빠르게 시도하는" 애자일(Agile)한 움직임이 굉장히 중요합니다. 이를 위해서는 새로운 프로젝트들을 빠르게 생성하고, 테스트하고, 배포하는 과정이 쉬워야 합니다. 프론트엔드 개발자가 하나의 프로젝트를 만드는 데 사용할 수 있는 에너지는 한정되어 있기 때문에, 개발자가 신규 프로젝트 생성, 테스트, 빌드, 배포 파이프라인에 드는 에너지를 줄일수록, "더 좋은 유저 경험"과 "비즈니스 모델"에 대해 깊이 고민할 수 있는 에너지가 더 생기게 된다고 생각합니다.

 

 

구성원들이 "재미있게" 개발할 수 있는 환경 만들기

"노력하는 자는 즐기는 자를 이기지 못한다"는 말이 있듯, 좋은 프로덕트를 개발하기 위해서는 개발자들이(더 나아가 회사의 구성원들이) "재미있게"일하는 것이 중요합니다. 그리고 개발자들이 "재미있게" 개발하기 위해서는 "도전적인 과제"와 "좋은 피드백"이 갖춰져야 한다고 생각합니다. 팀 구성원을 비롯해 많은 개발자들이 기술적으로, 혹은 비즈니스적으로 더 성장하기를 원하고, 더 많은 것들을 배우기를 원하기 때문에 이들이 많은 것을 배울 수 있는 "도전적인 과제"가 있고, 그 과제를 해결하면서 비슷한 과제들을 앞서 해결해본 여러 사람들의 "피드백"을 받을 수 있다면 구성원들이 성장하면서 재미있게 개발할 수 있는 환경을 제공한다고 이야기할 수 있을 것입니다.

 

 

모노레포의 문화적 의의

앞서 팀이 중요하게 생각하는 3가지 요인에 대해 간단하게 살펴보았습니다. 이 3가지 요인을 기준으로 생각해보았을 때, 모노레포를 팀에 도입하는 것이 이 3가지 요인 모두를 만족시켜 팀이 일하는 방식을 향상시키는데 도움이 된다고 판단했습니다. 

 

 

코드의 "충돌", 그리고 코드 "기웃거리기"

앞서 구성원들이 "즐겁게" 일하기 위해서는 "좋은 피드백"이 있어야 한다는 전제가 있었습니다. 모노레포를 사용하게 되면 개발자들이 "좋은 피드백"을 얻는데 더 도움이 됩니다. 이전에 코드 리뷰 문화에 대한 생각을 담은 포스팅에서 설명한 바 있지만, 팀에서 기본적으로 "작은 PR"을 권장하고 있고, 각각의 PR에는 Semantic 한 단위로 Summary, Reproduce, Description, Screenshots 등의 정보들이 들어가기 때문에 각각의 PR은 대부분 누구나 접근해서 피드백을 남기고, 자유롭게 리뷰할 수 있는 단위로 만들어집니다.

 

모노레포는 이 여러 프로젝트들의 PR들을 "하나의 레포"에서 이루어지도록 함으로써, 개발자들이 서로의 코드를 더 자주 충돌시키고(여기서의 충돌은 "merge conflict"를 의미하는 것이 아니라 서로 문제를 해결하는 다른 방식들을 교환한다는 의미입니다), 의견을 더 자주 교환하도록 도와줍니다. 의견을 교환하면서 Comment로 이어나가기엔 다소 길어지는 내용들은 즉석에서 Slack의 Huddle을 사용하거나 구글 Meet을 통해 즉석 회의를 진행하기도 하고, 팀 전체 차원에서의 논의가 필요한 내용들은 Weekly Team Meeting에 직접 Agenda를 올리기도 하면서 문제를 가장 효율적인 방식으로 해결하는데 도움을 줍니다.

 

 

PR에서 자주자주 의견을 교환하는 것 이외에도 내가 지금 작업하고 있는 바로 이 레포에 다른 프로젝트들의 최신 코드가 존재하기 때문에 비슷한 문제를 해결할 때, 다른 프로젝트에서 문제를 해결한 방식을 쉽게 도입하는 일명 "기웃거리기"가 가능해집니다. 혼자서 풀기 어려운 문제를 두고 고민하고 있을 때, 이미 동일한 문제를 해결한 시니어의 코드를 보거나, 내가 알지 못했던 Official Document의 API를 통해 문제를 깔끔하게 해결한 다른 동료의 코드를 보는 것은 개발을 "빠르고 재미있게" 하는데 많은 도움이 됩니다.

 

 

Global Configuration & Templates

모노레포를 사용하면서 얻게 되는 큰 이점 중의 하나는 ESLint나 Prettier와 같은 Coding Convention을 통일할 수 있다는 점입니다. 서로 다른 프로젝트들이 전체 레포 단위의 Config를 공유하기 때문에 신규 프로젝트를 세팅할 때, Coding Convention에 큰 신경을 쓸 필요 없이 레포의 Global Setting을 그대로 override 해서 개발할 수 있으므로 초기 설정에 드는 시간을 절약할 수 있습니다. (콴다 프론트엔드 팀에서는 AirBnB Base의 꽤 엄격한 Lint Rule을 지키면서 코딩을 하고 있기 때문에 런타임에서 발생할 수 있는 의도치 않은 잠재적인 이슈들을 빌드하기 전에, 심지어 커밋하기 전에 상당 부분 제거합니다. 또한 Pre-Commit Hook으로 Lint를 돌리고 있기 때문에 Lint를 통과하지 못하는 코드는 커밋할 수도 없습니다)

 

또한 신규 프로젝트를 런칭할 때 자주 쓰이는 SSR, CSR 프로젝트의 템플릿을 모노레포에서 제공하도록 하면 새로운 프로젝트를 생성할 때, 템플릿을 빠르게 복사해서 사용할 수 있으므로 초기 세팅에 드는 시간을 더 절약할 수 있습니다. 다시 말해서 신규 프로젝트를 개발할 때, 그냥 모노레포 안의 템플릿을 Copy & Paste 한 뒤에 바로 컴포넌트 개발을 진행할 수 있게 되는 것입니다. 

 

 

Code Updates

모노레포를 사용하면 팀 내에서 유지 보수하는 프로젝트들을 비교적 최신 상태로 유지할 수 있게 됩니다. 위에서 언급한 "코드의 충돌"이 자주 일어나기 때문에 비슷한 컴포넌트가 들어가 있는 다른 서비스들을 자주 기웃거리게 되는데, 이 과정에서 내가 담당하는 프로젝트가 아니더라도 개선할 여지가 있다고 판단되는 프로젝트들에 대해서 개선할 여지들이 자주 생기게 됩니다.

 

전체 레포에 대해 일종의 "주인의식"이 생기게 되는 셈인데, 이런 여지들이 자주 생길수록 프로젝트들의 코드가 다 같이 조금씩 개선되는 이점이 생기게 됩니다. 실제로 콴다 프론트엔드 팀에서도 모노레포로 기존 프로젝트들을 이전하면서 존재하는지도 몰랐던 프로젝트들을 많이 발견하게 되었는데, 2~3년 전에 만들어져서 아직 React + Flow의 조합으로 되어 있는 프로젝트이거나, RUM, Sentry와 같은 모니터링 툴이 붙어있지 않은 프로젝트들을 발견하고 최신화하여 서비스의 품질을 개선하기도 했습니다.

 

모노레포로 이전하면서 모니터링 툴이 붙어있지 않은 프로젝트들에 모니터링 툴을 추가했고, 성능상의 이슈를 발견해서 다음과 같이 대폭 개선하게 되었습니다.

 

 

For Agile

모노레포를 도입하자고 이야기가 나오고 실제로 Working Example을 만드는데 꽤 오랜 시간이 걸렸던 것 같습니다. 모노레포를 도입하는 과정에서, 배포 파이프라인과 테스트 파이프라인도 새로 구축해야 했고, 그외에도 Global Lint를 적용하거나, 빌드할 때 특정 서비스의 dependency만 빌드해야 하고, clone하거나 yarn install 할때 너무 오랜 시간이 걸리고 불편하다는 등의 여러 기술적인 문제들이 많이 튀어나와 진땀을 흘렸던 적도 있었습니다. 하지만 이를 팀원들이 함께 달려들어 해결하는 과정에서 Git, Node, Javascript등의 기술들에 대한 이해도가 높아졌고, 말도 많고 탈도 많았지만 결국에는 다같이 모노레포를 사용하는 환경을 만들었다는 점에서 "함께 달려들어서 문제를 해결하려고 하면 결국에는 어떻게 해서든 해결한다"는 습관이 팀 내에 생기기도 한 것 같다는 생각이 듭니다.

 

물론 한편으로는 모노레포를 도입하는 것이 능사는 아니라는 생각도 있습니다. 현재 팀의 크기(9명 ~ 10명)에서는 30~40개의 프로젝트들을 모노레포에서 운영하는 시스템이 잘 동작하더라도 팀이 30명, 50명, 100명 단위로 커지고 관리해야 하는 프로젝트가 수백개에 달할 때는 모노레포를 도입했을 때 예상하지 못한 문제들이 발생할 수 있을 것이며, 어느 시점에서는 모노레포를 포기해야 할 수도 있을 것입니다. 하지만 도입을 시도해보지 않았더라면 몰랐을 것들이 참 많았던 것 같습니다. 어느 순간부터는 "문제를 푸는 것"보다 "풀어야 할 좋은 문제를 정의하는 것"이 더 중요하다는 생각을 갖게 되었는데, 모노레포를 도입하면서 이런 좋은 문제들을 많이 발견했다는 생각도 듭니다.

반응형