320x100
320x100

순환참조

: 서로를 참조하는 모듈끼리 서로 호출하는 타이밍과 서로 메모리에 로드되는 타이밍이 틀리면서 

  호출하고자 하는 모듈이 undefined가 되는 현상

 

 

 

발생 원인

: 프로그램의 시작점인 index.js에서 A 모듈을 참조하고 호출

: A 모듈은 B 모듈을 참조하고 호출

: B 모듈에서도 A 모듈을 참조하고 호출

 

 

 

 

발생 과정

1) A 모듈의 require(B모듈)을 읽으면서 코드 실행을 멈춘 뒤 B 모듈을 실행
2) B 모듈이 실행 되면서 require(A모듈) 부분에서 코드 실행을 멈춘 뒤 A 모듈을 실행
3) A 그룹 모듈이 실행 되면서 require(B모듈) 부분에서 코드 실행을 멈춘 뒤 B 모듈을 실행
4) B 모듈은 실행중 멈춘 상태이기 때문에 더 이상의 실행을 할 수 없어, module.exports의 기본 객체인 {}를 반환
5) A 모듈의 B 모듈 함수 호출 부분에서 {}를 호출하게 됨
6) B 모듈에서는 이미 정의 된 A 모듈의 module.exports를 할당 받아 코드가 실행됨

 

 


순환참조 해결 방법
- 지연선언
: 참조하는 모듈을 module.exports 보다 나중에 선언
: 순서 변경으로 인해 다른 곳에서 오류가 발생할 수 있음

- exports의 사용
: 각 모듈인 JavaScript 파일은 하나의 module.exports를 가지는데 기본적으로 {}를 가짐
: 모듈내에서 module.exports = { ... }를 하는 것은 module.exports를 재정의 하는 것임
: 이로인해 모듈을 require() 하면 양쪽 모듈의 실행이 끝나고나서 정상적인 객체가 반환됨
: Object.assign을 통해 module.exports를 하면 {}인 module.exports에 함수들을 복사하게 되면서 정상 작동
: 모듈이 다 로드되고나서 수행하던 module.exports에 대한 정의를 

  Object.assign을 통해 모듈 내의 함수들을 한 번 더 읽음으로써 정의 

A 모듈의 파일 맨 하단 module.exports
Object.assign(module.exports, { '모듈a', '모듈b' })


B 모듈의 파일 맨 하단 module.exports
Object.assign(module.exports, { '모듈c', '모듈d' })

 

- 내부 모듈 패턴 사용

: 모든 모듈을 통합하는 하나의 파일을 생성하고 (ex) inner.js), index.js에서 해당 파일을 로드

: 모든 모듈들은 innder.js를 require하여 각 모듈간 필요한 함수 호출

 

※ 참조

: https://github.com/mobxjs/mobx/commit/e7f32aa0c2f6295b84270587285ab793b52d8643

 

To single module import · mobxjs/mobx@e7f32aa

Show file tree Hide file tree Showing 43 changed files with 432 additions and 286 deletions.

github.com

 

 

 

 

정리

 가장 좋은 방법은 순환 참조 구조를 없에는 것이다.

정 없에기 힘들다면 내부 모듈 패턴을 사용하여 한꺼번에 모든 모듈을 로드하고 불러내는 방법을 사용하는 것이 

가장 좋은 방법인 것 같다. 메모리 차지에 얼마나 영향이 있는지는 좀 더 알아봐야할 것 같다.

 

 

 

 

 

Refference

 

The Curious Case of Circular Dependencies in Node

Reasoning with what happens and how to solve for it

medium.com

 

Modules Node.js undefined Manual & Documentation

Modules# Stability: 5 - Locked Node has a simple module loading system. In Node, files and modules are in one-to-one correspondence. As an example, foo.js loads the module circle.js in the same directory. The contents of foo.js: var circle = require('./cir

nodejs.sideeffect.kr

 

Node.js의 순환 의존성 :: Outsider's Dev Story

코드를 모듈화해서 작성하다 보면 서로 간에 의존성을 갖게 되는데 이러다 보면 순환 의존성을 가질 수 있다. A 파일이 B를 참조하는데 B 파일이 다시 A 파일을 참조할 수 있고 좀 더 복잡하게는

blog.outsider.ne.kr

300x250
728x90