# Membangun Desain Sistem REST API Skala Besar dengan Go & Clean Architecture

> Diterbitkan oleh Literally Web ID pada 21 Oct 2026
> Sumber: https://literally.web.id/articles/membangun-desain-sistem-rest-api-skala-besar-dengan-go-clean-architecture

---

## 1. Menu Kita Hari Ini & Alat yang Perlu Disiapkan

Pernahkah Anda masuk ke sebuah proyek backend skala besar di mana folder handler, database query, dan business logic tercampur aduk bagaikan salad buah yang kelebihan susu kental manis? Saya sering melihatnya. Hari ini, dalam 15 menit ke depan, kita akan merakit sebuah REST API berstandar industri dengan Go menggunakan Clean Architecture, lengkap dengan pembagian domain, rate limiting, JWT authentication middleware, serta error handling terstandarisasi RFC 7807 yang elegan.

Sebelum kita mulai meracik kode di dapur, pastikan alat tempur berikut sudah terpasang di mesin Anda:
- Go versi 1.21 atau yang lebih baru.
- Make (opsional, tapi sangat membantu untuk otomasi perintah).
- Editor andalan Anda (VS Code atau Goland).

Mari kita mulai perjalanan ini dengan menyiapkan fondasi yang kokoh agar aplikasi kita tidak roboh saat dihantam jutaan trafik.

## 2. Peta Jalan Singkat: Apa yang Sedang Kita Rakit

Bayangkan arsitektur kita seperti sebuah restoran mewah. Bagian *Handler* adalah pelayan yang menerima pesanan dari tamu (HTTP Request). Bagian *Use Case* atau *Domain* adalah kepala koki yang mengolah bahan mentah menjadi hidangan lezat sesuai resep rahasia perusahaan. Sementara itu, *Repository* adalah gudang penyimpanan bahan baku (Database).

Kita tidak ingin pelayan masuk ke gudang mengambil kentang sendiri, bukan? Begitu juga dengan kode kita. Handler tidak boleh tahu bagaimana cara kerja SQL query. Dengan memisahkan lapisan-lapisan ini, aplikasi kita menjadi sangat mudah diuji (*testable*) dan dirawat (*maintainable*).

## 3. Langkah 1: Mempersiapkan Fondasi & Environment

Pertama-tama, mari kita buat direktori kerja baru dan inisialisasi modul Go kita. Buka terminal Anda dan jalankan perintah ini:

```bash
mkdir -p go-clean-rest-api && cd go-clean-rest-api
go mod init github.com/username/go-clean-rest-api
```

> [!TIP]
> Gunakan struktur folder berbasis domain atau lapisan Clean Architecture yang rapi sejak awal. Struktur direktori yang berantakan di awal akan menjadi mimpi buruk saat codebase menyentuh puluhan ribu baris.

Mari kita buat kerangka folder inti kita:

```bash
mkdir -p cmd/api internal/domain internal/usecase internal/delivery/http internal/infrastructure/database
```

Di dalam folder `internal/domain`, kita definisikan entitas utama kita. Buat file `user.go`:

```go
package domain

import "context"

type User struct {
    ID    int64  `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

type UserRepository interface {
    GetByID(ctx context.Context, id int64) (*User, error)
}

type UserUseCase interface {
    Profile(ctx context.Context, id int64) (*User, error)
}
```

Dengan mendefinisikan *interface* di domain, kita membalikkan arah panah dependensi (*Dependency Inversion Principle*). Use case tidak bergantung pada database, melainkan database yang harus mengikuti kontrak dari domain.

## 4. Langkah 2: Meracik Konfigurasi Inti Tanpa Basa-basi

Sekarang kita masuk ke bagian krusial: mengamankan jalur komunikasi. Kita butuh Middleware untuk menangani JWT Authentication dan Rate Limiting agar API kita kebal dari serangan brute-force atau DDoS skala kecil.

Buat file `internal/delivery/http/middleware.go`:

```go
package http

import (
    "net/http"
    "strings"
)

func JWTMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        authHeader := r.Header.Get("Authorization")
        if authHeader == "" || !strings.HasPrefix(authHeader, "Bearer ") {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }
        // Di dunia nyata, verifikasi token JWT Anda di sini
        next.ServeHTTP(w, r)
    })
}
```

> [!IMPORTANT]
> Jangan pernah meletakkan logika validasi token yang berat langsung di dalam middleware tanpa caching jika trafik Anda sudah mencapai ribuan *request per second*. Gunakan Redis untuk memvalidasi token yang telah di-blacklist.

## 5. Langkah 3: Sentuhan Akhir Keamanan & Optimasi

Bagaimana jika terjadi error? Sering kali backend engineer mengembalikan string error mentah seperti `Error 500: nil pointer dereference`. Ini berbahaya dan tidak profesional. Kita akan menggunakan standar **RFC 7807 (Problem Details for HTTP APIs)**.

Buat file `internal/delivery/http/response.go`:

```go
package http

import (
    "encoding/json"
    "net/http"
)

type ProblemDetail struct {
    Type     string `json:"type"`
    Title    string `json:"title"`
    Status   int    `json:"status"`
    Detail   string `json:"detail"`
    Instance string `json:"instance"`
}

func WriteError(w http.ResponseWriter, status int, title, detail, instance string) {
    w.Header().Set("Content-Type", "application/problem+json")
    w.WriteHeader(status)
    json.NewEncoder(w).Encode(ProblemDetail{
        Type:     "about:blank",
        Title:    title,
        Status:   status,
        Detail:   detail,
        Instance: instance,
    })
}
```

Dengan respons berformat JSON di atas, client frontend atau mobile app akan menerima informasi error yang sangat terstruktur dan konsisten.

## 6. Tes Rasa: Memastikan Semuanya Berjalan Sempurna

Saatnya menyatukan semua racikan ini ke dalam `cmd/api/main.go`. Mari kita jalankan server HTTP sederhana kita:

```go
package main

(
    "log"
    "net/http"
    h "github.com/username/go-clean-rest-api/internal/delivery/http"
)

func main() {
    mux := http.NewServeMux()
    
    mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("System is healthy and ready to serve!"))
    })

    log.Println("Server running on port 8080...")
    if err := http.ListenAndServe(":8080", mux); err != nil {
        log.Fatalf("Server failed: %v", err)
    }
}
```

Jalankan aplikasi Anda dengan perintah:

```bash
go run cmd/api/main.go
```

Buka terminal lain dan tembak endpoint-nya:

```bash
curl -i http://localhost:8080/health
```

Jika Anda melihat respons `HTTP/1.1 200 OK` beserta pesan kesiapan sistem, selamat! Arsitektur bersih berbasis Go Anda sudah mengudara.

## 7. Pertolongan Pertama: Jika Terjadi Kendala Kecil

- **Error `go: go.mod file not found`**: Pastikan Anda menjalankan perintah di dalam root direktori modul yang benar atau jalankan `go mod init <nama-modul>` terlebih dahulu.
- **Port 8080 Sudah Digunakan**: Ubah port pada `http.ListenAndServe(":8080", mux)` menjadi port lain seperti `:9000` atau matikan proses yang menggunakan port tersebut menggunakan `lsof -i :8080`.

Tetaplah tenang, baca log error dengan teliti, dan arsitektur Anda akan selalu siap menghadapi skala apa pun.