본문으로 건너뛰기

ElastiCORE Automotive 도메인 샘플 모델

자동차업계를 위한 ElastiCORE 기반 엔터티 모델 설계 가이드입니다. Salesforce Automotive Cloud 데이터 모델을 참고하여 실무에서 바로 활용 가능한 모델을 제시합니다.

📋 Domain Overview

Core Business Entities

  • Vehicle (차량): 차량 기본 정보 및 사양 관리
  • Vehicle Definition (차량 정의): 차량 모델 및 사양 정의
  • Asset (자산): 차량 자산 관리 및 추적
  • Appraisal (감정평가): 차량 가치 평가 및 감정
  • Service Record (서비스 이력): 차량 정비 및 서비스 이력
  • Warranty (보증): 차량 보증 관리
  • Inventory (재고): 부품 및 차량 재고 관리

🏗️ Entity Model Definitions

1. Vehicle (차량)

entity:
Vehicle:
meta: entity @expose(50) @audited @pageable @extend(AuditEntity) @table(name="VEHICLE")
fields:
vehicleId: long @id @sequence @search(eq) -- 차량ID
vin: string(17)! @search(eq) @unique -- 차대번호 (VIN)
licensePlate: string(20) @search(like) @unique -- 차량번호
vehicleDefinitionId: long! @search(eq) @ref(VehicleDefinition.id) -- 차량정의ID
ownerId: long @search(eq) @ref(Contact.id) -- 소유자ID
dealerId: long @search(eq) @ref(Dealer.id) -- 딜러ID
vehicleStatus: string(20)! @search(eq) -- 차량상태 (NEW, USED, CERTIFIED, DAMAGED, SOLD)
condition: string(20) @search(eq) -- 차량상태등급 (EXCELLENT, GOOD, FAIR, POOR)
mileage: int @search(between) -- 주행거리 (km)
engineNumber: string(50) @search(eq) -- 엔진번호
fuelType: string(20) @search(eq) -- 연료종류 (GASOLINE, DIESEL, HYBRID, ELECTRIC, HYDROGEN)
transmission: string(20) @search(eq) -- 변속기 (MANUAL, AUTOMATIC, CVT)
exteriorColor: string(30) @search(eq) -- 외부색상
interiorColor: string(30) @search(eq) -- 내부색상
manufactureDate: date @search(between) -- 제조일
firstRegistrationDate: date @search(between) -- 최초등록일
purchaseDate: date @search(between) -- 구매일
purchasePrice: bigdecimal(12.2) @search(between) -- 구매가격
currentValue: bigdecimal(12.2) @search(between) -- 현재가치
lastServiceDate: date @search(between) -- 최종정비일
nextServiceDate: date @search(between) -- 다음정비예정일
insurancePolicyNumber: string(50) @search(like) -- 보험증권번호
notes: text @search(like) -- 특이사항
isActive: boolean @search(eq) @default(true) -- 활성상태

2. Vehicle Definition (차량 정의)

entity:
VehicleDefinition:
meta: entity @expose(50) @table(name="VEHICLE_DEFINITION")
fields:
definitionId: long @id @sequence @search(eq) -- 차량정의ID
make: string(50)! @search(like) -- 제조사 (HYUNDAI, KIA, BMW, MERCEDES)
model: string(50)! @search(like) -- 모델명
trim: string(30) @search(like) -- 트림명
modelYear: int! @search(between) -- 연식
vehicleType: string(20)! @search(eq) -- 차량유형 (SEDAN, SUV, HATCHBACK, COUPE, TRUCK, MOTORCYCLE)
bodyStyle: string(20) @search(eq) -- 차체형태
engineSize: bigdecimal(3.1) @search(between) -- 엔진배기량 (리터)
horsepower: int @search(between) -- 마력
torque: int @search(between) -- 토크 (Nm)
fuelEfficiency: bigdecimal(4.1) @search(between) -- 연비 (km/L)
seatingCapacity: int @search(eq) -- 승차정원
driveType: string(10) @search(eq) -- 구동방식 (FWD, RWD, AWD, 4WD)
msrp: bigdecimal(12.2) @search(between) -- 제조사 권장 소비자 가격
length: int @search(between) -- 전장 (mm)
width: int @search(between) -- 전폭 (mm)
height: int @search(between) -- 전고 (mm)
wheelbase: int @search(between) -- 축거 (mm)
curbWeight: int @search(between) -- 공차중량 (kg)
maxWeight: int @search(between) -- 최대적재중량 (kg)
isActive: boolean @search(eq) @default(true) -- 생산중 여부
productionStartYear: int @search(between) -- 생산시작연도
productionEndYear: int @search(between) -- 생산종료연도

3. Vehicle Appraisal (차량 감정평가)

entity:
VehicleAppraisal:
meta: entity @expose(50) @audited @pageable @extend(AuditEntity) @table(name="VEHICLE_APPRAISAL")
fields:
appraisalId: long @id @sequence @search(eq) -- 감정평가ID
appraisalNumber: string(50)! @search(like) @unique -- 감정평가번호
vehicleId: long! @search(eq) @ref(Vehicle.id) -- 차량ID
appraisalType: string(20)! @search(eq) -- 감정유형 (PURCHASE, SALE, INSURANCE, LOAN, TRADE_IN)
appraisalStatus: string(20)! @search(eq) -- 감정상태 (REQUESTED, IN_PROGRESS, COMPLETED, CANCELLED)
requestDate: datetime! @search(between) -- 신청일시
completedDate: datetime @search(between) -- 완료일시
appraiserId: long @search(eq) @ref(Appraiser.id) -- 감정사ID
requesterId: long! @search(eq) @ref(Contact.id) -- 신청자ID
marketValue: bigdecimal(12.2) @search(between) -- 시장가치
tradeInValue: bigdecimal(12.2) @search(between) -- 하취가격
retailValue: bigdecimal(12.2) @search(between) -- 소매가격
estimatedMileage: int @search(between) -- 감정시 주행거리
overallCondition: string(20) @search(eq) -- 전반적 상태 (EXCELLENT, GOOD, FAIR, POOR)
exteriorCondition: string(20) @search(eq) -- 외관상태
interiorCondition: string(20) @search(eq) -- 내부상태
mechanicalCondition: string(20) @search(eq) -- 기계적 상태
accidentHistory: boolean @search(eq) @default(false) -- 사고이력 여부
floodDamage: boolean @search(eq) @default(false) -- 침수이력 여부
modifications: text @search(like) -- 개조사항
remarks: text @search(like) -- 감정의견
photos: text -- 사진경로 (JSON 배열)

4. Service Record (서비스 이력)

entity:
ServiceRecord:
meta: entity @expose(50) @pageable @table(name="SERVICE_RECORD")
fields:
serviceId: long @id @sequence @search(eq) -- 서비스ID
serviceNumber: string(50)! @search(like) @unique -- 서비스번호
vehicleId: long! @search(eq) @ref(Vehicle.id) -- 차량ID
serviceCenterId: long! @search(eq) @ref(ServiceCenter.id) -- 서비스센터ID
serviceType: string(30)! @search(eq) -- 서비스유형 (MAINTENANCE, REPAIR, INSPECTION, WARRANTY, RECALL)
serviceDate: date! @search(between) -- 서비스일자
mileageAtService: int @search(between) -- 서비스시 주행거리
workDescription: text! @search(like) -- 작업내용
partsUsed: text -- 사용부품 (JSON 배열)
laborCost: bigdecimal(10.2) @search(between) -- 공임비
partsCost: bigdecimal(10.2) @search(between) -- 부품비
totalCost: bigdecimal(10.2)! @search(between) -- 총비용
warranty: boolean @search(eq) @default(false) -- 보증작업 여부
warrantyPeriod: int @search(between) -- 보증기간 (개월)
technicianId: long @search(eq) @ref(Technician.id) -- 담당기사ID
customerSatisfaction: int @search(between) -- 고객만족도 (1-5)
nextServiceDate: date @search(between) -- 다음서비스예정일
notes: text @search(like) -- 비고

5. Vehicle Warranty (차량 보증)

entity:
VehicleWarranty:
meta: entity @expose(50) @table(name="VEHICLE_WARRANTY")
fields:
warrantyId: long @id @sequence @search(eq) -- 보증ID
vehicleId: long! @search(eq) @ref(Vehicle.id) -- 차량ID
warrantyType: string(30)! @search(eq) -- 보증유형 (BASIC, POWERTRAIN, BUMPER_TO_BUMPER, EXTENDED)
warrantyProvider: string(100)! @search(like) -- 보증제공자 (제조사, 딜러, 보험회사)
startDate: date! @search(between) -- 보증시작일
endDate: date! @search(between) -- 보증종료일
mileageLimit: int @search(between) -- 보증거리한계 (km)
isActive: boolean @search(eq) @default(true) -- 유효여부
coverageDetails: text @search(like) -- 보증범위 상세
deductible: bigdecimal(8.2) @search(between) -- 자기부담금
maxClaim: bigdecimal(10.2) @search(between) -- 최대청구금액
termsAndConditions: text -- 약관

6. Vehicle Inventory (차량 재고)

entity:
VehicleInventory:
meta: entity @expose(50) @pageable @table(name="VEHICLE_INVENTORY")
fields:
inventoryId: long @id @sequence @search(eq) -- 재고ID
vehicleId: long! @search(eq) @ref(Vehicle.id) -- 차량ID
dealerId: long! @search(eq) @ref(Dealer.id) -- 딜러ID
stockNumber: string(50)! @search(like) @unique -- 재고번호
location: string(50) @search(like) -- 보관위치
acquisitionDate: date! @search(between) -- 입고일
acquisitionType: string(20)! @search(eq) -- 입고유형 (NEW, TRADE_IN, AUCTION, LEASE_RETURN)
acquisitionCost: bigdecimal(12.2) @search(between) -- 취득원가
listPrice: bigdecimal(12.2) @search(between) -- 판매가격
marketPrice: bigdecimal(12.2) @search(between) -- 시장가격
daysInInventory: int @search(between) -- 재고보유일수
status: string(20)! @search(eq) -- 재고상태 (AVAILABLE, RESERVED, SOLD, PENDING)
reservedDate: date @search(between) -- 예약일
soldDate: date @search(between) -- 판매일
soldPrice: bigdecimal(12.2) @search(between) -- 판매가격
salespersonId: long @search(eq) @ref(Salesperson.id) -- 영업담당자ID
isDisplayVehicle: boolean @search(eq) @default(false) -- 전시차량 여부
notes: text @search(like) -- 비고

7. Parts Inventory (부품 재고)

entity:
PartsInventory:
meta: entity @expose(50) @pageable @table(name="PARTS_INVENTORY")
fields:
partId: long @id @sequence @search(eq) -- 부품ID
partNumber: string(50)! @search(like) @unique -- 부품번호
partName: string(100)! @search(like) -- 부품명
category: string(30)! @search(eq) -- 부품분류 (ENGINE, TRANSMISSION, BRAKE, SUSPENSION, ELECTRICAL)
manufacturer: string(50) @search(like) -- 제조사
compatibleMakes: string(200) -- 호환차종 (JSON 배열)
unitPrice: bigdecimal(10.2)! @search(between) -- 단가
cost: bigdecimal(10.2) @search(between) -- 원가
quantityOnHand: int! @search(between) -- 현재고량
minimumStock: int @search(between) @default(0) -- 최소재고량
maximumStock: int @search(between) -- 최대재고량
reorderPoint: int @search(between) -- 재주문점
supplierId: long @search(eq) @ref(Supplier.id) -- 공급업체ID
location: string(30) @search(like) -- 보관위치
isActive: boolean @search(eq) @default(true) -- 활성상태
lastOrderDate: date @search(between) -- 최종주문일
lastReceivedDate: date @search(between) -- 최종입고일

🔗 Relational Design Patterns

1:N 관계

  • VehicleDefinition (1) ↔ (N) Vehicle
  • Vehicle (1) ↔ (N) VehicleAppraisal
  • Vehicle (1) ↔ (N) ServiceRecord
  • Vehicle (1) ↔ (N) VehicleWarranty
  • Vehicle (1) ↔ (1) VehicleInventory

N:M 관계 (중간 테이블 활용)

  • PartsInventoryServiceRecord (ServiceParts 중간테이블)
  • VehiclePartsInventory (CompatibleParts 중간테이블)

📊 DTO Design Examples

VehicleSearchDTO

dto:
VehicleSearchDTO:
meta: dto @searchable @template('SEARCH')
fields:
vin: string @search(eq) -- 차대번호
licensePlate: string @search(like) -- 차량번호
make: string @search(like) @param('vehicleDefinition.make') -- 제조사
model: string @search(like) @param('vehicleDefinition.model') -- 모델명
modelYearFrom: int @search(gte) @param('vehicleDefinition.modelYear') -- 연식(시작)
modelYearTo: int @search(lte) @param('vehicleDefinition.modelYear') -- 연식(종료)
vehicleStatus: string @search(eq) -- 차량상태
mileageMax: int @search(lte) @param('mileage') -- 최대주행거리

AppraisalSummaryDTO

dto:
AppraisalSummaryDTO:
meta: dto
fields:
appraisalNumber: string -- 감정평가번호
vin: string -- 차대번호
vehicleInfo: string -- 차량정보 (make model year)
appraisalType: string -- 감정유형
marketValue: bigdecimal(12.2) -- 시장가치
requestDate: datetime -- 신청일시
completedDate: datetime -- 완료일시

📚 Repository Design Patterns

Complex Search Queries

repository:
Vehicle:
methods:
- id: findVehiclesByMakeAndYear
params:
make: string
yearFrom: int
yearTo: int
return: List<Vehicle>
nativeQuery: true
query: |
SELECT v.* FROM VEHICLE v
JOIN VEHICLE_DEFINITION vd ON v.vehicle_definition_id = vd.definition_id
WHERE vd.make = :make AND vd.model_year BETWEEN :yearFrom AND :yearTo
ORDER BY vd.model_year DESC, v.mileage ASC

- id: getServiceHistoryByVehicle
params:
vehicleId: long
return: List<ServiceHistoryDTO>
nativeQuery: true
query: |
SELECT sr.*, sc.center_name
FROM SERVICE_RECORD sr
JOIN SERVICE_CENTER sc ON sr.service_center_id = sc.center_id
WHERE sr.vehicle_id = :vehicleId
ORDER BY sr.service_date DESC

- id: getInventoryValueByDealer
params:
dealerId: long
return: InventoryStatsDTO
nativeQuery: true
query: |
SELECT
COUNT(*) as vehicle_count,
AVG(list_price) as avg_price,
SUM(list_price) as total_value,
AVG(days_in_inventory) as avg_days
FROM VEHICLE_INVENTORY
WHERE dealer_id = :dealerId AND status = 'AVAILABLE'

🎯 Best Practice Guidelines

1. Data Integrity

  • VIN은 17자리 고유값으로 반드시 관리
  • 차량정의와 차량은 1:N 관계로 정규화
  • 금액 필드는 bigdecimal 타입으로 정밀도 확보

2. Search Optimization

  • VIN, 차량번호는 정확일치 검색 (@search(eq))
  • 제조사, 모델명은 부분일치 검색 (@search(like))
  • 날짜, 주행거리, 가격은 범위검색 (@search(between))

3. 비즈니스 로직

  • 차량상태는 명확한 워크플로우로 관리
  • 서비스 이력은 시계열 데이터로 정렬 저장
  • 재고 회전율 계산을 위한 일자 정보 필수

4. Performance Considerations

  • 대용량 차량 데이터 조회 시 페이징 처리
  • 자주 조회되는 조건에 복합 인덱스 구성
  • 통계 정보는 별도 집계 테이블 고려

5. Scalability Design

  • 전기차, 수소차 등 신규 연료타입 확장 가능
  • 자율주행 기능 등 신규 사양 추가 대비
  • 딜러별 차별화된 비즈니스 로직 지원

이 모델들을 기반으로 자동차업계의 다양한 비즈니스 요구사항을 효과적으로 처리할 수 있는 확장 가능한 시스템을 구축할 수 있습니다.