ERD - PIC-2-team/PIC-2-team-project GitHub Wiki

ERD

์ตœ์ดˆ ์ž‘์„ฑ: 2026-10-08 | ์ตœ์ข… ์—…๋ฐ์ดํŠธ: 2026-10-14
API Spec v1 ๋ฐ ADR-004(๊ธฐ์ˆ  ์Šคํƒ ํ™•์ •) ๊ธฐ๋ฐ˜์œผ๋กœ ์ „๋ฉด ์žฌ์ž‘์„ฑ


์ธ์ฆยท์‚ฌ์šฉ์ž

erDiagram
    USER {
        bigint id PK
        string name
        string email
        string password "nullable: ์†Œ์…œ ๊ฐ€์ž… ๊ณ„์ •"
        string phone "nullable"
        string publicCode "nullable: GUARDIANยทSUPPORT_WORKER๋งŒ, P- ๋˜๋Š” S- + 8์ž"
        enum role "GUARDIAN | SUPPORT_WORKER | INSTITUTION"
        datetime createdAt
    }

    CONSENT {
        bigint id PK
        bigint userId FK
        boolean basicInfo
        boolean sensitiveInfo
        boolean caregiverShare
        boolean marketing "๊ธฐ๋ณธ false"
        string termsVersion
        datetime agreedAt
    }

    REFRESH_TOKEN {
        bigint id PK
        bigint userId FK
        string tokenHash
        datetime expiresAt "30์ผ"
        datetime revokedAt "nullable: ๋กœ๊ทธ์•„์›ƒยท๊ฐ•์ œ ๋งŒ๋ฃŒ"
        datetime createdAt
    }

    ORGANIZATION {
        bigint id PK
        bigint ownerId FK "INSTITUTION USER"
        string name
        string organizationCode "๊ณ ์œ , AA-999 ํ˜•์‹"
        datetime createdAt
    }

    ORGANIZATION_MEMBER {
        bigint id PK
        bigint organizationId FK
        bigint userId FK "SUPPORT_WORKER"
        enum status "ACTIVE | INACTIVE"
        datetime joinedAt
    }

    USER ||--|| CONSENT : ""
    USER ||--o{ REFRESH_TOKEN : ""
    USER ||--o| ORGANIZATION : "๊ธฐ๊ด€๋งŒ"
    ORGANIZATION ||--o{ ORGANIZATION_MEMBER : ""
    USER ||--o{ ORGANIZATION_MEMBER : "์ง€์›์‚ฌ๋งŒ"

๋‹น์‚ฌ์žยท๋ณดํ˜ธ์žยท๋ฐฐ์ •

erDiagram
    CARE_RECIPIENT {
        bigint id PK
        string careRecipientNumber "P-XXXXXXXX, ๊ณ ์œ "
        string name "์ตœ๋Œ€ 50์ž"
        date birthDate
        enum gender "FEMALE | MALE | NOT_SPECIFIED, nullable"
        string disabilityGrade "nullable, ์ตœ๋Œ€ 20์ž"
        string otherDisabilityType "nullable"
        datetime latestRecordAt "nullable"
        datetime createdAt
    }

    CARE_RECIPIENT_DISABILITY {
        bigint id PK
        bigint careRecipientId FK
        enum disabilityType "INTELLECTUAL | AUTISM | OTHER"
    }

    CARE_GUARDIAN {
        bigint id PK
        bigint careRecipientId FK
        bigint guardianId FK
        enum type "PRIMARY | SECONDARY"
        enum status "INVITED | READY | ACTIVE, nullable: SECONDARY๋งŒ"
        string invitationToken "nullable: SECONDARY INVITED ์ƒํƒœ"
        datetime expiresAt "nullable"
        datetime createdAt
    }

    ORGANIZATION_RECIPIENT_LINK {
        bigint id PK
        bigint organizationId FK
        bigint careRecipientId FK
        enum status "PENDING | ACCEPTED | REJECTED"
        datetime createdAt
    }

    CARE_ASSIGNMENT {
        bigint id PK
        bigint organizationId FK
        bigint careRecipientId FK
        bigint supportWorkerId FK
        string idempotencyKey "์ค‘๋ณต ๋ฐฐ์ • ๋ฐฉ์ง€"
        date startDate
        date endDate "nullable"
        datetime endedAt "nullable: ์ค‘๋„ ์ข…๋ฃŒ"
        datetime createdAt
    }

    CARE_RECIPIENT ||--o{ CARE_RECIPIENT_DISABILITY : ""
    CARE_RECIPIENT ||--o{ CARE_GUARDIAN : ""
    CARE_RECIPIENT ||--o{ ORGANIZATION_RECIPIENT_LINK : ""
    CARE_RECIPIENT ||--o{ CARE_ASSIGNMENT : ""

์ƒํ™œ๊ธฐ๋กยท๋Œ๋ด„์ •๋ณด

erDiagram
    DAILY_RECORD {
        bigint id PK
        bigint careRecipientId FK
        bigint authorId FK
        text content "์ตœ๋Œ€ 500์ž"
        enum category "COMMUNICATION | LIFESTYLE | MEAL | PREFERENCE | CHALLENGING_BEHAVIOR | HEALTH | EMERGENCY | OTHER"
        datetime recordedAt
        boolean pinned "๊ธฐ๋ณธ false"
        bigint recordRequestId FK "nullable"
        datetime createdAt
        datetime updatedAt
        datetime deletedAt "nullable: soft delete, 30์ผ ๋ณต๊ตฌ ๊ฐ€๋Šฅ"
    }

    RECORD_MEDIA {
        bigint id PK
        bigint careRecipientId FK
        bigint uploaderId FK
        string fileName
        enum mediaType "IMAGE | VIDEO | AUDIO"
        bigint sizeBytes "์ตœ๋Œ€ 50MB"
        string s3Key
        datetime createdAt
    }

    RECORD_MEDIA_LINK {
        bigint recordId FK
        bigint mediaId FK
    }

    RECORD_REVISION {
        bigint id PK
        bigint recordId FK
        bigint changedById FK
        text content
        enum category "DAILY_RECORD.category์™€ ๋™์ผ"
        datetime recordedAt
        int revision
        datetime changedAt
    }

    RECORD_SUGGESTION {
        bigint id PK
        bigint recordId FK
        bigint suggestedById FK
        text proposedContent
        enum proposedCategory "DAILY_RECORD.category์™€ ๋™์ผ"
        text reason "nullable"
        enum status "PENDING | APPROVED | REJECTED"
        datetime createdAt
    }

    CARE_INFO {
        bigint id PK
        bigint careRecipientId FK
        enum category "COMMUNICATION | PREFERENCE | LIFESTYLE | HEALTH_MEDICATION | PRECAUTION | EMERGENCY"
        text content "์ตœ๋Œ€ 3000์ž, nullable"
        datetime updatedAt "nullable"
    }

    DAILY_RECORD ||--o{ RECORD_MEDIA_LINK : ""
    RECORD_MEDIA ||--o{ RECORD_MEDIA_LINK : ""
    DAILY_RECORD ||--o{ RECORD_REVISION : ""
    DAILY_RECORD ||--o{ RECORD_SUGGESTION : ""
    CARE_RECIPIENT ||--o{ CARE_INFO : ""

์š”์ฒญยท์•Œ๋ฆผยท์ ‘๊ทผ ์ด๋ ฅ

erDiagram
    INFORMATION_REQUEST {
        bigint id PK
        bigint careRecipientId FK
        bigint requestedById FK "SUPPORT_WORKER"
        text message "์ตœ๋Œ€ 1000์ž"
        text reply "nullable"
        enum status "SUBMITTED | FORWARDED | ANSWERED | CLOSED"
        datetime createdAt
        datetime updatedAt
    }

    RECORD_REQUEST {
        bigint id PK
        bigint organizationId FK
        bigint careRecipientId FK
        bigint supportWorkerId FK
        string idempotencyKey
        text message
        bigint completedRecordId FK "nullable"
        enum status "OPEN | COMPLETED | CANCELLED"
        datetime createdAt
    }

    NOTIFICATION {
        bigint id PK
        bigint userId FK
        enum type "RECORD_CREATED | RECORD_UPDATED | ASSIGNMENT_CHANGED | SUGGESTION_RECEIVED | SUGGESTION_DECIDED | INFORMATION_REQUEST_RECEIVED | RECORD_REQUEST_RECEIVED | RECORD_FORWARDED | ORGANIZATION_LINK_REQUESTED"
        text message
        boolean read "๊ธฐ๋ณธ false"
        datetime createdAt
    }

    ACCESS_LOG {
        bigint id PK
        bigint actorId FK
        bigint careRecipientId FK
        enum action "READ | CREATE | UPDATE | DELETE"
        string resourceType
        bigint resourceId
        datetime occurredAt
    }

ํ•ต์‹ฌ enum ์š”์•ฝ

ํ…Œ์ด๋ธ” ํ•„๋“œ ๊ฐ’
USER role GUARDIAN | SUPPORT_WORKER | INSTITUTION
CARE_RECIPIENT gender FEMALE | MALE | NOT_SPECIFIED
CARE_RECIPIENT_DISABILITY disabilityType INTELLECTUAL | AUTISM | OTHER
DAILY_RECORD category COMMUNICATION | LIFESTYLE | MEAL | PREFERENCE | CHALLENGING_BEHAVIOR | HEALTH | EMERGENCY | OTHER
CARE_INFO category COMMUNICATION | PREFERENCE | LIFESTYLE | HEALTH_MEDICATION | PRECAUTION | EMERGENCY
CARE_GUARDIAN status INVITED | READY | ACTIVE
CARE_ASSIGNMENT โ€” startDate/endDate๋กœ ๊ธฐ๊ฐ„ ๊ด€๋ฆฌ (N:M temporal)
RECORD_SUGGESTION status PENDING | APPROVED | REJECTED
INFORMATION_REQUEST status SUBMITTED | FORWARDED | ANSWERED | CLOSED
RECORD_REQUEST status OPEN | COMPLETED | CANCELLED

์ด์ „ ๋ฏธ๊ฒฐ ์‚ฌํ•ญ โ†’ ํ•ด์†Œ

ํ•ญ๋ชฉ ๊ฒฐ์ •
๋Œ๋ด„ ์ œ๊ณต์ž โ†” ํ”ผ๋Œ๋ด„์ž ๊ด€๊ณ„ 1:N vs N:M CARE_ASSIGNMENT์˜ startDate/endDate๋กœ N:M temporal ๊ด€๋ฆฌ
CARE_INFO.content JSON vs ๋ถ„๋ฆฌ text ๋‹จ์ผ ์ปฌ๋Ÿผ (์นดํ…Œ๊ณ ๋ฆฌ 6๊ฐœ ํ–‰์œผ๋กœ ๋ถ„๋ฆฌ)
์ด๋ฏธ์ง€/ํŒŒ์ผ ์ฒจ๋ถ€ RECORD_MEDIA ํ…Œ์ด๋ธ” ์ถ”๊ฐ€, AWS S3 ์ €์žฅ (ADR-004)

์ฐธ๊ณ 

  • USER.publicCode: P- ์ ‘๋‘์‚ฌ๋Š” GUARDIAN, S- ์ ‘๋‘์‚ฌ๋Š” SUPPORT_WORKER
  • ORGANIZATION.organizationCode: AA-999 ํ˜•์‹ (์˜๋ฌธ 2์ž + ์ˆซ์ž 3์ž)
  • REFRESH_TOKEN.tokenHash: ์›๋ฌธ ํ† ํฐ์„ ํ•ด์‹œํ•˜์—ฌ ์ €์žฅ
  • DAILY_RECORD ์‚ญ์ œ๋Š” soft delete โ€” deletedAt ๊ธฐ๋ก ํ›„ 30์ผ ์ด๋‚ด ๋ณต๊ตฌ ๊ฐ€๋Šฅ
  • RECORD_MEDIA๋Š” ๊ธฐ๋ก์— ์ฒจ๋ถ€๋˜๊ธฐ ์ „ ๋‹จ๊ณ„(์—…๋กœ๋“œ ์งํ›„)์—๋„ ๋…๋ฆฝ ์กด์žฌ ๊ฐ€๋Šฅ