User Serviceλ API Gateway μν€ν μ²μμ μ¬μ©μ μΈμ¦ λ° κ΄λ¦¬ κΈ°λ₯μ λ΄λΉνλ λ§μ΄ν¬λ‘μλΉμ€μ λλ€.
- API Gateway: JWT ν ν° κ²μ¦, νμ±, ν€λ μΆκ°
- User Service: ν ν° μμ±, μ¬μ©μ κ΄λ¦¬, λ‘κ·Έμμ μ²λ¦¬
- μ¬μ©μ νμκ°μ /λ‘κ·ΈμΈ
- JWT ν ν° λ°κΈ (μ‘μΈμ€ ν ν° + 리νλ μ ν ν°)
- μ¬μ©μ νλ‘ν μ‘°ν
- λ‘κ·Έμμ μ²λ¦¬ (Redis κΈ°λ° ν ν° λ¬΄ν¨ν)
# env.example νμΌμ .envλ‘ λ³΅μ¬
cp env.example .env
# .env νμΌμμ μ€μ κ°μΌλ‘ μμ
# νΉν JWT μν¬λ¦Ώ ν€λ λ°λμ λ³κ²½ν΄μΌ ν©λλ€!# κ°λ° νκ²½μ© μν¬λ¦Ώ ν€ μμ± (Base64 μΈμ½λ©)
echo -n "your-dev-secret-key-here-minimum-32-characters-long" | base64
# μ΄μ νκ²½μ© μν¬λ¦Ώ ν€ μμ± (Base64 μΈμ½λ©)
echo -n "your-production-secret-key-here-minimum-32-characters-long" | base64
# μμ±λ ν€λ₯Ό .env νμΌμ JWT_SECRET_KEY_DEV, JWT_SECRET_KEY_PRODμ μ€μ # Docker Composeλ‘ MySQL, Redis μ€ν
docker-compose up -d
# μλΉμ€ μν νμΈ
docker-compose ps# .env νμΌμ μλμΌλ‘ λ‘λνκ³ μ ν리μΌμ΄μ
μ€ν
./run-with-env.sh# νκ²½ λ³μλ₯Ό μλμΌλ‘ λ‘λ ν μ€ν
export $(cat .env | grep -v '^#' | xargs) && cd user-service && ./gradlew bootRun- VSCode: F5 ν€ λλ Run and Debug ν¨λμμ "UserServiceApplication" μ ν
- IntelliJ IDEA: Run/Debug Configurationsμμ "UserServiceApplication" μ ν
π‘ μ°Έκ³ : IDE μ€μ μμ .env νμΌμ΄ μλμΌλ‘ λ‘λλλλ‘ κ΅¬μ±λμ΄ μμ΅λλ€.
# KeyTest ν΄λμ€λ‘ νκ²½ λ³μκ° μ λλ‘ λ‘λλλμ§ νμΈ
export $(cat .env | grep -v '^#' | xargs) && java -cp user-service/build/classes/java/main com.deefacto.user_service.dummy.KeyTest| λ³μλͺ | μ€λͺ | κΈ°λ³Έκ° | μμ |
|---|---|---|---|
SERVER_PORT |
μλ² ν¬νΈ | 8081 | 8081 |
DB_HOST |
MySQL νΈμ€νΈ | localhost | localhost |
DB_PORT |
MySQL ν¬νΈ | 3306 | 3306 |
DB_NAME |
λ°μ΄ν°λ² μ΄μ€ μ΄λ¦ | deefacto_db | deefacto_db |
DB_USERNAME |
λ°μ΄ν°λ² μ΄μ€ μ¬μ©μλͺ | deefacto | deefacto |
DB_PASSWORD |
λ°μ΄ν°λ² μ΄μ€ λΉλ°λ²νΈ | - | your_password |
REDIS_HOST |
Redis νΈμ€νΈ | localhost | localhost |
REDIS_PORT |
Redis ν¬νΈ | 6379 | 6379 |
JWT_SECRET_KEY_DEV |
κ°λ° νκ²½ JWT μν¬λ¦Ώ ν€ (Base64) | - | your_secret_key_dev |
JWT_SECRET_KEY_PROD |
μ΄μ νκ²½ JWT μν¬λ¦Ώ ν€ (Base64) | - | your_secret_key_prod |
| λ³μλͺ | μ€λͺ | κΈ°λ³Έκ° |
|---|---|---|
JWT_REFRESH_TOKEN_EXPIRES_IN |
리νλ μ ν ν° λ§λ£ μκ° (μ΄) | 86400 (24μκ°) |
JWT_ACCESS_TOKEN_EXPIRES_IN |
μ‘μΈμ€ ν ν° λ§λ£ μκ° (μ΄) | 900 (15λΆ) |
SPRING_PROFILES_ACTIVE |
νμ± νλ‘ν | dev |
FLYWAY_ENABLED |
Flyway νμ±ν μ¬λΆ | false |
LOGGING_LEVEL_USER_SERVICE |
λ‘κ·Έ λ 벨 | info |
| λ³μλͺ | μ€λͺ | κΈ°λ³Έκ° |
|---|---|---|
DEV_SHOW_SQL |
SQL 쿼리 λ‘κ·Έ μΆλ ₯ | true |
DEV_FORMAT_SQL |
SQL ν¬λ§·ν | true |
DEV_HIBERNATE_DDL_AUTO |
Hibernate DDL μλ μμ± | update |
.vscode/settings.json: .env νμΌ μλ λ‘λ μ€μ .vscode/launch.json: λλ²κΉ μ .env νμΌ μ¬μ© μ€μ
.idea/workspace.xml: μ€ν μ€μ μ .env νμΌ μ°κ²°
application.yml: .env νμΌ μλ λ‘λ μ€μ ν¬ν¨
POST /auth/register- μ¬μ©μ νμκ°μPOST /auth/login- μ¬μ©μ λ‘κ·ΈμΈ (JWT ν ν° λ°κΈ)
POST /auth/logout- μ¬μ©μ λ‘κ·ΈμμGET /user/info/search?- μ¬μ©μ νλ‘ν μ‘°νPOST /user/delete- νμ μμ POST /user/info/password- λΉλ°λ²νΈ λ³κ²½
GET /actuator/health- μ ν리μΌμ΄μ μν νμΈ
| μ ν | URL |
|---|---|
| Swagger | http://localhost:8081/swagger-ui.html |
| Actuator | http://localhost:8081/actuator/health |
| Grafana | (μ΄μ νκ²½) νκ²½ λ³μ μ°Έμ‘° |
- Framework: Spring Boot 3.5.4
- Language: Java 17 (Amazon Corretto)
- Database: MySQL 8.0
- Cache: Redis 7
- Security: Spring Security + JWT
- Build Tool: Gradle
- Container: Docker & Docker Compose
- Environment: .env νμΌ μ§μ (IDE μλ λ‘λ)
- MSA: λ§μ΄ν¬λ‘μλΉμ€ μν€ν μ²
- CI/CD: Jenkins + Docker + ArgoCD (μμ )
Backend-UserService/
βββ user-service/ # Spring Boot μ ν리μΌμ΄μ
β βββ src/main/java/com/deefacto/user_service/
β β βββ config/ # μ€μ ν΄λμ€
β β βββ controller/ # REST API 컨νΈλ‘€λ¬
β β βββ service/ # λΉμ¦λμ€ λ‘μ§
β β βββ domain/ # λλ©μΈ λͺ¨λΈ
β β β βββ Entitiy/ # JPA μν°ν°
β β β βββ Enum/ # μ΄κ±°ν
β β β βββ dto/ # λ°μ΄ν° μ μ‘ κ°μ²΄
β β β βββ repository/ # λ°μ΄ν° μ κ·Ό κ³μΈ΅
β β βββ secret/jwt/ # JWT κ΄λ ¨ ν΄λμ€
β β βββ common/ # κ³΅ν΅ ν΄λμ€
β β βββ advice/ # μμΈ μ²λ¦¬ λ° κ²μ¦
β β βββ dummy/ # ν
μ€νΈμ© ν΄λμ€
β βββ src/main/resources/
β β βββ application.yml # κΈ°λ³Έ μ€μ
β β βββ application-dev.yml # κ°λ° νκ²½ μ€μ
β β βββ application-prod.yml # μ΄μ νκ²½ μ€μ
β β βββ db/migration/ # λ°μ΄ν°λ² μ΄μ€ λ§μ΄κ·Έλ μ΄μ
β βββ build.gradle # λΉλ μ€μ
βββ docker-compose.yml # μΈνλΌ μλΉμ€ μ€μ
βββ env.example # νκ²½ λ³μ μμ
βββ .env # μ€μ νκ²½ λ³μ (gitignoreλ¨)
βββ run-with-env.sh # νκ²½ λ³μ λ‘λ μ€ν¬λ¦½νΈ
βββ .vscode/ # VSCode μ€μ
βββ .idea/ # IntelliJ IDEA μ€μ
βββ README.md # νλ‘μ νΈ λ¬Έμ
- νκ²½ λ³μ μ¬μ©: λ―Όκ°ν μ 보λ νκ²½ λ³μλ‘ κ΄λ¦¬
- JWT μν¬λ¦Ώ ν€:
- μ΄μ νκ²½μμλ κ°λ ₯ν λλ€ ν€ μ¬μ©
- Base64 μΈμ½λ© νμ
- μ΅μ 32μ μ΄μ κΆμ₯
- λ°μ΄ν°λ² μ΄μ€ λΉλ°λ²νΈ: νκ²½λ³λ‘ λ€λ₯Έ λΉλ°λ²νΈ μ¬μ©
- CORS μ€μ : νμ©λ λλ©μΈλ§ μ κ·Ό κ°λ₯νλλ‘ μ€μ
- .env νμΌ: μ λ Gitμ 컀λ°νμ§ μμ
- μΈμ¦μ νμΌ:
src/main/resources/certs/λ± λ―Όκ° νμΌμ gitμ μ»€λ° κΈμ§ - νκ²½ λ³μ/λΉλ°ν€: μ΄μ μλ² λλ CI/CDμμ μμ νκ² μ£Όμ
-
νκ²½ λ³μκ° nullλ‘ λμ€λ κ²½μ°:
# .env νμΌμ΄ μ λλ‘ λ‘λλλμ§ νμΈ source .env && echo $JWT_SECRET_KEY_DEV # λλ μ€ν¬λ¦½νΈ μ¬μ© ./run-with-env.sh
-
ν¬νΈ μΆ©λ:
SERVER_PORTνκ²½ λ³μλ‘ ν¬νΈ λ³κ²½ -
λ°μ΄ν°λ² μ΄μ€ μ°κ²° μ€ν¨: Docker Compose μλΉμ€ μν νμΈ
-
Redis μ°κ²° μ€ν¨: Redis 컨ν μ΄λ μν νμΈ
# μ ν리μΌμ΄μ
λ‘κ·Έ
./gradlew bootRun
# Docker 컨ν
μ΄λ λ‘κ·Έ
docker-compose logs mysql
docker-compose logs redis- λλ©μΈ λͺ¨λΈ μ μ (
domain/ν¨ν€μ§) - μλΉμ€ λ‘μ§ κ΅¬ν (
service/ν¨ν€μ§) - REST API μλν¬μΈνΈ μΆκ° (
controller/ν¨ν€μ§) - ν μ€νΈ μ½λ μμ±
- κ°λ° νκ²½:
application-dev.ymlμ¬μ© - μ΄μ νκ²½:
application-prod.ymlμ¬μ© - νκ²½ λ³μ:
.envνμΌ λλ μμ€ν νκ²½ λ³μ μ¬μ©
- λͺ¨λ μ€μ μ
application.ymlνμΌ μ¬μ© (.properties β κΈμ§) - μλ‘μ΄ μ€μ ν΄λμ€λ
XXConfig.javaλ€μ΄λ° μ¬μ©
μ:MqttConfig.java,KafkaConfig.java
- λͺ¨λ λ―Όκ° μ 보λ νκ²½ λ³μ λλ
.envνμΌλ‘ κ΄λ¦¬ - μ£Όμ νκ²½ λ³μ μμ:
AWS_IAM_ACCESS_KEY,AWS_IAM_SECRET_KEYGRAFANA_URL_OUTERspring.datasource.*,spring.kafka.*λ±
- ν
μ€νΈ μ½λλ
src/test/javaλλ ν°λ¦¬μ μμ± - JUnit 5 κΈ°λ° μ λ/ν΅ν© ν μ€νΈ ꡬμ±
[type] | sprint | JIRA-KEY | κΈ°λ₯ μμ½ | λ΄λΉμ- type: feat, fix, docs, config, refactor, test, chore, style λ±
- sprint: sprint0, sprint1, ...
- JIRA-KEY: JIRA μ΄μ λ²νΈ λλ μμ
- κΈ°λ₯ μμ½: ν΅μ¬ λ³κ²½ λ΄μ©
- λ΄λΉμ: μ€λͺ λλ λλ€μ
feat | sprint0 | μμ | μΌμ λ±λ‘ API ꡬν | KIM
feat | sprint0 | IOT-123 | μΌμ λ±λ‘ API ꡬν | KIM
fix | sprint1 | IOT-210 | MQTT μμ μ€ν¨ μμΈ μ²λ¦¬ | RAFA
config | sprint0 | IOT-001 | H2 DB μ€μ μΆκ° | MO
docs | sprint1 | IOT-999 | README μ΄μ μμ± | JONE
git commit -m "feat | sprint1 | IOT-112 | μμ
μ μΌμ μ‘°ν API μΆκ° | KIM"
git commit -m "fix | sprint0 | IOT-009 | H2 μ°κ²° μ€λ₯ μμ | RAFA"
git commit -m "config | sprint0 | IOT-000 | Spring Boot 3.4.4 μ μ© | MO"
git commit -m "chore | sprint1 | IOT-999 | μ»€λ° μ»¨λ²€μ
README μ 리 | JONE"- Jenkins λ° ArgoCD μ°λμ
Jenkinsfileμ°Έμ‘° - μ κ· μ€μ νμΌ μΆκ° μ λ°λμ
XXConfig.javaλ€μ΄λ° μ μ§
μ΄ νλ‘μ νΈλ MIT λΌμ΄μ μ€ νμ λ°°ν¬λ©λλ€.