CHAPTER 4. From zero to something

Developing and building a TypeScript app

์ด์ œ ์šฐ๋ฆฌ์˜ ์ฒซ๋ฒˆ์งธ Angular 2 ์•ฑ๊ณผ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๋„๋ก ํ•˜์ž. ๋‹น์‹ ์€ ์ด๋ฏธ Node.js์™€ NPM์„ ์„ค์น˜ํ•˜์˜€์„ ๊ฒƒ์ด๋‹ค. ๋‹น์‹ ์˜ Node.js ๋ฒ„์ ผ์ด ์ถฉ๋ถ„ํžˆ ์ตœ์‹ ์ธ์ง€ ํ™•์ธํ•˜๋„๋กํ•ด๋ผ.(node --version) ์šฐ๋ฆฌ๋Š” typescript ๊ธฐ๋ฐ˜์œผ๋กœ ์•ฑ์„ ๊ฐœ๋ฐœํ• ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ typescript๋ฅผ ์„ค์น˜ํ•ด๋ณด๋„๋ก ํ•˜์ž.

npm install -g typescript typings

๊ทธ๋ฆฌ๊ณ ๋‚˜์„œ ์—ฐ์Šต์„ ์œ„ํ•ด์„œ ๋นˆ ํด๋”๋ฅผ ์ƒˆ๋กœ ๋งŒ๋“ค์ž, ๊ทธ๋ฆฌ๊ณ  tsc๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋นˆ ํด๋”์— ํ”„๋กœ์ ํŠธ๋ฅผ ์ดˆ๊ธฐํ™” ํ•˜๋„๋ก ํ•œ๋‹ค. tsc ๋Š” typescript ์ปดํŒŒ์ผ๋Ÿฌ์˜ ์•ฝ์ž์ด๋‹ค.

tsc --init --target es5 --sourceMap --experimentalDecorators --emitDecoratorMetadata

์ด์ œ typescript ์ปดํŒŒ์ผ ์˜ต์…˜์„ ์ •์˜ํ•œ tsconfig.jsonํŒŒ์ผ์„ ๋งŒ๋“ค๊ฒƒ์ด๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์ด์ „์˜ ์ฑ•ํ„ฐ์—์„œ ๋ณด์•˜๋“ฏ์ด ์šฐ๋ฆฌ๋Š” decorator๋ฅผ ๊ฐ€์ง„ typescript๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ณ  ์šฐ๋ฆฌ๋Š” ์šฐ๋ฆฌ์˜ ์ฝ”๋“œ๊ฐ€ ๋ชจ๋“  ๋ธŒ๋ผ์šฐ์ ธ์—์„œ ๋™์ž‘ํ•˜๋„๋ก ECMASCRIPT 5๋กœ ๋ณ€ํ™˜๋˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค. sourceMap ์˜ต์…˜์€ ๊ธฐ์กด ์‚ฌ์šฉ์ž๊ฐ€ ์ž‘์„ฑํ•œ Typescript code์™€ ์ƒ์„ฑ๋œ ES5 ์ฝ”๋“œ๋ฅผ ์—ฐ๊ฒฐ์‹œ์ผœ์ฃผ๋Š” ์†Œ์Šค์˜ ๋งต์„ ์ƒ์„ฑํ•ด์ค€๋‹ค. sourceMap์€ ๋””๋ฒ„๊ทธ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ ธ์— ์˜ํ•ด ์‚ฌ์šฉ๋˜์–ด ์ง„๋‹ค.

์šฐ๋ฆฌ๋Š” ์„ ํ˜ธํ•˜๋Š” ํ†ตํ•ฉ ๊ฐœ๋ฐœํ™˜๊ฒฝ์„ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค. ๋‹น์‹ ์€ ๋‹น์‹ ์ด ์›ํ•˜๋Š” ๊ฒƒ์„ ๋งค์šฐ ์ž˜ ์•Œ๊ณ  ์žˆ์„๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹น์‹ ์€ ํ†ตํ•ฉ ๊ฐœ๋ฐœํ™˜๊ฒฝ์—์„œ TypeScript ์ง€์›์„ ํ™œ์„ฑํ™”ํ•ด์•ผ ํ•œ๋‹ค. ( typescript 1.5 ์ด์ƒ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค. )

{
  "compilerOptions": {
   "target": "es5",
   "experimentalDecorators": true,
   "emitDecoratorMetadata": true,
   "sourceMap": true,
   "module": "commonjs",
   "noImplicitAny": false,
  },
  "exclude": [
   "node_modules"
  ]
}

๊ธฐ๋ณธ์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ์˜ต์…˜๋“ค์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ํฅ๋ฏธ๋กœ์šด ์ ์€ module ์˜ต์…˜์ด๋‹ค. module option์€ ์šฐ๋ฆฌ๊ฐ€ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ commonjs ์•ˆ์œผ๋กœ ํŒจํ‚ค์ง€๋  ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์„ ์„ค๋ช…ํ•œ๋‹ค.

์ด์ œ ์šฐ๋ฆฌ๋Š” typesciprt ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์‹คํ–‰ํ•  ์ค€๋น„๊ฐ€ ๋˜์—ˆ๋‹ค. ๊ฐ€๋”์€ ๋‹น์‹ ์˜ ํ†ตํ•ฉ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์€ ๋‹น์‹ ์„ ์œ„ํ•ด ์ˆ˜ํ–‰๋  ๊ฒƒ์ด๋‹ค.

tsc --watch

๋‹น์‹ ์€ ์ด๋ ‡๊ฒŒ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ์‚ดํŽด๋ณด์•„์•ผ ํ•œ๋‹ค.

Compilation complete. Watching for file changes.

์ด ๊ธฐ๋Šฅ์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰ํ•˜๊ณ  ๋‹ค์Œ์— ์ œ๊ณต ํ•  ์ƒˆ๋กœ์šด ํ„ฐ๋ฏธ๋„์„ ์—ด์–ด๋„ ๋œ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด์ œ Angular 2 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค. Angular 2 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” NPM ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์šด๋ฐ›์„ ๊ฒƒ์ด๋‹ค. ๋ช‡๊ฐ€์ง€ ๋ฌธ์ œ๋“ค์„ ํšŒํ”ผํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” npm version 3์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค. ๋‹น์‹ ์˜ npm version์„ ํ™•์ธํ•˜๋„๋ก ํ•ด๋ผ(npm -v)

npm install --save @angular/core @angular/compiler @angular/common @angular/platformbrowser @angular/platform-browser-dynamic rxjs reflect-metadata zone.js

์ด์ œ packjage.json ํŒŒ์ผ์„ ์‚ดํŽด๋ณด๋„๋ก ํ•ด๋ผ. ๋‹ค์Œ์˜ ์˜์กด์„ฑ์ด ํฌํ•จ๋˜์–ด ์žˆ์„ ๊ฒƒ์ด๋‹ค. โ€ข the different @angular packages. โ€ข reflect-metadata, as we are using decorators. โ€ข rxjs, a really cool library called RxJSfor reactive programming. We have a dedicated chapter on this topic. โ€ข and finally, the zone.jsmodule, doing the heavy lifting of running our code in isolated zones for detecting the changes (weโ€™ll dive into this later also).

๋งˆ์ง€๋ง‰์œผ๋กœ ์ปดํŒŒ์ผ์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด ES6์™€ ์—ฐ๊ด€๋œ typings๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•œ๋‹ค. ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ core-js๋ฅผ ์„ค์น˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

typings init
typings install --save --global dt~core-js

๊ทธ๋ฆฌ๊ณ  tsconfig.json ํŒŒ์ผ์— exculde ์˜์—ญ์— ์ถ”๊ฐ€ํ•ด๋ผ.

"exclude": [
  "node_modules",
  "typings/main.d.ts",
  "typings/main"
]

Our first component

app.component.ts๋กœ ๋ถˆ๋ฆฌ์šฐ๋Š” ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋ผ.

ํŒŒ์ผ์„ ์ €์žฅํ•  ๊ฒฝ์šฐ์—, ๋””๋ ‰ํ† ๋ฆฌ์— app.component.ts๋ผ๋Š” ์ƒˆ ํŒŒ์ผ์ด ๋‚˜ํƒ€๋‚ ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์€ typeScript compoiler๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋‹น์‹ ์€ ์†Œ์Šค ๋งต ํŒŒ์ผ์„ ํ™•์ธํ•ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค. ๋งŒ์•ฝ์— ๊ทธ๋ ‡์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ค‘๋‹จ์‹œํ‚ฌ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ์ด์ „์— ์‚ดํŽด๋ณธ ์„น์…˜์—์„œ ์ปดํฌ๋„ŒํŠธ๋Š” template์˜ ์กฐํ•ฉ์ด๋ผ๊ณ  ํ•˜์˜€๊ณ  ์–ด๋–ค ๋กœ์ง์ด๋ผ๊ณ  ํ•˜์˜€๋‹ค. ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด๋ณด์ž.

export class PonyRacerAppComponent {
}

Angular๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” @Component decorator๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” import ํ•ด์•ผํ•œ๋‹ค.

import { Component } from '@angular/core';
@Component()
export class PonyRacerAppComponent {
}

IDE์—์„œ ์ง€์›ํ•˜๋Š” ๊ฒฝ์šฐ Angular 2 ์ข…์†์„ฑ์€ node_modules ๋””๋ ‰ํ† ๋ฆฌ์— ์ž์ฒด d.ts ํŒŒ์ผ์ด ์žˆ์œผ๋ฏ€๋กœ ์ฝ”๋“œ ์™„์„ฑ์ด ๋™์ž‘ํ•ด์•ผ ํ•˜๋ฉฐ typeScript ๊ฐ€ ์ด๋ฅผ ๊ฐ์ง€ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์›ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ์ •์˜ํ•œ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

typeScript๋Š” ์œ ํ˜• ์ฒดํฌ ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹น์‹ ์ด ์–ด๋– ํ•œ ์œ ํ˜•์„ ์‹ค์ˆ˜ํ•˜์˜€๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์˜ค๋ฅ˜๊ฐ€ ๋ฐ˜๋“œ์‹œ ์ฐจ๋‹จ๋˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋‹น์‹ ์ด ๋ณ€์ˆ˜์— ์œ ํ˜•์„ ์ถ”๊ฐ€ํ•˜๋Š”๊ฒƒ์„ ์žŠ์—ˆ๋‹ค๋ฉด ์ฝ”๋“œ๋Š” ์ ์ ˆํžˆ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ๋™์ž‘ํ•  ๊ฒƒ์ด๋‹ค.

๋‚˜๋Š” typescript ์—๋Ÿฌ๋ฅผ 0์œผ๋กœ ๋‚˜์˜ค๋„๋ก ์‹œ๋„ํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹น์‹ ์€ ํ•˜๊ณ  ์‹ถ์€ ๋Œ€๋กœ ํ•ด๋„ ๋œ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์†Œ์Šค๋งต์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‹น์‹ ์€ ts code๋ฅผ ๋ธŒ๋ผ์šฐ์ ธ์—์„œ ๋ฐ”๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‹น์‹ ์˜ ์•ฑ์— ์ค‘๋‹จ์ ์„ ์„ค์ •ํ•˜์—ฌ ๋””๋ฒ„๊น…์„ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

@Component decorator๋Š” ๊ฐ์ฒด์˜ ๊ตฌ์„ฑ ์„ค์ •์ด๋‹ค. ์šฐ๋ฆฌ๋Š” ๋‹น์‹ ์ด ์„ค์ •ํ•œ ์ •๋ณด๋ฅผ @Component ๋‚ด๋ถ€์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. "selector" ์ด๊ฒƒ์€ HTML ํŽ˜์ด์ง€์—์„œ ์–ด๋–ค ํƒœ๊ทธ๋กœ ์“ฐ์ผ์ง€๋ฅผ ์•Œ๋ ค์ค€๋‹ค.

import { Component } from '@angular/core';
@Component({
  selector: 'ponyracer-app'
})
export class PonyRacerAppComponent {
}

ํ•œ๊ฐ€์ง€ ์ฃผ์˜ํ•  ์ ์€ selector์˜ ๋ช…ํ™•ํ•œ ๋„ค์ด๋ฐ ๊ทœ์น™์€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋งŒ์•ฝ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋จธ์—๊ฒŒ ๋‹น์‹ ์˜ component๋ฅผ ์„ค๋ช…ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค๋ฉด namespace-component๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋ฅผ ๊ถŒ์žฅํ•œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด selecotr๋Š” ์œ ์ผํ•ด์•ผํ•˜๊ณ  ํƒœ๊ทธ๋ฅผ ์ข€ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ„๋‹จํ•œ ํŒ์ด๋ผ๊ณ  ํ• ์ˆ˜ ์žˆ๋‹ค.

import { Component } from '@angular/core';
@Component({
  selector: 'ponyracer-app',
  template: '<h1>PonyRacer</h1>'
})
export class PonyRacerAppComponent {
}

๋‹น์‹ ์€ @angular/code ๋ชจ๋“ˆ์„ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ํ•ญ์ƒ ํ•„์š”ํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ๋“ค์–ด http ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” @angular/http ๊ฐ€ ํ•„์š”ํ•˜๊ณ  router๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” @angular/router๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

Our first Angular module

Angular ๋ชจ๋“ˆ์€ ์ด์ „์— ๊ต์ฐจ ํ•œ ES6 ๋ชจ๋“ˆ๊ณผ๋Š” ๋‹ค๋ฅด๋‹ค.

๋‹น์‹ ์˜ ์–ดํ”Œ๋ ˆ์ด์…˜์€ root module ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์ตœ์†Œ ํ•˜๋‚˜์˜ ๋ชจ๋“ˆ์€ ๊ฐ€์ง€๊ณ  ์žˆ์„๊ฒƒ์ด๋‹ค. ํ›„์—๋Š” ๋‹ค์–‘ํ•œ ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€ํ•  ๊ฒƒ์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ์™€ ๋กœ์ง์„ ํฌํ•จํ•˜๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ Admin ๋ถ€๋ถ„ ์ „์šฉ ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€ ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋˜ํ•œ ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์šฐ๋ฆฌ์˜ ์•ฑ์— ์™ธ๋ถ€ ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ๋„ ์žˆ๋‹ค.

Angular app์— ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Class๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค. ์ฃผ๋กœ ํ•ด๋‹น ์ž‘์—…์€ ๋ฃจํŠธ ์˜ค๋“ˆ์˜ app.module.ts๋ผ๋Š” ๋ณ„๊ฐœ์˜ ํŒŒ์ผ์—์„œ ์ˆ˜ํ–‰๋œ๋‹ค. ํ•ด๋‹น ํด๋ž˜์Šค๋Š” @Ngmodule๋กœ ์žฅ์‹๋œ๋‹ค.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
  imports: [BrowserModule],
})
export class AppModule {
}

์šฐ๋ฆฌ๊ฐ€ ๋ธŒ๋ผ์šฐ์ ธ์— ์•ฑ์„ ๋นŒ๋“œํ•  ๊ฒฝ์šฐ์— root module์€ BrowserModule์„ ์ถ”๊ฐ€ํ•  ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ์€ Angular2์—๋งŒ ๊ฐ€๋Šฅํ•œ ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ์˜ˆ์ œ๋ฅผ ์œ„ํ•ด ์„œ๋ฒ„์— ์•ฑ์„ ๋ Œ๋”๋ง ํ• ์ˆ˜ ์žˆ๋Š” ์„ ํƒ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค. BrowserModule์€ component, directive, pipe๋กœ ์‚ฌ์šฉ๋˜์–ด ์งˆ ์ˆ˜ ์žˆ๋‹ค. ๋‹น์‹ ์ด ํ•ด๋‹น ๋ชจ๋“ˆ์„ ์ถ”๊ฐ€ํ•˜์˜€์„ ๊ฒฝ์šฐ์— ๋‹น์‹ ์€ ๊ฐ€์ ธ์˜จ ๋ชจ๋“ˆ์—์„œ ๋‚ด ๋ณด๋‚ธ ๋ชจ๋“  ์ง€์‹œ๋ฌธ, ๊ตฌ์„ฑ ์š”์†Œ ๋ฐ ํŒŒ์ดํ”„๋ฅผ ๋ชจ๋“ˆ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. root ๋ชจ๋“ˆ์€ import ๋˜์–ด์งˆ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— exports๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š์ง€๋งŒ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜๋Š” ์žˆ๋‹ค.

ํ•ด๋‹น ๊ธฐ์ˆ ์€ ์ดˆ๋ณด์ž์—๊ฒŒ๋Š” ์นœ์ˆ™ํ•˜์ง€ ์•Š๋Š”๋‹ค. ์šฐ๋ฆฌ๋Š” ์ฒซ ๋ฒˆ์งธ ์žฅ์—์„œ ES6 ๋ฐ TS ๋ชจ๋“ˆ์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐ๋ฅผ ํ•˜์˜€๋‹ค. ์ด ๋ชจ๋“ˆ์€ import, export๋ฅผ ์ •์˜ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๋Š” Angular ๋ชจ๋“ˆ์— ๋Œ€ํ•ด์„œ ์ด์•ผ๊ธฐ ํ•˜๊ณ  ์žˆ๋‹ค.

ES6 ๋˜๋Š” TS import ๊ธฐ๋Šฅ์€ Java์˜ import ๋ฌธ๊ณผ ๊ฐ™์€ ๋ฌธ์ž์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹น์‹ ์˜ ์†Œ์Šค์ฝ”๋“œ์— classes/function๋“ฑ์„ import ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๊ฒƒ์€ ๋˜ํ•œ bundler ๋˜๋Š” ๋ชจ๋“ˆ ๋กœ๋”(Webpack or SystemJS)๋ฅผ ์œ„ํ•œ ์œ„์กด์„ฑ์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ a.ts๊ฐ€ ๋กœ๋“œ๋˜์–ด์กŒ๋‹ค๋ฉด b.ts๋Š” a.ts์—์„œ ์‚ฌ์šฉ๋˜์–ด ์ง€๋ฏ€๋กœ ์šฐ์„ ์ ์œผ๋กœ ๋กœ๋“œ๋˜์–ด์•ผ ํ•œ๋‹ค. Angular ๋˜๋Š” ๊ธฐํƒ€ ํ”„๋ ˆ์ž„ ์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š์ง€ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด ES6 ๋ฐ TypeScript๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ ๋ฐ ๋‚ด๋ณด๋‚ด๊ธฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ž์‹ ์˜ Angular ๋ชจ๋“ˆ (AppModule)์—์„œ Angular ๋ชจ๋“ˆ (์˜ˆ : BrowserModule)์„ ๊ฐ€์ ธ ์˜ค๋Š” ๊ฒƒ์€ ๊ธฐ๋Šฅ์  ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค. BrowserModules์—์„œ ๋‚ด๋ณด๋‚ด๋Š” ๋ชจ๋“  ๊ตฌ์„ฑ ์š”์†Œ, ์ง€์‹œ๋ฌธ ๋ฐ ํŒŒ์ดํ”„๋Š” Angular ๊ตฌ์„ฑ ์š”์†Œ / ํ…œํ”Œ๋ฆฟ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ TypeScript ์ปดํŒŒ์ผ๋Ÿฌ์—์„œ๋Š” ํŠน๋ณ„ํ•œ ์˜๋ฏธ๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { PonyRacerAppComponent } from './app.component';
@NgModule({
  imports: [BrowserModule],
  declarations: [PonyRacerAppComponent],
})
export class AppModule {
}

์ด๊ฒƒ์ด ๋ฃจํŠธ ๋ชจ๋“ˆ์ด๋ฏ€๋กœ Angular์— ์–ด๋–ค ๊ตฌ์„ฑ ์š”์†Œ๊ฐ€ ๋ฃจํŠธ ๊ตฌ์„ฑ ์š”์†Œ (์ฆ‰, ์•ฑ์„ ๋ถ€ํŠธ ์ŠคํŠธ๋žฉ ํ•  ๋•Œ ์‹œ์ž‘๋  ๊ตฌ์„ฑ ์š”์†Œ)์ธ์ง€ ์•Œ๋ ค์ค„ ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์„ค์ • ๊ฐ์ฒด์˜ ๋ถ€ํŠธ ์ŠคํŠธ๋žฉ ํ•„๋“œ๊ฐ€ ํ•„์š”ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { PonyRacerAppComponent } from './app.component';
@NgModule({
  imports: [BrowserModule],
  declarations: [PonyRacerAppComponent],
  bootstrap: [PonyRacerAppComponent]
})
export class AppModule {
}

Bootstrapping the app

๋งˆ์ง€๋ง‰์œผ๋กœ ์šฐ๋ฆฌ๋Š” bootstrapModule ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ฑ์„ ์‹คํ–‰ํ•ด์•ผ ํ•œ๋‹ค. ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋Š” platformBrowserDynamic ๋ฉ”์†Œ๋“œ์— ์˜ํ•ด ๋ฐ˜ํ™˜ ๋œ ์˜ค๋ธŒ์ ํŠธ๋กœ ํ‘œ์‹œ๋œ๋‹ค. bootStrap ๋…ผ๋ฆฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด main.ts์™€ ๊ฐ™์€ ๋‹ค๋ฅธ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด๋ณด์ž.

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

์šฐ๋ฆฌ๋Š” ์•„์ง HTML ํŒŒ์ผ์ด ์—†๋‹ค. index.html ์ด๋ฆ„์˜ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด๋ณด์ž.

<html>
<head></head>
<body>
  <ponyracer-app>
   You will see me while Angular starts the app!
  </ponyracer-app>
</body>
</html>

์ด์ œ HTML ํŒŒ์ผ์— ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผํ•œ๋‹ค. AngularJS 1.x์—์„œ๋Š” ๊ฐ„๋‹จํ–ˆ๋‹ค. angular.js ์šฉ ์Šคํฌ๋ฆฝํŠธ์™€ ์ž‘์„ฑํ•œ ๋ชจ๋“  JS ํŒŒ์ผ ์šฉ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ๋งŒํ•˜๋ฉด ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹จ์ ์žˆ๋‹ค. ์‹œ์ž‘์‹œ์— ๋ชจ๋“  ๊ฒƒ์ด ์ •์ ์œผ๋กœ ๋กœ๋“œ ๋˜์–ด์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€๊ทœ๋ชจ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์‹œ์ž‘ ์‹œ๊ฐ„์ด ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

Angular 2์—์„œ๋Š” ์ƒํ™ฉ์ด ๋”์šฑ ๋ณต์žกํ•ด ์ง€์ง€๋งŒ ๋ณต์žก์„ฑ์—๋Š” ์ถ”๊ฐ€์ ์ธ ํž˜์ด ๋”ฐ๋ฅธ๋‹ค. Angular๋Š” ์ด์ œ ๋ชจ๋“ˆ (ES6 ๋ชจ๋“ˆ)์— ๋ฒˆ๋“ค๋กœ ์ œ๊ณต๋˜๋ฉฐ ์ด๋Ÿฌํ•œ ๋ชจ๋“ˆ์€ ๋™์ ์œผ๋กœ๋กœ๋“œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ „์— ๋ณด์•˜ ๋“ฏ์ด ์šฐ๋ฆฌ์˜ ์•ฑ์€ ๋ชจ๋“ˆ๋กœ ๋ฌถ์—ฌ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

  • ES5์—์„œ๋Š” ๋ชจ๋“ˆ์ด ์กด์žฌํ•˜์ง€ ์•Š๊ณ  ๋ธŒ๋ผ์šฐ์ ธ์—์„œ๋Š” ์˜ค์ง ES5๋ฅผ ์ง€์›ํ•œ๋‹ค.

  • ES6 ์„ค๊ณ„์ž๋Š” ๋ชจ๋“ˆ์„ ์ •์˜ํ•˜๊ณ  ๊ฐ€์ ธ ์˜ค๋Š” ๋“ฑ์˜ ๋ฐฉ๋ฒ•์„ ์ง€์ •ํ•˜์˜€๋‹ค. ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ํŒจํ‚ค์ง€ํ™” ํ•˜๊ณ  ๋กœ๋“œ ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•„์ง ์ง€์ •๋˜์ง€ ์•Š์•˜๋‹ค.

๋ชจ๋“ˆ์„ ๋กœ๋“œ ํ•˜๋ ค๋ฉด ๋„๊ตฌ์— ์˜์กด ํ•ด์•ผํ•œ๋‹ค. SystemJS๋Š” ์†Œํ˜• ๋ชจ๋“ˆ ๋กœ๋”๋กœ์จ HTML ํŽ˜์ด์ง€์— (์ •์ ์œผ๋กœ) ์ถ”๊ฐ€ํ•˜๊ณ  ๋ชจ๋“ˆ์ด ์„œ๋ฒ„์—์žˆ๋Š” ์œ„์น˜๋ฅผ ์•Œ๋ ค์ฃผ๊ณ  ๊ทธ ์ค‘ ํ•˜๋‚˜๋ฅผ ๋กœ๋“œํ•œ๋‹ค. ๋ชจ๋“ˆ ์‚ฌ์ด์˜ ์˜์กด์„ฑ์„ ์ž๋™์œผ๋กœ ํŒŒ์•…ํ•˜๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“ˆ์„ ๋‹ค์šด๋กœ๋“œํ•œ๋‹ค.

์ด๊ฒƒ์€ JS ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ์˜ bazillion์œผ๋กœ ์ด์–ด์งˆ ๊ฒƒ์ด๋‹ค. ๊ฐœ๋ฐœํ•˜๋Š” ๋™์•ˆ ๊ดœ์ฐฎ ์•˜์ง€๋งŒ ์ƒ์‚ฐ์„ ์œ„ํ•ด์„œ๋Š” ๋ฌธ์ œ์ ์ด ๋ฐœ์ƒํ•œ๋‹ค. ๋‹คํ–‰์Šค๋Ÿฝ๊ฒŒ๋„ SystemJS์—๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž‘์€ ๋ชจ๋“ˆ์„ ๋” ํฐ ๋ฌถ์Œ์œผ๋กœ ๋ฌถ์„ ์ˆ˜์žˆ๋Š” ๋„๊ตฌ๊ฐ€ ํ•จ๊ป˜ ์ œ๊ณต๋œ๋‹ค. ๋ชจ๋“ˆ์ด ํ•„์š”ํ•  ๋•Œ, ๊ทธ ๋ชจ๋“ˆ์„ ํฌํ•จํ•œ ๋ฒˆ๋“ค (๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ๋ชจ๋“ˆ๋“ค)์ด ๋‹ค์šด๋กœ๋“œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ ํ•  ์ˆ˜์žˆ๋Š” ์œ ์ผํ•œ ๋„๊ตฌ๋Š” ์•„๋‹ˆ๋ฉฐ ์›ํ•˜๋Š” ๊ฒฝ์šฐ Webpack๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

SystemJS๋ฅผ ์„ค์น˜ํ•ด๋ณด์ž.

npm install --save systemjs

์šฐ๋ฆฌ๋Š” SystemJS๋ฅผ ์ •์ ์œผ๋กœ ๋กœ๋“œํ•˜๊ณ  ๋ถ€ํŠธ ์ŠคํŠธ๋žฉ ๋ชจ๋“ˆ์ด (๋ฉ”์ธ์—) ์–ด๋””์— ์žˆ๋Š”์ง€ ์•Œ๋ ค์ค„ ํ•„์š”๊ฐ€ ์žˆ๋‹ค. @angular์™€ ๊ฐ™์ด ์šฐ๋ฆฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์˜์กด์„ฑ์„ ์–ด๋””์—์„œ ์ฐพ์„ ์ง€ ์•Œ๋ ค์ค„ ํ•„์š”๊ฐ€ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋จผ์ € reflect-metadata์™€ zone.js๋ฅผ ํฌํ•จ ์‹œ์ผœ์•ผํ•œ๋‹ค.

<html>
<head>
  <script src="node_modules/zone.js/dist/zone.js"></script>
  <script src="node_modules/reflect-metadata/Reflect.js"></script>
  <script src="node_modules/systemjs/dist/system.js"></script>
  <script>
   System.config({
   // we want to import modules without writing .js at the end
   defaultJSExtensions: true,
   // the app will need the following dependencies
   map: {
   '@angular/core': 'node_modules/@angular/core/bundles/core.umd.js',
   '@angular/common': 'node_modules/@angular/common/bundles/common.umd.js',
   '@angular/compiler': 'node_modules/@angular/compiler/bundles/compiler.umd.js',
   '@angular/platform-browser': 'node_modules/@angular/platformbrowser/bundles/platform-browser.umd.js',
   '@angular/platform-browser-dynamic': 'node_modules/@angular/platform-browserdynamic/bundles/platform-browser-dynamic.umd.js',
   'rxjs': 'node_modules/rxjs'
   }
   });
   // and to finish, let's boot the app!
   System.import('main');
  </script>
</head>
<body>
  <ponyracer-app>
   You will see me while Angular starts the app!
  </ponyracer-app>
</body>
</html>

From zero to something better with angular-cli

์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช‡๊ฐ€์ง€๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.

  • ์šฐ๋ฆฌ๊ฐ€ ์ผ์„ ๊นจ๋œจ๋ฆฌ์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ํ…Œ์ŠคํŠธ

  • ๋นŒ๋“œ ๋„๊ตฌ, ๋‹ค์–‘ํ•œ ์ž‘์—… (์ปดํŒŒ์ผ, ํ…Œ์ŠคํŠธ, ํŒจํ‚ค์ง€ ๋“ฑ)์„ ์กฐ์œจ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ผ์ด ์–ด๋–ป๊ฒŒ ์ง„ํ–‰๋˜๋Š”์ง€ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ํ•œ ๋ฒˆํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋”๋ผ๋„ ๋ชจ๋“  ๊ฒƒ์„ ์Šค์Šค๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์•ฝ๊ฐ„ ๋ฒˆ๊ฑฐ ๋กœ์šธ ์ˆ˜ ์žˆ๋‹ค.

์ง€๋‚œ ๋ช‡ ๋…„ ๋™์•ˆ ๋งŽ์€ ์†Œ๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ๊ธฐ๊ฐ€ Yeonman์„ ์‚ฌ์šฉํ•˜์—ฌ ๋น›์„ ๋ณด์•˜๋‹ค. ์ด์ „ Angularjs 1.x ๋ฒ„์ ผ์—์„œ๋„ Yeonman์„ ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ณ  2์—์„œ๋„ ๊ทธ๋Ÿฐ ์‹œ๋„๊ฐ€ ์žˆ์—ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ํ˜„์žฌ Google ํŒ€์—์„œ๋Š” angular-cli๋ฅผ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ์‰ฝ๊ฒŒ ์‹œ์ž‘ํ• ์ˆ˜ ์žˆ๊ณ , ๋‹ค์–‘ํ•œ tool, test, packge ๋“ค์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„์ด๋””์–ด๋Š” ์ƒˆ๋กœ์šด ๊ฒƒ์€ ์•„๋‹ˆ๋ฉฐ ์‹ค์ œ๋กœ ๋‹ค๋ฅธ ์ธ๊ธฐ์žˆ๋Š” ํ”„๋ ˆ์ž„ ์›Œํฌ ์ธ EmberJS์™€ ๊ทธ ์œ ๋ช…ํ•œ ember-cli์—์„œ ์ฐฉ์•ˆ ํ•˜์˜€๋‹ค.

์ด ๋„๊ตฌ๋Š” ์•„์ง ๊ฐœ๋ฐœ ์ค‘์ž…๋‹ˆ๋‹ค๋งŒ, ํ–ฅํ›„ Angular 2 ์•ฑ์„ ๋งŒ๋“œ๋Š” ๋ฐ ์žˆ์–ด ์‚ฌ์‹ค์ƒ์˜ ํ‘œ์ค€์ด ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ์‹œ๋„ํ•ด ๋ณผ ํ•„์š”๊ฐ€ ์žˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ์ˆ˜๋™์œผ๋กœํ–ˆ๋˜ ๊ฒƒ๊ณผ ๋˜‘๊ฐ™์€ ํšจ๊ณผ๋ฅผ ๊ฐ€์ง€๊ณ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

npm i -g angular-cli
ng new ponyracer

๊ทธ๋Ÿฌ๋ฉด ํ”„๋กœ์ ํŠธ ponyracer๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ๊ณผ ํ•จ๊ป˜ ์•ฑ์„ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

ng serve

์ด๋ ‡๊ฒŒํ•˜๋ฉด ํ•ซ ๋ฆฌ๋กœ๋“œ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ๋กœ ์ž‘์€ HTTP ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋œ๋‹ค. ์ฆ‰, ํŒŒ์ผ์„ ์ˆ˜์ •ํ•˜๊ณ  ์ €์žฅํ•  ๋•Œ๋งˆ๋‹ค ๋ธŒ๋ผ์šฐ์ €์—์„œ ์•ฑ์ด ์ƒˆ๋กœ ๊ณ ์นจ์ด ๋œ๋‹ค. ์ปดํฌ๋„ŒํŠธ ponyracer ์ƒ์„ฑ๊ณผ ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ๋‹ค๋ฅธ ๊ฐ€๋Šฅ์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ng generate component pony

์ด๋ ‡๊ฒŒํ•˜๋ฉด ๊ด€๋ จ ํ…œํ”Œ๋ฆฟ, ์Šคํƒ€์ผ ์‹œํŠธ ๋ฐ ํ…Œ์ŠคํŠธ ํŒŒ์ผ๊ณผ ํ•จ๊ป˜ ๊ตฌ์„ฑ ์š”์†Œ ํŒŒ์ผ์ด ๋งŒ๋“ค์–ด ์งˆ๊ฒƒ์ด๋‹ค. ์ด ๋„๊ตฌ๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐœ๋ฐœํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฐฐํฌ์™€ ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ์ž‘์—…์„ ๋‹จ์ˆœํ™”ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ ์‹œ์Šคํ…œ๊ณผ ํ•จ๊ป˜ ์ œ๊ณต๋œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด github-pagesplugin์„ ์‚ฌ์šฉํ•˜์—ฌ Github Pages์— ์‹ ์†ํ•˜๊ฒŒ ๋ฐฐํฌ ํ•  ์ˆ˜ ์žˆ๋‹ค.

ng github-pages:deploy

์ด๊ฒƒ์€ ์žฅ๊ธฐ์ ์œผ๋กœ ๋ณด์•˜์„ ๊ฒฝ์šฐ์— ์„ฑ๋Šฅ์ด ์ข‹์„ ๊ฒƒ์ด๋‹ค. ์šฐ๋ฆฌ๋Š” ํ”„๋กœ์ ํŠธ ์ „๋ฐ˜์— ๊ฑธ์ณ ๋™์ผํ•œ ์ฝ”๋“œ ์กฐ์ง, ์•ฑ์„ ๋นŒ๋“œํ•˜๊ณ  ๋ฐฐํฌํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•, ๊ทธ๋ฆฌ๊ณ  ์•„๋งˆ๋„ ์ผ๋ถ€ ์ž‘์—…์„ ๋‹จ์ˆœํ™”ํ•˜๊ธฐ์œ„ํ•œ ๊ฑฐ๋Œ€ํ•œ ์—์ฝ” ์‹œ์Šคํ…œ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ๋ณด์œ ํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ angular-cli๋ฅผ ์‚ดํŽด๋ณด๋„๋ก ํ•ด๋ผ.

Reference URL

Last updated