FluentStack

Service Layer

Mode tersedia: dark, light, paper
MasukDaftar
Advanced · Level 11: Production Next.jsAdvanced70 menitBahasa Indonesia

Service Layer

Menempatkan Supabase query dan auth-aware data access dalam fungsi server yang bernama jelas, bukan di component UI acak.

StatusMemuat progres
ProgresMemuat...

...

Memuat progres

Menyiapkan langkah berikutnya

Tujuan belajar

  • Menjelaskan alasan data access dipusatkan dalam service function
  • Membuat fungsi server yang membaca identity sebelum query user-owned data
  • Membedakan state UI dari operasi data
  • Menangani error data tanpa mengembalikan detail database ke user
Next.jsSupabaseService LayerServer ComponentsCode Organization

Isi lesson

6 blok
  1. 1.
    Component menjelaskan UI, service menjelaskan data accessBelum selesaiWajib
  2. 2.
    Service untuk profile user saat iniBelum selesaiWajib
  3. 3.
    Coding practiceBelum selesaiWajib
  4. 4.
    Cek pemahamanBelum selesaiWajib
  5. 5.
    Jangan menerima userId dari form lalu langsung mempercayainyaBelum selesaiWajib
  6. 6.
    RingkasanBelum selesaiWajib

Component menjelaskan UI, service menjelaskan data access

Wajib

Saat query Supabase langsung ditulis di banyak page, component mulai mencampur markup, session check, nama tabel, error handling, dan mapping data. Perubahan policy atau bentuk data lalu sulit ditelusuri. Service layer menyimpan operasi tersebut dalam fungsi kecil dengan nama yang menjelaskan tujuan, misalnya getCurrentProfile atau saveLearningNote.

Service layer bukan abstraction besar yang harus dibuat untuk setiap baris query. Mulailah saat query mempunyai identity check, aturan user-owned, mapping, atau error handling yang akan membuat component sulit dibaca. Page tetap bertanggung jawab memilih loading/error UI; service bertanggung jawab menjalankan operasi data dengan boundary server yang jelas.

Bagian ini memengaruhi progres lesson.

Service untuk profile user saat ini

Wajib
tsx
// lib/services/profile-service.ts
import "server-only";

import { createClient } from "@/lib/supabase/server";

export async function getCurrentProfile() {
  const supabase = await createClient();
  const { data: claimsData, error: claimsError } =
    await supabase.auth.getClaims();
  const userId = claimsData?.claims.sub;

  if (claimsError || !userId) {
    return null;
  }

  const { data, error } = await supabase
    .from("profiles")
    .select("id, display_name, bio")
    .eq("id", userId)
    .maybeSingle();

  if (error) {
    throw new Error("Profile belum bisa dimuat.");
  }

  return data;
}

server-only menyatakan bahwa service ini tidak boleh diimport ke browser bundle. Fungsi memverifikasi identity terlebih dahulu, lalu hanya meminta profile dengan id user saat ini. RLS tetap menjadi proteksi database jika query berubah atau dipanggil dari tempat lain. Error internal tidak diteruskan mentah ke UI; page dapat menangkap error dan menampilkan fallback yang sesuai.

Bagian ini memengaruhi progres lesson.

Coding practice

WajibDibuka di workspace khusus

Extract profile service layer

Lengkapi getCurrentProfile sebagai service server yang memverifikasi claims lalu membaca profile user saat ini.

Tujuan awal: Fokus di tab TSX.

Practice ini dibuka di workspace khusus. Buka practice untuk memakai editor, preview, dan cek otomatis.

Tombol selesai aktif setelah semua validasi wajib lolos.

7 cek otomatis5 checklist
Belum selesaiBuka practice

Cek pemahaman

WajibJawab dulu

Cek pemahaman singkat

Apa alasan terbaik memindahkan query profile yang berulang ke getCurrentProfile?

Progres lesson naik setelah jawaban benar.

Catatan penting

Wajib

Jangan menerima userId dari form lalu langsung mempercayainya

Untuk operasi user-owned, ambil identity dari auth context yang diverifikasi pada server. Nilai userId dari form, URL, atau Client Component dapat dimanipulasi. Kamu masih dapat menggunakan userId dari claims untuk query atau insert, lalu RLS tetap memastikan row yang diakses memang sesuai policy.

Bagian ini memengaruhi progres lesson.

Ringkasan

Wajib
  • Service layer memisahkan data access dari presentasi UI.
  • Gunakan fungsi bernama jelas untuk identity check, query, mapping, dan error handling yang berulang.
  • server-only membantu mencegah service server diimport ke Client Component.
  • Identity user-owned berasal dari auth context server, bukan field yang dikirim browser.
  • Berikutnya, kamu akan memakai service untuk alur create/read/update data yang kecil.

Bagian ini memengaruhi progres lesson.

Langkah berikutnya

Selesaikan bagian penting lesson ini

Lanjutkan blok wajib berikutnya: Component menjelaskan UI, service menjelaskan data access.