이전편에서 일단 app.component.ts에서 모든 작업을 했었는데, 이러한 모든 기능들이 다 app.component에 몰려있으면 안되겟지 당연히. 모든 기능적인 함수가 main() 문에 다 때려박혀있는 지저분한 코드나 마찬가지이므로 일단은 분리를 해보자.
나는 기능별로 component로 나눠서 관리를 할 거야.
솔직한 마음으로는 이 1,2 편 작성하면서 이거 찾으려고 여기저기 다들 돌아다녔을게 뻔함...(경험)
이후 진행하다가 손쓸 수 없게 터지면 여기로 돌아오자. 초기 세팅한 코드들이라고 생각하면 됨
그럼 일단 component를 생성해야지. 이제 약자에 많이 익숙해짐ㅇㅇ
cd src -> cd app
그냥 app폴더 밑에 만들으라는거고 비주얼스튜디오 내에서 내장 터미널 여는거 했었지 ⌃ + ⇧ + ~ 이거 누르면 됨
terminal에서 ng g c user 해서 user을 위한 컴포넌트를 생성하자.
컴포넌트 (ng g c 컴포넌트이름)
: 화면구성.
: 화면에 대한 모든 기능을 담당.
: 컴포넌트간의 데이터 - 컴포넌트에서 속성이나 Input 또는 Output같은 데코레이터 사용.
: 컴포넌트간의 데이터 공유는 서비스를 통해 구독(subscribe)하는 형태로도 공유.
user.component.ts에 아까 app.component.ts에 있던 내용들을 옮긴다.
user.component.ts
import { Component, OnInit } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection, CollectionReference } from '@angular/fire/firestore';
import { AngularFireStorage } from '@angular/fire/storage';
@Component({
selector: 'app-user',
templateUrl: './user.component.html',
styleUrls: ['./user.component.css']
})
export class UserComponent implements OnInit {
ngOnInit(): void { }
private database : AngularFirestore; // 파이어스토어를 쓸건데 그건 private해야겠지 당연히. database는 내가 지은 이름이고.
private itemCollection: AngularFirestoreCollection<any>; //collection을 가져올건데 일단 다 가져와
collections = new Array();
private storage : AngularFireStorage; // 나중에 쓸 저장소인데 이거 써볼라다가 일단 지웟음 일단 안 쓰고 있는 다
tang: object; // 지금 user에 객체의 상태로 2개가 만들어져있으니까 객체 타입으로 받는다 하고
constructor(db : AngularFirestore) { // AngularFirestore을 db라는 이름으로 가져올거고
this.database = db; // this.database 가 AngularFirestore 이라는 걸 알려주고
this.getItem('user').subscribe((res)=> { // 아까 firestore페이지에서 user 라는 collection 만들었었잖아. 그거 구독하자.
console.log(res); // F12 눌러서 나오는 콘솔에 내용을 찍어보자
this.tang = this.database;
this.collections = res;
});
}
getItem(db_name : string){ // getItem() 의 인자로 들어가는 이름의 collection에 접근을 할 거라고 설정
this.itemCollection = this.database.collection<any>(db_name, (ref : CollectionReference) => {
return ref.orderBy('phone_number','asc'); //시작, 한계점 추가
});
return this.itemCollection.valueChanges(); //리턴
}
}
로그인하는 컴포넌트도 만들어줄거다
ng g c login
이놈이 로그인을 제대로 한 놈인지 확인하는 ask 라는 서비스를 만들거다
ng g s ask
ask에서 만든 로그인 했냐? 확인하는 함수를 가드가 쓰게 할거야. 그런 auth 라는 가드를 만들거다
ng g g auth
→ CanActivate
기능 넣을거니까 쫄지마 쫄지마. 내가 이때까지 삽질하고 프로젝트 여러번 밀고 그러면서 짜놓은 안전한 코드니까 이거 그냥 복붙해도 됨 이건 전체 선택 해서 전체 붙여넣기 하면 됨
login.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { AskService } from '../ask.service';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit, OnDestroy {
id : string; // 화면 상에서 입력할 id 에 해당할 부분
passwd : string; // 화면 상에서 입력할비밀번호에 해당될 부분
constructor(private service : AskService, private rout: Router) {
// constructor. 그러니까 얘가 시작이 될 때에 바로 consttructor가 실행됨. 실행되는 서비스로 Ask 서비스를 돌리고, rout는 라우터라고 만들어놓았던 라우팅이 시작
}
ngOnInit(): void { }
private script : Subscription; // 여기에 로그인 했을때의 결과를 담을 거야
login() { // 화면상에서 누르면 이 기능이 실행되게끔 하는 함수야
if(this.script){
console.log(this.script);
this.script.unsubscribe(); //구독 종료
}
this.script = this.service.tryToLogin({id : this.id, passwd : this.passwd}).subscribe( (arg:any)=>{
if(arg.status == true){ // 둘 다 맞아서 true 되눈 경우에만 이렇게 하라
alert('로그인 성공!') // 이러면 화면 상에 팝업 뜨면서 로그인 성공 뜸
this.rout.navigate(['/user']); // 로그인 성공 하면 user이라고 라우팅 해놓은 곳으로 가라는 소리임
}
});
}
ngOnDestroy(): void { // 파괴될 때에는 구독 종료
console.log(this.script);
if(this.script){
this.script.unsubscribe(); //구독 종료
}
}
}
로그인하는 component를 만들었으면 로그인 화면, 그러니까 login.component.html을 꾸미자
login.component.html
<input type="text" placeholder="아이디" [(ngModel)]='id' />
<input type="text" placeholder="비밀번호" [(ngModel)]='passwd'/>
<input type="button" value="로그인" (click)='login()'/>
아이디, 비밀번호 넣는 input 필드 만들었고, 로그인이라는 버튼을 누르는 순간 내가 위에 login() 함수만들었던것이 실행되도록 함. onclick 을 이렇게 표현되는거임. 쫄지마 모르는거 나와도
로그인 기능을 담당할 컴포넌트를 만들었고, 이런 컴포넌트들을 실행시키려고 ask라는 서비스를 만들었었지. 이번엔 서비스를 구현해보자.
ask.service.ts
import { Injectable } from '@angular/core';
import { AngularFirestore, AngularFirestoreCollection, CollectionReference } from '@angular/fire/firestore';
import { BehaviorSubject, Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AskService {
private database: AngularFirestore;
private itemCollection: AngularFirestoreCollection<any>;
//저장소(나중에 데이터베이스 서버)
private readonly storage = {
id: 'bearbook',
passwd: 'club'
} // 지금 당장에는 이 bearbook, club 이 입력되지 않으면 login 화면에서 user 화면으로 넘기지 않을거야
constructor(db: AngularFirestore) { // Firestore을 db라고 부를거야.
this.database = db; // database = 이 Forestore 넣어주고
}
getItem(db_name: string) {
this.itemCollection = this.database.collection<any>(db_name, (ref: CollectionReference) => {
return ref;
}); //리턴
return this.itemCollection; // itemCollection이라 한거를 퉤 뱉어라
}
addItem(){
// 나중에 firestore에 데이터 집어넣는 코드 개발할거고
}
//로그인을 시도하는 함수
tryToLogin(your_input: any) {
return new Observable(arg => {
if (your_input.id == this.storage.id && your_input.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); // auth 에서는 이걸 볼 거야
//로그인이 되었는지 확인하는 함수
isLogIn(): void {
if (localStorage.getItem('status') == 'true') { // getItem 해봐서 true 그러니까 로그인이 되어있으면 next로 넘어가라
this.isLogged.next(true);
} else {
this.isLogged.next(false); // 로그인이 되어있지 않다면 갖다 버려라
}
}
}
서비스 (ng g s 서비스 이름)
: 비지니스 로직과 같은 형태의 기능.
: 자주 사용되는 함수나 데이터등을 서비스로 만든 뒤 모듈에서 의존성 주입(Inject)을 통해서 컴포넌트에게 제공.
: 컴포넌트는 생성자를 통해서 이러한 서비스를 받아서 사용.
우리는 이런 서비스를 만들었고, 서비스를 실행시킴에 있어서 사용자의 요청이 컴포넌트로 전달되기 전에 클럽 가드처럼 슥 보면서 확인을 하는거지 이놈을 보내도 되나~? 하면서.
ex) 클럽가드, 방화벽 .... 뭐 이런 식의 설명이려나 하여튼 고쳐보자
auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { AskService } from './ask.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
private status : boolean = false;
constructor(private serv : AskService){
serv.isLogged.subscribe( result=>{
console.log('서버에 물어보고온 결과', result);
this.status = result;
});
}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
this.serv.isLogIn();
return this.status;
}
}
가드 (ng g g 가드 이름)
: 일종의 서비스의 형태이며, 모듈에서 라우터 정보에서 canActivate 에 추가하여 사용 가능.
: 사용자의 요청이 컴포넌트에게 전달되기 전(pre) 동작을 하며 조건을 통해 해당 컴포넌트로 이동할지 말지를 결정.
마지막으로 바로 보일 화면을 조정해봅시다
난잡한거 딱 싫다했음. 일단 다 지우고 심플하게 가자고
app.component.html
<h2> Login 하면 User들이 보일 것입니다</h2>
<app-login></app-login>
실행 화면
'Back-End > Firebase firestore' 카테고리의 다른 글
firestore 데이터 내보내기, 엑셀로 내보내기 (0) | 2022.12.31 |
---|---|
Angular 11 + firebase(firestore) 프로젝트 #04 - 데이터 CRUD - C addItem 구현해보기 (0) | 2020.12.14 |
Angular 11 + firebase(firestore) 프로젝트 #02 - 데이터 CRUD(Read) -1 (0) | 2020.12.11 |
Angular 11 + firebase(firestore) 프로젝트 #01 - firestore 연결 (0) | 2020.12.10 |