지난 번에 vue.js와 react로 comment sample을 만들었는데 이번엔 angular로 만들어보기로 했다.
AppModule
platform-browser-dynamic를 사용해서 AppModule
을 로드하는 main.ts는 건너뛰고 바로 AppModule
로 들어간다. angular의 특징은 필요한 component, provider들을 미리 NgModule
에 다 적어주고 시작을 해야한다는 거다.
개발을 하면서 component가 하나씩 늘어나고 service도 하나씩 늘어날텐데 그때마다 이 파일을 수정해줘야 한다. 중간에 구조를 바꾸면서 CommentFormComponent
, CommentService
를 추가했는데 여기다가 추가해주는 것은 조금 번거로웠다.
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './components/app.component.js';
import { CommentFormComponent } from './components/comment-form.component.js';
import { CommentService } from './components/comment.service.js'
@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ AppComponent, CommentFormComponent ],
bootstrap: [ AppComponent ],
providers: [ CommentService ]
})
export class AppModule { }
AppComponent
AppComponent
는 bootstrap으로 지정되어 있다. 앱의 시작이라는 말이다. 그래서 그런지 파일이 좀 크다. list도 따로 분리했으면 좀 더 괜찮았을텐데 굳이 나누진 않았다. 그리고 template로 따로 분리했다면 파일이 좀 더 작아졌겠지만 그러지 않았다.
react의 state, prop에 익숙해져서 그런지 angular도 그런식으로 만들려고 했다. '근데 하위 component에 method는 어떻게 넘겨주지?'라는 생각을 했다. 그런데 angular는 data의 관리를 service에 모두 위임한다. constructor
가 commentService
를 받도록 하고 데이터를 가져올때 commentService
를 사용한다. view에서 직접 사용할 data만 component가 가진다.
import { Component, OnInit } from '@angular/core';
import { Comment } from './comment.js'
import { CommentService } from './comment.service.js'
@Component({
selector: 'comment-app',
template: `
<div class="app">
<div>{{count}} Comments</div>
<button *ngIf="hasMore" class="btn-more" (click)="onLoadMore()">more comment</button>
<div *ngFor="let comment of comments">
<div class="comment">
<div class="info">{{comment.created}}</div>
<div class="message">{{comment.message}}</div>
</div>
</div>
<comment-form></comment-form>
</div>
`,
})
export class AppComponent implements OnInit {
count = 6;
hasMore = true;
comments: Comment[];
constructor(private commentService: CommentService) { }
ngOnInit() { this.getComments() }
getComments() {
this.comments = this.commentService.getComments();
this.count = this.commentService.getCommentCount();
this.hasMore = this.count !== this.comments.length;
}
onLoadMore() {
this.commentService.loadMoreComments();
this.getComments();
}
}
CommentService
CommentService는 @Injectable
을 사용해서 Component들에 inject되도록 하고 내부에 실제 data들을 가진다. react로 치면 redux의 reducer의 역할과 비슷하다.
import { Injectable } from '@angular/core';
import { Comment } from './comment.js'
@Injectable()
export class CommentService {
count: number = 6;
hasMore: any = true;
comments: Comment[] = [
{id: 5, message:'Comment 5', created: new Date(new Date().getTime() - 600000)},
{id: 6, message:'Comment 6', created: new Date(new Date().getTime() - 500000)}
];
getCommentCount(): number {
return this.count
}
getComments(): Comment[] {
return this.comments
}
loadMoreComments(): void {
this.comments = [
{id: 1, message: 'Comment 1', created: new Date(new Date().getTime() - 1000000)},
{id: 2, message: 'Comment 2', created: new Date(new Date().getTime() - 900000)},
{id: 3, message: 'Comment 3', created: new Date(new Date().getTime() - 800000)},
{id: 4, message: 'Comment 4', created: new Date(new Date().getTime() - 700000)},
...this.comments
];
}
addComment(message: string): void {
this.comments.push({
id: this.count + 1,
message: message,
created: new Date()
});
this.count++;
}
}
CommentFormComponent
CommentFormComponent는 message
를 ngModel
로 사용해서 CommentService
에 새로운 message를 전달한다.
import { Component } from '@angular/core';
import { Comment } from './comment.js'
import { CommentService } from './comment.service.js'
@Component({
selector: 'comment-form',
template: `
<form class="form" (submit)="onAdd(message)">
<label>message</label>
<input [(ngModel)]="message" name="message" class="text" type='text' />
<button type='submit'>submit</button>
</form>
`,
})
export class CommentFormComponent {
message: string = "";
constructor(private commentService: CommentService) { }
onAdd(message: string) {
this.commentService.addComment(message);
this.message = "";
}
}
angular를 시작하는 것은 아주 멀고 멀었다. 시간을 들여서 하나하나 보다보니 그래도 뭔가 만들만한 수준으로 이해가 되긴 한다. 그런데 아직 production level로 사용하려면 어떻게 해야하는지 감이 안온다. 지금 코드도 dynamic으로 로드하고 있어서 수많은 js파일을 실시간으로 로드하는 것이다. 이런 부분에서 공식 문서에서 답을 찾기가 어렵다. 너무 당연하고 쉬운 방법이라 굳이 쓸 필요가 없었을까? 잘 모르겠다.
좋은 점이라면 그나마 vue.js보다는 코드 자체가 이해하기 쉬운형태이고... 아니다. 다시 처음시작하는 사람의 마음으로 보니 그렇지 않다. 매우매우 어렵다. 일단 typescript를 완전히 마스터하지 않는다면 angular는 시작할 생각도 하지 않는 것이 좋아보인다. typescript는 좋지만 너무 어렵다.
일단 샘플코드를 만들기는 했지만 과연 angular를 production으로 사용하는 곳이 많이 있을까싶다. 조금 더 알아보기는 하겠지만 난 react를 계속 할 것 같다.