Skip to content

0907

순환 참조를 해결하는 방법

  • register에 utils를 두고 login에서 register를 참조하는 패턴을 사용하다 보면 언젠가 순환 참조가 발생할 지도 모른다.
  • 왜냐하면 자바스크립트의 모듈 로딩 순서는 결정적이다. 이 때 결정적이라는 의미는 같은 조건에서 항상 같은 결과가 나온다는 뜻이다.
    • 즉 내가 main.js에서 아래와 같이 모듈을 불러오고 있다면,
js
import './a.js';  
import './b.js'
  • 항상 a 모듈을 불러온 후에 b 모듈을 불러오는 순서로 로딩이 된다. 언제는 b 불러 온 다음에 a를 불러오고 이러지 않는다.
  • 즉, 내가 로그인에다가 회원인지 비회원인지 여부를 따지기 위해 register를 참조하고 있고 register에다 로그인 한 회원인지 아닌지를 따지기 위해 login을 참조하고 있다면 이는 모듈의 참조 형식이 순환되기 때문에 순환참조 문제가 발생한다는거다. 그래서 보통 회원인지, 로그인한 유저인지를 판단하는, 사용자 인증과 같은 로직은 유저라는 피처를 따로 둔 다음에 거기서 세션이든 쿠키로 이를 감지하고 로그인과 유저에서 각각 불러오는거다.
  • 그래서 이를 해결하는 방법은, 공용으로 사용될 shared 디렉토리를 둬서 하위에 utils를 둔 다음 login과 register에서 불러오는 패턴이 적절하다.
  • 근데 이렇게 사용하다 보면 shared 디렉토리가 너무 비대해지지 않을까? 라는 생각이 들었다. 즉 다른 방법으론 해결할 수 없을까?
    • 그래서 등장한게 FSD 아키텍처 인 듯하다. 왜냐면 FSD는 계층적으로 구조가 나뉘어져 있기 때문에 하위 계층은 상위 계층의 모듈을 불러올 수 없다. 그리고 계층적으로 구조가 나눠져있다보니 shared 디렉토리가 비대해질거를 걱정할 일도 줄어든다.
    • 그치만 FSD를 익히는건 쉽지 않다보니,,, 개발자들 간의 멘탈 모델에도 집중하면서 아키텍처 구조를 적절히 나누는 습관이 필요할 것 같다 !ㅅ!
  • 또 다른 해결 방법으로는 의존성 주입 패턴과 메디터 패턴이라는 것이 있는데 솔직히 아무리 봐도 shared 디렉토리를 두는 패턴과 다 비슷비슷한 것 같다는 생각이 들었다.
  • 근데 shared 디렉토리는 고정된 구현체를 갖는 반면 디자인 패턴들은 미리 교체가 가능한 구현체들을 만들어두고 사용 하는 것이기에 확장성과 유연성 측면에서 차이가 나는 듯 하다.
  • 아니 근데 여기서 또 들었던 생각이, shared에서도 미리 여러 구현체들을 만들어둘 수 있지 않는가? 라는 생각이다. 그럼 진짜 차이는 뭘까? 하고 클로드한테 물어봤다. 그랬더니 의존성의 명시적 차이점이 가장 큰 차이라고 한다. 기술적인 차이 보단 철학적인 관점에서의 차이라는데.. 어렵다
js
// DI - 의존성이 명확히 드러남  
class LoginController {  
  constructor(userService, emailService, logger) { // 뭘 필요로 하는지 명확  
    // ...  
  }  
}

// Shared - 내부에서 import, 외부에서 파악하기 어려움  
class LoginController {  
  constructor() {  
    // 내부에서 뭘 import하는지 코드를 열어봐야 알 수 있음  
  }  
}

참고 자료