From ccd9eac7fb1c9d696a1e8e0a83d09a688a84b1cb Mon Sep 17 00:00:00 2001 From: codingTrip <83770197+codingTrip-IT@users.noreply.github.com> Date: Fri, 2 May 2025 20:30:47 +0900 Subject: [PATCH 1/2] =?UTF-8?q?Docs:=20README.md=20=EB=82=B4=EC=9A=A9=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 296 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 247 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index bf683a2..68fe6a3 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@
- -Image
- +Image
@@ -34,23 +32,23 @@ ## ๐Ÿ›  ๋ชฉ์ฐจ -1. [๐Ÿ“š ๊ธฐ์ˆ ์Šคํƒ](#-๊ธฐ์ˆ ์Šคํƒ) -2. [๐Ÿ‘ฉ๐Ÿปโ€ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜](#-์‹œ์Šคํ…œ-์•„ํ‚คํ…์ฒ˜) -3. [๐Ÿ‘ฉ๐Ÿปโ€ CI/CD](#-cicd) -4. [๐Ÿ‘ฉ๐Ÿปโ€ ์™€์ด์–ดํ”„๋ ˆ์ž„](#-์™€์ด์–ดํ”„๋ ˆ์ž„) -5. [๐Ÿ‘ฉ ERD](#-erd) -6. [๐Ÿ‘ฉ API ๋ช…์„ธ](#-api-๋ช…์„ธ) -7. [๐Ÿ‘ฉ ๊ธฐ์ˆ  ๊ณ ๋„ํ™”](#-๊ธฐ์ˆ -๊ณ ๋„ํ™”) -8. [โš—๏ธ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ](#-์„ฑ๋Šฅ-ํ…Œ์ŠคํŠธ) -9. [โš—๏ธ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€](#-ํ…Œ์ŠคํŠธ-์ปค๋ฒ„๋ฆฌ์ง€) -10. [๐Ÿ’ฅ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…](#-ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…) -11. [โš—๏ธ ํ–ฅํ›„ ๋ฐœ์ „ ๋ฐฉํ–ฅ](#-ํ–ฅํ›„-๋ฐœ์ „-๋ฐฉํ–ฅ) -12. [โš—๏ธ ํšŒ๊ณ ](#-ํšŒ๊ณ ) +1. [๐Ÿงฐ ๊ธฐ์ˆ ์Šคํƒ](#-๊ธฐ์ˆ ์Šคํƒ) +2. [๐Ÿ—‚ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜](#-์‹œ์Šคํ…œ-์•„ํ‚คํ…์ฒ˜) +3. [โš™๏ธ CI/CD](#โš™๏ธ-cicd) +4. [๐Ÿงฉ ์™€์ด์–ดํ”„๋ ˆ์ž„](#-์™€์ด์–ดํ”„๋ ˆ์ž„) +5. [๐Ÿงพ ERD](#-erd) +6. [๐Ÿ“ก API ๋ช…์„ธ](#-api-๋ช…์„ธ) +7. [๐Ÿš€ ๊ธฐ์ˆ  ๊ณ ๋„ํ™”](#-๊ธฐ์ˆ -๊ณ ๋„ํ™”) +8. [๐Ÿงช ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ](#-์„ฑ๋Šฅ-ํ…Œ์ŠคํŠธ) +9. [๐Ÿ“ˆ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€](#-ํ…Œ์ŠคํŠธ-์ปค๋ฒ„๋ฆฌ์ง€) +10. [๐Ÿงฏ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…](#-ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…) +11. [๐Ÿ”ญ ํ–ฅํ›„ ๋ฐœ์ „ ๋ฐฉํ–ฅ](#-ํ–ฅํ›„-๋ฐœ์ „-๋ฐฉํ–ฅ) +12. [๐Ÿ’ฌ๏ธ ํšŒ๊ณ ](#๐Ÿ’ฌ๏ธ-ํšŒ๊ณ )
-## ๐Ÿ“š ๊ธฐ์ˆ ์Šคํƒ +## ๐Ÿงฐ ๊ธฐ์ˆ ์Šคํƒ ### ๐Ÿ’ป Language / Backend @@ -70,63 +68,230 @@ ### ๐Ÿ›  Deployment & Distribution -### ๐Ÿ–ฅ๏ธ Monitoring - +

-


+## ๐Ÿ—‚ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ +ParkEZ แ„‰แ…ตแ„‰แ…ณแ„แ…ฆแ†ท แ„‹แ…กแ„แ…ตแ„แ…ฆแ†จแ„Žแ…ฅ แ„‹แ…ตแ„†แ…ตแ„Œแ…ต -## ๐Ÿ‘ฉ๐Ÿปโ€ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ -ParkEZ แ„‰แ…ตแ„‰แ…ณแ„แ…ฆแ†ท แ„‹แ…กแ„แ…ตแ„แ…ฆแ†จแ„Žแ…ฅ
-## ๐Ÿ‘ฉ๐Ÿปโ€ CI/CD +## โš™๏ธ CI/CD + ParkEZ CICD
-## ๐Ÿ‘ฉ ์™€์ด์–ดํ”„๋ ˆ์ž„ +## ๐Ÿงฉ ์™€์ด์–ดํ”„๋ ˆ์ž„ ParkEZ แ„‹แ…ชแ„‹แ…ตแ„‹แ…ฅแ„‘แ…ณแ„…แ…ฆแ„‹แ…ตแ†ท
-## ๐Ÿ‘ฉ ERD +## ๐Ÿงพ ERD Image
-## ๐Ÿ‘ฉ๐Ÿปโ€ API ๋ช…์„ธ +## ๐Ÿ“ก API ๋ช…์„ธ ๐Ÿ“‘ Swagger ์ฐธ์กฐ : [parkez.click](https://parkez.click/swagger-ui/index.html)

-

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

+โ˜๏ธ 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 โ†’ ์ „์ฒด ์ž‘์—…์— ์˜ํ–ฅ ์—†์ด ๋ณต๊ตฌ ๊ฐ€๋Šฅ -## ๐Ÿ‘ฉ๐Ÿปโ€ ๊ธฐ์ˆ  ๊ณ ๋„ํ™” -- [AWS Lambda๋กœ ํŠน์ • ์‹œ๊ฐ„์— ์™ธ๋ถ€API ํ˜ธ์ถœํ•˜๊ธฐ](https://dev-leonie.tistory.com/78) -- [Spring Batch๋ฅผ ์ด์šฉํ•œ ์ •์‚ฐ ๊ธฐ๋Šฅ](https://velog.io/@hyuk905/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B0%B0%EC%B9%98Spring-Batch%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0) -- [Amazon SES](https://codingtrip.tistory.com/137) -- [EventListener โ†’ Redis Pub/Sub](https://codingtrip.tistory.com/141) +
+
+๐Ÿ“ง 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. ๋™์‹œ์„ฑ ํ…Œ์ŠคํŠธ - ์ปค๋„ฅ์…˜ ํ’€ ๊ณ ๊ฐˆ ๋ฐœ์ƒ -๐Ÿ”Ž ์ƒํ™ฉ

-๋™์‹œ์„ฑ ํ…Œ์ŠคํŠธ์—์„œ ์ปค๋„ฅ์…˜ ํ’€ ๊ณ ๊ฐˆ๋กœ ์ธํ•ด, ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์Šต๋‹ˆ๋‹ค.
-๐Ÿ’ฅ ๋ฌธ์ œ

-ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ์— @Transacional์ด ๊ฑธ๋ ค ์žˆ์–ด์„œ ์ „์ฒด ํ…Œ์ŠคํŠธ๊ฐ€ ํ•˜๋‚˜์˜ ํŠธ๋žœ์žญ์…˜์œผ๋กœ ์‹คํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

-๐Ÿš€ ํ•ด๊ฒฐ

-ํ…Œ์ŠคํŠธ ๋ฉ”์„œ๋“œ์—์„œ @Transactional ์ œ๊ฑฐ +## ๐Ÿงฏ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… +### 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์ด ์ž‘๋™ํ•˜์ง€ ์•Š์Œ** + +```java +// ReservationService +Reservation reservation = reservationReader.findMyReservation(...); // ReadOnly ํŠธ๋žœ์žญ์…˜ + reservationWriter.cancel(reservation); // ๋‚ด๋ถ€์—์„œ reservation.cancel() ํ˜ธ์ถœ โ†’ ๋ณ€๊ฒฝ ๊ฐ์ง€ ์•ˆ ๋จ +``` +โœ… ํ•ด๊ฒฐ ๋ฐฉ์•ˆ + +โœ… ๋‹จ๊ธฐ ํ•ด๊ฒฐ: ๋ช…์‹œ์  save ํ˜ธ์ถœ + +```java +public void cancel(Reservation reservation) { + reservation.cancel(); + reservationRepository.save(reservation); // Detached ๊ฐ์ฒด merge +} +``` + +โœ… ๊ทผ๋ณธ์  ํ•ด๊ฒฐ: ํŠธ๋žœ์žญ์…˜ ๋ฒ”์œ„ ์žฌ์„ค๊ณ„ +```java +// 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 (๋น„๊ด€์  ๋ฝ) ์„ ํ™œ์šฉํ•˜์—ฌ ์ฟ ํฐ ์žฌ๊ณ ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ์ œ์–ดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. - **์žฅ์ ** @@ -137,9 +302,7 @@ DB์˜ Pessimistic Lock (๋น„๊ด€์  ๋ฝ) ์„ ํ™œ์šฉํ•˜์—ฌ ์ฟ ํฐ ์žฌ๊ณ ๋ฅผ ์•ˆ์ „ โ†’ **๋‹ค๋ฅธ ํŠธ๋žœ์žญ์…˜์ด ์ง€์—ฐ**๋˜๊ณ  โ†’ **์ฟ ํฐ ์กฐํšŒ ๋ฐ ๊ด€๋ จ ๋กœ์ง์— ๋ณ‘๋ชฉ**์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ -
- -
๐Ÿšง ๊ฐœ์„  ๋ฐฉํ–ฅ +๐Ÿšง ๊ฐœ์„  ๋ฐฉํ–ฅ ##### ๐Ÿ” ๋ถ„์‚ฐ๋ฝ ์ ์šฉ ์˜ˆ์ • @@ -153,9 +316,44 @@ DB์˜ Pessimistic Lock (๋น„๊ด€์  ๋ฝ) ์„ ํ™œ์šฉํ•˜์—ฌ ์ฟ ํฐ ์žฌ๊ณ ๋ฅผ ์•ˆ์ „ - **๋ฐœ๊ธ‰ ์š”์ฒญ์€ ๋™๊ธฐ ์ฒ˜๋ฆฌ**, ์‚ฌ์šฉ์ž์—๊ฒŒ ๋น ๋ฅธ ์‘๋‹ต ์ œ๊ณต - **๋ฐœ๊ธ‰ ๊ธฐ๋ก์€ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ**, ์‹œ์Šคํ…œ ๋ถ€ํ•˜ ๋ถ„์‚ฐ - **์˜ˆ์‹œ**: 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)** ๋„์ž… ๊ณ ๋ ค + +
+ + +## ๐Ÿ’ฌ๏ธ ํšŒ๊ณ  + +๐Ÿฃ [์กฐ์˜ˆ์ธ](https://codingtrip.tistory.com) : ๊ธด ์—ฌ์ •์„ ์ข‹์€ ํŠœํ„ฐ๋‹˜, ํŒ€์›๋ถ„๋“ค์„ ๋งŒ๋‚˜ ์ž˜ ๋งˆ๋ฌด๋ฆฌํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ ์ดํ›„์—๋„ ๊ฐ™์ด ๋งŒ๋‚˜์„œ๋ณต์Šต, ๊ฐœ์„  ๋ฐ ๋ฐœ์ „ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

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

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

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

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

+ +

From b4cc0525d7d447cab415653e40a486e381d94d12 Mon Sep 17 00:00:00 2001 From: codingTrip <83770197+codingTrip-IT@users.noreply.github.com> Date: Fri, 2 May 2025 20:43:07 +0900 Subject: [PATCH 2/2] =?UTF-8?q?Docs:=20=ED=95=98=EC=9D=B4=ED=8D=BC?= =?UTF-8?q?=EB=A7=81=ED=81=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 241 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 237 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 68fe6a3..5c27ae5 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ +Select Header + +
Image
@@ -34,7 +37,7 @@ 1. [๐Ÿงฐ ๊ธฐ์ˆ ์Šคํƒ](#-๊ธฐ์ˆ ์Šคํƒ) 2. [๐Ÿ—‚ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜](#-์‹œ์Šคํ…œ-์•„ํ‚คํ…์ฒ˜) -3. [โš™๏ธ CI/CD](#โš™๏ธ-cicd) +3. [๐Ÿ’ฟ CI/CD](#-cicd) 4. [๐Ÿงฉ ์™€์ด์–ดํ”„๋ ˆ์ž„](#-์™€์ด์–ดํ”„๋ ˆ์ž„) 5. [๐Ÿงพ ERD](#-erd) 6. [๐Ÿ“ก API ๋ช…์„ธ](#-api-๋ช…์„ธ) @@ -43,7 +46,7 @@ 9. [๐Ÿ“ˆ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€](#-ํ…Œ์ŠคํŠธ-์ปค๋ฒ„๋ฆฌ์ง€) 10. [๐Ÿงฏ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…](#-ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…) 11. [๐Ÿ”ญ ํ–ฅํ›„ ๋ฐœ์ „ ๋ฐฉํ–ฅ](#-ํ–ฅํ›„-๋ฐœ์ „-๋ฐฉํ–ฅ) -12. [๐Ÿ’ฌ๏ธ ํšŒ๊ณ ](#๐Ÿ’ฌ๏ธ-ํšŒ๊ณ ) +12. [๐Ÿ“– ํšŒ๊ณ ](#-ํšŒ๊ณ )
@@ -75,7 +78,7 @@
-## โš™๏ธ CI/CD +## ๐Ÿ’ฟ CI/CD ParkEZ CICD @@ -348,7 +351,7 @@ DB์˜ Pessimistic Lock (๋น„๊ด€์  ๋ฝ) ์„ ํ™œ์šฉํ•˜์—ฌ ์ฟ ํฐ ์žฌ๊ณ ๋ฅผ ์•ˆ์ „
-## ๐Ÿ’ฌ๏ธ ํšŒ๊ณ  +## ๐Ÿ“– ํšŒ๊ณ  ๐Ÿฃ [์กฐ์˜ˆ์ธ](https://codingtrip.tistory.com) : ๊ธด ์—ฌ์ •์„ ์ข‹์€ ํŠœํ„ฐ๋‹˜, ํŒ€์›๋ถ„๋“ค์„ ๋งŒ๋‚˜ ์ž˜ ๋งˆ๋ฌด๋ฆฌํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ ์ดํ›„์—๋„ ๊ฐ™์ด ๋งŒ๋‚˜์„œ๋ณต์Šต, ๊ฐœ์„  ๋ฐ ๋ฐœ์ „ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

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

@@ -357,3 +360,233 @@ DB์˜ Pessimistic Lock (๋น„๊ด€์  ๋ฝ) ์„ ํ™œ์šฉํ•˜์—ฌ ์ฟ ํฐ ์žฌ๊ณ ๋ฅผ ์•ˆ์ „ ๐ŸŽ… [์žฅ์œคํ˜](https://velog.io/@hyuk905/posts) : ์ตœ์ข… ํ”„๋กœ์ ํŠธ์ธ ๋งŒํผ ์ข‹์€ ํŒ€์›๋“ค๊ณผ ํ•จ๊ป˜ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์‹œ๋„๋ฅผ ๋‹ค์–‘ํ•˜๊ฒŒ ํ•ด ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ ์ข‹์•˜์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ•œ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ๋ณต์Šตํ•˜๋ฉฐ ์ง์ ‘ ๊ตฌํ˜„ํ•ด ๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

+ +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๋ฅผ ์ด์šฉํ•œ ์ •์‚ฐ ๊ธฐ๋Šฅ + + +๐Ÿ›  ๋ชฉ์ฐจ +๐Ÿงฐ ๊ธฐ์ˆ ์Šคํƒ +๐Ÿ—‚ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ +๐Ÿ’ฟ CI/CD +๐Ÿงฉ ์™€์ด์–ดํ”„๋ ˆ์ž„ +๐Ÿงพ ERD +๐Ÿ“ก API ๋ช…์„ธ +๐Ÿš€ ๊ธฐ์ˆ  ๊ณ ๋„ํ™” +๐Ÿงช ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ +๐Ÿ“ˆ ํ…Œ์ŠคํŠธ ์ปค๋ฒ„๋ฆฌ์ง€ +๐Ÿงฏ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… +๐Ÿ”ญ ํ–ฅํ›„ ๋ฐœ์ „ ๋ฐฉํ–ฅ +๐Ÿ“– ํšŒ๊ณ  + +๐Ÿงฐ ๊ธฐ์ˆ ์Šคํƒ +๐Ÿ’ป Language / Backend + + +โš™๏ธ Database + + +๐Ÿ” Test + + +๐Ÿ” Security + + +๐ŸŽจ Collaboration Tool + + +๐Ÿ›  Deployment & Distribution + + + + + +๐Ÿ—‚ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜ +ParkEZ แ„‰แ…ตแ„‰แ…ณแ„แ…ฆแ†ท แ„‹แ…กแ„แ…ตแ„แ…ฆแ†จแ„Žแ…ฅ แ„‹แ…ตแ„†แ…ตแ„Œแ…ต +๐Ÿ’ฟ CI/CD +ParkEZ CICD +๐Ÿงฉ ์™€์ด์–ดํ”„๋ ˆ์ž„ +ParkEZ แ„‹แ…ชแ„‹แ…ตแ„‹แ…ฅแ„‘แ…ณแ„…แ…ฆแ„‹แ…ตแ†ท +๐Ÿงพ ERD +Image +๐Ÿ“ก API ๋ช…์„ธ +๐Ÿ“‘ Swagger ์ฐธ์กฐ : parkez.click + + +๐Ÿš€ ๊ธฐ์ˆ  ๊ณ ๋„ํ™” +โ˜๏ธ AWS Lambda๋กœ ์™ธ๋ถ€ API ํ˜ธ์ถœ ์ž๋™ํ™” +๐Ÿ’ฐ Spring Batch ๊ธฐ๋ฐ˜ ์ •์‚ฐ ์ฒ˜๋ฆฌ +๐Ÿ“ง Redis Pub/Sub + Amazon SES ๊ธฐ๋ฐ˜ ๋ฉ”์ผ ์ „์†ก + +๐Ÿงช ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ +์˜ˆ์•ฝ ์ƒ์„ฑ ์‹œ ๋™์‹œ์„ฑ ์ œ์–ด ํ…Œ์ŠคํŠธ +ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค +์ด 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์กฐ ์ทจ๋ฝ€ ํ™”์ดํŒ… + +๐ŸŽ… ์žฅ์œคํ˜ : ์ตœ์ข… ํ”„๋กœ์ ํŠธ์ธ ๋งŒํผ ์ข‹์€ ํŒ€์›๋“ค๊ณผ ํ•จ๊ป˜ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์‹œ๋„๋ฅผ ๋‹ค์–‘ํ•˜๊ฒŒ ํ•ด ๋ณผ ์ˆ˜ ์žˆ์–ด์„œ ์ข‹์•˜์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ๊ตฌํ˜„ํ•˜์ง€ ๋ชปํ•œ ๋ถ€๋ถ„์— ๋Œ€ํ•ด์„œ ๋ณต์Šตํ•˜๋ฉฐ ์ง์ ‘ ๊ตฌํ˜„ํ•ด ๋ณผ ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.