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_INCREMENTuser_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLoriginal_name: ์ฌ์ฉ์๊ฐ ์ ๋ก๋ํ ์๋ณธ ํ์ผ๋ช ,VARCHAR,NOT NULLref_type: ํด๋น ์ฒจ๋ถํ์ผ์ ์ฐธ์กฐํ๋ ๋๋ฉ์ธ,VARCHAR,NOT NULLIndex(ref_type, ref_id, sort_order)โ ํน์ ๊ฒ์๊ธ/์ฑํ ์ ์ฒจ๋ถ๋ ํ์ผ ์กฐํ ๋ฐ ์ ๋ ฌ ์ธ๋ฑ์ค
ref_id: ํด๋น ๋๋ฉ์ธ์ PK,BIGINT,NULLs3_key: ํ์ผ์ด ์ ์ฅ๋ S3 ๊ฒฝ๋ก,VARCHAR,NOT NULLmime_type: ํ์ผ์ ์ ํ,VARCHAR,NOT NULLcategory: ํ์ผ์ ์นดํ ๊ณ ๋ฆฌ(์ด๋ ฅ์, ํฌํธํด๋ฆฌ์ค ๋ฑ),VARCHAR,NULLfile_size: ํ์ผ์ ์ฉ๋(Byte ๋จ์),BIGINT,NOT NULLsort_order: ํ์ผ ์ฒจ๋ถ ์์,TINYINT,NOT NULL,DEFAULT 0created_at: ํ์ผ ์ฒจ๋ถ ์๊ฐ,DATETIME,NOT NULLis_deleted: ์ฒจ๋ถํ์ผ ์ญ์ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSEdeleted_at: ์ฒจ๋ถํ์ผ ์ญ์ ์ผ์,DATETIME,NULL,DEFAULT NULL
async_tasks
async_tasks ํ
์ด๋ธ: ์ฌ์ฉ์๊ฐ ์คํํ ๋น๋๊ธฐ ์์
์ ์ฒ๋ฆฌ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ํ
์ด๋ธ
์ฐ๊ด ๊ด๊ณ
users : async_tasks = 1 : N
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTuser_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULL,UNIQUE(user_id, interest)task_type: ๋น๋๊ธฐ ์์ ์ข ๋ฅ(OCR, MASKING ๋ฑ),VARCHAR,NOT NULLreference_id: ๋น๋๊ธฐ ์ฒ๋ฆฌ ์ค์ธ ํ์ผ์ ID,BIGINT,NOT NULLstatus: ๋น๋๊ธฐ ์ฒ๋ฆฌ ์งํ ์ํ,VARCHAR,NOT NULLIndex(status, is_notified, updated_at)โ ๋น๋๊ธฐ ์์ ์๋ฃ ์๋ฆผ ์ฒ๋ฆฌ์ฉ ์ธ๋ฑ์ค
result: ๋ถ์ ๊ฒฐ๊ณผ ์์ ์ ์ฅ์ฉ ์ปฌ๋ผ,JSON,NULLcreated_at: ์์ ์์ฒญ ์ผ์,DATETIME,NOT NULLupdated_at: ์์ ์ํ ๋ณ๊ฒฝ ์ผ์,DATETIME,NOT NULLis_notified: ์์ ์๋ฃ ์๋ฆผ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSE
ํ์
users
users ํ
์ด๋ธ: ๊ตฌ๊ธ OAuth2๋ก ์ฐ๋ฆฌ ์๋น์ค์ ๊ฐ์
ํ ํ์์ ์ ๋ณด๋ฅผ ์ ์ฅํ๋ ํ
์ด๋ธ
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTemail: ์ฌ์ฉ์์ ๊ตฌ๊ธ ์ด๋ฉ์ผ,VARCHAR,NOT NULL,UNIQUE- ์ค๋ณต ๊ฐ์ ์ ๋ฐฉ์ง
nickname: ์ฐ๋ฆฌ ์๋น์ค์์ ์ฌ์ฉํ ๋๋ค์,VARCHAR,NOT NULL,UNIQUE- ์ค๋ณต ๋๋ค์์ ๋ฐฉ์ง
role: ํ์์ ๊ถํ,VARCHAR,NOT NULL,DEFAULT 'USER'- ๊ถํ ํ ์ด๋ธ ๋ถ๋ฆฌ ๋์ ์ปฌ๋ผ์ ์ถ๊ฐํด ๊ตฌํ ๋ณต์ก๋ ๋ฎ์ถค
created_at: ๊ฐ์ ์ผ์,DATETIME,NOT NULLupdated_at: ํ์์ ๋ณด ์์ ์ผ์,DATETIME,NOT NULLis_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 0updated_at: ํ์ ํ๋ก์ฐ ์์ ๋ง์ง๋ง ๋ณ๊ฒฝ ์๊ฐ,DATETIME,NOT NULL- ์ถํ ์บ์ฑ๊ณผ ๋๊ธฐํ ์ ๋ต ์๋ฆฝ ์ ํ์
user_interests
user_interests ํ
์ด๋ธ: ํ์๊ฐ์
/ํ์์ ๋ณด ์์ ํ๋ฉด์์ ์ค์ ํ ๊ฐ์ธ๋ณ ๊ด์ฌ ๋ถ์ผ๋ฅผ ์ ์ฅํ๋ ํ
์ด๋ธ
์ฐ๊ด ๊ด๊ณ
users : user_interests = 1 : N
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTuser_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULL,UNIQUE(user_id, interest)- ๋ณตํฉ ์ ๋ํฌ ์ธ๋ฑ์ค โ ํ ์ ์ ๊ฐ ๋์ผํ ๊ด์ฌ์ฌ๋ฅผ ์ค๋ณตํด์ ๋ฑ๋กํ๋ ๊ฒ์ DB ์ฐจ์์์ ๋ฐฉ์ง
interest: ๊ฐ์ธ์ด ์ค์ ํ ๊ด์ฌ ๋ถ์ผ,VARCHAR,NOT NULL- ๋ฐ์ ๊ทํ(Denormalization) ์ ์ฉ โ ๋ณ๋์ ๋ง์คํฐ ํ
์ด๋ธ์ ๋์ง ์๊ณ ํ
์คํธ๋ฅผ ์ปฌ๋ผ์ ๋ฐ๋ก ์ ์ฅํ์ฌ
JOIN์ฟผ๋ฆฌ ์ ๊ฑฐ - ๊ด์ฌ ๋ถ์ผ์ ๊ฒฝ์ฐ ๋ด์ฉ ์์ฒด๊ฐ ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ(e.g. ๋ฐฑ์๋ โ BE)๊ฐ ๊ฑฐ์ ์์ ๊ฒ์ด๋ผ๊ณ ํ๋จ, ๋ถํ์ํ Relation์ ์ถ๊ฐํ์ง ์์์
- ์ถํ ๊ด์ฌ ๋ถ์ผ ๊ธฐ๋ฅ ๊ณ ๋ํ ์ ์ ๊ทํ๋ฅผ ํตํ ํ์ฅ ๊ฐ๋ฅ
- ๋ฐ์ ๊ทํ(Denormalization) ์ ์ฉ โ ๋ณ๋์ ๋ง์คํฐ ํ
์ด๋ธ์ ๋์ง ์๊ณ ํ
์คํธ๋ฅผ ์ปฌ๋ผ์ ๋ฐ๋ก ์ ์ฅํ์ฌ
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_INCREMENTuser_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLprovider: ์์ ๋ก๊ทธ์ธ ์ ๊ณต์,VARCHAR,NOT NULL,DEFAULT 'GOOGLE',UNIQUE(provider, provider_user_id)- ๋ณตํฉ ์ ๋ํฌ ์ธ๋ฑ์ค โ
provider_user_id๋ ํ๋์ ํ๋ซํผ ์์์๋ง ์ ์ผํ๋ฏ๋ก ๋ฐ์ดํฐ์ ๋ ผ๋ฆฌ์ ๊ตฌ๋ถ์ ์ํด ID ์ ๊ณต์์ ID๋ฅผ ๋ฌถ์ด ์๋ณ - ๊ฐ์ ์ฌ๋์ด๋ผ๋ ์์ ๋ก๊ทธ์ธ ๋ฐฉ์์ด ๋ค๋ฅด๋ฉด ๋ค๋ฅธ ํ์์ผ๋ก ์ทจ๊ธ
- ๋ณตํฉ ์ ๋ํฌ ์ธ๋ฑ์ค โ
provider_user_id: ์์ ๋ก๊ทธ์ธ ๊ณ ์ ์๋ณ์,VARCHAR,NOT NULLcreated_at: ์์ ๋ก๊ทธ์ธ ์ฐ๋ ์ผ์,DATETIME,NOT NULLaccess_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_INCREMENTuser_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLrefresh_token: ์ฐ๋ฆฌ ์๋น์ค์์ ์ฌ์ฉ์์๊ฒ ๋ฐ๊ธํ ๋ฆฌํ๋ ์ฌ ํ ํฐ,VARCHAR,NOT NULL,UNIQUE- ํ ํฐ์ ๋ฌผ๋ฆฌ์ ์ ์ฅ์ ํตํ ๋ณด์ ํต์ ๊ถ ํ๋ณด โ ๊ฐ์ ๋ก๊ทธ์์/๋ค์ค ๊ธฐ๊ธฐ ๊ด๋ฆฌ
UNIQUE+updated_atโ Refresh Token Rotation ์ง์์ ์ํ ์ปฌ๋ผ
created_at: ๋ฆฌํ๋ ์ฌ ํ ํฐ ๋ฐ๊ธ ์ผ์,DATETIME,NOT NULLexpires_at: ๋ฆฌํ๋ ์ฌ ํ ํฐ ๋ง๋ฃ ์ผ์,DATETIME,NOT NULLupdated_at: ๋ฆฌํ๋ ์ฌ ํ ํฐ ๋ง์ง๋ง ๊ฐฑ์ ์์ ,DATETIME,NOT NULL- RTR ์คํ ์์ ์ ๊ธฐ๋ก
- ๋ฏธ์ฌ์ฉ ๊ธฐ๊ฐ ๋ฐ ํ ํฐ ์ฌ์ฉ ์์ ์ถ์ ์ฉ ์ปฌ๋ผ
์บ๋ฆฐ๋
calendar_events
calendar_events ํ
์ด๋ธ: ๊ตฌ๊ธ ์บ๋ฆฐ๋ API์ ์ฐ๋, ์ฌ์ฉ์์ ์ผ์ ๋ด์ฉ์ ์ ์ฅํ๋ ํ
์ด๋ธ
์ฐ๊ด ๊ด๊ณ
users : calendar_events = 1 : N
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTuser_id:userํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLIndex(user_id, start_at, end_at)โ ์ฌ์ฉ์์ ๊ธฐ๊ฐ ๋ด ์ผ์ ์กฐํ ์ฑ๋ฅ ์ต์ ํ์ฉ ์ธ๋ฑ์ค
google_event_id: ๊ตฌ๊ธ ์ด๋ฒคํธ ID,VARCHAR,NULL,UNIQUE- ๊ตฌ๊ธ ์บ๋ฆฐ๋ API์์ ๋์ด์ค๋ ๊ณ ์ ์๋ณ์
- ๋์ผํ ๊ตฌ๊ธ ์ผ์ ์ ์ค๋ณต ์์ฑ์ ๋ง๊ณ ,
UPSERT๋ก์ง ์ฒ๋ฆฌ๋ฅผ ์ํUNIQUE์ ์ฝ ์ถ๊ฐ - ์๋น์ค ๋ด์์ ์ง์ ์์ฑํ ์ผ์ ์ ๊ตฌ๊ธ API๋ก๋ถํฐ ์ฑ๊ณต ์๋ต์ ๋ฐ๊ธฐ ์ ๊น์ง ์ด๋ฒคํธ ID๊ฐ ์์ผ๋ฏ๋ก
NULL๊ฐ๋ฅ
stage: ์ ํ ๋จ๊ณ,VARCHAR,NOT NULLtitle: ์ผ์ ์ด๋ฆ,VARCHAR,NOT NULLcompany_name: ํ์ฌ๋ช ,VARCHAR,NOT NULLlocation: ์ผ์ ์ํ ์ฅ์,VARCHAR,NULLstart_at: ์์์ผ์,DATETIME,NOT NULLend_at: ์ข ๋ฃ์ผ์,DATETIME,NOT NULLis_all_day: ์ข ์ผ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSEdescription: ์ผ์ ์ ๊ดํ ์์ธ ๋ด์ฉ ๋๋ ๋ฉ๋ชจ,VARCHAR,NULLupdated_at: ์ผ์ ์ ๋ง์ง๋ง ์์ ์๊ฐ,DATETIME,NOT NULLis_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_INCREMENTevent_id:calendar_eventsํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLname: ํ๊ทธ ๋ด์ฉ,VARCHAR,NOT NULLIndex(name)โ ์ฌ์ฉ์๊ฐ ์ํ๋ ํ๊ทธ์ ์ผ์ ๋ง ํํฐ๋งํ ๋ ์ฑ๋ฅ ์ต์ ํ์ฉ ์ธ๋ฑ์ค
event_reminders
event_reminders ํ
์ด๋ธ: ์บ๋ฆฐ๋์ ๋ฑ๋ก๋ ์ผ์ ์ ์๋ฆผ ์ ๋ณด๊ฐ ์ ์ฅ๋๋ ํ
์ด๋ธ
์ฐ๊ด ๊ด๊ณ
calendar_events : event_reminders = 1 : 1
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTevent_id:calendar_eventsํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLremind_unit: ์ผ์ ์๋ฆผ ์๊ฐ์ ๋จ์(๋ถ, ์, ์ผ ๋ฑ),VARCHAR,NOT NULLremind_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 FALSEcreated_at: ์ผ์ ์๋ฆผ ์์ฑ ์๊ฐ,DATETIME,NOT NULL
todos
todos ํ
์ด๋ธ: ์ฌ์ฉ์์ To-Do ์ ๋ณด๊ฐ ์ ์ฅ๋๋ ํ
์ด๋ธ
์ฐ๊ด ๊ด๊ณ
users : todos = 1 : N
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTuser_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLIndex(user_id, target_date)โ ์ฌ์ฉ์๊ฐ ์ ํํ ๋ ์ง์ ํ ์ผ์ ์กฐํํ๋ ์ฟผ๋ฆฌ ์ต์ ํ์ฉ ์ธ๋ฑ์ค
content: ํ ์ผ ๋ด์ฉ,VARCHAR,NOT NULLis_completed: ํ ์ผ ์๋ฃ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSEtarget_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_INCREMENTuser_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLIndex(user_id, is_deleted, created_at, id)โ ๋ด๊ฐ ์์ฑํ ๊ธ ์กฐํ ์ฟผ๋ฆฌ ์ต์ ํ์ฉ ์ธ๋ฑ์ค
title: ๊ฒ์๊ธ ์ ๋ชฉ,VARCHAR,NOT NULLFull text Index(title, content)โ ์ ๋ชฉ ๋ฐ ๋ด์ฉ ๊ฒ์ ์ต์ ํ์ฉ ์ธ๋ฑ์ค
content: ๊ฒ์๊ธ ๋ด์ฉ,LONGTEXT,NOT NULL- ๊ฒ์๊ธ ๋ณธ๋ฌธ(๋งํฌ๋ค์ด)์ ์ ์ฅํ๊ธฐ ์ํด
LONGTEXT์ฑํ
- ๊ฒ์๊ธ ๋ณธ๋ฌธ(๋งํฌ๋ค์ด)์ ์ ์ฅํ๊ธฐ ์ํด
like_count: ์ข์์์,INT UNSIGNED,NOT NULL,DEFAULT 0- ๋ฐ์ ๊ทํ(Denormalization) ์ ์ฉ โ ๋ณ๋์ ํ
์ด๋ธ์์ ๋งค๋ฒ
COUNT์ฟผ๋ฆฌ๋ก ์ง๊ณํ์ง ์๊ณ ์ฝ๊ธฐ ์ฑ๋ฅ์ ํฅ์ํ๊ธฐ ์ํจ - ์ข์์์ ๊ธฐ์ค ์ ๋ ฌ ๋ก์ง์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์ ์ฟผ๋ฆฌ ์ต์ ํ๋ฅผ ์ํด ์ปฌ๋ผ์ผ๋ก ๊ด๋ฆฌ
- ๊ฒ์๊ธ์ ์ฃผ๋ก ๋ฆฌ์คํธ๋ก ์กฐํ โ ์ข์์์๊ฐ ๋ณ๋์ ํ
์ด๋ธ์ ์กด์ฌํ๋ค๋ฉด ๊ฒ์๊ธ ์๋งํผ
JOIN์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํด์ผ ํ๋ฏ๋ก ์ฑ๋ฅ ์ ํ ์ฐ๋ ค - ๊ฒ์๊ธ ๋ฐ์ดํฐ์ ์๋ช ์ฃผ๊ธฐ โ ๊ฒ์๊ธ์ ๋ณดํต ์์ฑ ์งํ์๋ง ์ข์์์๊ฐ ๋น ๋ฅด๊ฒ ๋ณํ๊ณ ๊ทธ ์ดํ์๋ ๊ฑฐ์ Read-Only์ฒ๋ผ ๋์
- ๋ฐ์ ๊ทํ(Denormalization) ์ ์ฉ โ ๋ณ๋์ ํ
์ด๋ธ์์ ๋งค๋ฒ
comment_count: ๋๊ธ์,INT UNSIGNED,NOT NULL,DEFAULT 0- ๋ฐ์ ๊ทํ(Denormalization) ์ ์ฉ โ ๋ณ๋์ ํ
์ด๋ธ์์ ๋งค๋ฒ
COUNT์ฟผ๋ฆฌ๋ก ์ง๊ณํ์ง ์๊ณ ์ฝ๊ธฐ ์ฑ๋ฅ์ ํฅ์ํ๊ธฐ ์ํจ - ๊ฒ์๊ธ์ ์ฃผ๋ก ๋ฆฌ์คํธ๋ก ์กฐํ โ ๋๊ธ์๊ฐ ๋ณ๋์ ํ
์ด๋ธ์ ์กด์ฌํ๋ค๋ฉด ๊ฒ์๊ธ ์๋งํผ
JOIN์ฟผ๋ฆฌ๊ฐ ๋ฐ์ํด์ผ ํ๋ฏ๋ก ์ฑ๋ฅ ์ ํ ์ฐ๋ ค - ๊ฒ์๊ธ ๋ฐ์ดํฐ์ ์๋ช ์ฃผ๊ธฐ โ ๊ฒ์๊ธ์ ๋ณดํต ์์ฑ ์งํ์๋ง ๋๊ธ์๊ฐ ๋น ๋ฅด๊ฒ ๋ณํ๊ณ ๊ทธ ์ดํ์๋ ๊ฑฐ์ Read-Only์ฒ๋ผ ๋์
- ๋ฐ์ ๊ทํ(Denormalization) ์ ์ฉ โ ๋ณ๋์ ํ
์ด๋ธ์์ ๋งค๋ฒ
share_count: ๊ณต์ ์,INT UNSIGNED,NOT NULL,DEFAULT 0created_at: ๊ฒ์๊ธ ์์ฑ ์๊ฐ,DATETIME,NOT NULLupdated_at: ๊ฒ์๊ธ ์์ ์๊ฐ,DATETIME,NOT NULLis_deleted: ๊ฒ์๊ธ ์ญ์ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSEIndex(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_INCREMENTpost_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_INCREMENTpost_id:postsํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLIndex(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 NULLparent_id:commentsํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NULL,DEFAULT NULL- ์๋๊ธ์ด๋ผ๋ ์๋ฏธ๋ฅผ ๋ช ํํ๊ฒ ํ๊ธฐ ์ํด ๋ณ๋์ ๋ค์ด๋ฐ ์ฌ์ฉ
- ์๊ธฐ ์์ ์ ์ฐธ์กฐํ๋ ์ฌ๊ท์ ๊ด๊ณ
- ํด๋น ๊ฐ์ด
NULL์ด๋ฉด ์ต์์ ๋ถ๋ชจ ๋๊ธ(์๋๊ธ), ๊ฐ์ด ์์ผ๋ฉด ํด๋น ๋๊ธ์ ๋ฌ๋ฆฐ ๋ต๊ธ
content: ๋๊ธ ๋ด์ฉ,VARCHAR,NOT NULLcreated_at: ๋๊ธ ์์ฑ์ผ์,DATETIME,NOT NULLupdated_at: ๋๊ธ ์์ฑ์ผ์,DATETIME,NOT NULLis_deleted: ๋๊ธ ์ญ์ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSEdeleted_at: ๋๊ธ ์ญ์ ์ผ์,DATETIME,NULL,DEFAULT NULL
likes
likes ํ
์ด๋ธ: ๊ฒ์๋ฌผ์ ์ข์์ ์ ๋ณด๊ฐ ์ ์ฅ๋๋ ํ
์ด๋ธ
์ฐ๊ด ๊ด๊ณ
posts : likes = 1 : N
users : likes = 1 : N
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTpost_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_INCREMENTuser_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLIndex(user_id, is_deleted, updated_at)โ ์ฌ์ฉ์์ ์ญ์ ๋์ง ์์ ์ฑํ ๋ฐฉ์ ์ต์ ์์ผ๋ก ์กฐํํ๋ ์ฟผ๋ฆฌ๋ฅผ ์ต์ ํํ๋ ์ฉ๋์ ์ธ๋ฑ์ค
room_uuid: AI ์๋ฒ ๋ฐ ๋ฒกํฐ DB์ ๊ณต์ ํ ๊ณ ์ ํค,VARCHAR,NOT NULL,UNIQUE- ์๋ฒ ๋ฉ ๋ฒกํฐ์ ๋ฉํ๋ฐ์ดํฐ์ ํด๋น ํค๊ฐ ๋ค์ด๊ฐ
title: AI ์์ฝ์ผ๋ก ๋ค์ด๊ฐ๋ ์ฑํ ๋ฐฉ ์ ๋ชฉ,VARCHAR,NULL,DEFAULT NULLcreated_at: AI ์ฑํ ๋ฐฉ ์์ฑ์ผ,DATETIME,NOT NULLupdated_at: ๋ง์ง๋ง ์ฑํ ์ผ์,DATETIME,NOT NULLis_deleted: AI ์ฑํ ๋ฐฉ ์ญ์ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSEdeleted_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_INCREMENTroom_id:ai_chat_roomsํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLIndex(room_id, id)โ ํน์ ๋ฐฉ์ ๋ํ ํ๋ฆ(์์) ๋ณต์์ ์ต์ ํํ๋ ์ธ๋ฑ์คcreated_at์ด ์๋id๋ฅผ ์ธ๋ฑ์ค๋ก ์ฌ์ฉํ ์ด์ โ ์ ๋ํฌํ ๊ฐ์ด ๋ณด์ฅ๋์ด ์ ๋ ฌ ๋ถ์ผ์น ๋ฌธ์ ๋ฐฉ์ง
interview_id:ai_chat_interviewํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NULLrole: ์ฑํ ๋ฉ์์ง๋ฅผ ๋ณด๋ธ ์ฃผ์ฒด,VARCHAR,NOT NULLcontent: ์ฑํ ๋ด์ฉ,LONGTEXT,NOT NULL- ๋งค์ฐ ๊ธธ์ด์ง ์ ์๋ AI ์ฑ๋ด ๋ต๋ณ์ ํน์ฑ์ ๊ณ ๋ คํ์ฌ
LONGTEXT์ฑํ
- ๋งค์ฐ ๊ธธ์ด์ง ์ ์๋ AI ์ฑ๋ด ๋ต๋ณ์ ํน์ฑ์ ๊ณ ๋ คํ์ฌ
created_at: ์ฑ๋ด ๋ฉ์์ง ์์ฑ์ผ์,DATETIME,NOT NULLtype: ๋ฉ์์ง์ ์ข ๋ฅ,VARCHAR,NOT NULLmetadata: ์ฑ๋ด ์๋ต์ ๋ฉํ ๋ฐ์ดํฐ,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_INCREMENTroom_id:ai_chat_roomsํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLIndex(room_id)โ ์ฑํ ๋ฐฉ๋ณ ๋ฉด์ ์งํ ์ฌ๋ถ ์กฐํ ์ฑ๋ฅ ์ต์ ํ์ฉ ์ธ๋ฑ์ค
interview_type: ๋ฉด์ ์ข ๋ฅ(์ธ์ฑ/๊ธฐ์ ),VARCHAR,NOT NULLcurrent_question_count: ํ์ฌ๊น์ง ์งํ๋ ์ง๋ฌธ ์,INT,NOT NULL,DEFAULT 0status: ๋ฉด์ ์งํ ์ํ(์งํ ์ค, ์๋ฃ),VARCHAR,NOT NULL,DEFAULT 'IN_PROGRESS'created_at: ๋ฉด์ ์ํ ์ผ์,DATETIME,NOT NULLupdated_at: ๋ฉด์ ์งํ ์ํ ๋ณ๊ฒฝ ์ผ์,DATETIME,NULL,DEFAULT NULL
์๋ฆผ
notifications
notifications ํ
์ด๋ธ: ์๋น์ค์์ ์ ๊ณต๋๋ ์๋ฆผ ์ ๋ณด๊ฐ ์ ์ฅ๋๋ ํ
์ด๋ธ
์ฐ๊ด ๊ด๊ณ
users(recipient) : notifications = 1 : N
users(sender) : notifications = 1 : N
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTrecipient_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 NULLtype: ๋ ๋๋ง ๋ก์ง ๋ถ๊ธฐ์ฉ ์๋ฆผ ํ์ ,VARCHAR,NOT NULLcontent: ์๋ฆผ ๋ด์ฉ,VARCHAR,NOT NULLtarget_path: ์๋ฆผ ํด๋ฆญ ์ ์ด๋ํ ๊ฒฝ๋ก,VARCHAR,NOT NULLresource_id: ์๋ฆผ์ ์์ฒ์ด ๋๋ ์ฐธ์กฐ ๋ฐ์ดํฐ ID,BIGINT,NOT NULLis_read: ์๋ฆผ ์ฝ์ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSEcreated_at: ์๋ฆผ ์์ฑ์ผ์,DATETIME,NOT NULLis_deleted: ์๋ฆผ ์ญ์ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSEdeleted_at: ์๋ฆผ ์ญ์ ์ผ์,DATETIME,NULL,DEFAULT NULL
fcm_tokens
fcm_tokens ํ
์ด๋ธ: ์ค์๊ฐ ํธ์ ์๋ฆผ์ ์ํ ์ฌ์ฉ์์ ๊ธฐ๊ธฐ ์ ๋ณด๊ฐ ์ ์ฅ๋๋ ํ
์ด๋ธ
์ฐ๊ด ๊ด๊ณ
users : fcm_tokens = 1 : N
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTuser_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLIndex(user_id)โ ์ฌ์ฉ์๋ณ ๊ธฐ๊ธฐ ํ ํฐ ์กฐํ์ฉ ์ธ๋ฑ์ค
token: ํธ์ ์๋ฆผ ๋ฐ์ก์ ์ํ FCM ๋จ๋ง๊ธฐ ํ ํฐ,VARCHAR,NOT NULL,UNIQUEdevice_type: ํ๋ซํผ๋ณ payload ๋ถ๊ธฐ๋ฅผ ์ํ ๊ธฐ๊ธฐ ํ์ ,VARCHAR,NOT NULLdevice_id: ํน์ ๊ธฐ๊ธฐ ์๋ณ์ ์ํ ๊ณ ์ ๊ฐ(UUID),VARCHAR,NOT NULLis_active: ์๋ฆผ ํ์ฑ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT TRUElast_used_at: ๋ง์ง๋ง ํธ์ ์๋ฆผ ๋ฐ์ก ์ฑ๊ณต ์์ ,DATETIME,NULL- ์ค๋ซ๋์ ์ฌ์ฉ๋์ง ์์ ํ ํฐ์ ์ ๋ฆฌํ๊ธฐ ์ํ ์ปฌ๋ผ
Index(last_used_at)โ ์ค๋๋ ํ ํฐ ์ง์ฐ๊ธฐ ์ฟผ๋ฆฌ ์ต์ ํ์ฉ ์ธ๋ฑ์ค
created_at: ๊ธฐ๊ธฐ ๋ฑ๋ก ์๊ฐ(FCM ํ ํฐ ๋ฑ๋ก ์๊ฐ),DATETIME,NOT NULLupdated_at: FCM ํ ํฐ์ด ๋ง์ง๋ง์ผ๋ก ๋ณ๊ฒฝ๋ ์๊ฐ,DATETIME,NOT NULL
์ค์๊ฐ ์ฑํ
chat_rooms
chat_rooms ํ
์ด๋ธ: ํ์ฌ ์์ฑ๋์ด ์๋ ๊ฐ์ธ/๊ทธ๋ฃน ์ฑํ
๋ฐฉ์ ์ ๋ณด๊ฐ ์ ์ฅ๋๋ ํ
์ด๋ธ
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTtype: ์ฑํ ๋ฐฉ ํ์ ๊ตฌ๋ถ์ฉ,VARCHAR,NOT NULLIndex(type, is_deleted, current_count, id)โ ์ธ๊ธฐ ์ฑํ ๋ฐฉ ์กฐํ ์ฟผ๋ฆฌ ์ต์ ํ์ฉ ์ธ๋ฑ์คIndex(type, is_deleted, last_message_at, id)โ ์ฐธ์ฌ ์ฑํ ๋ฐฉ ์กฐํ ์ฟผ๋ฆฌ ์ต์ ํ์ฉ ์ธ๋ฑ์ค
title: ์ฑํ ๋ฐฉ ์ ๋ชฉ,VARCHAR,NULLtag: ์ฑํ ๋ฐฉ ํ๊ทธ,VARCHAR,NULLIndex(tag)โ ์ฑํ ๋ฐฉ ํ๊ทธ ๊ฒ์ ์ต์ ํ์ฉ ์ธ๋ฑ์ค
current_count: ํ์ฌ ์ฑํ ๋ฐฉ ์ธ์,INT UNSIGNED,NOT NULL,DEFAULT 1last_message_content: ๋ง์ง๋ง์ผ๋ก ์์ ํ ๋ฉ์์ง,TEXT,NULLlast_message_at: ๋ง์ง๋ง์ผ๋ก ๋ฉ์์ง๋ฅผ ์์ ํ ์๊ฐ,DATETIME,NULLinvite_code: ์ด๋ ์ฝ๋,VARCHAR,NOT NULL,UNIQUEcreated_at: ๋ฐฉ ์์ฑ์ผ,DATETIME,NOT NULLis_deleted: ๋ฐฉ ์ญ์ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSEdeleted_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_INCREMENTroom_id:chat_roomsํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULL,UNIQUE(room_id, user_id)- ๋ณตํฉ ์ ๋ํฌ ์ธ๋ฑ์ค โ ํด๋น ๋ฐฉ์ ์ฐธ์ฌ์ ์กฐํ ์ต์ ํ์ฉ ์ธ๋ฑ์ค ๋ฐ ์ค๋ณต ์ฐธ์ฌ ๋ฐฉ์ง
user_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLIndex(user_id, room_id)โ ์ฌ์ฉ์๊ฐ ์ฐธ์ฌํ ์ฑํ ๋ฐฉ ๋ชฉ๋ก ์กฐํ ์ฟผ๋ฆฌ ์ต์ ํ์ฉ ์ธ๋ฑ์ค
room_name: ๊ฐ์ธํ๋ ๋ฐฉ ์ ๋ชฉ,VARCHAR,NULLlast_read_msg_id: ๋ง์ง๋ง์ผ๋ก ์ฝ์ ๋ฉ์์ง์ ID,BIGINT,NULLis_alarm_on: ์๋ฆผ ์ค์ ,BOOLEAN,NOT NULL,DEFAULT TRUEjoined_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_INCREMENTroom_id:chat_roomsํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NOT NULLIndex(room_id, is_deleted, id)โ ์ฑํ ๋ฐฉ ์ ์ฅ ์ ์ด์ ๋ฉ์์ง ๋ถ๋ฌ์ค๊ธฐ ์ต์ ํ์ฉ ์ธ๋ฑ์คcreated_at๋์id๋ก ์ ๋ ฌ โ ๋ฉ์์ง ์์ฑ ์์ ๋ณด์ฅ ๊ฐ๋ฅ + ์ ๋ํฌ
sender_id:usersํ ์ด๋ธ์ ์ฐธ์กฐํ๋ ์ธ๋ํค(FK),BIGINT,NULL- ๋ฉ์์ง๋ฅผ ๋ณด๋ธ ์ฌ๋์ด๋ผ๋ ์๋ฏธ๋ฅผ ๋ช ํํ๊ฒ ํ๊ธฐ ์ํด ๋ณ๋์ ๋ค์ด๋ฐ ์ฌ์ฉ
- ์์คํ
๋ฉ์์ง์ธ ๊ฒฝ์ฐ
NULL
type: ๋ฉ์์ง ์ ํ,VARCHAR,NOT NULLcontent: ๋ฉ์์ง ๋ด์ฉ,TEXT,NOT NULLcreated_at: ๋ฉ์์ง ์ ์ก ์๊ฐ,DATETIME,NOT NULLis_deleted: ๋ฉ์์ง ์ญ์ ์ฌ๋ถ,BOOLEAN,NOT NULL,DEFAULT FALSEdeleted_at: ๋ฉ์์ง ์ญ์ ์๊ฐ,DATETIME,NULL,DEFAULT NULL
chat_search_history
chat_search_history ํ
์ด๋ธ: ์ฌ์ฉ์์ ์ฑํ
๋ฐฉ ๊ฒ์ ๊ธฐ๋ก์ ์ ์ฅํ๋ ํ
์ด๋ธ
์ฐ๊ด ๊ด๊ณ
users : chat_search_history = 1 : N
์ปฌ๋ผ
id: ์๋ณ์ ๋ฐ ๊ธฐ๋ณธํค(PK),BIGINT,NOT NULL,AUTO_INCREMENTuser_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 NULLcreated_at: ๊ฒ์ ์์ ,DATETIME,NOT NULL