Skip to content

team8-nbc/eightyage

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

221 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ’„ ํ”Œ๋Ÿฌ์Šค ํ”„๋กœ์ ํŠธ - ํ™”์žฅํ’ˆ ์กฐํšŒ ๋ฐ ์ฟ ํฐ ๋ฐœ๊ธ‰ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

Java Spring Boot MySQL Redisson ElastiCache AWS GitHub Actions GitHub

Eighty-age (8์ž์ฃผ๋ฆ„)

Eighty-age๋Š” ์‹ค์‹œ๊ฐ„ ๊ฒ€์ƒ‰๊ณผ ์ฟ ํฐ ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜
ํ™”์žฅํ’ˆ ์ด์ปค๋จธ์Šค ์›น ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.
Redis ๊ธฐ๋ฐ˜ ์บ์‹ฑ๊ณผ ๋™์‹œ์„ฑ ์ œ์–ด๋ฅผ ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.


๐ŸŽฏ ํ”„๋กœ์ ํŠธ ํ•ต์‹ฌ ๋ชฉํ‘œ

  1. ์„ฑ๋Šฅ ์ตœ์ ํ™”

    • Redis ๊ธฐ๋ฐ˜ ์บ์‹ฑ ๋ฐ ์ธ๋ฑ์Šค ํŠœ๋‹์„ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„ ์ƒํ’ˆ ์กฐํšŒ ๋ฐ ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด ์‘๋‹ต ์†๋„ ๊ฐœ์„ 
  2. ๋™์‹œ์„ฑ ์ œ์–ด

    • Redisson ๊ธฐ๋ฐ˜ ๋ถ„์‚ฐ ๋ฝ์œผ๋กœ ์ฟ ํฐ ๋ฐœ๊ธ‰ ์‹œ ์ค‘๋ณต ๋ฐฉ์ง€ ๋ฐ ํŠธ๋žœ์žญ์…˜ ์•ˆ์ •์„ฑ ํ™•๋ณด
  3. ์šด์˜ ๋ฐ ๋ฐฐํฌ ํšจ์œจํ™”

    • GitHub Actions์™€ Docker๋ฅผ ํ™œ์šฉํ•œ CI/CD ๊ตฌ์ถ•
    • AWS ์ธํ”„๋ผ(ECR, EC2, RDS, S3, ElastiCache) ๊ธฐ๋ฐ˜์˜ ์ž๋™ํ™” ๋ฐฐํฌ ํ™˜๊ฒฝ ๊ตฌ์„ฑ

๐Ÿ’ก ์ฃผ์š” ๊ธฐ๋Šฅ

๋„๋ฉ”์ธ ๊ธฐ๋Šฅ ์„ค๋ช…
๐Ÿ‘ค ํšŒ์› ํšŒ์›๊ฐ€์ž… ์‚ฌ์šฉ์ž(User/Admin) ๊ตฌ๋ถ„ ๋“ฑ๋ก, ๋น„๋ฐ€๋ฒˆํ˜ธ ์ •์ฑ… ์ ์šฉ
๐Ÿ‘ค ํšŒ์› ๋กœ๊ทธ์ธ JWT ๋ฐœ๊ธ‰ ๋ฐ ์ธ์ฆ ์ฒ˜๋ฆฌ
๐Ÿ‘ค ํšŒ์› ํšŒ์›์ •๋ณด ์ˆ˜์ • ๋น„๋ฐ€๋ฒˆํ˜ธ ํ™•์ธ ํ›„ ๋‹‰๋„ค์ž„ ๋“ฑ ์ •๋ณด ์ˆ˜์ •
๐Ÿ‘ค ํšŒ์› ํšŒ์›ํƒˆํ‡ด ๋น„๋ฐ€๋ฒˆํ˜ธ ์žฌํ™•์ธ ํ›„ Soft Delete ์ฒ˜๋ฆฌ
๐Ÿ–ผ ์ด๋ฏธ์ง€ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ S3์— ์ €์žฅ ํ›„ URL ๋ฐ˜ํ™˜
๐Ÿงด ์ œํ’ˆ ์ œํ’ˆ ์ƒ์„ฑ ๊ด€๋ฆฌ์ž ๊ถŒํ•œ์œผ๋กœ ์ œํ’ˆ ๋“ฑ๋ก
๐Ÿงด ์ œํ’ˆ ์ œํ’ˆ ์ˆ˜์ • / ์‚ญ์ œ ์ œํ’ˆ ์ •๋ณด ๋ฐ ์ด๋ฏธ์ง€ ์ˆ˜์ •/์‚ญ์ œ
๐Ÿงด ์ œํ’ˆ ์ œํ’ˆ ๋‹จ๊ฑด ์กฐํšŒ ID ๊ธฐ๋ฐ˜ ์ƒ์„ธ ์ •๋ณด ์กฐํšŒ
๐Ÿงด ์ œํ’ˆ ์ œํ’ˆ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ ์ „์ฒด ๋˜๋Š” ํ•„ํ„ฐ ์กฐ๊ฑด์— ๋”ฐ๋ฅธ ๋ฆฌ์ŠคํŠธ ๋ฐ˜ํ™˜
๐Ÿงด ์ œํ’ˆ ์ œํ’ˆ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€/์‚ญ์ œ ์ œํ’ˆ์— ๋‹ค์ค‘ ์ด๋ฏธ์ง€ ์ถ”๊ฐ€ ๋ฐ ์‚ญ์ œ ๊ธฐ๋Šฅ
๐Ÿ” ๊ฒ€์ƒ‰ ์ œํ’ˆ ๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ, ์นดํ…Œ๊ณ ๋ฆฌ, ์ •๋ ฌ ์กฐ๊ฑด ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰
๐Ÿ” ๊ฒ€์ƒ‰ ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด ์ผ์ • ๊ธฐ๊ฐ„ ๋‚ด ๊ฐ€์žฅ ๋งŽ์ด ๊ฒ€์ƒ‰๋œ ํ‚ค์›Œ๋“œ Top-N ์ œ๊ณต
๐Ÿ” ๊ฒ€์ƒ‰ ๊ธ‰์ƒ์Šน ๊ฒ€์ƒ‰์–ด ์ตœ๊ทผ ๊ฒ€์ƒ‰๋Ÿ‰ ๊ธ‰์ฆํ•œ ํ‚ค์›Œ๋“œ ์ž๋™ ์ง‘๊ณ„
๐Ÿ“ ๋ฆฌ๋ทฐ ๋ฆฌ๋ทฐ ์ž‘์„ฑ ๊ตฌ๋งคํ•œ ์œ ์ €์— ํ•œํ•ด ํ‰์  ๋ฐ ์ฝ”๋ฉ˜ํŠธ ๋“ฑ๋ก
๐Ÿ“ ๋ฆฌ๋ทฐ ๋ฆฌ๋ทฐ ์ˆ˜์ • / ์‚ญ์ œ ๋ณธ์ธ์ด ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ ์ˆ˜์ • ๋ฐ ์‚ญ์ œ ๊ฐ€๋Šฅ
๐Ÿ“ ๋ฆฌ๋ทฐ ์ œํ’ˆ๋ณ„ ๋ฆฌ๋ทฐ ์กฐํšŒ ์ œํ’ˆ ์ƒ์„ธ ํŽ˜์ด์ง€ ๋‚ด ๋ฆฌ๋ทฐ ๋ฆฌ์ŠคํŠธ ์ œ๊ณต
๐ŸŽŸ ์ฟ ํฐ ์ฟ ํฐ ์ƒ์„ฑ / ์ˆ˜์ • ๊ด€๋ฆฌ์ž๋งŒ ๋“ฑ๋ก ๊ฐ€๋Šฅ, ์ˆ˜๋Ÿ‰ ๋ฐ ์œ ํšจ๊ธฐ๊ฐ„ ํฌํ•จ
๐ŸŽŸ ์ฟ ํฐ ์ฟ ํฐ ์กฐํšŒ ์ „์ฒด ์ฟ ํฐ ๋˜๋Š” ์ƒํƒœ๋ณ„ ํ•„ํ„ฐ๋ง ์ง€์›
๐ŸŽŸ ์ฟ ํฐ ์ฟ ํฐ ๋‹จ๊ฑด ์กฐํšŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ฟ ํฐ ๋‹จ๊ฑด ์ •๋ณด ๋ฐ˜ํ™˜
๐ŸŽŸ ์ฟ ํฐ ์ฟ ํฐ ๋‹ด๊ธฐ ์‚ฌ์šฉ์ž ์š”์ฒญ ์‹œ ์‚ฌ์šฉ ์กฐ๊ฑด ๋งŒ์กฑํ•˜๋ฉด ๋ฐœ๊ธ‰

๐Ÿ› ๏ธ ๊ธฐ์ˆ  ์Šคํƒ

์–ธ์–ด ๋ฐ ํ”„๋ ˆ์ž„์›Œํฌ

  • Java 17
  • Spring Boot 3.4.4

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

  • MySQL
  • H2

์บ์‹œ ์„œ๋ฒ„

  • Redis (ElastiCache)

์ธ์ฆ ๋ฐ ๋ณด์•ˆ

  • JWT
  • Bcrypt
  • Spring Security

๊ธฐํƒ€

  • JPA
  • JUnit 5
  • GitHub Actions
  • Docker
  • AWS (EC2, S3, RDS, ElastiCache, ECR)

๐Ÿ”ฅ Key Summary

Redisson ๊ธฐ๋ฐ˜ ๋ถ„์‚ฐ ๋ฝ ์ ์šฉ์œผ๋กœ ์•ˆ์ •์ ์ธ ์ฟ ํฐ ๋ฐœ๊ธ‰ ์ฒ˜๋ฆฌ

image

  • ๋™์‹œ์„ฑ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•œ ์ฟ ํฐ ๋ฐœ๊ธ‰ ๊ธฐ๋Šฅ์— Redisson ๊ธฐ๋ฐ˜ ๋ถ„์‚ฐ ๋ฝ ๋„์ž…
  • ๋‹จ์ผ ์„œ๋ฒ„ ํ™˜๊ฒฝ์„ ๊ณ ๋ คํ•ด Redisson Single Server Mode ์‚ฌ์šฉ
  • Redis์— ์ €์žฅ๋œ ์ฟ ํฐ ์ˆ˜๋Ÿ‰์„ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋จผ์ € ์กฐํšŒํ•˜๊ณ  ๊ฐ์†Œ โ†’ ์„ฑ๋Šฅ ๊ฐœ์„ 
  • ๋ถ„์‚ฐ ๋ฝ์„ ํ†ตํ•ด ๋™์‹œ์— ์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ฟ ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›๋Š” ์ƒํ™ฉ์—์„œ๋„ ์ค‘๋ณต ๋ฐœ๊ธ‰, ์ˆ˜๋Ÿ‰ ์ดˆ๊ณผ ๋ฐœ๊ธ‰, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ฏธํก ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€
-ํ•ญ๋ชฉ- -๋„์ž… ์ „- -๋„์ž… ํ›„-
์ฟ ํฐ ์ค‘๋ณต ๋ฐœ๊ธ‰ ๋ฐœ์ƒ ๊ฐ€๋Šฅ ์™„์ „ ๋ฐฉ์ง€
์ดˆ๊ณผ ๋ฐœ๊ธ‰ ๋นˆ๋ฒˆ ๋ฐฉ์ง€
์„ฑ๋Šฅ DB ๋ณ‘๋ชฉ ์žˆ์Œ Redis๋กœ ๊ฐœ์„ 
์•ˆ์ •์„ฑ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ๋ถˆ์•ˆ์ • ๋ฝ๊ณผ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋กœ ์•ˆ์ •ํ™”

์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด ์บ์‹ฑ: DB ์ง‘๊ณ„ ๋ฐฉ์‹ ๋Œ€๋น„ ์‘๋‹ต ์†๋„ 10๋ฐฐ ์ด์ƒ ํ–ฅ์ƒ

  • ๊ธฐ์กด ๋ฐฉ์‹์€ ๊ฒ€์ƒ‰ ๋กœ๊ทธ๋ฅผ ์‹ค์‹œ๊ฐ„ ์ง‘๊ณ„ โ†’ ์‘๋‹ต ์ง€์—ฐ ๋ฐœ์ƒ

  • Redis Sorted Set์œผ๋กœ ์ „ํ™˜ํ•˜์—ฌ 25ms ๋‚ด ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด ์กฐํšŒ ๊ฐ€๋Šฅ

  • DB ์ ‘๊ทผ ์—†์ด ์‹ค์‹œ๊ฐ„ ์ˆœ์œ„ ์กฐํšŒ์— ์ ํ•ฉํ•œ ๊ตฌ์กฐ๋กœ ๊ฐœ์„ 

    ๐Ÿ” ๊ฒ€์ƒ‰ API์— ์บ์‹œ๋ฅผ ์ ์šฉํ•œ ์ด์œ 

    ์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž๊ฐ€ ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ์ œํ’ˆ์„ ๊ฒ€์ƒ‰ํ•˜๋ฉด, ํ•ด๋‹น ๊ฒ€์ƒ‰์–ด๋Š” SearchLog ํ…Œ์ด๋ธ”์— ์ €์žฅ๋œ๋‹ค.
    ์ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉ์ž๋Š” ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด ๋ชฉ๋ก์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

    ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค์ˆ˜์˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด๋ฅผ ์š”์ฒญํ•  ๊ฒฝ์šฐ,
    SearchLog ํ…Œ์ด๋ธ”์—์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ง‘๊ณ„ํ•˜๊ฒŒ ๋˜๋ฉฐ DB์— ๊ณผ๋ถ€ํ•˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
    ์ด๋Š” ์ „์ฒด ์‹œ์Šคํ…œ ์„ฑ๋Šฅ ์ €ํ•˜๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

    ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์บ์‹œ๋ฅผ ์ ์šฉํ•˜์—ฌ,
    DB ์ ‘๊ทผ ์—†์ด ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด๋ฅผ ๋น ๋ฅด๊ฒŒ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•˜์˜€๋‹ค.

์ธ๋ฑ์Šค ํŠœ๋‹์œผ๋กœ ์‹ค์‹œ๊ฐ„ ์ƒํ’ˆ ์กฐํšŒ ์„ฑ๋Šฅ 8.3๋ฐฐ ๊ฐœ์„ 

  • ๋ณตํ•ฉ ์กฐ๊ฑด ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ์— ๋Œ€ํ•ด ์ธ๋ฑ์Šค ์ตœ์ ํ™” ์ ์šฉ โ†’ idx_sale_state_category_name ์ธ๋ฑ์Šค ์‚ฌ์šฉ
  • Postman ๊ธฐ์ค€ 580ms โ†’ 70ms (์•ฝ 8.3๋ฐฐ ์„ฑ๋Šฅ ํ–ฅ์ƒ)
  • ์ฟผ๋ฆฌ ์‹คํ–‰ ๊ณ„ํš ๊ธฐ๋ฐ˜์œผ๋กœ ๋‹ค์–‘ํ•œ ์ธ๋ฑ์Šค๋ฅผ ์‹คํ—˜ํ•˜๊ณ  ๊ฐ€์žฅ ํšจ์œจ์ ์ธ ์กฐํ•ฉ์„ ๋„์ถœ

N+1 ๋ฌธ์ œ ํ•ด๊ฒฐ๋กœ ๋‹ค์ค‘ ์ฟผ๋ฆฌ ์ œ๊ฑฐ

  • Review ์กฐํšŒ ์‹œ ์—ฐ๊ด€๋œ User, Product๋กœ ์ธํ•ด N+1 ๋ฐœ์ƒ
  • JOIN FETCH ์ ์šฉํ•˜์—ฌ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ ํ•œ ๋ฒˆ์— ๋กœ๋”ฉ, ์„ฑ๋Šฅ ๊ฐœ์„ 

GitHub Actions ๊ธฐ๋ฐ˜ CI/CD ๊ตฌ์ถ•

  • PR ์ƒ์„ฑ ์‹œ ์ž๋™ ๋นŒ๋“œ & ํ…Œ์ŠคํŠธ, main ๋ธŒ๋žœ์น˜ ํ‘ธ์‹œ ์‹œ ์ž๋™ ๋ฐฐํฌ
  • Slack ์•Œ๋ฆผ ์—ฐ๋™์œผ๋กœ PR, Merge, ๋ฐฐํฌ ์„ฑ๊ณต/์‹คํŒจ ์ƒํ™ฉ ์‹ค์‹œ๊ฐ„ ๊ณต์œ 
  • AWS ECR์„ ํ†ตํ•œ Docker ์ด๋ฏธ์ง€ ๊ด€๋ฆฌ ๋ฐ EC2 ๋ฐฐํฌ
  • ElastiCache(Redis)๋ฅผ ์ด์šฉํ•œ ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด ๋ฐ ์ฟ ํฐ ์บ์‹ฑ ์ฒ˜๋ฆฌ

โœ… Health Check

๐Ÿ”—๋ฐฐํฌ๋œ ์„œ๋น„์Šค ์ƒํƒœ ๋ณด๊ธฐ

๐Ÿ’ก ๊ธฐ์ˆ ์  ๊ณ ๋„ํ™”

์ธ๋ฑ์Šค ์ ์šฉ์œผ๋กœ ์‘๋‹ต์†๋„ 8.29๋ฐฐ ๊ฐœ์„ 

์ธ๋ฑ์Šค๋ฅผ ํ™œ์šฉํ•œ ์ฟผ๋ฆฌ ์ตœ์ ํ™”


์ตœ์ ํ™” ๋Œ€์ƒ ์ฟผ๋ฆฌ ์„ ์ • ๊ธฐ์ค€

์–ด๋–ค ์กฐ๊ฑด์œผ๋กœ ์ฟผ๋ฆฌ๋ฌธ์„ ์ž‘์„ฑํ•˜๋А๋ƒ์— ๋”ฐ๋ผ DB ์‘๋‹ต์†๋„๊ฐ€ ๋‹ฌ๋ผ์ง€๊ณ , ์ตœ์ ํ™”๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๊ธฐ๋ณธํ‚ค, ์™ธ๋ž˜ํ‚ค, ์œ ๋‹ˆํฌ ์ปฌ๋Ÿผ์€ ์ด๋ฏธ ์ •๋ ฌ๋˜์–ด ์žˆ์–ด ์ธ๋ฑ์Šค ํšจ๊ณผ๊ฐ€ ํฌ์ง€ ์•Š์Œ
  • ๋ฐ˜๋ฉด, ๋ณตํ•ฉ ์กฐ๊ฑด์„ ๊ฐ€์ง€๋Š” ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ๋Š” ์„ฑ๋Šฅ ์ตœ์ ํ™” ํšจ๊ณผ๊ฐ€ ํผ

์„ ํƒํ•œ ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ

@Query("SELECT new com.example.eightyage.domain.product.dto.response.ProductSearchResponseDto(p.name, p.category, p.price, AVG(r.score)) " +
      "FROM Product p LEFT JOIN p.reviews r " +
      "WHERE p.saleState = 'FOR_SALE' " +
      "AND (:category IS NULL OR p.category = :category) " +
      "AND (:name IS NULL OR p.name LIKE CONCAT('%', :name, '%')) " +
      "GROUP BY p.name, p.category, p.price " +
      "ORDER BY AVG(r.score)")

์œ„ ์ฟผ๋ฆฌ์— ์ฟผ๋ฆฌ๋ฌธ ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์ค‘ ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ ์ตœ์ ํ™” ๊ฒฐ์ •

์ธ๋ฑ์Šค ์ ์šฉ๊ณผ ์„ฑ๋Šฅ ๋น„๊ต

์—ฌ๋Ÿฌ ์ธ๋ฑ์Šค ํ›„๋ณด๋ฅผ ์„ ํƒํ•˜์—ฌ ์ธ๋ฑ์Šค ์ ์šฉ ์ „๊ณผ ์„ฑ๋Šฅ ๋ฐ ์‹คํ–‰๊ณ„ํš ๋น„๊ต

Index Strategy Response Time (ms) Actual DB Time Rows Scanned Cost
No Index 580 - 1,019,721 -
idx_sale_state_category_name 70 (8.3x faster) 39.2ms 145,046 1.36e+6
idx_category_sale_state_name 120 (4.8x faster) 51.6ms 145,846 1.36e+6
idx_category_sale_state 152 (3.8x faster) 122ms 109,560 619,582
  • idx_sale_state_category_name ์ธ๋ฑ์Šค ์ ์šฉ์‹œ ์‘๋‹ต์†๋„ ๋ฐ ์‹ค์ œ DB ์‹คํ–‰์‹œ๊ฐ„์ด ๊ฐ€์žฅ ๋น ๋ฅด๋‹ค.
  • postman ์‘๋‹ต์†๋„: 580ms โ†’ 70ms (8.29๋ฐฐ ๊ฐœ์„ )

๊ทธ๋ž˜ํ”„

์‘๋‹ต์‹œ๊ฐ„๊ทธ๋ž˜ํ”„

ํ–ฅํ›„ ๊ณ„ํš

  • ๊ฒ€์ƒ‰ ์„ฑ๋Šฅ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด ์ „๋ฌธ์ธ๋ฑ์Šค๋‚˜ Elastic Search ๋ฐ ๋” ์ •ํ™•ํ•œ ๊ฒ€์ƒ‰์—”์ง„ ์‚ฌ์šฉ
Redis ์บ์‹œ๋กœ ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด ์กฐํšŒ ์‘๋‹ต ์†๋„ 2.13๋ฐฐ ๊ฐœ์„ 

์„ฑ๋Šฅ ๋น„๊ต: DB ์ง‘๊ณ„ ๋ฐฉ์‹ vs Redis ์บ์‹œ ๋ฐฉ์‹

๋ฒ„์ „ ๋ฐฉ์‹ ์‘๋‹ต ์†๋„ (ms) ๊ฐœ์„ ๋ฅ 
V1 DB ์‹ค์‹œ๊ฐ„ ์ง‘๊ณ„ 49 ms ๊ธฐ์ค€๊ฐ’
V2 Redis Sorted Set 23 ms ๐Ÿ”ฅ ์•ฝ 2.13๋ฐฐ ๊ฐœ์„ 

๊ทธ๋ž˜ํ”„

Response Time Graph

  • V1์€ ๊ฒ€์ƒ‰ ๋กœ๊ทธ ํ…Œ์ด๋ธ”์—์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ง‘๊ณ„ํ•˜์—ฌ ์‘๋‹ต โ†’ 49ms ์†Œ์š”
  • V2๋Š” ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด๋ฅผ Redis Sorted Set์— ์บ์‹ฑํ•˜์—ฌ ์กฐํšŒ โ†’ 23ms ์†Œ์š”
  • DB ์ ‘๊ทผ ์—†์ด ๋น ๋ฅด๊ฒŒ ์ธ๊ธฐ ํ‚ค์›Œ๋“œ๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์–ด ์„œ๋ฒ„ ๋ถ€ํ•˜๋ฅผ ์ค„์ด๊ณ  ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ํ–ฅ์ƒ
N+1 ๋ฌธ์ œ ํ•ด๊ฒฐ: JOIN FETCH๋กœ ์„ฑ๋Šฅ ๊ฐœ์„ 

๋ฌธ์ œ ์š”์•ฝ

์ƒํ’ˆ ์‚ญ์ œ ์‹œ ๊ด€๋ จ ๋ฆฌ๋ทฐ๋“ค์„ soft delete ์ฒ˜๋ฆฌํ•˜๋Š” ๊ณผ์ •์—์„œ
Review โ†’ User, Review โ†’ Product ์ง€์—ฐ๋กœ๋”ฉ์œผ๋กœ ์ธํ•ด N+1 ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

๋ฌธ์ œ ์ฝ”๋“œ

// ProductService.java - deleteProduct ๋ฉ”์†Œ๋“œ
Product findProduct = productRepository.findProductByIdOrElseThrow(productId);
List<Review> findReviewList = reviewRepository.findReviewsByProductId(productId);

for (Review review : findReviewList){
    review.setDeletedAt(LocalDateTime.now());
}

// ProductRepository.java
@Query("SELECT r FROM Review r WHERE r.product.id = :productId AND r.deletedAt IS NULL")
List<Review> findReviewsByProductId(@Param("productId") Long productId);
  • Review์™€ ์—ฐ๊ด€๋œ User, Product๊ฐ€ ์ง€์—ฐ๋กœ๋”ฉ(LAZY) ๋˜์–ด ์กฐํšŒ ์‹œ๋งˆ๋‹ค ์ถ”๊ฐ€ ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒ โ†’ N+1

๊ฐ€์„ค

  • findReviewList๊ฐ€ N๊ฐœ๋ผ๋ฉด, ๊ฐ๊ฐ์˜ Review๋งˆ๋‹ค User, Product ์กฐํšŒ ์ฟผ๋ฆฌ 1ํšŒ์”ฉ ์ถ”๊ฐ€ ์‹คํ–‰๋จ
  • ์ด 1 + (2 ร— N) ๊ฐœ์˜ ์ฟผ๋ฆฌ ๋ฐœ์ƒ โ†’ ์‹ฌ๊ฐํ•œ ์„ฑ๋Šฅ ์ €ํ•˜

ํ•ด๊ฒฐ ๋ฐฉ์•ˆ

  • JOIN FETCH vs. @EntityGraph๋ฅผ ๋น„๊ตํ•˜์—ฌ ์„ฑ๋Šฅ ์šฐ์œ„์ธ JOIN FETCH ์„ ํƒ
  • JOIN FETCH์˜ ๊ฒฝ์šฐ ์ถ”๊ฐ€์ ์ธ SELECT ์—†์ด 1๋ฒˆ์˜ ์ฆ‰์‹œ ์กฐ์ธ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์–ด @EntityGraph ๋ณด๋‹ค ์„ฑ๋Šฅ์ด ์ข‹๋‹ค๊ณ  ํŒ๋‹จ

ํ•ด๊ฒฐ ์™„๋ฃŒ

@Query("SELECT r FROM Review r JOIN FETCH r.user JOIN FETCH r.product WHERE r.product.id = :productId AND r.deletedAt IS NULL")
List<Review> findReviewsByProductId(@Param("productId") Long productId);
  • JOIN FETCH ๋กœ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ๋ฒˆ์— ๊ฐ€์ ธ์™€์„œ ํ•ด๊ฒฐํ–ˆ๋‹ค.

โš ๏ธ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… ๋ชจ์Œ


โš™๏ธ ์ธํ”„๋ผ ์•„ํ‚คํ…์ฒ˜ & ์ ์šฉ ๊ธฐ์ˆ 

์•„ํ‚คํ…์ฒ˜ ๋‹ค์ด์–ด๊ทธ๋žจ

CI/CD ํŒŒ์ดํ”„๋ผ์ธ

๋ณธ ์•„ํ‚คํ…์ฒ˜๋Š” Spring Boot ๊ธฐ๋ฐ˜์˜ ๋‹จ์ผ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์กฐ๋กœ,
Docker ์ปจํ…Œ์ด๋„ˆํ™”, GitHub Actions ๊ธฐ๋ฐ˜ CI/CD,
๊ทธ๋ฆฌ๊ณ  AWS EC2 / RDS / S3 / ElastiCache๋ฅผ ์—ฐ๋™ํ•˜์—ฌ
์ž๋™ํ™”๋œ ๋ฐฐํฌ์™€ ์•ˆ์ •์ ์ธ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“ฆ ์ ์šฉ ๊ธฐ์ˆ  ์ƒ์„ธ๋ณด๊ธฐ

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค & ์บ์‹œ

  • MySQL (RDS)
    โ†’ ์‚ฌ์šฉ์ž, ์ œํ’ˆ, ๋ฆฌ๋ทฐ, ์ฟ ํฐ ๋“ฑ์˜ ์ฃผ์š” ๋ฐ์ดํ„ฐ ์ €์žฅ

  • Redis (ElastiCache)
    โ†’ ์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด, ์ตœ์ €๊ฐ€ ์บ์‹ฑ์— ์‚ฌ์šฉ. TTL ๊ธฐ๋ฐ˜ ๋งŒ๋ฃŒ ์ฒ˜๋ฆฌ๋กœ ํšจ์œจ์  ๋ฐ์ดํ„ฐ ์œ ์ง€

ํด๋ผ์šฐ๋“œ & ์ €์žฅ์†Œ

  • AWS S3
    โ†’ ์ œํ’ˆ/ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๋ฐ ์ •์  ๋ฆฌ์†Œ์Šค ์ €์žฅ

  • AWS EC2
    โ†’ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ ํ˜ธ์ŠคํŒ…

  • AWS RDS / ElastiCache / ECR
    โ†’ ๊ฐ๊ฐ DB, ์บ์‹œ, ๋„์ปค ์ด๋ฏธ์ง€ ์ €์žฅ์†Œ ์—ญํ• 

๋ฐฐํฌ & ์ž๋™ํ™”

  • Docker
    โ†’ ๊ฐ ๋ชจ๋“ˆ/์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ปจํ…Œ์ด๋„ˆํ™”

  • GitHub Actions
    โ†’ CI/CD ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•, Slack ์—ฐ๋™ ์•Œ๋ฆผ ํฌํ•จ
    โ†’ main ๋ธŒ๋žœ์น˜ ํ‘ธ์‹œ ๋ฐ PR Merge ์‹œ ์ž๋™ ๋ฐฐํฌ ํŠธ๋ฆฌ๊ฑฐ


๐Ÿงฌ ERD

ERD


๐Ÿ“œ API ๋ช…์„ธ์„œ

API ๋ช…์„ธ์„œ ๋ณด๊ธฐ


๐Ÿ–ผ๏ธ ์™€์ด์–ดํ”„๋ ˆ์ž„

์™€์ด์–ด ํ”„๋ ˆ์ž„ ๋ณด๊ธฐ


โค๏ธ ํŒ€์› ์†Œ๊ฐœ

์ด์ฑ„์›
๐Ÿ‘‘ ํŒ€์žฅ
์ด์ฑ„์›
CI/CD
GitHub
๋ด‰์ˆ˜ํ˜„
โœจ ํŒ€์›
๋ด‰์ˆ˜ํ˜„
์ฟ ํฐ
GitHub
์ด์ง€์€A
โœจ ํŒ€์›
์ด์ง€์€A
์ธ์ฆ / ์ธ๊ฐ€
GitHub
์ด์ง€์€B
โœจ ํŒ€์›
์ด์ง€์€B
์ œํ’ˆ / ๋ฆฌ๋ทฐ
GitHub
์ „์„œ์—ฐ
โœจ ํŒ€์›
์ „์„œ์—ฐ
์ธ๊ธฐ ๊ฒ€์ƒ‰์–ด
GitHub

About

๐Ÿ’„ Eighty-age: ํ™”์žฅํ’ˆ ์กฐํšŒ ๋ฐ ์ฟ ํฐ ๋ฐœ๊ธ‰ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors