Skip to content

Latest commit

ย 

History

History
358 lines (262 loc) ยท 18.2 KB

File metadata and controls

358 lines (262 loc) ยท 18.2 KB
Image

๐Ÿ…ฟ๏ธ ParkEZ: ์‰ฝ๊ณ  ๋น ๋ฅธ ํ†ตํ•ฉ ์ฃผ์ฐจ ํ”Œ๋žซํผ ํŒ€ ํ”„๋กœ์ ํŠธ

๐Ÿ™‹โ€โ™€๏ธ ParkEZ ํŒ€ ํ”„๋กœ์ ํŠธ ์„ค๋ช…

  • ParkEZ ํŒ€ ํ”„๋กœ์ ํŠธ๋Š” ์‚ฌ์šฉ์ž์™€ ์ฃผ์ฐจ์žฅ ์†Œ์œ ์ž๋ฅผ ์œ„ํ•œ ์˜ˆ์•ฝ, ๊ฒฐ์ œ, ์ •์‚ฐ์ด ๊ฐ€๋Šฅํ•œ ํ†ตํ•ฉ ์ฃผ์ฐจ ํ”Œ๋žซํผ์„ ๊ตฌํ˜„ํ•œ ํŒ€ ํ”„๋กœ์ ํŠธ์ž…๋‹ˆ๋‹ค.
  • ํŒ€์› : ์กฐ์˜ˆ์ธ, ์ •์ค€ํ˜ธ, ์ด๋ฏผ์ •, ์ „์„œ์—ฐ, ์žฅ์œคํ˜
  • ๊ธฐ๊ฐ„ : 2025.04.01 - 2025.05.06

๐Ÿ“‘ ํŒ€ ๋…ธ์…˜ : ParkEZ

๐Ÿ“‘ ํŒ€ ๋ธŒ๋กœ์…” : 10์กฐ - Park10EZ

๐Ÿ“‘ ๋„๋ฉ”์ธ : parkez.click

๐Ÿ“‘ ์‹œ์—ฐ์˜์ƒ : ParkEZ ์‹œ์—ฐ์˜์ƒ


๐Ÿง‘โ€๐Ÿง‘โ€๐Ÿง’โ€๐Ÿง’ ์—ญํ•  ๋ถ„๋‹ด

๐Ÿฃ ์กฐ์˜ˆ์ธ : ์ฃผ์ฐจ๊ณต๊ฐ„ API, ๋ฆฌ๋ทฐ API, Redis Pub/Sub์„ ์ด์šฉํ•œ ๋ฉ”์ผ ์ „์†ก ๊ธฐ๋Šฅ

๐Ÿฆฆ ์ •์ค€ํ˜ธ : ์œ ์ € API, JWT ์ธ์ฆ/์ธ๊ฐ€, ์นด์นด์˜ค ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ, ํ”„๋กœ๋ชจ์…˜ API + ๋™์‹œ์„ฑ ์ œ์–ด ์ ์šฉ, AWS ์•„ํ‚คํ…์ฒ˜ ๊ตฌ์„ฑ, GitHub Actions ํ™œ์šฉํ•œ CI/CD

๐Ÿถ๏ธ ์ด๋ฏผ์ • : ๊ฒฐ์ œ API, ์ •์‚ฐ API, AWS S3 ์ด๋ฏธ์ง€ ๊ธฐ๋Šฅ, Toss payments API ์—ฐ๋™, Redis๋ฅผ ์ด์šฉํ•œ ์˜ˆ์•ฝ ๋Œ€๊ธฐ์—ด ๊ธฐ๋Šฅ

๐Ÿ—ฟ ์ „์„œ์—ฐ : ์ฃผ์ฐจ์žฅ API, ๋„ค์ด๋ฒ„ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ, AWS Lambda๋ฅผ ์ด์šฉํ•œ ๊ณต๊ณต๋ฐ์ดํ„ฐ ์ €์žฅ, ์นด์นด์˜ค๋งต API ์—ฐ๋™ํ•˜์—ฌ ์ฃผ์†Œ ์ €์žฅ

๐ŸŽ… ์žฅ์œคํ˜ : ์˜ˆ์•ฝ API + ๋™์‹œ์„ฑ ์ œ์–ด ์ ์šฉ, ์ฃผ์ฐจ์žฅ ๋‹ค๊ฑด ์กฐํšŒ ์บ์‹ฑ, Spring Batch๋ฅผ ์ด์šฉํ•œ ์ •์‚ฐ ๊ธฐ๋Šฅ


๐Ÿ›  ๋ชฉ์ฐจ

  1. ๐Ÿงฐ ๊ธฐ์ˆ ์Šคํƒ
  2. ๐Ÿ—‚ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜
  3. ๐Ÿ’ฟ CI/CD
  4. ๐Ÿงฉ ์™€์ด์–ดํ”„๋ ˆ์ž„
  5. ๐Ÿงพ ERD
  6. ๐Ÿ“ก API ๋ช…์„ธ
  7. ๐Ÿš€ ๊ธฐ์ˆ  ๊ณ ๋„ํ™”
  8. ๐Ÿงช ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ
  9. ๐Ÿ“ˆ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€
  10. ๐Ÿงฏ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…
  11. ๐Ÿ”ญ ํ–ฅํ›„ ๋ฐœ์ „ ๋ฐฉํ–ฅ
  12. ๐Ÿ“– ํšŒ๊ณ 

๐Ÿงฐ ๊ธฐ์ˆ ์Šคํƒ

๐Ÿ’ป Language / Backend

โš™๏ธ Database

๐Ÿ” Test

๐Ÿ” Security

๐ŸŽจ Collaboration Tool

๐Ÿ›  Deployment & Distribution



๐Ÿ—‚ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜

ParkEZ แ„‰แ…ตแ„‰แ…ณแ„แ…ฆแ†ท แ„‹แ…กแ„แ…ตแ„แ…ฆแ†จแ„Žแ…ฅ แ„‹แ…ตแ„†แ…ตแ„Œแ…ต

๐Ÿ’ฟ CI/CD

ParkEZ CICD

๐Ÿงฉ ์™€์ด์–ดํ”„๋ ˆ์ž„

ParkEZ แ„‹แ…ชแ„‹แ…ตแ„‹แ…ฅแ„‘แ…ณแ„…แ…ฆแ„‹แ…ตแ†ท

๐Ÿงพ ERD

Image

๐Ÿ“ก API ๋ช…์„ธ

๐Ÿ“‘ Swagger ์ฐธ์กฐ : parkez.click


๐Ÿš€ ๊ธฐ์ˆ  ๊ณ ๋„ํ™”

โ˜๏ธ AWS Lambda๋กœ ์™ธ๋ถ€ API ํ˜ธ์ถœ ์ž๋™ํ™”
  • ๋„์ž… ๋ฐฐ๊ฒฝ: ํ•˜๋ฃจ 1ํšŒ ์‹คํ–‰ ์ž‘์—…์„ ์œ„ํ•ด ์„œ๋ฒ„๋ฅผ 24์‹œ๊ฐ„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์€ ๋น„ํšจ์œจ โ†’ ์„œ๋ฒ„๋ฆฌ์Šค ํ™˜๊ฒฝ์œผ๋กœ ์ „ํ™˜
  • ๊ธฐ์ˆ  ์„ ํƒ: AWS Lambda + EventBridge ์กฐํ•ฉ์œผ๋กœ ์„œ๋ฒ„ ๊ด€๋ฆฌ ๋ถ€๋‹ด ์—†์ด ์Šค์ผ€์ค„๋ง ์ž๋™ํ™”

โœ… JavaHandler ๋ฐฉ์‹ ์‚ฌ์šฉ ์ด์œ 

  • ๋น ๋ฅธ ์ฝœ๋“œ ์Šคํƒ€ํŠธ (Spring ์ดˆ๊ธฐํ™” ์ œ๊ฑฐ)
  • ํŒจํ‚ค์ง€ ๊ฒฝ๋Ÿ‰ํ™” โ†’ ๋ฐฐํฌ ๊ฐ„ํŽธ
  • ์‹คํ–‰ ์‹œ๊ฐ„ ๋‹จ์ถ• โ†’ ๋น„์šฉ ์ ˆ๊ฐ

โœ… ๋„คํŠธ์›Œํฌ ๊ตฌ์„ฑ ์š”์•ฝ

  • VPC Peering: Lambda โ†” RDS ๊ฐ„ ํ†ต์‹  ์œ„ํ•ด VPC ๊ฐ„ ์—ฐ๊ฒฐ
  • ํ”„๋ผ์ด๋น— ์„œ๋ธŒ๋„ท: Lambda ์‹คํ–‰ ์œ„์น˜, ์•„์›ƒ๋ฐ”์šด๋“œ๋งŒ ํ—ˆ์šฉ
  • ํผ๋ธ”๋ฆญ ์„œ๋ธŒ๋„ท + IGW: ์™ธ๋ถ€ ๊ณต๊ณต API ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๊ตฌ์„ฑ
  • NAT Gateway: ํ”„๋ผ์ด๋น— ์„œ๋ธŒ๋„ท์—์„œ๋„ ์™ธ๋ถ€ API ์ ‘๊ทผ ๊ฐ€๋Šฅ
๐Ÿ’ฐ Spring Batch ๊ธฐ๋ฐ˜ ์ •์‚ฐ ์ฒ˜๋ฆฌ
  • ๋„์ž… ๋ฐฐ๊ฒฝ: ์ˆ˜๋งŒ ๊ฑด ์ด์ƒ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ , ์ด๋ ฅ ๊ด€๋ฆฌ์™€ ์žฌ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ ํ•„์š”

โœ… ๊ธฐ์ˆ  ์„ ํƒ ์ด์œ 

  • ๋Œ€์šฉ๋Ÿ‰ ์ฒ˜๋ฆฌ ์ตœ์ ํ™”
    • ๊ฑฐ๋ž˜ ๋ฐ์ดํ„ฐ๋ฅผ Chunk ๋‹จ์œ„๋กœ ๋ถ„ํ•  ์ฒ˜๋ฆฌ โ†’ ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ ํ™•๋ณด
  • ๊ตฌ์กฐ์  ์„ค๊ณ„ (Job / Step ๋ถ„๋ฆฌ)
    • ์ •์‚ฐ ํ”„๋กœ์„ธ์Šค๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•˜์—ฌ ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด
  • ์ด๋ ฅ ๊ด€๋ฆฌ ์ž๋™ํ™”
    • Job ์‹คํ–‰ ๋‚ด์—ญ๊ณผ ์ƒํƒœ๋ฅผ DB์— ์ž๋™ ๊ธฐ๋ก
  • ์Šค์ผ€์ค„๋ง ๋ฐ ์žฌ์‹œ๋„ ์ง€์›
    • ์ •ํ•ด์ง„ ์‹œ๊ฐ์— ์ •์‚ฐ ์ž๋™ ์ˆ˜ํ–‰
    • ์‹คํŒจํ•œ Step๋งŒ ์žฌ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
  • Chunk ๊ธฐ๋ฐ˜ ํŠธ๋žœ์žญ์…˜ ์ œ์–ด
    • ์‹คํŒจํ•œ Chunk๋งŒ rollback โ†’ ์ „์ฒด ์ž‘์—…์— ์˜ํ–ฅ ์—†์ด ๋ณต๊ตฌ ๊ฐ€๋Šฅ
๐Ÿ“ง Redis Pub/Sub + Amazon SES ๊ธฐ๋ฐ˜ ๋ฉ”์ผ ์ „์†ก

๐Ÿ“Œ ๊ธฐ์กด ๊ตฌ์กฐ์˜ ํ•œ๊ณ„์ 

  • ์ด๋ฉ”์ผ ์ „์†ก ๋ฐฉ์‹: SMTP + JavaMailSender

    • ์ธ์ฆยท์ „์†ก ์‹ ๋ขฐ๋„ ๋‚ฎ์Œ
    • ์ŠคํŒธ ์ฒ˜๋ฆฌ ์šฐ๋ ค
    • TLS / ํฌํŠธ ์ œ์•ฝ ์กด์žฌ
  • ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ ๋ฐฉ์‹: Spring @EventListener

    • ๋™๊ธฐ ์ฒ˜๋ฆฌ ๋ฐฉ์‹ โ†’ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง๊ณผ ์•Œ๋ฆผ ๋กœ์ง ๊ฐ•๊ฒฐํ•ฉ
    • ๊ตฌ์กฐ ํ™•์žฅ ๋ฐ ์žฌ์‚ฌ์šฉ ์–ด๋ ค์›€

๐Ÿ›  ๊ฐœ์„  ๋ฐฉํ–ฅ

  • ์ด๋ฒคํŠธ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ:
    @EventListener โ†’ redisTemplate.convertAndSend()๋กœ ์ „ํ™˜
    โ†’ Redis Pub/Sub ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ๋กœ ๋ถ„๋ฆฌ

  • ์‹ ๋ขฐ์„ฑ ์žˆ๋Š” ์ด๋ฉ”์ผ ์ „์†ก:
    JavaMailSender โ†’ SesClient (AWS SDK v2) ์ „ํ™˜

    • ๋„๋ฉ”์ธ ์ธ์ฆ + DKIM ์„œ๋ช…
    • EmailTemplateService๋ฅผ ํ†ตํ•œ ํ…œํ”Œ๋ฆฟ ๊ธฐ๋ฐ˜ ๋ฉ”์ผ ๊ตฌ์„ฑ

๐Ÿš€ ๊ธฐ๋Œ€ ํšจ๊ณผ

ํ•ญ๋ชฉ ๊ฐœ์„  ๋‚ด์šฉ
์‹ ๋ขฐ๋„ ํ–ฅ์ƒ SES + DKIM ๊ธฐ๋ฐ˜์œผ๋กœ ์ „์†ก๋ฅ  ๋ฐ ์ˆ˜์‹  ์„ฑ๊ณต๋ฅ  ํ–ฅ์ƒ
ํ™•์žฅ์„ฑ ํ™•๋ณด FCM / SES / Slack ๋“ฑ ๋‹ค์–‘ํ•œ ์ฑ„๋„ ์—ฐ๋™ ์šฉ์ด
์œ ์ง€๋ณด์ˆ˜ ํŽธ์˜์„ฑ ์‹คํŒจ ๋‚ด์—ญ ๋กœ๊น…, ํ†ต๊ณ„ ๋ถ„์„, ์žฌ์ฒ˜๋ฆฌ ๊ตฌ์กฐ ์ ์šฉ ๊ฐ€๋Šฅ

๐Ÿงพ ์‹คํ–‰ ๊ฒฐ๊ณผ

  • ๊ธฐ์กด SMTP ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ ๋Œ€๋น„ ์ „์†ก ์‹ ๋ขฐ์„ฑ ๋ฐ ์œ ์ง€๋ณด์ˆ˜ ํŽธ์˜์„ฑ ๋Œ€ํญ ๊ฐœ์„ 
  • ์•Œ๋ฆผ ๋กœ์ง์˜ ์ฑ…์ž„ ๋ถ„๋ฆฌ๋กœ ๊ตฌ์กฐ ์œ ์—ฐ์„ฑ๊ณผ ํ™•์žฅ์„ฑ ํ™•๋ณด

๐Ÿงช ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ

์˜ˆ์•ฝ ์ƒ์„ฑ ์‹œ ๋™์‹œ์„ฑ ์ œ์–ด ํ…Œ์ŠคํŠธ

  • ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค
    ์ด 10๋ช…์˜ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— ์˜ˆ์•ฝ ์š”์ฒญ
  • ์‘๋‹ต ๋ฉ”์‹œ์ง€
    • "์˜ˆ์•ฝ ์„ฑ๊ณต" : ์‹ค์ œ ์˜ˆ์•ฝ ์™„๋ฃŒ
    • "๋Œ€๊ธฐ์—ด ๋“ฑ๋ก๋จ" : ์˜ˆ์•ฝ ์‹คํŒจ ํ›„ ๋Œ€๊ธฐ์—ด ๋“ฑ๋ก

๐Ÿ” ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

๊ตฌ๋ถ„ ์‘๋‹ต ๊ฒฐ๊ณผ
โœ… ๋™์‹œ์„ฑ ์ œ์–ด ์ด์ „ 10๋ช… ๋ชจ๋‘ "์˜ˆ์•ฝ ์„ฑ๊ณต" โ†’ ์ค‘๋ณต ์˜ˆ์•ฝ ๋ฐœ์ƒ
โœ… ๋™์‹œ์„ฑ ์ œ์–ด ์ดํ›„ 1๋ช… "์˜ˆ์•ฝ ์„ฑ๊ณต" + 9๋ช… "๋Œ€๊ธฐ์—ด ๋“ฑ๋ก๋จ" โ†’ ์ •์ƒ ์ฒ˜๋ฆฌ๋จ
  • ๊ฒฐ๋ก : ๋™์‹œ์„ฑ ์ œ์–ด๋ฅผ ํ†ตํ•ด ํ•˜๋‚˜์˜ ์ฃผ์ฐจ ๊ณต๊ฐ„์— ๋Œ€ํ•œ ์ค‘๋ณต ์˜ˆ์•ฝ์„ ๋ฐฉ์ง€ํ•˜๊ณ , ํ›„์ˆœ์œ„ ์‚ฌ์šฉ์ž๋ฅผ ๋Œ€๊ธฐ์—ด์— ์•ˆ์ „ํ•˜๊ฒŒ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ฐœ์„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์ฐจ์žฅ ์กฐํšŒ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ

๐Ÿ“Š JMeter๋ฅผ ํ™œ์šฉํ•œ ์ฃผ์ฐจ์žฅ ์กฐํšŒ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ

๐Ÿงช ํ…Œ์ŠคํŠธ ๊ฐœ์š”

  • ๋ชฉํ‘œ: Redis ์บ์‹œ ๋„์ž… ์ „/ํ›„ ์„ฑ๋Šฅ ๋น„๊ต
  • ๋Œ€์ƒ: ์•ฝ 10๋งŒ ๊ฑด์˜ ์ฃผ์ฐจ์žฅ ๋ฐ์ดํ„ฐ
  • ๋„๊ตฌ: Apache JMeter
  • ์กฐ๊ฑด: ๋™์ผํ•œ Thread ์ˆ˜, Ramp-up ์‹œ๊ฐ„, Delay ์„ค์ •

๐Ÿ“ˆ ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

ํ•ญ๋ชฉ ์บ์‹œ ์ ์šฉ ์ „ ์บ์‹œ ์ ์šฉ ํ›„ ๋ณ€ํ™”์œจ
Throughput 4.2/sec 31.9/sec ๐Ÿ”ผ +659.5% ์ฆ๊ฐ€
ํ‰๊ท  ์‘๋‹ต์‹œ๊ฐ„ 61,641 ms 15,678 ms ๐Ÿ”ฝ -74.6% ๊ฐ์†Œ

โœ… ๋ถ„์„

  • Redis ์บ์‹œ ์ ์šฉ์œผ๋กœ ์ฒ˜๋ฆฌ๋Ÿ‰(Throughput)์ด 6๋ฐฐ ์ด์ƒ ์ฆ๊ฐ€
  • ์‘๋‹ต์‹œ๊ฐ„์ด 1/4 ์ˆ˜์ค€์œผ๋กœ ๋‹จ์ถ•๋˜์–ด ์‚ฌ์šฉ์ž ๊ฒฝํ—˜ ๊ฐœ์„ 
  • ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•ด ์บ์‹œ ์ ์šฉ ์‹œ ํ™•์—ฐํ•œ ์„ฑ๋Šฅ ํ–ฅ์ƒ ํ™•์ธ

๐Ÿ“ˆ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€

ParkEZ แ„แ…ฆแ„‰แ…ณแ„แ…ณ แ„แ…ฅแ„‡แ…ฅแ„…แ…ตแ„Œแ…ต แ„‹แ…ตแ„†แ…ตแ„Œแ…ต

๐Ÿงฏ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

1. OSIV ์„ค์ • ์ฐจ์ด๋กœ ์ธํ•œ ์ƒํƒœ ๋ณ€๊ฒฝ ๋ฏธ๋ฐ˜์˜ ๋ฌธ์ œ

โ— ๋ฌธ์ œ ์ƒํ™ฉ

  • ๋กœ์ปฌ์—์„œ๋Š” ์ •์ƒ ๋™์ž‘ํ•˜๋˜ ์˜ˆ์•ฝ ์ƒํƒœ ๋ณ€๊ฒฝ ๊ธฐ๋Šฅ์ด, ๊ฐœ๋ฐœ ์„œ๋ฒ„์—์„œ๋Š” DB์— ๋ฐ˜์˜๋˜์ง€ ์•Š์Œ
  • ์˜ˆ์‹œ: reservation.cancel() ํ˜ธ์ถœ ํ›„์—๋„ ReservationStatus.CANCELED๊ฐ€ DB์— ๋ฐ˜์˜๋˜์ง€ ์•Š์Œ

๐Ÿ” ์›์ธ ๋ถ„์„

  • OSIV ์„ค์ • ์ฐจ์ด

    • ๋กœ์ปฌ: spring.jpa.open-in-view=true (๊ธฐ๋ณธ๊ฐ’)
      โ†’ ํŠธ๋žœ์žญ์…˜ ์ข…๋ฃŒ ์ดํ›„์—๋„ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ ์ ‘๊ทผ ๊ฐ€๋Šฅ
    • ๊ฐœ๋ฐœ ์„œ๋ฒ„: open-in-view=false
      โ†’ ํŠธ๋žœ์žญ์…˜ ์ข…๋ฃŒ ์‹œ ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋„ ์ข…๋ฃŒ
  • ๊ตฌ์กฐ์  ๋ฌธ์ œ

    • @Transactional(readOnly = true)๊ฐ€ ์ ์šฉ๋œ Reader์—์„œ ์กฐํšŒํ•œ ์—”ํ‹ฐํ‹ฐ๋Š” Detached ์ƒํƒœ์ผ ์ˆ˜ ์žˆ์Œ
    • ์ดํ›„ Writer์—์„œ ์ƒํƒœ ๋ณ€๊ฒฝ ๋ฉ”์„œ๋“œ๋งŒ ํ˜ธ์ถœํ•˜๋ฉด JPA์˜ dirty checking์ด ์ž‘๋™ํ•˜์ง€ ์•Š์Œ
// ReservationService
Reservation reservation = reservationReader.findMyReservation(...); // ReadOnly ํŠธ๋žœ์žญ์…˜
        reservationWriter.cancel(reservation); // ๋‚ด๋ถ€์—์„œ reservation.cancel() ํ˜ธ์ถœ โ†’ ๋ณ€๊ฒฝ ๊ฐ์ง€ ์•ˆ ๋จ

โœ… ํ•ด๊ฒฐ ๋ฐฉ์•ˆ

โœ… ๋‹จ๊ธฐ ํ•ด๊ฒฐ: ๋ช…์‹œ์  save ํ˜ธ์ถœ

public void cancel(Reservation reservation) {
  reservation.cancel();
  reservationRepository.save(reservation); // Detached ๊ฐ์ฒด merge
}

โœ… ๊ทผ๋ณธ์  ํ•ด๊ฒฐ: ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„ ์žฌ์„ค๊ณ„

// ReservationService
@Transactional
public void cancelReservation(...) {
  Reservation reservation = reservationReader.findMyReservation(...);
  reservation.cancel(); // ์˜์† ์ƒํƒœ์—์„œ ๋ณ€๊ฒฝ โ†’ dirty checking ์ž‘๋™
}

๐ŸŽฏ ๊ฒฐ๊ณผ

  • ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋„ ์˜ˆ์•ฝ ์ƒํƒœ ๋ณ€๊ฒฝ์ด ์ •์ƒ ๋ฐ˜์˜๋จ
  • ๊ตฌ์กฐ์ ์œผ๋กœ ์—ญํ•  ๋ถ„๋ฆฌ๊ฐ€ ๋ช…ํ™•ํ•ด์ง:
    • Reader โ†’ ์กฐํšŒ ์ฑ…์ž„
    • Writer โ†’ ๋„๋ฉ”์ธ ๋ณ€๊ฒฝ ์ฑ…์ž„
    • Service โ†’ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ ๋ฐ ํ๋ฆ„ ์กฐ์œจ

2. ๋™์‹œ์„ฑ ํ…Œ์ŠคํŠธ - ์ปค๋„ฅ์…˜ ํ’€ ๊ณ ๊ฐˆ ๋ฐœ์ƒ

๐Ÿ” ๋ฌธ์ œ ๋ฐœ๊ฒฌ

  • ๋™์‹œ์„ฑ ํ…Œ์ŠคํŠธ ์ˆ˜ํ–‰ ์ค‘, ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚˜์ง€ ์•Š๊ณ  ๋Œ€๊ธฐ ์ƒํƒœ ์ง€์†
  • ์ปค๋„ฅ์…˜ ํ’€ ๊ณ ๊ฐˆ๋กœ ์ธํ•œ ํƒ€์ž„์•„์›ƒ ํ˜„์ƒ ๋ฐœ์ƒ

โš ๏ธ ์›์ธ ๋ถ„์„

  • ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ์— @Transactional์ด ์ ์šฉ๋˜์–ด ์ „์ฒด ํ…Œ์ŠคํŠธ๊ฐ€ ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ์‹คํ–‰๋จ
  • ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ๋„ ๋™์ผ ํŠธ๋žœ์žญ์…˜์— ๋ฌถ์—ฌ ์ปค๋ฐ‹/๋กค๋ฐฑ ์ง€์—ฐ
  • ๊ฒฐ๊ณผ์ ์œผ๋กœ DB ๋ฝ์ด ํ•ด์ œ๋˜์ง€ ์•Š๊ณ , ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฝ ๋Œ€๊ธฐ ์ƒํƒœ์— ๋น ์ง
  • ์ปค๋„ฅ์…˜ ํ’€ ๋ถ€์กฑ โ†’ ์ƒˆ๋กœ์šด ์ปค๋„ฅ์…˜ ์ƒ์„ฑ ๋ถˆ๊ฐ€ โ†’ ํ…Œ์ŠคํŠธ ํƒ€์ž„์•„์›ƒ

โœ… ํ•ด๊ฒฐ ๋ฐฉ์•ˆ ๋ฐ ๊ฒฐ๊ณผ

  • @Transactional ์–ด๋…ธํ…Œ์ด์…˜ ์ œ๊ฑฐ
    • ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ๋…๋ฆฝ๋œ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ์‹คํ–‰๋˜์–ด DB ๋ฝ ์ •์ƒ ํ•ด์ œ
  • ํ…Œ์ŠคํŠธ ์ข…๋ฃŒ ํ›„ deleteAllInBatch() ์‚ฌ์šฉ
    • ํ…Œ์ŠคํŠธ ๊ฐ„ ๋ฐ์ดํ„ฐ ์ž”์กด ๋ฌธ์ œ ๋ฐฉ์ง€
    • ํŠธ๋žœ์žญ์…˜ ์ œ๊ฑฐ๋กœ ์ธํ•œ ๋ฐ์ดํ„ฐ ์ •๋ฆฌ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ˆ˜ํ–‰

๐Ÿ”ญ ํ–ฅํ›„ ๋ฐœ์ „ ๋ฐฉํ–ฅ

๐ŸŽŸ๏ธ ํ”„๋กœ๋ชจ์…˜ ์ฟ ํฐ ๋ฐœ๊ธ‰ ์ฒ˜๋ฆฌ ์ „๋žต

โœ… ํ˜„์žฌ ๊ตฌ์กฐ DB์˜ Pessimistic Lock (๋น„๊ด€์  ๋ฝ) ์„ ํ™œ์šฉํ•˜์—ฌ ์ฟ ํฐ ์žฌ๊ณ ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ œ์–ดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์žฅ์ 

    • ๋‹ค์ค‘ ์‚ฌ์šฉ์ž ํ™˜๊ฒฝ์—์„œ๋„ ์ค‘๋ณต ๋ฐœ๊ธ‰ ์—†์ด ์žฌ๊ณ  ์ œ์–ด ๊ฐ€๋Šฅ
  • ๋‹จ์ 

    • ํŠน์ • ํ”„๋กœ๋ชจ์…˜ ๋ฐœ๊ธ‰ ์š”์ฒญ์ด ๋ชฐ๋ฆฌ๋ฉด ํ•ด๋‹น ๋ ˆ์ฝ”๋“œ์— ๋ฝ์ด ๊ฑธ๋ ค
      โ†’ ๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์ด ์ง€์—ฐ๋˜๊ณ 
      โ†’ ์ฟ ํฐ ์กฐํšŒ ๋ฐ ๊ด€๋ จ ๋กœ์ง์— ๋ณ‘๋ชฉ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ

๐Ÿšง ๊ฐœ์„  ๋ฐฉํ–ฅ

๐Ÿ” ๋ถ„์‚ฐ๋ฝ ์ ์šฉ ์˜ˆ์ •
  • ๋ชฉํ‘œ: ํŠน์ • ํ”„๋กœ๋ชจ์…˜ ๋‹จ์œ„๋กœ ๋ถ„์‚ฐ๋ฝ ์ ์šฉ (ex. Redis ๊ธฐ๋ฐ˜)
  • ํšจ๊ณผ:
    • ๋ฐœ๊ธ‰์—๋งŒ ๋ฝ์„ ์ œํ•œํ•˜๊ณ  ์กฐํšŒ๋Š” ๋ฝ ์˜ํ–ฅ ์—†์ด ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅ
    • DB ๋ ˆ๋ฒจ ๋ณ‘๋ชฉ ์—†์ด ํ™•์žฅ์„ฑ ๋†’์€ ๋™์‹œ์„ฑ ์ œ์–ด ๊ฐ€๋Šฅ
โšก ๋ฐœ๊ธ‰๊ณผ ๊ด€๋ฆฌ ๋ถ„๋ฆฌ
  • ๋ฐœ๊ธ‰ ์š”์ฒญ์€ ๋™๊ธฐ ์ฒ˜๋ฆฌ, ์‚ฌ์šฉ์ž์—๊ฒŒ ๋น ๋ฅธ ์‘๋‹ต ์ œ๊ณต
  • ๋ฐœ๊ธ‰ ๊ธฐ๋ก์€ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ, ์‹œ์Šคํ…œ ๋ถ€ํ•˜ ๋ถ„์‚ฐ
  • ์˜ˆ์‹œ: Kafka, SQS ๋“ฑ ๋ฉ”์‹œ์ง€ ํ๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌ ๋ถ„๋ฆฌ

๐Ÿ”” ์•Œ๋ฆผ ์‹œ์Šคํ…œ ๊ตฌ์กฐ ๊ฐœ์„  ๋ฐฉํ–ฅ

โœ… ํ˜„์žฌ ๊ตฌ์กฐ ํ˜„์žฌ ์•Œ๋ฆผ ์‹œ์Šคํ…œ์€ Redis Pub/Sub ๊ธฐ๋ฐ˜์œผ๋กœ, ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•˜๊ณ , ๊ตฌ๋…์ž์—์„œ ์ด๋ฉ”์ผ(SES)์„ ์ „์†กํ•˜๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.
์ด ๊ตฌ์กฐ๋Š” ๊ฐ„๋‹จํ•˜๊ณ  ๋น ๋ฅด์ง€๋งŒ, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์šด์˜์ƒ์˜ ํ•œ๊ณ„๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

โ— ๋ฌธ์ œ์ 

๐Ÿ“Œ ๋ฉ”์‹œ์ง€ ์œ ์‹ค ๊ฐ€๋Šฅ์„ฑ
  • Redis Pub/Sub์€ ์‹ค์‹œ๊ฐ„ ๋ฉ”์‹œ์ง€ ์ „ํŒŒ๋งŒ ์ง€์›ํ•˜๋ฉฐ, ๋ฉ”์‹œ์ง€๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š์Œ
  • ๊ตฌ๋…์ž๊ฐ€ ๋‹ค์šด๋œ ๊ฒฝ์šฐ ๋ฉ”์‹œ์ง€๊ฐ€ ์œ ์‹ค๋˜์–ด ์•Œ๋ฆผ ์†์‹ค ๋ฐœ์ƒ
๐Ÿ“Œ ์žฌ์ฒ˜๋ฆฌ ๋ถˆ๊ฐ€
  • ์•Œ๋ฆผ ๋ฐœ์†ก ์‹คํŒจ ์‹œ ๋กœ๊ทธ๋งŒ ๋‚จ๊ณ , ๋ณ„๋„์˜ ์žฌ์‹œ๋„ ๋กœ์ง์ด ์—†์–ด ์šด์˜ ์‹ ๋ขฐ์„ฑ ๋ถ€์กฑ

โœ… ๊ฐœ์„  ๋ฐฉํ–ฅ

๐Ÿ“ฆ ๋ฉ”์‹œ์ง€ ์˜์†ํ™” ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ ๊ณ ๋ ค
  • Redis Streams ๋˜๋Š” Kafka ๋“ฑ ์˜์† ๋ฉ”์‹œ์ง• ํ๋กœ ๊ต์ฒด ๋˜๋Š” ๋ณด์™„ ์‹œ์Šคํ…œ ๋„์ž… ์˜ˆ์ •
  • ๊ตฌ๋…์ž ์žฅ์•  ์‹œ์—๋„ ์žฌ์ˆ˜์‹  ๋ฐ ๋ณต๊ตฌ ๊ฐ€๋Šฅ
๐Ÿ” ์‹คํŒจ ๋‚ด์—ญ ์ €์žฅ ๋ฐ ์žฌ์ฒ˜๋ฆฌ ๋„์ž…
  • ๋ฐœ์†ก ์‹คํŒจ ์ด๋ ฅ์„ Redis List ๋˜๋Š” DB Table ๋“ฑ์— ์ €์žฅ
  • Scheduled Task ๋˜๋Š” Spring Batch๋ฅผ ํ™œ์šฉํ•œ ์žฌ์ฒ˜๋ฆฌ ๊ตฌ์กฐ ์ ์šฉ
  • ์žฅ๊ธฐ์ ์œผ๋กœ๋Š” Kafka DLQ(Dead Letter Queue) ๋„์ž… ๊ณ ๋ ค

๐Ÿ“– ํšŒ๊ณ 

๐Ÿฃ ์กฐ์˜ˆ์ธ : ๊ธด ์—ฌ์ •์„ ์ข‹์€ ํŠœํ„ฐ๋‹˜, ํŒ€์›๋ถ„๋“ค์„ ๋งŒ๋‚˜ ์ž˜ ๋งˆ๋ฌด๋ฆฌํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ ์ดํ›„์—๋„ ๊ฐ™์ด ๋งŒ๋‚˜์„œ๋ณต์Šต, ๊ฐœ์„  ๋ฐ ๋ฐœ์ „ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๐Ÿฆฆ ์ •์ค€ํ˜ธ : ํŒ€์›๋“ค๊ณผ์˜ ์ง€์†์ ์ธ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜๊ณผ ์—ญํ•  ๋ถ„๋‹ด์„ ํ†ตํ•ด ์ ์ฐจ ์•ˆ์ •์ ์ธ ๊ฐœ๋ฐœ ํ๋ฆ„์„ ๋งŒ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์งง์€ ๊ธฐ๊ฐ„์ด์—ˆ์ง€๋งŒ ๊ธฐ์ˆ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ˜‘์—… ์—ญ๋Ÿ‰๊ณผ ์ฑ…์ž„๊ฐ๊นŒ์ง€ ํ•จ๊ป˜ ํ‚ค์šธ ์ˆ˜ ์žˆ์—ˆ๋˜ ๊ฐ’์ง„ ์‹œ๊ฐ„์ด์—ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿถ๏ธ ์ด๋ฏผ์ • : ์ฒ˜์Œ์œผ๋กœ ๊ธฐํš๋ถ€ํ„ฐ ๋ฐฐํฌ๊นŒ์ง€ ํ•ด๋ณธ ํ”„๋กœ์ ํŠธ์ธ ๋งŒํผ ์–ด๋ ค์šด ์ ๋„ ๋งŽ์•˜์ง€๋งŒ ๋ฐฐ์šด ์ ๋„ ๋งŽ์•˜๋˜ ์‹œ๊ฐ„์ด์—ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ๋Š” ๋๋‚ฌ์ง€๋งŒ, ์ œ๊ฐ€ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์€ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ๋„๊ผญ ๋ณต์Šตํ•˜๋ฉฐ ๊ณต๋ถ€ํ•ด์•ผ๊ฒ ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ข‹์€ ํŒ€์›๋“ค๊ณผ ํŠœํ„ฐ๋‹˜๊ณผ ์†Œํ†ตํ•˜๋ฉฐ ์ž˜ ๋งˆ๋ฌด๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์„œ ๊ฐ์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ—ฟ ์ „์„œ์—ฐ : ํ•œ ๋‹ฌ ๋™์•ˆ ์ตœ์ข… ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉฐ ์ข‹์€ ๊ฒฝํ—˜์„ ํ•˜๊ฒŒ ๋˜์–ด ๋œป ๊นŠ์€ ์‹œ๊ฐ„์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋ ค์šด ๋ถ€๋ถ„์ด ๋งŽ์•˜์ง€๋งŒ ์ข‹์€ ํŒ€์›๊ณผ ํŠœํ„ฐ๋‹˜ ๋•๋ถ„์— ์ž˜ ๋งˆ๋ฌด๋ฆฌ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 10์กฐ ์ทจ๋ฝ€ ํ™”์ดํŒ…

๐ŸŽ… ์žฅ์œคํ˜ : ์ตœ์ข… ํ”„๋กœ์ ํŠธ์ธ ๋งŒํผ ์ข‹์€ ํŒ€์›๋“ค๊ณผ ํ•จ๊ป˜ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์‹œ๋„๋ฅผ ๋‹ค์–‘ํ•˜๊ฒŒ ํ•ด ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ ์ข‹์•˜์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ•œ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ๋ณต์Šตํ•˜๋ฉฐ ์ง์ ‘ ๊ตฌํ˜„ํ•ด ๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.