티스토리 뷰

- 이 문서는 작성중입니다. 내용이 생각보다 많이 긴 관계로.... 차근차근 번역하는 중입니다.


Angular 어플리케이션을 구성하는 기본 요소


Angluar는 HTML 클라이언트 어플리케이션을 구성하는 프레임워크이며, JavaScript를 직접 사용하거나 TypeScript와 같이 JavaScript로 컴파일되는 언어를 사용할 수 있다.

Angular 프레임워크는 수많은 라이브러리들로 이루어지는데, 이 중 일부는 코어 모듈이고 일부는 옵션 모듈이다.

Angular 어플리케이션을 구성하기 위해서는, Angular 스타일의 마크업을 사용하여 템플릿을 만들거나, 이 템플릿을 관리하는 컴포넌트 클래스를 작성하기도 하고, 서비스에 어플리케이션 공통 로직을 작성할 수 있고, 컴포넌트와 서비스들을 묶어서 모듈로 구성할 수도 있다.

루트 모듈을 부트스트랩하는 것으로 앱을 실행 된다. Angular는 당신이 지정한 동작에 따라서 브라우저에 내용물을 표시하고 사용자의 입력에 반응할 것이다.

물론 위에서 말한 것보다 더 복잡한 과정이 있다. 이 문서를 따라가면서 자세한 내용을 알 수 있을 것이다.

자 이제, 전체 그림을 보는 것에서부터 시작하자.

이 다이어그램은 Angular 어플리케이션을 구성하는 8개의 중요한 영역을 나타내고 있다.

  • 모듈
  • 컴포넌트
  • 템플릿
  • 메타데이터
  • 데이터 바인딩
  • 디렉티브
  • 서비스
  • 의존성 주입
이제 하나씩 살펴보자.
이 페이지에서 언급된 코드들은 라이브 예제 페이지에서도 확인할 수 있다.


모듈

Angular 앱은 그 자체로 모듈이고, Angular 모듈이나 NgModule이라고 하는 독자적인 모듈 구조를 사용한다.

 Angular 모듈은 복잡한 영역이다. 이 페이지에서도 모듈에 대해 다루지만 Angular 모듈 페이지에서 좀 더 자세한 내용을 다룬다.

 모든 Angular 앱은 반드시 루트 모듈이라는 Angular 모듈 클래스를 가지며, 편의상 AppModule이라고 부른다.

 어플리케이션이 작은 경우 루트 모듈이 유일한 모듈일 수도 있지만, 대부분의 앱들은 어플리케이션 도메인, 동작 흐름, 연관성 등을 고려하여 좀 더 많은 개수의 모듈을 갖는다.

 루트 모듈이든 일반 모듈이든, Angular 모듈은 @NgModule 데코레이터가 붙는 클래스로 선언된다.

 데코레이터는 JavaScript 클래스를 변형하는 함수다. Angular는 클래스가 어떤 특징을 가지며 어떻게 동작해야 하는지 메타데이터를 사용하는 데코레이터를 여러개 구현해두고 있다. 데코레이터에 대해 좀 더 알아보려면 이곳을 참고하자.

 NgModule도 모듈을 정의하는 메타데이터 객체 하나를 사용하는 데코레이터 함수다. 가장 중요한 프로퍼티는 아래와 같다.

  • declarations - 이 모듈에서 사용하는 뷰 클래스를 정의한다. Angular에는 컴포넌트, 디렉티브, 파이프 세 종류의 뷰 클래스가 있다.
  • exports - 다른 모듈이나 컴포넌트 템플릿에서 접근할 수 있도록 외부로 공개 선언한다.
  • import - export로 공개된 클래스를 다른 컴포넌트 템플릿의 this 모듈에 선언해서 사용할 때 사용한다.
  • providers - 전역에서 사용되는 서비스를 해당 객체에서 사용할 수 있도록 생성하고 지정한다. 프로바이더는 앱의 모든 곳에서 접근할 수 있다.
  • bootstrap - 루트 컴포넌트라고 하는 메인 어플리케이션의 뷰를 선언한다. bootstrap 항목은 루트 모듈에만 존재한다.
간단한 루트 모듈의 예는 아래와 같다.

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 { }
 위 코드의 AppComponent export는 사실 이 예제에서 필요 없으며, 단순히 export가 어떻게 동작하는 지 보여주기 위해 추가되었다. 루트 모듈은 외부의 어느 컴포넌트에서도 로드되지 않기 때문에, 아무것도 외부로 공개할 필요가 없다. 

 이 루트 모듈을 부트스트랩핑해서 어플리케이션을 실행시켜 보자. 개발 단계에서는 main.ts파일에 있는 AppModule은 이런 식으로 부트스트랩한다.


import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

Angular 모듈 vs. JavaScript 모듈

 @NgModule 데코레이터가 붙은 Angular 모듈은 Angular 기능의 기본 요소다.

 JavaScript도 JavaScript 객체의 콜렉션을 관리하는 나름의 모듈 구조를 갖추고 있지만, Angular의 모듈 시스템과 비교해볼 때 전혀 다르고 연관성도 없다.

 JavaScript에서 각 모듈은 하나의 파일이며 모든 객체는 모듈 안에 선언된다. 이 때 export 키워드를 사용하면 어떤 객체를 외부로 공개하여 public으로 만들 수 있다. 다른 JavaScript 모듈에서는 import 구문을 사용하여 다른 모듈에서 공개된 객체를 사용할 수 있다.


import { NgModule }     from '@angular/core';
import { AppComponent } from './app.component';


export class AppModule { }

JavaScript 모듈 시스템에 대해 좀 더 알아보기

 Angular 모듈 시스템과 JavaScript 모듈 시스템은 서로 다르지만 상호 보완적일 수도 있다. 두 방식을 함께 사용하는 것도 나쁘지 않다.


Angular 라이브러리

 Angular는 수많은 JavaScript 라이브러리를 탑재하고 있다. 이 라이브러리드들이 각각의 모듈이라고 봐도 무방하다.

 Angular 라이브러리들은 @angular 접두사로 시작한다.

 Angular 라이브러리는 npm 패키지 매니저를 사용해서 설치하고 JavaScript 문법인 import를 사용해서 불러올 수 있다.


예를 들어 Angular의 @angular/core 라이브러리에서 Component 데코레이터를 불러오는 코드는 아래와 같다.

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

라이브러리뿐만 아니라 Angular 모듈을 불러오는 것도 import 구문을 사용한다.

import { BrowserModule } from '@angular/platform-browser';

위에 있는 루트 모듈 예제 코드을 보면 어플리케이션 모듈은 BrowserModule 안에 있는 기능을 사용한다. 이 기능을 사용하기 위해서는 @NgModule 메타데이터에 imports 항목을 아래와 같이 지정한다.

imports:      [ BrowserModule ],

이 방식은 Angular 모듈 시스템과 JavaScript 모듈 시스템을 함께 사용하는 방식이다.

두 모듈 시스템은 모두 "imports"와 "exports" 키워드를 사용하기 때문에 두 모듈 시스템을 혼동하기 쉽다. 이 고민은 시간과 경험이 쌓이면서 자연스럽게 해결될 것이다.

Angular 모듈에 대해 좀 더 알아보기


컴포넌트

컴포넌트는 화면의 '뷰'라고 하는 부분을 제어한다.

예를 들어, 아래 목록은 모듀 컴포넌트가 제어하는 뷰다.

  • 네비게이션 링크를 제공하는 앱 루트
  • 영웅들의 목록
  • 영웅 편집기
뷰에서 동작해야 하는 기능을 정의하는 컴포넌트의 어플리케이션 로직은 클래스 안에 정의할 수 있다. 클래스는 프로퍼티의 API와 함수들을 가지고 뷰와 상호작용한다.

예를 들어 HeroListComponent에는 서비스에서 영웅들의 배열을 받아 저장하는 heroes 프로퍼티가 있다.

HeroListComponent에는 사용자가 목록에서 영웅을 선택했을 때 selectedHero 프로퍼티의 값을 지정하는 selectHero() 함수도 있다.


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()과 같이 생명 주기를 가로채는 함수를 이용하여 특정 시점에 원하는 동작을 할 수도 있다.


템플릿

컴포넌트의 뷰는 템플릿으로 정의한다. 템플릿에서는 Angular가 컴포넌트를 HTML로 어떻게 렌더링할 지 모습을 정의한다.

 템플릿은 일반 HTML과 비슷하게 보이지만, 몇 가지는 다르다. HeroListComponent의 템플릿은 아래와 같다.


<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>


 이 템플릿에는 <h2>나 <p>와 같이 전통적으로 사용되던 HTML 엘리먼트들이 있지만 그 외에 다른 요소도 있다. *ngFor나 {{hero.name}}(click)[hero]<hero-detail> 등과 같은 요소는 Angular 템플릿 문법이 사용되었다.

위 코드의 마지막 줄에서 사용된 <hero-detail> 태그는 HeroDetailComponent를 나타내는 커스텀 엘리먼트다.

이 HeroDetailComponent는 이전에 봤던 HeroListComponent와는 다른 컴포넌트다. HeroDetailComponent에서는 HeroListComponent에서 표시하는 목록에서 사용자가 특정 영웅을 선택하면 그 영웅의 정보를 표시한다. HeroDetailComponent는 heroListComponent의 자식 컴포넌트라고 할 수 있다.

일반적인 HTML 엘리먼트들 사이에 <hero-detail>가 자연스럽게 어울리는 것에 주목하자. 화면에서도 커스텀 컴포넌트는 기본 HTML들과 함께 자연스럽게 레이아웃을 구성할 수 있다.



메타데이터

 메타데이터는 클래스가 어떻게 동작해야 하는지에 대한 정보를 지정한다.

HeroListComponent의 코드를 다시 보면, 이 컴포넌트는 단순한 클래스인 것을 확인할 수 있다. 이 클래스는 프레임워크에서 만든 것도 아니고 Angular에서 제공하는 기능도 아니다.

사실 HeroListComponent는 딱 클래스일 뿐이다. Angular에게 이 클래스에 대한 정보를 알려주기 전까지는 아직은 컴포넌트라고 할 수 없다.

TypeScript에서는 클래스에 데코레이터를 사용하여 메타데이터를 덧붙일 수 있다. HeroListComopnent에 메타데이터를 적용한 코드는 아래와 같다.


@Component({
  moduleId: module.id,
  selector:    'hero-list',
  templateUrl: './hero-list.component.html',
  providers:  [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}

여기에는 지정된 클래스를 컴포넌트 클래스로 변환하는 @Component 데코레이터가 사용되었다.

신고
댓글
댓글쓰기 폼
공지사항
Total
202,187
Today
34
Yesterday
280
링크
«   2017/09   »
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함