My Profile Photo

DongChanS's blog


수학과 학생의 개발일지


Angular (5) Tutorial - 두개의 기능을 분리하기

위의 튜토리얼은 https://angular.io/tutorial 을 참고하였습니다.

1) Master/Detail Components

이전에는 우리가 Master와 Detail 부분을 한곳에 몰아넣었는데,

이렇게 많은 코드를 한쪽에 넣는 것은 가독성이나 유지보수 측면에서 좋지 않습니다.

따라서 이 두 기능을 두 컴포넌트로 분리해서 넣어보도록 합시다.

1-1. Make the hero-detail component

먼저 detail 페이지 부분을 맡을 hero-detail 컴포넌트를 만들어봅시다.

ng generate component hero-detail

어찌됬건 hero-detail 컴포넌트에는 detail을 표시하는 부분들이 들어갈텐데

그 부분을 하나의 컴포넌트로 뭉치면, heros 컴포넌트는 대충 이런 모양일 것입니다.


<!-- heroes/heroes.component.html -->
<h2>히어로들</h2>
<ul>
  <li class="hero-list"
      *ngFor="let hero of heroes"
      [class.selected]="hero === selectedHero"
      [class.onMouse]="hero === hoveredHero"
      (click)="onSelect(hero)"
      (mouseover)="onMouse(hero)">
    <div>이름 : {{hero.name}}</div>
    <div>번호 : {{hero.id}}</div>
  </li>
</ul>


<app-hero-detail></app-hero-detail>

그러기 위해서는 hero-detail 컴포넌트에는 아까 넣었던 detail부분의 html파일을 넣어줘야 할 것입니다.

(물론 아예 부모 단계의 component에 넣는다고 생각할 수도 있지만, 부모단계에서는 selectedHero가 정의되지 않았고, 이 값을 직접적으로 이용해야 하므로, hero 컴포넌트 밑에서 정의하는게 편합니다.)

그런데, selectedHero 멤버변수는 hero-detail 컴포넌트에는 정의되지 않은 변수이므로, 이름을 hero로 바꿔줍시다.


<!-- hero-detail/hero-detail.components.html -->
<div *ngIf="hero">
    <h2>{{hero.name | uppercase}} Details</h2>
    <div><span>id: </span>{{hero.id}}</div>
    <div>
        <label>name:
            <input [(ngModel)]="hero.name" placeholder="name" />
        </label>
    </div>
</div>

1-2. Add the @Input() hero property

  1. 일단 detail 컴포넌트에 hero라는 변수가 바인딩되어 있는데 얘는 일단 Hero 클래스의 객체니까 먼저 Hero 클래스를 임포트합시다.

  2. 그 다음에는 selectedHero의 값을 detail 컴포넌트에 이식해야 합니다.

    이런 [] 문법은 Angular의 property binding 입니다.

    vue.js의 그 v-bind와 똑같은데.. 뭔가 component 단위로 크게 바인딩을 하다 보니 상당히 낯선 느낌이 듭니다.

    <app-hero-detail [hero]="selectedHero"></app-hero-detail>
    

    이런식의 표현을 통해 넣을 수 있습니다.

  3. 그런데 이런 표현은 Input 라이브러리에 의해서 지원됩니다. 따라서 임포트합시다.

    (아마 다른 컴포넌트로 변수를 넣어주기 위해서는 Input 라이브러리를 사용해야 하는 듯 합니다.)

    // hero-detail/hero-detail.components.ts
    import { Input } from '@angular/core';
    
  4. Input 라이브러리에 의해서 이식된 값은 @Input() 데코레이터를 통해서 선언해야 합니다.

    // hero-detail/hero-detail.components.ts
    export class HeroDetailComponent implements OnInit {
      @Input() hero: Hero;
    }
    

그러면 똑같이 작동하는 모습을 볼 수 있습니다.

1-3. 장점

  1. Heros 컴포넌트가 단순해짐
  2. Heros 컴포넌트를 건들지 않고도 Hero-Detail 컴포넌트를 발전시킬 수 있음.
  3. Hero-Detail 컴포넌트를 건들지 않고도 Heros 컴포넌트를 발전시킬 수 있음.
  4. 다른 컴포넌트에도 Hero-Detail 컴포넌트를 재사용할 수 있음.
comments powered by Disqus