Light Blue Pointer
본문 바로가기
Developing/Journal

[내일배움캠프][미니프로젝트]방명록 페이지 개발일지

by Greedy 2023. 10. 7.

해야할 일은 다음과 같다

 

1. 방명록 페이지 로딩시 db에서 불러오기

2. 내용 입력받아 db에 방명록 등록

3. 삭제 버튼 클릭시 해당하는 방명록 db에서 삭제

 

 

목표는 아래의 페이지를 구현하는 것!

일단 입력 창과 버튼들과 스크롤 바를 제일 먼저 만들었다

overflow: auto

하위 콘텐츠의 길이가 컨테이너의 길이를 초과했을 때 스크롤을 생성합니다.

(초과하지 않으면 생성하지 않음)

 

 

그리고 이거 추가해서  등록버튼 오른쪽으로 밂

style="float:right"

등록버튼이 오른쪽으로 간 것을 볼 수 있다

 

이렇게 떴는데 div를 span으로 바꾸니까 옆에 가서 얌전히 붙었다

<div class = "log">
                    <div class="input-group mb-3">
                        <span class="input-group-text">2023.10.05</span>
                        <span class="input-group-text">김이름</span>
                        <span><input type="text" placeholder="Password" aria-label="Password" class="form-control"></span>                        
                        <button class="btn btn-secondary" type="button" id="deleteBtn">삭제</button>
                        내용 내용 내용 내용내용 내용 내용 내용내용 내용 내용 내용내용 내용 내용 내용내용 내용 내용 내용
                      </div>

                </div>

문제1 : 그리고 실행하는데 다음 에러가 떴다

Uncaught ReferenceError: $ is not defined

 

제이쿼리 쓰려면 뭐 해야되는 거였나? 하고 찾아보니 역시 그랬다

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

해결 1 : 스크립트에 해당 부분을 추가해 주었더니 된다

 

 

문제 2 : 그리고 날짜를 받아오는데 용감하고 무식한 방법을 시도해 보았다

 let now = new Date();
            let date = now.getFullYear().append('.').append(now.getMonth()).append('.').append(now.getDate());

당연히 안 됨

해결 2 : 그래서 다음과 같이 바꾸었더니 되었다

const today = new Date();
let day = today.getDate();
let month = today.getMonth() + 1;
let year = today.getFullYear();

let date = `${year}-${month}-${day}`;

문제 3 : db연결도 안 해두고 db를 쓰려 해서

해결 3 : db를 연결했다

// Import the functions you need from the SDKs you need
        import { initializeApp } from "https://www.gstatic.com/firebasejs/10.4.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";
        // TODO: Add SDKs for Firebase products that you want to use
        // https://firebase.google.com/docs/web/setup#available-libraries

        // Your web app's Firebase configuration
        // For Firebase JS SDK v7.20.0 and later, measurementId is optional
        const firebaseConfig = {
           쉿 비밀이야!
        };

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

문제 4 :

Uncaught Error: Service firestore is not available
    at Provider.getImmediate (provider.ts:130:15)
    at Tg (index.esm2017.js:18368:12)
    at visitorlog.html:210:20

 

이런 에러가 떴다

 

해결 4 : 코드 부분부분 긁어다놓고 수정하다보니 버전이 안 맞아서 그러나 싶어서 버전 10.4.0으로 통일했다!

// Import the functions you need from the SDKs you need
        import { initializeApp } from "https://www.gstatic.com/firebasejs/10.4.0/firebase-app.js";
        import { getFirestore } from "https://www.gstatic.com/firebasejs/10.4.0/firebase-firestore.js";
        import { collection, addDoc } from "https://www.gstatic.com/firebasejs/10.4.0/firebase-firestore.js";
        import { getDocs } from "https://www.gstatic.com/firebasejs/10.4.0/firebase-firestore.js";

잘 되는 모습을 볼 수 있다

 

문제 5 : 이런 식으로 내용이 짧을 경우 삭제버튼 바로 옆에 가서 붙는 문제가 있었는데

 .logText{
            width : 100%;
            text-align: left;
        }

해결 5 : 텍스트 창을 class= logText인 div로 감싸고 style을 저렇게 지정하니까 해결되었다!

이제 삭제 기능만 하면 되겠다고 생각했다

대충 찾아보니 firebase update() remove()함수 쓰면 된다 해서 희망차게 시작했다

 

처음 찾아본 내용:

필드 삭제

문서에서 특정 필드를 삭제하려면 문서를 업데이트할 때 다음과 같은 언어별 FieldValue.delete() 메서드를 사용합니다.

deleteField() 메서드를 사용합니다.

하지만 field는 column인데요... 

 

구글링하다가 스택오버플로우에서 나랑 비슷한 거 하는 사람을 찾음

 

This line looks wrong to me (trying to get the nonexistent id property of the top level Assets node):

var assetKey = rootRef.child("id");

Try this instead:

var rowId = $row.data('id');
rootRef.child(rowId).remove()
...
let rootRef = firebase.database().ref().child("logs");
        $("#deleteLogBtn").click(async function () {

            row = $(this).closest('div'),
            
            rowId = row.val();
            var assetKey = rootRef.child("rowID");
            //it should remove the firebase object in here
            rootRef.child(assetKey).remove()
                //after firebase confirmation, remove table row
        });

let rootRef = db.database().ref().child("logs");

Uncaught TypeError: db.database is not a function

import 해야하려나?

문제6 : 아무리 여러방법을 시도해봐도 import가 먹히지 않음

나중에 알게 된건데 저런 함수들이 firebase database이기는 한데 firestore db가 아니라 realtime db에서 쓰는 경우가 좀 있어서 안 되었던 거 같다

해결6 : 그냥 realtime database를 쓴다

 

문제7나는 방명록 1개를 코드 내에서 동적으로 생성하고 있었는데 그러면 그 방명록들이 모두 같은 id값을 가지니까 어느 버튼이 호출했는지 몰라서 어느 버튼이 호출했는지 특정하는 것을 해야 했다.

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

            console.log(click);

            tempnow = $(this);
            console.log(tempnow);
            tempchild = now.parents();
            console.log(tempchild);

            $(this).remove();
            
            
        });

click 도 뜨지 않아서 아예 버튼이 안 불린다고 보면 될듯 했다

 

문제 8 : 동적으로 생성된 삭제 버튼을 부를 방법이 없음

 

html 동적 생성 요소 접근에 대해서 찾아보다가 다음 글을 발견함

jQuery - 동적 생성된 객체 클릭 이벤트 구현

동적으로 생성된 element에는 click 이벤트가 걸리지 않는다.는 사실을 알게 되었다.

$(".dj-tok .mem-list > li").click(function() {
	$(".mem-list > li").removeClass("active");
	$(this).addClass("active");
})

위처럼 하면 안 되고 아래처럼 해야한다고 함

$(document).on("click", ".dj-tok .mem-list > li", function() {
$(".mem-list > li").removeClass("active");
$(this).addClass("active");
})

이럴때는 .on() event를 걸어주면 된다고 함

Q. 근데 지금 저 코드에서 .dj-tok이랑 .mem-list가 이해가 안 간다 

$(document).on("click", "#deleteLogBtn", function () {

            console.log("click");

            let tempnow = $(this);
            console.log(tempnow);
            let tempchild = tempnow.parents();
            console.log(tempchild);

            $(this).remove();

        });

코드를 이렇게 수정했더니 버튼이 잘 먹혔다!

내가 클릭한 제일 위의 버튼이 사라진 모습을 볼 수 있음

 

동적으로 생성된 div 의 id 나 class, name 등을 이용해서 selector 을 통해 개체를 찾은 뒤 속성을 변경해야 한다고 하는데 

동적으로 생성될 때 겹치지 않는 id 을 어떻게 부여할지 고민하라고 함

근데 생각나는건 카운터 변수 하나 두고 하나씩 올려가면서 id값 생성하는 거였음

그러나 나는 호출하는 함수에서 주체적으로 버튼을 불러오는게 아니기에 그런 방식으로는 할 수 없다는 것을 깨닫고 다른 방법을 찾으러 갔다

 

$(document).on("click", "#deleteLogBtn", function () {

            
            alert("선택한 버튼을 삭제하겠습니다. : ");
            

        });

이렇게 하니까 클릭이 정상적으로 동작해서 알람창이 잘 떴다

해결 8 : $("#deleteLogBtn").click(async function () { 을 $(document).on("click", "#deleteLogBtn", function () { 으로 바꿨더니 동적으로 생성된 버튼 호출 가능해짐

 

클릭한 버튼이 달린 element의 하위 텍스트에 어떻게 접근해야할 지 찾아보니까 

parents()함수가 있었다

$(document).on("click", "#deleteLogBtn", function () {

            console.log("click");

            let tempnow = $(this);
            console.log(tempnow);
            let tempchild = tempnow.parents();
            console.log(tempchild);

            $(this).remove();

        });

그런데 이렇게 하니까 모든게 다 사라짐

모든 부모 element가 사라져버림

 

더 찾아보니 parents() 말고도 closest() 함수가 있었다

가장 가까운 상위 element만 적용하는 거라 함

$(document).on("click", "#deleteLogBtn", function () {

            console.log("click");

            let parent = $(this).closest('div');
            let child = parent.children('div')
            child.remove();

        });

해결 7 : 위와 같은 방법으로 동적으로 생성된 element중에서 어느 것이 함수를 호출하고 있는지 특정함

 

 

문제 9 : child.val() 이렇게 읽어오려 했더니 빈칸이 뜸

 

$(document).on("click", "#deleteLogBtn", function () {

            console.log("click");

            let parent = $(this).closest('div');
            
            let child = parent.children('div');
            console.log(child.val());
            parent.remove();

        });

해결 9 : 요소에 attribute 를 추가할 수 있다는 것을 알아내고 요소에서 attribute 받아오는 것이 가능해짐

$(document).on("click", "#deleteLogBtn", function () {

            console.log("click");

            let parent = $(this).closest('div');
            
            let child = parent.children('div');
            let val = child.attr( 'content' );
            console.log(val);
            parent.remove();

        });

 

구글링 하다보니 firestore db로는 삭제하는 법 자료가 나오긴 하는데 너무 없어서 이렇게는 좀 불가능하겠다 싶었음

그래서 realtime db 쓰기로 하고 realtime db 연동함

 

 

리얼타임 db연동하기

https://firebase.google.com/docs/database/web/start?hl=ko

import { initializeApp } from "firebase/app";
import { getDatabase } from "firebase/database";

// TODO: Replace the following with your app's Firebase project configuration
// See: <https://firebase.google.com/docs/web/learn-more#config-object>
const firebaseConfig = {
  // ...
  // The value of `databaseURL` depends on the location of the database
  databaseURL: "https://DATABASE_NAME.firebaseio.com",
};

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

// Initialize Realtime Database and get a reference to the service
const database = getDatabase(app);

처음에는 이렇게 시도했는데 뭐가 문제인지 import가 전혀 안 됐다

다른 사람들은 다 저렇게 잘 쓰던데 난 왜 안 됐을까

 

Uncaught TypeError: Failed to resolve module specifier "firebase/app".

Relative references must start with either "/", "./", or "../".

 

import { initializeApp } from "<https://www.gstatic.com/firebasejs/10.4.0/firebase-app.js>";
        import { getFirestore } from "<https://www.gstatic.com/firebasejs/10.4.0/firebase-firestore.js>"
        import { collection, getDocs, addDoc, Timestamp } from "<https://www.gstatic.com/firebasejs/10.4.0/firebase-firestore.js>"
        import { query, orderBy, limit, where, onSnapshot } from "<https://www.gstatic.com/firebasejs/10.4.0/firebase-firestore.js>"

onSnapshot이랑 쓸만한 함수 많아보였는데 아쉽게 됐다

import { getDatabase, ref, onValue } from "firebase/database";

const db = getDatabase();
const dbRef = ref(db, '/a/b/c');

onValue(dbRef, (snapshot) => {
  snapshot.forEach((childSnapshot) => {
    const childKey = childSnapshot.key;
    const childData = childSnapshot.val();
    // ...
  });
}, {
  onlyOnce: true
});

 

Uncaught TypeError: Failed to resolve module specifier "firebase/database". Relative references must start with either "/", "./", or "../".

계속 하는데 안 됐다

 

const firebaseConfig = {
            apiKey: "",
            authDomain: "",
            projectId: "",
            storageBucket: "",
            messagingSenderId: "",
            appId: "",
            measurementId: ""
            
        };

글 읽으면서 비교하다 보니 여기에 database url이 없어!!

const firebaseConfig = {
  apiKey: "",
  authDomain: "",
  databaseURL: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
  measurementId: ""
};

그래서 새것 퍼옴

그랬더니 import 성공함!!!!

Uncaught TypeError: Failed to resolve module specifier "firebase/database". Relative references must start with either "/", "./", or "../".

import 성공한 것은 나의 착각이었다

validation.ts:48 Uncaught Error: database.ref failed: Was called with 2 arguments. Expects no more than 1. at W (validation.ts:48:11) at Su.ref (Database.ts:97:5) at visitorlog.html:278:32

이렇게 뜨고 안된다...

어 근데 그냥 ref로 불렀을때는 그거 없다고 뜨더니 이제 database.ref로 부르니까 그건 안 뜨네?

그냥 안쪽을 “logs”만 남기면 될듯하다

visitorlog.html:279 Uncaught TypeError: database.onValue is not a function at visitorlog.html:279:18

database.onValue → onValue로 수정

visitorlog.html:279 Uncaught ReferenceError: onValue is not defined

 

    <script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-database.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-analytics.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-auth.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.8.1/firebase-firestore.js"></script>

Q. 무슨 차이인지 모르겠지만 import 문 포기하고 저런식으로 하니까 됨

//방명록 불러오는 부분 
const dbRef = database.ref('logs'); 
dbRef.on("value", (snapshot) => { 
snapshot.forEach((childSnapshot) => { 
//const childKey = childSnapshot.key; 
const object = childSnapshot.val(); 
let temp = ` <div class="log"> 
<div class="input-group mb-3"> 
<span class="input-group-text">${object.date}</span> 
<span class="input-group-text">${object.name}</span> 
<span><input type="text" id="deleteLogPw" placeholder="Password" aria-label="Password" class="form-control"></span> <button class="btn btn-secondary" type="button" id="deleteLogBtn">삭제</button>
<div class="logText" content = ${object.content}> ${object.content} </div> 
</div> 
</div> ` 

$('#logBox').append(temp)
});
});

문제 10 : 다 들어가긴 들어가는데 다 undefined로 들어감

해결 10 : db에 autogenereated id 세팅한거때문에 undefined로 뜨고 child 의 child로 해줘야 되는 거 같다고 생각함

db에 이런식으로 저장되어 있었다

그래서 childSnapshot으로 바꾸니까 잘 동작함

//방명록 불러오는 부분
        const dbRef = database.ref('logs');
        dbRef.on("value", (snapshot) => {
            snapshot.forEach((childSnapshot) => {
                //const childKey = childSnapshot.key;
                const object = childSnapshot.val();
                let temp = `
    <div class="log">
        <div class="input-group mb-3">
            <span class="input-group-text">${object.date}</span>
            <span class="input-group-text">${object.name}</span>
            <span><input type="text" id="deleteLogPw" placeholder="Password" aria-label="Password" class="form-control"></span>
            <button class="btn btn-secondary" type="button" id="deleteLogBtn">삭제</button>
            <div class="logText" content = ${object.content}>
                ${object.content}
            </div>
        </div>
    </div>
    `

                $('#logBox').append(temp)

            });
        });
        //방명록 등록 끝남

그리고 이제 다시 삭제 파트를 하는데

util.ts:556 Uncaught TypeError: object.remove is not a function

Uncaught TypeError: childSnapshot.remove is not a function

이런식으로 뜨고 .remove() 기능을 이용할수가 없었다

 

그 object 가 value만 읽어온 거잖아??

문제 11 : .remove() 기능을 이용하려면 노드에 주소로 접근해야 하는데 어떻게 해야 하는지 모르겠음

snapshot말고 접근할 방법을 알면 될거같은데

childNode에

//방명록 삭제하는 부분
        $(document).on("click", "#deleteLogBtn", function () {

            console.log("click");

            let parent = $(this).closest('div');
            let child = parent.children('div');
            let val = child.attr('content');
            console.log(val);

            const key = val;

            const remove = (key) =>{
                return database.child(key).remove();
            }
            
        //     const dbRef = database.ref('logs');
        //     dbRef.on("value", (snapshot) => {
        //     snapshot.forEach((child) => {
        //         //const childKey = childSnapshot.key;
        //         const object = child.val();

        //         if(object.content == val){
        //             child.ref().remove();
        //         }

        //     });
        // });
            
            

            parent.remove();

        });
        //방명록 삭제 끝남

저 id값을 알아내면 될 거 같다고 생각했다

TypeError: object.remove is not a function

그리고 .remove()을 써보려는 수많은 시도가 좌절됨

 

ref로 자식노드를 가리키려고 노력해봤는데 잘 안 됐다

if (object.content == val) {
                        console.log(object.content);
                        console.log(snapshot);
                        console.log(child.ref);
                        console.log(child.ref.key);
                        //dbRef.child(key).remove();
                    }

해결 11: 그러다가 자식의 key값 = autogenerated id값을 얻을 수 있는 방법을 발견함

visitorlog.html:312 ㅇㅇ

visitorlog.html:322 ㅇㅇ

visitorlog.html:323

mu {_database: Su, _delegate: ns}

visitorlog.html:324 Eu {database: Su, _delegate: es}

visitorlog.html:325 -Ng1WcXbdNAYa9SpOTnL

키값을 얻어버림!!!!!!!!!!!

-Ng1WcXbdNAYa9SpOTnL 이게 autogenerated id값이다

너무 신났다

db에서 삭제할 수 있었다

 

문제 12: 삭제된 데이터만 빼고 남은 데이터가 아래에 이어서 써지는 문제 존재

해결 12:  삭제한 다음 코드에 window.location.reload(); 추가하여 db에 있는 것들만 새로 불러올 수 있도록 한다

 

문제 13 : 아까는 삭제가 되었는데 갑자기 삭제가 안 되었음 

알고보니 div의 attribute의 name과 db의 name으로 대조해서 삭제중이었는데

attribute의 name에 띄어쓰기가 들어가면 띄어쓰기 전까지만 받아졌음

let childDiv = parentDiv.children('div');
            let val = childDiv.attr('name');

 

Q. 왜 띄어쓰기가 들어가면 안 나올까?

 

해결 13 : name 대신 띄어쓰기 없는 id를 사용함

 테스트용이라 이름으로 삭제하던 거여서 그냥 id값을 넣어놓고 그걸로 삭제를 했다

 

문제 14 : text input으로 비밀번호 받아와야 하는데 children.()함수로 안 찾아진다

해결 14 : 다시 관련 글 잘 읽어보니 바로 아래 요소, 즉 자식 요소만 탐색할때는 children()을 사용, 자식 및 하위 태그 모두에서 찾을 때는 find()를 사용해야 한다고 함 password입력하는 것이 하위 태그 안에 들어있어서 find()로 바꿨더니 잘 됐다

//방명록 삭제하는 부분
        $(document).on("click", "#deleteLogBtn", function () {

            //alert("click");

            let parentDiv = $(this).closest('div');
            let textDiv = parentDiv.children('.logText');
            let pwInput = parentDiv.find('input');


            let id = textDiv.attr('id');
            let password = pwInput.val();

            const dbRef = database.ref('logs');

            dbRef.on("value", (snapshot) => {
                snapshot.forEach((child) => {
                    const object = child.val();

                    if((id == child.ref.key )&&(object.pw == password)) {
                        console.log("the same password");
                        dbRef.child(id).remove();
                    }
                });
            });
            window.location.reload();
        });
        //방명록 삭제 끝남

문제 15 : db한바퀴를 돌며 키값 같은 자식 찾지 않고 바로 그 노드로 접근하고 싶다

 

//방명록 삭제하는 부분
$(document).on("click", "#deleteLogBtn", function () {

    let parentDiv = $(this).closest('div');
    let textDiv = parentDiv.children('.logText');
    let pwInput = parentDiv.find('input');


    let id = textDiv.attr('id');
    let password = pwInput.val();

    const dbRef = database.ref('logs');

    dbRef.on("value", (snapshot) => {
         snapshot.forEach((child) => {
             const object = child.val();

            if (id == child.ref.key) {
                if (object.pw == password) {
                    dbRef.child(id).remove();
                 }
                else {
                     alert("잘못된 비밀번호");

                 }
             }
         });
     });
    window.location.reload();
});
//방명록 삭제 끝남

다음 부분을

// dbRef.on("value", (snapshot) => {
    //     snapshot.forEach((child) => {
    //         const object = child.val();

    //         if (id == child.ref.key) {
    //             if (object.pw == password) {
    //                 dbRef.child(id).remove();
    //             }
    //             else {
    //                 alert("잘못된 비밀번호");

    //             }
    //         }
    //     });
    // });

다음과 같이 바꾸어서 해결했다

해결은 무슨 이렇게 하니까 안 되어서 코드 원상복귀함

const dbRef = database.ref('logs');
   
    if (object.pw == password) {
        dbRef.child(id).remove();
    }else{
        alert("잘못된 비밀번호");
    }

Q.잘 쓴 거 같은데 왜 안 될까?

 

문제 16 : 랜덤 프로필 사진 지정하고 싶음

해결 16 : 랜덤 함수와 배열을 이용하면 됨

let profiles = ['apeach','muzi','neo','prodo','ryan'];
    var random_index = Math.floor(Math.random() * profiles.length);
    var pfp = profiles[random_index];
//방명록 불러오는 부분//3개 불러오는걸로 수정해야함!!
    const dbRef = database.ref('logs').orderByChild('ups').limitToLast(3);
    dbRef.on("value", (snapshot) => {
        snapshot.forEach((child) => {

            const object = child.val();
            let temp = `
            <p><span><img class="pfp" , src="./image/minsun/pfp/${object.pfp}.png" , alt="pfp"></span>${object.content} (${object.name})</p>
            `

            $('#visit-comment').append(temp);

        });
    });
    //방명록 불러오는 부분 끝남
//방명록 불러오는 부분
const dbRef = database.ref('logs');
dbRef.on("value", (snapshot) => {
    snapshot.forEach((child) => {

        const object = child.val();
        let temp = `
    <div class="log">
        <div class="input-group mb-3">
            <span class="input-group-text">${object.date}</span>
            <span class="input-group-text">${object.name}</span>
            <span><input type="text" id="deleteLogPw" placeholder="Password" aria-label="Password" class="form-control"></span>
            <button class="btn btn-secondary" type="button" id="deleteLogBtn">삭제</button>
            <div class="logText" id = ${child.ref.key}>
            <span><img class="pfp" , src="./image/minsun/pfp/${object.pfp}.png" , alt="pfp"></span>
                ${object.content}
            </div>
        </div>
    </div>
    `
        $('#logBox').append(temp)

    });
});
//방명록 불러오는 부분 끝남

 

문제 17 : 오래 놔두면 페이지 초기화를 하면서 db에서 다시 읽어와서 밑으로 데이터가 중복되게 쌓임

Q. 새로고침하면 해결되긴 하는데 딱 페이지 처음 로딩시에만 동작하는 함수를 만들고 싶다?

 

 

문제 18 : 최신순으로 위부터 보고싶은데 forEach를 역순으로 수행하는 방법이 없을까?

https://firebase.google.com/docs/database/web/lists-of-data?hl=ko 

 

웹에서 데이터 목록 다루기  |  Firebase Realtime Database

Google I/O 2023에서 Firebase의 주요 소식을 확인하세요. 자세히 알아보기 의견 보내기 웹에서 데이터 목록 다루기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

firebase.google.com

 

orderByChild() 지정된 하위 키 또는 중첩된 하위 경로의 값에 따라 결과를 정렬합니다.
orderByKey() 하위 키에 따라 결과를 정렬합니다.
orderByValue() 하위 값에 따라 결과를 정렬합니다.

 

import { getDatabase, ref, query, orderByChild } from "firebase/database";
import { getAuth } from "firebase/auth";

const db = getDatabase();
const auth = getAuth();

const myUserId = auth.currentUser.uid;
const topUserPostsRef = query(ref(db, 'user-posts/' + myUserId), orderByChild('starCount'));

이런식으로 사용한다 함

나는 'ups'가 이미 있는 건줄 알고 구글링해봐도 안 나오는 걸 보니 내가 코드를 퍼온 사람이 'ups' field를 가지고 있는 거 같음

근데 없는걸로 정렬해도 왜 똑바로 되는지는 모르겠다고 한다

 

문제 19 : js파일로 분리했을 때 onclick() 이 작동하지 않았다.

해결 19: $(document).on("click"으로 바꿔주었더니 동작한다.

Q.왜 그럴까?