tutorial

24 Strategi Refactor Skema GraphQL untuk Proyek Besar

24 Strategi Refactor Skema GraphQL untuk Proyek Besar

GraphQL telah menjadi standar baru dalam membangun API modern — fleksibel, mudah dikonsumsi, dan powerful. Namun, ketika skema GraphQL kian membesar, tantangan baru muncul: fragmentasi, duplikasi, field yang terlupakan, hingga resolvers yang sulit dirawat. Merombak (refactor) skema GraphQL adalah tugas berat, tapi sangat krusial untuk menjaga performa dan maintainability di proyek besar.

Sebagai seorang engineer yang pernah menghadapi skema GraphQL dengan ratusan tipe dan ribuan baris, berikut saya bagikan 24 strategi refactor skema GraphQL yang sudah terbukti membantu beberapa tim dan organisasi naik level dalam pemeliharaan API.


1. Audit Seluruh Skema

Mulailah dengan memetakan struktur skema saat ini. Gunakan introspection query atau tools seperti GraphQL Voyager untuk visualisasi relasi antar tipe.

Contoh introspection query dengan Apollo:

const { ApolloServer } = require('apollo-server')
const gql = require('graphql-tag')

const typeDefs = gql`
  type Query {
    users: [User]
  }
  type User {
    id: ID
    name: String
    email: String
  }
`

Diagram relasi sederhana:

erDiagram
    USER ||--o| QUERY : tersedia

2. Dokumentasikan Perubahan Secara Berkala

Buat file CHANGELOG.md di dalam repository skema Anda. Setiap perubahan tipe, field, atau resolver harus tercatat — ini menyelamatkan dari kerancuan dan konflik antar tim.


3. Modulasi Skema dalam Folder Terkait

Pisahkan tipe, query, dan mutation berdasarkan domain/fitur, misal folder user, product, dll.

Contoh struktur:

├── schema
│   ├── user/
│   │   ├── typeDefs.js
│   │   └── resolvers.js
│   ├── product/
│   │   ├── typeDefs.js
│   │   └── resolvers.js
│   └── index.js

4. Implementasi Federation/Schema Stitching

Pada proyek besar, pertimbangkan membagi skema menjadi subgraph menggunakan Apollo Federation atau GraphQL Schema Stitching.

Keuntungan:

  • Setiap tim bisa deploy subgraph tanpa mengganggu tim lain.
  • Mengurangi risiko merge conflict skema.

5. Refactor Tipe Berulangkali Digunakan Menjadi Reusable Types

Identifikasi pola duplikasi pada tipe dan gunakan tipe generik.

Sebelum:

type Employee {
  id: ID!
  name: String!
}

type Manager {
  id: ID!
  name: String!
}

Sesudah:

type Person {
  id: ID!
  name: String!
}

6. Gunakan Union & Interface

Jika ada beberapa tipe dengan struktur serupa atau relasi polymorphic, gunakan interface atau union.

interface Node {
  id: ID!
}
type User implements Node {
  id: ID!
  email: String!
}
type Product implements Node {
  id: ID!
  price: Int!
}

7. Refactor Field yang Overfetching

Kurangi field-field tidak penting atau pindahkan detail ke properti nested atau resolver on-demand.


8. Implementasi Deprecation pada Field

GraphQL mendukung deprecated directive / @deprecated(reason: "message") /. Ini sangat membantu migrasi.

type User {
  email: String! @deprecated(reason: "Use contactEmail instead")
  contactEmail: String!
}

9. Hindari Query/Mutaion Megamonster

Bagi satu query/mutation super besar menjadi beberapa endpoint yang lebih kecil dan jelas.


10. Bersih-bersih Enum dan Input

Revisi seluruh enum dan InputType — hapus state/value yang tidak valid dan tidak terpakai.


11. Maksimalkan Scalar Types Custom

Tambahkan Scalar type custom seperti DateTime, Email, atau JSON untuk validasi yang lebih ketat.

scalar Email

type User {
  email: Email!
}

12. Sederhanakan Pagination

Adopsi satu pola paginasi, misal Relay Connection, dan singkirkan yang lain untuk konsistensi.


13. Batch Resolver dan DataLoader

Gabungkan akses ke data yang berulang agar efisien (misal, lewat dataloader).


14. Implementasi Field-level Authorization

Tambahkan middleware/logic authorization per field daripada membebani root resolver.


15. Integrasi Automated Schema Linting

Gunakan tools seperti graphql-schema-linter pada CI.


16. Buat Test Suite untuk Skema

Tes basic dan edge cases pada skema, seperti mandatory fields, query invalid, dll.

Contoh Jest test:

it('rejects missing mandatory fields', async () => {
  const res = await query({ query: '{ user }' })
  expect(res.errors).toBeDefined()
})

17. Refactor Mutation untuk Idempotency

Desain mutation besar agar idempotent jika diperlukan, supaya retry tidak menimbulkan duplikat data.


18. Versikan Skema Secara Berkala

Alih-alih big bang migration, lakukan breaking change pada v2 query field/type.

Skema versioning contoh:

type Query {
  getUserV1(id: ID!): UserV1
  getUserV2(id: ID!): UserV2
}

19. Hardening Field dengan NonNull

Pastikan field yang tidak boleh null memakai tanda !.


20. Gunakan Directive untuk Validation

Custom directive (@isEmail, @length, dll) memperkaya validasi otomatis di skema.

directive @isEmail on FIELD_DEFINITION

type User {
  email: String! @isEmail
}

21. Melakukan Query Usage Analysis

Pantau query mana yang sering dipakai lewat tools analytics seperti Apollo Studio untuk membantu memutuskan field mana yang ingin dihapus/refactor.


22. Standarisasi Penamaan

Gunakan casing dan pola standar dalam field, argumen, dan tipe (camelCase untuk field, PascalCase untuk type).


23. Mapping Skema Lama ke Skema Baru

Selalu dokumentasikan mapping (misal dalam tabel Excel/Markdown) untuk membantu migrasi client dan backend.

Field LamaField BaruKeterangan
emailcontactEmailDiganti untuk konsistensi

24. Diagram Alur Deployment Refactor

Alur ideal refactor skema GraphQL:

flowchart TD
    A(Audit & Documentasi Skema) --> B(Breakdown ke Micro-schema/Module)
    B --> C(Implementasi Deprecation)
    C --> D(Migrasi Client ke Field Baru)
    D --> E(Remove Field/Types Deprecated)
    E --> F(Test & Deploy)

Penutup

Merombak skema GraphQL besar memang tidak mudah, bahkan seringkali ditakuti karena kompleksitas dan risiko. Namun dengan 24 strategi di atas — mulai dari praktik simple (dokumentasi, linting, penamaan) sampai modularisasi complex (federation, versioning, batching) — proses refactor bisa lebih lancar, minim distrupsi, dan menaikkan kualitas maintainability jangka panjang.

Satu pesan terakhir: refactor skema itu maraton, bukan sprint. Bangunlah fondasinya, biasakan audit secara berkala, dan libatkan semua stakeholder (backend, frontend, SRE/devops, bahkan pebisnis). Semakin matang fondasi skema, semakin kokoh API GraphQL Anda di masa depan.


Referensi & Tools

comments powered by Disqus