모듈 기반의 개발 방식
모듈식 프로그래밍 (Modular Programming)
객체지향이 아닌 모듈,
모놀리식 구조의 한계는 모듈화(Modulariry)를 통해 해결할 수 있음
독립적이고 상호 교환 가능한 모듈로 분리하여 원하는 기능의 한 측면만 실행하는데 필요한 모든 것들이 포함되도록 강조하는 기술
더 작은 조각으로 분해하여 대규모 소프트웨어 프로그램 및 시스템 구축을 촉진한다는 목적을 가짐
Node에서는 Package라는 이름으로 개발 되어있음
커지는 프로덕트의 크기를 유지보수하기 위한 고민
점점 커지는 프로덕트, 어떻게 효율적으로 업무할 수 있을지 고민해보자.
프론트엔드에서의 코드: HTML/CSS/JS(TS)
HTML, CSS, JS(TS)를 이용해 코드 작성
과거부터 HTML,CSS,JS를 합쳐서 작성하기 위한 고민을 했었음
jQuery, backborn, angularjs 등
점진적으로 진화하면서 React, Vue 등에서 합친 단위를 "컴포넌트"라고 부름
과거에는 이러한 컴포넌트가 페이지 단위로 많이 없었기 때문에 모듈화 등을 크게 고려되지 않았음
비즈니스가 커지면서 "컴포넌트"를 묶고 개발 및 유지보수 할 수 있는 단위가 필요해지기 시작
웹에서 컴포넌트를 공유하기 위한 다양한 고민
Node 기반에서 Module의 체계를 구축(AMD.js, Common.js)
Module 단위로 응집하여 index.js 등의 중앙화를 통해 한번에 내보내는 등의 작업을 할 수 있음 (barrer index)
폴더로 도메인에 대한 이름을 만들고, 폴더 단위로 역할을 부여
NPM Library를 등록하여 사용하는 방법
Module 단위로 글로벌하게 Package로 가져와서 버저닝을 할 수 있다.
한 프로덕트에서 함께 관리하면서도 영향도를 제거하여 생산성을 높이는것이 목표, 관리포인트 절감 및 생산성 향상
어떠한 응집되는 단위를 어떻게 정의하고 운영할 것인가
작은 코드가 모여 커다란 도메인이 형성된다.
e.g) 공통으로 쓰이는 hook을 모아두는 hooks 폴더를 3년간 운영했더니 hook이 200~300개가 생성됨
고민 1) 200,300 개의 훅이 정상적으로 모든 react 버전에서 동작하는지, 모든 브라우저에서 동작하는지 어떻게 증명할지
고민2) hook 단위의 중복 코드는 어떻게 관리해야하지
고민3) hook에 등록되는 기준은 무엇일까
일정 수준을 넘으면 전문적으로 관리할 인원이 필요해지고, 지속적인 운영이 필요해짐
프로덕트의 성장 플로우 살펴보기
신규 사업의 시작, MVP 개발
초기에는 서버 개발, 프론트 개발 할 것 없이 적은 인원이 마구잡이로 만듬
만들고 나서 서버 프론트가 합쳐져 있다면 분리를 하여 프론트 및 서버의 전문성을 갖고 만들 수 있도록 한다.
이 떄 핵심 목표는 어떻게든 빠르게 개발하는 것이며, 업무 생산성이 어떻게 만들든 그렇게 저하되지 않는다.
사업의 확장, 기능 컨트롤을 쉽게 하기 위한 어드민 제작
사용자형 프로덕트와 운영에 필요한 어드민 프로덕트 두 개 (혹은 이상)이 되는 시점
이 떄 바로 Monorepo를 적용하기보단 각 서비스 별로 레포지토리를 다르게 하여 빠르게 개발하는 것이 목표
가장 중요한 것은 회사의 생존, 생산성을 고민하기 쉽지 않음
신규 인원 채용으로 인한 생산성을 위한 고민, 라이브러리 개발/운영
기존 인원으로 비즈니스 치는 시간도 촉박하여 생산성에 대한 고민을 하지 못하던 상황
신규로 추가된 인원으로 인해 더 많은 리소스를 할애 할 수 있게 됨
점진적으로 시간이 남기 시작, 생산성에 대한 고민을 할 수 있음
더 높은 생산성을 위해 공통의 코드를 모아서 라이브러리를 개발하고 운용하자는 결론을 내게됨
사업이 많은 성장과 지속된 인원의 채용으로 생산성을 논하고 코드 효율성을 생각하게 될 때
사업의 성장, 지속된 인원의 채용은 생산성을 고려하게 만든다.
인원을 뽑아도 인원이 2배 이상의 효율을 바로 내주진 않기 때문
코드 복잡도와 작업량을 인원의 증가로 바로 해결되지 않고, 그것을 위한 생산성 측면 R&R을 통해 적절하게 분리해줘야 한다.
회사의 사업 규모 확장으로 다양한 팀으로 쪼개지는 상황에서 전체 팀이 효율적으로 일하기 위해
여러 사업이 추가되면서 팀이 추가되고, 조직개편으로 업무는 더 많아지고, 각 팀 별로 더 업무를 잘 수행하기 위해 고민하게 된다.
각 팀의 모든 업무를 중앙에서 효율적으로 처리하기 위한 공통 조직이 필요해진다.
프로덕트가 성장하면서 따라오는 것들
"나누는 것의 비효율"이 "유지하는 것의 비효율" 을 넘어버리는 순간
사업이 커질수록 다양한 사업을 담당하는 조직이 생기고, 그에 따른 프로덕트를 개발하고 운영하기 위한 조직이 붙게 된다.
프로덕트를 개발하고 운영하는 조직은 계속 커지며, 커지면서 분리되고 운영하던 코드를 분리시키고 인수인계 한다.
이 때 인수인계 비용과 분리하기 위한 비용은 만만치 않게 발생
조직개편은 이러한 "나누는 것의 비효율"을 인지하지만 , "유지하는 것의 비효율"을 넘어버리는 순간이다.
조직개편으로 인해 더 많은 가치를 만들어내고 더 긴 미래를 바라보게 된다.
만약 이때 이미 코드들이 모듈 단위로 나뉘어져있다면?
모듈 기반으로 생각해야 하는 이유
모듈 기반으로 생각하는 것은 "미래를 위한 필수적인 선택"
첫 번째: 커져가는 프로덕트에서 코드간 의존성을 줄이기 위함
두 번째: 공통 코드의 변경 사항이 생겨도 운영중인 코드에 영향도를 줄이기 위함
세 번째: 관리 포인트를 분리하기 위함
이러한 목표를 달성하기 위해 점진적인 코드 응집 전략과 다양한 버저닝 정책을 고려해야 한다.
모듈 기반 개발 방식에 대한 이해
모듈 단위의 레이어 구상하기
"비즈니스에 적합"의 의미
비즈니스의 크기 (인원, 업무, 비용 등)에 따른 적합한 수준의 코드 퀄리티
과한 모듈의 추상화는 컨텍스트 스위칭 비용을 크게 한다.
반대로 분리되지 않은 코드는 협업을 까다롭게 만든다.
과하지 않는, 협업에 용이한 분리된 코드를 일컫음
하나의 팀이 여러 프로덕트를 운영하는 경우
공통 코드는 패키지화를 하지 않아도 모듈 단위로 사용하여 프로덕트에서 공통으로 쓰이는 코드를 묶어놓는 역할만 한다.
크게 복잡하지 않은 구성
하나의 팀이 여러 모노레포를 운영하는 경우
공통 코드의 레벨 자체가 별도의 수준으로 레이어가 형성됨
크게 복잡하지 않은 구성
독립된 단위로 프로덕트를 운영하는 경우
복잡해지기 시작하는 아키텍처
모노레포를 기반으로 각 팀이 사용하고 있는 상황이므로 코드베이스는 분리 되어있는게 효율적
동일 레포지토리를 사용하게 될 경우 팀 별로 특화된 전략을 사용할 수 없는 문제 생김
그러므로 팀 별로 레포지토리는 분리되는게 맞는 그림
팀 별로 코드를 가져오기 위한 방안을 고민
패키지로 받을 수 있도록 제공하는 것이 가장 이상적
iframe 등의 방법도 있지만 비단 레이아웃만 가져오는 것이 아니기 때문
수많은 팀이 여러 레포지토리 단위로 업무를 진행하는 경우
이미 서비스를 운영한지 오래된 대기업 등에서 보이는 현상
여러 레포지토리를 운영하기 위한 별도의 조직이 필요
별도의 조직은 일원화된 채널을 통해 레포지토리의 갱신사항을 전파하는 역할을 맡음
조직과 모듈 레이어가 일원화가 되어야함
어느정도 수준 (독립된 단위로 프로덕트를 운영하는 경우)까지는 조직과 무관하게 운영 가능
하지만 비즈니스가 커지고 수많은 팀이 존재하게 되면서 레이어가 조직과 더불어 함께 고민하게 되는 경우가 생긴다.
분리되는 코드를 운영하기 위한 프로세스 구축
공통의 코드를 유지보수 하는 전담 인원의 필요성 대두
여러 조직으로 분화되면서 모든 팀은 중복코드를 중앙화하기 위해 노력
각 조직별 공통된 라이브러리가 생기고, 각각 유지보수
전사단위로 보면 생산성 절감이 100%된 것이 아님
계속 파편화되어 커지면 나중에는 합칠때 더 어려워진다.
그러므로 중앙화할 수 있는 라이브러리가 필요
그러면 라이브러리는 누가 운영?
공통팀 (A.K.A Core)
웹 프론트엔드 전사적으로 공통을 담당하는 인원 필요
이를 팀으로 묶어도 되나, 전사의 프론트가 하나의 조직으로 구성되어있다면 파트나 TF도 충분할 수 있다.
공통팀의 역할: 웹 프론트 전사적으로 필요한 도구를 개발
지속적인 커뮤니케이션을 통해 개선사항을 듣고 반영
공통팀은 공정한 업무를 진행해야하며 공통이라는 것에 매몰되지 않고 비즈니스를 놓으면 안된다.
공통의 업무를 가장 큰 비즈니스를 담당하는 팀에 포함하기도 한다.
공통팀이 해야하는 일
비즈니스를 담당하는 팀에서 공통으로 기여할 코드를 올리면 검증 및 테스트를 진행하여 라이브러리에 포함하는 역할
공통의 코드를 유지보수하고 테스트 등을 진행하는 역할
새로운 공통의 코드를 만들고 생산성을 올리는 역할
웹 프론트 분야 뿐만 아니라, 앱, 서버와도 협업하여 생산성을 올리기 위한 방안을 마련
효율적으로 일하기 위해 생산성 툴을 만들거나 업무 가이드라인을 제작하여 공유
가장 중요한 것은 유기적인 프로세스의 구축
공통의 의미는 "비즈니스를 빠르게 동작하도록 돕는 것"
비즈니스가 제데로 안되면 공통은 존재할 이유가 없다. 오히려 비즈니스를 위해 공통의 모든 리소스를 할애해도 모자르다.
비즈니스를 개발하는 시간 대비 공통에서 생산성을 개선해서 올리는 비용이 더 높은 가치를 낼 때 공통은 필요하다.
공통은 팀의 가치를 위해, 팀의 존속을 위해 비즈니스를 최대한 기여
비즈니스 개발자들의 코드와 상황을 잘 이해하며, 이해하는 상황에서 코드 생산성을 올릴 수 있도록 프로세스를 구축한다.
방관자로 참여하여 비즈니스 개발자의 비효율 업무를 체크하여 추후 재발하지 않도록 가이드라인 및 툴을 개발
공통의 코드를 빠르게 제작하여 프로젝트 진행 시 사용할 수 있도록 코드를 제공한다.
커뮤니케이션 프로세스
바텀업 된 코드를 합치기 위한 프로세스 (MR - 템플릿으로 검증 / 테스트 프로세스 / 컴포넌트는 시각적 회귀 테스트 등)
탑다운으로 공통 코드를 공유하기 위한 프로세스 (Notion 채널 및 각 담당자에게 공유하기 위한 방법 고민)
전사 및 웹 표준안을 개발하여 전파(지원 브라우저, OS 버전 등 기준 작성)
버저닝이 추후 필요해진다면 버저닝을 공유하는 슬랙 채널이나 알람을 제공
프로젝트 별 라이브러리 버전 리포트 등을 제공해주는 것도 방법 (레포지토리의 package.json 읽기)
Last updated