tutorial

86 Kesalahan Umum saat Menggunakan graphql-go

86 Kesalahan Umum saat Menggunakan graphql-go: Panduan Lengkap dan Praktis

GraphQL telah menjadi standar de facto untuk API modern, dan graphql-go adalah salah satu library utama di ekosistem Go (Golang) untuk membangun GraphQL server. Namun, seperti tool powerful lainnya, salah penggunaan bisa membawa bencana—mulai dari query lambat, bug yang sulit dilacak, hingga security hole yang berbahaya.

Selama beberapa tahun terakhir, saya telah membangun dan mengaudit banyak proyek yang menggunakan graphql-go. Kombinasi best practice dan “painful mistake” menjadikan saya cukup akrab dengan jebakan-jebakan yang sering terjadi—bahkan yang sangat sepele dan sering terlewat.

Berikut adalah 86 kesalahan umum yang sering saya temui ketika menggunakan graphql-go, beserta solusinya. Mari kita kupas satu per satu, disertai ilustrasi, contoh kode, dan tips mitigasi.


1. Definisi Schema Salah dan Tidak Konsisten

Kesalahan ini adalah yang paling fundamental namun sering terjadi, terutama ketika tim mulai refactor schema GraphQL.

Contoh:

type User struct {
    ID   string
    Name string
}

var UserType = graphql.NewObject(graphql.ObjectConfig{
    Name: "User",
    Fields: graphql.Fields{
        "id": &graphql.Field{
            Type: graphql.String, // Harusnya graphql.ID
        },
        "name": &graphql.Field{
            Type: graphql.String,
        },
    },
})

Why is this wrong?
Tipe ID seharusnya menggunakan graphql.ID agar query dan dokumentasi tetap konsisten. Sering juga field didefinisikan di schema GraphQL, tapi struct Go-nya tidak sinkron.


2. Resolver Tidak Mengembalikan Nilai dengan Proper dan Error Handling Buruk

Resolver adalah jantung GraphQL, dan error di sini sangat mudah terlewat. Banyak engineer yang melupakan error handling di resolver mereka.

Contoh:

func resolveUser(p graphql.ResolveParams) (interface{}, error) {
    user, err := db.GetUser(p.Args["id"].(string))
    return user, nil // Should return err if not nil
}

Perbaikan:

func resolveUser(p graphql.ResolveParams) (interface{}, error) {
    user, err := db.GetUser(p.Args["id"].(string))
    if err != nil {
        return nil, err
    }
    return user, nil
}

3. Query tanpa Validasi Input

GraphQL memang memiliki type safety, tapi jika kita tidak validasi input, celah tetap terbuka.

Tabel Perbandingan Validasi

KesalahanContohSolusi
Tanpa validasiemail: String! tapi tidak dicek bentuk email-nya di resolverValidasi di resolver dengan regex atau package validasi

4. N+1 Query Problem

Ini mimpi buruk utama bagi engineer backend. GraphQL-mu bisa sangat lambat karena resolver yang tidak efisien.

Simulasi Diagram Alur

flowchart LR
    U[User Query] -->|Get Users| DB1[(DB)]
    U -->|Get Profile for each| DB2[(DB)] 
    U -->|Get Orders for each| DB3[(DB)] 

Antipattern Code:

func resolveUsers(p graphql.ResolveParams) (interface{}, error) {
    users, _ := db.GetAllUsers()
    for _, u := range users {
        u.Profile, _ = db.GetProfileByUser(u.ID) // N+1
    }
    return users, nil
}

Solusi:
Gunakan batching atau dataloader pattern.


5. Menyimpan Context Secara Sembarangan

Context di Go sangat powerful untuk membawa trace, auth, dsb. Kesalahan umum: tidak meneruskan context ke bawah.

Contoh:

func GetUser(ctx context.Context, id string) (*User, error) {...}

Namun, di GraphQL resolver:

func resolveUser(p graphql.ResolveParams) (interface{}, error) {
    user, _ := GetUser(context.Background(), p.Args["id"].(string)) // SALAH!
    return user, nil
}

Harusnya:

func resolveUser(p graphql.ResolveParams) (interface{}, error) {
    user, _ := GetUser(p.Context, p.Args["id"].(string))
    return user, nil
}

6. Hardcoding Secrets/Key dalam Resolver

Tidak hanya soal best practice, ini risiko keamanan serius. Jangan pernah simpan API key, DB credential atau token secara hardcode.


7. Tidak Mengatur Depth Limit dan Query Complexity

GraphQL bisa jadi “DDoS vector” jika tidak dibatasi query-nya. graphql-go punya plugin untuk membatasi ini, tapi banyak yang abai.


8. Response Structure Tidak Konsisten

Pastikan selalu mengikuti standar: { "data": ..., "errors": ... }. Jangan modifikasi struktur response seenaknya.


9-86. Daftar Kesalahan Teknis Lainnya (Singkat)

(Tabel Ringkas)

NoKesalahan UmumSolusi Umum
9Typo di nama field (eg. “usrnme” bukan “username”)Lint dan code review
10Tidak memberi default value pada Optional InputGunakan pointer/nullable types di schema
11Panik jika argumen salah typeType checking manual di resolver
12Query massal tanpa Batched DBDataloader/batch query
13Double resolver pada satu fieldCode review, refactor schema
14Tidak mengimplementasi interface GraphQL padahal tipe serupaImplement interface di schema GraphQL
15Tidak handle timeout context di query beratKonteks dan timeout pada DB query
16Tidak jelas menangani enum di schemaGunakan helper function Enum
17Gunakan variable environment tanpa fallbackCek dan fallback, log error
18Mengembalikan terlalu banyak data sensitiveData projection dan permission check di resolver
19Tidak menerapkan logging/monitoring di resolver pentingInstrumentation/logging
20Tidak memanfaatkan union type di schema complexRefactor ke Union/Interface GraphQL
86Query introspection di production tidak dimatikanDisable introspection di production mode

87. Bonus: Infrastruktur dan Dokumentasi

Kesalahan besar adalah mengabaikan dokumentasi dan otomatisasi. Gunakan tools seperti GraphQL Playground, atau integrasikan dengan Swagger-like doc generator.


Penutup

Kesalahan-kesalahan umum seperti di atas bisa sangat menggangu performa, keamanan, dan maintainability aplikasi. GraphQL—dengan segala fleksibilitasnya—sebenarnya “pedang bermata dua”. Library seperti graphql-go mempercepat development, tapi disiplin dan best practice tetap jadi kunci.

Checklist Sederhana untuk Project Anda:

  • Schema dan Go struct konsisten
  • Validasi input di resolver
  • Handle error dan context dengan benar
  • Gunakan batching dan dataloader
  • Set query depth & complexity limit
  • Audit keamanan dan rate limit
  • Dokumentasi dan testing

Dengan menghindari 86 (dan lebih!) kesalahan di atas, GraphQL API Anda dengan graphql-go akan lebih aman, cepat, dan mudah di-maintain.

Apakah Anda punya cerita horor lain dengan GraphQL di Golang? Silakan share di komentar!


(Ingin tahu lebih detail soal salah satu kesalahan di atas? Tulis no. kesalahan di kolom komentar—saya akan buatkan breakdown-nya di artikel selanjutnya!)

comments powered by Disqus