@@ -34,23 +35,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 +71,230 @@
### ๐ Deployment & Distribution

-### ๐ฅ๏ธ Monitoring
-

+
-
+## ๐ ์์คํ
์ํคํ
์ฒ
+

-## ๐ฉ๐ปโ ์์คํ
์ํคํ
์ฒ
-
-## ๐ฉ๐ปโ CI/CD
+## ๐ฟ CI/CD
+
-## ๐ฉ ์์ด์ดํ๋ ์
+## ๐งฉ ์์ด์ดํ๋ ์
-## ๐ฉ ERD
+## ๐งพ ERD
-## ๐ฉ๐ปโ 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 โ ์ ์ฒด ์์
์ ์ํฅ ์์ด ๋ณต๊ตฌ ๊ฐ๋ฅ
+
+
+
+๐ง 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 ์ค์
+
-## ๐ฉ๐ปโ ๊ธฐ์ ๊ณ ๋ํ
-- [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)
+### ๐ ํ
์คํธ ๊ฒฐ๊ณผ
-## ๐ฉ๐ปโ ์ฑ๋ฅ ํ
์คํธ
+| ํญ๋ชฉ | ์บ์ ์ ์ฉ ์ | ์บ์ ์ ์ฉ ํ | ๋ณํ์จ |
+|------------------|----------------|----------------|----------------|
+| **Throughput** | 4.2/sec | 31.9/sec | ๐ผ +659.5% ์ฆ๊ฐ |
+| **ํ๊ท ์๋ต์๊ฐ** | 61,641 ms | 15,678 ms | ๐ฝ -74.6% ๊ฐ์ |
+### โ
๋ถ์
+- Redis ์บ์ ์ ์ฉ์ผ๋ก **์ฒ๋ฆฌ๋(Throughput)์ด 6๋ฐฐ ์ด์ ์ฆ๊ฐ**
+- **์๋ต์๊ฐ์ด 1/4 ์์ค์ผ๋ก ๋จ์ถ๋์ด ์ฌ์ฉ์ ๊ฒฝํ ๊ฐ์ **
+- ๋์ฉ๋ ๋ฐ์ดํฐ์ ๋ํด ์บ์ ์ ์ฉ ์ ํ์ฐํ ์ฑ๋ฅ ํฅ์ ํ์ธ
-## โ๏ธ ํ
์คํธ ์ปค๋ฒ๋ฆฌ์ง
+
+
+
+## ๐ ํ
์คํธ ์ปค๋ฒ๋ฆฌ์ง
-## ๐ฅ ํธ๋ฌ๋ธ์ํ
-### 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 +305,7 @@ DB์ Pessimistic Lock (๋น๊ด์ ๋ฝ) ์ ํ์ฉํ์ฌ ์ฟ ํฐ ์ฌ๊ณ ๋ฅผ ์์
โ **๋ค๋ฅธ ํธ๋์ญ์
์ด ์ง์ฐ**๋๊ณ
โ **์ฟ ํฐ ์กฐํ ๋ฐ ๊ด๋ จ ๋ก์ง์ ๋ณ๋ชฉ**์ด ๋ฐ์ํ ์ ์์
-
-
-๐ง ๊ฐ์ ๋ฐฉํฅ
+๐ง ๊ฐ์ ๋ฐฉํฅ
##### ๐ ๋ถ์ฐ๋ฝ ์ ์ฉ ์์
@@ -153,9 +319,274 @@ 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) : ์ต์ข
ํ๋ก์ ํธ์ธ ๋งํผ ์ข์ ํ์๋ค๊ณผ ํจ๊ป ์ฌ๋ฌ ๊ฐ์ง ์๋๋ฅผ ๋ค์ํ๊ฒ ํด ๋ณผ ์ ์์ด์ ์ข์์ต๋๋ค. ์ ๊ฐ ๊ตฌํํ์ง ๋ชปํ ๋ถ๋ถ์ ๋ํด์ ๋ณต์ตํ๋ฉฐ ์ง์ ๊ตฌํํด ๋ณผ ์์ ์
๋๋ค.
+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์กฐ ์ทจ๋ฝ ํ์ดํ
+
+๐
์ฅ์คํ : ์ต์ข
ํ๋ก์ ํธ์ธ ๋งํผ ์ข์ ํ์๋ค๊ณผ ํจ๊ป ์ฌ๋ฌ ๊ฐ์ง ์๋๋ฅผ ๋ค์ํ๊ฒ ํด ๋ณผ ์ ์์ด์ ์ข์์ต๋๋ค. ์ ๊ฐ ๊ตฌํํ์ง ๋ชปํ ๋ถ๋ถ์ ๋ํด์ ๋ณต์ตํ๋ฉฐ ์ง์ ๊ตฌํํด ๋ณผ ์์ ์
๋๋ค.