"Queue, Cron, Background Tasks까지? Supabase는 정말 어디까지 진화할까요?" 요즘 Supabase가 제공하는 새로운 기능들이 주목받고 있습니다. 이 글에서는 Dev.to의 Taishi가 소개한 Supabase의 새로운 기능들을 살펴보고, 실용적인 예제와 함께 그 가능성을 탐구해보겠습니다. Supabase란 무엇인가요? Supabase는 Firebase의 오픈소스 대안으로 시작된 프로젝트로, 데이터베이스, 인증, 실시간 업데이트, 서버리스 함수 등 다양한 기능을 제공합니다. 최근 Supabase는 Queue, Cron, Background Tasks 등 백엔드 기능을 강화하며 개발자들에게 더 많은 도구를 제공하고 있습니다. 이런 기능은 특히 서버리스(Serverless) 환경에서 애플리케이션을 개발하는 데 유용합니다. 이번 글에서는 최근 강화된 Queue, Cron, Background Tasks에 대해서 소개합니다. 새로운 기능 살펴보기 1. Queue Queue는 작업을 대기열에 추가하고 순차적으로 실행할 수 있는 기능입니다. 복잡한 작업을 관리하거나, 대량의 데이터를 처리할 때 유용합니다. 예제 코드: import { createQueue } from 'supabase-functions'; const queue = createQueue('email-sender'); queue.on('process', async (job) => { await sendEmail(job.data); }); Supabase의 Queue는 Deno 환경에서 실행되며, 작업의 실패와 재시도를 자동으로 관리합니다. (참고로 Supabase는 내부적으로 Deno를 사용하여 서버리스 함수 (Edge Functions)를 실행합니다. Supabase Edge Functions는 Deno 런타임 위에서 작동하며, 타입스크립트를 기본 언어로 사용합니다.) 2. Cron Cron은 정기 작업을 설정하는 기능입니다. 예를 들어, 매일 자정마다 데이터를 정리하거나, 매주 보고서를 생성할 때 사용할 수 있습니다. 예제 코드: import { schedule } from 'supabase-functions'; schedule('0 0 * * *', async () => { await cleanupDatabase(); }); 표준 CRON 표현식을 사용해 원하는 시간에 작업을 예약할 수 있습니다. 복잡한 서버 관리를 하지 않아도 되니 효율적입니다. 3. Background Tasks Background Tasks는 비동기 작업을 처리하는 데 사용됩니다. 사용자가 대기하지 않아도 되는 작업(예: 이미지 처리, 데이터 분석)을 배경에서 실행할 수 있습니다. 예제 코드: import { createTask } from 'supabase-functions'; const task = createTask('image-processor'); await task.dispatch({ imageId: '1234' }); 이 기능은 사용자의 경험을 방해하지 않으면서 중요한 작업을 처리할 수 있는 강력한 도구입니다. Supabase의 새로운 기능으로 개발 가능한 애플리케이션 이메일 마케팅 플랫폼: Queue를 사용해 이메일 발송 자동화하기. 정기 보고서 생성: Cron으로 데이터 분석 결과를 주기적으로 생성하기. 이미지 업로드 서비스: Background Tasks로 대량의 이미지 처리하기. 결론 Supabase는 점점 더 강력한 백엔드 기능을 제공하며, 개발자가 애플리케이션에 집중할 수 있도록 돕고 있습니다. 특히, 백엔드 구축에 많은 시간을 할애하기 어려운 소규모 팀이나 1인 개발자에게는 최적의 선택이 될 것 같습니다.
안녕하세요. 백엔드 쪽은 공부해본적이 없어서 파이어베이스를 이용해 어플리케이션을 만들어 보는 중입니다. Auth 부분까지 잘 작동하는 것을 확인한 뒤, 공식 Documentation을 따라 실시간데이터베이스를 연결하고 코드를 짜봤는데요, 오류는 전혀 발생하지 않지만 데이터베이스에 제가 의도했던 어떠한 작업도 진행되지 않았습니다. 실시간데이터베이스 뿐만 아니라 파이어스토어도 마찬가지였습니다. 제 코드가 잘못된건가 싶어 Documentation에 있는 코드를 그대로 넣어봤으나 이 또한 작동하지 않았고 커넥트 및 디펜던스도 여러번 확인했습니다. 도대체 무엇이 문제일까요...? 아래는 파이어스토어 documentation에 있는 코드를 그대로 가져와 작성했던 코드입니다. class MainActivity : AppCompatActivity() { //파이어베이스 파이어스토어 초기화 val db = Firebase.firestore val user = hashMapOf( "first" to "Ada", "last" to "Lovelace", "born" to 1815 ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) db.collection("users") .add(user) .addOnSuccessListener { documentReference -> Log.d(TAG, "DocumentSnapshot added with ID: ${documentReference.id}") } .addOnFailureListener { e -> Log.w(TAG, "Error adding document", e) } }
먼저 로그 콘솔에 에러가 출력된 것이 있는지 확인을 해보시기 바랍니다.
공식 문서대로 실행했는데 에러가 없다면 일일이 로그를 추가하여 확인해보셔야 할 것 같습니다.
class MainActivity : AppCompatActivity() {
val db = Firebase.firestore
val user = hash...
class LogInActivity : AppCompatActivity() { var userId = "" var pcType = "" var nickName = "" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_log_in) val db: DatabaseReference = Firebase.database.reference // 이미 로그인이 되어있는 경우 UserApiClient.instance.accessTokenInfo { tokenInfo, error -> if (error != null) { Log.e("Token", "토큰 정보 보기 실패") } else if (tokenInfo != null) { Log.d("Token", "토큰 정보 보기 성공") UserApiClient.instance.me { user, error -> if (error != null) { Log.e("TAG", "사용자 정보 요청 실패", error) } else if (user != null) { val id = user.id.toString() setId(id) db.child("users").child(id).child("type").get().addOnSuccessListener { val dbType = it.value.toString() Log.i("info t", dbType.toString()) setType(dbType) }.addOnFailureListener { Log.e("firebase", "Error getting data", it) } db.child("users").child(id).child("nickname").get().addOnSuccessListener { val nick = it.value.toString() Log.i("info nick", nick) nickName = nick }.addOnFailureListener { Log.e("firebase", "Error getting data", it) } /*************************/ private fun setId(id : String) { userId = id } private fun setType(t : String) { pcType = t } 데이터 저장에 필요 변수는 전역으로 설정해주었습니다. db.child("users").child(id.toString()).child("type").get().addOnSuccessListener { 이 부분의 중괄호 내에서 dbType 변수에 데이터가 잘 저장된 걸 확인했습니다. 또한 전역변수로 선언해놓은 pcType에도 저장이 되어있습니다. 하지만 위 코드의 중괄호를 나가게 되면 pcType 변수에 다시 null 값이 들어 가 있습니다. nickName 처럼 set 메소드를 안 쓰고 직접 저장을 해도 똑같이 중괄호를 나가면 다시 null 값으로 돌아갑니다. 이와 마찬가지로 UserApiClient.instance.me에서 저장되는 id값도 중괄호를 벗어나면 null 값으로 됩니다.. 며칠 전만 해도 문제 없이 잘 저장되었던 걸로 알고 있었는데 갑자기 변수에 값이 저장이 안되니 막막합니다.. 제가 코틀린을 잘못 이해하고 사용하고 있는 것인가요? 파이어베이스에서 가져온 데이터 값을 어떻게 해야 변수에 저장할 수 있는지 궁금합니다. 현재 가지고 있는 코틀린 책도 없어서 구글링으로만 코드 작성 중이라 모르는 게 많습니다 ㅠㅠ..
addOnSuccessListener는 비동기로 실행됩니다.
즉, 언제 실행이 완료될 지 알 수 없는 코드입니다.
만약 중괄호 밖의 코드를 실행되기 전에 다행히 비동기 코드가 실행되었다면 정상적으로 동작하겠지만,
중괄호 밖의 코드가 실행될 때 아직 비동기 코드가 실행되어있지 않으면 값을 가져오지 못해 오류가 발생할 수 있습니다.
다시 말해,...