ERD - Team-likelion-3rd-Project/likelion-devops-7th-3rd-team01 GitHub Wiki

ERD (๊ฐœ๋…)

erDiagram
    users ||--o{ questions : "์งˆ๋ฌธํ•œ๋‹ค"
    users ||--o{ saved_articles : "์ €์žฅํ•œ๋‹ค"

    users {
        bigint user_id PK
        varchar email UK
        varchar password "BCrypt"
        varchar nickname
        datetime created_at
        datetime updated_at
    }
    questions {
        bigint question_id PK
        bigint user_id FK
        varchar query_text
        varchar status "PENDING PROCESSING COMPLETED REJECTED FAILED"
        text answer
        json sources "๊ทผ๊ฑฐ ๊ธฐ์‚ฌ"
        datetime saved_at "์งˆ๋ฌธ ์ €์žฅ(๋ณ„), NULL์ด๋ฉด ์ €์žฅ ์•ˆ ํ•จ"
        datetime created_at
        datetime started_at
        datetime completed_at
    }
    saved_articles {
        bigint saved_article_id PK
        bigint user_id FK
        varchar title
        varchar url "user_id์™€ ํ•จ๊ป˜ UK"
        varchar press
        datetime published_at
        datetime created_at "์ €์žฅ ์‹œ๊ฐ"
    }
    news_articles {
        bigint article_id PK
        varchar category
        varchar title
        text description
        varchar press
        varchar url UK
        datetime published_at
        datetime collected_at
    }
    news_issues {
        bigint issue_id PK
        varchar category
        datetime generated_at "์š”์•ฝ ๋ฐฐ์น˜ ์‹œ๊ฐ"
        int rank_no
        varchar title
        text summary "ํ•œ ์ค„ ์š”์•ฝ"
        json key_points "ํ•ต์‹ฌ ํฌ์ธํŠธ"
        json timeline "์ „๊ฐœ ํ๋ฆ„ (๊ทผ๊ฑฐ ๊ธฐ์‚ฌ๋กœ ๋งŒ๋“ฆ)"
        json glossary "์šฉ์–ด ํ’€์ด"
        json sources "๊ทผ๊ฑฐ ๊ธฐ์‚ฌ"
        boolean mock
    }
  • news_articles(์ˆ˜์ง‘ํ•œ ์›๋ฌธ, ์งˆ๋ฌธ ๋‹ต๋ณ€์˜ ๊ทผ๊ฑฐ ๊ฒ€์ƒ‰ ๋Œ€์ƒ)์™€ news_issues(30๋ถ„๋งˆ๋‹ค ๋งŒ๋“  ๋ถ„์•ผ๋ณ„ ์š”์•ฝ)๋Š” ์‚ฌ์šฉ์ž์™€ ๋ฌด๊ด€ํ•œ ํ…Œ์ด๋ธ”์ด๋ผ ๊ด€๊ณ„์„ ์ด ์—†๋‹ค.

  • ์‹œ๊ฐ„ ์ปฌ๋Ÿผ์€ ๋ชจ๋‘ DATETIME(UTC ์ €์žฅ, ์‘๋‹ต ์‹œ +09:00์œผ๋กœ ๋ณ€ํ™˜).

  • ๋ฌธ์ž์…‹ utf8mb4.

  • ๋ถ„์•ผ ์ฝ”๋“œ(category): AI, IT_GENERAL, MOBILE_TELECOM, COMPUTER, INTERNET, SCIENCE (IT 6๊ฐœ ๋ถ„์•ผ, docs/api-spec.md)

์œ ์ €: users

์ปฌ๋Ÿผ ํƒ€์ž… ๋น„๊ณ 
user_id BIGINT PK, Auto Increment
email VARCHAR(255) NOT NULL, UNIQUE
password VARCHAR(255) NOT NULL, BCrypt ํ•ด์‹œ
nickname VARCHAR(20) NOT NULL
created_at DATETIME NOT NULL, Default CURRENT_TIMESTAMP
updated_at DATETIME NOT NULL, Default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP

์งˆ๋ฌธ: questions

์ปฌ๋Ÿผ ํƒ€์ž… ๋น„๊ณ 
question_id BIGINT PK, Auto Increment
user_id BIGINT NOT NULL, FK (users.user_id) ON DELETE CASCADE
query_text VARCHAR(500) NOT NULL
status VARCHAR(20) NOT NULL (PENDING, PROCESSING, COMPLETED, REJECTED, FAILED)
answer TEXT NULL
sources JSON NULL, ๊ทผ๊ฑฐ ๊ธฐ์‚ฌ [{press, title, url, publishedAt}]
saved_at DATETIME NULL, ์งˆ๋ฌธ ์ €์žฅ(๋ณ„) ์‹œ๊ฐ. NULL์ด๋ฉด ์ €์žฅ ์•ˆ ํ•จ
created_at DATETIME NOT NULL, Default CURRENT_TIMESTAMP
started_at DATETIME NULL, ์›Œ์ปค๊ฐ€ ์ฒ˜๋ฆฌ ์‹œ์ž‘ํ•œ ์‹œ๊ฐ (๊ธฐ๋ก์šฉ. 60์ดˆ ํƒ€์ž„์•„์›ƒ์€ created_at ๊ธฐ์ค€)
completed_at DATETIME NULL

์ธ๋ฑ์Šค

  • (user_id, created_at): ์งˆ๋ฌธ ๊ธฐ๋ก ๋ชฉ๋ก, ํ•˜๋ฃจ ์งˆ๋ฌธ ํšŸ์ˆ˜ ์ง‘๊ณ„
  • (user_id, saved_at): ์ €์žฅํ•œ ์งˆ๋ฌธ ๋ชฉ๋ก
  • (status, created_at): ์˜ค๋ž˜๋œ PENDING ์žฌํˆฌ์ž…, 60์ดˆ ํƒ€์ž„์•„์›ƒ ํŒ์ •

๊ธฐ์กด saved_questions ํ…Œ์ด๋ธ”์€ questions.saved_at์œผ๋กœ ๋Œ€์ฒดํ–ˆ๋‹ค. ์งˆ๋ฌธ 1๊ฐœ์— ๋ณ„์€ ํ•˜๋‚˜๋ฟ์ด๋ผ ๋ณ„๋„ ํ…Œ์ด๋ธ”์ด ํ•„์š” ์—†๊ณ , ๊ธฐ๋ก์„ ์‚ญ์ œํ•˜๋ฉด ๋ณ„๋„ ๊ฐ™์ด ์‚ฌ๋ผ์ง€๋Š” ๊ทœ์น™์ด ์ €์ ˆ๋กœ ์ง€์ผœ์ง„๋‹ค.

์ €์žฅํ•œ ๊ธฐ์‚ฌ: saved_articles

์ปฌ๋Ÿผ ํƒ€์ž… ๋น„๊ณ 
saved_article_id BIGINT PK, Auto Increment
user_id BIGINT NOT NULL, FK (users.user_id) ON DELETE CASCADE
title VARCHAR(255) NOT NULL
url VARCHAR(512) NOT NULL, http(s) ์ฃผ์†Œ๋งŒ
press VARCHAR(100) NULL
published_at DATETIME NULL
created_at DATETIME NOT NULL, Default CURRENT_TIMESTAMP (์ €์žฅ ์‹œ๊ฐ)

์ธ๋ฑ์Šค

  • UNIQUE (user_id, url): ๊ฐ™์€ ๊ธฐ์‚ฌ๋ฅผ ๋‘ ๋ฒˆ ์ €์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค
  • (user_id, created_at): ์ €์žฅํ•œ ๊ธฐ์‚ฌ ๋ชฉ๋ก (์ตœ๊ทผ ์ €์žฅ ์ˆœ)

๋ถ„์•ผ ํŽ˜์ด์ง€์˜ ๊ทผ๊ฑฐ ๊ธฐ์‚ฌ ํ•˜๋‚˜๋ฅผ ์ €์žฅํ•œ๋‹ค. ์›๋ณธ(news_articles)์€ 7์ผ ๋’ค ์ง€์›Œ์ง€๋ฏ€๋กœ news_articles๋ฅผ ๊ฐ€๋ฆฌํ‚ค์ง€ ์•Š๊ณ  ๋‚ด์šฉ์„ ๋ณต์‚ฌํ•ด ๋‘”๋‹ค.

์ˆ˜์ง‘ ๊ธฐ์‚ฌ: news_articles

์ปฌ๋Ÿผ ํƒ€์ž… ๋น„๊ณ 
article_id BIGINT PK, Auto Increment
category VARCHAR(20) NOT NULL, ๋ถ„์•ผ ์ฝ”๋“œ
title VARCHAR(255) NOT NULL
description TEXT NULL, RSS๊ฐ€ ์ฃผ๋Š” ๊ธฐ์‚ฌ ์š”์•ฝ๋ฌธ
press VARCHAR(100) NULL
url VARCHAR(512) NOT NULL, UNIQUE (๊ฐ™์€ ๊ธฐ์‚ฌ ์ค‘๋ณต ์ˆ˜์ง‘ ๋ฐฉ์ง€. ์—ฌ๋Ÿฌ ๋ถ„์•ผ ํ”ผ๋“œ์— ๊ฐ™์€ ๊ธฐ์‚ฌ๊ฐ€ ์žˆ์–ด๋„ ํ•œ ๋ถ„์•ผ์—๋งŒ ์ €์žฅ)
published_at DATETIME NULL
collected_at DATETIME NOT NULL, Default CURRENT_TIMESTAMP

์ธ๋ฑ์Šค

  • (category, collected_at)
  • FULLTEXT (title, description) WITH PARSER ngram: ์งˆ๋ฌธ๊ณผ ๊ด€๋ จ๋œ ๊ธฐ์‚ฌ ๊ฒ€์ƒ‰ (ํ•œ๊ตญ์–ด ๋Œ€์‘)

๋ถ„์•ผ ์š”์•ฝ: news_issues

์ปฌ๋Ÿผ ํƒ€์ž… ๋น„๊ณ 
issue_id BIGINT PK, Auto Increment
category VARCHAR(20) NOT NULL, ๋ถ„์•ผ ์ฝ”๋“œ
generated_at DATETIME NOT NULL, ์š”์•ฝ ๋ฐฐ์น˜ ์‹œ๊ฐ (๊ฐ™์€ ๋ฐฐ์น˜์˜ ์ด์Šˆ๋Š” ๊ฐ™์€ ๊ฐ’)
rank_no INT NOT NULL, ๋ถ„์•ผ ์•ˆ์—์„œ์˜ ์ˆœ์„œ (1๋ถ€ํ„ฐ, ํ™ˆ์€ 1~3)
title VARCHAR(255) NOT NULL
summary TEXT NOT NULL, ํ•œ ์ค„ ์š”์•ฝ
key_points JSON NOT NULL, ํ•ต์‹ฌ ํฌ์ธํŠธ ["...", ...]
timeline JSON NOT NULL, ์ „๊ฐœ ํ๋ฆ„ [{date, text}]. ๊ทผ๊ฑฐ ๊ธฐ์‚ฌ์˜ ๋ฐœํ–‰์ผยท์ œ๋ชฉ์œผ๋กœ ๋งŒ๋“ ๋‹ค (AI๊ฐ€ ๋งŒ๋“ค์ง€ ์•Š์Œ). ๋นˆ ๋ฐฐ์—ด ๊ฐ€๋Šฅ
glossary JSON NOT NULL, ์šฉ์–ด ํ’€์ด [{term, description}]. ๋นˆ ๋ฐฐ์—ด ๊ฐ€๋Šฅ
sources JSON NOT NULL, [{press, title, url, publishedAt}]
mock BOOLEAN NOT NULL, mock AI๋กœ ๋งŒ๋“  ์š”์•ฝ ์—ฌ๋ถ€

์ธ๋ฑ์Šค: (category, generated_at). ๋ถ„์•ผ๋ณ„๋กœ ๊ฐ€์žฅ ์ตœ๊ทผ generated_at์˜ ์ด์Šˆ๋“ค์„ ๋ณด์—ฌ์ค€๋‹ค. ๊ฐฑ์‹ ์— ์‹คํŒจํ•˜๋ฉด ์ƒˆ ํ–‰์ด ์ƒ๊ธฐ์ง€ ์•Š์œผ๋ฏ€๋กœ ์ง์ „ ์š”์•ฝ์ด ๊ทธ๋Œ€๋กœ ๋ณด์ธ๋‹ค.

Redis์—๋Š” ํ™ˆยท๋ถ„์•ผ ์‘๋‹ต์„ ์บ์‹œ๋งŒ ํ•œ๋‹ค (ํ‚ค news:v2:home, news:v2:category:{๋ถ„์•ผ}, TTL 30๋ถ„. ์‘๋‹ต ๋ชจ์–‘์ด ๋ฐ”๋€Œ๋ฉด ๋ฒ„์ „์„ ์˜ฌ๋ฆฐ๋‹ค). ์š”์•ฝ ๋ฐฐ์น˜๊ฐ€ ๋๋‚˜๋ฉด ์บ์‹œ๋ฅผ ๋น„์›Œ ์ƒˆ ์š”์•ฝ์ด ๋ฐ”๋กœ ๋ณด์ธ๋‹ค. Redis๊ฐ€ ์ฃฝ์œผ๋ฉด DB์—์„œ ๋ฐ”๋กœ ์ฝ๋Š”๋‹ค.

๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ (Flyway)

๋ฒ„์ „ ๋‚ด์šฉ
V1 ์ดˆ๊ธฐ ์Šคํ‚ค๋งˆ: users, questions, saved_articles, news_articles, news_issues ๋ฐ FKยท์ธ๋ฑ์Šค
V2 IT 6๊ฐœ ๋ถ„์•ผ๋กœ ๋ณ€๊ฒฝ: ์˜› ๋ถ„์•ผ ๋ฐ์ดํ„ฐ(news_issues, news_articles) ์‚ญ์ œ, ์ €์žฅํ•œ ๊ธฐ์‚ฌ ๊ธฐ๋Šฅ ์ œ์™ธ๋กœ saved_articles ์‚ญ์ œ
V3 ๋ถ„์•ผ ๊ฐœํŽธ(GAME ์ œ์™ธ, AI ์ถ”๊ฐ€): GAME ๊ธฐ์‚ฌ ์‚ญ์ œ. ์ด์Šˆ ์ƒ์„ธ ํ•„๋“œ ์ถ”๊ฐ€: ์˜› news_issues ์‚ญ์ œ ํ›„ key_pointsยทtimelineยทglossary ์ปฌ๋Ÿผ ์ถ”๊ฐ€ (๋‹ค์Œ ๋ฐฐ์น˜๊ฐ€ ๋‹ค์‹œ ์ฑ„์›€)
V4 ์ €์žฅํ•œ ๊ธฐ์‚ฌ ๊ธฐ๋Šฅ ๋ณต๊ตฌ (FE ๋งˆ์ดํŽ˜์ด์ง€): saved_articles ๋‹ค์‹œ ์ƒ์„ฑ