angular 5 빌드 후에 docker nginx 서버에 적용하기

angular 빌드하기

$ ng build

빌드후에 /dist/퐬더에 생성된 파일을 nginx 서버가 적용 된 곳에 파일을 복사합니다.

localhost/까지는 잘 접속이 되는 것을 확인할 수 있습니다. 그러나, angular 의 RoutingModule을 사용한 주소 뒤에 localhost/some/some2/ 와 같은 주소는 접속이 되지 않습니다.

이를 해결하기 위해서는 아래와 같이 nginx/conf.d/default.conf 파일을 수정해 주어야 합니다.

일단 저는 nginx/1.13.5버전을 사용하고 docker 를 통해서 실행해 놓은 상태입니다.

docker exec -it some-nginx /bin/bash

명령어를 통해서 docker 내부에 접속을 한후에 vim 으로 설정을 변경합니다.

: vim이 실행이 되지않을때에는 apt-get update를 진행후 apt-get install vim를 통해 설치를 하기 바랍니다.

/etc/nginx/conf.d/default.conf 파일을 수정 합니다.

server {
    listen       80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri$args $uri$args/ $uri $uri/ /index.html =404;
    }
...

이대로 접속이 되면 만세!

반응형

Angular 라우팅 적용하기

  • @angular/core = “^5.0.1”

라우팅 기능을 통해서 페이지 이동을 구현하려고 하는데 생각보다 잘 안되서 무니서로 정리해 놓으려고 합니다.
Reference 문서를 살펴보면 가능은 하겠지만, 문서를 보면서 실수한 점에 대해서 기록

install routing module

$ ng generate module app-routing --flat --module=app

설치옵션

–flat : /src/app/ 폴더에 component 를 만들 때처럼 폴더를 생성하지 않고 파일을 생성합니다.
–module=app : AppModule 에 자동으로 import 합니다.

app.module.ts에 자동으로 imports:항목에 추가가 되므로, 따로 app.module 을 설정하지 않아도 되는 장점이 있습니다. 앵귤러는 설정때문에 왔다갔다 하는게 너무 많아요.

app.component.html파일

<div class="container">
  <router-outlet></router-outlet>
</div>

<router-outlet></router-outlet>이 라우팅이 적용되는 위치 입니다. 저는 router-outlet 을 html에 입력을 하지 않아서 적용이 되지 않았습니다.
이 거 찾는데 한시간 걸림. 왜 안되는지!!! 슬프다.

app-routing.module.ts파일

import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';

import { SalesComponent} from './sales/sales.component';
import { NotfoundpageComponent } from './notfoundpage/notfoundpage.component';

const routes: Routes = [
  {path: 'sales/:id', component: SalesComponent},
  { path: '', redirectTo: '', pathMatch: 'full'},
  { path: '**', component: NotfoundpageComponent }
]

@NgModule({
  imports: [ RouterModule.forRoot(routes)],
  exports: [ RouterModule]
})
export class AppRoutingModule {
  constructor() {}
}
반응형

webstorm 에서 자동완성 쌍따옴표를 따옴표로

웹스톰을 기본설치하고 angular 플러그인을 설치하고 난 뒤에 import {} 를 하고 나면 자동완성으로 쌍또옴표를 사용한다

이거 찾는다고 10분을 허비함.

이를 해결하기 위해서는 설정헤서 다음부분을 수정하면 된다.

Imgur

반응형

마무리

To Do 응용 프로그램을 실제 프로토 타입으로 확장해 보겠습니다. 우리는 처음 세장에서 필요한 모든 것을 만들어 작동하는 응용 프로그램을 만들었습니다. 우리는 서비스 태스크를 수정하여 추가 및 제거 메소드를 작성한 다음 Bootstrap 테마를 적용하여 이쁘게 만들어 고겠습니다.

/app폴더에 있는 tasks.service.ts 파일을 수정하면서 시작하겠습니다.

import {TASKS} from './sample.tasks';
import {Injectable} from 'angular2/core';

@Injectable()
export class TaskService {
  getTasks() {
    return TASKS;
  };
  addTask(task) {
    TASKS.push(task);
  };
  deleteTask (task) {
    for (var i=0; i<TASKS.length; i++) {
      if (TASKS[i].id === task.id) {
        TASKS.splice(i,1);
        break;
      }
    }    
  };
}

두가지 메소드를 추가 했습니다.

addTask는 task를 매개변수로 허용하고, deleteTask 또한 task를 매개변수로 허용하고 있습니다.
addTask메소드는 새로운 task를 배열에 추가하고, deleteTask는 전송 된 작업 개체의 ID 를 기반으로 배열에서 작업을 제거 합니다.

다음으로 수정할 파일은 index.html은 app폴더 바깥에 위치하고 있습니다.
Bootstrap CDN 을 통해서 Bootstrap CSS 를 추가할 것입니다.

index.html 를 수정합니다.

<html>
  <head>
    <title>Angular 2 - My Todo List</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <script src="node_modules/es6-shim/es6-shim.min.js"></script>
    <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
    <script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>

    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
    <script>
      System.config({
        packages: {
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('app/main')
            .then(null, console.error.bind(console));
    </script>
  </head>

  <body>
    <my-component>Loading...</my-component>
  </body>
</html>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">

Bootstrap CDN을 추가했습니다.

/app폴더에 위치하고 있는 app.component.ts파일을 수정합니다.

import {Component} from 'angular2/core';
import {HighlightDirective} from './highlight.directive';
import {TaskService} from './task.service';
import {Task} from './tasks';
import {OnInit} from 'angular2/core';

@Component({
  selector: 'my-component',
  templateUrl: 'app/app.component.html',
  directives: [HighlightDirective],
  providers: [TaskService]

})
export class MyComponent {
    public name: String;
    public today: Date;
    public task: String;
    public taskList: Task[];

constructor(private _taskService: TaskService) {
        this.name = 'Angular 2 Rocks !';
        this.today = new Date();       
        this.task = '';
        this.taskList = this._taskService.getTasks();

    }
    removeTask(item) {
         this._taskService.deleteTask(item);
    }
    addNewTask() {
        this._taskService.addTask ( { id: Math.floor((Math.random() * 10) + 10), name : this.task });
        this.task = '';
    }
}

sayMyName() 메소드를 제거하고 deleteTask, addNewTask 메소드를 추가했습니다. 이 앱은 데모앱이므로 따로 ID 등 확인은 없습니다.
프로덕션 환경에서는 이러한 방법을 보다 효과적으로 작동시키기 위해 더 많은 데이터 검증이 필요한 것입니다.

/app 폴더에 있는app.component.html파일을 수정 합니다.

<h1>{{today | date:"fullDate"}}</h1>
<div>
    <div class="form-group">
        <label for="usr">New Task:</label>
        <input [(ngModel)]="task"  class="form-control"> 
    </div>
    <button (click)="addNewTask()"  class='btn-default' myHighlight>Add Task</button>
</div>
<div>
    <div class="list-group">
        <a href="#" (click)="removeTask(item)" *ngFor="#item of taskList" class="list-group-item">{{item.name}}</a>
    </div>
</div>

우리는 목록을 제거하고, 추가 할 수 있는 버튼을 부트스트랩 테마와 함께 적용 했습니다.

마치며

반응형

의속성 주입(Dependency Injection)

의속성 주입(Dependency Injection)은 Angular에서 가장 강력한 기능 중에 하나 입니다.

Angular 1.x 에서의 의존주입은 몇가지 제한 사항이 있었습니다.

내부캐시(Internal cache) : 종손성은 싱글톤 입니다. 라이프 사이클당 한번만 생성
네임스페이스 출동(Namespace collision) : 오직 한가지 유형만을 가질 수 있습니다.
단단한 결합(Tightly coupled) : Angular 1.x 프레임워크에 내장되어 있습니다.

의존성 삽입을 설명하기 위해 다음 예제를 사용합니다.
차를 만드는 클래스를 생성하겠습니다.
일반적인 방법으로 아래와 같습니다.

class Car {
  constructor() {
    this.engine = new Engine();
    this.tyres = Tyres.getInstance();
  }
}

이 방법은 괜찮습니다. 하지만, 우리는 엔진 생성자와 싱글 톤 타이어에서 엔진을 얻을 수 있습니다.
만약 우리가 MockEngine 을 생성자로 대체해서 코드를 테스트해야 한다면 새로운 코드를 작성해야 합니다.
테스트 할 수 잇는 코드를 만들면 우연히 재사용 가능한 코드를 빌드하게 됩니다. 이 코드르 더 재사용 가능하게 만드는 한가지 방법은 TypeScript 생성자를 사용하여 형식과 값을 전달하는 것입니다.
다음은 그 예입니다.

class Car {
  constructor(engine, tires) {
    this.engine = engine;
    this.tyres = tyres;
  }
}

우리는 생성자로부터 의존성 생성을 제거하고 모든 필요한 종속성을 기대학 위해 생성자 함수를 확장했습니다. 이제 코드의 구현을 하드 코딩하지 않았습니다.
우리는 생성자에 옮겼습니다.
새차를 만드려면 다음과 같이 실행하면 됩니다.

var car = new Car(
  new Engine(),
  new Tyres()
);

코드를 테스트 할 필요가 있다면 모의 의존성을 보낼 수 있습니다. 예를 들면 다음과 같습니다.

var car = new Car(
  new MockEngine(),
  new MockTyres()
);

이제, 이것이 의존성 주입입니다.
Angular2 에서의 의존성 주입은 다음과 같이 구성이 됩니다.

인젝터(Injector) : API 를 노출하는 객체입니다.
공급자(Provider) : 인젝터에게 종속성의 인스턴스를 만드는 방법을 알려줍니다.
종속성(Dependency) : 객체를 생성해야 하는 유형

Angular2 에서는 동일한 객체를 만드려면 다음과 같이 정의합니다.

import { Injector } from 'angular2/core';

var injector = Injector.resolveAndCreate([
  Car,
  Engine,
  Tyres
]);

var car = injector.get(Car);

Angular2 에서 import하는 Injector는 Injector.resolveAndCreate()를 생성하는데 도움을 주는 API 를 확장하는 팩토리 함수이며 이는 제공자의 목록을 가져옵니다.

TypeScript 에서는 다음과 같이 Car 클래스를 정의합니다.

class Car {
  constructor(engine: Engine, tires: Tires, doors: Doors) {
    ...
  }
}

이 방법으로 의존성 주입을 생성함으로 이름 충돌 문제를 제거 할 수 있습니다.이 구조화 된 형식은 Angular 1.x 의 모든 문제를 제거 합니다.

반응형

메타데이터, 데이터 바인딩, 서비스

메타데이터 클래스를 처리하는 방법을 Angular에게 알려줍니다. app.component.ts파일에서 클래스를 만들었습니다.
데코레이터(Decorator)는 함수(function)이며, 데코레이터는 무엇을 할지 클래스에 알려줍니다.

@Component({
  selector: 'my-component',
  templateUrl: 'app/app.component.html',
  directives: [HighlightDirective]
})
export class MyComponent {
    public name: String;
    public today: Date;

    constructor() {
        this.name = 'Angular 2 Rocks !';
        this.today = new Date();       
    }
    sayMyName() {
        alert (this.name);
    }
}

여기서 @Component는 데코레이터 입니다. 이 함수에서는 클래스를 구성하는 매개변수를 전달합니다. 데코레이터에 전달하는 파라미터들은 다음과 같습니다.

selector : Angular 에서 바인딩할수 있는 CSS 선택
templateUrl : 템플릿 파일의 위치
directives : 템플릿에 바인딩 할 수 있는 디렉티브 배열
providers : 서비스를 의해 의존관계 주입자들(dependency injection providers)의 배열

데이터 바인딩 방법

데이터바인딩을 사용하면 템플릿의 데이터 구성요소에 바인딩 할 수 있습니다. 데이터 바인딩 형식에는 다음 네가지가 있습니다.

  1. DOM에 다가
  2. DOM에서 직접
  3. 1,2 번 둘다
  4. 속성 및 이벤트 바인딩을 사용하여 속성과 이벤트 바인딩을 결합한 양방향 데이터 바인딩 ngModel

단방향 바인딩

다음 코드를 한번 봅시다

<h1>{{today | date:"fullDate"}}</h1>

<div>
    <button (click)="sayMyName()" myHighlight>Do Something Special</button>
</div>

app.component.html파일 안에서 {{today}}app.component.ts 파일의 today 프로퍼티를 단방향 바인딩을 통해 바인딩하고 있습니다. sayMyName() 함수는 click 이벤트 핸들러에 바인딩 됩니다.

양방향 바인딩

양방향 바인딩을 시연하려면 app.component.html 파일에 <div> 태그를 포함하도록 변경하세요.

<div>
    <input [(ngModel)]="task">
</div>
<div>
    {{task}}
</div>

app.component.ts 파일에서는 아래와 같이 비슷하게 변경해 줍니다.

export class MyComponent {
    public name: String;
    public today: Date;
    public task: string;

    constructor() {
        this.name = 'Angular 2 Rocks !';
        this.today = new Date();
        this.task = '';
    }
    sayMyName() {
        alert (this.name);
    }
}

여기서는 task 프로퍼티에 바인딩했습니다. 사용자가 입력 할 때 입력 내용이 페이지에 나타납니다.

서비스 만들기

Angular2의 서비스는 정의 된 함수가 있는 클래스를 말합니다.무엇이든 서비스가 될 수 있습니다.
JS 파일에 저장된 작업 목록을 읽는 서비스를 작성해 보겠습니다.

/app폴더에 task.service.ts라는 파일을 만들고 다음 파일 추가해 보겠습니다.

import {Injectable} from 'angular2/core';

@Injectable()

export class TaskService {
}

Angular Injectable함수를 포함하고 이 함수를 @Injectable() 데코레이터에 적용했습니다.
TypeScript는 @Injectable 데코레이터를 보고 Angular가 이 서비스에 다른 종속성 주입을 하는데 필요한 메타 데이터를 방출합니다.

작업을 위한 모델을 만들어 보겠습니다.
/app폴더에 tasks.ts라는 새 파일을 만듭니다. 이 파일에서 우리는 다음과 같이 작업을 위한 모델을 생성할 것입니다.

export class Task {
  id: number;
  name: string;
}

JavaScript 배열을 사용하여 새 파일을 만듭니다. 이 파일은 sample.tasks.ts로 다음 내용을 추가 합니다.

import {Task} from './tasks';
export var TASKS: Task[] = [
    {"id": 11, "name": "Buy Bread"},
    {"id": 12, "name": "Buy Milk"},
    {"id": 13, "name": "Buy Soap"}
];

모델을 이 파일에 포함시켰고 이 모델을 가진 배열을 ㅁ나들었습니다. 이 배열은 다음과 같이 TASKS로 내보내집니다.

task.service.ts파일에서 우리는 이 클래스를 포함하고 GET 메소드를 생성할 것입니다. 서비스 파일의 내용을 다음 코드로 바꿉니다.

import {TASKS} from './sample.tasks';
import {Injectable} from 'angular2/core';

@Injectable()

export class TaskService {
  getTasks() {
    return TASKS;
  }
}

모델로 서비스와 데이터를 생성했습니다. 이제 템플릿과 구성 요소를 수정해야 합니다. app.component.ts 파일을 다음과 일치하도록 수정하세요.

import {Component} from 'angular2/core';
import {HighlightDirective} from './highlight.directive';
import {TaskService} from './task.service';
import {Task} from './tasks';

@Component({
  selector: 'my-component',
  templateUrl: 'app/app.component.html',
  directives: [HighlightDirective],
  providers: [TaskService]

})
export class MyComponent {
    public name: String;
    public today: Date;
    public task: String;
    public taskList: Task[];



    constructor(private _taskService: TaskService) {
        this.name = 'Angular 2 Rocks !';
        this.today = new Date();       
        this.task = '';
        this.taskList = this._taskService.getTasks();

    }
    sayMyName() {
        alert (this.name);
    }
}

service 와 tasks 를 포함 시켰습니다.

import {TaskService} from './task.service';
import {Task} from './tasks';

service 를 가능하게 하려면 공급자가 가능해야 합니다. 그래서 @Component 데코레이터에 다음 코드를 넣었습니다.

providers: [TaskService]

service 가 컴포넌트에 노출이 됩니다. taskList를 포함할 배열을 생성하고 Task 유형으로 만듭니다.

export class MyComponent {
    public name: String;
    public today: Date;
    public task: String;
    public taskList: Task[];

    constructor(private _taskService: TaskService) {
        this.name = 'Angular 2 Rocks !';
        this.today = new Date();       
        this.task = '';
        this.taskList = this._taskService.getTasks();

    }
    sayMyName() {
        alert (this.name);
    }
}

생성자에 service에 연결하여 개인 변수에 할당하는 정의가 포함되어 있습니다. 밑줄은 데이터가 외부로 전달되고 있음을 빠르게 확인 할 수 있도록 하기위해 사용됩니다.
this._taskSerivce.getTasks()메소드를 사용하면 서비스 파일에 작업을 가져올 수 있습니다.

app.component.html파일에 다음을추가합니다.

<div>
    <ul>
        <li *ngFor="#item of taskList">{{item.name}}</li>
    </ul>
</div>

*ngFor 다이렉티브를 사용하면 taskList배열을 신속하게 반복할 수 있습니다.

반응형

Angular2 컴포넌트, 디렉티브, 템플릿

이전 코드를 복제하기

Angular2 시작하기에서 Hello World 를 완료했습니다.

이전의 코드를 확장해서 구성요소, 모듈, 템플릿 작업을 해보도록 하겠습니다.

ng2-todolist 폴더를 만들고, 기존에 있던 코드들을 복사합니다.

 # cp -R ng2-helloworld ng2-todolist

package.json파일안에 "name"을 변경합니다.

"name": "ng2-todolist", 

index.html파일안에 title을 변경합니다.

<title>Angular 2 - My Todo List</title>

컴포넌트의 재사용

컴퐤넌트는 페이지에서 다른 요소를 만들고 정의하는 방법입니다. Angular 1에서는 디렉티브, 컨트롤러를 사용하여 컴포넌트 안에서 디렉티브을 찾도록 기능을 구현해야 했습니다.

app/app.component.ts파일을 수정해 보겠습니다.

import {Component} from 'angular2/core'

@Component({
  selector: 'my-component',
  template: '<div><button (click)="sayMyName()">Do Something Special</button></div>'
})
export class MyComponent {
    public name: String;
    constructor() {
        this.name = 'Angular 2 Rocks !';
    }
    sayMyName() {
        alert (this.name);
    }
}

class AppComponent 이름을 MyComponent 로 변경 하였기 때문에 index.html,main.ts 파일안의 내용을 변경해야 합니다.

<my-component>Loading...</my-component>

main.ts 파일 안에 다음으로 수정합니다.

import {bootstrap}    from 'angular2/platform/browser'
import {MyComponent} from './app.component'

bootstrap(MyComponent)

서버를 실행 시켜 봅니다. 버튼과 버튼을 눌렀을 경우에 경고창이 나오는 것을 확인할 수 있을것입니다.

 # npm start

Imgur

디렉티브 사용하기

app폴더에 highlight.directive.ts파일을 만들고 다음 내용을 추가 합니다.

import {Directive, ElementRef} from 'angular2/core';
@Directive({
    selector: '[myHighLight]'
})
export class HighlightDirective {
    constructor(el: ElementRef) {
       el.nativeElement.style.backgroundColor = 'orange';
    }
}

Directive : @directive 데코레이터를 위해 사용
ElementRef : DOM element 에 엑세스 할 수 있도록 허용합니다.

highlight.directive.ts파일을 다음과 같이 변경합니다.

import {Directive, ElementRef} from 'angular2/core';
@Directive({
    selector: '[myHighlight]',
     host: {
    '(mouseenter)': 'onMouseEnter()',
    '(mouseleave)': 'onMouseLeave()'
  }
})
export class HighlightDirective {
    private _el:HTMLElement;
    constructor(el: ElementRef) { this._el = el.nativeElement; }
    onMouseEnter() { this._highlight("yellow"); }
    onMouseLeave() { this._highlight(null); }
    private _highlight(color: string) {
        this._el.style.backgroundColor = color;
    }
}

host : MouseEnter, MouseLeave에서 CSS 변경을 수행하기 위해 호출할 두가지 메소드가 포함되어 있습니다.

템플릿의 위력

Angular는 템플릿을 사용해서 컴포넌트 안에서 클라이언트가 보는 것을 관리합니다. 템플릿에는 보여지기 위한 HTML 코드가 포함되어 있습니다. <script> 태그는 제외 한 대부분 모든 HTML 태그들을 템플릿에서 사용할 수 있습니다.
<html>,<body>,<base>와 같은 태그들을 사용할수는 있지만 실제로 템플릿에는 실제로 적용되지 않고 무시됩니다.
컴포넌트에 템플릿을 추가 하려면 템플릿 테그를 제거하고 templateUrl이라는 테그를 사용합니다.

templateUrl : 템플릿의 경로를 말합니다.

import {Component} from 'angular2/core'
import {HighlightDirective} from './highlight.directive';

@Component({
  selector: 'my-component',
  templateUrl: 'app/app.component.html',
  directives: [HighlightDirective]
})
export class MyComponent {
    public name: String;
    constructor() {
        this.name = 'Angular 2 Rocks !';
    }
    sayMyName() {
        alert (this.name);
    }
}

npm start를 사용하고 있다면 백그라운드에서 코드변경이 자동으로 브라우저에 적용되는 것을 확인할 수 있습니다.

간단히 날짜를 적용해 보겠습니다.
public today:Date 을 추가하고 new Date()를 추가해 봅니다.

app.component.ts부분을 아래와 같이 수정해 봅니다.

export class MyComponent {
    public name: String;
    public today: Date;

    constructor() {
        this.name = 'Angular 2 Rocks !';
        this.today = new Date();       
    }
    sayMyName() {
        alert (this.name);
    }
}

이제 app.component.html파일을 만들고 날짜가 표기 되도록 만들어 봅니다.

<h1>{{today | date:"fullDate"}}</h1>
| 표시
| 표시는 앵귤러1의 필터를 대체하는 파이프입니다. 필터처럼 템플릿 출력 형식을 지정하는데 도움이 됩니다.
반응형

Angular2 를 준비하기

Angular 2 와 Angular 1.x 차이

JavaScript를 기반으로하는 스크립트 언어.

Angular 1.x에 대한 지식이 필요하지 않지만 JavaScript, Node.js 및 npm에 대한 지식이 필요합니다.

Angular 2 는 TypeScriptECMA6 를 포함하고 있습니다.

기존에는 Angular 1.x 를 공부하면 됐지만, 이제는 typescript에 대해서 공부를 해야합니다. 또다른 자바스크립트를 공부하는 느낌입니다.
자나깨나 여러가지 언어를 혼합해서 사용하고 있는데, 이제는 점점 더 정리가 안되고 있습니다.

TypeScript는 JavaScript 확장을 돕기 위해 마이크로소프트에서 개발한 무료 오픈 소스 언어입니다. 고급 자동완성, 탐색 및 리팩터링을 제공합니다. 자세한 내용은 https://www.typescriptlang.org/ 에서 확인 할수 있습니다.

ECMA6는 클래스 및 모듈을 사용할 수있게 해주는 JavaScript 의 표준입니다. http://es6-features.org/ 를 참조하면 됩니다.

개발툴

Microsoft 의 Visual Studio Code 을 추천합니다.

기본적으로 마소에서 만들었기 때문에 TypeScript 언어를 잘 지원하고 있습니다. 개인적으로 Atom.io보다 최적화가 잘되어 있다고 생각합니다.
Atom 은 참여하는 사람들이 많아서 다양한 기능들을 찾을 수 있지만, 어수선합니다. 처음에는 Atom 으로 시작을 했지만, 지금은 Visual Code 에 정착해서 사용하고 있습니다.

폴더세팅

응용 프로그램을 시작하고 실행하기 위한 준비가 되었습니다.

package

package.json을 만들어서 npm 세팅을 하면 되지만, 다음과 같이 하면 기본세팅으로 자동설정이 됩니다.

# npm init --yes

그리고 아래 들어있는 내용은 아래와 같은 내용입니다.

{
  "name": "ng2-helloworld",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

새로운 파일 tsconfig.json을 만듭니다.

# touch tsconfig.json

안에 내용을 다른과 같이 작성합니다.

{
  "compilerOptions": {
    "target": "es5",
    "module": "system",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  },
  "exclude": [
    "node_modules",
    "typings/main",
    "typings/main.d.ts"
  ]
}

이 파일 대부분은 TypeScript 응용 프로그램의 기본 구성입니다. tsconfig.json파일을 처리하는 방법에 대해서 컴파일러에 알져주는 역할을 합니다.
noImplicitAny 변수는 컴파일러에게 변수 선언을 처리하는 방법을 알려줍니다. false로 설정을하면 기본 유형을 any로 설정할 수 있으므로 Angular 2 를 좀 더 쉽게 학습할 수 있습니다.

tsconfig.json에 대한 문서

새로운 파일 typings.json을 만들고 다음 내용을 추가 합니다.

{
  "ambientDependencies": {
    "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd",
    "jasmine": "github:DefinitelyTyped/DefinitelyTyped/jasmine/jasmine.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd"
  }
}

새로운 파일 package.json파일을 만들고 아래 내용을 추가합니다.

{
  "name": "ng2-helloworld",
  "version": "1.0.0",
  "scripts": {
    "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
    "tsc": "tsc",
    "tsc:w": "tsc -w",
    "lite": "lite-server",
    "typings": "typings",
    "postinstall": "typings install"
  },
  "license": "ISC",
  "dependencies": {
    "angular2": "2.0.0-beta.14",
    "systemjs": "0.19.25",
    "es6-shim": "^0.35.0",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.2",
    "zone.js": "0.6.6"
  },
  "devDependencies": {
    "concurrently": "^2.0.0",
    "lite-server": "^2.2.0",
    "typescript": "^1.8.9",
    "typings":"^0.7.12"
  }
}

tsc : 타입스크립트 컴파일러
lite : 실시간으로 파일변경을 감지해서 브라우저에 반영. 앵귤러 앱을 시작하기 위한 위한 파일 서버
typings : typings 툴을 시작
postinstall : npm 설치후에 타이핑 설치 method 실행

여기서 npm install 명령을 실행하셔야 문제가 없습니다.

 # npm install

npm manager 는 진리입니다. 그런데, 최근에는 비슷한 소스 이름으로 올려서 개인정보를 훔쳐가는 일이 발생했다고 하는데, npm install명령을 사용할때 소스 이름을 잘 파악해서 사용해야 되겠습니다.

이제 /app라는 하위폴더를 만들고 다음을 실행합니다.

 # mkdir app
 # cd app

컴포넌트(component) 파일 app.component.ts파일을 생성하고, 아래와 같은 내용을 입력합니다.

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: '<h1>Hello World !</h1>'
})
export class AppComponent { }

이파일은 컴포넌트의 루트 컴포넌트(root component) 파일입니다.
이 파일 안에는 angular2/core 모듈을 가져오는 import와 메타 데이터 객체를 가져오는 @Component데코레이터가 있습니다.
export class Appcomponent{}은 메인 어플리케이션을 가져오기 위해서 사용하는 빈 클래스 입니다.

이제 Angular가 방금 생성 한 구성 요소 파일을 로드 할 수 있도록 파일을 만들어야 합니다.

main.ts라는 파일을 만들고, 파일이 /app폴더에 있는 것을 확인하고 다음 코드들을 입력합니다.

import {bootstrap} from 'angular2/platform/browser'
import {AppComponent} from './app.component'

bootstrap(AppComponent)

bootstrap : 사용하기로 결정한 플랫폼을 기반으로해서 컴포넌트 로딩을 처리합니다.

다시 package.json 이 있는 폴더로 돌아옵니다.

index.html파일을 만들고 다음 코드를 입력합니다.

<html>
  <head>
    <title>Angular 2 Hello World</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <script src="node_modules/es6-shim/es6-shim.min.js"></script>
    <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
    <script src="node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script>

    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>

    <script>
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          }
        }
      });
      System.import('app/main')
            .then(null, console.error.bind(console));
    </script>
  </head>

  <body>
    <my-app>Loading...</my-app>
  </body>
</html>

지금까지 아래와 같은 폴더 구성을 갖고 있을겁니다.

Imgur

다음을 실행해서 제대로 되었는지 확인해 봅닌다.
문제가 없다면 다음과 같은 화면이 나오는 것을 확인 할 수 있습니다.

Imgur

반응형

+ Recent posts