본문 바로가기
스파르타(부트캠프)/TIL (Today I Learned)

[내일배움캠프] 스파르타 3일차_24.10.02

by Kimuky 2024. 10. 2.

공부 내용 및 활동 내용

 -  프로젝트 개발

1. 세션 구현 (Login, Logout) 
2. 모달창 구현 (input form)
3. Firestorage 이미지 (upload, download)
4. Firestore 데이터 (쿼리, 업데이트)


1. 세션 구현 (Login, Logout)

 로그인 구현을 위해선 어딘가에 로그인했다는 정보를 저장해야한다.

 그렇기에 많은 고민을 해보았다. 음... 고민해보고 구글링 중 쿠키, 로컬스토리지, 세션스토리지 라는 것이 있다는 것을 알게 되었다.

 

 - 처음

 처음에는 단순히 데이터를 저장 목적으로 Local storage를 통해 테스트를 해보았다.

// 데이터 저장
localStorage.setItem('username', 'Kimu');

// 데이터 가져오기
const username = localStorage.getItem('username');
console.log(username); // "Kimu"

// 데이터 삭제
localStorage.removeItem('username');

// 모든 데이터 삭제
localStorage.clear();

데이터를 손쉽게 저장, 가져오기, 삭제가 가능했으며 Key, Value 형태로 저장되어 굉장히 간편했다. 하지만 데이터가 브라우저를 닫아도 창을 닫아도 유지되어 세션을 유지하기에는 문제가 있어 포기했다.

 

- 중간

 여러 가지 조사를 하고 있던 도중 쿠키, 세션스토리지에 대해서 비교를 해보고 있었다. 쿠키와 세션스토리지 둘 다 데이터를 손쉽게 저장할 수 있었다. 허나 쿠키는 만료 날짜를 따로 설정해줘야 해서 세션을 유지 하기는 애매하다고 결정을 내렸다.

// 쿠키 설정
document.cookie = "username=kimu; expires=Fri, 31 Dec 2024 23:59:59 GMT; path=/";

// 쿠키 가져오기
const cookies = document.cookie; // "username=kimu; ..."
console.log(cookies);

// 쿠키 삭제
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/";

 

- 마지막

 세션 스토리지를 살펴 보는데, 탭이나 창을 닫으면 데이터가 삭제된다는 특징이 있었다. 내가 찾던 것이다..

드디어 구현이 가능할 것 같다는 생각이 들었다.

// 데이터 저장
sessionStorage.setItem('sessionUser', 'Kimu');

// 데이터 가져오기
const sessionUser = sessionStorage.getItem('sessionUser');
console.log(sessionUser); // "Kimu"

// 데이터 삭제
sessionStorage.removeItem('sessionUser');

// 모든 데이터 삭제
sessionStorage.clear();

 

그래서 세션스토리지를 어떻게 써야할지 잠시 고민에 빠졌다.

구현해야하는 페이지는 3페이지 모든 페이지에는 세션이 유지되야 하기에 별도의 스크립트를 이용해 html 파일에서 따로 호출할려고 한다.

$("#login_button").click(async function () {

            let login_id = $('#login_id').val()
            let login_pw = $('#login_pw').val()
            let id_check = false
            
            let docs = await getDocs(collection(db, "users"));
            
            docs.forEach((doc) => {
            
                let row = doc.data();
                
                if (login_id == row['id']) {                
                    id_check = true
                    if (login_pw == row['pw']) {
                        $("#login_box").css('display', 'none')
                        sessionStorage.setItem('user_id', login_id)
                        window.location.reload()
                        alert('로그인 되었습니다.')
                    } else {
                        console.log()
                        alert('비밀번호를 확인해주세요')
                    }
                }
            });

이렇게 로그인 패스워드가 문제없을 시, 세션스토리지에 해당 유저 아이디를 저장했다.

$(document).ready(function() {
    // 세션 user_id가 가져와지면
    if (Boolean(sessionStorage.getItem('user_id'))) {
        $("#login_box").css('display', 'none');

        let id = sessionStorage.getItem('user_id');
        let temp_html = `<div id='session' class="session">'${id}'님 환영합니다</div>`;
        let logout = 
        `<div id='logout' class="logout"><button type="button" 
        class="btn btn-outline-dark btn-sm">Logout</button></div>`;
        // 왼쪽 메뉴에 ''님 환영합니다
        $("#left_menu").prepend(logout);
        $("#left_menu").prepend(temp_html);
        $("#session").css('visibility', 'visible');
        $("#join_button").css('disabled', 'false');

        $("#logout").click(async function () {
            sessionStorage.clear();
            window.location.reload();
            alert('로그아웃 되었습니다.')
         })

        // 이미지 크게
        $("#main_img").css('width', '1200px');
        $("#main_img").css('height', '700px');
    } 
});

이렇게 DOM이 완전히 로드되면 작동하도록 코드를 써줬다. 세션값이 가져와지면 로그인 창을 없애고 환영메세지, 로그아웃 버튼이 생성되도록 구현 해주었다.

또한, 로그아웃 버튼 클릭 시, 세션스토리지를 클리어시켰지만 실제로는 접속한 아이디 값을 remove 해줘야한다.

귀찮은건 안비밀..


2. 모달창 구현 (input form)

 

이미 메인페이지에서 구현했기에 다시 구현하는 건 그리 어렵지 않았다.

// html
<div id="modal_container" class="hidden">
        <div class="member_modal_content">
            <h3>Join</h3>
            <div class="form-floating mb-5"></div>
            <h6>이름</h6>
            <div class="form-floating mb-3">
                <input type="text" class="form-control" id="modal_input_name" placeholder="">
                <label for="floatingInput">예&#41; 김스파르타</label>
            </div>
            <h6>MBTI</h6>
            <div class="form-floating mb-3">
                <input type="text" class="form-control" id="modal_input_mbti" placeholder="Password">
                <label for="floatingPassword">예&#41; ESTJ</label>
            </div>
            <h6>협업 스타일</h6>
            <div class="form-floating mb-3">
                <input type="text" class="form-control" id="modal_input_style" placeholder="Password">
                <label for="floatingPassword">예&#41; 소통 위주의 협업</label>
            </div>
            <h6>블로그 링크</h6>
            <div class="form-floating mb-3">
                <input type="text" class="form-control" id="modal_input_link" placeholder="Password">
                <label for="floatingPassword">Tistory, velog, Github 등 자유롭게 올려주세요</label>
            </div>
            <h6>한마디</h6>
            <div class="form-floating mb-3">
                <input type="text" class="form-control" id="modal_input_short" placeholder="Password">
                <label for="floatingPassword">짧게 한 말씀 부탁드려요~</label>
            </div>
            <div class="input-group mb-3">
                <label class="input-group-text" for="inputGroupFile01">Upload</label>
                <input type="file" class="form-control" id="modal_input_img" accept="image/*">
            </div>
            <div class="button_box">
                <div class="button_top_box">
                    <button type="button" id="modal_input_join" class="btn btn-dark btn-lg">Join</button>
                </div>
                <div class="button_bottom_box">
                    <button id="modal_close_button" type="button" class="btn btn-primary">Close</button>
                </div>
            </div>

        </div>
    </div>

 

//css
.member_modal_content {
    position: absolute;
    background-color: #ffffff;
    width: 500px;
    height: 900px;
    padding: 15px;
    border-radius: 20px;
}
.member_modal_content> h6 {
    font-weight: bold;
}

#modal_container.hidden {
    display: none;
}
//js 두 코드로 제어했다 -제이쿼리 활용
// 모달창 켤때
$('#modal_container').css('display', 'flex')
$('#card').css('visibility', 'hidden')

//모달창 끌때
$("#modal_close_button").click(async function () {
$('#modal_container').css('display', 'none')
$('#card').css('visibility', 'visible')
})

3. Firestorage 이미지 (upload, download)

 

 

오늘 여기서 가장 많은 시간을 소요했던 것 같다.

모달 창을 통해 FireStorage 이미지를 업로드하여 FireStorage url을 Firestore에도 저장하는 작업을 거쳤다.

 

// 버젼 안맞으면 오류납니다 꼭 맞추세여... 다 필요없는데 필요한 거 쓰시길
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
import { getFirestore } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
import { collection, addDoc } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
import { getDocs } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
import { doc, updateDoc } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
import { setDoc } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
import { getStorage, ref, getDownloadURL, uploadBytes } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-storage.js";
import { query, where } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";


// 기본 설정
// Your web app's Firebase configuration
const firebaseConfig = {
		// 키는 각자 거 넣으십쇼
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const db_img = getStorage(app);

// 이미지 들고오기
let imgFile = img_input.files[0]

// 이미지 레퍼런스 생성
const profile_img_ref = ref(db_img, `profile/${sessionStorage.getItem('user_id')}`);

// 이미지 업로드
await uploadBytes(profile_img_ref, imgFile).then((snapshot) => {
    console.log('Uploaded a blob or file!');
})

// 이미지 다운로드
const imagesRef = ref(db_img, `profile/${sessionStorage.getItem('user_id')}`)
const url = await getDownloadURL(imagesRef)

// 이미지 받아온 것을 users 콜렉션 안에 uid를 찾아서 url을 저장
await updateDoc(doc(db, "users", find_uid), {
    url: url
});

4. Firestore 데이터 (쿼리, 업데이트)

Firestore도 저장소다. 그래서 쿼리를 활용할 수 있다.

// Import the functions you need from the SDKs you need 필요한거 쓰세요
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-app.js";
import { getFirestore } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
import { collection, addDoc } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
import { getDocs } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
import { doc, updateDoc } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
import { setDoc } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";
import { getStorage, ref, getDownloadURL, uploadBytes } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-storage.js";
import { query, where } from "https://www.gstatic.com/firebasejs/9.22.0/firebase-firestore.js";

// 기본
const app = initializeApp(firebaseConfig);
const db = getFirestore(app);

// 세션 정보를 통해 검색
const q = query(collection(db, "users"), where("id", "==", sessionStorage.getItem('user_id')));

// getDocs에 쿼리를 넣고 해당 uid를 찾는다
const querySnapshot = await getDocs(q);
let find_uid
querySnapshot.forEach((doc) => {
	find_uid = doc.id
});

//Firestore 업데이트
await updateDoc(doc(db, "users", find_uid), {
    name: name,
    mbti: mbti,
    style: style,
    link: link,
    short: short,
    confirm: '1'
});

쿼리도 sql랑 비슷해서 사용하기 간편했다. 

 


 

- 코드가 많아질수록 내 코드를 읽기가 힘들다... mvc 패턴이던 깔끔하게 짤 수있는 사람이 되야겠다.. 너무 어운것

- 아직 web css js 모르는 것이 너무 많다. 계속 코드를 돌려가며 숙달해야겠다.

- 그래도 개발은 즐겁다.

 

개발상태

 

 

-> 마지막에 버그 발생... 내일 해야겠다. -> 수정해서 다시 올림 새벽 1시다 자야겠다..

 버그 고치고 자야 잠을 Even하게 잘 수 잇어요~

다들 감기 조심하시길