5분만에 블로그 리액션 버튼 만들기
Firebase Functions로 5분만에 웹 API 만들기

리액션 버튼을 만들었습니다! 이렇게 생겼는데요. 실제로 동작하는 버튼은 페이지 하단에서 확인하실 수 있습니다.

제가 원한 리액션 버튼의 조건은 이렇습니다.

  • 익명이어야 할 것
  • 버튼 모양(이모지)와 버튼 갯수 커스텀이 가능할 것
  • 여러번 누를 수 있을 것
  • 유지에 드는 값이 쌀 것
  • 개발에 드는 값이 쌀 것

이미 만들어진 서비스가 있는지 찾아봤는데 플러그인 형태로 리액션 버튼을 서비스하는 건 없더라고요. 별 수 없죠 만드는 수 밖에.

Firebase Functions

Firebase Functions는 JS로 함수를 만들면 바로 웹API로 배포할 수 있는 서비스입니다. 아주 간단해요. 함수를 만들고, 배포를 하면, 짠! API가 생깁니다.

유지비용도 나쁘지 않아요 제 블로그처럼 아주 작은 트래픽이 발생한다면 거의 무료로 쓸 수 있어요. 그러다 사용량이 많아지면 결제를 하면 되고요. 결제를 하는 순간부터는 AWS에 인스턴스 하나 띄우는 게 싸게 먹힐 수도 있지만, 자원을 관리하지 않아도 되는 건 큰 장점이에요.

Lambda VS Functions

AWS Lambda와 비슷한 서비스지만, Lambda는 웹 API를 만드려면 함수를 만들고, Gateway 구성하고, 배포하고, 트리거 걸고… 생각보다 빠르게 배포하긴 힘들어요. Functions는 함수를 배포하면 바로 사용할 수 있는 엔드포인트까지 만들어 준답니다.

5분만에 만든 리액션 API

초기화

먼저 functions와 firebase-admin을 불러오고 초기화 해줍니다.

const functions = require("firebase-functions")

const admin = require("firebase-admin")
admin.initializeApp({
  // 파이어베이스 웹앱 인증 코드를 여기에 넣으세요
})

리액션 저장 API

복잡한 코드는 없습니다. 필요한 파라미터가 모두 들어왔는지 확인하고 파이어베이스에 값을 저장합니다.

exports.addReactions = functions.https.onRequest(async (req, res) => {
  // 모든 host의 요청을 받습니다.
  res.set("Access-Control-Allow-Origin", "*")

  const host = req.query.host || null
  const slug = req.query.slug || null
  const reaction = req.query.reaction || null
  const count = req.query.count || 1

  // 필요한 파라미터가 모두 들어왔는지 검사합니다.
  if (!host || !slug || !reaction) {
    res.send({ error: "missing required params" })
  }

  // 제가 정한 리액션 타입만 처리합니다.
  if (!["like", "heart", "fun", "merong", "sad", "angry"].includes(reaction)) {
    res.send({ error: "reaction type error" })
  }

  try {
    const ref = await admin.database().ref(`/${host}/${slug}/${reaction}`)

    ref.once("value").then(snapshot => {
      const isExist = snapshot.exists() // 이미 문서가 있는지 확인합니다
      if (isExist) {
        // 문서 있으면 업데이트
        const reactionVal = snapshot.val()
        ref.update({
          count: Number(reactionVal.count) + Number(count),
          realCount: Number(reactionVal.realCount || 0) + 1,
        })
      } else {
        // 문서 없으면 초기화
        ref.set({
          count: count,
          realCount: 1,
        })
      }
    })
    res.send({ result: "success" })
  } catch (e) {
    res.send(e)
  }
})

리액션 값 읽는 API

exports.getReactions = functions.https.onRequest(async (req, res) => {
  // 모든 host의 요청을 받습니다.
  res.set("Access-Control-Allow-Origin", "*")

  const host = req.query.host || null
  const slug = req.query.slug || null

  // 필수 값 없으면 종료
  if (!host || !slug) {
    res.send({ error: "missing required params" })
  }

  // 값을 읽어서 보냅니다
  const ref = await admin.database().ref(`/${host}/${slug}`)
  ref.once("value").then(snapshot => {
    const isExist = snapshot.exists()
    if (!isExist) {
      res.send({ error: "no data" })
    }
    res.send(snapshot.val())
  })
})

끝입니다! 이렇게 간단한 코드를 쉽게 배포할 수 있는게 Firebase 장점인 것 같아요. 예외처리는 일부러 안 했습니다! 어뷰징 생기면 그냥 없애버리면 되니까요.

이제 복잡한 UI 코드를 작성하는 데 2시간을 보내고 나면 아래 리액션 버튼이 동작하게 됩니다.

0
👍
0
❤️
0
😄
0
😝