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

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

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


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

앵귤러 튜토리얼(Angular tutorial) - 22, with FireBase : 서비스 분리

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

저번시간까지 우리는 파이어베이스 파이어스토어의 데이터를 가져와 보여주는 기능에 대해서 살펴보았습니다.
이번시간에는 데이터를 등록하는 방법에 대해서 살펴보겠습니다.
해당기능을 구현하기에 앞서 우리가 여태껏 작성한 내용은 app컴포넌트에 존재합니다.
app컴포넌트에 기능이 존재하면 조회기능을 다시 만드는 경우, 같은 내용의 코드를 다른곳에서도 작성해야 되므로 불편합니다.
기존에 잘 만들어 두었던 ask서비스에 기능을 옮겨보도록 하겠습니다.

가장 먼저 해야되는 것은 ask서비스에서 생성자를 통하여 AngularFirestore객체를 공급받아야 되는 것 입니다.
그리고나서 잘 만들어둔 getItem함수를 옮겨주면 되겠습니다.
* 대상 : ask.service.ts

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

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

  private DataBase: AngularFirestore;
  private itemsCollection: AngularFirestoreCollection<any>;

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

  constructor(db: AngularFirestore) {   //모듈에서 만들어진 파이어 베이스 접속관련 객체
    this.DataBase = db;
  }

  getItem(db_name: string) {
    this.itemsCollection = 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.itemsCollection;
  }

  addItem(){  //등록을 위해 만들어둔 함수

  }

  //로그인을 시도하는 함수
  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);
    }
  }

}

* getItem 함수의 기능은 이제 저번시간의 내용을 토대로 다양하게 한번 만들어보시기를 권장 드립니다.

이렇게 하고나니 이제 각각의 컴포넌트에서는 ask서비스를 공급받아서 getItem 함수를 손쉽게 호출하여 사용 할 수 있게 되었습니다.
이처럼 자주사용되는 공통적인 기능, 데이터는 서비스로 분리하는 것이 편리합니다.

 

오늘의 주제인, 파이어스토어에서 데이터를 넣는것은 생각보다 쉽습니다.
전역변수 DataBase는 AngularFirestore의 객체이며 collection 함수를 실행하여 우리는 AngularFirestoreCollection객체를 생성 해 주었습니다.
그리고 AngularFirestoreCollection객체는 itemsCollection이라는 변수에 담아두었습니다.
해당 itemsCollection변수에서 add라는 함수를 호출하면 데이터 등록이 이루어 집니다.

* 대상 : ask.service.ts

  //생략..
  addItem(data : any){
    this.itemsCollection.add(data);
  }
  //생략..

 

아니..저게 뭡니까?? 저게 전부라구요??

네, 맞습니다. 저게 "끝"입니다.
매우 단순할 정도로 쉬우면서 직관적입니다. add함수에는 아무런 데이터를 넣어도 상관없습니다만 반드시 "자료"의 형태를 갖추어야 합니다.
그러면 이제 해당 함수를 한번 호출하여보겠습니다.
다시 우리의 app컴포넌트로 돌아가 ask서비스를 공급받은 뒤에 리스트를 가져오는 함수와, 등록하는 함수를 적용하여 보겠습니다.

* 대상 : app.component.ts

import { Component } from '@angular/core';
import { AskService } from './ask.service';

@Component({
  selector: 'app-root',
  template : '<router-outlet></router-outlet>',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'thirdStudy';

  constructor(private service : AskService) {   
    service.getItem("board").valueChanges().subscribe( arg => {
      console.log(arg);
    });
  }  

}

 

처음 수정한 모습입니다.
여기서 고려해야되는 점이 getItem함수를 실행해야지만 등록이 가능하다는 점 입니다.
이해를 위해서 먼저 등록하는 함수를 한번 호출해 보도록 하겠습니다.

* 대상 : app.component.ts

  //생략..
  constructor(private service : AskService) {   
    service.addItem({number:5,hello:'hello',today:new Date()});
    service.getItem("board").valueChanges().subscribe( arg => {
      console.log(arg);
    });
  }  
  //생략..

 

한번 실행하여 보겠습니다.  * ng serve

오류가 발생합니다?

 

오류가나는 원인은 바로 itemsCollection값이 null이기 때문 입니다. 
그러므로 데이터를 등록 해 주기위해서는 해당 객체가 생성이 되어 있어야 합니다.
ask서비스로 돌아가 addItem함수를 고쳐보도록 하겠습니다.

* 대상 : ask.service.ts

  //생략..
  addItem(db_name : string, data : any){
    if(this.itemsCollection == null){
      this.itemsCollection = this.DataBase.collection<any>(db_name);
    }
    this.itemsCollection.add(data);
  }
  //생략..

 

addItem이라는 함수를 호출 할 때 itemsCollection값이 비어있으면 해당 객체를 생성하게 하였습니다.
조건절이 없기는 하지만 등록 할 때 조건은 굳이 필요하지 않으므로 상관 없을 것 같습니다.
자 이제 그러면 app컴포넌트에서 해당 기능을 사용해 보도록 합니다.

* 대상 : app.component.ts

  //생략..
  constructor(private service : AskService) {   
    service.addItem("board",{number:5,hello:'hello',today:new Date()});
    service.getItem("board").valueChanges().subscribe( arg => {
      console.log(arg);
    });
  }  
  //생략..

데이터가 정상적으로 들어갔습니다~

 

데이터가 정상적으로 들어간 것을 볼 수 있습니다.
Observable 패턴에 의해서 데이터를 등록하자마자 역시나 getItem에서 추가되어 알아서 동작을 하게 될 것 입니다.

 

그런데, 해당 ask서비스는 다소 문제가 존재합니다.
데이터를 가져오고 등록하는 변수인 itemsCollection이 전역변수로 사용되었기 때문 입니다.
만약에 우리가 데이터를 조회하고 등록해야되는 컬렉션이 여러개면 중첩되어 원치않는 현상이 발생 할 수 있습니다.
해당 부분을 배열이나 json형식으로 바꾸어줄 필요가 있겠습니다.
여기서는 json형식으로 적용하여 보았습니다.

* 대상 : ask.service.ts

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

@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;
  }

  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);
    }
  }

}

 

이제 다양한 컬렉션에 조회와 등록이 가능한 모습의 서비스가 탄생하였습니다. ^^
여기까지가 파이어스토에서 데이터를 등록하는 기능의 모습입니다.
다음 시간에는 조금 어려운 수정방법에 대해서 살펴보도록 하겠습니다.

thirdStudy.zip
0.01MB

 

 

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

댓글