Angular2 Core Module

핵심 모듈은 Angular 애플리케이션 관점에서 핵심이 되는 모듈로, 애플리케이션 루트 모듈에 한번 설정함으로써 전역에서 사용할 수 있는 모듈을 말한다. 루트 모듈에 등록됐다는 것은 애플리케이션이 시작될 때 처음 한 번만 호출해서 전역으로 사용하겠다는 의미이다.

대표적인 예로 타이틀컴포넌트가 있다.

- title component

애플리케이션 실행 시 호출되어 애플리케이션이 실행되는 동안 항상 사용된다.

아래의 예제에서는 컴포넌트와 서비스를 핵심 모듈로 등록해서 핵심 모듈을 구성해 보겠다.

핵심 모듈에 등록할 title component 는 다음과 같이 정의하며 편의상 대부분 app/core 디렉토리에 정의한다.

import { Component, Input } from '@angular/core';
import { UserService } from '../core/user.service';

@Component({
  selector: 'app-title',
  template: `
  <h1 highlight></h1>
  by <b></b>`
})
export class TitleComponent {
  @Input() title = '';
  user = '';

  constructor(userService: UserService) {
    this.user = userService.nickName;
  }
}

===> title.component.ts

이이서 핵심 모듈에 등록할 UserService 는 다음과 같다.

import { Injectable, Optional } from '@angular/core';

export class UserServiceConfig {
  nickName = '';
}

@Injectable()
export class UserService {
  private _nickName = '';

  constructor( @Optional() config: UserServiceConfig) {
    if (config) { this._nickName = config.nickName; }
  }

  get nickName() {
    return this._nickName;
  }

===> user.service.ts

Userservice 서비스는 애플리케이션 루트 모듈에 등록되기 떄문에 싱글턴으로 존재하며, 전역 서비스로 사용이 된다.

위의 생성자에서 @Optional 장식자를 이용해 주입객체가 있다면, 해당 객체를 받게하고, 없다면 null 값을 반환한다.

그리고 주입 객체에 대한 조건문 검사를 통해 객체가 있다면 서비스에 선언된 _nickName 프로퍼티를 갱신한다.

마지막으로 핵심 모듈 설정은 다음과 같이 한다.

import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule } from '@angular/common';

import { TitleComponent } from './title.component';
import { UserService } from './user.service';
import { UserServiceConfig } from './user.service';

@NgModule({
  imports: [CommonModule],
  declarations: [TitleComponent],
  exports: [TitleComponent],
  providers: [UserService]
})
export class CoreModule {
  constructor( @Optional() @SkipSelf() parentModule: CoreModule) {
    if (parentModule) {
      throw new Error(
        'CoreModule이 이미 로딩되었습니다.');
    }
  }

  static forRoot(config: UserServiceConfig): ModuleWithProviders {
    return {
      ngModule: CoreModule,
      providers: [
        { provide: UserServiceConfig, useValue: config }
      ]
    };
  }
}

===> core-module.ts

핵심 모듈을 애플리케이션 루트 모듈에 추가하기 위해 @NgModule 설정에서 TitleComponent 를 declarations에 선언하고 다시 외부로 노출하도록 exports에 선언하였다.

생성자에서는 핵심 모듈인 자기 자신을 호출하여 부모 주입기에 핵심 모듈이 이미 생성되어 있는지 검사한다.

부모 주입기에 대한 의존성을 확인하기 위해 @SkipSelf 장식자를 이용하며, 부모 주입기에 객체 ( 자기자신 ) 이 존재하는지 확인 후 존재하면 해당 객체를 받기 위해 @Optional 장식자를 이용해 주입받는다

@Optional 장식자는 객체 존재시 해당 객체를 전달하고, 없다면 null 을 전달한다.

마지막으로 해당 핵심 모듈 설정을 전부 작성하였으면 export 로 노출 시킨 후 이를 AppRoot 모듈에 임포트 한다.

...
import { CoreModule } from './core/core.module';
...

@NgModule({
  imports: [
	 ...,
    CoreModule.forRoot({nickName: 'Happy'}),
    ...
  ],
	...
})
export class AppModule { }

===> app-routing.module.ts

forRoot 에 선언된 값 제공자를 받아 설정하기 위해 CoreModule.forRoot() 메서드를 호출해 값 제공자에 매개변수로 값을 전달한다.

이제 해당 핵심 모듈은 전역에서 사용 가능하게 등록이 되었다.

import { Component } from '@angular/core';

@Component({
  selector: 'core-test',
  template: `
  <app-title [title]="title"></app-title>`
})
export class CoreTestComponent {

  title = '반갑습니다! Core Module!';

}

===> core-test.component.ts

테스트 컴포넌트는 루트 라우팅 모듈에 다음과 같이 등록한다.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
...
import { CoreTestComponent } from './core-test/core-test.component';

const appRoutes: Routes = [
  ...,
  { path: 'core-test', component: CoreTestComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(appRoutes)],
  exports: [RouterModule]
})
export class AppRoutingModule {}

===> app-routing.module.ts

테스트 컴포넌트에 대한 라우터 설정이 끝났고, http://localhost:4200/core-test 로 접속하면 다음과 같이 테스트 컴포넌트에 추가한 타이틀 컴포넌트가 실행된다.

반갑습니다! Core Module!

by Happy