히어로들의 여행 : 4. 서비스 추가하기

Sang heon lee·2022년 8월 31일
0

히어로들의 여행

목록 보기
4/6

HeroService 생성하기

  • ng g s hero 로 Hero.service.ts 파일 생성

  • @Injectable 데코레이터는 해당 클래스가 의존성 주입 시스템에 포함이 되었다. 그래서 다른 컴포넌트 등에서 의존성으로 주입받을수 있으며 , 이 클래스도 의존성을 주입 받을 수 있다.

// src/app/service/hero.service.ts

import { Injectable } from '@angular/core';
import { HEROES } from '../mock';
import { Hero } from '../model/data';

@Injectable({
  providedIn: 'root',
})
export class HeroService {
  constructor() {}

  getHeroes(): Hero[] {
    return HEROES;
  }
}

HeroService 주입하기

  • 생성한 HeroService 타입의 heroService 인자를 생성하고 이 인자를 private로 지정합니다.

    constructor(private heroService: HeroService) {
       this.getHeroes();
     }
  • Angular 가 해당 HeroComponent를 생성할 때 의존성 주입 시스템이 HeroService의 인스턴스를 찾아서 heroService 라는 인자에 전달하여 의존성을 주입한다.

    // src/app/component/heroes/heroes.component.ts
    
    import { Component, OnInit } from '@angular/core';
    import { HSModel } from 'src/app/model';
    import { HeroService } from 'src/app/service/hero.service';
    
    @Component({
      selector: 'app-heroes',
      templateUrl: './heroes.component.html',
      styleUrls: ['./heroes.component.scss'],
    })
    export class HeroesComponent implements OnInit {
      heroes: HSModel.Hero[] = [];
      selectedHero?: HSModel.Hero;
    
      constructor(private heroService: HeroService) {
        this.getHeroes();
      }
    
      ngOnInit(): void {}
    
      onSelect(hero: HSModel.Hero): void {
        this.selectedHero = hero;
      }
    
      getHeroes(): void {
        this.heroes = this.heroService.getHeroes();
      }
    }
    

    옵저버블 데이터

  • 실제로는 데이터를 서버에서 가져온다. 서버에서 데이터를 가져오는 경우에는 비동기로 동작하여 데이터를 가져와야 하기에 this.heroes = this.heroService.getHeroes(); 문구는 비동기로 동작해야 한다.

  • Angular가 제공하연 HttpClient.get 메소드는 Observable 을 반환한다.

    // src/app/service/hero.service.ts
    
    import { Injectable } from '@angular/core';
    import { Observable, of } from 'rxjs';
    import { HEROES } from '../mock';
    import { Hero } from '../model/data';
    
    @Injectable({
      providedIn: 'root',
    })
    export class HeroService {
      constructor() {}
    	
      // 실제 동작은 서버에 요청을 하여 데이터를 받아오므로
      // 비동기로 동작하기에 Observable 타입으로 설정한다.
      getHeroes(): Observable<Hero[]> {
        const heroes = of(HEROES);
        return heroes;
      }
    }
  • this.heroService.getHeroes() 함수가 서버에 요청을 하여 데이터를 받기에 Observable 타입을 반환하는데, 반환 시점은 함수를 실행한 직후 일 수도 있고 몇분 후일수도 있습니다.

  • 비동기적으로 응답이 도착했을떄 subscribe가 응답을 콜백함수로 전달하고, 콜백 함수에서 응답을 this.heroes 와 같은 필요한 프로퍼티에 할당합니다.

    // src/app/component/heroes/heroes.component.ts
    
    import { Component, OnInit } from '@angular/core';
    import { HSModel } from 'src/app/model';
    import { HeroService } from 'src/app/service/hero.service';
    
    @Component({
      selector: 'app-heroes',
      templateUrl: './heroes.component.html',
      styleUrls: ['./heroes.component.scss'],
    })
    export class HeroesComponent implements OnInit {
      heroes: HSModel.Hero[] = [];
      selectedHero?: HSModel.Hero;
    
      constructor(private heroService: HeroService) {
        this.getHeroes();
      }
    
      ngOnInit(): void {}
    
      onSelect(hero: HSModel.Hero): void {
        this.selectedHero = hero;
      }
    
      getHeroes(): void {
        this.heroService.getHeroes().subscribe((heroes) => (this.heroes = heroes));
      }
    }
    

메시지 표시하기

  • messages 컴포넌트 생성하기

  • message 서비스 생성하기

    // src/app/service/message.service.ts
    
    import { Injectable } from '@angular/core';
    
    @Injectable({
      providedIn: 'root',
    })
    export class MessageService {
      messages: string[] = [];
    
      constructor() {}
    
      add(message: string): void {
        this.messages.push(message);
      }
    
      clear(): void {
        this.messages = [];
      }
    }

HeroService에 의존성으로 주입하기

  • A 서비스 안에 B 서비스 존재(사용)하는 경우

    // src/app/service/hero.service.ts
    
    import { Injectable } from '@angular/core';
    import { Observable, of } from 'rxjs';
    import { HEROES } from '../mock';
    import { Hero } from '../model/data';
    import { MessageService } from './message.service';
    
    @Injectable({
      providedIn: 'root',
    })
    export class HeroService {
      constructor(private messageService: MessageService) {}
    
      getHeroes(): Observable<Hero[]> {
        const heroes = of(HEROES);
        this.messageService.add('HeroService : fetched heroes(데이터를 불러옴)');
        return heroes;
      }
    }
    

MessageService 바인딩 하기

  • MessageComponet 에다가 MessageService 프로퍼티를 바인딩한다. 의존성 주입이 아니다!! 바인딩하는 것이다.!!!! public 을 사용한다.

    // src/app/component/messages/messages.component.ts
    
    import { Component, OnInit } from '@angular/core';
    import { MessageService } from 'src/app/service/message.service';
    
    @Component({
      selector: 'app-messages',
      templateUrl: './messages.component.html',
      styleUrls: ['./messages.component.scss'],
    })
    export class MessagesComponent implements OnInit {
      constructor(public messageService: MessageService) {}
    
      ngOnInit(): void {}
    }
    
  • 바인딩하였기에 MessageService의 프로퍼티 및 함수를 사용한다.

    // src/app/component/messages/messages.component.html
    
    <div *ngIf="messageService.messages.length">
      <h2>Messages</h2>
      <button class="clear" (click)="messageService.clear()">Clear messages</button>
      <div *ngFor="let message of messageService.messages">{{ message }}</div>
    </div>
    

선택한 Hero에 대해 메시지 보내기

  • 히어로를 선택했을때 이에 대한 메시지를 표현하기 위하여 선택했을떄 동작하는 함수에 MessageService 를 이용하자.

    // src/app/component/heroes/heroes.component.ts
    
    import { Component, OnInit } from '@angular/core';
    import { HSModel } from 'src/app/model';
    import { HeroService } from 'src/app/service/hero.service';
    import { MessageService } from 'src/app/service/message.service';
    
    @Component({
      selector: 'app-heroes',
      templateUrl: './heroes.component.html',
      styleUrls: ['./heroes.component.scss'],
    })
    export class HeroesComponent implements OnInit {
      heroes: HSModel.Hero[] = [];
      selectedHero?: HSModel.Hero;
    
      constructor(
        private heroService: HeroService,
        private messageService: MessageService
      ) {
        this.getHeroes();
      }
    
      ngOnInit(): void {}
    
      onSelect(hero: HSModel.Hero): void {
        this.selectedHero = hero;
        this.messageService.add(
          `HeroesComponent : Selected hero id=${hero.id}, name=${hero.name}`
        );
      }
    
      getHeroes(): void {
        this.heroService.getHeroes().subscribe((heroes) => (this.heroes = heroes));
      }
    }
    
profile
개초보

0개의 댓글