Angular 의존성 해결의 흐름

6357 단어 Angular
Angular는 DI(Dependency Injection)의 기구를 갖추고 있어 constructor 등을 통해서 서비스 등을 컴포넌트에 주입할 수 있습니다.
서비스의 @Injectable 데코레이터로 providedIn: 'root' 올거야.

주입물은 도대체 어디에서 오는가



동작을 확인하기 위해 이런 느낌의 샘플을 준비합니다.
AppModule ─────┐
│ AppComponent │
└─┬────────────┘
  └ ParentModule ─────┐
    │ ParentComponent │
    └─┬───────────────┘
      └ ChildModule ─────┐
        │ ChildComponent │
        └────────────────┘

각 모듈, 각 컴퍼넌트에는 각각 프로바이더를 가지게 해, 주입물의 출자가 알 수 있도록(듯이) 합니다.

app.module.ts
@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, ParentModule],
  providers: [{ provide: AnyService, useValue: { injectLevel: 'root' } }],
  bootstrap: [AppComponent]
})
export class AppModule {}

app.component.ts
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  providers: [
    { provide: AnyService, useValue: { injectLevel: 'root component' } }
  ]
})
export class AppComponent {
  constructor(public anyService: AnyService) {}
}

각 컴퍼넌트에서는 constructor 로 anyService 를 주입해 injectLevel (서비스가 제공되는 계층)를 View 에 표시시킵니다.

app.component.html
<div>root: {{ anyService.injectLevel }}</div>
<app-parent></app-parent>

parent.component.html
<div>parent: {{ anyService.injectLevel }}</div>
<app-child></app-child>

결과는 다음과 같습니다.


당연하네요. 자신의 컴퍼넌트 클래스에서 원하는 것이 제공되고 있기 때문에, 물론 그대로 주입되고 있습니다.
그럼, ChildComponent -> ParentComponent -> AppComponent 와 차례로 컴퍼넌트 클래스의 프로바이더를 삭제해 가면 어떻게 되겠지요.







자신의 컴퍼넌트 클래스내에 주입 대상이 제공되어 있지 않은 경우, Angular는 부모 클래스에 거슬러 공급자를 찾습니다.
루트 컴포넌트(여기서는 AppComponent)로 거슬러 올라가고, 찾을 수 없다면 루트 모듈(여기서는 AppModule)을 찾으러 간다.

그렇다면 루트 모듈에도 공급자가 없으면 Angular는 오류를 반환합니까?
한층 더 프로바이더를 삭제해 가면, 다음과 같이 됩니다.





root 모듈에 프로바이더가 없었던 경우, Angular는 root 모듈의 imports (을)를 따라 더 프로바이더를 찾습니다.
루트 모듈이 출발점이기 때문에 ParentModule -> ChildModule 의 순서가 되고 있습니다.
모든 모듈을 스캔하여 공급자를 찾을 수 없으면 NullInjector가 오류를 반환합니다.



요약



Angular가 DI를 요구한 클래스에서 출발하여 의존성을 해결해 나가는 흐름을 쫓았습니다.
  • DI를 요구한 클래스 자신이 프로바이더를 가지고 있는 경우는, 그것을 우선한다
  • 자신이 공급자가없는 경우 조상을 따라 공급자를 찾습니다.
  • 루트 모듈에 도달하면 imports 모듈을 따라 공급자를 찾습니다.

    프로바이더의 위치를 ​​고안하는 것으로, DI 토큰(여기에서는 AnyService 클래스)이 동일해도 완전히 다른 것을 주입시키거나, 주입 가능한 범위를 제한하거나 할 수 있습니다.
    하지만 특별한 이유가 없으면 providedIn: 'root' 로 좋지 않을까 개인적으로는 생각합니다.
  • 좋은 웹페이지 즐겨찾기