ARCHITECTURE OVERVIEW
Angular 앱의 기본 요소
Angular는 HTML와 JavaScript 또는 JavaScript로 컴파일 되는 TypeScript와 같은 언어로 클라이언트 앱을 만드는 프레임워크이다.
프레임워크는 몇몇은 코어, 몇몇은 선택적으로 사용가능한 라이브러리들로 이뤄져 있다.
Angular 마크업이 있는 HTML템플릿과 템플릿을 관리하는 컴포넌트 클래스, 서비스의 추가적인 앱 로직, 컴포넌트와 서비스를 포함하고 있는 모
듈로 Angular 앱을 작성한다.
(Angular 앱은 템플릿, 컴포넌트, 서비스 그리고 모듈로 이뤄져 있다.)
root 모듈을 부트스트랩해 앱을 실행한다. Angular은 브라우저에 앱의 콘텐츠를 보여주고 사용자와 상호작용 한다.
물론 이 것 이외의 내용도 있다. 자세한 내용은 이 문서에서 다룰 것이다. 지금은 큰 그림에 주목하자.
구조에 대한 그림은 Angular 앱의 8개의 주요 구성요소를 보여준다:
- Modules
- Components
- Templates
- Metadata
- Data binding
- Directives
- Services
- Dependency injection
위의 구성요소들에 대해서 알아볼 것이다
이 문서에서 참조하는 코드는 live example / 다운로드 가능한 예제 이다
Modules
Angular 앱은 모듈로 이뤄져 있으면 Angular는 Angular 모듈 또는 NgModule이라고 불리는 모듈화 시스템을 가지고 있다.
Angular Module은 다룰 내용이 많다. 여기서는 단지 모듈에 대해서 소개만 한다. Angular Modules 페이지에서 좀더 자세하게 다룰 것이다.
모든 Angular 앱은 최소한 하나의 모듈 클래스 the root module를 가지며 편의상 이름을 AppModule이라고 한다.
작은 앱은 root 하나로 이뤄진 반면 대부분의 앱은 많은 기능 모듈로 이뤄져 있다.
루트 또는 기능 하나의 Angular 모듈은 은 @NgModule 데코레이터를 가지는 클래스이다.
데코레이터는 JavaScript 클래스들을 변경하는 함수이다. Angular는 클래스에 메타데이터를 추가해 클래스가 어떠한 의미를 가지고 어떻게 동작하는지 알려주는 많은 데코레이터를 가지고 있다. 웹에 데코레이터에 대에서 더 많은 내용 들이 있다
NgModule은 모듈에 대한 속성을 가지고 있는 하나 메타데이터 객체를 가지는 데코레이터 함수이다. 중요한 속성들은 다음과 같다:
declarations - 모듈에 포함되는 뷰 클래스들이다. Angular는 3가지의 뷰클래스들을 가지고 있다: 컴포넌트, 디렉티브, 파이
exports - 다른 모듈의 컴포넌트 템플릿에서 접근해 사용가능한 declarations의 뷰클래스들의 부분집합이다.
imports - export한 클래스들 현재 모듈의 컴포넌트 템플릿에서 필요한 다른 모듈들
providers - 서비스의 전역 집합을 제공하는 서비스들의 생성자 이다;서비스들은 앱의 모든 부분에서 접근이 가능하게 된다.
bootstrap - 루트 컴포넌트라고 불리는 앱의 첫 화면이다. 다른 화면들을 가지고 있다. 오직 루트 모듈만 bootstrap 속성에 설정한다.
아래는 간단한 root 모듈 이다:
src/app/app.modules.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
imports: [ BrowserModule ],
providers: [ Logger ],
declarations: [ AppComponent ],
exports: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}
AppCompnent의 export는 어떻게 내보내기를 하는지 보여주기 위해서 한 것이다; 실제로 예제서 내보내기는 필요가 없다. 루트 모듈은 다른 컴폰넌트에서 이 모듈을 가져오기를 할 필요가 없기 때문에 어떤것도 내보내기를 할 필요가 없다
루트모듈을 부트스트랩해 앱을 실행시킨다. 개발동안 다음 예제처럼 main.ts에서 AppModule을 부트스트랩 할 것이다:
src/main.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
Angular modules vs. JavaScript modules
클래스가 @NgModule데코레이터로 표현되는 Angular 모듈은 Angular의 기본적인 기능이다.
JavaScript는 JavaScript 객체의 집합을 관리하기 위한 모듈 시스템이 존재한다. JavaScript 모듈 시스템은 Angular 모듈 시스템과 전혀 다르며 관련도 없다.
JavaScript에서 각각의 파일은 모듈이며 모든 객체들은 자신이 속해 있는 파일에 정의돼 있다. 모듈들 export 키워드로 일부 객체들을 외부에 공개한다. 다른 JavaScript 모듈은 import 문을 사용해 다른 모듈이 외부에 공개한 객체들에 접근한다.
import { Component } from '@angular/core';
JavaScript import 구문으로 또한 Angular 라이브러리들에서 Angular 모듈들을 가져올 수 있다:
import { BrowserModule } from '@angular/platform-browser';
위의 간단한 루트 모듈예제에서, 앱 모듈은 BrowserModule 내부의 객체들가 필요할 수 있다. 내부의 내용들을 사용하기 위해서 @NgModule 메타데이터에 다음과 같이 imports를 작성 할 수 있다:
imports: [ BrowserModule ],
위의 방법으로 Angular와 JavaScript 모듈 시스템을 같이 사용할 수 있다.
같은 "import"와 "export"를 사용하기 때문에 두개의 시스템을 쉽게 혼동한다. 시간과 경험으로 이러한 혼동은 명확해 질 것 이다.
더 자세한 내용은 Angular 모듈 페이지를 참고하면 된다.
Components
컴포넌트는 화면의 뷰라고 불리는 부분을 제어한다.
예를들어, 다음 뷰는 컴포넌트에 의해서 제어된다.
- 네비게이션 링크를 가지고 있는 앱의 기본 화면
- 히어로 리스트
- 히어로 에디터
클래스 안에 컴포넌트의 앱 로직- 뷰를 어떻게 제어할지 을 정의할 수 있다. 클래스는 메소드와 속성의 API로 뷰와 상호작용한다.
예를들어 HeroListComponent는 서비스로 부터 얻어지는 히어로를 반환하는 heroes 속성을 가지고 있다. 또한 사용자가 리스트에서 히어로를 선택해 클릭했을 때, selectedHero 속성을 설정한는 selectHero() 메서드도 있다.
src/app/hero-list.component.ts (class)
export class HeroListComponent implements OnInit {
heroes: Hero[];
selectedHero: Hero;
constructor(private service: HeroService){ }
ngOnInit() {
this.heroes = this.service.getHeroes();
}
selectHero(hero: Hero) { this.selectedHero = hero; }
}
Angular는 사용자가 앱을 돌아다닐 때 생성, 업데이트, 제거된다. 앱은 위에서 선언한 ngOnInit()처럼 lifecycle hooks에서 선택해 각 순간에 취할 동작을 정의할 수 있다.
Templates
컴포넌트의 뷰는 컴포넌트의 템플릿으로 정의한다. 템플릿은 Angular에게 컴포넌트가 어떻게 보여질지 알려주는 HTML 형태이다.
템플릿은 몇가지 다른점을 빼곤 일반적인 HTML처럼 보인다. 다음은 HeroListComponet에 대한 템플릿이다
src/app/hero-list.component.html
<h2>Hero List</h2>
<p><i>Pick a hero from the list</i></p>
<ul>
<li *ngFor="let hero of heroes" (click)="selectHero(hero)">
{{hero.name}}
</li>
</ul>
<hero-detail *ngIf="selectedHero" [hero]="selectedHero"></hero-detail>