IP Address Management μμ€ν μ λ°±μλ μλ²μ λλ€.
| λΆλ₯ | κΈ°μ |
|---|---|
| Language | Java 17 |
| Framework | Spring Boot 3.5.x |
| Database | MySQL 8.x (FULLTEXT κ²μ) |
| Session | Redis 7.x (Spring Session, Sentinel HA) |
| Auth | Keycloak (OAuth2/OIDC) |
| Realtime | SSE (Server-Sent Events, Redis Pub/Sub) |
| Docs | Swagger (springdoc-openapi) |
src/main/java/com/nhn/ipambackend/
βββ domain/
β βββ address/ # IP μ£Όμ κ΄λ¦¬ (13μ’
νμ
, TABLE_PER_CLASS μμ)
β βββ subnet/ # μλΈλ· κ΄λ¦¬ (κ³μΈ΅ ꡬ쑰, λΆν /λ³ν©/VLSM)
β βββ region/ # Region κ΄λ¦¬
β βββ user/ # μ¬μ©μ/μν κ΄λ¦¬ (Keycloak μ°λ)
β βββ favorite/ # μ¦κ²¨μ°ΎκΈ° (볡ν©ν€)
β βββ log/ # κ°μ¬ λ‘κ·Έ (μ€λ
μ· λ°©μ)
β βββ dashboard/ # λμ보λ ν΅κ³
β βββ search/ # ν΅ν© κ²μ (FULLTEXT, ν€μλ νμ
μλ κ°μ§)
β βββ manage/ # λ§μ€ν° λ°μ΄ν° κ΄λ¦¬ (Zone, SubnetType, DynamicAddressType, ESM, Service)
β βββ alertpanel/ # μλ¦Ό ν¨λ (CIλ²νΈ λλ½ κ°μ§)
β βββ sse/ # μ€μκ° μ΄λ²€νΈ (SSE + Redis Pub/Sub)
βββ global/
βββ base/ # κ³΅ν΅ μλ΅, μμΈ μ²λ¦¬, μν μ½λ
βββ config/ # μ€μ (Security, Redis, Async, WebClient λ±)
βββ util/ # μ νΈλ¦¬ν° (IPConverter, JsonUtil)
κ° λλ©μΈμ μλμ κ°μ ν¨ν€μ§ ꡬ쑰λ₯Ό λ°λ¦ λλ€:
domain/{λλ©μΈλͺ
}/
βββ controller/ # REST API 컨νΈλ‘€λ¬
βββ service/ # λΉμ¦λμ€ λ‘μ§ (interface + impl)
βββ repository/ # JPA Repository (+ Specification/QueryDSL)
βββ dto/
β βββ request/ # μμ² DTO
β βββ response/ # μλ΅ DTO
βββ entity/ # JPA μν°ν°
βββ enums/ # Enum μ μ (νμ μ)
- Java 17
- Docker & Docker Compose
- MySQL 8.x (λ‘컬 λλ Docker)
- Frontend νλ‘μ νΈ (
../ipam-frontend)
Keycloak μΈμ¦μ΄ λλ©μΈ κΈ°λ°μΌλ‘ λμνλ―λ‘ hosts νμΌ μμ μ΄ νμν©λλ€.
sudo vi /etc/hostsμλ λ΄μ© μΆκ°:
127.0.0.1 ipam.nhn.com
.env.local νμΌ νμΈ λ° μμ :
FRONTEND_URL=http://ipam.nhn.com # Frontend URL (hosts μ€μ νμ)
MYSQL_HOST=host.docker.internal # Docker λ΄μμ λ‘컬 MySQL μ κ·Ό
MYSQL_PORT=3306
MYSQL_DATABASE=mydb
MYSQL_USERNAME=root
MYSQL_PASSWORD=your_password
SPRING_PROFILES_ACTIVE=local # local νλ‘ν (ν
μ€νΈ λ°μ΄ν° μμ±)# Frontend + Backend + Redis μ 체 μ€ν
docker compose --env-file .env.local up -d --build
# λ‘κ·Έ νμΈ
docker compose logs -f backendIntelliJ/VSCodeμμ μ§μ μ€ν μ:
- Run Configurationμ νκ²½λ³μ μ€μ
- λλ
application-local.ymlμ¬μ©
./gradlew bootRun --args='--spring.profiles.active=local'| μλΉμ€ | URL |
|---|---|
| Frontend | http://ipam.nhn.com |
| Backend API | http://ipam.nhn.com/api |
| Swagger UI | http://ipam.nhn.com/api/swagger-ui/index.html |
| Health Check | http://ipam.nhn.com/api/actuator/health |
# Git pull + ν
μ€νΈ + μ΄λ―Έμ§ λΉλ + μλΉμ€ μμ
./deploy.sh rebuild
# ν
μ€νΈ 건λλ°κ³ λ°°ν¬ (κΈν λ)
./deploy.sh rebuild --skip-test
# ν
μ€νΈλ§ μ€ν
./deploy.sh test
# μλΉμ€ μν νμΈ
./deploy.sh status
# λ‘κ·Έ νμΈ
./deploy.sh logs
# μλΉμ€ μ€μ§
./deploy.sh down# μ΄μ€ν λͺ¨λλ‘ λ°°ν¬
./deploy.sh rebuild --secondary
# μ΄μ€ν μλ² μν νμΈ
./deploy.sh status --secondarySwagger UI: /api/swagger-ui.html
| λλ©μΈ | Base URL | μ£Όμ κΈ°λ₯ |
|---|---|---|
| Subnet | /api/subnets |
CRUD, λΆν (κ· λ±/VLSM), λ³ν©, Supernet, Import, λ§΅, μ¬μ©λ, 곡μΈIP λμ보λ |
| Address | /api/addresses |
μ‘°ν, μμ½/μ·¨μ(κ°λ³/λ²μ), μμ½ κ°λ₯ μ¬λΆ, λμ μ£Όμ μμ± |
| Region | /api/regions |
Region CRUD |
| User | /api/users |
μν κ΄λ¦¬, μμ± κ΄λ¦¬, λ²ν¬ μν λ³κ²½ |
| Favorite | /api/favorites |
μλΈλ· μ¦κ²¨μ°ΎκΈ° μΆκ°/μ κ±°/μ‘°ν |
| Log | /api/logs |
κ°μ¬ λ‘κ·Έ μ‘°ν, CSV λ΄λ³΄λ΄κΈ° |
| Search | /api/search |
ν΅ν© κ²μ, IP Range, ESM, κ²μ κΈ°λ‘, λ©νλ°μ΄ν° |
| Dashboard | /api/dashboard |
λμ보λ ν΅κ³ |
| Manage | /api/zones, /api/subnet-types, /api/dynamic-address-types |
λ§μ€ν° λ°μ΄ν° κ΄λ¦¬ |
| Alert Panel | /api/alert-panel |
ci_no λλ½ μλ¦Ό |
| SSE | /api/sse |
μ€μκ° μ΄λ²€νΈ μ€νΈλ¦Ό |
# μ 체 ν
μ€νΈ
./gradlew test
# λλ©μΈλ³ ν
μ€νΈ
./gradlew test --tests "com.nhn.ipambackend.domain.subnet.*"
./gradlew test --tests "com.nhn.ipambackend.domain.address.*"
./gradlew test --tests "com.nhn.ipambackend.domain.search.*"
./gradlew test --tests "com.nhn.ipambackend.domain.favorite.*"
./gradlew test --tests "com.nhn.ipambackend.domain.region.*"
./gradlew test --tests "com.nhn.ipambackend.domain.log.*"
./gradlew test --tests "com.nhn.ipambackend.domain.dashboard.*"
./gradlew test --tests "com.nhn.ipambackend.domain.user.*"
./gradlew test --tests "com.nhn.ipambackend.domain.manage.*"| λλ©μΈ | ν μ€νΈ νμΌ |
|---|---|
| Subnet | SubnetServiceTest, SubnetEntityTest |
| Address | AddressServiceTest, AddressEntityTest |
| Search | SearchServiceTest |
| Favorite | FavoriteServiceTest |
| Region | RegionServiceTest |
| Log | LogServiceTest, AuditLogServiceTest |
| Dashboard | DashboardServiceTest |
| User | UserServiceTest, RoleTest |
| Manage | DynamicAddressTypeServiceTest |
.cursor/rules/ λλ ν 리μ λλ©μΈλ³ κ°λ° κ°μ΄λκ° μμ΅λλ€.
| νμΌ | μ€λͺ |
|---|---|
.overview.mdc |
νλ‘μ νΈ μ 체 ꡬ쑰, μ½λ© 컨벀μ |
subnets.mdc |
μλΈλ· λλ©μΈ (κ³μΈ΅ ꡬ쑰, λΆν /λ³ν©/VLSM, Import) |
addresses.mdc |
μ£Όμ λλ©μΈ (13μ’ νμ , TABLE_PER_CLASS, μμ½/μ·¨μ) |
search.mdc |
κ²μ λλ©μΈ (FULLTEXT, ν€μλ μλ κ°μ§, ESM) |
regions.mdc |
Region λλ©μΈ |
logs.mdc |
κ°μ¬ λ‘κ·Έ (μ€λ μ· λ°©μ) |
favorites.mdc |
μ¦κ²¨μ°ΎκΈ° (볡ν©ν€) |
Cursorμμ ν΄λΉ λλ©μΈ νμΌ μμ μ μλμΌλ‘ κ·μΉμ΄ μ μ©λ©λλ€.
| νλ‘ν | μ©λ | νΉμ§ |
|---|---|---|
local |
λ‘컬 κ°λ° | ν μ€νΈ λ°μ΄ν° μλ μμ±, SQL λ‘κΉ |
prod |
μ΄μ (Primary) | SQL λ‘κΉ λΉνμ±ν, Redis Sentinel |
| νμΌ | μ€λͺ |
|---|---|
.env.local |
λ‘컬 κ°λ° νκ²½λ³μ |
.env.prod |
μ΄μ νκ²½λ³μ (Primary) |
.env.secondary |
μ΄μ νκ²½λ³μ (Secondary, μ΄μ€ν) |
docker-compose.yml |
Primary: Frontend + Backend + Redis Master + Sentinel |
docker-compose.secondary.yml |
Secondary: μ΄μ€ν κ΅¬μ± |
deploy.sh |
ν΅ν© λ°°ν¬ μ€ν¬λ¦½νΈ (up, down, restart, rebuild, logs, status, test) |
| νμΌ | μ€λͺ |
|---|---|
db/init.sql |
μ΄κΈ° μ€ν€λ§/λ°μ΄ν° |
db/init-logs.sql |
λ‘κ·Έ ν μ΄λΈ μ΄κΈ°ν |
db/alias.sql |
κ²μ Alias λ°μ΄ν° |
db/preset.sql |
κ²μ Preset λ°μ΄ν° |
db/migration-fulltext-search.sql |
FULLTEXT κ²μ μΈλ±μ€ λ§μ΄κ·Έλ μ΄μ |
db/migration-roles.sql |
μν (Roles) λ§μ΄κ·Έλ μ΄μ |
db/migration-log-server-ip.sql |
λ‘κ·Έ μλ² IP λ§μ΄κ·Έλ μ΄μ |
db/migration-dynamic-address-type.sql |
λμ μ£Όμ νμ λ§μ΄κ·Έλ μ΄μ |
/etc/hostsμipam.nhn.comμ€μ νμΈFRONTEND_URLμ΄http://ipam.nhn.comμΈμ§ νμΈ- Keycloak ν΄λΌμ΄μΈνΈ μ€μ μμ Redirect URI νμΈ
MYSQL_HOSTλ₯Ό host.docker.internalλ‘ μ€μ (Mac/Windows)
SPRING_PROFILES_ACTIVE=local μ€μ νμΈ