본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


앵귤러, 리엑트, 뷰/Angular Tutorial(new)

앵귤러 튜토리얼(Angular tutorial) - 23, with FireBase : alter

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2020. 8. 28.

저번시간에는 파이어 스토어에 등록하는 방법에 대해서 살펴 보았습니다.
이번시간에는 수정하는 방법을 알아보기 위한 첫번째 시간 입니다.
이를 위해서 우리는 먼저 pipe와 map, 그리고 take라는 함수를 살펴볼 것 입니다.
pipe라는 함수는 말 그대로 관, 통로의 의미입니다.
* Javascript에서 우리는 배열같은 데이터를 filter나 map등으로 가공할 수 있습니다.
* 마찬가지로 Java에서도 stream객체를 활용해서 컬렉션 데이터를 가공 할 수 있습니다.

앵귤러에서의 pipe는 데이터의 결과가 만들어지기 전 옵션같은 개녑 입니다.
결과를 만들 때 pipe를 통해서 선언된 행동을 하고난 뒤에 최종 결과를 만들어 냅니다.
역시나 말이 어렵습니다..
이해를 위해 테스트 함수 1개를 ask서비스에 만들어 보겠습니다.

* 대상 : ask.service.ts

import { Injectable } from '@angular/core';
import { Observable, BehaviorSubject } from 'rxjs';
import { AngularFirestore, CollectionReference, AngularFirestoreCollection } from '@angular/fire/firestore';

import {take, map} from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class AskService {

  private DataBase: AngularFirestore;
  private itemsCollection: AngularFirestoreCollection<any>;
  private collectionArray = {};  //json형식으로 변경하여 줍니다. 

  //저장소(나중에 데이터베이스 서버)
  private readonly storage = {
    id: 'admin',
    passwd: '1234'
  }

  constructor(db: AngularFirestore) {   //모듈에서 만들어진 파이어 베이스 접속관련 객체
    this.DataBase = db;
  }
  
  testPipeTake(){  //파이프와 테이크의 예제
    this.DataBase.collection<any>("test").stateChanges().pipe(take(1)).subscribe(
      arg=>{
        console.log(arg);
      }
    );
  }

  getItem(db_name: string) {
    if(this.collectionArray[db_name]){
      this.collectionArray[db_name] = null;
    }
    this.collectionArray[db_name] = this.DataBase.collection<any>(db_name, (ref: CollectionReference) => {
      //ref.where("hello","==",'hahaha') //일반 질의문
      //ref.where("world","array-contains", "aaa") // 배열인 경우
      //ref.orderBy('number', 'asc').startAt(0).limit(2);  //시작, 한계점 추가
      return ref;
    });  //리턴
    return this.collectionArray[db_name];
  }

  addItem(db_name : string, data : any){
    if(this.collectionArray[db_name] == null){
      this.collectionArray[db_name] = this.DataBase.collection<any>(db_name);
    }
    this.collectionArray[db_name].add(data);
  }

  //로그인을 시도하는 함수
  tryToLogin(param: any) {
    return new Observable(arg => {
      if (param.id == this.storage.id && param.passwd == this.storage.passwd) {
        arg.next({ status: true });
        localStorage.setItem('status', "true");
      } else {
        arg.next({ status: false, reason: 'wrong information' });
      }
      arg.complete();
    });
  }

  //가드가 구독하는 대상
  readonly isLogged: BehaviorSubject<boolean> = new BehaviorSubject(false);

  //로그인이 되었는지 확인하는 함수
  isLogIn(): void {
    if (localStorage.getItem('status') == 'true') {
      this.isLogged.next(true);
    } else {
      this.isLogged.next(false);
    }
  }

}

 

testPipeTake라는 함수를 만들어 주었습니다.
여태껏 우리는 valueChanges라는 함수를 호출한 뒤에 subscribe를 해 주었는데, testPipeTake 함수에서는 stateChanges라는 함수가 사용 되었습니다.
백문이 불여일견!
test라는 컬렉션이 비어있으므로 데이터를 몇개 넣어주고 나서 해당 함수를 app컴포넌트에서 호출하여 봅니다.

* 대상 : app.component.ts

  //생략..
  constructor(private service : AskService) {   
    //service.addItem("board",{number:6,hello:'hello',today:new Date()});
    service.getItem("board").valueChanges().subscribe( arg => {
      console.log(arg);
      //{idField: 'idx'} <---- 이거 설명해야 된다
    });

    service.testPipeTake();  //추가!
    
  }  
  //생략..

데이터는 단순하게 3개를 넣었습니다.

 

단순한 데이터 3개를 넣었는데...알 수 없는 형식의 데이터가 나오고 있습니다.
valueChanges 함수는 값에대한 변화를 감지하며, stateChanges는 상태변화에 대한 감지를 실시 합니다.
사용하는 기능은 거의 동일하나 stateChanges가 데이터+상태 정보를 가져오는 기능 입니다.
그러면 평소에 하던데로 test컬렉션에 데이터를 1개 더 추가하여 봅니다.

데이터를 넣었는데 콘솔에 내용이 추가되지 않습니다.

 

subscribe함수를 통해서 구독행위를 했는데..데이터가 나오지 않습니다??
그 이유는 바로 pipe를 통해서 take함수가 호출되었기 때문 입니다.
take함수는 위 모습처럼 구독횟수를 지정할 수 있습니다.
pipe를 통해서 1번만 구독한다고 하였기 때문에 1번 구독(subscribe)하고 더 이상 구독을 하지 않는 것 입니다.

구독 행위의 제한을 우리는 pipe와 take함수를 통해서 이처럼 편리하게 줄 수가 있습니다.

 

예전에 우리는 subscribe를 통해서 나온 Subscription에 대해서 살펴본 적이 있습니다.

lts0606.tistory.com/373

 

구독하는 대상의 행위를 종료하려면 unsubsribe함수를 호출 해야 하였습니다.

그러나 take를 활용하면 이처럼 손쉽게 종료를 할 수 있습니다.


그러면 이어서 map이라는 함수에 대해서도 한번 살펴보겠습니다.
기존 서비스에서 내용을 수정하여봅니다.

* 대상 : ask.service.ts

  //생략..
  testPipeTake(){  //파이프와 테이크의 예제
    this.DataBase.collection<any>("test").stateChanges().pipe(
      take(1), 
      map(actions => {
        return actions.map(a => a.payload.doc.data());
      })
    ).subscribe(
      arg=>{
        console.log(arg);
      }
    );
  }
  //생략..


take함수 뒤에 map이라는 함수를 넣어주었습니다.
map은 가공의 의미 입니다. 데이터를 주어진 내용에 따라 가공하라는 의미 입니다. 

입력한 데이터의 형태로 출력이 되고 있습니다.

 

이전에 알 수 없는 형식의 데이터들이 이제 사용자가 넣은 데이터의 모양으로 탄생 하였습니다.
map 함수의 의미를 조금 더 쉽게 살펴보기위해 아래 사진을 한번 보도록 합니다.

1234를 리턴하게 하였습니다.

 

map을 통해서 단순하게 숫자를 반환하도록 하였더니 숫자값만 나오는 것을 볼 수 있습니다.

마찬가지로 문자, 배열등을 입력하여도 해당 입력된 데이터로 출력이 됩니다.

action은 DocumentChangeAction라는 인터페이스로 되어 있습니다.

 

맨 처음 testPipeTake함수에서 map을 통해 만난 action이라는 객체는 DocumentChangeAction의 형태로 되어 있습니다.

DocumentChangeAction은 type, payload라는 키 값을 통해서 다양한 정보를 제공 합니다.

그러한 다양한 정보가 출력된 것이 map을 적용하지 않았을때의 모습입니다.


그리고 action 객체에서 map이라는 함수를 한번 더 호출하여서 데이터를 가공하였습니다.
다시 말해, map을 2번 실행해서 데이터를 가공 한 모습입니다.

그렇게 2번 가공하고 나니 입력한 데이터가 나온 모습이  map이 적용된 최종모습 입니다.

 

"map이라는 함수를 호출하여 데이터를 가공한다" 라는 내용이 이번장의 핵심 입니다.

이번시간에는 pipe라는 기능을 통해서 주어진 데이터를 가공하는 방법에 대해서 살펴 보았습니다.
해당내용을 이해 하여야만 데이터를 수정, 삭제 할 수 있습니다..^^;
다음시간에도 이어서 데이터를 수정하는 방법에 대해서 살펴 보겠습니다.

thirdStudy.zip
0.01MB

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글