Flow λκΈ°μ΄ μμ€ν μ μ 체 REST API λ¬Έμ
Base URL: http://localhost:9010
μ¬μ©μλ₯Ό λκΈ°μ΄μ λ±λ‘νκ³ νμ¬ μμλ₯Ό λ°νν©λλ€.
Endpoint
POST /api/v1/queue
Query Parameters
| νλΌλ―Έν° | νμ | νμ | κΈ°λ³Έκ° | μ€λͺ |
|---|---|---|---|---|
queue |
String | β | "default" | ν μ΄λ¦ (λ©ν° ν μ§μ) |
user_id |
Long | β | - | μ¬μ©μ ID (μμ) |
is_vip |
Boolean | β | false | VIP μ¬λΆ (trueλ©΄ μ°μ μμ) |
Request Example
# μΌλ° μ¬μ©μ λ±λ‘
curl -X POST "http://localhost:9010/api/v1/queue?user_id=100&queue=default"
# VIP μ¬μ©μ λ±λ‘
curl -X POST "http://localhost:9010/api/v1/queue?user_id=101&queue=default&is_vip=true"Response (200 OK)
{
"rank": 1
}Error Response (400 Bad Request)
{
"code": "UQ-001",
"reason": "μ΄λ―Έ λ±λ‘λ μ¬μ©μμ
λλ€."
}{
"code": "UQ-005",
"reason": "λκΈ°μ΄μ΄ κ°λ μ°Όμ΅λλ€. μ΅λ μ©λ: 100λͺ
"
}μ€λͺ
- λ±λ‘ μ±κ³΅ μ νμ¬ μμλ₯Ό μ¦μ λ°ν
- VIP μ¬μ©μλ μΌλ° μ¬μ©μλ³΄λ€ νμ μ μμ
- λμΌ λ±κΈ λ΄μμλ μ μ°©μ (νμμ€ν¬ν κΈ°μ€)
- μ€λ³΅ λ±λ‘ μ μλ¬ λ°ν
λκΈ°μ΄μμ Nλͺ μ μ¬μ©μλ₯Ό μ§μ νμ© μνλ‘ λ³κ²½ν©λλ€.
Endpoint
POST /api/v1/queue/allow
Query Parameters
| νλΌλ―Έν° | νμ | νμ | κΈ°λ³Έκ° | μ€λͺ |
|---|---|---|---|---|
queue |
String | β | "default" | ν μ΄λ¦ |
count |
Long | β | - | μ§μ νμ©ν μ¬μ©μ μ |
Request Example
# 10λͺ
μ§μ
νμ©
curl -X POST "http://localhost:9010/api/v1/queue/allow?queue=default&count=10"Response (200 OK)
{
"requestCount": 10,
"allowedCount": 10
}μ€λͺ
- λκΈ°μ΄ μμμλΆν° μμλλ‘ μ§μ νμ©
- μ§μ
νμ©λ μ¬μ©μλ
proceedνλ‘ μ΄λ requestCountμallowedCountκ° λ€λ₯Ό μ μμ (λκΈ°μκ° λΆμ‘±ν κ²½μ°)
μ¬μ©μμ νμ¬ λκΈ° μμλ₯Ό μ‘°νν©λλ€.
Endpoint
GET /api/v1/queue/rank
Query Parameters
| νλΌλ―Έν° | νμ | νμ | κΈ°λ³Έκ° | μ€λͺ |
|---|---|---|---|---|
queue |
String | β | "default" | ν μ΄λ¦ |
user_id |
Long | β | - | μ¬μ©μ ID |
Request Example
curl "http://localhost:9010/api/v1/queue/rank?user_id=100&queue=default"Response (200 OK)
{
"rank": 5
}μ€λͺ
rankκ°μ΄-1μ΄λ©΄ λκΈ°μ΄μ μλ μ¬μ©μ- μμλ 1λΆν° μμ (1 = κ°μ₯ μ)
μ¬μ©μκ° μ§μ νμ©λμλμ§ νμΈν©λλ€.
Endpoint
GET /api/v1/queue/allowed
Query Parameters
| νλΌλ―Έν° | νμ | νμ | κΈ°λ³Έκ° | μ€λͺ |
|---|---|---|---|---|
queue |
String | β | "default" | ν μ΄λ¦ |
user_id |
Long | β | - | μ¬μ©μ ID |
Request Example
curl "http://localhost:9010/api/v1/queue/allowed?user_id=100&queue=default"Response (200 OK)
{
"allowed": true
}{
"allowed": false
}μ€λͺ
allowed: true: μ§μ νμ©λ¨, μλΉμ€ μ΄μ© κ°λ₯allowed: false: μμ§ λκΈ° μ€
μ¬μ©μμ μ§μ ν ν°μ μμ±νκ³ μΏ ν€μ μ μ₯ν©λλ€.
Endpoint
GET /api/v1/queue/touch
Query Parameters
| νλΌλ―Έν° | νμ | νμ | κΈ°λ³Έκ° | μ€λͺ |
|---|---|---|---|---|
queue |
String | β | "default" | ν μ΄λ¦ |
user_id |
Long | β | - | μ¬μ©μ ID |
Request Example
curl "http://localhost:9010/api/v1/queue/touch?user_id=100&queue=default"Response (200 OK)
a3b5c7d9e1f2a4b6c8d0e2f4a6b8c0d2e4f6a8b0c2d4e6f8a0b2c4d6e8f0a2b4c6
Response Headers
Set-Cookie: user-queue-default-token=a3b5c7d9...; Max-Age=300; Path=/
μ€λͺ
- SHA-256 ν΄μ κΈ°λ° ν ν° μμ±
- μΏ ν€λ‘ μλ μ μ₯ (μ ν¨ μκ°: 300μ΄)
- μ§μ μ ν ν° κ²μ¦μ μ¬μ©
λκΈ° μ€μΈ μ¬μ©μ μμ μ§μ νμ©λ μ¬μ©μ μλ₯Ό μ‘°νν©λλ€.
Endpoint
GET /api/v1/queue/statistics
Query Parameters
| νλΌλ―Έν° | νμ | νμ | κΈ°λ³Έκ° | μ€λͺ |
|---|---|---|---|---|
queue |
String | β | "default" | ν μ΄λ¦ |
Request Example
curl "http://localhost:9010/api/v1/queue/statistics?queue=default"Response (200 OK)
{
"queue": "default",
"waitingCount": 150,
"allowedCount": 50
}μ€λͺ
waitingCount: νμ¬ λκΈ° μ€μΈ μ¬μ©μ μallowedCount: μ§μ νμ©λ μ¬μ©μ μ- μ€μκ° ν΅κ³ μ 곡
νΉμ μ¬μ©μμ λκΈ°μ΄ μ΄λ ₯μ μ‘°νν©λλ€.
Endpoint
GET /api/v1/queue/history
Query Parameters
| νλΌλ―Έν° | νμ | νμ | κΈ°λ³Έκ° | μ€λͺ |
|---|---|---|---|---|
queue |
String | β | "default" | ν μ΄λ¦ |
user_id |
Long | β | - | μ¬μ©μ ID |
count |
Integer | β | 10 | μ‘°νν μ΄λ ₯ κ°μ |
Request Example
curl "http://localhost:9010/api/v1/queue/history?user_id=100&queue=default&count=5"Response (200 OK)
[
{
"queue": "default",
"userId": 100,
"action": "ALLOW",
"timestamp": 1730000016
},
{
"queue": "default",
"userId": 100,
"action": "REGISTER",
"timestamp": 1730000000
}
]μ€λͺ
- μ΅μ μ΄λ ₯λΆν° λ°ν (μκ° μμ)
action: REGISTER (λ±λ‘), ALLOW (μ§μ νμ©)timestamp: Unix timestamp (μ΄ λ¨μ)
νμ μ 체 μ΄λ ₯μ μ‘°νν©λλ€ (κ΄λ¦¬μμ©).
Endpoint
GET /api/v1/queue/history/all
Query Parameters
| νλΌλ―Έν° | νμ | νμ | κΈ°λ³Έκ° | μ€λͺ |
|---|---|---|---|---|
queue |
String | β | "default" | ν μ΄λ¦ |
count |
Integer | β | 50 | μ‘°νν μ΄λ ₯ κ°μ |
Request Example
curl "http://localhost:9010/api/v1/queue/history/all?queue=default&count=20"Response (200 OK)
[
{
"queue": "default",
"userId": 102,
"action": "ALLOW",
"timestamp": 1730000020
},
{
"queue": "default",
"userId": 101,
"action": "ALLOW",
"timestamp": 1730000016
},
{
"queue": "default",
"userId": 100,
"action": "REGISTER",
"timestamp": 1730000000
}
]μ€λͺ
- λͺ¨λ μ¬μ©μμ μ΄λ ₯ ν¬ν¨
- μ΅μ μ΄λ ₯λΆν° λ°ν
- κ°μ¬ λ° λͺ¨λν°λ§ λͺ©μ
μ¬μ©μ μΉνμ μΈ λκΈ°μ€ UIλ₯Ό μ 곡ν©λλ€.
Endpoint
GET /waiting-room
Query Parameters
| νλΌλ―Έν° | νμ | νμ | κΈ°λ³Έκ° | μ€λͺ |
|---|---|---|---|---|
queue |
String | β | "default" | ν μ΄λ¦ |
user_id |
Long | β | - | μ¬μ©μ ID |
Request Example
http://localhost:9010/waiting-room?queue=default&user_id=100
Response
- HTML νμ΄μ§ (Thymeleaf ν νλ¦Ώ)
- μ€μκ° μμ μ λ°μ΄νΈ (ν΄λ§ λ°©μ)
- μ§μ νμ© μ μλ 리λ€μ΄λ νΈ
UI κΈ°λ₯
- νμ¬ μμ νμ
- λκΈ° μ€μΈ μ¬μ©μ μ
- μμ λκΈ° μκ° (κ³μ°)
- μλ μλ‘κ³ μΉ¨
| μν μ½λ | μ€λͺ |
|---|---|
200 OK |
μμ² μ±κ³΅ |
400 Bad Request |
μλͺ»λ μμ² (κ²μ¦ μ€ν¨, μ€λ³΅ λ±λ‘) |
404 Not Found |
리μμ€λ₯Ό μ°Ύμ μ μμ |
500 Internal Server Error |
μλ² λ΄λΆ μ€λ₯ |
| μ½λ | HTTP μν | μ€λͺ | μμΈ |
|---|---|---|---|
UQ-001 |
400 | μ΄λ―Έ λ±λ‘λ μ¬μ©μμ λλ€. | μ€λ³΅ λ±λ‘ μλ |
UQ-002 |
400 | μ ν¨νμ§ μμ μ¬μ©μ IDμ λλ€. userIdλ μμμ¬μΌ ν©λλ€. | userIdκ° nullμ΄κ±°λ 0 μ΄ν |
UQ-003 |
400 | μ ν¨νμ§ μμ ν μ΄λ¦μ λλ€. ν μ΄λ¦μ λΉμ΄μμ μ μμ΅λλ€. | queueκ° nullμ΄κ±°λ λΉ λ¬Έμμ΄ |
UQ-004 |
400 | μ ν¨νμ§ μμ count κ°μ λλ€. countλ 0 μ΄μμ΄μ΄μΌ ν©λλ€. | countκ° nullμ΄κ±°λ μμ |
UQ-005 |
400 | λκΈ°μ΄μ΄ κ°λ μ°Όμ΅λλ€. μ΅λ μ©λ: Nλͺ | λκΈ°μ΄ μ©λ μ΄κ³Ό |
Example
{
"code": "UQ-001",
"reason": "μ΄λ―Έ λ±λ‘λ μ¬μ©μμ
λλ€."
}- μΈμ¦ μμ (κ°λ°/ν μ€νΈ λ¨κ³)
user_idλ₯Ό 쿼리 νλΌλ―Έν°λ‘ μ λ¬
1. JWT κΈ°λ° μΈμ¦
- Authorization: Bearer {token}
- ν ν°μ userId ν¬ν¨
2. API Key μΈμ¦ (κ΄λ¦¬μ API)
- X-API-Key: {key}
- /api/v1/queue/allow λ± κ΄λ¦¬μ API 보νΈ
3. Rate Limiting
- μ¬μ©μλΉ λΆλΉ μμ² μ μ ν
- IP κΈ°λ° μ ν
# 1. λκΈ°μ΄ λ±λ‘
curl -X POST "http://localhost:9010/api/v1/queue?user_id=100"
# β {"rank": 10}
# 2. μμ μ£ΌκΈ°μ μ‘°ν (ν΄λ§)
curl "http://localhost:9010/api/v1/queue/rank?user_id=100"
# β {"rank": 7}
# 3. μ§μ
νμ© μ¬λΆ νμΈ
curl "http://localhost:9010/api/v1/queue/allowed?user_id=100"
# β {"allowed": false}
# ... λκΈ° ...
# 4. μ§μ
νμ© νμΈ
curl "http://localhost:9010/api/v1/queue/allowed?user_id=100"
# β {"allowed": true}
# 5. ν ν° μμ±
curl "http://localhost:9010/api/v1/queue/touch?user_id=100"
# β ν ν° λ°ν + μΏ ν€ μ€μ
# 6. μλΉμ€ μ΄μ©
# (λ©μΈ μλΉμ€λ‘ 리λ€μ΄λ νΈ, ν ν° κ²μ¦)# 1. VIPλ‘ λ±λ‘
curl -X POST "http://localhost:9010/api/v1/queue?user_id=200&is_vip=true"
# β {"rank": 1} (μΌλ° μ¬μ©μλ³΄λ€ μ°μ μμ)
# 2. λΉ λ₯Έ μ§μ
# VIPλ μΌλ° μ¬μ©μλ³΄λ€ λ¨Όμ μ§μ
νμ©λ¨# 1. νμ¬ ν΅κ³ νμΈ
curl "http://localhost:9010/api/v1/queue/statistics"
# β {"queue": "default", "waitingCount": 150, "allowedCount": 50}
# 2. 20λͺ
μ§μ
νμ©
curl -X POST "http://localhost:9010/api/v1/queue/allow?count=20"
# β {"requestCount": 20, "allowedCount": 20}
# 3. μ 체 μ΄λ ₯ νμΈ
curl "http://localhost:9010/api/v1/queue/history/all?count=50"
# β [...]νλ‘λμ νκ²½μμλ λ€μκ³Ό κ°μ μ νμ κΆμ₯ν©λλ€:
| API | μ ν |
|---|---|
| POST /api/v1/queue | μ¬μ©μλΉ 1λΆμ 1ν |
| GET /api/v1/queue/rank | μ¬μ©μλΉ 1λΆμ 10ν |
| GET /api/v1/queue/allowed | μ¬μ©μλΉ 1λΆμ 10ν |
| POST /api/v1/queue/allow | κ΄λ¦¬μλ§, 1λΆμ 10ν |
# application.yml
spring:
webflux:
cors:
allowed-origins: "*"
allowed-methods: GET,POST
allowed-headers: "*"νμ¬ λ²μ : v1
ν₯ν λ²μ κ΄λ¦¬:
/api/v1/queue # νμ¬ λ²μ
/api/v2/queue # λ―Έλ λ²μ (νμ νΈν κΉ¨μ§ λ)
νλ‘μ νΈμ ν¬ν¨λ Postman Collectionμ μ¬μ©νμ¬ μ½κ² ν μ€νΈν μ μμ΅λλ€.
docs/postman/Flow-API.postman_collection.json
# test-api.sh
#!/bin/bash
BASE_URL="http://localhost:9010"
echo "1. λκΈ°μ΄ λ±λ‘"
curl -X POST "$BASE_URL/api/v1/queue?user_id=100"
echo "\n2. μμ μ‘°ν"
curl "$BASE_URL/api/v1/queue/rank?user_id=100"
echo "\n3. ν΅κ³ μ‘°ν"
curl "$BASE_URL/api/v1/queue/statistics"π READMEλ‘ λμκ°κΈ° | π ν¬νΈν΄λ¦¬μ€ | ποΈ μν€ν μ²
API κ΄λ ¨ λ¬Έμμ¬νμ μ΄μλ‘ λ±λ‘ν΄μ£ΌμΈμ.