개요
앞서 진행하였던 Firebase 의 이메일과 소셜네트워크 계정을 이용한 사용자 인증을 통해 획득되는 기본적인 정보는 사용자의 식별자와 uid
정보입니다. 하지만 이외에도 로그인 과정을 통해 획득할 수 있는 사용자의 정보는 다양합니다. 필요에 따라 이러한 사용자의 추가 정보를 수집하여 데이터베이스에 저장하면 어플에 등록된 사용자에 대한 반복작업을 수행하는데 도움이 될 것입니다.
이번 포스트에서는 인증(로그인) 과정을 통해 획득한 사용자의 상세한 정보를 Firebase
파이어 베이스의 데이터베이스 중 하나인 Cloud Firestore
에 저장해 보도록 하겠습니다.
기존에 구현하였던 로그인 기능을 바탕으로 수정합니다.
사용자의 정보를 데이터베이스에 저장하기
사용자의 정보를 데이터베이스에 저장하기 위해, AngularFirestoreDocument
를 사용하도록 하겠습니다. AngularFirestoreDocument service 는 Firestore SDK 의 DocumentReference
형의 데이터를 Angular의 service 에서 함께 사용하기 좋게 설계가 되어 있습니다. 이를 사용하기 위해서 기존의 코드에 관련 모듈을 추가하도록 합니다.
▼ /src/app.module.ts
... 생략 ...
import { AngularFirestoreModule } from '@angular/fire/firestore'; // ← 추가
... 생략 ...
@NgModule({
imports: [ ... 생략 ...
AngularFirestoreModule, // ← 추가
... 생략 ...
],
... 생략 ...
})
▼ /src/auth.service.ts
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';
... 생략 ...
다음으로 Cloud Firestore
에 저장할 사용자의 정보를 담은 Interface
를 선언합니다. 여기에 필요로 하는 임의의 데이터를 선택하여 추가 할 수 있습니다. 저는 사용자식별자(uid
), 이메일주소(email
), 계정과 연결된 사진(photoURL
), 표시할 이름(displayName
) 항목을 Cloud Firestore
데이터베이스에 저장해 보도록 하겠습니다. 재사용을 위해서는 별도의 파일에 작성할 수도 있으나, 여기서는 auth.service.ts
파일에 추가하도록 하겠습니다.
▼ /src/auth.service.ts
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import firebase from 'firebase/app';
// ▼ 추가
interface User {
uid: string;
email: string;
photoURL?: string;
displayName?: string;
}
... 생략 ...
본격적으로 Cloud Firestore
데이터베이스에 사용자 정보를 저장하도록 기능을 작성해보도록 합니다.
우선 Cloud Firestore
데이터베이스에서 현재 로그인 되어 있는 사용자의 정보를 읽어오도록 합니다. 그리고 이를 auth service
를 사용하는 다른 component
에서 사용할 수 있도록 변수(UserInfo: Observable<User>
)에 저장하도록 하겠습니다. 이 변수는 데이터베이스의 값이 변경될 때마다 이를 인지하여 값이 갱신됩니다.
▼ /src/auth.service.ts
... 생략 ...
// ▼ 추가
UserInfo: Observable<User>;
constructor(private afAuth: AngularFireAuth,
private afs: AngularFirestore /*← 추가*/) {
this.user = this.afAuth.authState;
// ▼ 추가
this.afAuth.authState.subscribe((User:firebase.User) => {
if (User) {
this.UserInfo = this.afs.doc<User>(`users/${User.uid}`).valueChanges();
} else {
this.UserInfo = null;
}
})
}
... 생략 ...
다음은 인증(로그인)을 통해 획득한 사용자의 정보를 Cloud Firestore
데이터베이스에 저장하도록 합니다. fnUpdateUserData()
매서드로 작성하였습니다.
① 사용자의 정보를 저장할 Cloud Firestore
데이터베이스의 문서를 참고하는 변수를 선언합니다. ② 사용자 인증으로 획득한 사용자의 정보를 해당 문서에 병합합니다.
▼ /src/auth.service.ts
... 생략 ...
private fnUpdateUserData(UserInfo) {
// ①
const userRef: firestoreDocument<any> = this.afs.doc(`users/${UserInfo.uid}`);
// ②
const data: User = {
uid: UserInfo.uid,
email: UserInfo.email,
displayName: UserInfo.displayName,
photoURL: UserInfo.photoURL
}
// ②
return userRef.set(data, { merge: true })
}
마지막으로 사용자의 정보를 Cloud Firestore
데이터베이스에 갱신(덮어쓰기) 하는 함수를 로그인 함수에 연결하도록 합니다.
▼ /src/auth.service.ts
fnGoogleLogin() {
// this.afAuth.auth.currentUser.linkWithRedirect(new firebase.auth.GoogleAuthProvider());
this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider())
// ▼ 추가
.then((credential) => {
this.fnUpdateUserData(credential.user)
})
}
구글 로그인 외에도 다른 로그인 매서드에도 해당 절차를 수행하도록 연결합니다.
동작확인
이제 어플을 실행하여 로그인을 다시 진행하도록 합니다. 다음과 같이 파이어베이스의 Console 에 접속하여 Project 를 선택합니다. 좌측의 메뉴(Database) 를 통해 Cloud Firestore
를 접속합니다. 방금 로그인 한 사용자의 정보가 users
컬렉션아래 uid
문서로 생성되었으며, 해당문서에는 앞서 interface
로 정의한 displayName
, email
, photoURL
, uid
필드가 각각 생성되는 것을 확인할 수 있습니다.
▲ Firebase Cloud Store UsreInfo 생성결과
결론
이번 포스트에서는 인증(로그인) 을 통해 획득되는 사용자의 정보를 Cloud Firestore
데이터베이스에 저장하여 보았습니다. 수정한 전체 코드는 다음과 같습니다.
▼ /src/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatButtonModule, MatCheckboxModule } from '@angular/material';
import { MatInputModule } from '@angular/material/input';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatIconModule } from '@angular/material/icon';
import { MatDividerModule } from '@angular/material/divider';
import { MatCardModule } from '@angular/material/card';
import { MatTabsModule } from '@angular/material/tabs';
// FlexLayout
import { FlexLayoutModule } from '@angular/flex-layout';
// FontAwesome
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { library } from '@fortawesome/fontawesome-svg-core';
import { faFacebookF, faGooglePlusG, faTwitter } from '@fortawesome/free-brands-svg-icons';
import { faComment } from '@fortawesome/free-solid-svg-icons';
library.add([faFacebookF, faGooglePlusG, faComment]);
import { AppComponent } from './app.component';
import { AngularFireModule } from '@angular/fire';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { AngularFirestoreModule } from '@angular/fire/firestore'; // ← 추가
import { environment } from '../environments/environment';
import { AuthService } from './auth.service';
@NgModule({
imports: [ BrowserModule, FormsModule, BrowserAnimationsModule,
MatButtonModule, MatCheckboxModule, MatToolbarModule, MatIconModule, MatInputModule,
MatDividerModule, MatCardModule,
MatTabsModule,
FontAwesomeModule,
FlexLayoutModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,
AngularFirestoreModule, // ← 추가
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ],
providers: [AuthService]
})
export class AppModule { }
▼ /src/auth.service.ts
...
import { AngularFirestore, AngularFirestoreDocument } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import firebase from 'firebase/app';
// ▼ 추가
interface User {
uid: string;
email: string;
photoURL?: string;
displayName?: string;
}
@InjeAuthService {
user: Observable<firebase.User>;
UserInfo: Observable<User>;
constructor(private afAuth: AngularFireAuth,
private afs: AngularFirestore /*← 추가*/) {
this.user = this.afAuth.authState;
this.afAuth.authState.subscribe((User:firebase.User) => {
if (User) {
this.UserInfo = this.afs.doc<User>(`users/${User.uid}`).valueChanges();
} else {
this.UserInfo = null;
}
})
}
private fnUpdateUserData(UserInfo) {
const userRef: AngularFirestoreDocument<any> = this.afs.doc(`users/${UserInfo.uid}`);
const data: User = {
uid: UserInfo.uid,
email: UserInfo.email,
displayName: UserInfo.displayName,
photoURL: UserInfo.photoURL
}
return userRef.set(data, { merge: true })
}
// ▼ 수정
fnGoogleLogin() {
// this.afAuth.auth.currentUser.linkWithRedirect(new firebase.auth.GoogleAuthProvider());
this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider())
.then((credential) => {
this.fnUpdateUserData(credential.user)
})
}
// ▼ 수정
fnFacebookLogin() {
this.afAuth.auth.signInWithPopup(new firebase.auth.FacebookAuthProvider())
.then((credential) => {
this.fnUpdateUserData(credential.user)
});
}
// ▼ 수정
fnTwitterLogin() {
this.afAuth.auth.signInWithPopup(new firebase.auth.TwitterAuthProvider())
.then((c AngularFirestoreDocument<User>
this.user = this.afAuth.authState;efreelseri rieireseutCredential) => {
this.fnUpdateUserData(credential.user)
});
}
// ▼ 수정
fnCreateEmailUser(email, password) {
tisAuareteetmanasoremal oren((credential) => {
this.fnUpdateUserData(credential.user)
})
}
// ▼ 수정
fnEmailLogin(email, password) {
this.afAuth.auth.signInWithEmailAndPassword(email, password).then((credential) => {
this.fnUpdateUserData(credential.user)
})
.catch((error) => {
// Handle Errors here.
let errorCode = error.code;
let errorMessage = error.message;
if (errorCode === "auth/user-not-found") {
this.fnCreateEmailUser(email, password);
} else {
console.log(errorCode);
console.log(errorMessage);
}
})
}
fnlogout() {
this.afAuth.auth.signOut();
} return this.afAuth.auth.createUserWithEmailAndPassword(email, password);
}
}
완성된 최종 소스코드 및 동작은 다음을 통해 확인할 수 있습니다.
'모듈, 프레임웍 > Firebase' 카테고리의 다른 글
파이어베이스(Firebase) 앱 등록 (=키 발급) (0) | 2020.07.02 |
---|---|
Firebase 호스팅 사용하기 (0) | 2020.07.02 |
Angular Firebase - 사용자 인증 (이메일) (0) | 2018.11.09 |
Angular Firebase - 사용자 인증 (2/2) (0) | 2018.10.19 |
Angular Firebase - 사용자 인증 (1/2) (0) | 2018.09.27 |