ERD - 100-hours-a-week/9-team-Devths-WIKI GitHub Wiki

๋ฌธ์„œ ๋ณ€๊ฒฝ ๋‚ด์—ญ

  • ๊ฒŒ์‹œ๊ธ€ ํ…Œ์ด๋ธ”(posts)์˜ ๋ณตํ•ฉ ์ธ๋ฑ์Šค ๊ด€๋ จ ๋‚ด์šฉ ์ˆ˜์ •(2026.01.09) : is_deleted ์ปฌ๋Ÿผ์„ ์„ ํ–‰์œผ๋กœ ๋‘๋Š” ๊ฒƒ์— ๊ด€ํ•œ ๊ทผ๊ฑฐ ๋ณด๊ฐ•
  • S3 ์ฒจ๋ถ€ํŒŒ์ผ ๊ด€๋ฆฌ ํ…Œ์ด๋ธ”(s3_attachments) ์ผ์›ํ™”(2026.01.08) : ๊ธฐ์กด ๋„๋ฉ”์ธ๋ณ„๋กœ ์กด์žฌํ–ˆ๋˜ ์ฒจ๋ถ€ํŒŒ์ผ ํ…Œ์ด๋ธ”์„ ํ†ตํ•ฉ
  • ๋น„๋™๊ธฐ ์ž‘์—… ๊ด€๋ฆฌ ํ…Œ์ด๋ธ”(async_tasks) ์ถ”๊ฐ€(2026.01.08)
  • ๊ฒŒ์‹œ๊ธ€ ๊ฒ€์ƒ‰์„ ์œ„ํ•œ Full Text Index ์ถ”๊ฐ€(2026.01.08)

ERDCloud

๐Ÿ‘‰ ERDCloud ๋งํฌ

  • ํ…Œ์ด๋ธ”๋ช… ๋ฐ ์ปฌ๋Ÿผ๋ช…: snake_case, ์˜๋ฌธ ์†Œ๋ฌธ์ž
  • ๊ธฐ๋ณธํ‚ค(PK): id BIGINT AUTO_INCREMENT NOT NULL
  • ์™ธ๋ž˜ํ‚ค(FK): [์ฐธ์กฐํ…Œ์ด๋ธ”๋ช…]_id BIGINT NOT NULL๋กœ ์ž‘์„ฑ, FK ์ œ์•ฝ ์กฐ๊ฑด ๋ช…์‹œ
    • ์ฐธ์กฐ ํ…Œ์ด๋ธ”๋ช…์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ณต์ˆ˜ํ˜•์ด์ง€๋งŒ ์™ธ๋ž˜ํ‚ค์—์„œ ์‚ฌ์šฉํ•  ๋• ๋‹จ์ˆ˜ํ˜•์œผ๋กœ ์ž‘์„ฑ
    • ์˜๋ฏธ์ ์œผ๋กœ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋ณ„๋„์˜ ๋„ค์ด๋ฐ ์ถ”๊ฐ€(follower_id, following_id ๋“ฑ)
  • ์ƒํƒœ๊ฐ’์„ ๊ฐ€์ง€๋Š” ์ปฌ๋Ÿผ: VARCHAR๋กœ ์ •์˜
    • ENUM ํƒ€์ž… ๋ฏธ์ฑ„ํƒ ์ด์œ  โ†’ ์ƒํƒœ๊ฐ’ ์ถ”๊ฐ€/๋ณ€๊ฒฝ/์‚ญ์ œ ์‹œ ์„œ๋น„์Šค ์šด์˜ ๋„์ค‘ ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ๋ถ€๋‹ด
  • ๋‚ ์งœ/์‹œ๊ฐ„ ์ปฌ๋Ÿผ
    • created_at : DATETIME NOT NULL, ์—”ํ‹ฐํ‹ฐ ์ƒ์„ฑ ์‹œ๊ฐ
    • updated_at : DATETIME NOT NULL, ์—”ํ‹ฐํ‹ฐ ์ˆ˜์ • ์‹œ๊ฐ(์—”ํ‹ฐํ‹ฐ ์ƒ์„ฑ ์‹œ ๋™์‹œ ์—…๋ฐ์ดํŠธ)
    • deleted_at : DATETIME NULL, ์—”ํ‹ฐํ‹ฐ ์‚ญ์ œ ์‹œ๊ฐ(is_deleted=true๋กœ ๋ณ€๊ฒฝ๋œ ์‹œ๊ฐ), ์‚ญ์ œ ์ •์ฑ…์— ํ™œ์šฉ
    • TIMESTAMP ํƒ€์ž… ๋ฏธ์ฑ„ํƒ ์ด์œ  โ†’ ๋ฐ์ดํ„ฐ ์ž…/์ถœ๋ ฅ ๊ณผ์ •์—์„œ UTC ์ž๋™ ๋ณ€ํ™˜์œผ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋Š” DB ์„œ๋ฒ„ ํƒ€์ž„์กด ์˜์กด์„ฑ ์ œ๊ฑฐ ๋ฐ Year 2038 Problem ๋ฐฉ์ง€
  • ์ธ๋ฑ์Šค: ์ž์ฃผ ๊ฒ€์ƒ‰ํ•˜๊ฑฐ๋‚˜ JOIN์— ์‚ฌ์šฉ๋˜๋Š” ์ปฌ๋Ÿผ์— ์ธ๋ฑ์Šค ์ถ”๊ฐ€
  • M:N(๋‹ค๋Œ€๋‹ค) ์—ฐ๊ด€ ๊ด€๊ณ„ : ๋ณ„๋„์˜ ๋งคํ•‘ ํ…Œ์ด๋ธ”์„ ์ถ”๊ฐ€
    • JPA ๊ตฌํ˜„์˜ ๋ณต์žก์„ฑ ๊ณ ๋ ค, ๋ณตํ•ฉํ‚ค๊ฐ€ ์•„๋‹Œ ๋Œ€๋ฆฌํ‚ค ๋ฐฉ์‹ ์‚ฌ์šฉ

๊ณตํ†ต

s3_attachments

s3_attachments ํ…Œ์ด๋ธ”: S3์— ์—…๋กœ๋“œํ•œ ํŒŒ์ผ๋“ค์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
  • original_name: ์‚ฌ์šฉ์ž๊ฐ€ ์—…๋กœ๋“œํ•œ ์›๋ณธ ํŒŒ์ผ๋ช…, VARCHAR, NOT NULL
  • ref_type: ํ•ด๋‹น ์ฒจ๋ถ€ํŒŒ์ผ์„ ์ฐธ์กฐํ•˜๋Š” ๋„๋ฉ”์ธ, VARCHAR, NOT NULL
    • Index(ref_type, ref_id, sort_order) โ†’ ํŠน์ • ๊ฒŒ์‹œ๊ธ€/์ฑ„ํŒ…์— ์ฒจ๋ถ€๋œ ํŒŒ์ผ ์กฐํšŒ ๋ฐ ์ •๋ ฌ ์ธ๋ฑ์Šค
  • ref_id: ํ•ด๋‹น ๋„๋ฉ”์ธ์˜ PK, BIGINT, NULL
  • s3_key: ํŒŒ์ผ์ด ์ €์žฅ๋œ S3 ๊ฒฝ๋กœ, VARCHAR, NOT NULL
  • mime_type: ํŒŒ์ผ์˜ ์œ ํ˜•, VARCHAR, NOT NULL
  • category: ํŒŒ์ผ์˜ ์นดํ…Œ๊ณ ๋ฆฌ(์ด๋ ฅ์„œ, ํฌํŠธํด๋ฆฌ์˜ค ๋“ฑ), VARCHAR, NULL
  • file_size: ํŒŒ์ผ์˜ ์šฉ๋Ÿ‰(Byte ๋‹จ์œ„), BIGINT, NOT NULL
  • sort_order: ํŒŒ์ผ ์ฒจ๋ถ€ ์ˆœ์„œ, TINYINT, NOT NULL, DEFAULT 0
  • created_at: ํŒŒ์ผ ์ฒจ๋ถ€ ์‹œ๊ฐ, DATETIME, NOT NULL
  • is_deleted: ์ฒจ๋ถ€ํŒŒ์ผ ์‚ญ์ œ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
  • deleted_at: ์ฒจ๋ถ€ํŒŒ์ผ ์‚ญ์ œ ์ผ์ž, DATETIME, NULL, DEFAULT NULL

async_tasks

async_tasks ํ…Œ์ด๋ธ”: ์‚ฌ์šฉ์ž๊ฐ€ ์‹คํ–‰ํ•œ ๋น„๋™๊ธฐ ์ž‘์—…์˜ ์ฒ˜๋ฆฌ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users : async_tasks = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL, UNIQUE(user_id, interest)
  • task_type: ๋น„๋™๊ธฐ ์ž‘์—… ์ข…๋ฅ˜(OCR, MASKING ๋“ฑ), VARCHAR, NOT NULL
  • reference_id: ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์ค‘์ธ ํŒŒ์ผ์˜ ID, BIGINT, NOT NULL
  • status: ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ ์ง„ํ–‰ ์ƒํƒœ, VARCHAR, NOT NULL
    • Index(status, is_notified, updated_at) โ†’ ๋น„๋™๊ธฐ ์ž‘์—… ์™„๋ฃŒ ์•Œ๋ฆผ ์ฒ˜๋ฆฌ์šฉ ์ธ๋ฑ์Šค
  • result: ๋ถ„์„ ๊ฒฐ๊ณผ ์ž„์‹œ ์ €์žฅ์šฉ ์ปฌ๋Ÿผ, JSON, NULL
  • created_at: ์ž‘์—… ์š”์ฒญ ์ผ์‹œ, DATETIME, NOT NULL
  • updated_at: ์ž‘์—… ์ƒํƒœ ๋ณ€๊ฒฝ ์ผ์‹œ, DATETIME, NOT NULL
  • is_notified: ์ž‘์—… ์™„๋ฃŒ ์•Œ๋ฆผ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE

ํšŒ์›

users

users ํ…Œ์ด๋ธ”: ๊ตฌ๊ธ€ OAuth2๋กœ ์šฐ๋ฆฌ ์„œ๋น„์Šค์— ๊ฐ€์ž…ํ•œ ํšŒ์›์˜ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ”

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • email: ์‚ฌ์šฉ์ž์˜ ๊ตฌ๊ธ€ ์ด๋ฉ”์ผ, VARCHAR, NOT NULL, UNIQUE
    • ์ค‘๋ณต ๊ฐ€์ž…์„ ๋ฐฉ์ง€
  • nickname: ์šฐ๋ฆฌ ์„œ๋น„์Šค์—์„œ ์‚ฌ์šฉํ•  ๋‹‰๋„ค์ž„, VARCHAR, NOT NULL, UNIQUE
    • ์ค‘๋ณต ๋‹‰๋„ค์ž„์„ ๋ฐฉ์ง€
  • role: ํšŒ์›์˜ ๊ถŒํ•œ, VARCHAR, NOT NULL, DEFAULT 'USER'
    • ๊ถŒํ•œ ํ…Œ์ด๋ธ” ๋ถ„๋ฆฌ ๋Œ€์‹  ์ปฌ๋Ÿผ์„ ์ถ”๊ฐ€ํ•ด ๊ตฌํ˜„ ๋ณต์žก๋„ ๋‚ฎ์ถค
  • created_at: ๊ฐ€์ž… ์ผ์‹œ, DATETIME, NOT NULL
  • updated_at: ํšŒ์›์ •๋ณด ์ˆ˜์ • ์ผ์‹œ, DATETIME, NOT NULL
  • is_withdraw: ํšŒ์› ํƒˆํ‡ด ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
    • Soft Delete ๊ตฌํ˜„์„ ์œ„ํ•œ Flag
  • withdraw_at: ํšŒ์› ํƒˆํ‡ด ์ผ์‹œ, DATETIME, NULL, DEFAULT 0
    • Soft Delete ๊ตฌํ˜„์„ ์œ„ํ•œ Flag ๋ฐ ์‚ญ์ œ ์ •์ฑ…์— ํ™œ์šฉ

user_stats

user_stats ํ…Œ์ด๋ธ”: ํšŒ์›์˜ ํŒ”๋กœ์›Œ/ํŒ”๋กœ์ž‰ ์ˆ˜๋ฅผ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ” โ†’ ์ถ”ํ›„ ๊ฒŒ์‹œ๊ธ€ ์ˆ˜, ๋Œ“๊ธ€ ์ˆ˜ ๋“ฑ์œผ๋กœ ํ™•์žฅ ๊ฐ€๋Šฅ

์—ฐ๊ด€ ๊ด€๊ณ„

users : user_stats = 1 : 1 (์‹๋ณ„ ๊ด€๊ณ„)

์ปฌ๋Ÿผ

  • follower_count: ํšŒ์›์„ ํŒ”๋กœ์šฐํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ์šฉ์ž์˜ ์ˆ˜, INT UNSIGNED, NOT NULL, DEFAULT 0
    • ์“ฐ๊ธฐ ์ž‘์—…์ด ๋น„๊ต์  ๋นˆ๋ฒˆํ•œ ์ปฌ๋Ÿผ์„ users ํ…Œ์ด๋ธ”์—์„œ ๋ถ„๋ฆฌ, ๋™์‹œ์„ฑ ์ œ์–ด์™€ ํ™•์žฅ์„ฑ์„ ๊ณ ๋ ค
  • following_count: ํšŒ์›์ด ํŒ”๋กœ์šฐํ•˜๊ณ  ์žˆ๋Š” ์‚ฌ์šฉ์ž์˜ ์ˆ˜, INT UNSIGNED, NOT NULL, DEFAULT 0
  • updated_at: ํšŒ์› ํŒ”๋กœ์šฐ ์ˆ˜์˜ ๋งˆ์ง€๋ง‰ ๋ณ€๊ฒฝ ์‹œ๊ฐ, DATETIME, NOT NULL
    • ์ถ”ํ›„ ์บ์‹ฑ๊ณผ ๋™๊ธฐํ™” ์ „๋žต ์ˆ˜๋ฆฝ ์‹œ ํ•„์š”

user_interests

user_interests ํ…Œ์ด๋ธ”: ํšŒ์›๊ฐ€์ž…/ํšŒ์›์ •๋ณด ์ˆ˜์ • ํ™”๋ฉด์—์„œ ์„ค์ •ํ•œ ๊ฐœ์ธ๋ณ„ ๊ด€์‹ฌ ๋ถ„์•ผ๋ฅผ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users : user_interests = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL, UNIQUE(user_id, interest)
    • ๋ณตํ•ฉ ์œ ๋‹ˆํฌ ์ธ๋ฑ์Šค โ†’ ํ•œ ์œ ์ €๊ฐ€ ๋™์ผํ•œ ๊ด€์‹ฌ์‚ฌ๋ฅผ ์ค‘๋ณตํ•ด์„œ ๋“ฑ๋กํ•˜๋Š” ๊ฒƒ์„ DB ์ฐจ์›์—์„œ ๋ฐฉ์ง€
  • interest: ๊ฐœ์ธ์ด ์„ค์ •ํ•œ ๊ด€์‹ฌ ๋ถ„์•ผ, VARCHAR, NOT NULL
    • ๋ฐ˜์ •๊ทœํ™”(Denormalization) ์ ์šฉ โ†’ ๋ณ„๋„์˜ ๋งˆ์Šคํ„ฐ ํ…Œ์ด๋ธ”์„ ๋‘์ง€ ์•Š๊ณ  ํ…์ŠคํŠธ๋ฅผ ์ปฌ๋Ÿผ์— ๋ฐ”๋กœ ์ €์žฅํ•˜์—ฌ JOIN ์ฟผ๋ฆฌ ์ œ๊ฑฐ
    • ๊ด€์‹ฌ ๋ถ„์•ผ์˜ ๊ฒฝ์šฐ ๋‚ด์šฉ ์ž์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋˜๋Š” ๊ฒฝ์šฐ(e.g. ๋ฐฑ์—”๋“œ โ†’ BE)๊ฐ€ ๊ฑฐ์˜ ์—†์„ ๊ฒƒ์ด๋ผ๊ณ  ํŒ๋‹จ, ๋ถˆํ•„์š”ํ•œ Relation์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•˜์Œ
    • ์ถ”ํ›„ ๊ด€์‹ฌ ๋ถ„์•ผ ๊ธฐ๋Šฅ ๊ณ ๋„ํ™” ์‹œ ์ •๊ทœํ™”๋ฅผ ํ†ตํ•œ ํ™•์žฅ ๊ฐ€๋Šฅ

follows

follows ํ…Œ์ด๋ธ”: ํšŒ์› ๊ฐ„ ํŒ”๋กœ์šฐ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users : follows = 1 : N ( users ๊ฐ„์˜ M : N ์—ฐ๊ด€ ๊ด€๊ณ„๋ฅผ ์œ„ํ•œ ๋งคํ•‘ ํ…Œ์ด๋ธ”)

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
    • ๋Œ€๋ฆฌํ‚ค ์ „๋žต ์ฑ„ํƒ
  • follower_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL, UNIQUE(follower_id, following_id)
    • ํŒ”๋กœ์šฐ๋ฅผ ํ•˜๋Š” ์‚ฌ๋žŒ์ด๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ๋„ค์ด๋ฐ ์‚ฌ์šฉ
    • ๋ณตํ•ฉ ์œ ๋‹ˆํฌ ์ธ๋ฑ์Šค โ†’ ๋™์ผํ•œ ์œ ์ €๊ฐ€ ๊ฐ™์€ ์ƒ๋Œ€๋ฅผ ์ค‘๋ณตํ•ด์„œ ํŒ”๋กœ์šฐํ•˜๋Š” ์ƒํ™ฉ์„ DB ์ฐจ์›์—์„œ ๋ฐฉ์ง€
    • Index(follower_id, created_at DESC) โ†’ ํŒ”๋กœ์ž‰ ๋ชฉ๋ก ์กฐํšŒ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • following_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • ํŒ”๋กœ์šฐ๋ฅผ ๋ฐ›๋Š” ์‚ฌ๋žŒ์ด๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ๋„ค์ด๋ฐ ์‚ฌ์šฉ
    • Index(following_id, created_at DESC) โ†’ ํŒ”๋กœ์›Œ ๋ชฉ๋ก ์กฐํšŒ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • created_at: ํŒ”๋กœ์šฐ ์ผ์‹œ, DATETIME, NOT NULL

social_accounts

social_accounts ํ…Œ์ด๋ธ”: ํšŒ์›์˜ ์†Œ์…œ ๋กœ๊ทธ์ธ ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ” โ†’ ์ถ”ํ›„ ์†Œ์…œ ๋กœ๊ทธ์ธ ๋ฐฉ์‹ ์ถ”๊ฐ€๋ฅผ ๊ณ ๋ ค

์—ฐ๊ด€ ๊ด€๊ณ„

users : social_accounts = 1 : 1 (์ถ”ํ›„ 1 : N์œผ๋กœ ํ™•์žฅ)

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
  • provider: ์†Œ์…œ ๋กœ๊ทธ์ธ ์ œ๊ณต์ž, VARCHAR, NOT NULL, DEFAULT 'GOOGLE', UNIQUE(provider, provider_user_id)
    • ๋ณตํ•ฉ ์œ ๋‹ˆํฌ ์ธ๋ฑ์Šค โ†’ provider_user_id๋Š” ํ•˜๋‚˜์˜ ํ”Œ๋žซํผ ์•ˆ์—์„œ๋งŒ ์œ ์ผํ•˜๋ฏ€๋กœ ๋ฐ์ดํ„ฐ์˜ ๋…ผ๋ฆฌ์  ๊ตฌ๋ถ„์„ ์œ„ํ•ด ID ์ œ๊ณต์ž์™€ ID๋ฅผ ๋ฌถ์–ด ์‹๋ณ„
    • ๊ฐ™์€ ์‚ฌ๋žŒ์ด๋ผ๋„ ์†Œ์…œ ๋กœ๊ทธ์ธ ๋ฐฉ์‹์ด ๋‹ค๋ฅด๋ฉด ๋‹ค๋ฅธ ํšŒ์›์œผ๋กœ ์ทจ๊ธ‰
  • provider_user_id: ์†Œ์…œ ๋กœ๊ทธ์ธ ๊ณ ์œ  ์‹๋ณ„์ž, VARCHAR, NOT NULL
  • created_at: ์†Œ์…œ ๋กœ๊ทธ์ธ ์—ฐ๋™ ์ผ์‹œ, DATETIME, NOT NULL
  • access_token: ์†Œ์…œ ๋กœ๊ทธ์ธ ์ œ๊ณต์ž ์ธก(ํ˜„์žฌ๋Š” ๊ตฌ๊ธ€)์—์„œ ๋ฐœ๊ธ‰ํ•œ ์•ก์„ธ์Šค ํ† ํฐ, VARCHAR, NOT NULL
    • ๊ตฌ๊ธ€ ์บ˜๋ฆฐ๋”์˜ ๋ฆฌ๋งˆ์ธ๋“œ ์•Œ๋žŒ์„ ์œ„ํ•ด์„œ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ๋„ ์ž‘๋™ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์•ก์„ธ์Šค ํ† ํฐ์„ ์„œ๋ฒ„ DB์— ์ €์žฅ
    • ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์œผ๋กœ ๋งค๋ฒˆ ์•ก์„ธ์Šค ํ† ํฐ์„ ์š”์ฒญํ•˜๋Š” ๊ณผ์ •์—์„œ ๋‚ญ๋น„๋˜๋Š” ๊ตฌ๊ธ€ API ์‚ฌ์šฉ๋Ÿ‰ ์ ˆ์•ฝ
  • refresh_token: ์†Œ์…œ ๋กœ๊ทธ์ธ ์ œ๊ณต์ž ์ธก(ํ˜„์žฌ๋Š” ๊ตฌ๊ธ€)์—์„œ ๋ฐœ๊ธ‰ํ•œ ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ, VARCHAR, NOT NULL
    • ๋ฐ˜๋“œ์‹œ ์•”ํ˜ธํ™”ํ•ด์„œ ์ €์žฅ
  • expires_at: access_token์˜ ๋งŒ๋ฃŒ ์‹œ๊ฐ, DATETIME, NOT NULL

user_tokens

user_tokens ํ…Œ์ด๋ธ”: ํšŒ์›์ด ์šฐ๋ฆฌ ์„œ๋น„์Šค์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ์„ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users : user_tokens = 1 : N (๋‹ค์ค‘ ๊ธฐ๊ธฐ ๋กœ๊ทธ์ธ)

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
  • refresh_token: ์šฐ๋ฆฌ ์„œ๋น„์Šค์—์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ฐœ๊ธ‰ํ•œ ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ, VARCHAR, NOT NULL, UNIQUE
    • ํ† ํฐ์˜ ๋ฌผ๋ฆฌ์  ์ €์žฅ์„ ํ†ตํ•œ ๋ณด์•ˆ ํ†ต์ œ๊ถŒ ํ™•๋ณด โ†’ ๊ฐ•์ œ ๋กœ๊ทธ์•„์›ƒ/๋‹ค์ค‘ ๊ธฐ๊ธฐ ๊ด€๋ฆฌ
    • UNIQUE + updated_at โ‡’ Refresh Token Rotation ์ง€์›์„ ์œ„ํ•œ ์ปฌ๋Ÿผ
  • created_at: ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ ๋ฐœ๊ธ‰ ์ผ์‹œ, DATETIME, NOT NULL
  • expires_at: ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ ๋งŒ๋ฃŒ ์ผ์‹œ, DATETIME, NOT NULL
  • updated_at: ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ ๋งˆ์ง€๋ง‰ ๊ฐฑ์‹  ์‹œ์ , DATETIME, NOT NULL
    • RTR ์‹คํ–‰ ์‹œ์ ์„ ๊ธฐ๋ก
    • ๋ฏธ์‚ฌ์šฉ ๊ธฐ๊ฐ„ ๋ฐ ํ† ํฐ ์‚ฌ์šฉ ์‹œ์  ์ถ”์ ์šฉ ์ปฌ๋Ÿผ

์บ˜๋ฆฐ๋”

calendar_events

calendar_events ํ…Œ์ด๋ธ”: ๊ตฌ๊ธ€ ์บ˜๋ฆฐ๋” API์™€ ์—ฐ๋™, ์‚ฌ์šฉ์ž์˜ ์ผ์ • ๋‚ด์šฉ์„ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users : calendar_events = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: user ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • Index(user_id, start_at, end_at) โ†’ ์‚ฌ์šฉ์ž์˜ ๊ธฐ๊ฐ„ ๋‚ด ์ผ์ • ์กฐํšŒ ์„ฑ๋Šฅ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • google_event_id: ๊ตฌ๊ธ€ ์ด๋ฒคํŠธ ID, VARCHAR, NULL, UNIQUE
    • ๊ตฌ๊ธ€ ์บ˜๋ฆฐ๋” API์—์„œ ๋„˜์–ด์˜ค๋Š” ๊ณ ์œ  ์‹๋ณ„์ž
    • ๋™์ผํ•œ ๊ตฌ๊ธ€ ์ผ์ •์˜ ์ค‘๋ณต ์ƒ์„ฑ์„ ๋ง‰๊ณ , UPSERT ๋กœ์ง ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ UNIQUE ์ œ์•ฝ ์ถ”๊ฐ€
    • ์„œ๋น„์Šค ๋‚ด์—์„œ ์ง์ ‘ ์ƒ์„ฑํ•œ ์ผ์ •์€ ๊ตฌ๊ธ€ API๋กœ๋ถ€ํ„ฐ ์„ฑ๊ณต ์‘๋‹ต์„ ๋ฐ›๊ธฐ ์ „๊นŒ์ง€ ์ด๋ฒคํŠธ ID๊ฐ€ ์—†์œผ๋ฏ€๋กœ NULL ๊ฐ€๋Šฅ
  • stage: ์ „ํ˜• ๋‹จ๊ณ„, VARCHAR, NOT NULL
  • title: ์ผ์ • ์ด๋ฆ„, VARCHAR, NOT NULL
  • company_name: ํšŒ์‚ฌ๋ช…, VARCHAR, NOT NULL
  • location: ์ผ์ • ์ˆ˜ํ–‰ ์žฅ์†Œ, VARCHAR, NULL
  • start_at: ์‹œ์ž‘์ผ์‹œ, DATETIME, NOT NULL
  • end_at: ์ข…๋ฃŒ์ผ์‹œ, DATETIME, NOT NULL
  • is_all_day: ์ข…์ผ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
  • description: ์ผ์ •์— ๊ด€ํ•œ ์ƒ์„ธ ๋‚ด์šฉ ๋˜๋Š” ๋ฉ”๋ชจ, VARCHAR, NULL
  • updated_at: ์ผ์ •์˜ ๋งˆ์ง€๋ง‰ ์ˆ˜์ • ์‹œ๊ฐ, DATETIME, NOT NULL
  • is_deleted: ์ผ์ • ์‚ญ์ œ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
    • Soft Delete ๊ตฌํ˜„์„ ์œ„ํ•œ Flag
  • deleted_at: ์ผ์ • ์‚ญ์ œ ์ผ์‹œ, DATETIME, NULL, DEFAULT 0
    • Soft Delete ๊ตฌํ˜„์„ ์œ„ํ•œ Flag

event_tags

event_tags ํ…Œ์ด๋ธ”: ์บ˜๋ฆฐ๋”์— ๋“ฑ๋ก๋œ ์ผ์ •๊ณผ ํ•ด๋‹น ์ผ์ •์˜ ํƒœ๊ทธ๋ฅผ ๋งคํ•‘ํ•˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

calendar_events : event_tags = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • event_id: calendar_events ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
  • name: ํƒœ๊ทธ ๋‚ด์šฉ, VARCHAR, NOT NULL
    • Index(name) โ†’ ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” ํƒœ๊ทธ์˜ ์ผ์ •๋งŒ ํ•„ํ„ฐ๋งํ•  ๋•Œ ์„ฑ๋Šฅ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค

event_reminders

event_reminders ํ…Œ์ด๋ธ”: ์บ˜๋ฆฐ๋”์˜ ๋“ฑ๋ก๋œ ์ผ์ •์˜ ์•Œ๋ฆผ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

calendar_events : event_reminders = 1 : 1

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • event_id: calendar_events ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
  • remind_unit: ์ผ์ • ์•Œ๋ฆผ ์‹œ๊ฐ„์˜ ๋‹จ์œ„(๋ถ„, ์‹œ, ์ผ ๋“ฑ), VARCHAR, NOT NULL
  • remind_value: ์ผ์ • ์•Œ๋ฆผ ์‹œ๊ฐ„์˜ ํฌ๊ธฐ(30, 1, 24 ๋“ฑ), INT, NOT NULL
    • ๋‹จ์œ„์™€ ๊ฐ’์˜ ๋ถ„๋ฆฌ โ†’ ๊ตฌ๊ธ€ ์บ˜๋ฆฐ๋” API์˜ ์™ธ๋ถ€ ๊ทœ๊ฒฉ๊ณผ ํ˜ธํ™˜์„ฑ ๋ฐ UI/UX์—์„œ์˜ ์œ ์—ฐํ•จ ํ™•๋ณด
  • notify_at: ์‹œ๊ฐ„์˜ ๋‹จ์œ„+๊ฐ’์„ ๋ฐ”ํƒ•์œผ๋กœ ๊ณ„์‚ฐ๋œ ์ผ์ • ์•Œ๋ฆผ ์˜ˆ์ • ์‹œ๊ฐ„, DATETIME, NOT NULL
    • ์„ ํ–‰ ๊ณ„์‚ฐ ๋กœ์ง์„ ํ†ตํ•ด ๋‹จ์ˆœ ๋น„๊ต ์กฐํšŒ๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•จ
    • Index(notify_at, is_sent) โ†’ ์•Œ๋ฆผ ๋ฐœ์†ก ์›Œ์ปค๊ฐ€ ์‹คํ–‰ํ•  ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • is_sent: ์ผ์ • ์•Œ๋ฆผ ๋ฐœ์†ก ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
  • created_at: ์ผ์ • ์•Œ๋ฆผ ์ƒ์„ฑ ์‹œ๊ฐ„, DATETIME, NOT NULL

todos

todos ํ…Œ์ด๋ธ”: ์‚ฌ์šฉ์ž์˜ To-Do ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users : todos = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • Index(user_id, target_date) โ†’ ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ๋‚ ์งœ์˜ ํ•  ์ผ์„ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • content: ํ•  ์ผ ๋‚ด์šฉ, VARCHAR, NOT NULL
  • is_completed: ํ•  ์ผ ์™„๋ฃŒ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
  • target_date: ํ•  ์ผ ๋‚ ์งœ, DATE, NOT NULL
    • ํ•ด๋‹น ๊ธฐ๋Šฅ ๊ธฐํš ์˜๋„๊ฐ€ โ€˜์˜ค๋Š˜ ํ•  ์ผโ€™์ด๋ฏ€๋กœ ์‹œ๊ฐ„ ์ •๋ณด๊ฐ€ ์—†๋Š” DATE ํƒ€์ž… ์„ ํƒ
  • created_at: ํ•  ์ผ ์ƒ์„ฑ์ผ์ž, DATETIME, NOT NULL
    • 2์ฐจ ์ •๋ ฌ ๊ธฐ์ค€ : ํ•  ์ผ ์ƒ์„ฑ ์ˆœ์„œ
  • updated_at: ํ•  ์ผ ์ˆ˜์ •์ผ์ž, DATETIME, NOT NULL

๊ฒŒ์‹œํŒ

posts

posts ํ…Œ์ด๋ธ”: ๊ฒŒ์‹œ๊ธ€ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users : posts = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • Index(user_id, is_deleted, created_at, id) โ†’ ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๊ธ€ ์กฐํšŒ ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • title: ๊ฒŒ์‹œ๊ธ€ ์ œ๋ชฉ, VARCHAR, NOT NULL
    • Full text Index(title, content) โ†’ ์ œ๋ชฉ ๋ฐ ๋‚ด์šฉ ๊ฒ€์ƒ‰ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • content: ๊ฒŒ์‹œ๊ธ€ ๋‚ด์šฉ, LONGTEXT, NOT NULL
    • ๊ฒŒ์‹œ๊ธ€ ๋ณธ๋ฌธ(๋งˆํฌ๋‹ค์šด)์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด LONGTEXT ์ฑ„ํƒ
  • like_count: ์ข‹์•„์š”์ˆ˜, INT UNSIGNED, NOT NULL, DEFAULT 0
    • ๋ฐ˜์ •๊ทœํ™”(Denormalization) ์ ์šฉ โ†’ ๋ณ„๋„์˜ ํ…Œ์ด๋ธ”์—์„œ ๋งค๋ฒˆ COUNT ์ฟผ๋ฆฌ๋กœ ์ง‘๊ณ„ํ•˜์ง€ ์•Š๊ณ  ์ฝ๊ธฐ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒํ•˜๊ธฐ ์œ„ํ•จ
    • ์ข‹์•„์š”์ˆ˜ ๊ธฐ์ค€ ์ •๋ ฌ ๋กœ์ง์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ฟผ๋ฆฌ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ์ปฌ๋Ÿผ์œผ๋กœ ๊ด€๋ฆฌ
    • ๊ฒŒ์‹œ๊ธ€์€ ์ฃผ๋กœ ๋ฆฌ์ŠคํŠธ๋กœ ์กฐํšŒ โ†’ ์ข‹์•„์š”์ˆ˜๊ฐ€ ๋ณ„๋„์˜ ํ…Œ์ด๋ธ”์— ์กด์žฌํ•œ๋‹ค๋ฉด ๊ฒŒ์‹œ๊ธ€ ์ˆ˜๋งŒํผ JOIN ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์„ฑ๋Šฅ ์ €ํ•˜ ์šฐ๋ ค
    • ๊ฒŒ์‹œ๊ธ€ ๋ฐ์ดํ„ฐ์˜ ์ˆ˜๋ช… ์ฃผ๊ธฐ โ†’ ๊ฒŒ์‹œ๊ธ€์€ ๋ณดํ†ต ์ž‘์„ฑ ์งํ›„์—๋งŒ ์ข‹์•„์š”์ˆ˜๊ฐ€ ๋น ๋ฅด๊ฒŒ ๋ณ€ํ•˜๊ณ  ๊ทธ ์ดํ›„์—๋Š” ๊ฑฐ์˜ Read-Only์ฒ˜๋Ÿผ ๋™์ž‘
  • comment_count: ๋Œ“๊ธ€์ˆ˜, INT UNSIGNED, NOT NULL, DEFAULT 0
    • ๋ฐ˜์ •๊ทœํ™”(Denormalization) ์ ์šฉ โ†’ ๋ณ„๋„์˜ ํ…Œ์ด๋ธ”์—์„œ ๋งค๋ฒˆ COUNT ์ฟผ๋ฆฌ๋กœ ์ง‘๊ณ„ํ•˜์ง€ ์•Š๊ณ  ์ฝ๊ธฐ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒํ•˜๊ธฐ ์œ„ํ•จ
    • ๊ฒŒ์‹œ๊ธ€์€ ์ฃผ๋กœ ๋ฆฌ์ŠคํŠธ๋กœ ์กฐํšŒ โ†’ ๋Œ“๊ธ€์ˆ˜๊ฐ€ ๋ณ„๋„์˜ ํ…Œ์ด๋ธ”์— ์กด์žฌํ•œ๋‹ค๋ฉด ๊ฒŒ์‹œ๊ธ€ ์ˆ˜๋งŒํผ JOIN ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์„ฑ๋Šฅ ์ €ํ•˜ ์šฐ๋ ค
    • ๊ฒŒ์‹œ๊ธ€ ๋ฐ์ดํ„ฐ์˜ ์ˆ˜๋ช… ์ฃผ๊ธฐ โ†’ ๊ฒŒ์‹œ๊ธ€์€ ๋ณดํ†ต ์ž‘์„ฑ ์งํ›„์—๋งŒ ๋Œ“๊ธ€์ˆ˜๊ฐ€ ๋น ๋ฅด๊ฒŒ ๋ณ€ํ•˜๊ณ  ๊ทธ ์ดํ›„์—๋Š” ๊ฑฐ์˜ Read-Only์ฒ˜๋Ÿผ ๋™์ž‘
  • share_count: ๊ณต์œ ์ˆ˜, INT UNSIGNED, NOT NULL, DEFAULT 0
  • created_at: ๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ ์‹œ๊ฐ, DATETIME, NOT NULL
  • updated_at: ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ์‹œ๊ฐ, DATETIME, NOT NULL
  • is_deleted: ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
    • Index(is_deleted, created_at, id) โ†’ ์ตœ์‹ ์ˆœ ์กฐํšŒ(๊ธฐ๋ณธ ํ”ผ๋“œ) ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
    • Index(is_deleted, like_count, id) โ†’ ์ธ๊ธฐ๊ธ€ ์กฐํšŒ ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • deleted_at: ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ์‹œ๊ฐ, DATETIME, NULL, DEFAULT NULL

โ“๊ฒŒ์‹œ๊ธ€ย ๋ชฉ๋ก ์กฐํšŒ์˜ ์ฟผ๋ฆฌ์˜ WHERE์ ˆ์€ ๋Œ€๋ถ€๋ถ„ is_deleted = 0์„ ์‚ฌ์šฉํ•œ๋‹ค. ๊ฒŒ์‹œํŒ์—๋Š” ํ•ด๋‹น ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•˜๋Š” ๋ฏธ์‚ญ์ œ ๊ฒŒ์‹œ๊ธ€์ด ํ›จ์”ฌ ๋” ๋งŽ์„ ํ…๋ฐ, ์นด๋””๋„๋ฆฌํ‹ฐ(๋˜๋Š” ์„ ํƒ๋„)๊ฐ€ ๋‚ฎ์€ is_deleted ์ปฌ๋Ÿผ์„ ๋ณตํ•ฉ ์ธ๋ฑ์Šค์˜ ์„ ํ–‰์œผ๋กœ ๋‘๋ฉด ์˜ตํ‹ฐ๋งˆ์ด์ €๊ฐ€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„ ์˜คํžˆ๋ ค ํ•ด๋‹น ์ธ๋ฑ์Šค๋กœ ์ธํ•œ ์‚ฝ์ž…/์ˆ˜์ • ๋น„์šฉ๊ณผ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ฒ„ํ—ค๋“œ๋งŒ ๋Š˜์–ด๋‚˜๋Š” ๊ฒƒ ์•„๋‹Œ๊ฐ€?

  • ์ธ๋ฑ์Šค๊ฐ€ (created_at, id)๋ผ๋ฉด ์˜ตํ‹ฐ๋งˆ์ด์ €๋Š” ๋งค๋ฒˆ ํ…Œ์ด๋ธ”์— ์ ‘๊ทผํ•ด is_deleted=0์ธ์ง€ ํ™•์ธํ•ด์•ผ ํ•จ
    • ๋งŒ์•ฝ ์‚ญ์ œ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์•„์ง„๋‹ค๋ฉด LIMIT ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๊ธฐ ์œ„ํ•ด ์ถ”๊ฐ€์ ์ธ ์Šค์บ”์ด ๋ฐœ์ƒ
    • WHERE์ ˆ์—์„œ ์ƒ์ˆ˜๋กœ ๊ณ ์ •๋˜๋Š” is_deleted ์ปฌ๋Ÿผ์ด ์ธ๋ฑ์Šค์— ์„ ํ–‰์œผ๋กœ ์ถ”๊ฐ€๋˜๋ฉด ๊ทธ ํ›„ํ–‰ ์ปฌ๋Ÿผ๋“ค์€ ๋ฌผ๋ฆฌ์ ์ธ ์ •๋ ฌ ์ˆœ์„œ๋ฅผ ๋ณด์žฅ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ
    • ์ฆ‰, is_deleted=0์ธ ๊ตฌ๊ฐ„์—์„œ LIMIT ๊ฐœ์ˆ˜๋งŒํผ ๋ฐ”๋กœ ๊ฐ€์ง€๊ณ  ์˜ฌ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ
    • ์˜ตํ‹ฐ๋งˆ์ด์ €๋Š” cost ๊ธฐ๋ฐ˜์œผ๋กœ ์‹คํ–‰ ๊ณ„ํš์„ ์ˆ˜๋ฆฝ โ†’ ํ•ด๋‹น ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ผ๊ณ  ์˜ˆ์ƒ
  • ๋˜ํ•œ ๊ฒŒ์‹œ๊ธ€์€ ์กฐํšŒ ๋นˆ๋„๊ฐ€ ์ž‘์„ฑ/์ˆ˜์ •/์‚ญ์ œ ๋นˆ๋„๋ณด๋‹ค ์••๋„์ ์œผ๋กœ ๋†’์€, ์ „ํ˜•์ ์ธ Read-Intensive ๋„๋ฉ”์ธ
  • ์“ฐ๊ธฐ ์‹œ ๋ฐœ์ƒํ•˜๋Š” ์ธ๋ฑ์Šค ๊ฐฑ์‹  ๋น„์šฉ๋ณด๋‹ค ๋‹ค์ˆ˜์˜ ์‚ฌ์šฉ์ž๊ฐ€ ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ํ˜ธ์ถœํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์กฐํšŒ ํšจ์œจ์˜ ์ด๋“์ด ํ›จ์”ฌ ํฌ๋‹ค๊ณ  ํŒ๋‹จ
  • ์„œ๋น„์Šค ์ดˆ๊ธฐ(๊ฒŒ์‹œ๊ธ€์˜ ์‚ญ์ œ ๋น„์œจ์ด ๋งค์šฐ ์ž‘์„ ๋•Œ)์—๋Š” ์ถ”๊ฐ€ ์Šค์บ” ๊ฑฐ์˜ ์—†์ด LIMIT๋ฅผ ๋งŒ์กฑํ•˜๋ฏ€๋กœ (created_at, id)๊ฐ€ ์•ฝ๊ฐ„ ๋” ์ด๋“์ด๊ฑฐ๋‚˜ ๋น„์Šทํ•œ ์ˆ˜์ค€์ด์ง€๋งŒ, ์ถ”ํ›„ ํ™•์žฅ์„ ๊ณ ๋ คํ–ˆ์„ ๋•Œ์—๋Š” (is_deleted, created_at, id)๊ฐ€ ์ ์ ˆํ•˜๋‹ค๊ณ  ํŒ๋‹จ

post_tags

post_tags ํ…Œ์ด๋ธ”: ๊ฒŒ์‹œ๊ธ€๊ณผ ํ•ด๋‹น ๊ฒŒ์‹œ๊ธ€์˜ ํƒœ๊ทธ๋ฅผ ๋งคํ•‘ํ•˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

posts : post_tags = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • post_id: posts ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL, UNIQUE(post_id, tag_name)
    • ๋ณตํ•ฉ ์œ ๋‹ˆํฌ ์ธ๋ฑ์Šค โ†’ ํ•œ ๊ฒŒ์‹œ๊ธ€์— ๋˜‘๊ฐ™์€ ํƒœ๊ทธ๊ฐ€ ์ค‘๋ณต ์ €์žฅ๋˜๋Š” ๊ฒƒ์„ DB ์ฐจ์›์—์„œ ๋ฐฉ์ง€
  • tag_name: ๊ฒŒ์‹œ๊ธ€ ํƒœ๊ทธ ๋‚ด์šฉ, VARCHAR, NOT NULL
    • ๊ฒŒ์‹œ๊ธ€ ํƒœ๊ทธ์˜ ๊ฒฝ์šฐ ํ˜„์žฌ ์„œ๋น„์Šค ์ŠคํŽ™์—์„œ๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ๊ณ ์ •๋œ ๊ฐ’๋“ค์„ ์ œ๊ณตํ•ด์คŒ
    • ๋ฐ˜์ •๊ทœํ™”(Denormalization) ์ ์šฉ โ†’ ๋ณ„๋„์˜ ๋งˆ์Šคํ„ฐ ํ…Œ์ด๋ธ”์„ ๋‘์ง€ ์•Š๊ณ  ํ…์ŠคํŠธ๋ฅผ ์ปฌ๋Ÿผ์— ๋ฐ”๋กœ ์ €์žฅํ•˜์—ฌ JOIN ์ฟผ๋ฆฌ ์ œ๊ฑฐ
    • ์ถ”ํ›„ ํƒœ๊ทธ ๊ธฐ๋Šฅ ๊ณ ๋„ํ™” ์‹œ ์ •๊ทœํ™”๋ฅผ ํ†ตํ•œ ํ™•์žฅ ๊ฐ€๋Šฅ
    • Index(tag_name) โ†’ ์›ํ•˜๋Š” ํƒœ๊ทธ์˜ ๊ธ€๋งŒ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค

comments

comments ํ…Œ์ด๋ธ”: ๊ฒŒ์‹œ๊ธ€์— ์ž‘์„ฑ๋œ ๋Œ“๊ธ€ ๋ฐ ๋‹ต๊ธ€ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

posts : comments = 1 : N

users : comments = 1 : N

comments : comments(๋‹ต๊ธ€) = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • post_id: posts ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • Index(post_id, is_deleted, parent_id, created_at, id, user_id) โ†’ ๊ฒŒ์‹œ๋ฌผ์— ์ž‘์„ฑ๋œ ๋Œ“๊ธ€ ๋ชฉ๋ก ์กฐํšŒ ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค
    • Index(parent_id, is_deleted, created_at, id, user_id) โ†’ ๊ฒŒ์‹œ๋ฌผ์— ์ž‘์„ฑ๋œ ๋‹ต๊ธ€ ๋ชฉ๋ก ์กฐํšŒ ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค
    • ๋Œ“/๋‹ต๊ธ€ ๋‚ด์šฉ์€ ๋ชฉ๋ก์—์„œ id๋กœ ๋ฐ”๋กœ ๊ฐ€์ ธ ์˜ด
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
  • parent_id: comments ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NULL, DEFAULT NULL
    • ์›๋Œ“๊ธ€์ด๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ๋„ค์ด๋ฐ ์‚ฌ์šฉ
    • ์ž๊ธฐ ์ž์‹ ์„ ์ฐธ์กฐํ•˜๋Š” ์žฌ๊ท€์  ๊ด€๊ณ„
    • ํ•ด๋‹น ๊ฐ’์ด NULL์ด๋ฉด ์ตœ์ƒ์œ„ ๋ถ€๋ชจ ๋Œ“๊ธ€(์›๋Œ“๊ธ€), ๊ฐ’์ด ์žˆ์œผ๋ฉด ํ•ด๋‹น ๋Œ“๊ธ€์— ๋‹ฌ๋ฆฐ ๋‹ต๊ธ€
  • content: ๋Œ“๊ธ€ ๋‚ด์šฉ, VARCHAR, NOT NULL
  • created_at: ๋Œ“๊ธ€ ์ž‘์„ฑ์ผ์ž, DATETIME, NOT NULL
  • updated_at: ๋Œ“๊ธ€ ์ž‘์„ฑ์ผ์ž, DATETIME, NOT NULL
  • is_deleted: ๋Œ“๊ธ€ ์‚ญ์ œ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
  • deleted_at: ๋Œ“๊ธ€ ์‚ญ์ œ์ผ์ž, DATETIME, NULL, DEFAULT NULL

likes

likes ํ…Œ์ด๋ธ”: ๊ฒŒ์‹œ๋ฌผ์˜ ์ข‹์•„์š” ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

posts : likes = 1 : N

users : likes = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • post_id: posts ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL, UNIQUE(post_id, user_id)
    • ๋ณตํ•ฉ ์œ ๋‹ˆํฌ ์ธ๋ฑ์Šค โ†’ ๋™์ผํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์ผํ•œ ๊ฒŒ์‹œ๋ฌผ์— ์ค‘๋ณต์œผ๋กœ ์ข‹์•„์š”๋ฅผ ๋ˆ„๋ฅด๋Š” ํ˜„์ƒ ๋ฐฉ์ง€
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL

์ฑ—๋ด‡

ai_chat_rooms

ai_chat_rooms ํ…Œ์ด๋ธ”: AI ์ฑ—๋ด‡๊ณผ์˜ ์ฑ„ํŒ…๋ฐฉ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users : ai_chat_rooms = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • Index(user_id, is_deleted, updated_at) โ†’ ์‚ฌ์šฉ์ž์˜ ์‚ญ์ œ๋˜์ง€ ์•Š์€ ์ฑ„ํŒ…๋ฐฉ์„ ์ตœ์‹ ์ˆœ์œผ๋กœ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๋Š” ์šฉ๋„์˜ ์ธ๋ฑ์Šค
  • room_uuid: AI ์„œ๋ฒ„ ๋ฐ ๋ฒกํ„ฐ DB์™€ ๊ณต์œ ํ•  ๊ณ ์œ  ํ‚ค, VARCHAR, NOT NULL, UNIQUE
    • ์ž„๋ฒ ๋”ฉ ๋ฒกํ„ฐ์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ์— ํ•ด๋‹น ํ‚ค๊ฐ€ ๋“ค์–ด๊ฐ
  • title: AI ์š”์•ฝ์œผ๋กœ ๋“ค์–ด๊ฐ€๋Š” ์ฑ„ํŒ…๋ฐฉ ์ œ๋ชฉ, VARCHAR, NULL, DEFAULT NULL
  • created_at: AI ์ฑ„ํŒ…๋ฐฉ ์ƒ์„ฑ์ผ, DATETIME, NOT NULL
  • updated_at: ๋งˆ์ง€๋ง‰ ์ฑ„ํŒ…์ผ์ž, DATETIME, NOT NULL
  • is_deleted: AI ์ฑ„ํŒ…๋ฐฉ ์‚ญ์ œ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
  • deleted_at: AI ์ฑ„ํŒ…๋ฐฉ ์‚ญ์ œ์ผ์ž, DATETIME, NULL, DEFAULT NULL

ai_chat_messages

ai_chat_messages ํ…Œ์ด๋ธ”: ์‚ฌ์šฉ์ž๊ฐ€ ์ฑ—๋ด‡๊ณผ ๋‚˜๋ˆˆ ๋ฉ”์‹œ์ง€๋“ค์ด ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

ai_chat_rooms : ai_chat_messages = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • room_id: ai_chat_rooms ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • Index(room_id, id) โ†’ ํŠน์ • ๋ฐฉ์˜ ๋Œ€ํ™” ํ๋ฆ„(์ˆœ์„œ) ๋ณต์›์„ ์ตœ์ ํ™”ํ•˜๋Š” ์ธ๋ฑ์Šค
    • created_at์ด ์•„๋‹Œ id๋ฅผ ์ธ๋ฑ์Šค๋กœ ์‚ฌ์šฉํ•œ ์ด์œ  โ†’ ์œ ๋‹ˆํฌํ•œ ๊ฐ’์ด ๋ณด์žฅ๋˜์–ด ์ •๋ ฌ ๋ถˆ์ผ์น˜ ๋ฌธ์ œ ๋ฐฉ์ง€
  • interview_id: ai_chat_interview ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NULL
  • role: ์ฑ„ํŒ… ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ธ ์ฃผ์ฒด, VARCHAR, NOT NULL
  • content: ์ฑ„ํŒ… ๋‚ด์šฉ, LONGTEXT, NOT NULL
    • ๋งค์šฐ ๊ธธ์–ด์งˆ ์ˆ˜ ์žˆ๋Š” AI ์ฑ—๋ด‡ ๋‹ต๋ณ€์˜ ํŠน์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ LONGTEXT ์ฑ„ํƒ
  • created_at: ์ฑ—๋ด‡ ๋ฉ”์‹œ์ง€ ์ƒ์„ฑ์ผ์ž, DATETIME, NOT NULL
  • type: ๋ฉ”์‹œ์ง€์˜ ์ข…๋ฅ˜, VARCHAR, NOT NULL
  • metadata: ์ฑ—๋ด‡ ์‘๋‹ต์˜ ๋ฉ”ํƒ€ ๋ฐ์ดํ„ฐ, JSON, NULL, DEFAULT NULL

ai_chat_interview

ai_chat_interview ํ…Œ์ด๋ธ”: AI์˜ ๋ชจ์˜ ๋ฉด์ ‘ ์„ธ์…˜์˜ ์ƒํƒœ์™€ ์ง„ํ–‰ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

ai_chat_rooms : ai_chat_interview = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • room_id: ai_chat_rooms ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • Index(room_id) โ†’ ์ฑ„ํŒ…๋ฐฉ๋ณ„ ๋ฉด์ ‘ ์ง„ํ–‰ ์—ฌ๋ถ€ ์กฐํšŒ ์„ฑ๋Šฅ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • interview_type: ๋ฉด์ ‘ ์ข…๋ฅ˜(์ธ์„ฑ/๊ธฐ์ˆ ), VARCHAR, NOT NULL
  • current_question_count: ํ˜„์žฌ๊นŒ์ง€ ์ง„ํ–‰๋œ ์งˆ๋ฌธ ์ˆ˜, INT, NOT NULL, DEFAULT 0
  • status: ๋ฉด์ ‘ ์ง„ํ–‰ ์ƒํƒœ(์ง„ํ–‰ ์ค‘, ์™„๋ฃŒ), VARCHAR, NOT NULL, DEFAULT 'IN_PROGRESS'
  • created_at: ๋ฉด์ ‘ ์‹œํ–‰ ์ผ์ž, DATETIME, NOT NULL
  • updated_at: ๋ฉด์ ‘ ์ง„ํ–‰ ์ƒํƒœ ๋ณ€๊ฒฝ ์ผ์ž, DATETIME, NULL, DEFAULT NULL

์•Œ๋ฆผ

notifications

notifications ํ…Œ์ด๋ธ”: ์„œ๋น„์Šค์—์„œ ์ œ๊ณต๋˜๋Š” ์•Œ๋ฆผ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users(recipient) : notifications = 1 : N

users(sender) : notifications = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • recipient_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • ์•Œ๋ฆผ์„ ๋ฐ›๋Š” ์‚ฌ๋žŒ์ด๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ๋„ค์ด๋ฐ ์‚ฌ์šฉ
    • Index(recipient_id, created_at) โ†’ ์•Œ๋ฆผ ์„ผํ„ฐ ๋ชฉ๋ก ์กฐํšŒ์šฉ ์ธ๋ฑ์Šค
    • Index(recipient_id, is_read) โ†’ ์•Œ๋ฆผ ์ฝ์Œ ์ฒ˜๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • sender_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NULL
    • ์•Œ๋ฆผ์„ ๋ณด๋‚ธ ์‚ฌ๋žŒ์ด๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ๋„ค์ด๋ฐ ์‚ฌ์šฉ
    • ์‹œ์Šคํ…œ ์•Œ๋ฆผ์ธ ๊ฒฝ์šฐ NULL
  • category: ์•Œ๋ฆผ ์ข…๋ฅ˜ ํ•„ํ„ฐ๋ง์„ ์œ„ํ•œ ์นดํ…Œ๊ณ ๋ฆฌ, VARCHAR, NOT NULL
  • type: ๋ Œ๋”๋ง ๋กœ์ง ๋ถ„๊ธฐ์šฉ ์•Œ๋ฆผ ํƒ€์ž…, VARCHAR, NOT NULL
  • content: ์•Œ๋ฆผ ๋‚ด์šฉ, VARCHAR, NOT NULL
  • target_path: ์•Œ๋ฆผ ํด๋ฆญ ์‹œ ์ด๋™ํ•  ๊ฒฝ๋กœ, VARCHAR, NOT NULL
  • resource_id: ์•Œ๋ฆผ์˜ ์›์ฒœ์ด ๋˜๋Š” ์ฐธ์กฐ ๋ฐ์ดํ„ฐ ID, BIGINT, NOT NULL
  • is_read: ์•Œ๋ฆผ ์ฝ์Œ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
  • created_at: ์•Œ๋ฆผ ์ƒ์„ฑ์ผ์ž, DATETIME, NOT NULL
  • is_deleted: ์•Œ๋ฆผ ์‚ญ์ œ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
  • deleted_at: ์•Œ๋ฆผ ์‚ญ์ œ์ผ์ž, DATETIME, NULL, DEFAULT NULL

fcm_tokens

fcm_tokens ํ…Œ์ด๋ธ”: ์‹ค์‹œ๊ฐ„ ํ‘ธ์‹œ ์•Œ๋ฆผ์„ ์œ„ํ•œ ์‚ฌ์šฉ์ž์˜ ๊ธฐ๊ธฐ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users : fcm_tokens = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • Index(user_id) โ†’ ์‚ฌ์šฉ์ž๋ณ„ ๊ธฐ๊ธฐ ํ† ํฐ ์กฐํšŒ์šฉ ์ธ๋ฑ์Šค
  • token: ํ‘ธ์‹œ ์•Œ๋ฆผ ๋ฐœ์†ก์„ ์œ„ํ•œ FCM ๋‹จ๋ง๊ธฐ ํ† ํฐ, VARCHAR, NOT NULL, UNIQUE
  • device_type: ํ”Œ๋žซํผ๋ณ„ payload ๋ถ„๊ธฐ๋ฅผ ์œ„ํ•œ ๊ธฐ๊ธฐ ํƒ€์ž…, VARCHAR, NOT NULL
  • device_id: ํŠน์ • ๊ธฐ๊ธฐ ์‹๋ณ„์„ ์œ„ํ•œ ๊ณ ์œ ๊ฐ’(UUID), VARCHAR, NOT NULL
  • is_active: ์•Œ๋ฆผ ํ™œ์„ฑ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT TRUE
  • last_used_at: ๋งˆ์ง€๋ง‰ ํ‘ธ์‹œ ์•Œ๋ฆผ ๋ฐœ์†ก ์„ฑ๊ณต ์‹œ์ , DATETIME, NULL
    • ์˜ค๋žซ๋™์•ˆ ์‚ฌ์šฉ๋˜์ง€ ์•Š์€ ํ† ํฐ์„ ์ •๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์ปฌ๋Ÿผ
    • Index(last_used_at) โ†’ ์˜ค๋ž˜๋œ ํ† ํฐ ์ง€์šฐ๊ธฐ ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • created_at: ๊ธฐ๊ธฐ ๋“ฑ๋ก ์‹œ๊ฐ(FCM ํ† ํฐ ๋“ฑ๋ก ์‹œ๊ฐ), DATETIME, NOT NULL
  • updated_at: FCM ํ† ํฐ์ด ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ณ€๊ฒฝ๋œ ์‹œ๊ฐ, DATETIME, NOT NULL

์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ…

chat_rooms

chat_rooms ํ…Œ์ด๋ธ”: ํ˜„์žฌ ์ƒ์„ฑ๋˜์–ด ์žˆ๋Š” ๊ฐœ์ธ/๊ทธ๋ฃน ์ฑ„ํŒ…๋ฐฉ์˜ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • type: ์ฑ„ํŒ…๋ฐฉ ํƒ€์ž… ๊ตฌ๋ถ„์šฉ, VARCHAR, NOT NULL
    • Index(type, is_deleted, current_count, id) โ†’ ์ธ๊ธฐ ์ฑ„ํŒ…๋ฐฉ ์กฐํšŒ ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
    • Index(type, is_deleted, last_message_at, id) โ†’ ์ฐธ์—ฌ ์ฑ„ํŒ…๋ฐฉ ์กฐํšŒ ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • title: ์ฑ„ํŒ…๋ฐฉ ์ œ๋ชฉ, VARCHAR, NULL
  • tag: ์ฑ„ํŒ…๋ฐฉ ํƒœ๊ทธ, VARCHAR, NULL
    • Index(tag) โ†’ ์ฑ„ํŒ…๋ฐฉ ํƒœ๊ทธ ๊ฒ€์ƒ‰ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • current_count: ํ˜„์žฌ ์ฑ„ํŒ…๋ฐฉ ์ธ์›, INT UNSIGNED, NOT NULL, DEFAULT 1
  • last_message_content: ๋งˆ์ง€๋ง‰์œผ๋กœ ์ˆ˜์‹ ํ•œ ๋ฉ”์‹œ์ง€, TEXT, NULL
  • last_message_at: ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜์‹ ํ•œ ์‹œ๊ฐ, DATETIME, NULL
  • invite_code: ์ดˆ๋Œ€ ์ฝ”๋“œ, VARCHAR, NOT NULL, UNIQUE
  • created_at: ๋ฐฉ ์ƒ์„ฑ์ผ, DATETIME, NOT NULL
  • is_deleted: ๋ฐฉ ์‚ญ์ œ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
  • deleted_at: ๋ฐฉ ์‚ญ์ œ ์‹œ๊ฐ, DATETIME, NULL, DEFAULT NULL

chat_members

chat_members ํ…Œ์ด๋ธ”: ์ฑ„ํŒ…๋ฐฉ์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž๋ณ„ ์ฐธ์—ฌ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

chat_rooms : chat_members = 1 : N

users : chat_members = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • room_id: chat_rooms ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL, UNIQUE(room_id, user_id)
    • ๋ณตํ•ฉ ์œ ๋‹ˆํฌ ์ธ๋ฑ์Šค โ†’ ํ•ด๋‹น ๋ฐฉ์˜ ์ฐธ์—ฌ์ž ์กฐํšŒ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค ๋ฐ ์ค‘๋ณต ์ฐธ์—ฌ ๋ฐฉ์ง€
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • Index(user_id, room_id) โ†’ ์‚ฌ์šฉ์ž๊ฐ€ ์ฐธ์—ฌํ•œ ์ฑ„ํŒ…๋ฐฉ ๋ชฉ๋ก ์กฐํšŒ ์ฟผ๋ฆฌ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
  • room_name: ๊ฐœ์ธํ™”๋œ ๋ฐฉ ์ œ๋ชฉ, VARCHAR, NULL
  • last_read_msg_id: ๋งˆ์ง€๋ง‰์œผ๋กœ ์ฝ์€ ๋ฉ”์‹œ์ง€์˜ ID, BIGINT, NULL
  • is_alarm_on: ์•Œ๋ฆผ ์„ค์ •, BOOLEAN, NOT NULL, DEFAULT TRUE
  • joined_at: ์ฑ„ํŒ…๋ฐฉ ์ž…์žฅ์ผ, DATETIME, NOT NULL

chat_messages

chat_messages ํ…Œ์ด๋ธ”: ์ฑ„ํŒ…๋ฐฉ์—์„œ ์ฃผ๊ณ ๋ฐ›์€ ๋ฉ”์‹œ์ง€ ์ •๋ณด๊ฐ€ ์ €์žฅ๋˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

chat_rooms : chat_messages = 1 : N

users(sender) : chat_messages = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • room_id: chat_rooms ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL
    • Index(room_id, is_deleted, id) โ†’ ์ฑ„ํŒ…๋ฐฉ ์ž…์žฅ ์‹œ ์ด์ „ ๋ฉ”์‹œ์ง€ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
    • created_at ๋Œ€์‹  id๋กœ ์ •๋ ฌ โ†’ ๋ฉ”์‹œ์ง€ ์ƒ์„ฑ ์ˆœ์„œ ๋ณด์žฅ ๊ฐ€๋Šฅ + ์œ ๋‹ˆํฌ
  • sender_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NULL
    • ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ธ ์‚ฌ๋žŒ์ด๋ผ๋Š” ์˜๋ฏธ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋ณ„๋„์˜ ๋„ค์ด๋ฐ ์‚ฌ์šฉ
    • ์‹œ์Šคํ…œ ๋ฉ”์‹œ์ง€์ธ ๊ฒฝ์šฐ NULL
  • type: ๋ฉ”์‹œ์ง€ ์œ ํ˜•, VARCHAR, NOT NULL
  • content: ๋ฉ”์‹œ์ง€ ๋‚ด์šฉ, TEXT, NOT NULL
  • created_at: ๋ฉ”์‹œ์ง€ ์ „์†ก ์‹œ๊ฐ, DATETIME, NOT NULL
  • is_deleted: ๋ฉ”์‹œ์ง€ ์‚ญ์ œ ์—ฌ๋ถ€, BOOLEAN, NOT NULL, DEFAULT FALSE
  • deleted_at: ๋ฉ”์‹œ์ง€ ์‚ญ์ œ ์‹œ๊ฐ, DATETIME, NULL, DEFAULT NULL

chat_search_history

chat_search_history ํ…Œ์ด๋ธ”: ์‚ฌ์šฉ์ž์˜ ์ฑ„ํŒ…๋ฐฉ ๊ฒ€์ƒ‰ ๊ธฐ๋ก์„ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ”

์—ฐ๊ด€ ๊ด€๊ณ„

users : chat_search_history = 1 : N

์ปฌ๋Ÿผ

  • id: ์‹๋ณ„์ž ๋ฐ ๊ธฐ๋ณธํ‚ค(PK), BIGINT, NOT NULL, AUTO_INCREMENT
  • user_id: users ํ…Œ์ด๋ธ”์„ ์ฐธ์กฐํ•˜๋Š” ์™ธ๋ž˜ํ‚ค(FK), BIGINT, NOT NULL, UNIQUE(user_id, keyword)
    • ๋ณตํ•ฉ ์œ ๋‹ˆํฌ ์ธ๋ฑ์Šค โ†’ ์ค‘๋ณต ์ €์žฅ ๋ฐฉ์ง€(Upsert)
    • Index(user_id, created_at) โ†’ ์‚ฌ์šฉ์ž ์ตœ๊ทผ ๊ฒ€์ƒ‰์–ด ์กฐํšŒ ์ตœ์ ํ™”์šฉ ์ธ๋ฑ์Šค
    • ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค ๊ณ ๋ ค : Index(user_id, created_at, keyword)
  • keyword: ๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ, VARCHAR, NOT NULL
  • created_at: ๊ฒ€์ƒ‰ ์‹œ์ , DATETIME, NOT NULL