cd ../
Frontend·2026-01-17·5 min read·# entry/007

Module Federation의 Shared 의존성 관리

Module Federation의 의존성 Singleton과 버전관리 성능이슈는 어떻게 이뤄질까?

Module Federation(이하 MF)을 도입할 때 가장 먼저 마주하는 벽은 의존성(Dependency) 관리 입니다.

Host와 Remote가 서로 다른 버전의 라이브러리를 사용하고 있다면 MF는 어떤 결정을 내릴까요? "React 18.3.1(Host) 위에 React 18.2.0(Remote)을 띄우는 상황" 을 가정하고 시뮬레이션을 돌려봅시다.

1. Singleton: true 가 의미하는 바

package.json이나 webpack.config.js에서 singleton: true를 설정한다는 것은 다음과 같은 강력한 선언입니다.

"이 라이브러리는 브라우저 탭 전체에서 **딱 하나(Single Instance)**만 존재해야 해!"

React는 내부적으로 전역 상태Hooks 로직을 관리합니다. 만약 한 페이지에 두 개의 React 인스턴스가 로드되면 다음과 같은 치명적인 문제가 발생합니다.

Multiple React Instance Error
  • Context 손실: Host의 Provider가 Remote의 Consumer에게 닿지 않습니다.
  • Hooks 에러: "Invalid hook call" 에러가 발생하며 앱이 셧다운 됩니다.

2. 의존성 해결 알고리즘 (Resolution)

singleton: true가 설정되어 있을 때, MF는 "새로운 의존성 다운로드"를 극도로 꺼리는 모드로 진입합니다.

Host(18.3.1)가 이미 로드된 상태에서 Remote(18.2.0)가 진입할 때의 판단 로직은 다음과 같습니다.

1

1. 검색 (Discovery)

MF 런타임이 질문합니다. "누가 이미 React를 로드했나?"


👉 Host가 이미 18.3.1 버전을 로드해서 들고 있음.

2

2. 비교 (Semver Check)

"Remote 너는 무슨 버전을 원해?"


👉 Remote: "나는 18.2.0이 필요해."

MF는 유의적 버전(Semver) 규칙에 따라 호환성을 체크합니다.

  • Major: 18 == 18 (동일)
  • Minor: 3(Host) >= 2(Remote) (상위 호환)

결론: 18.3.1은 18.2.0의 기능을 모두 포함하므로 호환된다.

3

3. 결정 (Decision)

"굳이 18.2.0을 또 받을 필요 없다. Host가 가진 18.3.1을 같이 쓰자!"


👉 네트워크 요청을 아끼고 메모리를 절약합니다.


3. 예외 상황: "나는 따로 쓸래" (Singleton: false)

만약 Host는 "하나만 쓰자(true)"고 하는데, Remote가 "나는 내 거 따로 쓸래(false)"라고 설정하면 어떻게 될까요?

Remote 우선의 법칙

의존성을 소비하는 쪽(Remote)의 설정이 우선시됩니다.

동작 메커니즘

  1. Host 초기화: singleton: true 선언. "웬만하면 내 거 써라."
  2. Remote 초기화: singleton: false 선언.
  3. 판단: MF는 Remote의 의사를 존중하여, 호환되는 버전이 있더라도 Remote용 React 18.2.0을 별도로 다운로드하여 실행합니다. (물론 React 같은 라이브러리는 이렇게 하면 에러가 나겠지만, lodash 같은 유틸리티는 가능합니다.)

4. shared에 명시하지 않는다면?

webpack.config.jsshared 옵션에 라이브러리를 아예 적지 않는 경우는 어떨까요? 이는 MF의 버전 관리 및 공유 기능을 사용하지 않겠다는 의미입니다.

// webpack.config.js
new ModuleFederationPlugin({
  name: 'app1',
  // shared에 lodash를 넣지 않음
  shared: { 
    react: { singleton: true }, 
    // lodash 생략 
  },
});

중복 로드는 무조건 나쁠까?

반드시 그렇지는 않습니다. "격리""최적화" 관점에서 장단점이 있습니다.

공유하지 않을 때의 장점 (Isolation)
  • 안전성: 버전 충돌 걱정이 없습니다. Remote가 구형 버전을 쓰든 말든 Host는 영향을 받지 않습니다.
  • Tree Shaking 효율: shared로 묶으면 웹팩은 라이브러리 전체를 공유 덩어리로 만드는 경향이 있습니다. 반면, 공유하지 않으면 각 앱이 자기가 쓰는 함수만 쏙쏙 뽑아서(Tree Shaking) 번들링하므로, 사이즈가 작은 라이브러리는 공유하지 않는 게 오히려 용량이 작을 수 있습니다.
공유하지 않을 때의 단점 (Duplication)
  • 네트워크 낭비: React, ReactDOM 처럼 거대한 라이브러리를 중복해서 받으면 초기 로딩 속도가 느려집니다.
  • 메모리 낭비: 브라우저가 똑같은 코드를 두 번 해석하고 실행해야 합니다.
Strategy
  • Core 라이브러리 (React, Vue, Router): 반드시 shared + singleton: true로 관리하세요.
  • 유틸리티 (Lodash, Date-fns): 버전 민감도가 낮고 사이즈가 작다면 shared에서 빼서 각자 번들링하는 것이 더 효율적일 수 있습니다.