본문 바로가기

블로그 회원가입 제작 [3편. 마이 페이지]

by Recstasy 2022. 1. 10.

회원가입 이후 우측창에서 '마이페이지'로 이동할 수 있는 링크를 볼 수 있다.

 

[ 마이페이지 생성] 

 

 

'마이페이지'에서는 회원가입 폼에서 입력한 자신의 정보와 기타 데이터를 볼 수 있다.

 

01

 

 

 

 

 

 


1 myPageInterface.js :: 인터페이스 생성

myPageInterface.js는 페이지 이름을 필터링한 뒤에 페이지 html코드를 랜더링하는 인터페이스 역할을 한다. 

 

  import { getAuth, updateProfile } from "https://www.gstatic.com/firebasejs/9.6.1/firebase-auth.js";
 
  const firebaseApp = initializeApp(firebaseConfig());
  const auth = getAuth();
   
  window.addEventListener('load', async() => {
      const content = document.getElementById('content')
     
      auth.onAuthStateChanged(async(user) => {

            if(user){
                content.innerHTML = await myPageScreen.render(user);
                if(myPageScreen.after_render) await myPageScreen.after_render(user);
               
            }else{
                window.location.href="https://webdoli.tistory.com/";
            }
        })
       
  });

[ wd-myPageInterface.js ]

 

auth.onAuthStateChanged( )의 리턴값, user가 존재할 경우에만 myPageScreen모듈의 .render( )메서드를 호출한다.

 

 

 

 

 

 

 


2 myPageScreen.js :: 페이지 랜더링

마이페이지에는 '세팅', '내 폴더', '제작기능', '찾기', '장바구니', '계좌' 5가지 탭이 있다. 사용자가 각 탭을 클릭할 때마다 FireStore DB는 요청받은 정보를 전달해야한다. 이를 위해서는 FireStore 관련 모듈이 필요하고, 각 버튼에 해당하는 랜더링 파일 6개가 필요하다.

 

myPageScreen.js 파일은 FireStore( )관련 모듈을 받고, 6개 탭에 관한 랜더링 모듈을 import한다. 또한 myPage 인터페이스에 전달하는 html태그를 반환한다. render( )메서드에는 html파일을 반환하고, after_render( )메서드는 해당 태그에 관한 사용자의 반응 이벤트를 구현해준다. 여기서 아이콘 관련 라이브러리는 "https://svgbox.net/iconset/materialui" svgBox를 이용한다. 

 

 


   
import { collection, getDocs, getDoc, doc, getFirestore, query } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-firestore.js';
       
    const db = getFirestore();
    const mypageRouter = {
        'setting': settingScreen,
        'myfolder': myfolderScreen,
        'film': filmScreen,
        'search': searchScreen,
        'cart': cartScreen,
        'account': accountScreen
    }
   
    let currentSlcBtn = mypageRouter['setting'];
   
    const myPageScreen = {
        after_render: async(user) =>{
            let mypageIcons = document.getElementsByClassName("mypage-icons");
            let mypageIconDivs = document.querySelectorAll('.mypage-aside>div');
            const mypageBoard = document.getElementById('mypageBoard');
       
                [...mypageIcons].forEach(icon => {
               
                    icon.addEventListener('click', async(e) => {
                            e.preventDefault();
                            resetTag(mypageIconDivs);
                            icon.parentElement.setAttribute('class','slc');
                   
                            let iconName = icon.getAttribute('data-name');
                            currentSlcBtn = await mypageRouter[iconName];

                            mypageBoard.innerHTML = await currentSlcBtn.render(user);
                            if(mypageRouter[iconName].after_render()) await mypageRouter[iconName].after_render(user);
                    });
               
                });
           
            mypageBoard.innerHTML = await currentSlcBtn.render(user);
            if(currentSlcBtn.after_render()) await currentSlcBtn.after_render(user);
           
        },
   
        render: async(user) => {
       
            const userInfoDoc = doc(db, "webdoliUsers", user.uid);
            const docSnap = await getDoc(userInfoDoc);
       
            if(docSnap.exists()){
                console.log('유저 정보: ', docSnap.data());
            }
       
       
            return `
            <div id="myPageContainer">

                <div class="mypage-aside">
                    <div id="mypage-setting" class="slc">
                        <svg class="mypage-icons" data-name="setting" data-src="https://s2.svgbox.net/materialui.svg?ic=settings" width="32" height="32" color="#fff"></svg>
                    </div>
                    <div id="mypage-myfolder">
                        <svg class="mypage-icons" data-name="myfolder" data-src="https://s2.svgbox.net/materialui.svg?ic=folder_open" width="32" height="32" color="#fff"></svg>
                    </div>
                    <div id="mypage-cgfilm">
                        <svg class="mypage-icons" data-name="film" data-src="https://s2.svgbox.net/materialui.svg?ic=view_in_ar" width="32" height="32" color="#fff"></svg>
                    </div>
                    <div id="mypage-search">
                        <svg class="mypage-icons" data-name="search" data-src="https://s2.svgbox.net/materialui.svg?ic=search" width="32" height="32" color="#fff"></svg>
                    </div>
                    <div id="mypage-cart">
                        <svg class="mypage-icons" data-name="cart" data-src="https://s2.svgbox.net/materialui.svg?ic=shopping_cart" width="32" height="32" color="#fff"></svg>
                    </div>
                    <div id="mypage-account">
                        <svg class="mypage-icons" data-name="account" data-src="https://s2.svgbox.net/materialui.svg?ic=credit_card" width="32" height="32" color="#fff"></svg>
                    </div>
                </div>

            <div class="mypage-main">
                <div class="mypage-main-title">
                    <h3>${docSnap.data().userID}님 페이지</h3>
                </div>
                <div class="mypage-main-content" id="mypageBoard">
                </div>
            </div>

        </div>
            `
        }
    }
   
    const resetTag = (ele) => {
        ele.forEach(item => {
            item.setAttribute('class', '');
        });
        return;
    }
   
    export default myPageScreen;

[ myPageScreen.js ]

 

 

파이어베이스 쿼리관련 메서드는 여러가지가 있으며, 각 상황에 맞는 쿼리를 사용하면 된다. 위의 경우에는 getDoc모듈과 .exists( )메서드를 조합했다. 단, 단일 데이터를 검색할 때는 .exists( )메서드보다 .empty( )가 유용할 수 있다. 쿼리 관련 정보는 아래 링크에서 확인해보자.

 

https://firebase.google.com/docs/firestore/query-data/get-data

 

Cloud Firestore로 데이터 가져오기  |  Firebase Documentation

의견 보내기 Cloud Firestore로 데이터 가져오기 두 가지 방법으로 Cloud Firestore에 저장된 데이터를 검색할 수 있습니다. 문서, 문서 컬렉션 또는 쿼리 결과에 대해 이러한 방법 중 하나를 사용할 수

firebase.google.com

 

 

https://firebase.google.com/docs/firestore/query-data/queries

 

Cloud Firestore에서 단순 쿼리 및 복합 쿼리 실행  |  Firebase Documentation

의견 보내기 Cloud Firestore에서 단순 쿼리 및 복합 쿼리 실행 Cloud Firestore는 컬렉션 또는 컬렉션 그룹에서 검색할 문서를 지정하는 강력한 쿼리 기능을 제공합니다. 데이터 가져오기 및 실시간 업

firebase.google.com

 

 

 

 

 

 

 

 


3 하위 모듈

mypageScreen.js에서 요청한 하위 6개의 모듈이 필요하다. 테스트용이므로 내용보다는 연결에 중점을 뒀지만, 실제로 서비스를 공개한다면 fetch나 ajax를 통한 외부데이터를 각 모듈에 담을 수 있다.

 

3-1 settingScreen.js

    import { collection, getDocs, getDoc, doc, getFirestore, query } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-firestore.js';
       
    const db = getFirestore();
    const settingScreen = {
        after_render: () =>{
       
        },
   
        render: (user) => {
            return `
                    <div class="mypage-main-control">
                        <span>유저</span>
                        <span>uid:${user.uid} </span>
                    </div>
                    <div class="mypage-main-control">
                        <span>이메일</span>
                        <span> email: ${user.email}  </span>
                    </div>
                    `
        }
    }
   
    export default settingScreen;

[ settingScreen.js ]

 

 

이어지는 myfolderScreen.js ~ accountScreen.js까지 모두 같은 형식으로 채워준다.

 

3-2 myfolderScreen.js


   
import { collection, getDocs, getDoc, doc, getFirestore, query } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-firestore.js';
       
    const db = getFirestore();
       
    const myfolderScreen = {
        after_render: () =>{
       
        },
   
        render: async(user) => {
       
            return `
                <h3>내 폴더 Board </h3>
            `
        }
    }
   
    export default myfolderScreen;

[ myfolderScreen.js  ]

 

 

3-3 filmScreen.js


   
import { collection, getDocs, getDoc, doc, getFirestore, query } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-firestore.js';
       
    const db = getFirestore();
       
    const filmScreen = {
        after_render: () =>{
       
        },
   
        render: async(user) => {
       
            return `
                <h3> CG제작 Board </h3>
            `
        }
    }
   
    export default filmScreen;

[ filmScreen.js ]

 

 

3-4 searchScreen.js


   
import { collection, getDocs, getDoc, doc, getFirestore, query } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-firestore.js';
       
    const db = getFirestore();
       
    const searchScreen = {
        after_render: () =>{
       
        },
   
        render: async(user) => {
       
            return `
                <h3> 소스찾기 Board </h3>
            `
        }
    }
   
    export default searchScreen;

[ searchScreen.js  ]

 

 

3-5 cartScreen.js


   import { collection, getDocs, getDoc, doc, getFirestore, query } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-firestore.js';
       
    const db = getFirestore();
       
    const cartScreen = {
        after_render: () =>{
       
        },
   
        render: async(user) => {
       
            return `
                <h3>쇼핑카트 Board </h3>
            `
        }
    }
   
    export default cartScreen;

[ cartScreen.js  ]

 

 

3-6 accountScreen.js


   
import { collection, getDocs, getDoc, doc, getFirestore, query } from 'https://www.gstatic.com/firebasejs/9.6.1/firebase-firestore.js';
       
    const db = getFirestore();
       
    const accountScreen = {
        after_render: () =>{
       
        },
   
        render: async(user) => {
       
            return `
                <h3>내 계좌 Board </h3>
            `
        }
    }
   
    export default accountScreen;

[ accountScreen.js  ]

 

 

 

 

 

 

 


4 myPage.css

메뉴에 토글 효과를 구현하기 위한 CSS를 구현한다. 티스토리 블로그에서 구현하는 상황에서는 부트스트랩, 파운데이션 같은 css라이브러리들을 배제하는 편이 좋다. 태그, 클래스명이 티스토리 css와 충돌할 수도 있기 때문이다. 

 

  #container .content-wrap{
    margin-top: -350px;
  }
 
  #myPageContainer{
    display: flex;
    width: 680px;
  }
 
  .mypage-aside{
    width: 20%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
  }
  .mypage-aside > div:first-child{
    margin-top: 70px;
  }
 
  .mypage-aside > div.slc{
    background-color: #eda36b;
  }
 
  .mypage-aside > div{
    padding: 10px 15px;
    margin: 10px 0;
    background-color: #48CFAD;
    color: white;
    cursor: pointer;
  }
 
  .mypage-aside > div:hover{
    background-color: #979c9b;
  }
 
  .mypage-main{
    width: 80%;
    display: flex;
    flex-direction: column;
  }
 
  .mypage-main-title{
    border-bottom: 1px solid #979c9b;
    padding: 15px 5px;
  }
 
  .mypage-main-content{
    padding: 20px 5px;
    background: #f3f5f7;
      margin-top: 10px;
      height: 100%;
  }
 
  .mypage-main-content > h3{
    padding: 0 10px;
  }
 
  .mypage-main-control{
    margin-bottom: 15px;
    padding: 5px 10px;
  }

[ myPage.css ]

 

 

css를 적용한 후에는 아래와 같은 '마이페이지'를 제작할 수 있다. 위의 코드를 응용한다면, 관리자 페이지도 제작할 수 있으며, 더 나아가 커뮤니티 게시판 서비스도 자체적으로 제공할 수 있다.

 

 

 

댓글

최신글 전체

이미지
제목
글쓴이
등록일