본문 바로가기
Web

[Firebase]Firebase CRUD 요청 백엔드 API

by 다봄이 2020. 8. 6.

원본: 내 네이버 블로그, 2020-05-29 포스팅

오늘은 본격적으로 백엔드 기능을 구현하기에 앞서, 웹페이지에서 가장 기본적으로 CRUD API를 firebase로 구현해 볼 것이다. 전에 포스팅 관련 페이지에 들어가는 CRUD API를 firebase로 몇 번 짜 본 적이 있어서 포스팅 페이지를 기준으로 한다.

사용될 firebase 메서드는 크게 .set(), .get(), .update(), .remove() 이다.

Create : 포스팅 등록(set)

/**
 * @function
 * 관리자가 공지글 등록
 * */

const firebase = require('firebase/app');
require('firebase/database');
require('firebase/auth');
const auth = require('../auth');

module.exports = async(title, body, imageUrl, url) => {
    try{
        if (!(await auth.isLogin())) {
            throw new Error('PERMISSION_DENIED');
        }

        let noticeRef = firebase.database().ref('notice').push();
        let addedTime = new Date().getTime();

        await noticeRef.set({
            title: title,
            body: body,
            imageUrl: imageUrl,
            url: url,
            addedTime: addedTime
        });

        return;
    }
    catch(e){
        throw e;
    }
}

기본적으로 firebase에서 database에 최초 등록할 때는 .set()을 사용한다.

database.ref('example')을 사용하여 데이터를 등록할 root node를 설정할 수 있다.

.push()를 사용할 경우에는 firebase 난수로 key가 생성되고, 해당 key의 하위 노드로 데이터가 set된다.

참고로 isLogin()은 로그인 상태 확인을 위해 firebase onAuthStateChange 메서드를 사용해서 짠 함수이다.

즉, 위의 경우에는
noticeRef : 데이터를 db의 'notice'루트에 저장할 거야. 이 때 키는 난수야.
noticeRef.set() : notice 루트에 이 데이터들을 저장할거야.
title(저장되는 데이터 이름) : title(parameter로 전달받는 저장될 데이터 내용)
의 구성이다.


그러면 이처럼 지정한 루트(여기서는 post이다.)에 난수가 key로 생성되고, 이 key의 하위 노드들인 contents, createdTime, rcreatedTime, uid가 실제 저장한 data이다.

Read : 포스팅 글 조회(get)

/**
 * @function
 * 공지글 리스트 가져오기
 */

const firebase = require('firebase/app');
require('firebase/database');
const auth = require('../auth');

module.exports = async (key) => {
    try {
        if (!(await auth.isLogin())) {
            throw new Error('PERMISSION_DENIED');
        }
        if (!key) {
            return await allNotices();            
        }

        return await thatNotice(key);       
    }
    catch (e) {
        throw e;
    }
}

let thatNotice = async function(key){
    let ref = (await firebase.database().ref('notice/').orderByChild('key').equalTo(key).once('value')).val();
    if (!ref) {
        throw new Error('database/no-matched');
    }

    return ref;
}

let allNotices = async function() {
    let ref = (await firebase.database().ref('notice').once('value')).val();

    return ref;
}

조회는 firebase의 .get()을 사용한다고 하는데, 사실상 써본적이 거의 없는 것 같다.

대신 지금처럼 orderByChild와 equalTo를 사용하여 특정 데이터 로드하는 방법을 훨씬 많이 썼다.

해당 코드는 관리자용 백엔드 코드이기 때문에, 전체 글을 로드하는 함수와 해당 글을 로드하는 함수를 따로 만들었다. 이 외에도 최근 5개 포스팅만 로드는 orderByChild().equalTo().limitToLost(5)와 같은 방법으로 가능하다.

Update : 포스팅 수정(update)

/**
 * @function
 * 관리자가 공지글 업데이트. 업데이트 하는 부분은 제목/타입/내용/url
 * @param
 * key : 공지글 삭제 시 해당 공지글의 db key를 이용하여 업데이트
 * filed : 업데이트 할 부분
 * contents : 업데이트 할 내용.
 */
const firebase = require('firebase/app');
require('firebase/database');
const auth = require('../auth');

module.exports = async (key, filed, contents) => {
    try {
        if (!(await auth.isLogin())) {
            throw new Error('PERMISSION_DENIED');
        }

        //key를 가지고 db쿼리
        let ref = firebase.database().ref('notice/' + key);

        //db에 key에 해당하는 내용이 있을 때
        if ((await ref.once('value')).val()) {

            switch (filed) {
                case 'title':
                    await ref.update({ title: contents });
                    return
                case 'body':
                    await ref.update({ body: contents });
                    return
                case 'imageUrl':
                    await ref.update({ imageUrl: contents });
                    return
                case 'url':
                    await ref.update({ url: contents });
                    return

                default:
                    throw new Error('common/invalid-params');
            }
        }
        else { //db에 해당 key가 없을 경우
            throw new Error('database/no-matched');
        }
    }
    catch (e) {
        throw e;
    }
}

update는 주의를 좀 기울여야 한다.

firebase의 update 메서드를 사용할 때 key를 잘못 잡으면 데이터가 업데이트 되는 것이 아니라 해당 자리에 새로운 key가 생기고 그 key의 하위값으로 업데이트한 내용이 들어가기 때문.

Delete : 포스팅 삭제(remove)

/**
 * @function
 * 관리자가 공지글 삭제 시 db에는 expired가 true로 업데이트 됨.
 * @param
 * key : 공지글 삭제 시 해당 공지글의 db key를 이용하여 삭제.
 */

const firebase = require('firebase/app');
require('firebase/database');
const auth = require('../auth');

module.exports = async (key) => {
    try {
        if (!(await auth.isLogin())) {
            throw new Error('PERMISSION_DENIED');
        }
        let ref = firebase.database().ref('notice/' + key);
        //db에 해당 key가 있을 경우
        if ((await ref.once('value')).val()) {         
            await ref.remove();
        }
        else { //db에 해당 key가 없을 경우
            throw new Error('database/no-matched');
        }
    }
    catch (e) {
        throw e;
    }
}

remove() 메서드를 사용하며 key를 받아와서 해당 key와 일치하는 key의 데이터를 통째로 지운다.

이제 해당 모듈들을 적절한 이름으로 exports시켜서 index.js에서 프론트에서 사용될 API 로직을 짠 다음 프론트엔드 구성만 하면 된다.

끄읏~

댓글