9.x 버전의 파이어베이스에서는 모듈 사용이 필수다.
8.x 버전의 경우, 콜벡을 체이닝하는 방식으로 .get( ), then( )을 필요 이상으로 사용하는 경우가 잦았다.
9.x 버전으로 업데이트 되면서, 더이상 get( ), then( )을 여러번 혼용할 필요가 없어졌다. 대신 아래와 같이 모듈을 import하는 방식으로 간단하게 코드를 구현할 수 있다.
이번 포스팅에서는 변경된 모듈 방식(firebase v9.x)을 사용해서 인증을 제작해보자.
1 파이어베이스 회원가입
AWS, Azure, GCP를 사용하기에는 부담이 된다면, 파이어베이스가 제격이다. 파이어베이스는 테스트용으로 사용하기에 좋다. 모바일, 웹은 물론 유니티와 같은 게임서버까지 다양한 플랫폼을 api방식으로 사용할 수 있고, Storage, Auth같은 기능을 통해 회원관리도 가능하기 때문이다. 파이어베이스 CLI를 사용한다면, node.js를 설치한 뒤에 벡앤드에서 미들웨어까지 제작할 수 있다. 단, 9.x 버전부터 Firebase Function은 유료이다.
1-1 파이어베이스 회원가입
파이어베이스 회원가입은 구글 아이디와 연동된다. 구글에서 회원가입을 완료하고, 파이어베이스에 가입만 클릭하면 된다. (해당과정은 생략)
1-2 앱 추가
파이어베이스의 메인 페이지에 접속하면 아래와 같은 화면을 볼 수 있다.
앱 추가 버튼을 클릭한 뒤, 웹 프로젝트를 생성한다.
블로그에서 회원가입 인증을 진행할 예정이므로 '<script>태그 사용'을 선택하고, 모듈형 SDK 스크립트 코드를 받는다.
firebaseConfig 키는 메인화면의 설정탭에서 다시 볼 수 있다. 일단, 콘솔로 이동을 클릭하며 마무리한다.
2 파이어베이스 Auth 설정
파이어베이스 Auth를 사용하기 위해서는 인증방법을 선택해야 한다. 테스트용으로 인증하기 위해서 이메일 인증을 선택한다.
기존의 v8에서는 CDN방식으로 웹에서 파이어베이스 기능을 사용할 수 있었다. 'https://www.gstatic.com/firebasejs/[파이어베이스 버전]/파이어베이스-기능' 형식이며, 현재도 가능하다. CDN방식으로 사용한다면, 아래의 형식에서 버전 부분만 변경하면 된다.
파이어베이스 v9에서는 모듈 방식을 사용한다.
<script type="module"> import { getAuth, createUserWithEmailAndPassword, updateProfile, sendPasswordResetEmail } from "https://www.gstatic.com/firebasejs/9.6.1/firebase-auth.js";
import { onAuthStateChk } from './AuthUI_utils.js';
import ResetPWScreen from './front/src/screens/ResetPWScreen.js';
import SeekIDScreen from './front/src/screens/SeekIDScreen.js';
// 중략...
<script>
|
[ v9 파이어베이스 모듈]
v8과 바뀐 점은 파이어베이스 DOC에서 볼 수 있다. Restful API와 관련된 모듈 사용법은 DOC 웹페이지에서 모두 찾을 수 있다. 파이어베이스로 프로젝트를 진행한다면, 아래 url 즐겨찾기는 필수다.
https://firebase.google.com/docs/firestore/manage-data/add-data#web-version-9_3
3 로그인 회원폼 제작
티스토리에서는 블로그만의 자체 로그인 기능을 제공하지 않는다. 파이어베이스 Auth인증을 위해서는 자체적으로 로그인 폼을 제작해야 한다.
3-1 설계
티스토리 블로그에서 자체적으로 회원가입 기능을 제작하기 위해서는 대략적으로 아래와 같은 구조를 생각해 볼 수 있다.
사용자의 요청에 따라 블로그 메인 페이지는 인터페이스 역할을 해야 한다. 단, 블로그 index페이지와 연결되는 인터페이스를 넣어서(인터페이스 역전) 외부 모듈에 블로그가 의존되지 않도록 해준다. 파이어베이스는 단지 여러 개의 외부모듈 중의 하나일 뿐이며, AWS, GCP, AZURE로 변경되더라도 회원가입, 로그인과 관련된 직접적인 변경이 발생하지 않도록 설계하는 것이 중요하다.
3-2 로그인 폼
위의 설계에서 '유저 인터페이스' 역할은 로그인 폼이 담당한다. 로그인 폼은 내부의 모듈이 변경되더라도 변하지 않는다. '스킨편집'에서 'id = aside' 아래에 로그인 div태그를 추가해준다.
3-3 wd-loginChk_.js
블로그에 접속했을 때, 사용자 세션을 체크하고 각종 모듈을 import하는 인터페이스가 필요하다. wd-loginChk_.js파일은 라우터 기능을 담당한다. 즉, 로그인 폼을 랜더링하고, 사용자 유무를 체크하는 역할을 한다.
import loginGuestScreen from 'https://tistory3.daumcdn.net/tistory/2784544/skin/images/wd-loginGuestScreen.js';
import loginUserScreen from 'https://tistory4.daumcdn.net/tistory/2784544/skin/images/wd-loginUserScreen.js';
const firebaseConfig = {
//config파일 입력
};
const chkRoutes = {
'guest': loginGuestScreen,
'user': loginUserScreen,
}
const firebaseApp = initializeApp(firebaseConfig);
const auth = getAuth();
const router = async() => {
const loginContainer = document.getElementById('sidebar-login');
let screen = chkRoutes['guest'];
auth.onAuthStateChanged(async(user) => {
if(user){
screen = chkRoutes['user'];
loginContainer.innerHTML = await screen.render(user);
if(screen.after_render) await screen.after_render(auth);
}else{
loginContainer.innerHTML = await screen.render();
if(screen.after_render) await screen.after_render(auth);
}
})
}
window.addEventListener('load', router);
window.addEventListener('hashchange', router);
|
[ wd-loginChk_.js ]
사용자가 블로그 메인페이지에 접속할 때마다 router( )함수가 실행된다. screen변수는 사용자 상태('guest', 'user')에 따라 loginGuestScreen, loginUserScreen모듈을 선택한다. 이때 auth.onAuthStateChange( )메서드는 유저의 세션을 검사해준다. 현재 기본설정은 'guest'이므로 loginGuestScreen.js 모듈이 실행된다.
3-4 loginGuestScreen.js
loginGuestScreen.js는 사용자 세션이 없는 상태에서 실행된다. 따라서 render( )메서드를 통해 로그인 폼을 생성해야 하고, 해당 폼의 이벤트를 after_render( )에 구현한다.
import { signInWithEmailAndPassword } from "https://www.gstatic.com/firebasejs/9.6.1/firebase-auth.js"; const loginGuestScreen = {
after_render: (auth) =>{
let signInForm = document.getElementById('sidebar-login-form');
let authset = document.querySelectorAll('.signset');
authset.forEach(ele => {
ele.addEventListener('click', e =>{
let usrSelection = e.target.getAttribute('setauth');
console.log('유저선택: '+ usrSelection);
if(usrSelection == 'reset-id'){
console.log('아이디 재설정 링크');
}else if(usrSelection == 'reset-pw'){
console.log('비밀번호 재설정 링크');
}else if(usrSelection == 'register-user'){
console.log('회원가입 실행 링크');
}
})
})
signInForm.addEventListener('submit', e => {
e.preventDefault();
const email = document.getElementById('sidebar-id').value;
const password = document.getElementById('sidebar-password').value;
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
console.log('로컬스토러지 저장 및 기타 구현');
})
.catch(err => {
console.log('Error: '+err.message);
})
})
},
render: async() => {
return `
<div class="sidebar-form-container" style="display:flex;margin-bottom:5px;">
<form id="sidebar-login-form" style="display:flex;">
<div class="sidebar-login-input" style="width:72%;padding-right:2px;">
<input id="sidebar-id" type="email" name="login-email" style="width:100%; border:none;background-color:#F5F7FA;margin:2px 0; font-size:0.7rem;padding:7px 0;">
<input id="sidebar-password" type="password" name="login-password" style="width:100%;border:none;background-color:#F5F7FA;margin:2px 0;font-size:0.7rem;padding:7px 0;">
</div>
<button id="sidebar-login-btn" style="width:27%;background-color:#48CFAD;color:#ffffff;margin-left:2px;">
<span style="text-align:center;font-size:0.85rem;">로그인</span>
</button>
</form>
<div id="sidebar-login-info"> </div>
</div>
<div id="signUpContainer" style="">
<div id="getUser">
<button class="signset" setauth="reset-id">
<i class="fas fa-lock"></i>아이디 </button>
<button class="signset" setauth="reset-pw">비밀번호 찾기</button>
</div>
<div id="registerUser">
<button class="signset" setauth="register-user">
<i class="fas fa-user"></i>회원가입</button>
</div>
</div>
`
}
}
export default loginGuestScreen;
|
[ loginGuestScreen.js ]
티스토리의 style과 혼용하지 않기 위해서는 html에 직접 입력하는 방식을 사용한다.
3-5 loginUserScreen.js
loginUserScreen.js는 사용자 세션이 있는 경우(로그인 상태)에 랜더링되는 모듈이다. 구조는 loginGuestScreen.js와 같다.
const loginUserScreen = {
after_render: (auth) =>{
let logoutBtn = document.getElementById('wd-logout');
let mypageBtn = document.querySelectorAll('.wd-usr-btn');
mypageBtn.forEach(eachItems => {
eachItems.addEventListener('click' , (e) => {
let attrBtn = e.target.getAttribute('profile');
if(attrBtn == 'mypage'){
}else if(attrBtn == 'alert'){
console.log('알림 설정!');
}
})
});
logoutBtn.addEventListener('click', () => {
auth.signOut();
document.location.reload();
});
},
render: async(user) => {
return `
<div id="wd-login-success-container">
<p> ${user.email}님 </p>
<div id="wd-usr-loginInfo">
<button class="wd-usr-btn" profile="mypage">마이페이지</button>
<button class="wd-usr-btn" profile="alert">알림</button>
</div>
<button id="wd-logout-container">
<span id="wd-logout" style="cursor:pointer">로그아웃</span>
</button>
</div>
`
}
}
export default loginUserScreen;
|
[ loginUserScreen.js ]
위의 코드에서 주의할 부분은 attribute 속성값이다. html태그의 특정 클래스에는 임의적으로 속성을 지정할 수가 있다. 가령, 위와같이 'profile'이라는 속성을 지정한 뒤에 해당 값에 따라 이벤트를 설정하는 방법으로 구현가능하다.
3-6 style.css
로그인 폼 및 기타 CSS는 블로그 관리자 설정 => 스킨편집 => CSS에서 추가할 수 있다.
/* Sidebar wd-login */
#signUpContainer{
display: flex;
justify-content: space-between;
}
.signset{
font-size:.76rem;
color:#4a4d4c;
}
.signset > i{
margin-right:3px;
opacity: 0.7;
}
#wd-login-success-container{
display: flex;
flex-direction: column;
}
#wd-login-success-container p{
margin-bottom:10px;
margin-left:5px;
}
#wd-usr-loginInfo{
display:flex;
justify-content: center;
}
.wd-usr-btn{
background-color:#48CFAD;
color:white;
font-size:0.75rem;
width:49%;
padding:7px 0;
margin:5px 5px;
}
#wd-logout-container{
background-color:#ebebeb;
padding:7px 0;
margin:5px 5px;
font-size:0.73rem;
}
|
[ 스킨편집/css ]
4 실행 테스트
css설정까지 마쳤다면, 블로그 메인에 접속해보자. 아래와 같이 우측 상단에 나타난 로그인 폼을 볼 수 있다.
'웹개발 자료실 > Firebase 개발 Code' 카테고리의 다른 글
블로그 회원가입 제작 [3편. 마이 페이지] (0) | 2022.01.10 |
---|---|
블로그 회원가입 제작 [2편. 회원가입 페이지] (0) | 2022.01.07 |
Firebase『Auth 로그인, 비밀번호 찾기』 (1) | 2019.12.28 |
Firebase『Auth 회원가입, 이메일 인증,』 (10) | 2019.12.27 |
Firebase『Firestore 쿼리문』 (0) | 2019.12.12 |
댓글