Skip to content

๐Ÿง‘โ€๐Ÿ’ป ์‚ฌ์šฉ์ž ๊ฐ€์ด๋“œ

์ด ๊ฐ€์ด๋“œ๋Š” ์นตํ…Œ์ผ ์ฃผ๋ฅ˜ ์ •๋ณด API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๊ธฐ๋ณธ์ ์ธ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  API์˜ ๊ธฐ๋ณธ URL์€ /api/v1 ์ž…๋‹ˆ๋‹ค.

๐Ÿ”‘ ์ธ์ฆ (Authentication)

๋ฐ์ดํ„ฐ ๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œ ๋“ฑ ๋ณดํ˜ธ๋œ ์—”๋“œํฌ์ธํŠธ์— ์ ‘๊ทผํ•˜๋ ค๋ฉด ์ธ์ฆ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. JWT ๊ธฐ๋ฐ˜ ์ฟ ํ‚ค ์ธ์ฆ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

ํšŒ์›๊ฐ€์ž…

์ƒˆ ๊ณ„์ •์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: POST /api/v1/signup
  • Content-Type: application/json
{
  "userId": "your_user_id",
  "password": "your_password"
}

์‘๋‹ต: ํšŒ์›๊ฐ€์ž… ์„ฑ๊ณต ์‹œ ์ž๋™์œผ๋กœ ๋กœ๊ทธ์ธ๋˜๋ฉฐ, ์ธ์ฆ ์ฟ ํ‚ค๊ฐ€ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ

๊ธฐ์กด ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: POST /api/v1/signin
  • Content-Type: application/json
{
  "userId": "your_user_id", 
  "password": "your_password"
}

์‘๋‹ต: ๋กœ๊ทธ์ธ ์„ฑ๊ณต ์‹œ accessToken๊ณผ refreshToken ์ฟ ํ‚ค๊ฐ€ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

ํ† ํฐ ๊ฐฑ์‹ 

์•ก์„ธ์Šค ํ† ํฐ์ด ๋งŒ๋ฃŒ๋˜๋ฉด ์ž๋™์œผ๋กœ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Endpoint: POST /api/v1/refresh-token

์ฟ ํ‚ค์˜ refreshToken์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋™์œผ๋กœ ์ƒˆ๋กœ์šด accessToken์„ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ๊ถŒํ•œ ํ™•์ธ

ํ˜„์žฌ ๋กœ๊ทธ์ธ๋œ ์‚ฌ์šฉ์ž์˜ ๊ถŒํ•œ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: GET /api/v1/my-role
  • ์ธ์ฆ: ํ•„์š”

๐Ÿฅƒ ์ฃผ๋ฅ˜ (Spirits)

์ฃผ๋ฅ˜ ๋“ฑ๋ก

์ƒˆ๋กœ์šด ์ฃผ๋ฅ˜ ์ •๋ณด๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: POST /api/v1/spirits
  • Content-Type: multipart/form-data
  • ์ธ์ฆ: ํ•„์š”

ํ•„์ˆ˜ ํ•„๋“œ: - name (string): ์ฃผ๋ฅ˜ ์ด๋ฆ„ - aroma (array): ํ–ฅ ํŠน์„ฑ (๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ฐ’ ์‚ฌ์šฉ) - taste (array): ๋ง› ํŠน์„ฑ (๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ฐ’ ์‚ฌ์šฉ)
- finish (array): ์—ฌ์šด ํŠน์„ฑ (๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๊ฐ’ ์‚ฌ์šฉ) - kind (string): ์ฃผ๋ฅ˜ ์ข…๋ฅ˜ (์˜ˆ: Gin, Whiskey, Rum) - subKind (string): ์„ธ๋ถ€ ์ข…๋ฅ˜ - amount (float): ์šฉ๋Ÿ‰ (mL) - alcohol (float): ์•Œ์ฝ”์˜ฌ ๋„์ˆ˜ (%) - originNation (string): ์›์‚ฐ์ง€ ๊ตญ๊ฐ€ - originLocation (string): ์›์‚ฐ์ง€ ์ง€์—ญ - description (string): ์„ค๋ช… - mainImage (file): ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ (์ตœ๋Œ€ 2MB)

์„ ํƒ ํ•„๋“œ: - subImage1-4 (file): ๋ณด์กฐ ์ด๋ฏธ์ง€๋“ค

curl -X POST "http://localhost:8000/api/v1/spirits" \
  -F "name=Tanqueray London Dry Gin" \
  -F "aroma=juniper" \
  -F "aroma=citrus" \
  -F "taste=dry" \
  -F "taste=botanical" \
  -F "finish=clean" \
  -F "kind=Gin" \
  -F "subKind=London Dry" \
  -F "amount=750" \
  -F "alcohol=47.3" \
  -F "originNation=England" \
  -F "originLocation=London" \
  -F "description=Classic London Dry Gin" \
  -F "mainImage=@tanqueray.jpg"

์ฃผ๋ฅ˜ ๊ฒ€์ƒ‰

๋‹ค์–‘ํ•œ ์กฐ๊ฑด์œผ๋กœ ์ฃผ๋ฅ˜๋ฅผ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: GET /api/v1/spirits

์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ: - name (string): ์ด๋ฆ„์œผ๋กœ ๋ถ€๋ถ„ ๊ฒ€์ƒ‰ - aroma (array): ํ–ฅ ํŠน์„ฑ์œผ๋กœ ์ •ํ™•ํžˆ ์ผ์น˜ - taste (array): ๋ง› ํŠน์„ฑ์œผ๋กœ ์ •ํ™•ํžˆ ์ผ์น˜ - finish (array): ์—ฌ์šด ํŠน์„ฑ์œผ๋กœ ์ •ํ™•ํžˆ ์ผ์น˜ - kind (string): ์ฃผ๋ฅ˜ ์ข…๋ฅ˜๋กœ ์ •ํ™•ํžˆ ์ผ์น˜ - subKind (string): ์„ธ๋ถ€ ์ข…๋ฅ˜๋กœ ์ •ํ™•ํžˆ ์ผ์น˜ - minAlcohol (float): ์ตœ์†Œ ์•Œ์ฝ”์˜ฌ ๋„์ˆ˜ - maxAlcohol (float): ์ตœ๋Œ€ ์•Œ์ฝ”์˜ฌ ๋„์ˆ˜ - originNation (string): ์›์‚ฐ์ง€ ๊ตญ๊ฐ€๋กœ ์ •ํ™•ํžˆ ์ผ์น˜ - originLocation (string): ์›์‚ฐ์ง€ ์ง€์—ญ์œผ๋กœ ๋ถ€๋ถ„ ์ผ์น˜ - pageNumber (int): ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ (๊ธฐ๋ณธ๊ฐ’: 1) - pageSize (int): ํŽ˜์ด์ง€ ํฌ๊ธฐ (๊ธฐ๋ณธ๊ฐ’: 10, ์ตœ๋Œ€: 100)

# ์ง„ ์ข…๋ฅ˜ ๊ฒ€์ƒ‰
curl "http://localhost:8000/api/v1/spirits?kind=Gin&pageNumber=1&pageSize=5"

# ๋“œ๋ผ์ดํ•˜๊ณ  ๊น”๋”ํ•œ ์ฃผ๋ฅ˜ ๊ฒ€์ƒ‰
curl "http://localhost:8000/api/v1/spirits?taste=dry&finish=clean"

# ์•Œ์ฝ”์˜ฌ ๋„์ˆ˜ 40-50% ๋ฒ”์œ„ ๊ฒ€์ƒ‰
curl "http://localhost:8000/api/v1/spirits?minAlcohol=40&maxAlcohol=50"

๋‹จ์ผ ์ฃผ๋ฅ˜ ์กฐํšŒ

ํŠน์ • ์ฃผ๋ฅ˜์˜ ์ƒ์„ธ ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: GET /api/v1/spirits/{name}
curl "http://localhost:8000/api/v1/spirits/Tanqueray%20London%20Dry%20Gin"

์ฃผ๋ฅ˜ ์ˆ˜์ •

๊ธฐ์กด ์ฃผ๋ฅ˜ ์ •๋ณด๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: PUT /api/v1/spirits/{document_id}
  • Content-Type: multipart/form-data
  • ์ธ์ฆ: ํ•„์š”

์ฃผ๋ฅ˜ ์‚ญ์ œ

์ฃผ๋ฅ˜ ์ •๋ณด๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: DELETE /api/v1/spirits/{document_id}
  • ์ธ์ฆ: ํ•„์š”

๐Ÿน ๋ฆฌํ๋ฅด (Liqueur)

๋ฆฌํ๋ฅด ๋“ฑ๋ก

์ƒˆ๋กœ์šด ๋ฆฌํ๋ฅด ์ •๋ณด๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: POST /api/v1/liqueur
  • Content-Type: multipart/form-data
  • ์ธ์ฆ: ํ•„์š”

ํ•„์ˆ˜ ํ•„๋“œ: - name (string): ๋ฆฌํ๋ฅด ์ด๋ฆ„ - brand (string): ๋ธŒ๋žœ๋“œ - taste (array): ๋ง› ํŠน์„ฑ - kind (string): ๋ฆฌํ๋ฅด ์ข…๋ฅ˜ - subKind (string): ์„ธ๋ถ€ ์ข…๋ฅ˜ - mainIngredients (array): ์ฃผ์žฌ๋ฃŒ ๋ชฉ๋ก - volume (float): ์šฉ๋Ÿ‰ (mL) - abv (float): ์•Œ์ฝ”์˜ฌ ๋„์ˆ˜ (%) - originNation (string): ์›์‚ฐ์ง€ ๊ตญ๊ฐ€ - description (string): ์„ค๋ช… - mainImage (file): ๋Œ€ํ‘œ ์ด๋ฏธ์ง€

curl -X POST "http://localhost:8000/api/v1/liqueur" \
  -F "name=Cointreau" \
  -F "brand=Cointreau" \
  -F "taste=sweet" \
  -F "taste=citrus" \
  -F "kind=Triple Sec" \
  -F "subKind=Premium Triple Sec" \
  -F "mainIngredients=orange peel" \
  -F "volume=700" \
  -F "abv=40" \
  -F "originNation=France" \
  -F "description=Premium orange liqueur" \
  -F "mainImage=@cointreau.jpg"

๋ฆฌํ๋ฅด ๊ฒ€์ƒ‰

  • Endpoint: GET /api/v1/liqueur
  • ์ธ์ฆ: ํ•„์š”

์ฃผ์š” ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ: - name, brand, taste, kind, subKind - mainIngredients, minVolume, maxVolume - minAbv, maxAbv, originNation - pageNumber, pageSize

๋‹จ์ผ ๋ฆฌํ๋ฅด ์กฐํšŒ

  • Endpoint: GET /api/v1/liqueur/{name}

๋ฆฌํ๋ฅด ์ˆ˜์ •/์‚ญ์ œ

  • ์ˆ˜์ •: PUT /api/v1/liqueur/{document_id} (์ธ์ฆ ํ•„์š”)
  • ์‚ญ์ œ: DELETE /api/v1/liqueur/{document_id} (์ธ์ฆ ํ•„์š”)

๐ŸŒฟ ๊ธฐํƒ€ ์žฌ๋ฃŒ (Ingredient)

๊ธฐํƒ€ ์žฌ๋ฃŒ ๋“ฑ๋ก

์ฃผ์Šค, ์‹œ๋Ÿฝ ๋“ฑ ๊ธฐํƒ€ ์žฌ๋ฃŒ๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: POST /api/v1/ingredient
  • Content-Type: multipart/form-data
  • ์ธ์ฆ: ํ•„์š”

ํ•„์ˆ˜ ํ•„๋“œ: - name (string): ์žฌ๋ฃŒ ์ด๋ฆ„ - kind (string): ์žฌ๋ฃŒ ์ข…๋ฅ˜ (์˜ˆ: Juice, Syrup, Bitters) - description (string): ์„ค๋ช… - mainImage (file): ๋Œ€ํ‘œ ์ด๋ฏธ์ง€

์„ ํƒ ํ•„๋“œ: - brand (array): ๋ธŒ๋žœ๋“œ ๋ชฉ๋ก

curl -X POST "http://localhost:8000/api/v1/ingredient" \
  -F "name=Simple Syrup" \
  -F "kind=Syrup" \
  -F "description=Basic sugar syrup for cocktails" \
  -F "mainImage=@simple_syrup.jpg"

๊ธฐํƒ€ ์žฌ๋ฃŒ ๊ฒ€์ƒ‰

  • Endpoint: GET /api/v1/ingredient
  • ์ธ์ฆ: ํ•„์š”

์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ: - name, brand, kind, description - pageNumber, pageSize

๋‹จ์ผ ๊ธฐํƒ€ ์žฌ๋ฃŒ ์กฐํšŒ

  • Endpoint: GET /api/v1/ingredient/{name}

๊ธฐํƒ€ ์žฌ๋ฃŒ ์ˆ˜์ •/์‚ญ์ œ

  • ์ˆ˜์ •: PUT /api/v1/ingredient/{document_id} (์ธ์ฆ ํ•„์š”)
  • ์‚ญ์ œ: DELETE /api/v1/ingredient/{document_id} (์ธ์ฆ ํ•„์š”)

โš™๏ธ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ (Metadata)

๋ง›, ํ–ฅ, ์ข…๋ฅ˜ ๋“ฑ ๋ถ„๋ฅ˜์— ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์กฐํšŒ

ํŠน์ • ์ข…๋ฅ˜์™€ ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: GET /api/v1/metadata/{kind}/{category}
  • {kind}: spirits, liqueur, ingredient
  • {category}: taste, aroma, finish, kind
# ์ฃผ๋ฅ˜์˜ ๋ง› ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์กฐํšŒ
curl "http://localhost:8000/api/v1/metadata/spirits/taste"

# ๋ฆฌํ๋ฅด์˜ ํ–ฅ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์กฐํšŒ  
curl "http://localhost:8000/api/v1/metadata/liqueur/aroma"

๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋“ฑ๋ก

์ƒˆ๋กœ์šด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ•ญ๋ชฉ์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: POST /api/v1/metadata/{kind}/{category}
  • Content-Type: application/json
  • ์ธ์ฆ: ๊ด€๋ฆฌ์ž ๊ถŒํ•œ ํ•„์š”
{
  "items": ["sweet", "dry", "fruity", "spicy"]
}

๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์‚ญ์ œ

๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ•ญ๋ชฉ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

  • Endpoint: DELETE /api/v1/metadata/{id}
  • ์ธ์ฆ: ๊ด€๋ฆฌ์ž ๊ถŒํ•œ ํ•„์š”

๐Ÿ“Š ์‘๋‹ต ํ˜•์‹

๋ชจ๋“  API ์‘๋‹ต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ‘œ์ค€ํ™”๋œ ํ˜•์‹์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค:

{
  "status": "success",
  "code": 200,
  "data": {
    // ์‹ค์ œ ๋ฐ์ดํ„ฐ
  },
  "message": "Successfully retrieved data"
}

ํŽ˜์ด์ง€๋„ค์ด์…˜๋œ ์‘๋‹ต:

{
  "status": "success", 
  "code": 200,
  "data": {
    "items": [...],
    "total_count": 150,
    "page_number": 1,
    "page_size": 10,
    "total_pages": 15
  },
  "message": "Successfully search spirits"
}

๐Ÿšจ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ

์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ RFC 9457 Problem Details ํ˜•์‹์œผ๋กœ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค:

{
  "type": "https://httpstatuses.com/400",
  "title": "Client Error 400",
  "detail": "Invalid input data",
  "status": 400
}

๋” ์ž์„ธํ•œ ์—”๋“œํฌ์ธํŠธ ์ •๋ณด์™€ ์ „์ฒด ์š”์ฒญ/์‘๋‹ต ์Šคํ‚ค๋งˆ๋Š” API ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.