리액션 버튼을 만들었습니다! 이렇게 생겼는데요. 실제로 동작하는 버튼은 페이지 하단에서 확인하실 수 있습니다.
제가 원한 리액션 버튼의 조건은 이렇습니다.
- 익명이어야 할 것
- 버튼 모양(이모지)와 버튼 갯수 커스텀이 가능할 것
- 여러번 누를 수 있을 것
- 유지에 드는 값이 쌀 것
- 개발에 드는 값이 쌀 것
이미 만들어진 서비스가 있는지 찾아봤는데 플러그인 형태로 리액션 버튼을 서비스하는 건 없더라고요. 별 수 없죠 만드는 수 밖에.
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시간을 보내고 나면 아래 리액션 버튼이 동작하게 됩니다.