8 Struktur Direktori Ideal untuk Proyek graphql-go
GraphQL menjadi solusi mainstream untuk API karena modelnya yang fleksibel dan kemampuan fetch data yang efisien. Salah satu library yang cukup populer untuk Go adalah graphql-go
. Meskipun dokumentasi library ini solid, detail tentang struktur proyek sering kali diabaikan—padahal, project structure punya dampak signifikan ke maintainability dan collaboration.
Selama beberapa tahun membangun microservice dengan GraphQL di Go, saya sudah mencoba aneka pola, serta melihat berbagai bentuk codebase di open-source maupun internal product. Artikel ini membagikan 8 struktur direktori ideal yang menurut saya bisa membuat proyek graphql-go kamu lebih terorganisir, scaleable dan nyaman di-maintain oleh tim.
1. Struktur Dasar: Template Modular, bukan Monolith
Singkatnya, flat structure itu jebakan pemula. Proyek kecil memang bisa survive, tapi begitu berkembang, satu folder jadi lautan file yang berantakan. Struktur modular—berbasis domain atau feature—memberi ruang untuk bertumbuh.
Berikut template ideal yang bisa dijadikan starting point:
my-graphql-app/
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ ├── domain/
│ │ ├── user/
│ │ │ ├── model.go
│ │ │ ├── resolver.go
│ │ │ └── repository.go
│ │ └── post/
│ │ ├── model.go
│ │ ├── resolver.go
│ │ └── repository.go
│ ├── gql/
│ │ ├── schema/
│ │ │ └── schema.graphql
│ │ ├── loader.go
│ │ └── resolver.go
│ ├── config/
│ │ └── config.go
│ └── pkg/
│ ├── db/
│ │ └── db.go
│ ├── logger/
│ │ └── logger.go
│ └── utils/
│ └── utils.go
├── vendor/
├── go.mod
└── go.sum
2. cmd/
– Entry Point yang Clean
Di dalam folder cmd/
, kita letakkan entry point aplikasi; biasanya satu folder per binary. Untuk server GraphQL, buat cmd/server/main.go
. Di sinilah aplikasi start, parse config, dan menjalankan server.
Contoh:
package main
import (
"log"
"net/http"
"my-graphql-app/internal/gql"
"my-graphql-app/internal/config"
)
func main() {
cfg := config.Load()
srv := gql.NewGraphQLServer(cfg)
http.Handle("/query", srv)
log.Printf("Running at :%s...", cfg.Port)
log.Fatal(http.ListenAndServe(":" + cfg.Port, nil))
}
3. internal/domain/
– Pisahkan Per Domain/Feature
Jangan campurkan semua resolvers dalam satu file. Gunakan internal/domain/
guna menyimpan resource per domain (misal: user
, post
). Setiap domain punya:
- model.go: Struct data sesuai schema
- repository.go: Abstraksi akses data
- resolver.go: Implementasi resolver GraphQL spesifik untuk domain
Contoh internal/domain/user/model.go
:
package user
type User struct {
ID string
Name string
Email string
}
Dan resolver-nya:
package user
import "context"
type Resolver struct {
Repo Repository
}
// Contoh query resolver
func (r *Resolver) GetUser(ctx context.Context, args struct{ID string}) (*User, error) {
return r.Repo.FindByID(ctx, args.ID)
}
4. internal/gql/
– Pusat GraphQL Logic
Folder gql/
bersifat global untuk GraphQL, misal:
- schema/: File
.graphql
, misalschema.graphql
- loader.go: Fungsionalitas DataLoader (bila butuh efisiensi query)
- resolver.go: Root resolver yang mendelegasikan ke masing-masing resolver domain
Contoh root resolver:
package gql
import (
"my-graphql-app/internal/domain/user"
"my-graphql-app/internal/domain/post"
)
type Resolver struct {
User *user.Resolver
Post *post.Resolver
}
5. internal/config/
– Konfigurasi Terkelola
Segala konfigurasi (port, env, dsb) ditempatkan di sini dalam satu source of truth, memudahkan testing dan deployment.
package config
import "os"
type Config struct {
Port string
DBUrl string
}
func Load() *Config {
return &Config{
Port: os.Getenv("PORT"),
DBUrl: os.Getenv("DB_URL"),
}
}
6. internal/pkg/
– Helper & Library Umum
Simpan library internal, helper, atau komponen infrastruktur (misal utilitas database, logger, JWT, dsb) di sini. Hindari kebiasaan kodok “helper.go” di root yang isinya random stuff.
Contoh basic logger:
package logger
import "log"
func Info(msg string) {
log.Printf("[INFO]: %s", msg)
}
7. Testing: Dekatkan Test dengan Fungsinya
Terapkan konvensi Go, simpan test di file _test.go
pada folder yang sama. Untuk integrasi GraphQL, ciptakan test case query ke API.
Contoh: internal/domain/user/user_test.go
func TestGetUser(t *testing.T) {
// Set up dummy repository and context
// Call resolver
// Assert output
}
8. Documentasi & Schema yang Rapi
Jangan sepelekan API documentation. Simpan GraphQL schema di internal/gql/schema/schema.graphql
. Lengkapi dengan deskripsi setiap type/query.
Contoh:
"""User yang terdaftar dalam sistem"""
type User {
"ID unik user"
id: ID!
"Nama user"
name: String!
"Email user"
email: String!
}
type Query {
"Ambil user sesuai ID"
user(id: ID!): User
}
Simulasi Alur Query
Mari visualisasikan alurnya dengan diagram Mermaid:
flowchart LR Client["Client"] GQLHandler["GraphQL Handler (/query)"] RootResolver["Root Resolver"] UserDomain["User Resolver (Domain)"] DB["User Repository & Database"] Client --> GQLHandler GQLHandler --> RootResolver RootResolver --> UserDomain UserDomain --> DB
Begitu request GraphQL masuk, handler akan parsing schema, request didelegasikan ke root resolver sesuai dengan type/query, baru dilempar ke resolver domain (misal: user), lalu diteruskan ke repository buat fetch data dari DB.
Tabel Referensi Struktur Folder
Folder | Isi & Tanggung Jawab | Contoh File |
---|---|---|
cmd/ | Entry point aplikasi | main.go |
internal/domain/ | Business logic per domain/model | user/model.go |
internal/gql/ | Integrasi GraphQL (schema & root resolver) | schema.graphql , loader.go |
internal/config/ | Konfigurasi terpusat | config.go |
internal/pkg/ | Utility/helper/infra internal | db.go , logger.go |
vendor/ | Library dependencies | |
go.mod , go.sum | Go module management |
Kesimpulan
Mengadopsi struktur direktori yang rapi adalah investasi jangka panjang. Dengan memisahkan concern antar domain, utility, schema, dan entry point, kita membantu seluruh tim maintain dan scale codebase. Don’t let your project structure be an afterthought. Mulai dengan kerangka modular seperti di atas, lalu adaptasikan sesuai kebutuhan real teams. Struktur yang baik = maintainability, scalability, dan happy team.
Mau diskusi? Drop di komentar pengalaman kalian dengan struktur GraphQL project di Go!
Referensi:
29 Studi Kasus: Streaming Upload File
Artikel Terhangat
30 Studi Kasus: Streaming Progress Update
07 Jul 2025
29 Studi Kasus: Streaming Upload File
07 Jul 2025
28 Studi Kasus: Streaming Chat Sederhana
07 Jul 2025
6 Inisialisasi Proyek Go untuk GraphQL
07 Jul 2025

30 Studi Kasus: Streaming Progress Update

29 Studi Kasus: Streaming Upload File

28 Studi Kasus: Streaming Chat Sederhana
