[Angular] Angular CLI를 부셔보자

OFFDUTYBYBLO·2020년 12월 4일
0

Angular

목록 보기
5/14
post-thumbnail

1. 정의

Angular CLI는 간단한 명령어를 사용하여 Angular 프로젝트 스캐폴딩(scaffolding)을 생성, 실행, 빌드할 수 있으며 Angular의 다양한 구성 요소를 선별적으로 추가할 수 있는 커맨드-라인 인터페이스(Command Line Interface)이다. 개발용 서버를 내장하고 있어서 간단히 프로젝트를 실행시켜서 동작을 확인할 수 있다.

스캐폴딩(Scaffolding)이란?
양식, 포맷, 기본 구조를 뜻한다. Angular로 처음 프로젝트를 셋팅할 때 프로젝트의 기본 구조라고 생각하면 이해가 쉽다.

2. Angular CLI가 지원하는 기능

  • Angular 프로젝트 생성
  • Angular 프로젝트에 컴포넌트,디렉티브,파이프,서비스,클래스,인터페이스 등의 구성 요소 추가
  • LiveReload를 지원하는 내장 개발 서버를 사용한 Angular 프로젝트 실행
  • Unit/E2E(end-to-end) 테스트 환경 지원
  • 배포를 위한 Angular 프로젝트 페키징

3. Angular CLI 설치

  • Angular CLI는 Node.js 6.9.0, NPM 3.0.0 이상이 필요하다.
$ npm install -g @angular/cli

4. 프로젝트 생성

  • Angular 프로젝트를 생성하려면 ng new 명령어를 사용한다.
$ ng new <project-name>
  • ng new 명령어 다음에 프로젝트 이름을 지정하면 프로젝트 이름과 일치하는 새로운 프로젝트 폴더가 생성되고 스캐폴딩(프로젝트 기본 골격)이 작성된다.

5. 프로젝트 실행

  • 프로젝트를 로컬 환경에서 실행하기 위해서는 ng serve 명령어를 사용한다.

  • 프로젝트를 실행할 때 --open(축약형 -o) 옵션을 추가하면 자동으로 브라우저를 실행한다.

$ cd <project-name> // 프로젝트 폴더로 이동
$ ng serve --open // 프로젝트 실행
  • 이미 포트 4200번을 사용하고 있다면 Angular CLI 내장 서버를 실행할 수 없다. 포트번호를 변경해 실행하려면 --port(축약형 -p)옵션을 추가한다.
$ ng serve --port 4201
  • Angular CLI가 내장하고 있는 개발용 서버는 코드의 변경을 감지하여 자동으로 브라우저를 리로드하는 LiveReload 기능을 제공한다. 따라서 코드 수정 후 파일을 저장하면 코드 변경을 자동 반영하여 번들링이 수행되고 브라우저가 리로드되어 코드 변경 결과를 즉시 확인할 수 있다.

6. 프로젝트 구성 요소 생성

  • 프로젝트에 새로운 구성요소를 생성하기 위해서는 ng generate 명령어를 사용한다.

  • ng generate 명령어는 축약형 ng g와 동일하게 동작한다.

6.1 컴포넌트 생성

  • 프로젝트에 새로운 컴포넌트를 생성하기 위해서는 ng generate component 명령어를 사용한다.
  • ng generate component home 명령어를 실행하면 Angular CLI는 아래와 같이 동작한다.
  • src/app폴더에 home 폴더를 생성한다. 컴포넌트는 URL 경로의 단위가 될 수 있기 때문에 폴더로 구분된다.
  • src/app/home 폴더에 4개의 파일을 생성한다.
    • home.component.html : 컴포넌트 템플릿을 위한 HTML 파일
    • home.component.css : 컴포넌트 템플릿의 스타일링을 위한 CSS 파일
    • home.component.ts : 컴포넌트 클래스 파일
    • home.component.spec.ts : 컴포넌트 유닛 테스트를 위한 스펙 파일
  • 루트 모듈 src/app/app.moddule.ts에 새롭게 생성된 컴포넌트를 등록한다. 컴포넌트 클래스를 import하고 @NgModule 데코레이터의 declarations 프로퍼티에 컴포넌트 클래스를 등록한다.

6.1.1 파일명의 암묵적 변경

  • 주의해야 할 것은 ng generate component 명령어 다음에 지정한 컴포넌트명이 실제 생성된 파일명과 다를 수 있다는 것이다.

  • 컴포넌트명을 Angular CLI는 지정된 컴포넌트명의 대소문자를 구별하여 정해진 규칙에 따라 파일명을 암묵적으로 변경한다.

$ ng generate component newComponent // new-component로 변경됨

이와 같은 파일명의 암묵적 변경은 컴포넌트뿐만 아니라 ng generate 명령어로 추가되는 모든 구성요소에 모두 적용된다. 혼란을 방지하기 위해 ng generate 명령어에 지정하는 구성요소 명칭은 하이픈으로 단어를 연결하는 케밥 표기법(kebab-case)을 사용하는 것이 좋다.

즉, CamelCase를 사용하여 ng generate 명령어의 이름을 짓는다면 모두 kebab-case로 변경되어 생성이된다는 의미이다.

6.1.2 selector 프로퍼티값의 접두사(prefix)와 컴포넌트 클래스 이름

  • 생성된 컴포넌트 클래스 파일 src/app/home/home.component.ts을 살펴보자
// src/app/home/home.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  constructor() { }

  ngOnInit() { }
}
  • selector 프로퍼티값 'app-home'과 9번째 줄에 있는 HomeComponent가 처음에는 혼동될 수 있다.
  • Angular를 처음 접한 나는 해당 ts파일을 보고 이렇게 생각했다. '분명히 내가 컴포넌트 이름을 home으로 생성했는데, HomeComponent는 뭐고 selector는 뭐야?'
  • selector 프로퍼티에 할당된 'app-home'은 컴포넌트 마크업으로 표현할 때 사용하는 이름이다. HTML파일에서 해당 컴포넌트를 뷰에 보여줄때 사용하는 Element 이름이라고 생각하면 쉽다.
<!-- src/app/app.component.html -->
<app-home></app-home> 
  • selector 프로퍼티값 'app-home'은 ng generate component home 명령어에서 지정한 컴포넌트명 home 앞에 접두사 app이 자동으로 추가된 값이다.
  • Angular는 다른 애플리케이션의 selector 또는 HTML 요소와 충돌을 방지하기 위해 접두사를 추가하여 케밥 표기법으로 명명하는 것을 권장한다.

6.1.3 templateUrl,styleUrls 프로퍼티와 template,styles 프로퍼티

templateUrl,styleUrl 프로퍼티는 외부 파일을 로드하기 위해 사용한다.

  • templateUrl
    외부 파일로 작성된 HTML 템플릿(컴포넌트의 뷰를 정의)의 경로
  • styleUrls
    외부 파일로 작성된 CSS 파일의 경로
// src/app/home/home.component.ts
...
@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
...
  • 위 예제의 경우 컴포넌트는 같은 폴더 내의 외부 파일 home.component.html과 home.component.css를 HTML 템플릿과 CSS로 사용한다.
  • HTML 템플릿이나 CSS가 간단한 경우에는 메타데이터(@Component()에 인자로 전달된 객체) 내부에 직접 기술할 수도 있다. 이때 templateUrl,styleUrls 프로퍼티 대신 template,style 프로퍼티를 사용한다.

    메타데이터는 또 뭐야?
    메타데이터는 쉽게 말해서 데이터의 데이터이다. '이 데이터는 어떤 목적, 내용, 이름을 갖고있느냐?' 이뜻이다. 우리가 불러온 데이터를 어떤 목적으로 쓸꺼야? 데코레이터가 프로퍼티명으로 물어보면 우리는 프로퍼티값으로 대답하면 됩니다. 'selector는 HTML Element로 쓸꺼야, templateUrl은 사용자에게 컴포넌트를 보여주는 HTML파일이야, styleUrls는 컴포넌트를 꾸며주는 CSS파일이야'

6.2 디렉티브 생성

프로젝트에 새로운 디렉티브를 생성하기 위해서는 ng generate directive 명령어를 사용한다.

$ ng generate directive highlight

ng generate directive highlight 명령어를 실행하면 Angular CLI는 아래와 같이 동작한다.

  • src/app 폴더에 2개의 파일을 생성
    - highlight.directive.ts : 디렉티브 클래스 파일
    - highlight.directive.spec.ts : 디렉티브 유닛 테스트를 위한 스펙 파일
  • 루트 모듈 src/app/app.module.ts에 새롭게 생성된 디렉티브를 등록한다.
    디렉티브를 import하고 @NgModule 데코레이터의 declarations 프로퍼티에 디렉티브를 등록한다.

컴포넌트를 생성할 때와는 달리 디렉티브를 위한 폴더는 생성되지 않으며 기본적으로 src/app 폴더에 생성된다. 생성된 highlight.directive.ts를 살펴보면 @Directive 데코레이터 함수에 전달된 메타데이터 객체의 selector 프로퍼티값으로 '[appHighlight]'가 설정되었다.

// src/app/highlight.directive.ts
import { Directive } from '@angular/core';

@Directive({
  selector: '[appHighlight]'
})
export class MyDirectiveDirective {

  constructor() { }

}

angular.json에 설정된 기본 접두사 app과 ng generate directive 명령어에 지정한 디렉티브 이름으로 합성된 디렉티브 셀렉터 이름으로 카멜표기법(camelCase)으로 작성된다. selector 프로퍼티에 지정한 디렉티브의 이름 appHighlight은 HTML attribute처럼 사용된다.

<p appHighlight>Highlight Directive!</p>

6.3 모듈 생성

프로젝트에 새로운 모듈을 생성하기 위해서는 ng generate module 명령어를 사용한다.

$ ng generate module todos

ng generate module todos 명령어를 실행하면 Angular CLI는 아래와 같이 동작한다.

  • src/app 폴더에 todos 폴더를 생성한다.
  • src/app/todos 폴더에 1개의 파일을 추가한다.
    - todos.module.ts : 모듈 클래스 파일
    - todos.module.spec.ts : 모듈 유닛 테스트를 위한 스펙 파일

생성된 모듈은 해당 모듈을 사용하려는 다른 모듈의 imports 프로퍼티에 등록되어야 한다.

// src/app/app.module.ts
...
import { TodosModule } from './todos/todos.module';

@NgModule({
  ...
  imports: [
    ...
    TodosModule
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

6.4 서비스 생성

프로젝트에 새로운 서비스를 생성하기 위해서는 ng generate serivce 명령어를 사용한다.

$ ng generate service data

꿈에서 ng generate 나올지경
ng generate service data 명령어를 실행하면 Angular CLI는 아래와 같이 동작한다.

  • 루트 폴터에 2개의 파일을 생성한다.
    - user.service.spec.ts : 서비스 유닛테스트를 위한 스펙 파일
    - user.service.ts : 서비스 클래스 파일

컴포넌트를 생성할 때와는 달리 서비스를 위한 폴더는 생성되지 않으며 기본적으로 src/app 폴더에 생성된다. 생성된 data.service.ts를 살펴보면 @Injectable 데코레이터 함수에 전달된 메타데이터 객체의 providedIn 프로퍼티 값으로 'root'가 설정되었다.

// src/app/data.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  constructor() { }
}

provideIn 프로퍼티는 Angular 6에서 도입된 것으로 프로퍼티 값으로 'root'를 설정하면 루트 인젝터에게 서비스를 제공하도록 지시하여 애플리케이션 전역에서 서비스를 주입할 수 있도록 한다.

6.5 클래스 생성

프로젝트에 새로운 클래스를 생성하기 위해서는 ng generate class 명령어를 사용한다.

$ ng generate class user

테스트를 위한 스펙 파일을 함께 생성하기 위해서는 --spec 옵션을 추가한다.

$ ng generate class user --spec

7. 프로젝트 빌드

프로젝트 개발을 완료한 이후 배포를 위해서는 ng build 명령어를 사용한다.

$ ng build

빌드가 완료되면 프로젝트 루트에 빌드 결과물이 포함된 dist 폴더가 생성된다.

7.1 트랜스파일링과 의존 모듈 번들링

TypeScript기반으로 개발이 진행되는 Angular 애플리케이션은 TypeScript를 Javascript로 변환하여야 한다. 또한 프로젝트가 의존하는 모듈들을 로드하는 HTML 파일의 script 태그를 작성해야 한다. 다양한 프로젝트의 의존 모듈을 순서에 맞게 수작업으로 script 태그에 기술하는 것은 매우 곤란한 일이며 실수가 발생할 수 있다.

Angular CLI로 새로운 프로젝트를 생성할 경우, 의존 모듈의 설치는 기본 패키지 매니저인 npm으로 자동화되어 진행된다. 이때 설치되는 의존 모듈은 약 1,000여 개로 의존성 관리를 위해 수작업은 현실적이지 않다. Angular CLI의 빌드 기능은 의존성 관리를 위한 작업을 자동화하여 진행한다.

Angular CLI 빌드 기능은 내부적으로 모듈 번틀러인 webpack을 사용하며 아래와 같은 작업의 자동화를 지원한다.

  • TypeScript에서 JavaScript로의 트랜스파일링
  • 디버깅 용도의 source map 파일 생성
  • 의존 모듈과 HTML,CSS,JavaScript 번들링
  • AoT 컴파일
  • 코드의 문법 체크
  • 코드의 규약 준수 여부 체크
  • 불필요한 코드의 삭제 및 압축

Angular CLI 빌드 기능은 소스코드와 의존 모듈을 번들링한다. 이때 번들링되는 코드는 JavaScript뿐만이 아니라 HTML,CSS까지 JavaScript 파일 내에 번들링된다. 또한 index.html에 번들링된 자바스크립트 파일 5개를 로드하기 위한 태그를 추가한다.

<!-- 빌드 전 -->
<!-- src/index.html -->
...
<body>
  <app-root></app-root>
</body>
</html>


<!-- 빌드 후 -->
<!-- dist/index.html -->
...
<body>
  <app-root></app-root>

  <script type="text/javascript" src="runtime.js"></script>
  <script type="text/javascript" src="polyfills.js"></script>
  <script type="text/javascript" src="styles.js"></script>
  <script type="text/javascript" src="vendor.js"></script>
  <script type="text/javascript" src="main.js"></script>
</body>
</html>

  • 빌드 처리는 다음과 같이 진행되며 빌드가 완료되면 dist 폴더가 추가되고 그 내부에 빌드 결과물이 생성된다.
profile
블로그 운영 x

0개의 댓글