안녕하세요. 꼬동입니다.
오랜만이군요. 저는 요새 새로운 직장으로 '뉴 커리어'를 시작하며 살고 있습니다.
원하는 일, 업무 환경, 기업이다 보니 출근 길이 예전처럼 힘들진 않네요 !
그렇게 공부 중 forChild() / forRoot()라는 친구들을 만났습니다.
이 친구들에 대해서 알아보도록 합시다.
우선 얘들이 왜 쓰이는지 부터 알아봅시다.
서비스 프로바이더가 중복 등록이 될 경우가 있습니다.
서로 다른 모듈에서 같은 서비스의 인스턴스를 생성하는 경우인데요, 이렇게 되는 경우 더 이상 싱글턴이 아니게 됩니다.
그렇기 때문에 서비스를 싱글턴으로 유지해야하는 필요성이 있는데, 아래와 같은 해결 방법이 있습니다.
- 서비스를 모듈에 직접 등록하지말고, providedIn 문법을 쓰자.
- 모듈마다 서비스를 분리하자.
- 모듈에 forRoot()와 forChild() 메소드를 정의하자.
// greeting.module.ts
static forRoot(config: UserServiceConfig): ModuleWithProviders<GreetingModule> {
return {
// GreetingModule 클래스를 의미
ngModule: GreetingModule,
// 인자로 받은 객체로 설정된 프로바이더를 의미
providers: [
{ provide: UserServiceConfig, useValue: config }
]
}
}
// app.module.ts
@NgModule({
imports: [
...
GreetingModule.forRoot({userName:'Miss Marple'})
...
]
})
이런식으로요.
서비스 프로바이딩하는 주체가 모듈이 아닌 forRoot() 메소드로 이동하게 되면서, AppModule에서만 프로바이딩을 하게 되었습니다.
이렇게 된다면, 다른 모듈이 UserServiceConfig 토큰으로 인스턴스를 찾는다고 했을 때, App 모듈 인젝터에서 값을 찾게 되겠죠.
여기까진 오케이
그러면 forChild()는 무엇일까요?
해당 메소드에 대해선 제가 부족해서 끙끙 거리고 있을 때, 제 훌륭한 동료이자 교수님이신 해당 블로거님이 알려주셨습니다.
많은 사랑 해주세요.
가르침을 받은 내용은 아래와 같습니다.
rootModule에서는 forRoot를 이용해서 모듈을 import하고, rootModule 이외 모듈에서는 forChild 함수를 이용해서 모듈을 import 해서 service가 반복해서 생성되는 것을 막을 수 있다.
무슨 소리인지 모르겠죠?
코드로 봅시다.
// AModule.ts
@NgModule()
export class AModule{
static forRoot(): ModuleWithProviders<AModule>{
return {
ngModule:AModule,
providers:[
BService,AService // 여기에는 서비스가 생성됩니다.
]
}
}
static forChild(): ModuleWithProviders<>{
return {
ngModule:AModule
providers : [] // providers가 없어 자식에는 AService, BService 서비스가 생성되지 않는다.
}
}
}
상황
=> AppModule에서 AModule을 사용하고 지연 로드하는 ContentModule도 AModule을 쓰며, AModule의 AService와 BService를 싱글톤으로 유지하고 싶다.
해당 상황을 이뤄내기 위해서 저흰 일단, forRoot()를 통해서 AModule.forRoot()를 AppModule에 등록을 할 수 있습니다. 여기까지는 싱글톤 완성
ContentModule에서도 AModule을 끌어오면, ContentModule도 AModule을 생성하지만, forChild를 사용해서 AService, BService를 생성 안하도록 끌고옵시다.
보시다시피 forChild의 경우엔 providers가 빠져있으니, RootModule에서 service를 끌어와서 Injection이 가능해집니다.
그래서 NgModule 메타데이터에 providers가 없으면 forChild처럼 동작할 수 있겠죠.
참고 사이트
https://blog.toyseed.tech/2020/09/09/angular-module/
추신
forRoot() 메소드의 경우엔 AppModule에만 사용하는 것은 아닙니다.
이름도 자유자제로 정해도 됩니다. 정의해서 사용하는 메소드이니까요. 물론 RouterModule과 같이 들고와서 사용해야하는건 지켜서 사용해야겠죠.
즉, forRoot() / forChild() 모두 어떻게 NgModule을 꽂고 어떻게 providing을 해야하는지를 중점으로 생각하다가 나온 개념이기에, 사용 방법을 외우기 보단, 개념을 이해하는 방향으로 공부하시면 될 거 같습니다.
이상 forRoot() / forChild() 당신은 누구신가요? 였습니다. ^_^
'Web + APP > Angular' 카테고리의 다른 글
RxJS가 해결하려고 했던 문제 1 (0) | 2021.05.19 |
---|---|
RxJS를 시작하기 전에 (0) | 2021.05.19 |
Angular Large List 최적화 (Angular CDK) (0) | 2021.04.20 |
Angular Tutorial with Docs - 2 (0) | 2021.04.16 |
Angular Tutorial with Docs - 1 (3) | 2021.04.16 |