관리 메뉴

나구리의 개발공부기록

[온보딩 1주차]4주차, 5주차 본문

내일배움캠프_spring6기

[온보딩 1주차]4주차, 5주차

소소한나구리 2025. 2. 19. 17:22
728x90

4주차

파이어 베이스(Firebase)

구글이 개발한 모바일 및 웹 애플리케이션 서버리스(무서버)개발 플랫폼

백엔드 인프라를 구축하거나 관리하는 복잡한 작업 없이 핵심 기능에 집중할 수 있도록 도와줌

즉, 백엔드 코드 한 줄 없이도(서버 없이) 프론트엔드 지식만알아도 웹 서비스를 출시할 수 있음(물론 자유도는 떨어짐)

 

사용량만 넘어가지 않으면 무료

보안 인증, NoSQL DB, Storage, 백엔드 로직 API, 호스팅 등등의 여러가지 서비스를 손쉽게 사용할 수 있음

 

프로젝트 만들기 

더보기

1. 사이트 접속 후 우측 Go to console 이동

 

2. 프로젝트 시작하기

 

3. 프로젝트 이름 설정 후 계속

 

4. AI 지원, 구글 애널리틱스 사용 유/무를 설정하고 계속

 

5. 애널리틱스 계정이 있다면 선택하고 없으면 위치를 대한민국으로 선택 후 프로젝트 생성

 

6. 잠시 기다리면 생성 됨

 

7. 여러 앱에 파이어베이스를 연동할 수 있음 (IOS, 안드로이드, 웹)

 

8. 웹을 선택하면 이렇게 등록할 웹 앱 이름을 정하고 앱 등록

 

9. npm이나, script 태그를 사용하여 파이어베이스에 앱을 등록할 수 있음

데이터 베이스 개념

데이터베이스는 데이터 저장하고 여러 사람들이 관리하는 데이터의 모음임

즉, 데이터를 저장한 사용자가 데이터를 잘 찾기 위해 존재하는 것!

 

여러 회사가 제공하는 데이터 베이스마다 장, 단점이 존재하므로 데이터 베이스를 선택할 때에는 각각의 DB의 특징과 성능차이 등을 어느정도 파악하고 있을 필요성이 있음

 

DB는 크게 두 가지 종류가 있으며 각각의 DB 유형은 다른 용도데이터의 구조와 요구 사항에 맞춰서 적절한 데이터베이스 유형을 선택하는 것이 중요함

 

관계형 데이터베이스: SQL

  • 정리된 정보를 다룰 때 사용
  • 정형화된 엑셀의 형태로 사용함
  • Index를 활용하여 조회가 매우 빠름

비 관계형 데이터베이스: NoSQL (Not Only SQL)

  • 복잡하거나 유연한 정보를 다룰 때 사용
  • 정형화 되어있지 않음
  • 유연하기 때문에 비즈니스의 형태가 자주 바뀌는 곳에서 주로 사용함

데이터 베이스는 프로그램과 같은 것이므로 개인 PC에도 설치할 수 있지만 이 마저도 요새는 Cloud 형태로 제공해주는 곳이 많음

Firestore Database 개념

파이어스토어는 구글의 클라우드 기반 NoSQL 데이터베이스임

 

파이어스토어 만들기

더보기

1. 콘솔 좌측 빌드에 Firestore Database 클릭하여 이동 후 데이터 베이스 만들기 선택

2. 위치를 서울로 설정하고 프로적션 모드로 시작을 선택 후 만들기를 누르면 시간이 지나면 만들어짐

3. 생성 후 첫 화면

 

4. 규칙을 들어가서 read, write를 true로 변경하면 보안 규칙이 공개가 되어 누구나 읽고, 쓰기가 가능함

물론 실제로 운영할 때는 권한에 따라 설정을 하는 것이 좋음

 

5. 좌측 상단 프로젝트 설정 클릭

 

6. 설정 하단의 SDK 설정 및 구성으로 들어가서 구성을 선택

 

7. 해당 코드를 사용하고자 하는 html파일의 <script> 태그 사이에 입력해야 함

 

먼저 스크립트 태그에 type="module"를 입력해주고 파이어베이스 설정 코드를 입력해 주어야 함

 

import 코드는 기본 설정 코드이므로 파이어 베이스를 사용하기 위해 필요한 코드이며

그 아래에 위의 구성 코드를 복사하여 붙여 넣고 파이어베이스 인스턴스를 초기화하면 초기 세팅이 끝남

<script type="module">
    // Firebase SDK 라이브러리 가져오기
    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";

    // Firebase 구성 정보 설정
    // For Firebase JS SDK v7.20.0 and later, measurementId is optional
    const firebaseConfig = {
        apiKey: "AIzaSyCNQd-VZsNbgZtzjrz52l5hqfvIDdt4ZzY",
        authDomain: "sparta-5fba9.firebaseapp.com",
        projectId: "sparta-5fba9",
        storageBucket: "sparta-5fba9.firebasestorage.app",
        messagingSenderId: "500040163959",
        appId: "1:500040163959:web:b22d78fc501d9be37a5c72",
        measurementId: "G-X021V6B07D",
    };

    // Firebase 인스턴스 초기화
    const app = initializeApp(firebaseConfig);
    const db = getFirestore(app);

    // ... 기타 코드들 생략
</script>

Firestore Database에 데이터 넣기

$("#id").click(async function () {
    let doc = {};
    await addDoc(collection(db, "콜렉션이름"), doc);
});

 

<script> 태그를 type="module">로 적용하게 되면 onclick 등의 기능이 동작하지 않기 때문에, 위의 코드처럼 id값을 기반으로한 JQuery를 적용해야 동작함

 

id값을 적용한 대상이 클릭이 되면 정의한 두줄의 코드가 동작하는데 그 두 줄의 코드가 핵심심

doc 변수는 저장하고 싶은 데이터를 변수에 저장하는 것이고, 그 아래의 코드는 위의 변수(저장할 데이터)를 지정한 콜렉션에 저장하는 코드임

 

즉, 파이어베이스(db변수에 저장된 데이터베이스)에 원하는 지정한 콜렉션에 데이터를 저장하는 코드임

 

$("#postingbtn").click(async function () {
    let doc = {};
    await addDoc(collection(db, "albums"), doc);
});
<div class="mybtn">
    <button id="postingbtn" type="button" class="btn btn-dark">
        기록하기
    </button>
    <button type="button" class="btn btn-outline-dark">닫기</button>
</div>

 

버튼 태그에 id값을 지정하고 JQuery에 지정한 id값을 입력한 후에 await addDoc(collection(db, "albums"), doc)으로 지정

이렇게 하면 doc 변수에 담긴 데이터가 db(파이어베이스 스토리지)의 albums 콜렉션에 저장이 됨

$("#postingbtn").click(async function () {
    let doc = {'name':'bob', 'age':30};
    await addDoc(collection(db, "albums"), doc);
});

 

doc의 내용을 딕셔너리 형태로 작성하고 기록하기 버튼을 클릭하면 아래의 이미지 처럼 데이터가 딕셔너리(키:밸류)의 형태로 필드에 추가 된 것을 확인할 수 있음

 

이렇게 <script> 태그에 module을 적용하게 되면 페이지가 로딩 된 다음에 스크립트 태그의 코드들이 적용되기 됨

 

그래서 기존에 작성한 fetch를 통해 서울 날씨 정보를 받아와서 노출시키는 코드는 일부로 페이지가 로딩 된 다음에 정보를 받아오게 하도록 추가적인 코드가 필요하였음

그러나 지금은 <script> 태그에 type="module"이 적용되었으므로 $(document).ready(function()) 부분을 제거하고 실제 동작에 필요한 fetch 부분만 적용시켜도 정상적으로 동작함

// 기존의 코드
$(document).ready(function () {
    let url = "http://spartacodingclub.shop/sparta_api/seoulair";
    fetch(url)
        .then((res) => res.json())
        .then((data) => {
            let mise = data["RealtimeCityAir"]["row"][0]["IDEX_NM"];
            $("#mise").text(mise);
        });
});

// <script> 태그에 module을 적용하면 이렇게만 적용해도 동작함
let url = "http://spartacodingclub.shop/sparta_api/seoulair";
fetch(url)
    .then((res) => res.json())
    .then((data) => {
        let mise = data["RealtimeCityAir"]["row"][0]["IDEX_NM"];
        $("#mise").text(mise);
    });

 

 

나만의 추얼앨범의 데이터를 DB에 저장하기

나만의 추억앨범의 기록하기 버튼을 눌렀을 때 작성한 앨범 이미지, 앨범 제목, 앨범 내용, 앨범 날짜를 DB에 저장하기 위해서 기존에 makdCard() 함수에 작성했던 각 지정된 id의 값을 변수에 저장하는 코드를 가져와서 함수를 완성

$("#postingbtn").click(async function () {
    let image = $("#image").val();
    let title = $("#title").val();
    let content = $("#content").val();
    let date = $("#date").val();

    let doc = {
        'image' : image,
        'title' : title,
        'content' : content,
        'date' : date,
    };
    await addDoc(collection(db, "albums"), doc);
});

 

이렇게 작성하면 기록하기 버튼을 눌렀을 때 각 태그의 값을 가져온 변수들의 값을 딕셔너리 형태로 albums 컬렉션에 저장할 수 있으며 아래 이미지를 보면 데이터가 DB에 저장되는 것을 확인할 수 있음

 

데이터 저장 후 화면 새로고침 하기

지금은 데이터를 입력한 후 기록하기 버튼을 클릭하면 DB에 데이터는 저장되지만 화면에 데이터가 계속 남아있고 저장이 잘 되었는지 명확하게 확인하기가 어려움

 

작성한 함수에 arlert()로 저장이 완료되었습니다 라는 팝업을 띄워서 저장이 되었다는 것을 알려주고, 화면을 새로고침하여 작성한 데이터를 날려주면 데이터는 DB에 저장되고 다시 데이터를 작성하기 편하도록 작성한 문구들아 삭제가 됨

$("#postingbtn").click(async function () {
    let image = $("#image").val();
    let title = $("#title").val();
    let content = $("#content").val();
    let date = $("#date").val();

    let doc = {
        image: image,
        title: title,
        content: content,
        date: date,
    };
    await addDoc(collection(db, "albums"), doc);

    alert('저장이 완료되었습니다.')
    window.location.reload();
});


함수를 완성하고 앨범 기록을 위해 각 데이터를 입력하고 기록하기 버튼을 누르면 이렇게 저장되었다는 팝업과 함께 새로고침되어 페이지는 원상 복구가 되고, DB에는 입력한 데이터가 반영되는 것을 확인할 수 있음 

 

여기에 추가적으로 동작하지 않는 기능이 있는데, 추억 저장하기 버튼을 클릭하면 toggle()이 작동하여 앨범을 기록하기 위해 데이터를 입력하는 창이 on/off가 되어야 하지만 <script> 태그에 type="module"을 저장했으므로 동작하지 않음

<button id="savebtn">추억 저장하기</button>
$("#savebtn").click(async function () {
    $("#postingbox").toggle();
});

 

위 처럼 추억 저장하기 버튼에 id를 지정하고, 해당 id를 클릭했을 때 id가 postingbox인 태그가 토글 되도록하면 기존처럼 추억 저장하기 버튼을 누르면 앨범 기록을 위한 카드가 on/off 되는 것을 확인할 수 있음

 

Firestore Database에서 데이터 가져오기

let docs = await getDocs(collection(db, "콜렉션이름"));
docs.forEach((doc) => {
    let row = doc.data();
    console.log(row);
});

 

DB에 저장된 값을 불러오기 위한 뼈대 코드

지정한 콜렉션의 데이터를 docs의 변수에 담은 후 docs의 변수를 forEach문으로 순회하여 값들을 가져올 수 있음

 

원한다면 반복분이 아니라 특정 데이터를 가져오도록 할 수 있음

 let docs = await getDocs(collection(db, "albums"));
        docs.forEach((doc) => {
            let row = doc.data();
            console.log(row);
        });

 

이렇게 데이터가 저장된 컬렉션을 입력하고 잘 가져오는지 브라우저의 console을 확인해보면 DB에 저장된 데이터들이 콘솔에 출력되는 것을 확인할 수 있음

 

이제 DB에 저장된 데이터가 페이지에 반영되도록 card를 붙이기만 하면 됨

 

기존에 동일한 동작을 하던 makeCard()의 함수 코드를 그대로 복사하여 forEach 문의 실행되는 {  } 중괄호 사이로 복사, 붙여넣기를 수행할 때 doc.date()로 DB의 데이터를 변수에 저장하는 코드 밑에 붙여넣기를 진행

 

row값에 저장된 각 필드를 변수로 저장한 후 해당 변수의 값을 활용하여 html 코드를 완성시켜 붙여주도록 수정하면 자동으로 DB의 데이터가 card에 반영되어 추가되는 것을 확인할 수 있음

let docs = await getDocs(collection(db, "albums"));
docs.forEach((doc) => {
    let row = doc.data();

    let image = row['image'];
    let title = row['title'];
    let content = row['content'];
    let date = row['date'];

    let addTag = `
                <div class="col">
                    <div class="card h-100">
                        <img
                        src="${image}"
                        class="card-img-top"
                        alt="..."
                        />
                        <div class="card-body">
                        <h5 class="card-title">${title}</h5>
                        <p class="card-text">${content}</p>
                        </div>
                        <div class="card-footer">
                        <small class="text-body-secondary">${date}</small>
                        </div>
                    </div>
                </div>`;

    $("#card").append(addTag);
});

 

이제 코드가 완성되어 기존에는 앨범을 기록했을때 어딘가에 저장을 하지 않았기 때문에 새로고침하거나 새창을 띄우면 데이터가 날라갔지만 이제는 서버(정확하게는 저장소)에서 데이터를 불러와서 출력하기 때문에 기존의 기록과, 새로운 기록도 모두 영구적으로 저장되고 웹페이지에 반영되는 것을 확인할 수 있음

 


5주차

스파르타 플릭스에 영화 데이터 넣기

먼저 나만의 앨범에서 처럼 스파르타 플릭스 화면에서도 파이어베이스를 사용할 수 있도록 세팅을 해야함

기존에 나만의 앨범에서 설정했던 코드를 그대로 활용하여 스파르타 플리스의 script에도 동일하게 적용해주면 됨

이때 type = "module"이 빠지지 않도록 해야함

<script type="module">
    // Firebase SDK 라이브러리 가져오기
    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";

    // Firebase 구성 정보 설정
    // For Firebase JS SDK v7.20.0 and later, measurementId is optional
    const firebaseConfig = {
        apiKey: "AIzaSyCNQd-VZsNbgZtzjrz52l5hqfvIDdt4ZzY",
        authDomain: "sparta-5fba9.firebaseapp.com",
        projectId: "sparta-5fba9",
        storageBucket: "sparta-5fba9.firebasestorage.app",
        messagingSenderId: "500040163959",
        appId: "1:500040163959:web:b22d78fc501d9be37a5c72",
        measurementId: "G-X021V6B07D",
    };

    // Firebase 인스턴스 초기화
    const app = initializeApp(firebaseConfig);
    const db = getFirestore(app);
    
    ....
</script>

 

스파르타 플릭스에서는 기존에 파이어 베이스를 사용하기 전에 동작하던 모든 동작이 정상적으로 동작하고 기록하기 버튼을 눌렀을 때 카드에 적힌 내용을 DB에 저장되도록 하는 것이 1차적인 목표임

 

<button id="postingbtn" type="button" class="btn btn-danger">
    기록하기
</button>
$("#postingbtn").click(async function () {
    let image = $("#image").val();
    let title = $("#title").val();
    let comment = $("comment").val();
    let starNum = parseInt($("#starNum").val());

    let star = "";
    for (i = 0; i < starNum; i++) {
        star += "⭐";
    }

    let doc = {
        'image': image,
        'title': title,
        'comment': comment,
        'star': star,
    };
    await addDoc(collection(db, "movies"), doc);

    alert("저장이 완료되었습니다.");
    window.location.reload();
});

 

우선 기록하기 버튼에 id를 적용하고 id값을 활용하여 동적으로 동작하기 위한 코드를 작성하고, 나만의 추억 앨범에서 적용했던 코드를 가져와서 라벨의 id 값만 해당 html에 맞게 수정해주면 적용이 완료됨

 

각 id값이 적용된 태그들의 값을 각 변수에 저장하는 것은 동일하며 스파르타플릭스 html 파일에서는 별점이 select 태그이므로 value의 값을 문자열 타입의 숫자(1, 2, 3, 4, 5)로 가져온 것을 int로 변환하여 그 개수만큼 별 이모티콘을 반복문으로 저장하도록 코드를 수정하면 적용이 완료됨

 

 

카드에 데이터를 입력하고 기록하기를 해보면 데이터 베이스에 데이터가 잘 들어가는 것을 확인할 수 있음

추가적으로 영화 기록하기 버튼을 눌렀을 때 영화를 기록하는 toggle()기능도 정상적으로 동작하도록 수정해야 함

 

<button id = "savebtn" type="button" class="btn btn-outline-light">
    영화 기록하기
</button>
$("#savebtn").click(async function () {
    $("#postingbox").toggle();
});

 

이렇게 영화 기록하기 버튼에 id값을 지정하고 함수명이 아닌 id값으로 함수가 동작하도록 수정하면 영화 기록하기 버튼을 누를때마다 toggle()이 정상 동작하여 영화 기록 창이 on/off 되는 것을 확인할 수 있음

 

 

또한, 마찬가지로 실시간 서울의 기온을 가져오는 fetch 함수의 코드도 script에 module을 적용했으므로 아래의 코드 처럼 $(document).ready(fucntion()) 부분을 삭제해도 정상적으로 데이터가 호출됨

let url = "http://spartacodingclub.shop/sparta_api/weather/seoul";
fetch(url)
    .then((res) => res.json())
    .then((data) => {
        let temp = data["temp"];
        $("#temp").text(temp);
    });

스파르타 플릭스에 서버 데이터를 가져와서 붙이기

let docs = await getDocs(collection(db, "movies"));
docs.forEach((doc) => {
    let row = doc.data();

    let image = row["image"];
    let title = row["title"];
    let comment = row["comment"];
    let star = row["star"];

    let addMovie = `
    <div class="col">
        <div class="card h-100">
            <img
                src="${image}"
            />
            <div class="card-body">
                <h5 class="card-title">${title}</h5>
                <p class="card-text">${star}</p>
                <p class="card-text">${comment}</p>
            </div>
        </div>
    </div>`;

    $("#card").append(addMovie);
});

 

마찬가지로 나만의 앨범에서 사용했던 코드를 그대로 활용하여 서버에서 movies 콜렉션의 각 키에 맞는 데이터를 가져와서 변수에 저장하고, 추가해야할 카드에 JQuery를 이용하여 각 변수의 값이 출력되도록 적용해주면 정상적으로 서버의 데이터가 태그들과 함께 출력되는 것을 확인할 수 있음

 

기존에 동적 코드를 적용하기 전에 그냥 html로 기록했던 영화를 모두 삭제하고, 새로 영화를 등록해보면 내가 서버에서 저장한 데이터만 출력되는 것을 확인할 수 있음

좌) 더이데이터 삭제 전 / 우) 더미데이터 삭제 후

배포

 

지금까지는 위의 이미지 처럼 vscode를 열었던 화면은 웹에서 동작하는 화면이 아니라, 실제 컴퓨터에 저장된 파일을 브라우저를 통해서 열어본 것임

즉, local 컴퓨터에 있는 파일을 그냥 열어본 것에 불과함

 

배포는 소프트웨어 개발 과정에서 개발한 애플리케이션, 웹사이트, 서비스 등을 실제 사용자들에게 보여주기 위한 과정을 말함

즉, 만든 작업물을 외부에 공개하고 링크(주소)에 접속한 사용자들에게 내가 만든 서비스를 사용할 수 있게 할 수 있음

 

URL: Uniform Resource Locator의 약자로 인터넷에서 특정 리소스의 위치를 나타내는 주소, 웹 페이지나 파일의 고유한 주소라고 생각하면 되며 프로토콜://도메인/경로 의 형식을 가지고 있음

예시: https://www.naver.com/

 

프로토콜: 웹 브라우저와 웹 서버 간의 통신 방식을 지정, 가장 일반적으로 사용되는 프로토콜은 http://, https:// 이며 https는 http에 보안 기능이 추가되어 중간에 요청, 응답의 내용을 알 수가 없음

 

도메인: 인터넷 상에서 고유한 식별자로 사용되는 웹 사이드 주소, 일반적으로 사이트의 이름과 최상위 도메인(Top-Level Domain, 예: .com, .org)으로 구성됨

 

경로(path): 웹 사이트 내에서 특정 페이지나 파일의 위치를 지정하며 경로는 스래시로 구분된 디렉토리 경로와 파일명으로 구성됨

 

Github Pages로 배포하기

깃허브로 접속해서 리포지토리를 하나 생성하고 파란 줄로 작게 쓰여져 있는 uploading an existing file을 누르면 아래처럼 파일을 업로드 할 수 있는 창으로 이동함

 

여기에 choose your files를 선택하여 스파르타플렉스 index.html 파일을 옮겨다 놓고 commit changes를 누르게 되면 일정 시간이 지나고 이렇게 파일이 등록 됨

파일은 html파일 하나만 올리려면 index.html 로 올려야함

 

이후 Settings -> Pages로 들어가서 Branch 부분서 None을 main으로 바꿔주고 저장하고 기다리면 주소를 받을 수 있음

 

전달 받은 주소로 접속하면 내가 올려 둔 스파르타플렉스가 띄워지는 것을 확인할 수 있으며, 실제 적용햇던 기능들도 정상적으로 동작하는 것을 확인할 수 있음

 

파일은 얼마든지 삭제하거나 다시 올릴 수 있으며, 해당 리포지토리에 올라간 파일은 해당 주소로 배포가 된다고 생각하면 됨

파이어 베이스의 한계점

파이어 베이스를 사용하여 웹 애플리케이션을 호스팅하면 편리함과 빠른 개발 속도를 얻을 순 있지만 남이 만들어놓은 백엔드 서버를 쓰기 때문에 제한사항이 있음

 

서버 제어 제한: 서버 인프라에 대한 직접적인 컨트롤이 불가능하기 때문에 추가적인 커스터 마이징을 할 수가 없고 파이어베이스에서 제공하는 기능과 방식에 따라 작업을 수행해야만 함

확장성 제약: 규모에 따른 병렬 확장성 측면에서 제한이 있을 수 있음

종속성: 구글의 서비스에 의존하기 때문에 파이어 베이스 외부의 다른 서비스나 기능을 활용하기 어렵거나 제한적일 수 있음

 

즉, 내입맛에 맞게 서비스를 구축하기 위해서는 결국 다른 서버를 사용해야 함

 

728x90