문제상황


앵귤러2 에서 일반적으로 자식 컴포넌트가 부모 컴포넌트에게 데이터를 전달하는 방법은 Output 과 EventEmitter 를 이용한 방법을, 부모 컴포넌트가 자식 컴포넌트에게 데이터를 전달하는 방법은 자식컴포넌트 선택자에 단지 속성으로 변수를 넘긴 후 Input 을 사용하여 받는다. 즉 뷰템플릿이 데이터 전송의 매체가 되는 셈.


하지만 문제가 복잡해져 서로 거리가 먼 컴포넌트 간의 통신을 해야하는 경우가 생김.

마치 나와 큰아빠와 큰아버지와 사촌동생 간에 동시에 데이터를 공유해야 하는 상황이라면?





1. 매개자 역할의 서비스 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';
 
@Injectable()
export class DataService {
  private subject = new Subject<any>();
 
  constructor() { }
 
  sendData(data){
    this.subject.next(data);
    console.log("sendData() data : " , data);
  }
 
  getData(){
    return this.subject.asObservable();
  }
}
 
cs


rxjs 의 Subject 객체는 Observable 인 동시에 Observer. 한 컴포넌트에서 서비스의 sendData() 를 호출하여 데이터를 Subject 의 next 메서드를 통해서 데이터 스트림에 밀어넣는다.


다른 getData() 메서드는 데이터를 받을 컴포넌트에서 호출하여 데이터스트림에서 Observable 객체를 받은 후, 데이터 전송이 완료되었을 때 구독(subscribe) 할 것이다.




2. 데이터를 보낼 컴포넌트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import { Component, OnInit, OnDestroy } from '@angular/core';
import { PostService } from '../../services/post/post.service';
import { DataService } from '../../services/data.service';
 
import { Post } from '../../models/post';
import { ActivatedRoute, Params } from '@angular/router';
import { Subscription } from 'rxjs/Subscription';
 
@Component({
  selector: 'app-post',
  templateUrl: './post.component.html',
  styleUrls: ['./post.component.css']
})
export class PostComponent implements OnInit, OnDestroy {
  private subscription: Subscription;
  post: Post;
  postNo: number;
 
  constructor(private activatedRouter: ActivatedRoute, private postService: PostService, private dataService: DataService) {
    this.subscription = activatedRouter.params.subscribe((params: Params) => {
      this.postNo = params['postNo'];
      this.postService.getPost(this.postNo)
      .subscribe(
        (post) => {
          this.post = post;
          dataService.sendData(this.post);
        },
        (error) => {
          console.log(error);
        }
      );
    });
  }
 
  ngOnInit() {
    
  }
 
  ngOnDestroy() {
    this.subscription.unsubscribe();
  }
}
 
cs


좀 복잡해 보이지만 핵심은 단지 위에서 생성한 service 의 sendData() 를 호출하는 것. 참고로 subscription 객체는 구독했던 객체를 파괴하기 위해 사용. ngOnDestroy() 라이프사이클에서 저장했던 subscription 을 unsubscribe 해주면 된다.


DataService 를 주입받고, 보내고자 하는 데이터를 dataService.sendData() 로 호출하여 넘겨준다.




3. 데이터를 받을 컴포넌트

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import { Component, OnInit, OnDestroy } from '@angular/core';
import { DataService } from '../../services/data.service';
 
import { Subscription } from 'rxjs/Subscription';
 
@Component({
  selector: 'app-banner',
  templateUrl: './banner.component.html',
  styleUrls: ['./banner.component.css']
})
export class BannerComponent implements OnInit, OnDestroy {
  title = 'Blog';
  regDate = '';
  categoryName = '';
 
  subscription: Subscription;
 
  constructor(private dataService: DataService) {
    console.log("banner 컴포넌트 생성!");
    
    this.subscription = dataService.getData().subscribe(data => {
      console.log("banner subscription : " , data);
      this.title = data.title;
      this.regDate = data.regTime;
      this.categoryName = data.categoryId;
    })
 
  }
 
  ngOnInit() {
  }
 
  ngOnDestroy(){
    this.subscription.unsubscribe();
  }
 
}
 
cs


데이터를 수신할 컴포넌트에서도 마찬가지로 Subscription 객체를 이용해 구독한 객체를 파괴시켜주어야 하며, DataService 를 주입받고, 이 DataService 의 getData() 메서드를 호출하여 Observable 객체를 받는다. 이를 subscribe 메서드를 사용하여 데이터가 전달되면 수행할 작업을 진행하면 된다.




블로그 이미지

망원동똑똑이

프로그래밍 지식을 자유롭게 모아두는 곳입니다.

,