@Value: Opini Engineering tentang Konfigurasi di Spring Boot
Dalam banyak codebase Spring Boot—terutama di Indonesia—konfigurasi sering dianggap hal remeh. Selama aplikasi bisa jalan, selesai. Akibatnya, @Value digunakan di mana-mana: di service, di controller, bahkan di utility class.
Masalahnya bukan karena @Value itu buruk. Masalahnya adalah @Value terlalu mudah, sehingga sering dipakai tanpa sadar konsekuensi jangka panjangnya. Dalam artikel ini, kita tidak sekadar membahas bagaimana menggunakan konfigurasi di Spring Boot, tetapi mengapa pilihan yang salah bisa berubah menjadi technical debt tersembunyi.
Argumen Utama: Konfigurasi adalah Kontrak, Bukan Sekadar Nilai
Secara engineering, konfigurasi adalah:
- Kontrak antara aplikasi dan environment
- Bagian dari public API internal
- Fondasi untuk scalability dan operasional
Jika konfigurasi diperlakukan seperti “string biasa”, maka desain aplikasi ikut turun kualitasnya.
@Value: Nyaman di Awal, Mahal di Akhir
Kenyataan di Lapangan
Contoh yang sering ditemukan:
@Value("${jwt.secret}")
private String jwtSecret;
@Value("${jwt.expired}")
private long expired;
Awalnya terlihat rapi. Tapi setelah 6 bulan:
jwt.secretjuga dipakai di 4 class lainjwt.expiredberubah jadijwt.access.expireddanjwt.refresh.expired- Tidak ada satu tempat pun yang mendokumentasikan struktur JWT config
Kenapa Ini Technical Debt
Konfigurasi tersebar (configuration scattering) Tidak ada single source of truth.
Tidak ada kontrak tipe Semua berbentuk string sampai runtime.
Refactor berisiko tinggi Rename property = grep seluruh codebase.
Validasi nol besar Salah config = crash saat runtime.
Kapan @Value Masih Bisa Diterima
Opini jujur:
- Feature flag sederhana
- Nilai boolean / integer tunggal
- PoC, prototype, atau tooling internal
Di luar itu? Mulai berbahaya.
@ConfigurationProperties: Saat Engineering Mulai Dewasa
Jika @Value adalah shortcut, maka @ConfigurationProperties adalah keputusan desain.
Apa yang Berubah Secara Fundamental
Dengan pendekatan ini, kamu mengatakan:
“Konfigurasi ini adalah satu domain yang utuh.”
Contoh File application.yaml
jwt:
secret: my-super-secret
access-token:
expired: 15m
refresh-token:
expired: 7d
Contoh Class Configuration Java
@ConfigurationProperties(prefix = "jwt")
public class JwtProperties {
private String secret;
private Duration accessTokenExpired;
private Duration refreshTokenExpired;
}
Sekarang:
- Struktur konfigurasi jelas
- Perubahan terlokalisasi
- Kontrak eksplisit
Efek Samping Positif (yang Sering Diremehkan)
- Code review jadi lebih mudah
- Onboarding engineer baru lebih cepat
- Bug akibat misconfig turun drastis
Tapi Ini Masih Belum Sempurna
Masalahnya:
- Konfigurasi masih mutable
- Masih bisa disalahgunakan sebagai state
Record: Titik Balik dari “Bisa Jalan” ke “Benar Secara Desain”
Kenapa Immutable Itu Penting
Konfigurasi seharusnya:
- Dibaca saat startup
- Tidak berubah seumur hidup aplikasi
record memaksa disiplin ini.
Contoh File application.yaml
jwt:
secret: my-super-secret
access-token:
expired: 15m
refresh-token:
expired: 7d
Contoh Class Record Java
@ConfigurationProperties(prefix = "jwt")
public record JwtProperties(
String secret,
Duration accessTokenExpired,
Duration refreshTokenExpired
) {}
Sekarang secara desain:
- Tidak ada setter
- Tidak ada mutasi
- Tidak ada ambiguity
Dampak Jangka Panjang
- Konfigurasi jadi self-documented
- Testing lebih deterministik
- Debugging lebih cepat
Aturan Konversi Nama (PENTING)
Spring Boot menganggap ini setara:
| YAML / Properties | Java Field |
|---|---|
access-token | accessToken |
access_token | accessToken |
access.token | accessToken |
ACCESSTOKEN | accessToken |
Semua ini akan di-bind ke:
Token accessToken;
Karena Spring Boot melakukan normalisasi nama.
Perbandingan Filosofis
| Pertanyaan | @Value | ConfigProperties | ConfigProperties + record |
|---|---|---|---|
| Cepat di awal? | ✅ | ❌ | ❌ |
| Aman di jangka panjang? | ❌ | ⚠️ | ✅ |
| Ramah tim besar? | ❌ | ✅ | ✅ |
| Menahan technical debt? | ❌ | ⚠️ | ✅ |
Rekomendasi Nyata untuk Tim
- Startup kecil → boleh
@Value, tapi sadar risikonya - Produk yang akan tumbuh → langsung
@ConfigurationProperties - Microservices / regulated system →
recordatau jangan sama sekali
Best Practice
- Jika kamu ragu, jangan pakai
@Value - Satu domain konfigurasi = satu class / record
- Anggap konfigurasi sebagai bagian dari arsitektur
- Gunakan immutable configuration secara default
@Valueadalah exception, bukan default
Kesimpulan
@Value bukan musuh. Tapi kenyamanan berlebihan adalah akar technical debt.
Engineer yang matang tidak bertanya:
“Mana yang paling cepat?”
Tapi:
“Mana yang masih masuk akal ketika codebase ini 2 tahun lagi?”
Konfigurasi adalah tempat yang tepat untuk mulai bersikap dewasa secara engineering.