# Angular2 TypeScript > Angular
Angular2는 이전 JS를 사용하던 Angular의 업데이트이다.
처음 Angular2가 만들어 질 때는 AtScript를 사용하였지만,
AtScript에서 필요한 주요기능들이 TypeScript에 모두 포함되었고
결국, TypeScript를 사용하여 만들어졌다.
'Mastering TypeScript' 11장에서는 TypeScript를 사용하는 Angular에 대해 알아보자
<br><br>
on ng : https://nplab.run.goorm.io/
goorm.ide(root) : https://goor.me/jfr4X
---
### App Structure
Angular는 html 코드를 한 html 파일에 모두 작성하지 않고 어플리케이션 구조를 활용한다.
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div><div style="line-height:130%">10</div><div style="line-height:130%">11</div><div style="line-height:130%">12</div><div style="line-height:130%">13</div><div style="line-height:130%">14</div><div style="line-height:130%">15</div><div style="line-height:130%">16</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span>app<span style="color:#039C43"></span><span style="color:#ff3399">-</span>header<span style="color:#039C43"></span><span style="color:#ff3399">></span><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>app<span style="color:#039C43"></span><span style="color:#ff3399">-</span>header<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>sidenav<span style="color:#039C43"></span><span style="color:#ff3399">-</span>container <span style="color:#ff3399">class</span><span style="color:#ff3399">=</span><span style="color:#993333">"full-height-container"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>sidenav #sidenav mode<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"over"</span> </div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#ff3399">class</span><span style="color:#ff3399">=</span><span style="color:#993333">"content-padding"</span> </div><div style="padding:0 6px; white-space:pre; line-height:130%"> [fixedInViewport]<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"true"</span> </div><div style="padding:0 6px; white-space:pre; line-height:130%"> [fixedTopGap]<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"60"</span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> [fixedBottomGap]<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"0"</span> </div><div style="padding:0 6px; white-space:pre; line-height:130%"> [opened]<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"false"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>app<span style="color:#039C43"></span><span style="color:#ff3399">-</span>login<span style="color:#039C43"></span><span style="color:#ff3399">></span><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>app<span style="color:#039C43"></span><span style="color:#ff3399">-</span>login<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>sidenav<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>sidenav<span style="color:#039C43"></span><span style="color:#ff3399">-</span><span style="color:#0099cc">content</span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>div <span style="color:#ff3399">class</span><span style="color:#ff3399">=</span><span style="color:#993333">"content-padding"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> Main Content goes here.</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>div<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>sidenav<span style="color:#039C43"></span><span style="color:#ff3399">-</span><span style="color:#0099cc">content</span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>sidenav<span style="color:#039C43"></span><span style="color:#ff3399">-</span>container<span style="color:#039C43"></span><span style="color:#ff3399">></span></div></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
위 app.component.html 코드를 보면
(1) 에서 헤더 컴포넌트를 <app-header>로 표현한 것과
(2~16) 에서 app.component 내용이 나오는 것을 확인할 수 있다.
방금 말한 것처럼 각 컴포넌트 부분을 <app-root> <app-header> 등과 같이 표현하는데
각 컴포넌트의 ts파일에서 selector 명이 바로 그 이름이 된다.
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div><div style="line-height:130%">10</div><div style="line-height:130%">11</div><div style="line-height:130%">12</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">import</span> ...</div><div style="padding:0 6px; white-space:pre; line-height:130%"> </div><div style="padding:0 6px; white-space:pre; line-height:130%">@Component({</div><div style="padding:0 6px; white-space:pre; line-height:130%"> selector: <span style="color:#993333">'app-header'</span>,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> templateUrl: <span style="color:#993333">'./header.component.html'</span>,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> styleUrls: [<span style="color:#993333">'./header.component.scss'</span>]</div><div style="padding:0 6px; white-space:pre; line-height:130%">})</div><div style="padding:0 6px; white-space:pre; line-height:130%"> </div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">class</span> HeaderComponent implements OnInit {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ...</div><div style="padding:0 6px; white-space:pre; line-height:130%">}</div><div style="padding:0 6px; white-space:pre; line-height:130%"> </div></div><div style="text-align:right;margin-top:-13px;margin-right:5px;font-size:9px;font-style:italic"><a href="http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter</a></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
header.component.ts 코드로 (4) 에서 selector 명을 확인 가능하다.
또한 이렇게 컴포넌트를 사용하기 위해서는 기반이 되는 app에 추가해주어야 하며,
app.module.ts의 declarations에 import한 컴포넌트의 클래스명을 입력하면 된다.
컴포넌트 생성 코드는 아래와 같다.
> ng generate component 모듈명
> #출력문
CREATE src/app/header/header.component.scss (0 bytes)
CREATE src/app/header/header.component.html (21 bytes)
CREATE src/app/header/header.component.spec.ts (626 bytes)
CREATE src/app/header/header.component.ts (276 bytes)
UPDATE src/app/app.module.ts (503 bytes)
컴포넌트의 경우 4가지 파일이 생성되는 것을 볼 수 있으며
그 중에서 'scss, html, ts' 세 파일을 가장 많이 이용하게 된다.
생소한 확장자 명 두 가지 중
이 프로젝트의 경우 scss는 스타일 코드로
Angular 프로젝트 생성시에 다양한 스타일 포맷중 선택하며
spec.ts는 주로 사용하지는 않지만 우리가 프로젝트를 정상적으로 컴파일 하더라도
원하는 기능이 작동되지 않는 경우를 예방하기 위하여 test할 때 사용된다.
---
### Let's add some Modules
Angular에서는 '버튼, 헤더 바, 아이콘, 메뉴 아이템, 다이얼 로그 등' 의
다양하고 유용한 기능을 제공한다.
Material이라 불리며 아래와 같은 코드로 추가할 수 있다.
> ng add @angular/material
> 출력/선택문
? Choose a prebuilt theme name, or "custom" for a custom theme:
Indigo/Pink [ Preview: https://material.angular.io?theme=indigo-pink ]
? Set up global Angular Material typography styles? Yes
? Set up browser animations for Angular Material? Yes
Material을 설치하게 되면 자동으로 Angular의 속성 파일들을 수정해주며 바로 사용 가능하다.
간단한 import 과정만 거치면 되는데 방금 전 컴포넌트를 설명할 때 포넌트를 사용하기 위해서는
기반 앱 컴포넌트의 ts파일에 import후 명시해주면 된다고 하였다.
이렇게 add 명령어를 통하여 추가된 모듈의 경우에는 ts파일의 imports에 입력해준다.
툴바의 예시를 들어보겠다.
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div><div style="line-height:130%">10</div><div style="line-height:130%">11</div><div style="line-height:130%">12</div><div style="line-height:130%">13</div><div style="line-height:130%">14</div><div style="line-height:130%">15</div><div style="line-height:130%">16</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">import</span> { MatToolbarModule } <span style="color:#ff3399">from</span> <span style="color:#993333">'@angular/material/toolbar'</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%"> </div><div style="padding:0 6px; white-space:pre; line-height:130%">@NgModule({</div><div style="padding:0 6px; white-space:pre; line-height:130%"> declarations: [</div><div style="padding:0 6px; white-space:pre; line-height:130%"> AppComponent,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> HeaderComponent</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ],</div><div style="padding:0 6px; white-space:pre; line-height:130%"> imports: [</div><div style="padding:0 6px; white-space:pre; line-height:130%"> BrowserModule,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> AppRoutingModule,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> BrowserAnimationsModule,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> MatToolbarModule</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ],</div><div style="padding:0 6px; white-space:pre; line-height:130%"> </div><div style="padding:0 6px; white-space:pre; line-height:130%"> ...</div><div style="padding:0 6px; white-space:pre; line-height:130%">})</div></div><div style="text-align:right;margin-top:-13px;margin-right:5px;font-size:9px;font-style:italic"><a href="http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter</a></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
보면 (1) 에서 import한 후 (8~13) imports에 입력하였다.
우리가 추가한 MatToolbarModule 외에 기본적으로 추가되는 Angular의 모듈명 또한 확인 가능하다.
하지만 이렇게 계속 추가된 모듈이 늘어간다면
다른 App 구성또한 추가되는 app.module.ts가 굉장히 지저분해 질 것이며
심한 경우 컴포넌트 test마다 각각의 모든 (불필요한)모듈들이 항상 import 될 것이다.
그 것을 방지하기 위해서는 shared module이 필요하다.
> ng generate module shared
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div><div style="line-height:130%">10</div><div style="line-height:130%">11</div><div style="line-height:130%">12</div><div style="line-height:130%">13</div><div style="line-height:130%">14</div><div style="line-height:130%">15</div><div style="line-height:130%">16</div><div style="line-height:130%">17</div><div style="line-height:130%">18</div><div style="line-height:130%">19</div><div style="line-height:130%">20</div><div style="line-height:130%">21</div><div style="line-height:130%">22</div><div style="line-height:130%">23</div><div style="line-height:130%">24</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">import</span> { NgModule } <span style="color:#ff3399">from</span> <span style="color:#993333">'@angular/core'</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">import</span> { BrowserModule } <span style="color:#ff3399">from</span> <span style="color:#993333">'@angular/platform-browser'</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">import</span> { BrowserAnimationsModule } <span style="color:#ff3399">from</span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#993333">'@angular/platform-browser/animations'</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ...</div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">import</span> { MatInputModule } <span style="color:#ff3399">from</span> <span style="color:#993333">'@angular/material/input'</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">import</span> { MatButtonModule } <span style="color:#ff3399">from</span> <span style="color:#993333">'@angular/material/button'</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%">@NgModule({</div><div style="padding:0 6px; white-space:pre; line-height:130%"> imports: [</div><div style="padding:0 6px; white-space:pre; line-height:130%"> BrowserModule,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> BrowserAnimationsModule,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ...</div><div style="padding:0 6px; white-space:pre; line-height:130%"> MatInputModule,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> MatButtonModule</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ],</div><div style="padding:0 6px; white-space:pre; line-height:130%"> exports: [</div><div style="padding:0 6px; white-space:pre; line-height:130%"> BrowserModule,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> BrowserAnimationsModule,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ...</div><div style="padding:0 6px; white-space:pre; line-height:130%"> MatInputModule,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> MatButtonModule</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ]</div><div style="padding:0 6px; white-space:pre; line-height:130%">})</div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">class</span> SharedModule { }</div></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
위 (9~22) 같이 shared.module.ts에 다른 모든 모듈 들을 imports 및 exports하고
app.module.ts에서는 SharedModule 하나만 해결하면 된다.
---
### Angular Application
지금까지 진행된 프로젝트는 쇼핑 사이트의 기반을 만드는 것이였다.
이번에는 헤더 컴포넌트에 하위 컴포넌트로 유저 디테일 사항을 만들어
Material의 버튼 등과 이벤트 처리를 해본다.
위와 같은 방식으로 컴포넌트를 만들고 헤더 컴포넌트의 ts파일에 하위 컴포넌트를 넣으면
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>toolbar color<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"primary"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>span<span style="color:#039C43"></span><span style="color:#ff3399">></span>Switch Sales<span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>span<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>span <span style="color:#ff3399">class</span><span style="color:#ff3399">=</span><span style="color:#993333">"example-spacer"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>span<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>app<span style="color:#039C43"></span><span style="color:#ff3399">-</span>user<span style="color:#039C43"></span><span style="color:#ff3399">-</span>details<span style="color:#039C43"></span><span style="color:#ff3399">></span><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>app<span style="color:#039C43"></span><span style="color:#ff3399">-</span>user<span style="color:#039C43"></span><span style="color:#ff3399">-</span>details<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>toolbar<span style="color:#039C43"></span><span style="color:#ff3399">></span></div></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
(4)와 같이 다른 컴포넌트의 html 코드에 하위 컴포넌트를 사용할 수 있다.
이번에는 html 코드를 작성해보자.
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div><div style="line-height:130%">10</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span>span <span style="color:#ff3399">class</span><span style="color:#ff3399">=</span><span style="color:#993333">"username-span"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span>{{loggedInUserName}}<span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>span<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span>button mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>icon<span style="color:#039C43"></span><span style="color:#ff3399">-</span>button color<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"white"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>icon<span style="color:#039C43"></span><span style="color:#ff3399">></span>shopping_cart<span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>icon<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>button<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span>button mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>icon<span style="color:#039C43"></span><span style="color:#ff3399">-</span>button color<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"white"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>icon<span style="color:#039C43"></span><span style="color:#ff3399">></span>logout<span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>icon<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>button<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span>button mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>icon<span style="color:#039C43"></span><span style="color:#ff3399">-</span>button color<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"white"</span> (click)<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"onLoginClicked()"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>icon<span style="color:#039C43"></span><span style="color:#ff3399">></span>login<span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>icon<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>button<span style="color:#039C43"></span><span style="color:#ff3399">></span></div></div><div style="text-align:right;margin-top:-13px;margin-right:5px;font-size:9px;font-style:italic"><a href="http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter</a></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
평범한 html과 비슷하지만 (2, 3)을 보면 Material의 버튼과 아이콘을 사용하고있으며,
(8) 로그인 버튼에서는 클릭 이벤트에 funtion을 연결해 주고있다.
이제 유저 디테일 사항의 ts로 가서 이벤트에 연결된 function을 작성해보자
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">class</span> UserDetailsComponent implements OnInit {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> loggedInUserName: string <span style="color:#039C43"></span><span style="color:#ff3399">=</span> <span style="color:#993333">"logged_in_user"</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%"> constructor() { }</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ngOnInit(): <span style="color:#ff3399">void</span> {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%"> onLoginClicked() {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">console</span>.log(`UserDetailsComponent : onLoginClicked()`);</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%">}</div></div><div style="text-align:right;margin-top:-13px;margin-right:5px;font-size:9px;font-style:italic"><a href="http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter</a></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
위와 같이 콘솔에 로그를 남기는 간단한 코드를 작성하면
버튼을 눌렀을 때 function이 잘 작동하게 된다.
하지만 이렇게 이벤트를 처리하게 되면
이벤트가 발생한 child 컴포넌트 내에서만 작용할 수 있다.
---
### Event Emitter
앵귤러의 Event Emitter는 child 컴포넌트가 parent에 메시지를 보낼 수 있게 해준다.
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">import</span> { EventEmitter, Output } <span style="color:#ff3399">from</span> <span style="color:#993333">'@angular/core'</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">class</span> UserDetailsComponent implements OnInit {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> .. existing code</div><div style="padding:0 6px; white-space:pre; line-height:130%"> @Output() notify <span style="color:#039C43"></span><span style="color:#ff3399">=</span> <span style="color:#ff3399">new</span> EventEmitter();</div><div style="padding:0 6px; white-space:pre; line-height:130%"> onLoginClicked() {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">console</span>.log(`UserDetailsComponent : onLoginClicked()`);</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">this</span>.notify.emit(<span style="color:#993333">"UserDetailsComponent : emit value"</span>);</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%">}</div></div><div style="text-align:right;margin-top:-13px;margin-right:5px;font-size:9px;font-style:italic"><a href="http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter</a></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
우선 Angular에서 EventEmitter를 import 해준다.
하지만 EventEmitter가 메시지를 보내기 위해서는 output 속성이 필요하다.
(4)를 보면 @Output notify 특성을 만들어 EventEmitter를 대신 처리할 수 있게 해주었다.
그리고 (5~8) 클릭 이벤트 처리 funtion에서 notify 특성을 사용하여 메시지를 보낸다.
여기서 child 컴포넌트가 할 수 있는 일은 끝난다.
이제 parent가 메시지를 받아줄 차례다.
컴포넌트의 클릭 이벤트를 작성할 때
우선, html에 클릭 이벤트를 처리 할 function을 지정해준다.
parent인 헤더 컴포넌트의 html로 가보자.
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>toolbar color<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"primary"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>span<span style="color:#039C43"></span><span style="color:#ff3399">></span>Board Sales<span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>span<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>span <span style="color:#ff3399">class</span><span style="color:#ff3399">=</span><span style="color:#993333">"example-spacer"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>span<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span>app<span style="color:#039C43"></span><span style="color:#ff3399">-</span>user<span style="color:#039C43"></span><span style="color:#ff3399">-</span>details (notify)<span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#993333">"onUserDetailsEvent($event)"</span><span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> </div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>app<span style="color:#039C43"></span><span style="color:#ff3399">-</span>user<span style="color:#039C43"></span><span style="color:#ff3399">-</span>details<span style="color:#039C43"></span><span style="color:#ff3399">></span></div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#039C43"></span><span style="color:#ff3399"><</span><span style="color:#039C43"></span><span style="color:#ff3399">/</span>mat<span style="color:#039C43"></span><span style="color:#ff3399">-</span>toolbar<span style="color:#039C43"></span><span style="color:#ff3399">></span></div></div><div style="text-align:right;margin-top:-13px;margin-right:5px;font-size:9px;font-style:italic"><a href="http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter</a></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
(4)를 보면 child 컴포넌트에 notify에 대한 처리 funtion이 추가되었다.
전달받는 매개변수명은 prefix로 $심볼을 붙여준다.
child에서 그랬던 것 처럼 ts에서 원하는 function을 작성해주자
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">class</span> HeaderComponent implements OnInit {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> constructor() { }</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ngOnInit(): <span style="color:#ff3399">void</span> {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%"> onUserDetailsEvent(<span style="color:#0099cc">event</span>: any) {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">console</span>.log(`<span style="color:#0099cc">event</span> : ${<span style="color:#0099cc">event</span>}`)</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%">}</div></div><div style="text-align:right;margin-top:-13px;margin-right:5px;font-size:9px;font-style:italic"><a href="http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter</a></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
항상 그래왔던 것 처럼 매개변수의 자료형을 지정해주어야 한다.
ts에서는 TypeScript를 사용하니 $를 붙일 필요는 없다.
하지만 콘솔에 뛰워지는 로그 메시지의 변수명은 $가 필요하니 코드를 보고 헷갈리지 말자.
하지만 EventEmitter에도 2가지 문제점이 발생한다.
1. 직접 연결된 parent 이외의 컴포넌트에 메시지를 보내려면
체인처럼 모두 연결되어 있어야 한다는 것
(계속해서 parent의 parent로 반복해서 보내야한다.)
2. 매개변수의 자료형이 any로 강제되기에 다른 특정 구조를 다루기 쉽지않다는 것
<br>
이 두가지 문제를 해결하기 위해서는 아래의 방법을 시도해보자.
---
### Angular Service
Domain Events Desgin Pattern을 사용하는 메커니즘은
다양한 클래스들이 이벤트를 확인할 수 있게해준다.
우리의 App안에서 어떠한 클래스던지 이벤트를 발생시키고,
어떠한 클래스던지 그 이벤트를 확인할 수 있게 된다는 것이다.
DEDP의 기본 구조는 모든 클래스가 접속할 수 있는 single event bus를 만든다.
그러면 클래스가 특정 이벤트를 event bus에서 받거나 반대로 보낼 수 있다.
9장에서 본 BroadcastService 클래스는 event bus 역할을 해준다.
Angular CLI를 사용하여 service를 만들어보자.
> ng generate service services/broadcast
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div><div style="line-height:130%">10</div><div style="line-height:130%">11</div><div style="line-height:130%">12</div><div style="line-height:130%">13</div><div style="line-height:130%">14</div><div style="line-height:130%">15</div><div style="line-height:130%">16</div><div style="line-height:130%">17</div><div style="line-height:130%">18</div><div style="line-height:130%">19</div><div style="line-height:130%">20</div><div style="line-height:130%">21</div><div style="line-height:130%">22</div><div style="line-height:130%">23</div><div style="line-height:130%">24</div><div style="line-height:130%">25</div><div style="line-height:130%">26</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">interface</span> IBroadcastEvent {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> key: EventKeys;</div><div style="padding:0 6px; white-space:pre; line-height:130%"> data?: any;</div><div style="padding:0 6px; white-space:pre; line-height:130%">}</div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">enum</span> EventKeys {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ALL <span style="color:#039C43"></span><span style="color:#ff3399">=</span> <span style="color:#993333">"all-events"</span>,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> LOGIN_BUTTON_CLICKED <span style="color:#039C43"></span><span style="color:#ff3399">=</span> <span style="color:#993333">"login_button_clicked"</span>,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> USER_LOGIN_EVENT <span style="color:#039C43"></span><span style="color:#ff3399">=</span> <span style="color:#993333">"user_login_event"</span></div><div style="padding:0 6px; white-space:pre; line-height:130%">}</div><div style="padding:0 6px; white-space:pre; line-height:130%">@Injectable({</div><div style="padding:0 6px; white-space:pre; line-height:130%"> providedIn: <span style="color:#993333">'root'</span></div><div style="padding:0 6px; white-space:pre; line-height:130%">})</div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">class</span> BroadcastService {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#ff3399">private</span> _eventBus <span style="color:#039C43"></span><span style="color:#ff3399">=</span> <span style="color:#ff3399">new</span> Subject<span style="color:#039C43"></span><span style="color:#ff3399"><</span>IBroadcastEvent<span style="color:#039C43"></span><span style="color:#ff3399">></span>();</div><div style="padding:0 6px; white-space:pre; line-height:130%"> on(key: EventKeys): Observable<span style="color:#039C43"></span><span style="color:#ff3399"><</span>string<span style="color:#039C43"></span><span style="color:#ff3399">></span> {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#ff3399">return</span> <span style="color:#0099cc">this</span>._eventBus.asObservable().pipe(</div><div style="padding:0 6px; white-space:pre; line-height:130%"> filter(</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">event</span> <span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#039C43"></span><span style="color:#ff3399">></span> <span style="color:#0099cc">event</span>.key <span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#039C43"></span><span style="color:#ff3399">=</span> key <span style="color:#039C43"></span><span style="color:#ff3399">|</span><span style="color:#039C43"></span><span style="color:#ff3399">|</span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">event</span>.key <span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#039C43"></span><span style="color:#ff3399">=</span> EventKeys.ALL),</div><div style="padding:0 6px; white-space:pre; line-height:130%"> map(<span style="color:#0099cc">event</span> <span style="color:#039C43"></span><span style="color:#ff3399">=</span><span style="color:#039C43"></span><span style="color:#ff3399">></span> <span style="color:#0099cc">event</span>.data));</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%"> broadcast(key: EventKeys, data: string) {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">this</span>._eventBus.next({ key, data });</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%"> constructor() { }</div><div style="padding:0 6px; white-space:pre; line-height:130%">}</div></div><div style="text-align:right;margin-top:-13px;margin-right:5px;font-size:9px;font-style:italic"><a href="http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter</a></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
추가한 서비스에 제공된 Broadcast의 코드를 작성한다.
여기서 우리가 눈여겨 볼 곳은 enum 이벤트 키와 @Injectable이다.
enum EventKeys의 각 상수들은
로그인 버튼과 제출 버튼의 이벤트를 구별하는 역할을 하게된다.
@Injectable은 Dependncy Injection Framework로 인해 주입이 가능한 상태로 만들어준다.
DI는 아래에서 설명하도록 하겠다.
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div><div style="line-height:130%">10</div><div style="line-height:130%">11</div><div style="line-height:130%">12</div><div style="line-height:130%">13</div><div style="line-height:130%">14</div><div style="line-height:130%">15</div><div style="line-height:130%">16</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%">@NgModule({</div><div style="padding:0 6px; white-space:pre; line-height:130%"> declarations: [</div><div style="padding:0 6px; white-space:pre; line-height:130%"> AppComponent,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> HeaderComponent,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> UserDetailsComponent</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ],</div><div style="padding:0 6px; white-space:pre; line-height:130%"> imports: [</div><div style="padding:0 6px; white-space:pre; line-height:130%"> AppRoutingModule,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> SharedModule</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ],</div><div style="padding:0 6px; white-space:pre; line-height:130%"> providers: [</div><div style="padding:0 6px; white-space:pre; line-height:130%"> BroadcastService</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ],</div><div style="padding:0 6px; white-space:pre; line-height:130%"> bootstrap: [AppComponent]</div><div style="padding:0 6px; white-space:pre; line-height:130%">})</div><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">class</span> AppModule { }</div></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
만들어진 서비스는 app.module.ts에서 (11) providers에 추가하여 사용 가능하다.
---
### Angular Dependency Injection
Angular는 컴포넌트에 서비스를 제공하기 위해서 DI라는 기술을 사용한다.
클래스는 의존하는 서비스의 인스턴스를 요청하고,
Angular는 런타임에 이것을 해결한다.
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div><div style="line-height:130%">10</div><div style="line-height:130%">11</div><div style="line-height:130%">12</div><div style="line-height:130%">13</div><div style="line-height:130%">14</div><div style="line-height:130%">15</div><div style="line-height:130%">16</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">class</span> UserDetailsComponent implements OnInit {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> loggedInUserName: string <span style="color:#039C43"></span><span style="color:#ff3399">=</span> <span style="color:#993333">"logged_in_user"</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%"> constructor(<span style="color:#ff3399">private</span> broadcastService: BroadcastService) {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%"> ngOnInit(): <span style="color:#ff3399">void</span> {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%"> @Output() notify <span style="color:#039C43"></span><span style="color:#ff3399">=</span> <span style="color:#ff3399">new</span> EventEmitter();</div><div style="padding:0 6px; white-space:pre; line-height:130%"> onLoginClicked() {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">console</span>.log(`UserDetailsComponent : onLoginClicked()`);</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">this</span>.notify.emit(<span style="color:#993333">"UserDetailsComponent : emit value"</span>);</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">this</span>.broadcastService.broadcast(</div><div style="padding:0 6px; white-space:pre; line-height:130%"> EventKeys.LOGIN_BUTTON_CLICKED,</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#993333">"UserDetailsComponent: LOGIN_BUTTON_CLICKED"</span></div><div style="padding:0 6px; white-space:pre; line-height:130%"> );</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%">}</div></div><div style="text-align:right;margin-top:-13px;margin-right:5px;font-size:9px;font-style:italic"><a href="http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter</a></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
Di는 컴포넌트의 (3) constructor를 통해 작동하게 된다.
constructor는 Angular가 직접적으로 컴포넌트의 lifecycle을 확인하여
발생한 이벤트를 낚아챌 수 있게해준다.
(8~14)를 보면 BroadcastService에 대한 부분이 추가되어
어떠한 이벤트가 발생되었는지에 대하여 이벤트 키와 메시지를 전달하는 것을 확인할 수 있다.
이제 메시지가 전달 되었으니 기반 app.component에 Material의 사이드 패널과 폼을 사용하여
로그인 패널을 만들고 그것을 이벤트를 처리하여 보자.
(DI에 집중하기 위하여 사이드 패널과 폼 코드는 생략한다.)
<div class="colorscripter-code" style="color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important; position:relative !important;overflow:auto"><table class="colorscripter-code-table" style="margin:0;padding:0;border:none;background-color:#fafafa;border-radius:4px;" cellspacing="0" cellpadding="0"><tr><td style="padding:6px;border-right:2px solid #e5e5e5"><div style="margin:0;padding:0;word-break:normal;text-align:right;color:#666;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="line-height:130%">1</div><div style="line-height:130%">2</div><div style="line-height:130%">3</div><div style="line-height:130%">4</div><div style="line-height:130%">5</div><div style="line-height:130%">6</div><div style="line-height:130%">7</div><div style="line-height:130%">8</div><div style="line-height:130%">9</div><div style="line-height:130%">10</div><div style="line-height:130%">11</div><div style="line-height:130%">12</div><div style="line-height:130%">13</div></div></td><td style="padding:6px 0;text-align:left"><div style="margin:0;padding:0;color:#010101;font-family:Consolas, 'Liberation Mono', Menlo, Courier, monospace !important;line-height:130%"><div style="padding:0 6px; white-space:pre; line-height:130%"><span style="color:#ff3399">export</span> <span style="color:#ff3399">class</span> AppComponent {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> title <span style="color:#039C43"></span><span style="color:#ff3399">=</span> <span style="color:#993333">'angular-app'</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%"> @ViewChild(<span style="color:#993333">"sidenav"</span>) sidenav: MatSidenav <span style="color:#039C43"></span><span style="color:#ff3399">|</span> <span style="color:#0099cc">null</span> <span style="color:#039C43"></span><span style="color:#ff3399">=</span> <span style="color:#0099cc">null</span>;</div><div style="padding:0 6px; white-space:pre; line-height:130%"> constructor(broadCastService: BroadcastService) {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> _.bindAll(<span style="color:#0099cc">this</span>, <span style="color:#993333">"onLoginClicked"</span>);</div><div style="padding:0 6px; white-space:pre; line-height:130%"> broadCastService.on(EventKeys.LOGIN_BUTTON_CLICKED)</div><div style="padding:0 6px; white-space:pre; line-height:130%"> .subscribe(<span style="color:#0099cc">this</span>.onLoginClicked);</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%"> onLoginClicked(<span style="color:#0099cc">event</span>: string) {</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">console</span>.log(`AppComponent received : ${<span style="color:#0099cc">event</span>}`);</div><div style="padding:0 6px; white-space:pre; line-height:130%"> <span style="color:#0099cc">this</span>.sidenav?.open();</div><div style="padding:0 6px; white-space:pre; line-height:130%"> }</div><div style="padding:0 6px; white-space:pre; line-height:130%">}</div></div><div style="text-align:right;margin-top:-13px;margin-right:5px;font-size:9px;font-style:italic"><a href="http://colorscripter.com/info#e" target="_blank" style="color:#e5e5e5text-decoration:none">Colored by Color Scripter</a></div></td><td style="vertical-align:bottom;padding:0 2px 4px 0"><a href="http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white"><span style="font-size:9px;word-break:normal;background-color:#e5e5e5;color:white;border-radius:10px;padding:1px">cs</span></a></td></tr></table></div>
####
app.component.ts코드이다.
(3)에서 Material의 사이드 패널의 변수를 추가한다.
@ViewChild 데코레이터는 parent가 직접 적으로 제어를 할 수 있게해준다.
(4~8)을 보면 bindAll을 사용하여 클릭 이벤트 function이 호출되었는지 확인하고 이벤트 키를 붙여 함수를 실행시킨다.
(9~11)을 보면 콘솔에 log를 남김과 동시에 Metarial의 사이드 패널을 여는 것을 확인할 수있다.
이번 장은 여기서 끝내도록 한다.