-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Byeongmin Bae edited this page Jul 19, 2026
·
2 revisions
erDiagram
User ||--|| UserSubscription : ""
SubscriptionPlan ||--o{ SubscriptionPlanBenefit : ""
SubscriptionPlan ||--o{ UserSubscription : ""
SubscriptionBenefit ||--o{ SubscriptionPlanBenefit : ""
UserSubscription ||--o{ PaymentHistory : ""
User ||--o{ Watch : ""
User ||--|{ UserOAuth : ""
UserOAuth ||--o| NaverOAuth : ""
Watch ||--|{ WatchCondition : ""
Watch ||--o{ WatchSnapshot : ""
PaymentHistory ||--|| PlanPaymentHistory : ""
PaymentHistory ||--|| TossPaymentHistory : ""
TossPaymentHistory ||--o{ TossPaymentCancelHistory : ""
Base {
Long id PK
%% ์ํฐํฐ๊ฐ ์์ฑ๋ ๋ ์ง์ ์๊ฐ. ๋ชจ๋ ๋ ์ง๋ DB์ UTC๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ์ฅ
LocalDateTime createdAt
%% ์ํฐํฐ์ ํ๋์ค ํ๋ ์ด์์ด ์
๋ฐ์ดํธ๋ ๋ ์ง์ ์๊ฐ
LocalDateTime updatedAt
%% ์ํฐํฐ๊ฐ ๋
ผ๋ฆฌ์ญ์ ๋ ๋ ์ง์ ์๊ฐ
LocalDateTime deletedAt
}
LogBase {
Long id PK
%% ์ํฐํฐ๊ฐ ์์ฑ๋ ๋ ์ง์ ์๊ฐ. ๋ชจ๋ ๋ ์ง๋ DB์ UTC๋ฅผ ๊ธฐ์ค์ผ๋ก ์ ์ฅ
LocalDateTime createdAt
}
SubscriptionPlan {
%% ํ๋ ์ด๋ฆ
String name
%% ํ๋ ๊ฐ๊ฒฉ
BigDecimal price
%% ํ๋ ์ ๊ณต ์ผ์
Int durationDays
%% ํ๋ ์ด์ฉ์ค์ด๋ฉด์ ์์ ํ๋์ ์ถ๊ฐ๊ฒฐ์ ํ๋๊ฒฝ์ฐ ์
๊ทธ๋ ์ด๋๊ฐ ๋จ
%% ํ๋ ๋ค์ด๊ทธ๋ ์ด๋๋ ๋ถ๊ฐ๋ฅํ์ง๋ง ํ๋ถ์ ๋จ์ ์ผ์๋งํผ ๊ฐ๋ฅ
Int priority
%% ์ด๋ฒคํธ์ฑ ํ๋์ด๋ผ๋ฉด ๊ธฐ๋ก
LocalDateTime availableUntil
}
SubscriptionPlanBenefit {
SubscriptionPlan subscriptionPlan FK
SubscriptionBenefit subscriptionBenefit FK
%% 20๊ฐ
Int value
}
SubscriptionBenefit {
%% WATCH_AMOUNT
Enum benefitType
}
%% ์ ์ ๊ฐ ํ์ฌ ์ด์ฉ์ค์ธ ํ๋. ํ์ฌ ๊ธฐ๋ณธ์ free ํ๋
UserSubscription{
User user FK
SubscriptionPlan plan FK
%% PaymentHistory ๋ฐ๋ผ ๊ฒฐ์ ๋จ
%% ๋ง์ฝ ๋์ผ ํ๋์ผ๋ก ์ฌ๊ฒฐ์ ํ ๊ฒฝ์ฐ -> ๋ ์ง๋ง ๋๋ฆฌ๋ฉด ๋จ
%% ์
๊ทธ๋ ์ด๋์ธ ๊ฒฝ์ฐ -> ๊ธฐ์กด ํ๋ ๋จ์์ผ์ ๊ณ์ฐํด์ ์ฐจ์ก์ ํ ์ธ.
LocalDateTime expiredAt
%% ์ ํ๋ ๊ฒฐ์ ์ผ๋ก startedAt ๊ฐฑ์
LocalDateTime startedAt
}
PaymentHistory {
User user FK
%% ํ ์ธ๋ฐ์ ๊ธ์ก
BigDecimal discountPrice
%% ๊ฒฐ์ API ์ ๊ณต PG์ฌ
Enum pgProvider
%% ๊ฒฐ์ ์น์ธ ๋ ์ง ์๊ฐ
LocalDateTime approvedAt
%% ํ๋ถ์ ๊ธฐ๋ก
LocalDateTime refundedAt
}
PlanPaymentHistory{
PaymentHistory paymentHistory FK
%% ํ๋ ์ด๋ฆ
String name
%% ํ๋ ๊ฐ๊ฒฉ
BigDecimal price
%% ํ๋ ๊ฐ์
Int month
%% ํ๋ ์ฐ์ ์์
Enum tier
}
TossPaymentHistory {
PaymentHistory paymentHistory FK
%% ์ฌ๊ธฐ์ api ๋ฌธ์์ ์๋ ํ๋ ๋๋ค์ด๊ฐ์ผํจ
%% ๊ฒฐ์ ์ทจ์์ ํ์
String paymentKey
String orderId
%% ๊ฒฐ์ ๊ธ์ก
Int balanceAmount
%% DONE, CANCELED ๋ฑ
Enum status
String rawResponse
}
%% ์ทจ์๋ ์ฌ๋ฌ๋ฒ ๋ฐ์ ๊ฐ๋ฅ(๋ถ๋ถ์ทจ์)
TossPaymentCancelHistory {
TossPaymentHistory tossPaymentHistory FK
%% ๊ฒฐ์ ๋ฅผ ์ทจ์ํ ๊ธ์ก์
๋๋ค.
Int cancelAmount
%% ๊ฒฐ์ ๋ฅผ ์ทจ์ํ ์ด์ ์
๋๋ค. ์ต๋ ๊ธธ์ด๋ 200์์
๋๋ค.
String cancelReason
%% ๊ฒฐ์ ์ทจ์๊ฐ ์ผ์ด๋ ๋ ์ง์ ์๊ฐ ์ ๋ณด์
๋๋ค.
LocalDateTime canceledAt
%% ์ทจ์ ๊ฑด์ ํค๊ฐ์
๋๋ค. ์ฌ๋ฌ ๊ฑด์ ์ทจ์ ๊ฑฐ๋๋ฅผ ๊ตฌ๋ถํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ต๋ ๊ธธ์ด๋ 64์์
๋๋ค.
String transactionKey
}
User {
%% USER, ADMIN
Enum role
%% accessToken ๋ง๋ฃ์ ๋ฆฌํ๋ ์ ํ ํฐ์ผ๋ก ์ฌ๋ฐ๊ธ ๊ฐ๋ฅ
String refreshToken
LocalDateTime lastLoginAt
%% ์๋๋ ๋ก๊ทธ์ธ API ์์ ๋์ด์จ ์์๋ค
String nickname
String email
String profileImageUrl
}
UserOAuth {
User user FK
%% NAVER, GOOGLE
Enum provider
String providerId
LocalDateTime connectedAt
}
%% ๋ค์ด๋ฒ ๋ก๊ทธ์ธ์์ ๋ฐ๊ธ๋๋ ๋ค์ด๋ฒ ์๋น์ค ์ ์ฉ ํ ํฐ
NaverOAuth {
UserOAuth userOAuth FK
String accessToken
String refreshToken
LocalDateTime expiredAt
}
Watch {
User user FK
%% ์ ์ ๊ฐ ๋ฑ๋กํ ์ด๋ฆ
String name
%% ์ ์ ๊ฐ ๋ฑ๋กํ url
String url
%% ์ฒซ ์์ฒญํ ๊ฐ์ ธ์จ ํ๋น์ฝ. ์ผ์ ์๊ฐ๋ง๋ค ๊ฐฑ์ ํ์ํจ
String faviconUrl
%% RUNNING, PAUSED(์ฌ์ฉ์๊ฐ ์ผ์์ ์ง), PAYMENT_REQUIRED(๊ฒฐ์ ํ์), ILLEGAL_SUSPENDED(๋ถ๋ฒ์ ์ธ ๋ด์ฉ)
Enum status
%% ํฌ๋กค๋ง ์ฃผ๊ธฐ
Int intervalSecond
Boolean isIncludedInStat
%% ๋ง์ง๋ง ํฌ๋กค๋ง ์ํ ์๊ฐ
LocalDateTime lastFetchedAt
%% ๋ง์ง๋ง ์๋ฆผ ์ํ ์๊ฐ
LocalDateTime lastNotifiedAt
}
%% ํ์
๋์ด๋์ nullable ํ๋๊ฐ ์๊ธด๋ค๋ฉด ์ํผ/์๋ธํ์
๊ณ ๋ ค
WatchCondition {
Watch watch FK
%% HTML_FULL, KEYWORD
Enum type
String keyword
}
%% fetch fail ์ ์์ฑ๋์ง ์์
WatchSnapshot {
Watch watch FK
%% ํ์ฌ ํฌ๋กค๋งํด์ ๊ฐ์ ธ์จ html ์๋ณธ
String htmlContentUrl
%% ์ด์ html ํ๊ณ ํ์ฌ html ํ๊ณ diff ๊ฒฐ๊ณผ
String htmlContentDiffUrl
%% ํ์ฌ ํฌ๋กค๋งํ ์ฌ์ดํธ ์บก์ณ๋ณธ
String screenshotUrl
%% ์ด์ ์ฌ์ดํธ ์บก์ณ๋ณธ๊ณผ ๋น๊ตํด ๊ฒฐ๊ณผ์ ์ผ๋ก ๋ค๋ฅธ ๋ถ๋ถ์ด ๊ฐ์กฐ๋ ์บก์ณ๋ณธ
String screenshotDiffUrl
%% htmlContentDiff ๊ธฐ๋ฐ์ผ๋ก ์์ฑ๋ AI ์์ฝ
String aiSummary
%% ์๋ฆผ ์ ์ก ์๊ฐ
LocalDateTime notifiedAt
}
HotUrlStat {
%% ์กฐํ๋ ํ์
Int hit
%% ๋ฉ์ธ ์ฌ์ดํธ ํต๊ณ์ชฝ์ ๋ณด์ผ url(a.com)
String url
%% ์ผ ๋จ์ ํต๊ณ
LocalDate statDate
}
Crawlinglog {
%% ์์น๋ฆฌ์คํธ์ ์ฌ์ฉ์๊ฐ ๋ฑ๋กํ ์ด๋ฆ
String name
%% ์์ฒญ์ด ์ํ๋ url
String requestedUrl
%% ํฌ๋กค๋ง ์ฃผ๊ธฐ
Int intervalSecond
%% ํฌ๋กค๋ง ์์
์์ ์๊ฐ
LocalDateTime startedAt
%% ํฌ๋กค๋ง ์์
์ด ์ฑ๊ณตํ ์๊ฐ. ์คํจ์ null
LocalDateTime succeededAt
%% ํฌ๋กค๋ง ์์
์ด ๋๋ ์๊ฐ
LocalDateTime endedAt
%% http ์๋ต ์ฝ๋
Int httpResponseCode
%% ์คํจ์ ์ฑ์์ง๋ ์์ถ๋ html ์๋ณธ ์ปจํ
์ธ
String compressedHtml
}
| Method | URL | ์ค๋ช |
|---|---|---|
| GET | /auth/naver/url |
๋ค์ด๋ฒ OAuth URL ์์ฑ ๋ฐ ๋ฐํ |
| GET | /auth/naver/callback |
๋ค์ด๋ฒ OAuth ์ฝ๋ฐฑ ์ฒ๋ฆฌ ๋ฐ Watchtower JWT ๋ฐ๊ธ |
| DELETE | /auth/naver/revoke |
๋ค์ด๋ฒ OAuth Token Revocation |
| POST | /auth/renew |
Watchtower Token ์ฌ๋ฐ๊ธ |
| DELETE | /auth/logout |
Watchtower Refresh Token ์ญ์ |
| Method | URL | ์ค๋ช |
|---|---|---|
| GET | /users/{userId} |
ํ๋กํ ์กฐํ |
| GET | /users/{userId}/payments |
๊ฒฐ์ ์ด๋ ฅ ์กฐํ |
| GET | /users/{userId}/watches |
์์น ๋ชฉ๋ก ์กฐํ |
| PATCH | /users/{userId} |
ํ๋กํ ์ ๋ณด ์์ |
| DELETE | /users/{userId} |
ํ์ ํํด (๋ ผ๋ฆฌ์ญ์ + ๋ค์ด๋ฒ revoke) |
| GET | /users/{userId}/subscriptions |
ํ์ฌ ๊ตฌ๋ ์ค์ธ ํ๋ ์กฐํ |
| DELETE | /users/{userId}/subscriptions |
๊ตฌ๋ ํด์ง ์์ฒญ(ํ๋ถ) |
| Method | URL | ์ค๋ช |
|---|---|---|
| GET | /payments/{paymentId} |
๊ฒฐ์ ๋ด์ญ ๋จ๊ฑด ์์ธ ์กฐํ |
| POST | /payments/toss/confirm |
ํ ์ค ๊ฒฐ์ ์น์ธ |
| Method | URL | ์ค๋ช |
|---|---|---|
| POST | /watches |
์์น ๋ฑ๋ก |
| GET | /watches/trending |
์ค์๊ฐ ์ธ๊ธฐ URL ์กฐํ |
| GET | /watches/{watchId} |
์์น ๋จ๊ฑด ์์ธ ์กฐํ |
| PATCH | /watches/{watchId} |
์์น ์์ (์ผ์์ ์ง/์ฌ๊ฐ ํฌํจ) |
| DELETE | /watches/{watchId} |
์์น ์ญ์ |
| POST | /watches/{watchId}/notify |
ํ ์คํธ ์๋ฆผ ๋ฐ์ก |
| GET | /watches/{watchId}/conditions |
์์น ์กฐ๊ฑด ๋ชฉ๋ก ์กฐํ |
| POST | /watches/{watchId}/conditions |
์์น ์กฐ๊ฑด ์ถ๊ฐ |
| PATCH | /watches/{watchId}/conditions/{conditionId} |
์์น ์กฐ๊ฑด ์์ |
| DELETE | /watches/{watchId}/conditions/{conditionId} |
์์น ์กฐ๊ฑด ์ญ์ |
| GET | /watches/{watchId}/snapshots |
์ค๋ ์ท ํ์๋ผ์ธ ์กฐํ |
| GET | /watches/{watchId}/snapshots/{snapshotId} |
์ค๋ ์ท ๋จ๊ฑด ์์ธ ์กฐํ |
| Method | URL | ์ค๋ช |
|---|---|---|
| GET | /admin/stats/watches |
๋์๋ณด๋ ์์น ํต๊ณ ์กฐํ |
| GET | /admin/stats/payments |
๋์๋ณด๋ ๊ฒฐ์ ํต๊ณ ์กฐํ |
| GET | /admin/stats/users |
๋์๋ณด๋ ์ ์ ์/ํ์ํํด์ ๋ฑ ํต๊ณ ์กฐํ |
| GET | /admin/stats/auth |
๋์๋ณด๋ ๋ก๊ทธ์ธ/ํ์๊ฐ์ ํต๊ณ ์กฐํ |
| PATCH | /admin/watches/{watchId} |
์์น ์ํ ๋ณ๊ฒฝ(์ ์ฑ ์๋ฐ ์ ์ง ํฌํจ) |
| POST | /admin/payments/{paymentId}/cancel |
๊ฒฐ์ ์ง๊ถ ์ทจ์ |
| GET | /admin/payments |
๊ฒฐ์ ๋ด์ญ ์กฐํ/๊ฒ์ |
| GET | /admin/users |
์ ์ฒด ์ ์ ์กฐํ/๊ฒ์ |
| PATCH | /admin/users/{userId}/roles |
์ ์ ๊ถํ ์์ |
| PATCH | /admin/users/{userId}/status |
ban/unban ๋ฑ ์ ์ ์ํ ๋ณ๊ฒฝ |
-
ํ์
- ํ์ฌ๋ก์ ๋ค์ด๋ฒ ๋ก๊ทธ์ธ๋ง ์ง์ํ๊ณ ์์ฒด ํ์๊ฐ์ ์ ์ง์ํ์ง ์์
- ์ ๋ฃ ์ ์ฑ
- ํ์ฌ๋ Free(์์น๋ฆฌ์คํธ ์ต๋ 10๊ฐ) ํ๋๊ณผ Basic(ํ๋ฌ์ 1000์ ์์น๋ฆฌ์คํธ ์ต๋ 20๊ฐ) ํ๋๋ง ์กด์ฌ
- ๊ธฐ์กด ํ๋ ์ด์ฉ์๊ฐ ๋์์ ์๋ก์ด ํ๋์ ์ถ๊ฐ๋ก ๊ฒฐ์ ํ๋ ค๋ ๊ฒฝ์ฐ ๊ธฐ์กด ํ๋ ๊ฐ๊ฒฉ์ ์ฌ์ฉํ ์ผ์๋งํผ ์ฐจ๊ฐํ ํ ํ ์ธ์ด ์ ์ฉ๋ ํ๋ ๊ตฌ๋งค ๊ฐ๋ฅ
- ํ๋ ๊ธฐ๊ฐ์ด ๋๋ free ํ๋์ผ๋ก ๋ณ๊ฒฝ๋ ๊ฒฝ์ฐ 1์ฃผ์ผ์์ ์ฌ๊ฒฐ์ ๋ฅผ ํ์ง ์์ ์ free ํ๋์ ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ ์ต๊ทผ์ ์ถ๊ฐ๋ ์์น๋ฆฌ์คํธ๋ค์ด ์ ์ง๋๊ณ ๊ฒฐ์ ์ ๊น์ง ์ฌ์ฉ์ ์์๋ก ํด์ ๋ถ๊ฐ
- ํ๋ถ ์์ฒญ์ ์ฌ์ฉ์ผ์๋ฅผ ์ฐจ๊ฐํ์ฌ ํ๋ถ
-
์์น๋ฆฌ์คํธ(๋ชจ๋ํฐ๋ง URL) ๋ฑ๋ก
- 1๋ ๋์ ์ฌ์ดํธ์ ๋ก๊ทธ์ธ์ ํ์ง ์์ผ๋ฉด ๋ฑ๋ก๋ ๋ฆฌ์คํธ ์ ๋ถ ์ผ์์ค์ง๋จ
- ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ ์ฃผ์์ ๋ํด์ ๋ฑ๋ก ๋ถ๊ฐ
- ๋ง์ฝ ๋ฑ๋ก ์ดํ ์ ๊ทผ ๋ถ๊ฐ์ ์ผ์์ ์ง๋ก ๋ณ๊ฒฝ, ์ฌ์ฉ์๊ฐ ์ฌ๊ฐ ๋ฒํผ์ ๋๋ฌ ์ ๊ทผ์ด ๋๋๊ฒ์ด ํ์ธ๋ ํ์ ์ฌ์ฌ์ฉ ๊ฐ๋ฅ
- ๋ก๊ทธ์ธ ํด์ผ๋ง ๋ณด์ด๋ ํ์ด์ง๋ ์ถํ ์ฟ ํค ์ ๊ณต์ ๋์ํ ๊ณ ๊ฐ๋ค์ ํํด์ ์ด์ฉ๊ฐ๋ฅ
- ์์น๋ฆฌ์คํธ ์ผ์ชฝ์ ๋ค์ ํญ๋ชฉ์ด ํ์๋๋ค(๋ฌดํ ์คํฌ๋กค)
- URL
- ํ๋น์ฝ
- ์ฌ์ฉ์๊ฐ ์ค์ ํ ์ฌ์ดํธ ์ด๋ฆ
- ์ผ์์ ์ง ์ฌ๋ถ(ํ์๊ณผ ์ด๋ก์ ์ ์์ด์ฝ์ผ๋ก)
- ์ต๊ทผ AI ์์ฝ
- ์์น๋ฆฌ์คํธ ์ค๋ฅธ์ชฝ์ ์ฒ์ ๋ค์ด๊ฐ ๊ฒฝ์ฐ ๋งจ ์ฒซ๋ฒ์งธ ์์ดํ ์ด ๊ธฐ๋ณธ ์ ํ๋จ
- ๋ง์ฝ ํ์ฌ ์ฌ์ฉ์๊ฐ ๋ฑ๋กํ ์์น๋ฆฌ์คํธ๊ฐ ์๋ค๋ฉด ๋ฑ๋ก ์๊ตฌ๋ฅผ ํด์ผํจ
- ์์น๋ฆฌ์คํธ์ ์ค๋ฅธ์ชฝ์๋ ๋ค์ ํญ๋ชฉ์ด ํ์๋๋ค.
- ์์ ํ์๋์๋ ์ ๋ณด์ ํจ๊ป
- ์ต๊ทผ ๊ฐฑ์ ๋ ์๊ฐ
- ์ผ์์ ์ง/์ฌ๊ฐ ๋ฒํผ(์ฌ๊ฐ์ URL ์ ๊ทผ ๊ฐ๋ฅ์ฌ๋ถ ์ฒดํฌํ ์ผ์์ ์ง ํ์ด์ผํจ)
- ํ์ด์ง ์ ์ฒด์ ํ์๋ผ์ธ๊ณผ ๋ณ๊ฒฝ๋ ๋ถ๋ถ๋ง์ ์๊ฐํํ๋ ํ์๋ผ์ธ์ผ๋ก ์ ์ ๊ฐ ์ด๋ค ๋ถ๋ถ์ด ๋ณํ๋์ง ์์์๋๋กํจ
- ๊ฐ ํ์๋ผ์ธ์์ ์ค๋ ์ท๋ค์ ์ต๋ ์ผ์ฃผ์ผ๊ฐ ๋ณด๊ด ๋ฐ ์กฐํ๊ฐ๋ฅ(S3 ์๊ธ์ ๊ณ ๋ คํด์ ์ถํ์ ๋๋ฆฌ๋๊ฒ ๊ณ ๋ ค)
- ์ต์ ํ์ธ ์ฃผ๊ธฐ๋ 5๋ถ๋จ์๋ก 5๋ถ๋ถํฐ ์ต๋ 24์๊ฐ๊น์ง ์ค์ ๊ฐ๋ฅ.
- ๋ง์ฝ ๋์ผ URL ์ ์ฌ๋ฌ ์กฐ๊ฑด์ผ๋ก ์๋์ ๋ฐ๊ณ ์ถ๋ค๋ฉด ํ๋์ ์์น๋ฆฌ์คํธ์์ ๋ค์ค ์กฐ๊ฑด์ ์ค์ ํ๋ฉด๋จ.
- ์ฌ๋ฌ ์กฐ๊ฑด์๋ ํ์ฌ๋ก์ html ์ ์ฒด ๊ฐ์ง์ ํน์ ํค์๋ ๋ฑ์ฅ/์๋ฉธ ๊ฐ์ง๊ฐ ์์
- ํ๋์ ์์น๋ฆฌ์คํธ์๋ ๋ค์ค์กฐ๊ฑด์ด ์๋๊ฒ๊ณผ๋ ๋ฌด๊ดํ๊ฒ ํ๋์ ํ์ธ์ฃผ๊ธฐ๋ง ์กด์ฌํจ(์: a.com/abc ์ ๋ํ ์กฐ๊ฑด์ด 3๊ฐ ์๋๋ผ๋ ๋ชจ๋ ํ์ธ ์ฃผ๊ธฐ๋ ๋์ผํจ)
- ์ค๋ณต์กฐ๊ฑด์ ์ต๋ 3๊ฐ๊น์ง ๋ฑ๋ก๊ฐ๋ฅ
-
ํ์ฌ Hot ํ ์์น๋ฆฌ์คํธ
- ๋ค์ด๋ฒ ์ค์๊ฐ ๊ฒ์์ด์ฒ๋ผ ๋ณํ์๋ฅผ ๊ธฐ์ค์ผ๋ก ํ์ฌ ํซํ URL ์ ์ผ๋จ์ ์ง๊ณํ์ฌ 10๊ฐ๊น์ง ๋์ด
- URL ์ ํด๋ฆญํด์ ๋ค์ด๊ฐ์์์
- ๋ ธ์ถ๋๋ค๋ ๊ฑฐ๋ถ๊ฐ์ด ๋ค์ง ์๋๋ก ๋๋ฉ์ธ๊น์ง๋ง(a.com) ํ๊ธฐ
- ํต๊ณ ์ง๊ณ๋ฅผ ์ํ์ง ์๋ ๊ณ ๊ฐ์ ํด๋น ์์น๋ฆฌ์คํธ ์์ฑ์์๋ง ๋๊ธฐ ๊ฐ๋ฅ
-
์์น๋ฆฌ์คํธ ๋ณํ ์๋ฆผ
- ํ์ฌ๋ก์ ๋์ค์ฝ๋์ ํ ๋ ๊ทธ๋จ๋ง ์ง์(์นด์นด์คํก, ๋ฉ์ผ๊ฐ์ ๋น์ฉ๋๋๊ฑด ์ดํ์ ๊ณ ๋ ค)
- ์ต์ด ํฌ๋กค๋ง์ ์ค๋ ์ท๋ง ์ ์ฅํ๊ณ ์๋ฆผ์ ์์
- ์์น๋ฆฌ์คํธ์๋ ์๋ฆผ ์์ ํ ์คํธ ๊ธฐ๋ฅ์ด ์์ด์ผํจ Uptime Kuma ๊ฐ์ด
- ์๋ฆผ๋ด์ฉ์ ๋ค์์ด ํฌํจ๋์ด์์ด์ผํจ
- ์ฌ์ฉ์๊ฐ ์ค์ ํ ์ฌ์ดํธ ์ด๋ฆ
- URL
- ๋ฐฉ๊ธ ๋ฐ์ํ ๋ณํ์ ๋ํ AI ์์ฝ
- ์ด์ ์ค๋ ์ท๊ณผ ๋ฌ๋ผ์ง ๋ถ๋ถ๋ง ๊ฐ์กฐ
-
์ธ์ฆ
- ์๋ฒ ์ํํ์ฅ์ redis ์ฌ์ฉ์ ํ์ง ์๊ธฐ์ํด(๊ด๋ฆฌํฌ์ธํธ/๋น์ฉ ์ ๊ฐ) JWT ์ฌ์ฉ
-
์์น๋ฆฌ์คํธ ๋ฑ๋ก
- ์ ๊ทผํ ์ ์๋ ์ฃผ์๋ฅผ ํ๋จํ๋ ๊ธฐ์ค
- 400๋ฒ๋ ์๋ฌ
- ๋นํ์ด์ง
- Cloudflare challenge(์ถํ์ ์ฐํ๋ฒ์ ์ฐพ์์ผํจ)
- ๋ฑ๋ฑ...(์ถํ์ ์ถ๊ฐ)
- js ๋ ๋๋ง์ ํด์ผ ๋ํ๋๋ ์ปจํ
์ธ ๋ ์์ผ๋ Playwright ๊ฐ์๊ฑธ ์จ์ผํจ
- ์คํ๋ง๊ณผ๋ ๋ณ๊ฐ๋ก SQS ํ์์ ๋ฉ์์ง ์ ๊ธฐ์ค์ผ๋ก ์คํ ์ค์ผ์ผ๋ง ๊ณ ๋ ค
- ์ฟ ํค๋ document.cookie ๋ฅผ ์ฌ์ฉ์๊ฐ ์น๊ฒ ๋ง๋ค๊ฑฐ๋, ๋ธ๋ผ์ฐ์ ์ต์คํ ์ ๋ง๋ค๊ฑฐ๋ ๋ฑ ๋ฐฉ๋ฒ์ ๊ณ ๋ ค
- ์ ๊ทผํ ์ ์๋ ์ฃผ์๋ฅผ ํ๋จํ๋ ๊ธฐ์ค
-
ํ์ฌ Hot ํ ์์น๋ฆฌ์คํธ
- ์นด์ดํ ์ ๊ฒฝํฉ์ด ํฌ์ง ์์๊ฒ์ผ๋ก ์์๋๊ธฐ ๋๋ฌธ์ ๋๊ด๋ฝ์ผ๋ก 3ํ ์ง์ ๋ฐฑ์คํ+jitter๋ก ๋ฆฌํธ๋ผ์ดํ๊ณ ๊ทธ๋๋ ์คํจ์ ์ฌ๋์ ๋ก๊ทธ ๋จ๊ธฐ๊ธฐ
- ์ฌํ๋ฉด ๋น๊ด๋ฝ ๋๋ ๊ฐ row ์์ ์ ๋ฐ์ดํธ ์น๊ณ ํต๊ณ ํ ์ด๋ธ ๋ฐ๋ก ๋ง๋๋ ๋ฑ๋ฑ๋ฑ ๋ค๋ฅธ ์ ๋ต ๊ณ ๋ ค
-
๋ณํ ๊ฐ์ง ํ๋ก์ธ์ค
- HTML ์ค๋ ์ท ์์ฑ โ ์ด์ ์ค๋ ์ท๊ณผ diff
- ๋ณํ ์์ผ๋ฉด ์ข ๋ฃ
- ๋ณํ ์์ผ๋ฉด ์์๋๋ก ์คํ
- ๋ณํ ์ /ํ ์คํฌ๋ฆฐ์ท ์ดฌ์
- OpenCV๋ก ๋ณํ ์์ญ ๋นจ๊ฐ ๋ค๋ชจ ๊ฐ์กฐ
- ํ ํฐ์ ์๋ผ๊ธฐ์ํด ์ด์ html ๊ณผ ์ ๊ท html ๊ฐ์ diff ๋ฅผ ์์ฑํ๊ณ llm ์ ์ ๋ฌ
- ์๋ฆผ ์ ์ก
- ์์ฒญํ 1๋ถ์ด๋ด ์๋ต ์์์ ์คํจ๋ก ๊ฐ์ฃผํ๊ณ ์ง์ ๋ฐฑ์คํ๋ก 3๋ฒ๊น์ง ์ฌ์๋(์ ๊ทผํ ์ ์๋ ์ฌ์ดํธ๋ ์ฌ์ ์ ๊ฑธ๋ฌ์ง๋ฏ๋ก ์ฌ๊ธฐ์ ์ผ์์ ์ธ ๋คํธ์ํฌ/์๋ฒ ์ค๋ฅ์ผ ๊ฐ๋ฅ์ฑ)
- ๋ชจ๋ ์์ฒญ ์คํจํ๋ฉด ์ฌ์ดํธ์ ๋ฌธ์ ๊ฐ ์๊ฒผ๋ค๋ ์๋๋ณด๋ธ๋ค ๊ฐ์ง ์ ์ง ์ฒ๋ฆฌํจ
-
์๋ฆผ
- ์๋ฆผ ์ ์ก ์คํจ ์ ๋ฐฑ์คํ+jitter(ํญ์ฃผ ๋ฐฉ์ง)๋ก ์ต๋ 10ํ๊น์ง ์ฌ์๋ํ ๋ด ์ฌ๋์ผ๋ก ์๋ฆผ(๊ธด๊ธ. ์ธ๋ถ์ชฝ ์ฅ์ ์ผ ๊ฐ๋ฅ์ฑ์ด ์์)
-
๊ทธ์ธ
- ๋ชจ๋ ์ํฐํฐ๋ ๋ ผ๋ฆฌ์ญ์ ๋ก ์ฒ๋ฆฌ
- ๋ฌด์ค๋จ ๋ฐฐํฌ(GitHub Action + aws๋ก๋ ๋ฐธ๋ฐ์ ๊ณ ๋ ค)
- graceful shutdown ์ผ๋ก ๋ชจ๋ connection drainํ๊ณ ์ค๋จ
- ์คํค๋ง ์ ๋ฐ์ดํธ๋ฅผ ํ๋๋ผ๋ ์๋, ๊ฒฐ์ ์๋น์ค๋ ๋๊ธฐ๋ฉด ์๋๋ฏ๋ก SQS์ ๋ฃ์ด์ ๊ด๋ฆฌ
- ๋ชจ๋ํฐ๋ง์ด๋ ๋ฐฑ์ ๊ณ ๋ ค