์๊ฒฉ ์ ์ฅ์์ ํ์ผ์ ์ ๋ก๋/๋ค์ด๋ก๋ํ๊ณ ์ฌ๋ฌ ๊ธฐ๊ธฐ ๊ฐ ์๋ ๋๊ธฐํํ๋ ํด๋ผ์ฐ๋ ์คํ ๋ฆฌ์ง ์๋น์ค
ํ์ผ ์ ๋ก๋
ํ์ผ ๋ค์ด๋ก๋
ํ์ผ ๊ณต์
์๋ ๋๊ธฐํ
๊ฐ์
๊ณ์ฐ
์ด request = 10^8 ร 10 = 10^9 request/์ผ
๋ค์ด๋ก๋ TPS = (10^9 ร 0.75~0.8) / 10^5 = 7,500~8,000 TPS
์
๋ก๋ TPS = (10^9 ร 0.25~0.2) / 10^5 = 2,000~2,500 TPS
๋ถ์ฐ ์ฒ๋ฆฌ
CAP ์ ๋ฆฌ
๋ค์ด๋ก๋/์ ๋ก๋ ์๊ฐ
๋คํธ์ํฌ ์ฅ์ ์ฒ๋ฆฌ
ํ์ผ ๋๊ธฐํ
| ํญ๋ชฉ | ๊ฐ |
|---|---|
| ๋ค์ด๋ก๋ TPS | 7,500~8,000 TPS |
| ์ ๋ก๋ TPS | 2,000~2,500 TPS |
| ์ต๋ ํ์ผ ํฌ๊ธฐ | 50GB |
| CAP ์ฐ์ ์์ | AP (Availability) |
| ์ผ๊ด์ฑ ๋ชจ๋ธ | Eventual Consistency |
ํต์ฌ ๊ธฐ์ ์ ๊ณผ์
S3, Azure Storage, ..)block ๋จ์์ ๊ฐ์ง, ๋ค์ด๋ก๋, ์
๋ก๋ ๊ธฐ๋ฅ ์ ๊ณตTable: file_metadata
| Column | Type | Description | Constraints |
|---|---|---|---|
| id | BIGINT | Primary key | NOT NULL, PRIMARY KEY |
| file_name | TEXT | ํ์ผ ์ด๋ฆ | NOT NULL |
| file_type | VARCHAR | ํ์ผ ํ์ (ํ์ฅ์) | NOT NULL |
| file_key | TEXT | ์ธ๋ถ ์คํ ๋ฆฌ์ง ๊ฒฝ๋ก/ํค | NOT NULL, UNIQUE |
| file_size | BIGINT | ํ์ผ ํฌ๊ธฐ (bytes) | NOT NULL |
| user_id | BIGINT | ์์ ์ ID | NOT NULL, FOREIGN KEY |
| created_at | TIMESTAMP | ์์ฑ ์๊ฐ | NOT NULL |
| updated_at | TIMESTAMP | ์ต์ข ์์ ์๊ฐ | NOT NULL |
Table: chunks
| Column | Type | Description | Constraints |
|---|---|---|---|
| id | BIGINT | Primary key | NOT NULL, PRIMARY KEY |
| file_id | BIGINT | ํ์ผ ID | NOT NULL |
| hash_value | TEXT | ํ์ผ hash ๊ฐ | NOT NULL |
| created_at | TIMESTAMP | ์์ฑ ์๊ฐ | NOT NULL |
| updated_at | TIMESTAMP | ์ต์ข ์์ ์๊ฐ | NOT NULL |
Table: users
| Column | Type | Description | Constraints |
|---|---|---|---|
| id | BIGINT | Primary key | NOT NULL, PRIMARY KEY |
| name | VARCHAR(255) | ์ฌ์ฉ์ ์ด๋ฆ | NOT NULL |
| VARCHAR(255) | ์ด๋ฉ์ผ | NOT NULL, UNIQUE | |
| hashed_password | VARCHAR(255) | ์ํธํ๋ ๋น๋ฐ๋ฒํธ | NOT NULL |
| created_at | TIMESTAMP | ๊ณ์ ์์ฑ ์๊ฐ | NOT NULL |
| updated_at | TIMESTAMP | ์ต์ข ์์ ์๊ฐ | NOT NULL |
๋ฑ๋ฑ ํ์์ ๋ฐ๋ผ ๋ ์ฌ๋ฌ๊ฐ์ ๋๋ฉ์ธ์ด ์ฌ์ฉ๋ ์ ์์ผ๋ฉฐ, RDBMS๊ฐ ์๋๋ผ MongoDB ๋ฑ์ NoSQL ์ฌ์ฉ๋ ๊ฐ๋ฅ
GET /api/v1/files/{fileId}
Response
200 OK
{
"presigned_url": "https://s3.amazonaws.com/bucket/file.pdf?X-Amz-Signature=...",
"file_name": "presentation.pdf",
"file_size": 5242880,
"expires_in": 3600
}
์ค๋ช
POST /api/v1/files
Request
{
"file_name": "presentation.pdf",
"file_type": "pdf",
"file_size": 5242880
}
Response
201 Created
{
"file_id": 1000001,
"presigned_url": "https://s3.amazonaws.com/bucket/upload?X-Amz-Signature=...",
"expires_in": 3600
}
์ค๋ช
Endpoint
POST /api/files/{fileId}/share
Request
{
"user_ids": [1, 32, 22],
"permission": "read" // "read" or "write"
}
Response
201 Created
{
"file_id": 1000001,
"shared_with": [
{
"user_id": 1,
"email": "user1@example.com",
"permission": "read",
"shared_at": "2025-01-09T15:30:00Z"
},
{
"user_id": 32,
"email": "user32@example.com",
"permission": "read",
"shared_at": "2025-01-09T15:30:00Z"
},
{
"user_id": 22,
"email": "user22@example.com",
"permission": "read",
"shared_at": "2025-01-09T15:30:00Z"
}
],
"share_url": "https://app.dropbox.com/s/abc123/presentation.pdf"
}
์ค๋ช
N:N์ ๊ด๊ณ๋ฅผ ๊ฐ์ง๋ ์๋ก์ด table shared_files ๋์
๊ฐ๋ฅEndpoint
GET /api/v1/sync/connect/{userId}
Response
200 OK
Content-Type: text/event-stream
data: {"event": "file_updated", "file_id": 1000001, "updated_at": "2025-01-09T14:20:00Z"}
data: {"event": "file_deleted", "file_id": 1000002}
data: {"event": "file_created", "file_id": 1000003, "file_name": "new_document.pdf"}
์ค๋ช
| Method | Endpoint | Description | ์ธ์ฆ ํ์ |
|---|---|---|---|
| GET | /api/v1/files/{fileId} | ํ์ผ ๋ค์ด๋ก๋ URL ์์ฑ | โ |
| POST | /api/v1/files | ํ์ผ ์ ๋ก๋ URL ์์ฑ | โ |
| GET | /api/v1/sync/connect/{userId} | ์ค์๊ฐ ๋๊ธฐํ ์ฐ๊ฒฐ | โ |
์ธ๋ถ ๊ฐ์ฒด ์คํ ๋ฆฌ์ง ํ์ฉ
์ฒญํฌ ๊ธฐ๋ฐ ์ฒ๋ฆฌ
๋ฑ์ ๊ณ ๋ คํ๊ณ ๋ ์ด๋ฏธ ์ ์ค๊ณ ๋ CDN, S3 ๊ฐ์ ์๋น์ค๋ค์ ์๋ง๊ฒ ์ฌ์ฉํ๋ฉด ๋๋ถ๋ถ์ ์๊ตฌ๋์๋ TPS ์ฒ๋ฆฌ๋ฅผ ์๋์ ๊ฐ์ด Third Party Service ์ ์์ํ ์ ์์ต๋๋ค:

๊ทธ๋ฆฌ๊ณ ์ถ๊ฐ๋ก ๋ก์ปฌํ๊ฒฝ์์์ ๋ณํ๋ฅผ ๊ฐ์งํ์ฌ ํด๋ผ์ฐ๋ํ๊ฒฝ ๋ฐ์ํ๊ฑฐ๋ ๋ฐ๋๋ก ํด๋ผ์ฐ๋ํ๊ฒฝ์์์ ๋ณํ๋ฅผ ๋ก์ปฌ์ ๋ฐ์ํ์ฌ์ผ ํ๋ค๋ฉด ๋ช๊ฐ์ง ์ปดํฌ๋ํธ๋ค์ด ๋ ์ถ๊ฐ ๋ ์ ์์ต๋๋ค:

๋์ฉ๋ ํ์ผ ์
๋ก๋์ ์ฌ๊ฐ์ ํจ์จ์ ์ธ ๋ณ๊ฒฝ ๊ฐ์ง๋ก ๋ฐ์ํ ์
๋ก๋, ๋ค์ด๋ก๋๋ฅผ ์ํด์๋ chunk๋ฅผ ํ์ฉํ๋๊ฒ ํต์ฌ
50GB ํ์ผ
โ
ํด๋ผ์ด์ธํธ์์ 5-10MB ์ฒญํฌ๋ก ๋ถํ
โ
๊ฐ ์ฒญํฌ๋ง๋ค SHA-256 ์ง๋ฌธ ์์ฑ
โ
์ ์ฒด ํ์ผ ์ง๋ฌธ ์์ฑ (fileId)
โ
๋ณ๋ ฌ ์
๋ก๋ ์์
โ ์๋ฒ ์ฒญํน: ์ ์ฒด ํ์ผ์ ์ผ๋จ ์๋ฒ๋ก ์ ์ก (์๋ฏธ ์์)
โ
ํด๋ผ์ด์ธํธ ์ฒญํน: ์์ ์กฐ๊ฐ์ผ๋ก ๋๋ ์ ์ ์ก ์์
โ
์งํ๋ฅ ํ์ ๊ฐ๋ฅ (3/10 ์ฒญํฌ ์๋ฃ)
โ
๋คํธ์ํฌ ๋๊น ์ ์ด์ด๋ฐ๊ธฐ
โ
API Gateway 10MB ์ ํ ์ฐํ
โ
๋ณ๋ ฌ ์
๋ก๋๋ก ์๋ ํฅ์
โ
ํ์ผ ๋ณ๊ฒฝ ์ ๋ณ๊ฒฝ๋ ์ฒญํฌ๋ง ์ฌ์
๋ก๋ (๋ธํ ๋๊ธฐํ)
1. ํด๋ผ์ด์ธํธ: ํ์ผ ์ง๋ฌธ ๊ณ์ฐ
โ
2. GET /files/{fileId} โ ์ด๋ฏธ ์
๋ก๋ ์ค์ธ์ง ํ์ธ
โ (์์ผ๋ฉด)
3. POST /files โ S3 Multipart Upload ์์
โ
4. ๊ฐ ์ฒญํฌ ์
๋ก๋ to S3 Presigned URL
โ
5. PATCH /files/{fileId}/chunks โ ETag + ์ํ ์
๋ฐ์ดํธ
โ
6. ์๋ฒ์์๋ S3 ListParts API์ ETag๋ก ์ํธ๊ฒ์ฆ
โ
7. ๋ชจ๋ ์ฒญํฌ ์๋ฃ โ CompleteMultipartUpload
ํด๋ผ์ด์ธํธ ์ธก
โโ ์ฒญํฌ ์
๋ก๋ ์ฆ์ PATCH ์์ฒญ
โโ ๋น ๋ฅธ UI ์
๋ฐ์ดํธ (์งํ๋ฅ ํ์)
โโ ์ฌ์ฉ์ ๊ฒฝํ ํฅ์
์๋ฒ ์ธก
โโ ์ฒญํฌ ์
๋ก๋ ํ์ธ ์์ฒญ์ S3 ListParts API ํธ์ถ
โโ ETag ๋น๊ต๋ก ์ค์ ์ํ ํ์ธ
โโ ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๋ณด์ฅ
{
"fileId": "sha256-hash",
"name": "video.mp4",
"size": 50000000000,
"uploadedBy": "user123",
"status": "uploading",
"uploadId": "s3-multipart-id",
"chunks": [
{"id": "chunk-1", "etag": "abc123", "status": "uploaded"},
{"id": "chunk-2", "etag": "def456", "status": "uploaded"},
{"id": "chunk-3", "etag": null, "status": "pending"}
]
}
์์ถ ๊ณ ๋ ค
โ
์์ถ์๊ฐ + ์์ถํ Network IO
vs
์๋ณธ Network IO
โ
๋น ๋ฅธ ์ชฝ ์ ํ
โ
ํ
์คํธ (.txt, .log, .json): 5GB โ 1GB (80% ๊ฐ์)
โ
CSV, XML: ์์ถ๋ฅ ๋์
โ
์ฝ๋ ํ์ผ (.js, .py, .java)
โ
JSON/XML API ์๋ต
โ ์ด๋ฏธ์ง (.jpg, .png): ์ด๋ฏธ ์์ถ๋จ
โ ๋น๋์ค (.mp4, .mov): ํจ๊ณผ ๊ฑฐ์ ์์
โ ์์ถ ํ์ผ (.zip, .gz): ์ด๋ฏธ ์์ถ๋จ
โ ์ํธํ๋ ํ์ผ: ์์ถ ํจ๊ณผ ์์
์ฌ๋ฐ๋ฅธ ์์
์์ถ โ ์ํธํ โ
(์์ถ๋ฅ ์ต๋ํ)
์๋ชป๋ ์์
์ํธํ โ ์์ถ โ
(๋๋ค ๋ฐ์ดํฐ๋ ์์ถ ๋ถ๊ฐ)
์์ฃผ ์ฌ์ฉ๋๋ ํ์ผ (์์ 20%)
โ
WebSocket ์ค์๊ฐ ์ฐ๊ฒฐ ์ ์ง
โ
๋ณ๊ฒฝ ์ฆ์ ํธ์
โ
ํ์
๊ฒฝํ ํฅ์
๊ฐ๋ ์ฌ์ฉ๋๋ ํ์ผ (๋๋จธ์ง 80%)
โ
Polling (30์ด๋ง๋ค ํ์ธ)
โ
๋ฆฌ์์ค ์ ์ฝ
โ
๋น์ฉ ์ต์ ํ
ํ์ผ ์ ๊ทผ ํจํด
โโ ์ต๊ทผ 7์ผ๊ฐ ์ ๊ทผ ํ์
โโ ๋ง์ง๋ง ์ ๊ทผ ์๊ฐ
โโ ์ ๊ทผ ๋น๋ (์ผ ๋จ์)
ํ์
์งํ
โโ ๋์ ํธ์ง์ ์
โโ ๊ณต์ ๋ฒ์ (๊ฐ์ธ/ํ/์ ์ฌ)
โโ ๋๊ธ/์์ ํ๋
ํ์ผ ํน์ฑ
โโ ํ์ผ ํ์
(๋ฌธ์ > ๋ฏธ๋์ด > ์์นด์ด๋ธ)
โโ ํ์ผ ํฌ๊ธฐ (์์ ํ์ผ ์ฐ์ )
โโ ํธ์ง ๊ฐ๋ฅ ์ฌ๋ถ
๋ฑ๋ฑ
Hot โ Cold ์ ํ
โโ 7์ผ๊ฐ ์ ๊ทผ ์์
โโ ํ์
์ ๋ชจ๋ ์คํ๋ผ์ธ
โโ ์ฝ๊ธฐ ์ ์ฉ ๋ชจ๋
Cold โ Hot ์ ํ
โโ ํธ์ง ์์
โโ ์ ํ์
์ ์ฐธ์ฌ
โโ 3ํ ์ด์ ์ฐ์ ์ ๊ทผ
Hot Files (20%)
โโ WebSocket: 10,000 ๋์ ์ฐ๊ฒฐ
โโ ๋ฉ๋ชจ๋ฆฌ: ํ์ผ ๋ฉํ๋ฐ์ดํฐ ์บ์ฑ
โโ ๋น์ฉ: ๋์
Cold Files (80%)
โโ HTTP Polling: ํ์์์๋ง
โโ ๋ฉ๋ชจ๋ฆฌ: ๋์คํฌ ๊ธฐ๋ฐ ์กฐํ
โโ ๋น์ฉ: ๋ฎ์
๋ฑ ๊ณ ๋ ค ๊ฐ๋ฅ