NgModule 메타 데이터
뷰에서 사용할 로직은 컴포넌트에 정의한다.(뷰 로직은 컴포넌트에, 비지니스 로직은 서비스 또는 effect에)
@Component 데코레이터를 붙이기 전까지는 컴포넌트로 등록되지 않는다.
데코레이터의 providers 메타데이터는 컴포넌트 생성시, 의존성으로 주입되는 서비스의 프로바이더를 지정한다.
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}
파이프
파이프는 원래값을 입력받고 새로운 형식의 값을 반환하는 함수에 @Pipe
데코레이터를 사용해서 Angular에 등록한다.
사용법
<!-- 기본 형식: 'Jun 15, 2015'-->
<p>Today is {{today | date}}</p>
<!-- fullDate 형식: 'Monday, June 15, 2015'-->
<p>The date is {{today | date:'fullDate'}}</p>
디렉티브
템플릿이 렌더링 될 때 디렉티브가 있으면 DOM의 모양을 디렉티브의 로직에 따라 변형시키며, 디렉티브는 클래스의 @Directive()
데코레이터를 사용해서 정의한다.
@Copmonent()
도 문법적으로는 디렉티브의 한 종류이다. 커스텀 한 것.
구조 디렉티브와 어브리뷰트 디렉티브로 나누어 진다.
구조 디렉티브: DOM 엘리먼트를 추가하거나 제거, 치환하는 용도로 사용한다.
<li *ngFor="let hero of heroes"></li>
<app-hero-detail *ngIf="selectedHero"></app-hero-detail>
어트리뷰트 디렉티브: 이미 존재하는 엘리먼트의 모양이나 동작을 변형한다.(HTML 어트리뷰트처럼 보인다.)
<input [(ngModel)]="hero.name">
ngModel 디렉티브는 양방향 바인딩에 사용되며, 어트리뷰트 디렉티브의 한 종류이다.
서비스와 DI
컴포넌트에는 해당 뷰에서 일어나는 사용자의 행동에 관련된 로직만 둔다.
의존성 주입 (DI)
서비스와 같은 객체를 Angular 프레임워크와 묶는 개념. 컴포넌트가 생성될 때 자유롭게 주입할 수 있다. 서비스를 컴포넌트에 의존성으로 주입하면 컴포넌트는 서비스 클래스에 접근할 수 있다.
Angular는 애플리케이션을 부트스트랩할 때 애플리케이션 전역 범위에 동작하는 인젝터를 생성한다.
인젝터는 의존성 객체의 인스턴스를 생성하고, 이 인스턴스를 나중에 재사용할 수 있도록 컨테이너에서 관리한다.
프로바이더는 의존성으로 주입되는 객체를 어떻게 만드는지 정의한 것이다.
애플리케이션에 필요한 의존성 객체가 있다면, 이 의존성 객체의 프로바이더를 인젝터에 등록해야 한다. 그러면 인젝터가 이 프로바이더를 사용해서 의존성 객체의 인스턴스를 생성한다. 서비스의 경우에는 보통 서비스 클래스가 그 자체로 서비스 프로바이더의 역할을 한다.
의존성 객체가 서비스만 가능한 것은 아니다. 함수나 기본 자료형도 의존성 객체가 될 수 있다.
Angular가 컴포넌트 클래스의 인스턴스를 새로 만들 때, 컴포넌트 생성자에 지정된 타입을 보고 이 컴포넌트에 서비스와 같은 의존성이 있는지 확인한다.
// HeroService가 의존성으로 주입되어야 한다.
constructor(private service: HeroService) { }
컴포넌트에 서비스가 주입되어야 한다는 것을 Angular가 확인하면, 이 서비스의 인스턴스가 인젝터에 이미 있는지 먼저 확인한다. 이 때 인스턴스가 아직 생성되지 않았으면 프로바이더에 등록된 방법으로 객체의 인스턴스를 생성하고, 인젝터에 이 인스턴스를 추가한 후에 Angular로 전달한다.
그리고 컴포넌트에 필요한 서비스가 모두 준비되고 나면 Angular가 컴포넌트 생성자를 실행하면서 이 서비스들을 인자로 전달한다.
서비스 프로바이더 등록하기
서비스를 사용하려면 프로바이더를 어디엔가 등록해야 하는데, 두가지 방법이 있다.
서비스 메타데이터(@Injectable()
데코레이터)에 자신의 프로바이더를 직접 등록하는 방법
@NgModule()
이나 @Component()
메타데이터에 프로바이더를 등록하고 하위 계층에서 이 프로바이더를 이용하는 방법
Angular CLI로 ng generate service
명령을 실행하면 서비스 클래스를 생성하면서 @Injectable()
데코레이터를 사용해서 이 서비스를 최상위 인젝터에 등록한다.
@Injectable({
providedIn: 'root'
})
서비스 프로바이더를 최상위 인젝터에 등록하면, 해당 Service의 인스턴스는 애플리케이션 전역에 딱 하나만 생성되며, 이 의존성을 주입하는 컴포넌트가 모두 같은 인스턴스를 공유한다.
그리고 @Injectable()
메타데이터를 사용해서 프로바이더를 등록하면, 애플리케이션 배포 단계에서 코드를 최적화하면서 이 서비스가 실제로 사용되는지 확인하고 사용되지 않으면 최종 결과물에서 제외시킬 수도 있다.
서비스 프로바이더를 특정 NgModule에 등록하면, 이 NgModule 범위에 있는 컴포넌트만 같은 서비스 인스턴스를 공유한다. 이렇게 등록하려면 @NgModule()
데코레이터의 providers 프로퍼티를 다음과 같이 지정해야한다.
@NgModule({
providers: [
BackendService,
Logger
],
...
})
컴포넌트 계층에 프로바이더를 지정하면 해당 컴포넌트의 인스턴스가 생성될 때마다 의존성 객체에 대해 새로운 인스턴스를 생성한다. 컴포넌트 계층에 서비스 프로바이더를 등록하려면 @Component()
메타데이터의 providers 프로퍼티를 다음과 같이 지정한다.
@Component({
selector: 'app-hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
개인적인 생각. service 관련 규칙이 참 뭐가 많다… 특히 프로바이더 등록하는 부분.. 방식이 여러개라 헷갈리기도 하고, 제대로 공부해서 사용하지 않으면 잘못된 코드를 생산할 가능성이 높을 것 같다. 왜 앵귤러에서 이렇게 만들었는지는 모르겠지만, 우리는 앵귤러를 사용하기에 빡시게 공부하고 정확한 사용법을 통해 어플리케이션을 만들어야 한다.💪🏽
반응형 프로그래밍
내가 정말정말 * 100 공부하고 싶은 부분이다. 다른 프레임워크와 달리 앵귤러의 장점 중 하나를 뽑자면, 애플리케이션 전체적으로 리액티브하게 만들 수 있다는 것이다..! 공부해서 정말 리액티브한 애플리케이션을 만들고 싶다.🙏
클라이언트-서버통신
개발 지원
개발, 빌드, 배포 환경설정