> For the complete documentation index, see [llms.txt](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/dev_note/system-design/undefined-5.md).

# 모듈 기반의 개발 방식

## 모듈식 프로그래밍 (Modular Programming)

> 객체지향이 아닌 모듈,

* 모놀리식 구조의 한계는 모듈화(Modulariry)를 통해 해결할 수 있음
* 독립적이고 상호 교환 가능한 모듈로 분리하여 원하는 기능의 한 측면만 실행하는데 필요한 모든 것들이 포함되도록 강조하는 기술
* 더 작은 조각으로 분해하여 대규모 소프트웨어 프로그램 및 시스템 구축을 촉진한다는 목적을 가짐
* Node에서는 Package라는 이름으로 개발 되어있음

### 커지는 프로덕트의 크기를 유지보수하기 위한 고민

> 점점 커지는 프로덕트, 어떻게 효율적으로 업무할 수 있을지 고민해보자.

* 프론트엔드에서의 코드: HTML/CSS/JS(TS)
  * HTML, CSS, JS(TS)를 이용해 코드 작성
  * 과거부터 HTML,CSS,JS를 합쳐서 작성하기 위한 고민을 했었음
    * jQuery, backborn, angularjs 등&#x20;
    * 점진적으로 진화하면서 React, Vue 등에서 합친 단위를 "컴포넌트"라고 부름
* 과거에는 이러한 컴포넌트가 페이지 단위로 많이 없었기 때문에 모듈화 등을 크게 고려되지 않았음
  * 비즈니스가 커지면서 "컴포넌트"를 묶고 개발 및 유지보수 할 수 있는 단위가 필요해지기 시작

#### 웹에서 컴포넌트를 공유하기 위한 다양한 고민

* Node 기반에서 Module의 체계를 구축(AMD.js, Common.js)
  * Module 단위로 응집하여 index.js 등의 중앙화를 통해 한번에 내보내는 등의 작업을 할 수 있음 (barrer index)
  * 폴더로 도메인에 대한 이름을 만들고, 폴더 단위로 역할을 부여
* NPM Library를 등록하여 사용하는 방법
  * Module 단위로 글로벌하게 Package로 가져와서 버저닝을 할 수 있다.

{% hint style="info" %}
한 프로덕트에서 함께 관리하면서도 영향도를 제거하여 생산성을 높이는것이 목표, 관리포인트 절감 및 생산성 향상
{% endhint %}

#### 어떠한 응집되는 단위를 어떻게 정의하고 운영할 것인가

* 작은 코드가 모여 커다란 도메인이 형성된다.
  * e.g) 공통으로 쓰이는 hook을 모아두는 hooks 폴더를 3년간 운영했더니 hook이 200\~300개가 생성됨
  * 고민 1) 200,300 개의 훅이 정상적으로 모든 react 버전에서 동작하는지, 모든 브라우저에서 동작하는지 어떻게 증명할지
  * 고민2) hook 단위의 중복 코드는 어떻게 관리해야하지
  * 고민3) hook에 등록되는 기준은 무엇일까
* 일정 수준을 넘으면 전문적으로 관리할 인원이 필요해지고, 지속적인 운영이 필요해짐

#### 프로덕트의 성장 플로우 살펴보기

> 신규 사업의 시작, MVP 개발

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FrbARUKkAHyzjs4ptDQQX%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.51.02.png?alt=media&amp;token=f0e383aa-0b66-47e8-9d5c-19d015ccf00e" alt=""><figcaption></figcaption></figure>

* 초기에는 서버 개발, 프론트 개발 할 것 없이 적은 인원이 마구잡이로 만듬
  * 만들고 나서 서버 프론트가 합쳐져 있다면 분리를 하여 프론트 및 서버의 전문성을 갖고 만들 수 있도록 한다.
* 이 떄 핵심 목표는 어떻게든 빠르게 개발하는 것이며, 업무 생산성이 어떻게 만들든 그렇게 저하되지 않는다.

> 사업의 확장, 기능 컨트롤을 쉽게 하기 위한 어드민 제작

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FnAQL0eHDQ7FOVocGiQN0%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.52.23.png?alt=media&amp;token=244aa6f7-1d12-42d2-b479-71a14044a7b1" alt=""><figcaption></figcaption></figure>

* 사용자형 프로덕트와 운영에 필요한 어드민 프로덕트 두 개 (혹은 이상)이 되는 시점
  * 이 떄 바로 Monorepo를 적용하기보단 각 서비스 별로 레포지토리를 다르게 하여 빠르게 개발하는 것이 목표
  * 가장 중요한 것은 회사의 생존, 생산성을 고민하기 쉽지 않음

> 신규 인원 채용으로 인한 생산성을 위한 고민, 라이브러리 개발/운영

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FEgpSfC3p67tWXPU4PcwR%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.53.47.png?alt=media&amp;token=d799315f-06e1-4d43-b7f7-2568b20eb501" alt=""><figcaption></figcaption></figure>

* 기존 인원으로 비즈니스 치는 시간도 촉박하여 생산성에 대한 고민을 하지 못하던 상황
  * 신규로 추가된 인원으로 인해 더 많은 리소스를 할애 할 수 있게 됨
  * 점진적으로 시간이 남기 시작, 생산성에 대한 고민을 할 수 있음
* 더 높은 생산성을 위해 공통의 코드를 모아서 라이브러리를 개발하고 운용하자는 결론을 내게됨

> 사업이 많은 성장과 지속된 인원의 채용으로 생산성을 논하고 코드 효율성을 생각하게 될 때

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FUwQnHn9QX8UuyoSThj3j%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.55.21.png?alt=media&amp;token=f22709a8-f15c-4a50-8669-99a71315daad" alt=""><figcaption></figcaption></figure>

* 사업의 성장, 지속된 인원의 채용은 생산성을 고려하게 만든다.
  * 인원을 뽑아도 인원이 2배 이상의 효율을 바로 내주진 않기 때문
    * 코드 복잡도와 작업량을 인원의 증가로 바로 해결되지 않고, 그것을 위한 생산성 측면 R\&R을 통해 적절하게 분리해줘야 한다.

> 회사의 사업 규모 확장으로 다양한 팀으로 쪼개지는 상황에서 전체 팀이 효율적으로 일하기 위해

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2F4dZbcPZm5kRMBQpva9LY%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.57.05.png?alt=media&amp;token=e3f3ad51-6c7c-40bb-bcd9-32d0af2ed8d0" alt=""><figcaption></figcaption></figure>

* 여러 사업이 추가되면서 팀이 추가되고, 조직개편으로 업무는 더 많아지고, 각 팀 별로 더 업무를 잘 수행하기 위해 고민하게 된다.
* 각 팀의 모든 업무를 중앙에서 효율적으로 처리하기 위한 공통 조직이 필요해진다.&#x20;

### 프로덕트가 성장하면서 따라오는 것들

> "나누는 것의 비효율"이 "유지하는 것의 비효율" 을 넘어버리는 순간

* 사업이 커질수록 다양한 사업을 담당하는 조직이 생기고, 그에 따른 프로덕트를 개발하고 운영하기 위한 조직이 붙게 된다.
* 프로덕트를 개발하고 운영하는 조직은 계속 커지며, 커지면서 분리되고 운영하던 코드를 분리시키고 인수인계 한다.
  * 이 때 인수인계 비용과 분리하기 위한 비용은 만만치 않게 발생
* 조직개편은 이러한 "나누는 것의 비효율"을 인지하지만 , "유지하는 것의 비효율"을 넘어버리는 순간이다.
  * 조직개편으로 인해 더 많은 가치를 만들어내고 더 긴 미래를 바라보게 된다.
* **만약 이때 이미 코드들이 모듈 단위로 나뉘어져있다면?**

### **모듈 기반으로 생각해야 하는 이유**

> 모듈 기반으로 생각하는 것은 "미래를 위한 필수적인 선택"

* 첫 번째: 커져가는 프로덕트에서 코드간 의존성을 줄이기 위함
* 두 번째: 공통 코드의 변경 사항이 생겨도 운영중인 코드에 영향도를 줄이기 위함
* 세 번째: 관리 포인트를 분리하기 위함

{% hint style="info" %}
이러한 목표를 달성하기 위해 점진적인 코드 응집 전략과 다양한 버저닝 정책을 고려해야 한다.
{% endhint %}

## 모듈 기반 개발 방식에 대한 이해

### 모듈 단위의 레이어 구상하기

> "비즈니스에 적합"의 의미
>
> 비즈니스의 크기 (인원, 업무, 비용 등)에 따른 적합한 수준의 코드 퀄리티

* 과한 모듈의 추상화는 컨텍스트 스위칭 비용을 크게 한다.
* 반대로 분리되지 않은 코드는 협업을 까다롭게 만든다.
* 과하지 않는, 협업에 용이한 분리된 코드를 일컫음

#### 하나의 팀이 여러 프로덕트를 운영하는 경우

* 공통 코드는 패키지화를 하지 않아도 모듈 단위로 사용하여 프로덕트에서 공통으로 쓰이는 코드를 묶어놓는 역할만 한다.
* 크게 복잡하지 않은 구성

#### 하나의 팀이 여러 모노레포를 운영하는 경우

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FcyiMXTSJpYsGwLqJW2f9%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.00.34.png?alt=media&amp;token=30587127-8628-416e-bb46-2ecdac72b5ac" alt=""><figcaption></figcaption></figure>

* 공통 코드의 레벨 자체가 별도의 수준으로 레이어가 형성됨
* 크게 복잡하지 않은 구성

#### 독립된 단위로 프로덕트를 운영하는 경우

> 복잡해지기 시작하는 아키텍처

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FUqQc9fQqmUevP8ecp3ul%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.00.25.png?alt=media&amp;token=a0051468-e6ff-4530-b585-e22753592fdc" alt=""><figcaption></figcaption></figure>

* 모노레포를 기반으로 각 팀이 사용하고 있는 상황이므로 코드베이스는 분리 되어있는게 효율적
  * 동일 레포지토리를 사용하게 될 경우 팀 별로 특화된 전략을 사용할 수 없는 문제 생김
  * 그러므로 팀 별로 레포지토리는 분리되는게 맞는 그림
* 팀 별로 코드를 가져오기 위한 방안을 고민
  * 패키지로 받을 수 있도록 제공하는 것이 가장 이상적
  * iframe 등의 방법도 있지만 비단 레이아웃만 가져오는 것이 아니기 때문

#### 수많은 팀이 여러 레포지토리 단위로 업무를 진행하는 경우

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FzXuFeVyk9aIuERdfisRU%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.02.56.png?alt=media&amp;token=09c973a2-2a07-4523-952c-7d9b7e2fd8bc" alt=""><figcaption></figcaption></figure>

* 이미 서비스를 운영한지 오래된 대기업 등에서 보이는 현상
* 여러 레포지토리를 운영하기 위한 별도의 조직이 필요
* 별도의 조직은 일원화된 채널을 통해 레포지토리의 갱신사항을 전파하는 역할을 맡음
* 조직과 모듈 레이어가 일원화가 되어야함

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FYT7hFuV7vDMVqz02ZvvE%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.04.17.png?alt=media&amp;token=e8e5c40f-f361-46f9-9813-11c9660640bc" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
어느정도 수준 (독립된 단위로 프로덕트를 운영하는 경우)까지는 조직과 무관하게 운영 가능

하지만 비즈니스가 커지고 수많은 팀이 존재하게 되면서 레이어가 조직과 더불어 함께 고민하게 되는 경우가 생긴다.
{% endhint %}

### 분리되는 코드를 운영하기 위한 프로세스 구축

#### 공통의 코드를 유지보수 하는 전담 인원의 필요성 대두

* 여러 조직으로 분화되면서 모든 팀은 중복코드를 중앙화하기 위해 노력
* 각 조직별 공통된 라이브러리가 생기고, 각각 유지보수
* 전사단위로 보면 생산성 절감이 100%된 것이 아님
* 계속 파편화되어 커지면 나중에는 합칠때 더 어려워진다.
* 그러므로 중앙화할 수 있는 라이브러리가 필요
* 그러면 라이브러리는 누가 운영?

### 공통팀 (A.K.A Core)

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FCxkciQOOw5dGmMmtIxnq%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.09.25.png?alt=media&amp;token=23dd7939-d939-4d5f-9d32-3562c325f037" alt=""><figcaption></figcaption></figure>

* 웹 프론트엔드 전사적으로 공통을 담당하는 인원 필요
  * 이를 팀으로 묶어도 되나, 전사의 프론트가 하나의 조직으로 구성되어있다면 파트나 TF도 충분할 수 있다.
  * 공통팀의 역할: 웹 프론트 전사적으로 필요한 도구를 개발
    * 지속적인 커뮤니케이션을 통해 개선사항을 듣고 반영
    * 공통팀은 공정한 업무를 진행해야하며 공통이라는 것에 매몰되지 않고 비즈니스를 놓으면 안된다.
    * 공통의 업무를 가장 큰 비즈니스를 담당하는 팀에 포함하기도 한다.

#### 공통팀이 해야하는 일

* 비즈니스를 담당하는 팀에서 공통으로 기여할 코드를 올리면 검증 및 테스트를 진행하여 라이브러리에 포함하는 역할
* 공통의 코드를 유지보수하고 테스트 등을 진행하는 역할
* 새로운 공통의 코드를 만들고 생산성을 올리는 역할
* 웹 프론트 분야 뿐만 아니라, 앱, 서버와도 협업하여 생산성을 올리기 위한 방안을 마련
* 효율적으로 일하기 위해 생산성 툴을 만들거나 업무 가이드라인을 제작하여 공유

#### 가장 중요한 것은 유기적인 프로세스의 구축

* 공통의 의미는 "**비즈니스를 빠르게 동작하도록 돕는 것**"
* 비즈니스가 제데로 안되면 공통은 존재할 이유가 없다. 오히려 비즈니스를 위해 공통의 모든 리소스를 할애해도 모자르다.
* 비즈니스를 개발하는 시간 대비 공통에서 생산성을 개선해서 올리는 비용이 더 높은 가치를 낼 때 공통은 필요하다.
  * 공통은 팀의 가치를 위해, 팀의 존속을 위해 비즈니스를 최대한 기여
* 비즈니스 개발자들의 코드와 상황을 잘 이해하며, 이해하는 상황에서 코드 생산성을 올릴 수 있도록 프로세스를 구축한다.
  * 방관자로 참여하여 비즈니스 개발자의 비효율 업무를 체크하여 추후 재발하지 않도록 가이드라인 및 툴을 개발
  * 공통의 코드를 빠르게 제작하여 프로젝트 진행 시 사용할 수 있도록 코드를 제공한다.

#### 커뮤니케이션 프로세스

<figure><img src="https://1912740209-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F3GVYdZvmqQyBVq29ebqk%2Fuploads%2FtIf67aI7dU039iGzLS3T%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202024-03-16%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2012.14.43.png?alt=media&amp;token=7d6f67d3-f02f-42c3-9b32-3563e50b378a" alt=""><figcaption></figcaption></figure>

* 바텀업 된 코드를 합치기 위한 프로세스 (MR - 템플릿으로 검증 / 테스트 프로세스 / 컴포넌트는 시각적 회귀 테스트 등)
* 탑다운으로 공통 코드를 공유하기 위한 프로세스 (Notion 채널 및 각 담당자에게 공유하기 위한 방법 고민)
* 전사 및 웹 표준안을 개발하여 전파(지원 브라우저, OS 버전 등 기준 작성)
* 버저닝이 추후 필요해진다면 버저닝을 공유하는 슬랙 채널이나 알람을 제공
  * 프로젝트 별 라이브러리 버전 리포트 등을 제공해주는 것도 방법 (레포지토리의 package.json 읽기)
