본문으로 건너뛰기

ElastiCORE Insurance 도메인 샘플 모델

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

📋 Domain Overview

Core Business Entities

  • Insurance Policy (보험증권): 보험 계약의 핵심 정보
  • Insurance Product (보험상품): 판매 가능한 보험 상품
  • Insurance Quote (보험견적): 견적 및 인수 프로세스
  • Insurance Claim (보험청구): 보험금 청구 및 지급
  • Coverage Type (보장유형): 보험 보장 범위 정의
  • Policy Participant (계약참여자): 피보험자, 수익자 등

🏗️ Entity Model Definitions

1. Insurance Policy (보험증권)

entity:
InsurancePolicy:
meta: entity @expose(50) @audited @extend(AuditEntity) @table(name="INSURANCE_POLICY")
fields:
policyId: long @id @sequence @search(eq) -- 증권번호
policyNumber: string(50)! @search(like) @unique -- 증권번호 (사용자용)
policyType: string(30)! @search(eq) -- 보험종류 (AUTO, HOME, LIFE, HEALTH)
policyStatus: string(20)! @search(eq) -- 증권상태 (ACTIVE, EXPIRED, CANCELLED, PENDING)
insuredName: string(100)! @search(like) -- 피보험자명
policyEffectiveDate: date! @search(between) -- 보험개시일
policyExpiryDate: date! @search(between) -- 보험만료일
totalPremium: bigdecimal(12.2) @search(between) -- 총보험료
currencyCode: string(3) @search(eq) @default('KRW') -- 통화코드 (KRW, USD)
producerId: long @search(eq) @ref(Producer.id) -- 담당 설계사/대리점 ID
productId: long! @search(eq) @ref(InsuranceProduct.id) -- 보험상품 ID
accountId: long! @search(eq) @ref(Account.id) -- 고객계정 ID
renewalCount: int @search(between) @default(0) -- 갱신횟수
riskScore: int @search(between) -- 위험도 점수 (1-100)
notes: text @search(like) -- 특이사항

2. Insurance Product (보험상품)

entity:
InsuranceProduct:
meta: entity @expose(50) @audited @extend(AuditEntity) @table(name="INSURANCE_PRODUCT")
fields:
productId: long @id @sequence @search(eq) -- 상품ID
productCode: string(20)! @search(eq) @unique -- 상품코드
productName: string(100)! @search(like) -- 상품명
productType: string(30)! @search(eq) -- 상품유형 (AUTO, HOME, LIFE, HEALTH, COMMERCIAL)
productCategory: string(50) @search(eq) -- 상품카테고리
isActive: boolean @search(eq) @default(true) -- 판매여부
minPremium: bigdecimal(12.2) @search(between) -- 최소보험료
maxPremium: bigdecimal(12.2) @search(between) -- 최대보험료
minCoverage: bigdecimal(15.2) @search(between) -- 최소보장한도
maxCoverage: bigdecimal(15.2) @search(between) -- 최대보장한도
salesStartDate: date @search(between) -- 판매개시일
salesEndDate: date @search(between) -- 판매종료일
description: text @search(like) -- 상품설명
terms: text -- 약관내용

3. Insurance Coverage (보험보장)

entity:
InsuranceCoverage:
meta: entity @expose(50) @table(name="INSURANCE_COVERAGE")
fields:
coverageId: long @id @sequence -- 보장ID
policyId: long! @search(eq) @ref(InsurancePolicy.id) -- 증권ID
coverageTypeId: long! @search(eq) @ref(CoverageType.id) -- 보장유형ID
coverageAmount: bigdecimal(15.2)! @search(between) -- 보장한도
deductibleAmount: bigdecimal(12.2) @search(between) @default(0) -- 자기부담금
premiumAmount: bigdecimal(12.2) @search(between) -- 보장별 보험료
isOptional: boolean @search(eq) @default(false) -- 선택보장 여부
effectiveDate: date! @search(between) -- 보장시작일
expiryDate: date! @search(between) -- 보장종료일

4. Insurance Claim (보험청구)

entity:
InsuranceClaim:
meta: entity @expose(50) @audited @pageable @extend(AuditEntity) @table(name="INSURANCE_CLAIM")
fields:
claimId: long @id @sequence @search(eq) -- 청구ID
claimNumber: string(50)! @search(like) @unique -- 청구번호
policyId: long! @search(eq) @ref(InsurancePolicy.id) -- 증권ID
claimStatus: string(20)! @search(eq) -- 청구상태 (SUBMITTED, INVESTIGATING, APPROVED, DENIED, PAID)
claimType: string(30)! @search(eq) -- 청구유형 (ACCIDENT, THEFT, DAMAGE, MEDICAL, DEATH)
incidentDate: date! @search(between) -- 사고발생일
reportedDate: datetime! @search(between) -- 신고일시
claimedAmount: bigdecimal(15.2)! @search(between) -- 청구금액
approvedAmount: bigdecimal(15.2) @search(between) -- 승인금액
paidAmount: bigdecimal(15.2) @search(between) -- 지급금액
deductibleApplied: bigdecimal(12.2) @search(between) @default(0) -- 차감된 자기부담금
claimantName: string(100)! @search(like) -- 청구인명
claimantPhone: string(20) @search(like) -- 청구인 연락처
incidentLocation: string(200) @search(like) -- 사고발생지
description: text @search(like) -- 사고경위
assessorId: long @search(eq) @ref(Assessor.id) -- 손해사정사 ID
finalizedDate: datetime @search(between) -- 처리완료일시

5. Coverage Type (보장유형)

entity:
CoverageType:
meta: entity @expose(50) @table(name="COVERAGE_TYPE")
fields:
coverageTypeId: long @id @sequence @search(eq) -- 보장유형ID
coverageCode: string(20)! @search(eq) @unique -- 보장코드
coverageName: string(100)! @search(like) -- 보장명
insuranceType: string(30)! @search(eq) -- 보험종류 (AUTO, HOME, LIFE, HEALTH)
isBasic: boolean @search(eq) @default(false) -- 기본보장 여부
defaultAmount: bigdecimal(15.2) @search(between) -- 기본보장한도
minAmount: bigdecimal(15.2) @search(between) -- 최소보장한도
maxAmount: bigdecimal(15.2) @search(between) -- 최대보장한도
description: text @search(like) -- 보장설명

6. Policy Participant (계약참여자)

entity:
PolicyParticipant:
meta: entity @expose(50) @table(name="POLICY_PARTICIPANT")
fields:
participantId: long @id @sequence -- 참여자ID
policyId: long! @search(eq) @ref(InsurancePolicy.id) -- 증권ID
participantType: string(20)! @search(eq) -- 참여자유형 (INSURED, BENEFICIARY, OWNER, GUARDIAN)
contactId: long! @search(eq) @ref(Contact.id) -- 연락처ID
relationshipType: string(30) @search(eq) -- 관계 (SELF, SPOUSE, CHILD, PARENT, SIBLING, OTHER)
beneficiaryPercentage: bigdecimal(5.2) @search(between) -- 수익자 배분율 (0-100%)
isPrimary: boolean @search(eq) @default(false) -- 주 참여자 여부
effectiveDate: date! @search(between) -- 참여시작일
expiryDate: date @search(between) -- 참여종료일

7. Insurance Quote (보험견적)

entity:
InsuranceQuote:
meta: entity @expose(50) @pageable @extend(AuditEntity) @table(name="INSURANCE_QUOTE")
fields:
quoteId: long @id @sequence @search(eq) -- 견적ID
quoteNumber: string(50)! @search(like) @unique -- 견적번호
quoteStatus: string(20)! @search(eq) -- 견적상태 (DRAFT, SUBMITTED, APPROVED, REJECTED, CONVERTED)
productId: long! @search(eq) @ref(InsuranceProduct.id) -- 보험상품ID
accountId: long! @search(eq) @ref(Account.id) -- 고객계정ID
producerId: long @search(eq) @ref(Producer.id) -- 설계사ID
quotedPremium: bigdecimal(12.2)! @search(between) -- 견적보험료
totalCoverage: bigdecimal(15.2) @search(between) -- 총보장한도
validUntil: date! @search(between) -- 견적유효기간
riskScore: int @search(between) -- 위험도 점수
underwritingNotes: text @search(like) -- 인수심사 의견
convertedPolicyId: long @search(eq) @ref(InsurancePolicy.id) -- 전환된 증권ID

🔗 Relational Design Patterns

1:N 관계

  • InsurancePolicy (1) ↔ (N) InsuranceCoverage
  • InsurancePolicy (1) ↔ (N) InsuranceClaim
  • InsurancePolicy (1) ↔ (N) PolicyParticipant
  • InsuranceProduct (1) ↔ (N) InsurancePolicy

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

  • InsuranceProductCoverageType (ProductCoverage 중간테이블)

📊 DTO Design Examples

PolicySearchDTO

dto:
PolicySearchDTO:
meta: dto @searchable @template('SEARCH')
fields:
policyNumber: string @search(like) -- 증권번호
insuredName: string @search(like) -- 피보험자명
policyStatus: string @search(eq) -- 증권상태
effectiveDateFrom: date @search(gte) @param('policyEffectiveDate') -- 보험개시일(시작)
effectiveDateTo: date @search(lte) @param('policyEffectiveDate') -- 보험개시일(종료)

ClaimSummaryDTO

dto:
ClaimSummaryDTO:
meta: dto
fields:
claimNumber: string -- 청구번호
policyNumber: string -- 증권번호
claimStatus: string -- 청구상태
claimedAmount: bigdecimal(15.2) -- 청구금액
approvedAmount: bigdecimal(15.2) -- 승인금액
incidentDate: date -- 사고발생일

📚 Repository Design Patterns

Complex Search Queries

repository:
InsurancePolicy:
methods:
- id: findPoliciesByStatusAndDateRange
params:
status: string
startDate: date
endDate: date
return: List<InsurancePolicy>
nativeQuery: true
query: |
SELECT p.* FROM INSURANCE_POLICY p
WHERE p.policy_status = :status
AND p.policy_effective_date BETWEEN :startDate AND :endDate
ORDER BY p.policy_effective_date DESC

- id: getClaimStatsByPolicy
params:
policyId: long
return: ClaimStatsDTO
nativeQuery: true
query: |
SELECT
COUNT(*) as claim_count,
SUM(claimed_amount) as total_claimed,
SUM(approved_amount) as total_approved
FROM INSURANCE_CLAIM
WHERE policy_id = :policyId

🎯 Best Practice Guidelines

1. Data Integrity

  • 필수 필드에 @nullable(false) 적용
  • 외래키는 @ref 어노테이션으로 참조 무결성 확보
  • 상태값은 ENUM 형태의 제한된 값으로 관리

2. Search Optimization

  • 자주 검색되는 필드에 적절한 @search 어노테이션 적용
  • 날짜 범위 검색은 @search(between) 활용
  • 텍스트 검색은 @search(like) 활용

3. Audit Tracking

  • 중요 엔터티는 @audited 어노테이션 적용
  • 생성일시, 수정일시 필드 필수 포함

4. Performance Considerations

  • 대용량 데이터 조회 시 @pageable 활용
  • 인덱스가 필요한 필드는 @Index 어노테이션 고려
  • 계산된 필드는 DTO에서 처리

5. Business Logic

  • 금액 필드는 decimal 타입으로 정밀도 확보
  • 상태 변경은 워크플로우 기반으로 관리
  • 날짜 유효성 검증 로직 필수

이 모델들을 기반으로 보험업계의 다양한 비즈니스 요구사항을 효과적으로 처리할 수 있는 안정적인 시스템을 구축할 수 있습니다.