Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

hyunho12/PookyBlog

Repository files navigation

๐Ÿ“– PookyBlog: ๊ณ ์„ฑ๋Šฅ, ํ™•์žฅ์„ฑ์„ ๊ณ ๋ คํ•œ ๋ธ”๋กœ๊ทธ ๋ฐฑ์—”๋“œ ์‹œ์Šคํ…œ

PookyBlog๋Š” ๋‹จ์ˆœํ•œ CRUD ๊ธฐ๋Šฅ์„ ๋„˜์–ด, ๋Œ€์šฉ๋Ÿ‰ ํŠธ๋ž˜ํ”ฝ ํ™˜๊ฒฝ์—์„œ๋„ ์•ˆ์ •์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ณ ์„ฑ๋Šฅ ๋ฐฑ์—”๋“œ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•˜๊ธฐ ์œ„ํ•œ ๊ฐœ์ธ ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค. ๋„๋ฉ”์ธ ๊ธฐ๋ฐ˜์˜ ๋ฉ€ํ‹ฐ ๋ชจ๋“ˆ ๊ตฌ์กฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ CQRS(๋ช…๋ น๊ณผ ์กฐํšŒ ์ฑ…์ž„ ๋ถ„๋ฆฌ), ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜ ๋“ฑ ํ˜„๋Œ€์ ์ธ ์„ค๊ณ„ ์›์น™์„ ์ ์šฉํ•˜์—ฌ ์‹ค์ œ ์„œ๋น„์Šค ์ˆ˜์ค€์˜ ๊ธฐ์ˆ ์  ๊ณผ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ์ง‘์ค‘ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด ๊ธฐ์ˆ ์˜ ์›๋ฆฌ๋ฅผ ๊นŠ์ด ํƒ๊ตฌํ•˜๊ณ , ์„ฑ๋Šฅ์„ ์ธก์ •ํ•˜๋ฉฐ, ์‹œ์Šคํ…œ์„ ์ ์ง„์ ์œผ๋กœ ๊ฐœ์„ ํ•ด ๋‚˜๊ฐ€๋Š” ๊ณผ์ •์„ ๊ธฐ๋กํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ› ๏ธ ๊ธฐ์ˆ  ์Šคํƒ (Tech Stack)

Java Spring Boot Spring Security JPA QueryDSL

MySQL Redis Kafka

Gradle GitHub IntelliJ

๐Ÿ—๏ธ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ (Project Structure)

๋„๋ฉ”์ธ ์ค‘์‹ฌ์˜ ๋ฉ€ํ‹ฐ ๋ชจ๋“ˆ ์„ค๊ณ„๋ฅผ ํ†ตํ•ด ๊ฐ ๋ชจ๋“ˆ์˜ ์ฑ…์ž„๊ณผ ์˜์กด์„ฑ์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•˜์—ฌ ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ๋†’์˜€์Šต๋‹ˆ๋‹ค.

.
โ”œโ”€โ”€ pookyBlog (root)
โ”‚
โ”œโ”€โ”€ ๐Ÿ“ common # Outbox, Snowflake ๋“ฑ ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์—์„œ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ
โ”‚
โ”œโ”€โ”€ ๐Ÿ“ services # ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ๋„๋ฉ”์ธ ๋ชจ๋ธ์„ ํฌํ•จํ•˜๋Š” ์„œ๋น„์Šค ๊ณ„์ธต
โ”‚ โ”œโ”€โ”€ ๐Ÿ“ comment
โ”‚ โ”œโ”€โ”€ ๐Ÿ“ hot-post
โ”‚ โ”œโ”€โ”€ ๐Ÿ“ like
โ”‚ โ”œโ”€โ”€ ๐Ÿ“ post
โ”‚ โ”œโ”€โ”€ ๐Ÿ“ post-read # CQRS์˜ ์กฐํšŒ(Query) ์ฑ…์ž„ ๋ชจ๋“ˆ
โ”‚ โ”œโ”€โ”€ ๐Ÿ“ user
โ”‚ โ””โ”€โ”€ ๐Ÿ“ view
โ”‚
โ”œโ”€โ”€ ๐Ÿ“ web # API End-point๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์™ธ๋ถ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์›น ๊ณ„์ธต
โ”‚
โ””โ”€โ”€ build.gradle

๐Ÿ›๏ธ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ (System Architecture)

CQRS ํŒจํ„ด์„ ๊ธฐ๋ฐ˜์œผ๋กœ, ์‹œ์Šคํ…œ์˜ ์“ฐ๊ธฐ ์ฑ…์ž„(Command)๊ณผ ์ฝ๊ธฐ ์ฑ…์ž„(Query)์„ ๋ถ„๋ฆฌํ•˜์—ฌ ํ™•์žฅ์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ๊ทน๋Œ€ํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค.

graph TD
 %% ๋…ธ๋“œ ์ •์˜
 subgraph Client
 UserRequest[์‚ฌ์šฉ์ž ์š”์ฒญ]
 end
 subgraph "Command Service (์“ฐ๊ธฐ/์ˆ˜์ • ์ฑ…์ž„)"
 direction LR
 A[API Controller]
 B(Business Logic)
 C{JPA & Outbox}
 D[MySQL]
 E[Outbox Table]
 end
 subgraph "Query Service (์กฐํšŒ ์ฑ…์ž„)"
 direction LR
 G[Kafka Consumer]
 H[Data Projection]
 I[Redis]
 end
 F[Message Queue - Kafka]
 %% ํ™”์‚ดํ‘œ ์—ฐ๊ฒฐ
 UserRequest -- "CUD Request" --> A
 A --> B
 B -- "@Transactional" --> C
 C --> D
 C --> E
 E -- "Kafka Connect / Scheduler" --> F
 F --> G
 G --> H
 H --> I
 UserRequest -- "Read Request" --> A
 A -- "1. Read from Cache" --> I
 A -- "2. Cache-Miss ์‹œ Fallback" --> B
Loading
  1. **์“ฐ๊ธฐ/์ˆ˜์ •/์‚ญ์ œ ์š”์ฒญ(Command)**์€ Command Service๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌ๋˜๋ฉฐ, ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ์€ ์ฃผ DB์™€ Outbox ํ…Œ์ด๋ธ”์— ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ์ปค๋ฐ‹๋˜์–ด ๋ฐ์ดํ„ฐ ์ •ํ•ฉ์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
  2. Outbox์— ์Œ“์ธ ์ด๋ฒคํŠธ๋Š” Kafka๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ๋ฐœํ–‰๋ฉ๋‹ˆ๋‹ค.
  3. **์กฐํšŒ ์š”์ฒญ(Query)**์€ 1์ฐจ์ ์œผ๋กœ Redis์—์„œ ์ฒ˜๋ฆฌ๋˜์–ด ๋งค์šฐ ๋น ๋ฅธ ์‘๋‹ต ์†๋„๋ฅผ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. Redis์— ๋ฐ์ดํ„ฐ๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—๋งŒ DB๋ฅผ ์กฐํšŒํ•˜๋Š” ํด๋ฐฑ(Fallback) ๋กœ์ง์œผ๋กœ ์•ˆ์ •์„ฑ์„ ํ™•๋ณดํ–ˆ์Šต๋‹ˆ๋‹ค.
  4. Query Service์˜ Kafka Consumer๋Š” ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ ์กฐํšŒ ๋ชจ๋ธ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ตœ์‹  ์ƒํƒœ๋กœ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ’พ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ERD (Database ERD)

erDiagram
 USER {
 bigint id PK "์œ ์ € ID"
 string username
 string password
 string email
 string nickname
 Role role
 }
 POST {
 bigint id PK "๊ฒŒ์‹œ๊ธ€ ID"
 bigint user_id FK
 string title
 text content
 string writer
 int view
 }
 COMMENT {
 bigint id PK "๋Œ“๊ธ€ ID"
 bigint post_id FK
 bigint user_id FK
 text comments
 }
 POST_LIKE {
 bigint id PK "์ข‹์•„์š” ID"
 bigint post_id FK
 bigint user_id FK
 }
 LIKE_COUNT {
 bigint id PK "๊ฒŒ์‹œ๊ธ€ ID์™€ ๋™์ผ"
 long likeCount
 long version "๋‚™๊ด€์  ๋ฝ์„ ์œ„ํ•œ ๋ฒ„์ „"
 }
 USER ||--o{ POST : "์ž‘์„ฑ"
 USER ||--o{ COMMENT : "์ž‘์„ฑ"
 USER ||--o{ POST_LIKE : "ํด๋ฆญ"
 POST ||--o{ COMMENT : "ํฌํ•จ"
 POST ||--o{ POST_LIKE : "ํฌํ•จ"
 POST ||--|{ LIKE_COUNT : "๊ฐ€์ง"
Loading

๐Ÿš€ ์ฃผ์š” ๊ธฐ์ˆ  ๋ฐ ์„ฑ๊ณผ (Key Features & Achievements)

๊ตฌ๋ถ„ ๋ฌธ์ œ ์ •์˜ (Problem) ํ•ด๊ฒฐ ๋ฐฉ์•ˆ (Solution) & ์„ฑ๊ณผ
CQRS & ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ธ ์กฐํšŒ ์‹œ ๋ฐœ์ƒํ•˜๋Š” ๋‹ค์ค‘ JOIN์œผ๋กœ ์ธํ•œ DB ๋ถ€ํ•˜์™€ ์‘๋‹ต ์†๋„ ์ €ํ•˜ CQRS ํŒจํ„ด์„ ๋„์ž…ํ•˜์—ฌ ์กฐํšŒ ์ „์šฉ ๋ชจ๋ธ์„ Redis์— ๊ตฌ์ถ•. DB ์กฐ์ธ ์—†์ด O(1) ์‹œ๊ฐ„ ๋ณต์žก๋„๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋„๋ก ์‹œ์Šคํ…œ ์„ค๊ณ„.
์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜ ์‹ค์‹œ๊ฐ„ ์ธ๊ธฐ๊ธ€ ์ง‘๊ณ„ ๋กœ์ง์ด ์ฃผ์š” ๋น„์ฆˆ๋‹ˆ์Šค์™€ ๊ฐ•ํ•˜๊ฒŒ ๊ฒฐํ•ฉ๋˜์–ด ํ™•์žฅ์„ฑ์ด ๋–จ์–ด์ง€๋Š” ๋ฌธ์ œ Outbox ํŒจํ„ด๊ณผ Kafka๋ฅผ ํ™œ์šฉํ•ด ์ด๋ฒคํŠธ ๋ฐœํ–‰์˜ ์ •ํ•ฉ์„ฑ์„ ๋ณด์žฅํ•˜๊ณ  ์‹œ์Šคํ…œ ๊ฐ„ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถค. Redis์˜ Sorted Set์„ ์ด์šฉํ•ด ์ธ๊ธฐ๊ธ€ ๋žญํ‚น ์กฐํšŒ ์„ฑ๋Šฅ ์ตœ์ ํ™”.
๋™์‹œ์„ฑ ์ œ์–ด ๋‹ค์ˆ˜์˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— '์ข‹์•„์š”' ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์Ÿ ์ƒํƒœ(Race Condition)๋กœ ์ธํ•œ ๋ฐ์ดํ„ฐ ์œ ์‹ค ๋น„๊ด€์ /๋‚™๊ด€์  ๋ฝ์„ ์ง์ ‘ ์ ์šฉํ•˜๊ณ , CountDownLatch ๊ธฐ๋ฐ˜์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋กœ ์„ฑ๋Šฅ์„ ๋น„๊ต ๋ถ„์„ํ•˜์—ฌ ๊ฐ ๊ธฐ์ˆ ์˜ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„๋ฅผ ์ฒด๋“.
API ์‘๋‹ต ์†๋„ ๊ฐœ์„  ๋ฐ์ดํ„ฐ ์ฆ๊ฐ€์— ๋”ฐ๋ฅธ ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก ์กฐํšŒ API์˜ ์„ฑ๋Šฅ ์ €ํ•˜ ๋ถˆํ•„์š”ํ•œ I/O๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ์ปค๋ฒ„๋ง ์ธ๋ฑ์Šค ์ ์šฉ. ์‹คํ–‰ ์‹œ๊ฐ„ ์•ฝ 69% ๊ฐœ์„  (21.97์ดˆ โ†’ 6.85์ดˆ).
์บ์‹ฑ ๋ฐ DB ๋ถ€ํ•˜ ๋ถ„์‚ฐ ์กฐํšŒ์ˆ˜ ์ฆ๊ฐ€ ์š”์ฒญ์ด DB์— ์ง์ ‘์ ์ธ ๋ถ€ํ•˜๋ฅผ ์ฃผ๋Š” ๋ฌธ์ œ Redis ๋ถ„์‚ฐ ๋ฝ์œผ๋กœ ์ค‘๋ณต ์กฐํšŒ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ , 100ํšŒ ๋‹จ์œ„์˜ ๋ฐฐ์น˜ ์—…๋ฐ์ดํŠธ๋กœ DB ์“ฐ๊ธฐ ๋ถ€ํ•˜๋ฅผ ์ตœ์†Œํ™”.

โœ๏ธ ๊ธฐ์ˆ  ํƒ๊ตฌ ๊ธฐ๋ก (Technical Deep Dive on Blog)

ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ๋งˆ์ฃผํ•œ ๊ธฐ์ˆ ์  ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ ๊ณผ์ •, ๊ทธ๋ฆฌ๊ณ  ์„ค๊ณ„์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์„ ๋ธ”๋กœ๊ทธ์— ์ƒ์„ธํžˆ ๊ธฐ๋กํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

AltStyle ใซใ‚ˆใฃใฆๅค‰ๆ›ใ•ใ‚ŒใŸใƒšใƒผใ‚ธ (->ใ‚ชใƒชใ‚ธใƒŠใƒซ) /