DEBI PRAHARADIKA
← Back to Blog Index
Software Architecture2026-05-2315 min read

Membangun Aplikasi Web Pencatatan Ide dengan Pendekatan C4 Model

Panduan dokumentasi arsitektur perangkat lunak end-to-end menggunakan C4 Model untuk membangun aplikasi web pencatatan ide berbasis React, TypeScript, dan TailwindCSS.

Membangun aplikasi web sederhana seperti pencatat ide (seperti Google Keep) tampak mudah di awal. Namun, saat tim developer bertambah dan aplikasi mulai terintegrasi dengan berbagai layanan eksternal (seperti modul autentikasi pihak ketiga, sistem sinkronisasi offline, dan database), dokumentasi teknis yang tidak terstruktur akan menjadi kendala besar.

Pendekatan dokumentasi tradisional seperti diagram UML (Unified Modeling Language) sering kali terlalu rumit untuk dipahami secara cepat oleh pengembang baru.

Di sinilah C4 Model yang dipopulerkan oleh Simon Brown menjadi sangat berguna. C4 Model membagi visualisasi arsitektur perangkat lunak menjadi empat tingkatan abstraksi yang berbeda: Context, Container, Component, dan Code (seperti Google Maps yang bisa diperbesar dari skala benua hingga jalan raya).

Artikel ini akan mengupas tuntas dokumentasi arsitektur sistem aplikasi pencatatan ide "QuickNotes" menggunakan C4 Model beserta contoh source code menggunakan TypeScript, React, dan TailwindCSS.


Memahami 4 Tingkatan C4 Model

Berikut adalah penjelasan detail langkah demi langkah bagaimana kita memetakan aplikasi web pencatatan ide "QuickNotes" ke dalam C4 Model.

Level 1: System Context Diagram

System Context Diagram adalah peta tingkat tertinggi. Diagram ini tidak mempedulikan teknologi apa yang digunakan di dalam aplikasi, melainkan fokus pada bagaimana User berinteraksi dengan sistem secara keseluruhan dan sistem eksternal apa saja yang terhubung.

Pada sistem pencatatan ide QuickNotes, berikut adalah peta konteksnya:

C4 Model Level 1 Context Diagram & Level 2 Container Diagram

Komponen Utama pada Level 1:

  • Person (User): Pengguna aplikasi yang ingin menulis ide, mengelompokkan catatan dengan label, dan mencari catatan lama.
  • Software System (Note-Taking System): Batas luar sistem QuickNotes yang memfasilitasi pembuatan, pengeditan, pencarian, dan pengelolaan catatan.
  • External Identity Provider (e.g., Google Account): Sistem eksternal yang melayani proses autentikasi sistem secara aman (OAuth 2.0).

Level 2: Container Diagram

Masuk ke tingkat berikutnya, Container Diagram mendefinisikan kontainer-kontainer perangkat lunak terpisah yang membentuk sistem kita. Sebuah kontainer bisa berupa aplikasi web, database, layanan backend API, atau script CLI. Di sini, pilihan teknologi utama mulai dideklarasikan secara eksplisit.

Seperti terlihat pada bagian bawah gambar arsitektur di atas:

Pembagian Kontainer pada QuickNotes:

  1. React SPA (Single Page Application): Frontend web aplikasi yang ditulis menggunakan TypeScript dan React. Berfungsi sebagai antarmuka interaktif bagi user yang berjalan sepenuhnya di browser klien.
  2. REST API Container: Layanan backend API berbasis Node.js/Express dan TypeScript yang melayani request dari frontend, mengeksekusi logika bisnis catatan, dan memvalidasi akses token autentikasi.
  3. Database: Mesin database relasional PostgreSQL yang menyimpan metadata catatan, relasi tag/label, dan kredensial dasar pengguna.
  4. Google Account (OAuth API): Layanan eksternal yang dihubungi oleh REST API untuk memverifikasi profil user.

Level 3: Component Diagram

Component Diagram membongkar isi dari kontainer tertentu untuk melihat komponen-komponen penyusunnya secara logis beserta dependensinya. Pada tingkat ini, kita fokus menguraikan struktur logis di dalam backend REST API Container.

Berikut adalah rancangan diagram komponen level 3 untuk backend REST API QuickNotes:

C4 Model Level 3 Component Diagram

Komponen Internal dalam API Container:

  • Auth Controller: Komponen pengontrol yang bertugas menangani request masuk terkait login, registrasi, dan verifikasi token OAuth 2.0.
  • Note Controller: Menangani REST API endpoints untuk data catatan (Create, Read, Update, Delete).
  • Note Service: Berisi logika bisnis inti aplikasi (misalnya: aturan validasi panjang judul, pengecekan batas maksimum catatan per pengguna, dan filtering label).
  • Note Repository: Abstraksi akses database (menggunakan TypeORM atau Prisma) yang bertugas melakukan query database SQL tanpa mengotori logika bisnis di Note Service.

Level 4: Code Diagram

Tingkat terakhir ini sangat opsional dan biasanya hanya digambarkan untuk bagian arsitektur yang sangat kompleks. Code Diagram menunjukkan implementasi detail komponen ke tingkat kelas (class), antarmuka (interface), atau relasi fungsi/hooks pada level kode program.

Berikut adalah diagram relasi kode internal pada frontend React SPA QuickNotes:

C4 Model Level 4 Code Diagram

Di bawah ini adalah contoh nyata implementasi dari diagram level 4 tersebut menggunakan TypeScript dan React:

1. Interface Definisi Data (Note.ts)

export interface Note {
  id: string;
  title: string;
  content: string;
  color: string; // kode warna hex seperti '#f28b82'
  isPinned: boolean;
  labels: string[];
  createdAt: Date;
  updatedAt: Date;
}

2. Klien Panggilan API (NoteService.ts)

import axios from 'axios';
import { Note } from './Note';

const API_BASE_URL = 'https://api.QuickNotes.com/v1';

export class NoteService {
  private static client = axios.create({
    baseURL: API_BASE_URL,
    headers: { 'Content-Type': 'application/json' }
  });

  public static async getNotes(token: string): Promise<Note[]> {
    const response = await this.client.get<Note[]>('/notes', {
      headers: { Authorization: `Bearer ${token}` }
    });
    return response.data;
  }

  public static async createNote(noteData: Partial<Note>, token: string): Promise<Note> {
    const response = await this.client.post<Note>('/notes', noteData, {
      headers: { Authorization: `Bearer ${token}` }
    });
    return response.data;
  }
}

3. Custom Hook React (useNotes.ts)

import { useState, useEffect } from 'react';
import { Note } from './Note';
import { NoteService } from './NoteService';

export function useNotes(token: string) {
  const [notes, setNotes] = useState<Note[]>([]);
  const [isLoading, setIsLoading] = useState<boolean>(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!token) return;

    NoteService.getNotes(token)
      .then((data) => {
        setNotes(data);
        setIsLoading(false);
      })
      .catch((err) => {
        setError(err.message || 'Gagal memuat catatan');
        setIsLoading(false);
      });
  }, [token]);

  const addNote = async (newNote: Partial<Note>) => {
    try {
      const createdNote = await NoteService.createNote(newNote, token);
      setNotes((prev) => [createdNote, ...prev]);
    } catch (err: any) {
      setError(err.message || 'Gagal menyimpan catatan');
    }
  };

  return { notes, isLoading, error, addNote };
}

4. Perancangan Antarmuka Pengguna (TailwindCSS)

Untuk menyelaraskan arsitektur C4 dengan produk akhir, kita mendesain antarmuka aplikasi pencatat ide QuickNotes dengan layout grid responsif dan pilihan warna penanda kartu layaknya Google Keep:

Desain UI Aplikasi QuickNotes

Berikut adalah struktur kode antarmuka statis React menggunakan utility classes TailwindCSS untuk merender daftar catatan dalam bentuk grid kartu yang rapi:

import React from 'react';

// Contoh data statis catatan
const mockNotes = [
  {
    id: "1",
    title: "Project Alpha Tasks",
    content: "Define MVP, Backend Setup, UI Wireframes.",
    color: "border-emerald-500 bg-emerald-950/20 text-emerald-300",
    isPinned: true,
    labels: ["Work", "Urgent"]
  },
  {
    id: "2",
    title: "Groceries List",
    content: "Milk, Eggs, Bread, Kale.",
    color: "border-cyan-500 bg-cyan-950/20 text-cyan-300",
    isPinned: false,
    labels: ["Groceries"]
  }
];

export default function NoteGrid() {
  return (
    <div class="min-h-screen bg-neutral-950 text-neutral-100 flex p-6 font-sans">
      
      <!-- Side Navbar -->
      <aside class="w-60 pr-6 border-r border-neutral-800 space-y-4">
        <h1 class="text-xl font-bold text-white tracking-wide">QuickNotes</h1>
        <nav class="space-y-1 text-sm">
          <a href="#" class="block px-3 py-2 bg-neutral-900 text-emerald-400 font-semibold rounded-lg">Active Notes</a>
          <a href="#" class="block px-3 py-2 text-neutral-400 hover:text-white rounded-lg">Pinned</a>
          <a href="#" class="block px-3 py-2 text-neutral-400 hover:text-white rounded-lg">Trash</a>
        </nav>
      </aside>

      <!-- Main Section -->
      <main class="flex-1 pl-8 space-y-6">
        <!-- Top Search Bar -->
        <header class="flex justify-between items-center">
          <input 
            type="text" 
            placeholder="Cari ide atau label..." 
            class="w-full max-w-md bg-neutral-900 border border-neutral-800 rounded-lg px-4 py-2 text-sm text-white focus:outline-none focus:border-emerald-500"
          />
        </header>

        <!-- Grid Cards -->
        <section class="grid grid-cols-1 md:grid-cols-3 gap-6">
          {mockNotes.map((note) => (
            <div key={note.id} class={`p-5 rounded-lg border-2 ${note.color} flex flex-col justify-between space-y-4`}>
              <div>
                <div class="flex justify-between items-start">
                  <h3 class="font-bold text-white text-base">{note.title}</h3>
                  {note.isPinned && <span class="text-xs font-semibold text-emerald-400">📌 Pinned</span>}
                </div>
                <p class="text-xs mt-2 leading-relaxed text-neutral-300">{note.content}</p>
              </div>

              <!-- Tags / Labels -->
              <div class="flex flex-wrap gap-1.5 mt-4">
                {note.labels.map((label) => (
                  <span key={label} class="text-[9px] font-bold bg-neutral-900 text-neutral-400 border border-neutral-800 px-2 py-0.5 rounded-full uppercase">
                    {label}
                  </span>
                ))}
              </div>
            </div>
          ))}
        </section>
      </main>

    </div>
  );
}

Kesimpulan: Mengapa C4 Model Sangat Efektif?

Dokumentasi arsitektur "QuickNotes" dengan C4 Model memecahkan masalah kompleksitas komunikasi teknis melalui beberapa keuntungan penting:

  1. Navigasi Arsitektur yang Mudah: Manajer Produk (Product Manager) dapat memahami Level 1 (Context). Developer baru dapat mempelajari Level 2 (Container) dan Level 3 (Component) sebelum mulai ngoding, sedangkan QA Engineers dapat langsung memetakan integrasi pengujian dari Level 3.
  2. Skalabilitas yang Jelas: Ketika kita ingin menambahkan fitur sinkronisasi offline berbasis Service Worker di browser, kita cukup menambahkan kontainer baru pada diagram Level 2 dan merinci komponen sinkronisasinya pada Level 3 tanpa perlu mengotak-atik bagan konteks di Level 1.

Referensi & Resource Penting

  • Brown, Simon. Software Architecture for Developers. Leanpub. Buku panduan resmi yang menjelaskan asal mula dan penerapan taktis C4 Model.
  • The C4 Model Official Website. Situs dokumentasi resmi dengan sampel standar notasi diagram C4 Model: C4 Model Official Site.
  • Structurizr. Kakas (tooling) pembuat diagram berbasis kode (diagram-as-code) untuk mendokumentasikan C4 Model secara dinamis: Structurizr Site.
  • TypeScript documentation. Penjelasan struktur modular class, import/export, dan interface pada TypeScript: TypeScript Official Site.