Web

NestJS : 순환 참조

필립 2024. 8. 12. 09:58

현재 진행하고 있는 프로젝트에서 소켓을 이용한 실시간 채팅을 구현하였습니다. 

구현 과정에서 여러가지 문제들을 겪었고 그 중 하나로 순환 참조에 대해 작성해보겠습니다. 

 

순환참조

순환 종속성은 두 클래스가 서로 종속될 때 발생합니다. 예를 들어 클래스 A에는 클래스 B가 필요하고 클래스 B에도 클래스 A가 필요합니다. 모듈 간 및 공급자 간에 중첩에서 순환 종속성이 발생할 수 있습니다.
가능한 경우 순환 종속성을 피해야 하지만 항상 그렇게 할 수는 없습니다. 이러한 경우 Nest는 두 가지 방법으로 공급자 간의 순환 종속성을 해결할 수 있습니다. 이 장에서는 정방향 참조를 하나의 기술로 사용하고 ModuleRef 클래스를 사용하여 DI 컨테이너에서 제공자 인스턴스를 검색하는 다른 기술을 설명합니다.
또한 모듈 간의 순환 종속성을 해결하는 방법도 설명합니다.

NestJS 공식문서 : https://docs.nestjs.com/fundamentals/circular-dependency#moduleref-class-alternative

 

순환참조란 두 개 이상의 모듈 혹은 프로바이더가 서로를 참조할 때 발생합니다. 즉, 모듈 A가 모듈 B를 참조하고 다시 모듈 B가 모듈 A를 참조할 때 발생하는 문제입니다. 

 

현재 프로젝트에서 순환참조는 하나의 모듈에서 2개의 프로바이더가 서로 참조하게 되며 발생하고 있습니다. 

ChatRoom 모듈
ChatRoom 게이트웨이, forwardRef 사용
ChatRoom 서비스

게이트웨이와 서비스가 서로 참조하게 된 건 채팅룸과 관련된 기능 중에서 순서가 어긋나는 경우가 있기 때문입니다. 

 

1. Controller API 요청 -> Service 비즈니스 로직 -> Gateway를 통한 브로드캐스트 -> 클라이언트 

2. 클라이언트가 소켓 서버로 메세지 -> Gateway에서 수신 -> Service 호출하여 비즈니스 로직 -> 클라이언트 

 

시작점이 API 요청인지, 클라이언트의 소켓 메시지인지에 따라 Gateway와 Service 간의 호출 순서가 바뀌게 됩니다. 특히, 채팅방의 생성은 다른 모듈에서 시작되기 때문에 참조 순서가 복잡하게 얽혀있습니다. 이로 인해 Service와 Gateway가 서로를 호출하며 순환 종속성이 발생했고 현재는 forwardRef() 함수를 사용하여 문제를 해결한 상태입니다. 

 

하지만 이는 근본적인 해결책은 아닙니다. forwardRef()를 사용하면 모듈 간 결합도가 높아져 독립성이 떨어지며, 이는 모듈의 재사용성, 확장성, 유지보수성을 저하시킬 수 있습니다. 결국, forwardRef()는 임시적인 해결책일 뿐, 사용을 지양해야 합니다.

 

좀 더 효율적인 구조를 고민하고 재구조화한 후, 관련 글을 다시 작성하도록 하겠습니다.