Casper μνκ³μ μ ν리μΌμ΄μ μ€μ μ κ΄λ¦¬νλ Spring Cloud Config Serverμ λλ€.
λΆμ° μμ€ν μ μν μΈλΆ μ€μ μ μ 곡νλ μ€μμ§μ€μ μ€μ μλ²μ λλ€. MySQL λ°μ΄ν°λ² μ΄μ€μ μ€μ λ°μ΄ν°λ₯Ό μ μ₯νκ³ λ―Όκ°ν κ°μ λν μνΈνλ₯Ό μ§μν©λλ€.
- λ°μ΄ν°λ² μ΄μ€ κΈ°λ° μ€μ μ μ₯ - MySQLμ μ€μ μ μ₯
- ν΄λΌμ΄μΈνΈ μΈ‘ μνΈν - λ€νΈμν¬ μ μ‘ κ΅¬κ°μμλ μνΈν μ μ§
- JWT κΈ°λ° κ΄λ¦¬ API 보μ - κ΄λ¦¬μ© APIμ JWT μΈμ¦ μ μ©
- νλ‘ν κΈ°λ° μ€μ - νκ²½λ³ λ€λ₯Έ μ€μ
- REST API - μ€μ CRUD λ° νμ€ Spring Cloud Config μλν¬μΈνΈ
- μν λͺ¨λν°λ§ - Actuator μλν¬μΈνΈλ₯Ό ν΅ν λͺ¨λν°λ§
- Java 21+
- MySQL 8.0+
- Gradle 8.0+
νκ²½ λ³μ νμΌ(.env λλ μμ€ν
νκ²½λ³μ)μ λ€μμ μ€μ νμΈμ:
MYSQL_URL=mysql://localhost:3306/casper_config
MYSQL_USER=your_mysql_user
MYSQL_PASSWORD=your_mysql_password
ENCRYPT_KEY=your_encryption_key_here
ENCRYPT_SALT=your_encryption_salt_here
JWT_SECRET_KEY=your_jwt_secret_key_here
β οΈ λ³΄μ μ£Όμμ¬ν: μ€μ μνΈν ν€μ μνΈλ μΆ©λΆν 볡μ‘νκ³ κΈ΄ κ°μ μ¬μ©νμΈμ.
- MySQL λ°μ΄ν°λ² μ΄μ€ μμ±:
CREATE DATABASE casper_config;- μ€μ ν μ΄λΈ μμ±:
CREATE TABLE tbl_environment_configuration (
id BINARY(16) NOT NULL PRIMARY KEY,
application VARCHAR(20) NOT NULL,
profile VARCHAR(24) NOT NULL,
label VARCHAR(100) NOT NULL,
prop_key VARCHAR(100) NOT NULL,
prop_value TEXT NOT NULL
);- νκ²½ λ³μ μ€μ ν μ ν리μΌμ΄μ μ€ν:
./gradlew bootRun- μλ²κ°
http://localhost:8888μμ μ€νλ©λλ€.
POST http://localhost:8888/api/env
Content-Type: application/json
{
"application": "myapp",
"profile": "dev",
"label": "main",
"properties": {
"database.url": "jdbc:mysql://localhost:3306/myapp_dev",
"database.username": "dev_user",
"database.password": "my_secret_password"
}
}π‘ μλ μνΈν: νλ¬ΈμΌλ‘ μ μ‘λ λͺ¨λ κ°μ μλ²μμ μλμΌλ‘ μνΈνλμ΄ μ μ₯λ©λλ€.
{cipher}μ λμ¬λ₯Ό μλμΌλ‘ λΆμΌ νμκ° μμ΅λλ€.
GET http://localhost:8888/api/env/myapp/dev/mainμλ΅ μμ:
{
"database.url": "jdbc:mysql://localhost:3306/myapp_dev",
"database.username": "dev_user",
"database.password": "decrypted_password"
}GET http://localhost:8888/api/env/myapp/dev/main/database.urlDELETE http://localhost:8888/api/env/myapp/dev/main/database.urlDELETE http://localhost:8888/api/env/myapp/dev/mainGET http://localhost:8888/myapp/dev
GET http://localhost:8888/myapp/dev/mainμλ΅ μμ:
{
"name": "myapp",
"profiles": ["dev"],
"label": "main",
"version": null,
"state": null,
"propertySources": [
{
"name": "myapp-dev-main",
"source": {
"database.url": "jdbc:mysql://localhost:3306/myapp_dev",
"database.username": "dev_user",
"database.password": "decrypted_password"
}
}
]
}POST http://localhost:8888/encrypt
Content-Type: text/plain
my_secret_passwordμλ΅:
AQCKx8xPJ5N8C2YHnBWJ5+nMqpZ8XbWzEqK3...
POST http://localhost:8888/decrypt
Content-Type: text/plain
AQCKx8xPJ5N8C2YHnBWJ5+nMqpZ8XbWzEqK3...μλ΅:
my_secret_password
GET http://localhost:8888/actuator/healthGET http://localhost:8888/actuator/infoPOST http://localhost:8888/actuator/refresh-
μ€μ μ μ₯:
/api/envPOST μλν¬μΈνΈμ νλ¬ΈμΌλ‘ μ μ‘- μλ²μμ μλμΌλ‘ μνΈννμ¬ μ μ₯
-
μ€μ μ‘°ν:
- Spring Cloud Config νμ€ μλν¬μΈνΈ λλ 컀μ€ν μλν¬μΈνΈ μ¬μ©
- μνΈνλ κ°μ μλμΌλ‘ 볡νΈνλμ΄ λ°ν
-
μ€μ κ΄λ¦¬:
- νμμ DELETE μλν¬μΈνΈλ‘ μ€μ μμ
1. μ€μ μ μ₯ (νλ¬ΈμΌλ‘ μ μ‘)
POST /api/env
Content-Type: application/json
{
"application": "user-service",
"profile": "production",
"label": "v1.0",
"properties": {
"spring.datasource.url": "jdbc:mysql://prod-db:3306/userdb",
"spring.datasource.username": "prod_user",
"spring.datasource.password": "my_database_password",
"external.api.key": "secret_api_key_123",
"logging.level.root": "WARN"
}
}2. μ€μ μ‘°ν λ° νμΈ
GET /user-service/production/v1.0π‘ μλ²μμ μλμΌλ‘ λ―Όκ°ν κ°λ€μ μνΈννμ¬ μ μ₯νκ³ , μ‘°ν μμλ 볡νΈνλ κ°μ λ°νν©λλ€.
bootstrap.yml (μ€μ!):
encrypt:
key: ${ENCRYPT_KEY}
salt: ${ENCRYPT_SALT}
spring:
application:
name: myapp
profiles:
active: dev
config:
import: "configserver:http://localhost:8888"
cloud:
config:
fail-fast: true
retry:
initial-interval: 1000
max-attempts: 6νκ²½λ³μ μ€μ :
ENCRYPT_KEY=your_encryption_key_here
ENCRYPT_SALT=your_encryption_salt_hereπ‘ ν΄λΌμ΄μΈνΈμμ 볡νΈν: μλ²μμ μνΈνλ κ°μ μ μ‘νκ³ , ν΄λΌμ΄μΈνΈκ° μ§μ 볡νΈννμ¬ λ€νΈμν¬ λ³΄μμ κ°νν©λλ€.
κ΄λ¦¬μ© API μ¬μ© μ JWT ν ν°μ΄ νμν©λλ€:
1. JWT ν ν° λ°κΈ:
POST http://localhost:8888/auth/token
Content-Type: application/json
{
"username": "admin",
"password": "config-admin-2024"
}2. κ΄λ¦¬ API μ¬μ©:
POST http://localhost:8888/api/env
Authorization: Bearer <JWT_TOKEN>
Content-Type: application/json
{
"application": "myapp",
"profile": "dev",
"label": "main",
"properties": { ... }
}