Bottle Note Admin API ๋ฌธ์„œ

๋ชฉ์ฐจ

1. ๊ฐœ์š” (overview)

๋กœ๊ทธ์ธ API๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  API๋Š” Authorization ํ—ค๋”์— ์œ ํšจํ•œ ์•ก์„ธ์Šค ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ํ•ด๋‹น ํ”„๋กœ์ ํŠธ API๋ฌธ์„œ๋Š” ๊ฐœ๋ฐœํ™˜๊ฒฝ๊นŒ์ง€ ๋…ธ์ถœ๋˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
์ด API๋ฌธ์„œ๋Š” bottle-note ๊ด€๋ฆฌ์ž ํ”„๋กœ์ ํŠธ์˜ API๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
ํฌํ•จ๋˜๋ฉด ์ข‹์„๊ฒƒ ๊ฐ™์€ ๋‚ด์šฉ์ด๋‚˜ ์ˆ˜์ •์ด ํ•„์š”ํ•œ ๋‚ด์šฉ์€ ์–ธ์ œ๋“ ์ง€ ๋””์Šค์ฝ”๋“œ ์ฑ„๋„์„ ํ†ตํ•ด ์•Œ๋ ค์ฃผ์„ธ์š”.

1.2. ์‘๋‹ตํ˜•์‹

ํ”„๋กœ์ ํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‘๋‹ตํ˜•์‹์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์š”์ฒญ ๊ฒฐ๊ณผ

์š”์ฒญ์ด ์„ฑ๊ณตํ•œ ๊ฒฝ์šฐ ( "success" : true ) ์š”์ฒญ์ด ์‹คํŒจํ•œ ๊ฒฝ์šฐ( "success" : false )
{
  "success" : true,
  "code" : 200,
  "data" : {
    "value1" : "value1",
    "value2" : {
            "value2-1" : "value2-1",
            "value2-2" : "value2-2"
    }
  },
  "errors" : {},
  "meta" : {
    "serverEncoding" : "UTF-8",
    "serverVersion" : "0.0.1",
    "serverPathVersion" : "v1",
    "serverResponseTime" : "2024-04-16T16:22:56.561466"
  }
}
{
  "success" : false,
  "code" : 400,
  "data" : {},
  "errors" : {
    "user_id": "์‚ฌ์šฉ์ž ์•„์ด๋””๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.",
    "user_pw": "์‚ฌ์šฉ์ž ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.",
    "type": "์‚ฌ์šฉ์ž ํƒ€์ž…์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค."
  },
  "meta" : {
    "serverEncoding" : "UTF-8",
    "serverVersion" : "0.0.1",
    "serverPathVersion" : "v1",
    "serverResponseTime" : "2024-04-16T16:22:56.561466"
  }
}
  • ๊ธฐ๋ณธ์ ์œผ๋กœ success , code , data , errors , meta ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

    • success : ์š”์ฒญ ์„ฑ๊ณต ์—ฌ๋ถ€

    • code : ์š”์ฒญ ๊ฒฐ๊ณผ ์ฝ”๋“œ (http status code ์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.)

    • data : ์š”์ฒญ ๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ ( success๊ฐ€ true์ธ ๊ฒฝ์šฐ )

    • errors : ์š”์ฒญ ๊ฒฐ๊ณผ ์—๋Ÿฌ ( success๊ฐ€ false์ธ ๊ฒฝ์šฐ )

    • meta : ์š”์ฒญ ๊ฒฐ๊ณผ ๋ฉ”ํƒ€์ •๋ณด ( ์„œ๋ฒ„ ์‘๋‹ต ์ •๋ณด, ๊ธฐ์กด ๊ฒ€์ƒ‰ ์ •๋ณด , page ์ •๋ณด ๋“ฑ)

  • ๋ˆ„๋ฝ๋œ ์ •๋ณด๋Š” ์„œ๋ฒ„ ๋ฐฑ์—”๋“œ ํŒ€์—๊ฒŒ ๋ฌธ์˜ํ•ด์ฃผ์„ธ์š”.


1.3. ๊ณตํ†ต ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

๊ณตํ†ต์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ์˜ˆ์™ธ๋ฅผ ์ •๋ฆฌํ•˜๋Š” ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.

success ์ฝ”๋“œ๊ฐ€ false์ธ ๊ฒฝ์šฐ errors ๊ฐ’์„ ํ™•์ธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๊ณตํ†ต์ ์ธ ์˜ˆ์™ธ์˜ ์ข…๋ฅ˜์—๋Š” ์ด๋Ÿฐ ๊ฐ’๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ˆซ์ž ๊ฐ’์ด ํ•„์š”ํ•œ๋ฐ ๋ฌธ์ž์—ด ๊ฐ’์ด ๋“ค์–ด์˜จ ๊ฒฝ์šฐ

POST http://localhost:8080/admin/api/v1/example
Content-Type: application/json

{
  "userId": "์ผ", // ์ˆซ์ž ๊ฐ’์ด ํ•„์š”ํ•œ๋ฐ ๋ฌธ์ž์—ด ๊ฐ’์ด ๋“ค์–ด์˜จ ๊ฒฝ์šฐ
  "targetId": 0,
  "type": "EXAMPLE",
  "content": "๋‚ด์šฉ"
}
{
  "success": false,
  "code": 400,
  "data": [],
  "errors": {
    "message": "'userId' ํ•„๋“œ์˜ ๊ฐ’์ด ์ž˜๋ชป๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ํ•„๋“œ์˜ ๊ฐ’์˜ ํƒ€์ž…์„ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
  },
  "meta": {
    "serverVersion": "1.0.0",
    "serverEncoding": "UTF-8",
    "serverResponseTime": "2024-04-19T22:28:52.428425",
    "serverPathVersion": "v1"
  }
}
  • ํ•„์ˆ˜์ ์ธ ๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ

POST http://localhost:8080/admin/api/v1/example
Content-Type: application/json

{
  "userId": "", // ํ•„์ˆ˜์ ์ธ ๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ
  "targetId": 0,
  "type": "EXAMPLE",
  "content": "๋‚ด์šฉ"
}
{
  "success": false,
  "code": 400,
  "data": [],
  "errors": {
    "userId": "์‚ฌ์šฉ์ž ์•„์ด๋””๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค."
  },
  "meta": {
    "serverVersion": "1.0.0",
    "serverEncoding": "UTF-8",
    "serverResponseTime": "2024-04-19T22:31:48.742731",
    "serverPathVersion": "v1"
  }
}
  • ๋ˆ„๋ฝ๋œ ์ •๋ณด๋Š” ์„œ๋ฒ„ ๋ฐฑ์—”๋“œ ํŒ€์—๊ฒŒ ๋ฌธ์˜ํ•ด์ฃผ์„ธ์š”.

  • ์ถ”๊ฐ€๋˜์—ˆ์œผ๋ฉด ์ข‹์€ ์ •๋ณด๊ฐ€ ์žˆ์œผ๋ฉด ์„œ๋ฒ„ ๋ฐฑ์—”๋“œ ํŒ€์—๊ฒŒ ๋ฌธ์˜ํ•ด์ฃผ์„ธ์š”.


2. Auth API

2.1. ๋กœ๊ทธ์ธ

  • ๊ด€๋ฆฌ์ž ๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธํ•˜์—ฌ ์•ก์„ธ์Šค ํ† ํฐ๊ณผ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์Šต๋‹ˆ๋‹ค.

POST /admin/api/v1/auth/login

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

email

String

๊ด€๋ฆฌ์ž ์ด๋ฉ”์ผ

password

String

๋น„๋ฐ€๋ฒˆํ˜ธ

POST /auth/login HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 68
Host: localhost:8080

{
  "email" : "admin@bottlenote.com",
  "password" : "password123"
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data.accessToken

String

์•ก์„ธ์Šค ํ† ํฐ

data.refreshToken

String

๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 358

{
  "success" : true,
  "code" : 200,
  "data" : {
    "accessToken" : "45NB0IdMDEUNFhoo6aSEJoCd4ogXTKZU",
    "refreshToken" : "H3rWo6kqoHlE1okBrRMMe5Gj8b98ACQB"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:22.765819652",
    "serverPathVersion" : "v1"
  }
}

2.2. ํ† ํฐ ๊ฐฑ์‹ 

  • ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒˆ๋กœ์šด ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์Šต๋‹ˆ๋‹ค.

POST /admin/api/v1/auth/refresh

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

refreshToken

String

๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ

POST /auth/refresh HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 47
Host: localhost:8080

{
  "refreshToken" : "existing_refresh_token"
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data.accessToken

String

์ƒˆ ์•ก์„ธ์Šค ํ† ํฐ

data.refreshToken

String

์ƒˆ ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 358

{
  "success" : true,
  "code" : 200,
  "data" : {
    "accessToken" : "ynrM8nEWwJPLLygaBSPXlHyDvvxbGQNF",
    "refreshToken" : "GmfB6SOWt0iVa1ZfYQzb4OY9O6QI8Abm"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:22.791133856",
    "serverPathVersion" : "v1"
  }
}

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

  • ์ธ์ฆ๋œ ๊ด€๋ฆฌ์ž๊ฐ€ ์ƒˆ๋กœ์šด ๊ด€๋ฆฌ์ž ๊ณ„์ •์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • ๋ชจ๋“  ์ธ์ฆ๋œ ์–ด๋“œ๋ฏผ์ด ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • ROOT_ADMIN ์—ญํ• ์€ ROOT_ADMIN๋งŒ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

POST /admin/api/v1/auth/signup

์š”์ฒญ ํ—ค๋”

Name Description

Authorization

Bearer ์•ก์„ธ์Šค ํ† ํฐ

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

email

String

์–ด๋“œ๋ฏผ ์ด๋ฉ”์ผ

password

String

๋น„๋ฐ€๋ฒˆํ˜ธ (8~35์ž)

name

String

์–ด๋“œ๋ฏผ ์ด๋ฆ„ (2~50์ž)

roles

Array

์—ญํ•  ๋ชฉ๋ก (ROOT_ADMIN, PARTNER, CLIENT, BAR_OWNER, COMMUNITY_MANAGER)

AdminRole (๊ด€๋ฆฌ์ž ์—ญํ• )

๊ฐ’ ์„ค๋ช…

ROOT_ADMIN

์ตœ๊ณ  ๊ด€๋ฆฌ์ž

PARTNER

ํŒŒํŠธ๋„ˆ์‚ฌ

CLIENT

๊ณ ๊ฐ์‚ฌ

BAR_OWNER

๋ฐ”/๋งค์žฅ ์‚ฌ์žฅ๋‹˜

COMMUNITY_MANAGER

์ปค๋ฎค๋‹ˆํ‹ฐ ๋งค๋‹ˆ์ €

POST /auth/signup HTTP/1.1
Content-Type: application/json;charset=UTF-8
Authorization: Bearer test_access_token
Content-Length: 142
Host: localhost:8080

{
  "email" : "new@bottlenote.com",
  "password" : "password123",
  "name" : "์ƒˆ ์–ด๋“œ๋ฏผ",
  "roles" : [ "PARTNER", "COMMUNITY_MANAGER" ]
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data.adminId

Number

์ƒ์„ฑ๋œ ์–ด๋“œ๋ฏผ ID

data.email

String

์–ด๋“œ๋ฏผ ์ด๋ฉ”์ผ

data.name

String

์–ด๋“œ๋ฏผ ์ด๋ฆ„

data.roles

Array

๋ถ€์—ฌ๋œ ์—ญํ•  ๋ชฉ๋ก

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 380

{
  "success" : true,
  "code" : 200,
  "data" : {
    "adminId" : 1,
    "email" : "new@bottlenote.com",
    "name" : "์ƒˆ ์–ด๋“œ๋ฏผ",
    "roles" : [ "PARTNER", "COMMUNITY_MANAGER" ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:22.729611519",
    "serverPathVersion" : "v1"
  }
}

2.4. ํƒˆํ‡ด

  • ์ธ์ฆ๋œ ๊ด€๋ฆฌ์ž ๊ณ„์ •์„ ํƒˆํ‡ด ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

DELETE /admin/api/v1/auth/withdraw

์š”์ฒญ ํ—ค๋”

Name Description

Authorization

Bearer ์•ก์„ธ์Šค ํ† ํฐ

DELETE /auth/withdraw HTTP/1.1
Authorization: Bearer test_access_token
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data.message

String

์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 294

{
  "success" : true,
  "code" : 200,
  "data" : {
    "message" : "ํƒˆํ‡ด ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:22.677793668",
    "serverPathVersion" : "v1"
  }
}

3. Alcohol API

3.1. ์ˆ (Alcohol) ๋ชฉ๋ก ์กฐํšŒ

  • ๊ด€๋ฆฌ์ž์šฉ ์ˆ  ๋ชฉ๋ก ์กฐํšŒ API์ž…๋‹ˆ๋‹ค.

  • ํ‚ค์›Œ๋“œ ๊ฒ€์ƒ‰, ์นดํ…Œ๊ณ ๋ฆฌ ํ•„ํ„ฐ, ์ •๋ ฌ, ํŽ˜์ด์ง•์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/alcohols

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Parameter Description

keyword

๊ฒ€์ƒ‰์–ด (ํ•œ๊ธ€/์˜๋ฌธ ์ด๋ฆ„ ๊ฒ€์ƒ‰)

category

์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน ํ•„ํ„ฐ (์˜ˆ: SINGLE_MALT, BLEND ๋“ฑ)

regionId

์ง€์—ญ ID ํ•„ํ„ฐ

sortType

์ •๋ ฌ ๊ธฐ์ค€ (KOR_NAME, ENG_NAME, KOR_CATEGORY, ENG_CATEGORY / ๊ธฐ๋ณธ๊ฐ’: KOR_NAME)

sortOrder

์ •๋ ฌ ๋ฐฉํ–ฅ (๊ธฐ๋ณธ๊ฐ’: ASC)

page

ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ (๊ธฐ๋ณธ๊ฐ’: 0)

size

ํŽ˜์ด์ง€ ํฌ๊ธฐ (๊ธฐ๋ณธ๊ฐ’: 20)

AlcoholCategoryGroup (์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน)

๊ฐ’ ์„ค๋ช…

SINGLE_MALT

์‹ฑ๊ธ€๋ชฐํŠธ ์œ„์Šคํ‚ค

BLEND

๋ธ”๋ Œ๋””๋“œ ์œ„์Šคํ‚ค

BLENDED_MALT

๋ธ”๋ Œ๋””๋“œ ๋ชฐํŠธ ์œ„์Šคํ‚ค

BOURBON

๋ฒ„๋ฒˆ ์œ„์Šคํ‚ค

RYE

๋ผ์ด ์œ„์Šคํ‚ค

OTHER

๊ธฐํƒ€ ์œ„์Šคํ‚ค

$ curl 'http://localhost:8080/alcohols?keyword=%EA%B8%80%EB%A0%8C&category=SINGLE_MALT&regionId=1&sortType=KOR_NAME&sortOrder=ASC&page=0&size=20' -i -X GET
GET /alcohols?keyword=%EA%B8%80%EB%A0%8C&category=SINGLE_MALT&regionId=1&sortType=KOR_NAME&sortOrder=ASC&page=0&size=20 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Array

์ˆ  ๋ชฉ๋ก ๋ฐ์ดํ„ฐ

data[].alcoholId

Number

์ˆ  ID

data[].korName

String

์ˆ  ํ•œ๊ธ€ ์ด๋ฆ„

data[].engName

String

์ˆ  ์˜๋ฌธ ์ด๋ฆ„

data[].korCategoryName

String

์นดํ…Œ๊ณ ๋ฆฌ ํ•œ๊ธ€๋ช…

data[].engCategoryName

String

์นดํ…Œ๊ณ ๋ฆฌ ์˜๋ฌธ๋ช…

data[].imageUrl

String

์ˆ  ์ด๋ฏธ์ง€ URL

data[].createdAt

String

์ƒ์„ฑ์ผ์‹œ

data[].modifiedAt

String

์ˆ˜์ •์ผ์‹œ

data[].deletedAt

String

์‚ญ์ œ์ผ์‹œ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.page

Number

ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ

meta.size

Number

ํŽ˜์ด์ง€ ํฌ๊ธฐ

meta.totalElements

Number

์ „์ฒด ์š”์†Œ ์ˆ˜

meta.totalPages

Number

์ „์ฒด ํŽ˜์ด์ง€ ์ˆ˜

meta.hasNext

Boolean

๋‹ค์Œ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1020

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "alcoholId" : 1,
    "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค 1",
    "engName" : "Test Whisky 1",
    "korCategoryName" : "์‹ฑ๊ธ€๋ชฐํŠธ",
    "engCategoryName" : "Single Malt",
    "imageUrl" : "https://example.com/image.jpg",
    "createdAt" : "2024-01-01T00:00:00",
    "modifiedAt" : "2024-06-01T00:00:00",
    "deletedAt" : null
  }, {
    "alcoholId" : 2,
    "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค 2",
    "engName" : "Test Whisky 2",
    "korCategoryName" : "์‹ฑ๊ธ€๋ชฐํŠธ",
    "engCategoryName" : "Single Malt",
    "imageUrl" : "https://example.com/image.jpg",
    "createdAt" : "2024-02-01T00:00:00",
    "modifiedAt" : "2024-07-01T00:00:00",
    "deletedAt" : null
  } ],
  "errors" : [ ],
  "meta" : {
    "page" : 0,
    "size" : 20,
    "totalElements" : 2,
    "totalPages" : 1,
    "hasNext" : false,
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T13:53:18.781091333",
    "serverPathVersion" : "v1"
  }
}

3.2. ์ˆ (Alcohol) ๋‹จ๊ฑด ์ƒ์„ธ ์กฐํšŒ

  • ๊ด€๋ฆฌ์ž์šฉ ์ˆ  ๋‹จ๊ฑด ์ƒ์„ธ ์กฐํšŒ API์ž…๋‹ˆ๋‹ค.

  • ๊ธฐ๋ณธ ์ •๋ณด, ์นดํ…Œ๊ณ ๋ฆฌ, ์ŠคํŽ™, ์ง€์—ญ, ์ฆ๋ฅ˜์†Œ, ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ, ํ†ต๊ณ„ ์ •๋ณด๋ฅผ ๋ชจ๋‘ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/alcohols/{alcoholId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 1. /alcohols/{alcoholId}
Parameter Description

alcoholId

์ˆ  ID

$ curl 'http://localhost:8080/alcohols/1' -i -X GET
GET /alcohols/1 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

์ˆ  ์ƒ์„ธ ์ •๋ณด

data.alcoholId

Number

์ˆ  ID

data.korName

String

ํ•œ๊ธ€ ์ด๋ฆ„

data.engName

String

์˜๋ฌธ ์ด๋ฆ„

data.imageUrl

String

์ด๋ฏธ์ง€ URL

data.type

String

์ˆ  ํƒ€์ž… (WHISKY ๋“ฑ)

data.korCategory

String

์นดํ…Œ๊ณ ๋ฆฌ ํ•œ๊ธ€๋ช…

data.engCategory

String

์นดํ…Œ๊ณ ๋ฆฌ ์˜๋ฌธ๋ช…

data.categoryGroup

String

์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน

data.abv

String

๋„์ˆ˜

data.age

String

์ˆ™์„ฑ๋…„๋„

data.cask

String

์บ์Šคํฌ ํƒ€์ž…

data.volume

String

์šฉ๋Ÿ‰

data.description

String

์„ค๋ช…

data.regionId

Number

์ง€์—ญ ID

data.korRegion

String

์ง€์—ญ ํ•œ๊ธ€๋ช…

data.engRegion

String

์ง€์—ญ ์˜๋ฌธ๋ช…

data.distilleryId

Number

์ฆ๋ฅ˜์†Œ ID

data.korDistillery

String

์ฆ๋ฅ˜์†Œ ํ•œ๊ธ€๋ช…

data.engDistillery

String

์ฆ๋ฅ˜์†Œ ์˜๋ฌธ๋ช…

data.tastingTags

Array

ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ๋ชฉ๋ก

data.tastingTags[].id

Number

ํƒœ๊ทธ ID

data.tastingTags[].korName

String

ํƒœ๊ทธ ํ•œ๊ธ€๋ช…

data.tastingTags[].engName

String

ํƒœ๊ทธ ์˜๋ฌธ๋ช…

data.avgRating

Number

ํ‰๊ท  ํ‰์ 

data.totalRatingsCount

Number

ํ‰์  ์ˆ˜

data.reviewCount

Number

๋ฆฌ๋ทฐ ์ˆ˜

data.pickCount

Number

์ฐœ ์ˆ˜

data.createdAt

String

์ƒ์„ฑ์ผ์‹œ

data.modifiedAt

String

์ˆ˜์ •์ผ์‹œ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1240

{
  "success" : true,
  "code" : 200,
  "data" : {
    "alcoholId" : 1,
    "korName" : "๊ธ€๋ Œํ”ผ๋”• 12๋…„",
    "engName" : "Glenfiddich 12 Year",
    "imageUrl" : "https://example.com/image.jpg",
    "type" : "WHISKY",
    "korCategory" : "์‹ฑ๊ธ€๋ชฐํŠธ",
    "engCategory" : "Single Malt",
    "categoryGroup" : "SINGLE_MALT",
    "abv" : "40%",
    "age" : "12",
    "cask" : "์˜คํฌ",
    "volume" : "700ml",
    "description" : "์Šค์ฝ”ํ‹€๋žœ๋“œ์˜ ๋Œ€ํ‘œ์ ์ธ ์‹ฑ๊ธ€๋ชฐํŠธ ์œ„์Šคํ‚ค",
    "regionId" : 1,
    "korRegion" : "์Šค์ฝ”ํ‹€๋žœ๋“œ",
    "engRegion" : "Scotland",
    "distilleryId" : 1,
    "korDistillery" : "๊ธ€๋ Œํ”ผ๋”•",
    "engDistillery" : "Glenfiddich",
    "tastingTags" : [ {
      "id" : 1,
      "korName" : "๋ฐ”๋‹๋ผ",
      "engName" : "Vanilla"
    }, {
      "id" : 2,
      "korName" : "๊ฟ€",
      "engName" : "Honey"
    } ],
    "avgRating" : 4.2,
    "totalRatingsCount" : 150,
    "reviewCount" : 45,
    "pickCount" : 200,
    "createdAt" : "2024-01-01T00:00:00",
    "modifiedAt" : "2024-06-01T00:00:00"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:19.635627766",
    "serverPathVersion" : "v1"
  }
}

3.3. ์ˆ (Alcohol) ์ƒ์„ฑ

  • ๊ด€๋ฆฌ์ž์šฉ ์ˆ  ์ƒ์„ฑ API์ž…๋‹ˆ๋‹ค.

  • ๋ชจ๋“  ํ•„๋“œ๋Š” ํ•„์ˆ˜๊ฐ’์ž…๋‹ˆ๋‹ค.

POST /admin/api/v1/alcohols

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

korName

String

ํ•œ๊ธ€ ์ด๋ฆ„

engName

String

์˜๋ฌธ ์ด๋ฆ„

abv

String

๋„์ˆ˜

type

String

์ˆ  ํƒ€์ž… (WHISKY ๋“ฑ)

korCategory

String

์นดํ…Œ๊ณ ๋ฆฌ ํ•œ๊ธ€๋ช…

engCategory

String

์นดํ…Œ๊ณ ๋ฆฌ ์˜๋ฌธ๋ช…

categoryGroup

String

์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน (SINGLE_MALT ๋“ฑ)

regionId

Number

์ง€์—ญ ID

distilleryId

Number

์ฆ๋ฅ˜์†Œ ID

age

String

์ˆ™์„ฑ๋…„๋„

cask

String

์บ์Šคํฌ ํƒ€์ž…

imageUrl

String

์ด๋ฏธ์ง€ URL

description

String

์„ค๋ช…

volume

String

์šฉ๋Ÿ‰

tastingTagIds

Array

ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ID ๋ชฉ๋ก

AlcoholType (์ˆ  ํƒ€์ž…)

๊ฐ’ ์„ค๋ช…

WHISKY

์œ„์Šคํ‚ค

RUM

๋Ÿผ

VODKA

๋ณด๋“œ์นด

GIN

์ง„

TEQUILA

๋ฐํ‚ฌ๋ผ

BRANDY

๋ธŒ๋žœ๋””

BEER

๋งฅ์ฃผ

WINE

์™€์ธ

ETC

๊ธฐํƒ€

AlcoholCategoryGroup (์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน)

๊ฐ’ ์„ค๋ช…

SINGLE_MALT

์‹ฑ๊ธ€๋ชฐํŠธ ์œ„์Šคํ‚ค

BLEND

๋ธ”๋ Œ๋””๋“œ ์œ„์Šคํ‚ค

BLENDED_MALT

๋ธ”๋ Œ๋””๋“œ ๋ชฐํŠธ ์œ„์Šคํ‚ค

BOURBON

๋ฒ„๋ฒˆ ์œ„์Šคํ‚ค

RYE

๋ผ์ด ์œ„์Šคํ‚ค

OTHER

๊ธฐํƒ€ ์œ„์Šคํ‚ค

$ curl 'http://localhost:8080/alcohols' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค",
  "engName" : "Test Whisky",
  "abv" : "40%",
  "type" : "WHISKY",
  "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
  "engCategory" : "Single Malt",
  "categoryGroup" : "SINGLE_MALT",
  "regionId" : 1,
  "distilleryId" : 1,
  "age" : "12",
  "cask" : "American Oak",
  "imageUrl" : "https://example.com/test.jpg",
  "description" : "ํ…Œ์ŠคํŠธ ์„ค๋ช…",
  "volume" : "700ml",
  "tastingTagIds" : [ 1, 2 ]
}'
POST /alcohols HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 429
Host: localhost:8080

{
  "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค",
  "engName" : "Test Whisky",
  "abv" : "40%",
  "type" : "WHISKY",
  "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
  "engCategory" : "Single Malt",
  "categoryGroup" : "SINGLE_MALT",
  "regionId" : 1,
  "distilleryId" : 1,
  "age" : "12",
  "cask" : "American Oak",
  "imageUrl" : "https://example.com/test.jpg",
  "description" : "ํ…Œ์ŠคํŠธ ์„ค๋ช…",
  "volume" : "700ml",
  "tastingTagIds" : [ 1, 2 ]
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ (ALCOHOL_CREATED)

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์ƒ์„ฑ๋œ ์ˆ  ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 393

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "ALCOHOL_CREATED",
    "message" : "์œ„์Šคํ‚ค๊ฐ€ ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:19"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:19.96254606",
    "serverPathVersion" : "v1"
  }
}

3.4. ์ˆ (Alcohol) ์ˆ˜์ •

  • ๊ด€๋ฆฌ์ž์šฉ ์ˆ  ์ˆ˜์ • API์ž…๋‹ˆ๋‹ค.

  • ์ „์ฒด ์ˆ˜์ •(PUT)์ด๋ฏ€๋กœ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ์ด๋ฏธ ์‚ญ์ œ๋œ ์ˆ ์€ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

PUT /admin/api/v1/alcohols/{alcoholId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 2. /alcohols/{alcoholId}
Parameter Description

alcoholId

์ˆ˜์ •ํ•  ์ˆ  ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

korName

String

ํ•œ๊ธ€ ์ด๋ฆ„

engName

String

์˜๋ฌธ ์ด๋ฆ„

abv

String

๋„์ˆ˜

type

String

์ˆ  ํƒ€์ž… (WHISKY ๋“ฑ)

korCategory

String

์นดํ…Œ๊ณ ๋ฆฌ ํ•œ๊ธ€๋ช…

engCategory

String

์นดํ…Œ๊ณ ๋ฆฌ ์˜๋ฌธ๋ช…

categoryGroup

String

์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน (SINGLE_MALT ๋“ฑ)

regionId

Number

์ง€์—ญ ID

distilleryId

Number

์ฆ๋ฅ˜์†Œ ID

age

String

์ˆ™์„ฑ๋…„๋„

cask

String

์บ์Šคํฌ ํƒ€์ž…

imageUrl

String

์ด๋ฏธ์ง€ URL

description

String

์„ค๋ช…

volume

String

์šฉ๋Ÿ‰

tastingTagIds

Array

ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ID ๋ชฉ๋ก

AlcoholType (์ˆ  ํƒ€์ž…)

๊ฐ’ ์„ค๋ช…

WHISKY

์œ„์Šคํ‚ค

RUM

๋Ÿผ

VODKA

๋ณด๋“œ์นด

GIN

์ง„

TEQUILA

๋ฐํ‚ฌ๋ผ

BRANDY

๋ธŒ๋žœ๋””

BEER

๋งฅ์ฃผ

WINE

์™€์ธ

ETC

๊ธฐํƒ€

AlcoholCategoryGroup (์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน)

๊ฐ’ ์„ค๋ช…

SINGLE_MALT

์‹ฑ๊ธ€๋ชฐํŠธ ์œ„์Šคํ‚ค

BLEND

๋ธ”๋ Œ๋””๋“œ ์œ„์Šคํ‚ค

BLENDED_MALT

๋ธ”๋ Œ๋””๋“œ ๋ชฐํŠธ ์œ„์Šคํ‚ค

BOURBON

๋ฒ„๋ฒˆ ์œ„์Šคํ‚ค

RYE

๋ผ์ด ์œ„์Šคํ‚ค

OTHER

๊ธฐํƒ€ ์œ„์Šคํ‚ค

$ curl 'http://localhost:8080/alcohols/1' -i -X PUT \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "korName" : "์ˆ˜์ •๋œ ์œ„์Šคํ‚ค",
  "engName" : "Updated Whisky",
  "abv" : "40%",
  "type" : "WHISKY",
  "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
  "engCategory" : "Single Malt",
  "categoryGroup" : "SINGLE_MALT",
  "regionId" : 1,
  "distilleryId" : 1,
  "age" : "12",
  "cask" : "American Oak",
  "imageUrl" : "https://example.com/test.jpg",
  "description" : "ํ…Œ์ŠคํŠธ ์„ค๋ช…",
  "volume" : "700ml",
  "tastingTagIds" : [ 1, 2 ]
}'
PUT /alcohols/1 HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 432
Host: localhost:8080

{
  "korName" : "์ˆ˜์ •๋œ ์œ„์Šคํ‚ค",
  "engName" : "Updated Whisky",
  "abv" : "40%",
  "type" : "WHISKY",
  "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
  "engCategory" : "Single Malt",
  "categoryGroup" : "SINGLE_MALT",
  "regionId" : 1,
  "distilleryId" : 1,
  "age" : "12",
  "cask" : "American Oak",
  "imageUrl" : "https://example.com/test.jpg",
  "description" : "ํ…Œ์ŠคํŠธ ์„ค๋ช…",
  "volume" : "700ml",
  "tastingTagIds" : [ 1, 2 ]
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ (ALCOHOL_UPDATED)

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์ˆ˜์ •๋œ ์ˆ  ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 394

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "ALCOHOL_UPDATED",
    "message" : "์œ„์Šคํ‚ค๊ฐ€ ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:19"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:20.000960629",
    "serverPathVersion" : "v1"
  }
}

3.5. ์ˆ (Alcohol) ์‚ญ์ œ

  • ๊ด€๋ฆฌ์ž์šฉ ์ˆ  ์‚ญ์ œ API์ž…๋‹ˆ๋‹ค.

  • ์†Œํ”„ํŠธ ์‚ญ์ œ๋กœ ์ฒ˜๋ฆฌ๋˜๋ฉฐ, ์‹ค์ œ ๋ฐ์ดํ„ฐ๋Š” ์‚ญ์ œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ๋ฆฌ๋ทฐ ๋˜๋Š” ํ‰์ ์ด ์กด์žฌํ•˜๋Š” ์ˆ ์€ ์‚ญ์ œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

  • ์ด๋ฏธ ์‚ญ์ œ๋œ ์ˆ ์€ ์žฌ์‚ญ์ œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

DELETE /admin/api/v1/alcohols/{alcoholId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 3. /alcohols/{alcoholId}
Parameter Description

alcoholId

์‚ญ์ œํ•  ์ˆ  ID

$ curl 'http://localhost:8080/alcohols/1' -i -X DELETE
DELETE /alcohols/1 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ๋ฐ์ดํ„ฐ

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ (ALCOHOL_DELETED)

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์‚ญ์ œ๋œ ์ˆ  ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 394

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "ALCOHOL_DELETED",
    "message" : "์œ„์Šคํ‚ค๊ฐ€ ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:19"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:19.595359491",
    "serverPathVersion" : "v1"
  }
}

3.6. ์นดํ…Œ๊ณ ๋ฆฌ ๋ ˆํผ๋Ÿฐ์Šค ์กฐํšŒ

  • ํ˜„์žฌ DB์— ๋“ฑ๋ก๋œ ๋ชจ๋“  ์นดํ…Œ๊ณ ๋ฆฌ ํŽ˜์–ด(ํ•œ๊ธ€/์˜๋ฌธ) ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ์ˆ  ์ƒ์„ฑ/์ˆ˜์ • ์‹œ ๊ธฐ์กด ์นดํ…Œ๊ณ ๋ฆฌ๋ฅผ ์ฐธ์กฐํ•˜๊ธฐ ์œ„ํ•œ API์ž…๋‹ˆ๋‹ค.

  • ๋™์ผ ํ•œ๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ผ๋„ ์˜๋ฌธ ์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ ๋‹ค๋ฅด๋ฉด ๋ณ„๋„ ํ•ญ๋ชฉ์œผ๋กœ ์กฐํšŒ๋ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/alcohols/categories/reference

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Array

์นดํ…Œ๊ณ ๋ฆฌ ํŽ˜์–ด ๋ชฉ๋ก

data[].korCategory

String

ํ•œ๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ

data[].engCategory

String

์˜๋ฌธ ์นดํ…Œ๊ณ ๋ฆฌ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 460

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
    "engCategory" : "Single Malt"
  }, {
    "korCategory" : "๋ธ”๋ Œ๋””๋“œ",
    "engCategory" : "Blended"
  }, {
    "korCategory" : "๋ฒ„๋ฒˆ",
    "engCategory" : "Bourbon"
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:19.72385149",
    "serverPathVersion" : "v1"
  }
}

4. Help API

4.1. ๋ฌธ์˜ ๋ชฉ๋ก ์กฐํšŒ

  • ์ „์ฒด ๋ฌธ์˜ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ์ƒํƒœ(status)์™€ ์œ ํ˜•(type)์œผ๋กœ ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ปค์„œ ๊ธฐ๋ฐ˜ ํŽ˜์ด์ง•์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/helps

์š”์ฒญ ํ—ค๋”

Name Description

Authorization

Bearer ์•ก์„ธ์Šค ํ† ํฐ

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Parameter Description

status

์ƒํƒœ ํ•„ํ„ฐ (WAITING, SUCCESS, REJECT, DELETED)

type

๋ฌธ์˜ ์œ ํ˜• ํ•„ํ„ฐ (WHISKEY, REVIEW, USER, ETC)

cursor

ํŽ˜์ด์ง• ์ปค์„œ (๊ธฐ๋ณธ๊ฐ’: 0)

pageSize

ํŽ˜์ด์ง€ ํฌ๊ธฐ (๊ธฐ๋ณธ๊ฐ’: 20)

HelpType (๋ฌธ์˜ ์œ ํ˜•)

๊ฐ’ ์„ค๋ช…

WHISKEY

์œ„์Šคํ‚ค ๊ด€๋ จ ๋ฌธ์˜

REVIEW

๋ฆฌ๋ทฐ ๊ด€๋ จ ๋ฌธ์˜

USER

ํšŒ์› ๊ด€๋ จ ๋ฌธ์˜

ETC

๊ทธ ์™ธ ๋ชจ๋“  ๋ฌธ์˜

StatusType (์ฒ˜๋ฆฌ ์ƒํƒœ)

๊ฐ’ ์„ค๋ช…

WAITING

๋Œ€๊ธฐ์ค‘

SUCCESS

์ฒ˜๋ฆฌ ์™„๋ฃŒ

REJECT

๋ฐ˜๋ ค

DELETED

์‚ญ์ œ

GET /helps?status=WAITING&type=WHISKEY&cursor=0&pageSize=20 HTTP/1.1
Authorization: Bearer test_access_token
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data.content.totalCount

Number

์ „์ฒด ๋ฌธ์˜ ์ˆ˜

data.content.helpList[].helpId

Number

๋ฌธ์˜ ID

data.content.helpList[].userId

Number

๋ฌธ์˜์ž ID

data.content.helpList[].userNickname

String

๋ฌธ์˜์ž ๋‹‰๋„ค์ž„

data.content.helpList[].title

String

๋ฌธ์˜ ์ œ๋ชฉ

data.content.helpList[].type

String

๋ฌธ์˜ ์œ ํ˜•

data.content.helpList[].status

String

์ฒ˜๋ฆฌ ์ƒํƒœ

data.content.helpList[].createAt

String

์ƒ์„ฑ์ผ์‹œ

data.cursorPageable.cursor

Number

๋‹ค์Œ ์ปค์„œ

data.cursorPageable.pageSize

Number

ํŽ˜์ด์ง€ ํฌ๊ธฐ

data.cursorPageable.hasNext

Boolean

๋‹ค์Œ ํŽ˜์ด์ง€ ์—ฌ๋ถ€

data.cursorPageable.currentCursor

Number

ํ˜„์žฌ ์ปค์„œ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 700

{
  "success" : true,
  "code" : 200,
  "data" : {
    "content" : {
      "totalCount" : 1,
      "helpList" : [ {
        "helpId" : 1,
        "userId" : 100,
        "userNickname" : "ํ…Œ์ŠคํŠธ์œ ์ €",
        "title" : "์œ„์Šคํ‚ค ๊ด€๋ จ ๋ฌธ์˜",
        "type" : "WHISKEY",
        "status" : "WAITING",
        "createAt" : "2026-04-08T13:53:25.277155046"
      } ]
    },
    "cursorPageable" : {
      "currentCursor" : 0,
      "cursor" : 20,
      "pageSize" : 20,
      "hasNext" : false
    }
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:25.280926197",
    "serverPathVersion" : "v1"
  }
}

4.2. ๋ฌธ์˜ ์ƒ์„ธ ์กฐํšŒ

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

  • ๋ฌธ์˜ ๋‚ด์šฉ, ์ด๋ฏธ์ง€, ๋‹ต๋ณ€ ๋‚ด์šฉ ๋“ฑ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

GET /admin/api/v1/helps/{helpId}

์š”์ฒญ ํ—ค๋”

Name Description

Authorization

Bearer ์•ก์„ธ์Šค ํ† ํฐ

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 4. /helps/{helpId}
Parameter Description

helpId

๋ฌธ์˜ ID

GET /helps/1 HTTP/1.1
Authorization: Bearer test_access_token
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data.helpId

Number

๋ฌธ์˜ ID

data.userId

Number

๋ฌธ์˜์ž ID

data.userNickname

String

๋ฌธ์˜์ž ๋‹‰๋„ค์ž„

data.title

String

๋ฌธ์˜ ์ œ๋ชฉ

data.content

String

๋ฌธ์˜ ๋‚ด์šฉ

data.type

String

๋ฌธ์˜ ์œ ํ˜•

data.imageUrlList[].order

Number

์ด๋ฏธ์ง€ ์ˆœ์„œ

data.imageUrlList[].viewUrl

String

์ด๋ฏธ์ง€ URL

data.status

String

์ฒ˜๋ฆฌ ์ƒํƒœ

data.adminId

Null

๋‹ด๋‹น ๊ด€๋ฆฌ์ž ID

data.responseContent

Null

๋‹ต๋ณ€ ๋‚ด์šฉ

data.createAt

String

์ƒ์„ฑ์ผ์‹œ

data.lastModifyAt

String

์ˆ˜์ •์ผ์‹œ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 732

{
  "success" : true,
  "code" : 200,
  "data" : {
    "helpId" : 1,
    "userId" : 100,
    "userNickname" : "ํ…Œ์ŠคํŠธ์œ ์ €",
    "title" : "์œ„์Šคํ‚ค ๊ด€๋ จ ๋ฌธ์˜",
    "content" : "์œ„์Šคํ‚ค์— ๋Œ€ํ•ด ๋ฌธ์˜๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
    "type" : "WHISKEY",
    "imageUrlList" : [ {
      "order" : 1,
      "viewUrl" : "https://example.com/image.jpg"
    } ],
    "status" : "WAITING",
    "adminId" : null,
    "responseContent" : null,
    "createAt" : "2026-04-08T13:53:25.197951792",
    "lastModifyAt" : "2026-04-08T13:53:25.197962542"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:25.203897138",
    "serverPathVersion" : "v1"
  }
}

4.3. ๋ฌธ์˜ ๋‹ต๋ณ€ ๋“ฑ๋ก

  • ๋ฌธ์˜์— ๋Œ€ํ•œ ๋‹ต๋ณ€์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค.

  • ์ฒ˜๋ฆฌ ์ƒํƒœ๋ฅผ SUCCESS(์ฒ˜๋ฆฌ ์™„๋ฃŒ) ๋˜๋Š” REJECT(๋ฐ˜๋ ค)๋กœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

POST /admin/api/v1/helps/{helpId}/answer

์š”์ฒญ ํ—ค๋”

Name Description

Authorization

Bearer ์•ก์„ธ์Šค ํ† ํฐ

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 5. /helps/{helpId}/answer
Parameter Description

helpId

๋ฌธ์˜ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

responseContent

String

๋‹ต๋ณ€ ๋‚ด์šฉ

status

String

์ฒ˜๋ฆฌ ์ƒํƒœ (SUCCESS, REJECT)

StatusType (์ฒ˜๋ฆฌ ์ƒํƒœ)

๊ฐ’ ์„ค๋ช…

WAITING

๋Œ€๊ธฐ์ค‘

SUCCESS

์ฒ˜๋ฆฌ ์™„๋ฃŒ

REJECT

๋ฐ˜๋ ค

DELETED

์‚ญ์ œ

POST /helps/1/answer HTTP/1.1
Content-Type: application/json;charset=UTF-8
Authorization: Bearer test_access_token
Content-Length: 75
Host: localhost:8080

{
  "responseContent" : "๋‹ต๋ณ€ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.",
  "status" : "SUCCESS"
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data.helpId

Number

๋ฌธ์˜ ID

data.status

String

์ฒ˜๋ฆฌ ์ƒํƒœ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 340

{
  "success" : true,
  "code" : 200,
  "data" : {
    "helpId" : 1,
    "status" : "SUCCESS",
    "message" : "๋‹ต๋ณ€์ด ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:25.25640657",
    "serverPathVersion" : "v1"
  }
}

5. File API

5.1. PreSigned URL ๋ฐœ๊ธ‰

  • S3 ์—…๋กœ๋“œ์šฉ PreSigned URL์„ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฐœ๊ธ‰๋œ URL์€ ์ง€์ •๋œ ์‹œ๊ฐ„(๊ธฐ๋ณธ 5๋ถ„) ๋™์•ˆ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.

  • ์—ฌ๋Ÿฌ ๊ฐœ์˜ URL์„ ํ•œ ๋ฒˆ์— ๋ฐœ๊ธ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

GET /admin/api/v1/s3/presign-url

์š”์ฒญ ํ—ค๋”

Name Description

Authorization

Bearer ์•ก์„ธ์Šค ํ† ํฐ

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Parameter Description

rootPath

์—…๋กœ๋“œ ๊ฒฝ๋กœ (์˜ˆ: admin/banner, admin/alcohol)

uploadSize

๋ฐœ๊ธ‰ํ•  URL ๊ฐœ์ˆ˜

contentType

์—…๋กœ๋“œ ํŒŒ์ผ์˜ Content-Type. ํ—ˆ์šฉ ๋ชฉ๋ก: image/jpeg, image/png, image/webp, image/gif, image/svg+xml, video/mp4, application/pdf. ์—…๋กœ๋“œ(PUT) ์š”์ฒญ ์‹œ ๋™์ผํ•œ Content-Type ํ—ค๋” ํ•„์š”

GET /s3/presign-url?rootPath=admin%2Fbanner&uploadSize=2&contentType=image%2Fjpeg HTTP/1.1
Authorization: Bearer test_access_token
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data.bucketName

String

S3 ๋ฒ„ํ‚ท๋ช…

data.expiryTime

Number

URL ๋งŒ๋ฃŒ ์‹œ๊ฐ„ (๋ถ„)

data.uploadSize

Number

๋ฐœ๊ธ‰๋œ URL ๊ฐœ์ˆ˜

data.imageUploadInfo[].order

Number

์ด๋ฏธ์ง€ ์ˆœ์„œ

data.imageUploadInfo[].viewUrl

String

์ด๋ฏธ์ง€ ์กฐํšŒ URL (CDN)

data.imageUploadInfo[].uploadUrl

String

์ด๋ฏธ์ง€ ์—…๋กœ๋“œ URL (PreSigned)

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 777

{
  "success" : true,
  "code" : 200,
  "data" : {
    "bucketName" : "bottlenote-bucket",
    "uploadSize" : 2,
    "expiryTime" : 5,
    "imageUploadInfo" : [ {
      "order" : 1,
      "viewUrl" : "https://cdn.example.com/admin/banner/uuid-1.jpg",
      "uploadUrl" : "https://s3.ap-northeast-2.amazonaws.com/bucket/admin/banner/uuid-1.jpg?X-Amz-Algorithm=..."
    }, {
      "order" : 2,
      "viewUrl" : "https://cdn.example.com/admin/banner/uuid-2.jpg",
      "uploadUrl" : "https://s3.ap-northeast-2.amazonaws.com/bucket/admin/banner/uuid-2.jpg?X-Amz-Algorithm=..."
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:24.771985802",
    "serverPathVersion" : "v1"
  }
}

6. Tasting Tag API

6.1. ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ๋ชฉ๋ก ์กฐํšŒ

  • ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ๋ชฉ๋ก์„ ํŽ˜์ด์ง€๋„ค์ด์…˜์œผ๋กœ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ํ‚ค์›Œ๋“œ๋กœ ํ•œ๊ธ€๋ช…/์˜๋ฌธ๋ช… ๊ฒ€์ƒ‰์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/tasting-tags

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Parameter Description

keyword

๊ฒ€์ƒ‰์–ด (ํ•œ๊ธ€๋ช…/์˜๋ฌธ๋ช…)

page

ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ (0๋ถ€ํ„ฐ ์‹œ์ž‘, ๊ธฐ๋ณธ๊ฐ’: 0)

size

ํŽ˜์ด์ง€ ํฌ๊ธฐ (๊ธฐ๋ณธ๊ฐ’: 20)

sortOrder

์ •๋ ฌ ๋ฐฉํ–ฅ (ASC/DESC, ๊ธฐ๋ณธ๊ฐ’: ASC)

$ curl 'http://localhost:8080/tasting-tags?keyword=&page=0&size=20&sortOrder=ASC' -i -X GET
GET /tasting-tags?keyword=&page=0&size=20&sortOrder=ASC HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

include::example$/admin/tasting-tags/list/response-fields.adoc[]๋ฃฐ

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 924

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "id" : 1,
    "korName" : "ํƒœ๊ทธ1",
    "engName" : "Tag1",
    "icon" : "icon1.png",
    "description" : "ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์„ค๋ช… 1",
    "parent" : null,
    "children" : null
  }, {
    "id" : 2,
    "korName" : "ํƒœ๊ทธ2",
    "engName" : "Tag2",
    "icon" : "icon2.png",
    "description" : "ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์„ค๋ช… 2",
    "parent" : null,
    "children" : null
  }, {
    "id" : 3,
    "korName" : "ํƒœ๊ทธ3",
    "engName" : "Tag3",
    "icon" : "icon3.png",
    "description" : "ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์„ค๋ช… 3",
    "parent" : null,
    "children" : null
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:22.013136375",
    "size" : 3,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 3
  }
}

6.2. ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์ƒ์„ธ ์กฐํšŒ

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

  • ๋ถ€๋ชจ/์ž์‹ ํƒœ๊ทธ ์ •๋ณด ๋ฐ ์—ฐ๊ฒฐ๋œ ์ˆ  ๋ชฉ๋ก์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/tasting-tags/{tagId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 6. /tasting-tags/{tagId}
Parameter Description

tagId

ํƒœ๊ทธ ID

$ curl 'http://localhost:8080/tasting-tags/1' -i -X GET
GET /tasting-tags/1 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

ํƒœ๊ทธ ์ƒ์„ธ ์ •๋ณด

data.tag

Object

ํƒœ๊ทธ ํŠธ๋ฆฌ ์ •๋ณด

data.tag.id

Number

ํƒœ๊ทธ ID

data.tag.korName

String

ํƒœ๊ทธ ํ•œ๊ธ€๋ช…

data.tag.engName

String

ํƒœ๊ทธ ์˜๋ฌธ๋ช…

data.tag.icon

String

์•„์ด์ฝ˜ (Base64)

data.tag.description

String

์„ค๋ช…

data.tag.parent

Object

๋ถ€๋ชจ ํƒœ๊ทธ (๋งˆํŠธ๋ฃŒ์‹œ์นด ๊ตฌ์กฐ)

data.tag.children

Array

์ž์‹ ํƒœ๊ทธ ๋ชฉ๋ก (๋งˆํŠธ๋ฃŒ์‹œ์นด ๊ตฌ์กฐ)

data.tag.children[].id

Number

์ž์‹ ํƒœ๊ทธ ID

data.tag.children[].korName

String

์ž์‹ ํƒœ๊ทธ ํ•œ๊ธ€๋ช…

data.tag.children[].engName

String

์ž์‹ ํƒœ๊ทธ ์˜๋ฌธ๋ช…

data.tag.children[].icon

String

์ž์‹ ํƒœ๊ทธ ์•„์ด์ฝ˜

data.tag.children[].description

String

์ž์‹ ํƒœ๊ทธ ์„ค๋ช…

data.tag.children[].parent

Object

์†์ž์˜ ๋ถ€๋ชจ (null)

data.tag.children[].children

Array

์†์ž ํƒœ๊ทธ ๋ชฉ๋ก

data.alcohols

Array

์—ฐ๊ฒฐ๋œ ์œ„์Šคํ‚ค ๋ชฉ๋ก

data.alcohols[].alcoholId

Number

์œ„์Šคํ‚ค ID

data.alcohols[].korName

String

์œ„์Šคํ‚ค ํ•œ๊ธ€๋ช…

data.alcohols[].engName

String

์œ„์Šคํ‚ค ์˜๋ฌธ๋ช…

data.alcohols[].korCategoryName

String

์นดํ…Œ๊ณ ๋ฆฌ ํ•œ๊ธ€๋ช…

data.alcohols[].engCategoryName

String

์นดํ…Œ๊ณ ๋ฆฌ ์˜๋ฌธ๋ช…

data.alcohols[].imageUrl

String

์ด๋ฏธ์ง€ URL

data.alcohols[].createdAt

String

์ƒ์„ฑ์ผ์‹œ

data.alcohols[].modifiedAt

String

์ˆ˜์ •์ผ์‹œ

data.alcohols[].deletedAt

String

์‚ญ์ œ์ผ์‹œ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1058

{
  "success" : true,
  "code" : 200,
  "data" : {
    "tag" : {
      "id" : 1,
      "korName" : "๋ฐ”๋‹๋ผ",
      "engName" : "Vanilla",
      "icon" : "base64icon",
      "description" : "๋ฐ”๋‹๋ผ ํ–ฅ",
      "parent" : null,
      "children" : [ {
        "id" : 2,
        "korName" : "๋ฐ”๋‹๋ผ ํฌ๋ฆผ",
        "engName" : "Vanilla Cream",
        "icon" : null,
        "description" : "๋ฐ”๋‹๋ผ ํฌ๋ฆผ ํ–ฅ",
        "parent" : null,
        "children" : [ ]
      } ]
    },
    "alcohols" : [ {
      "alcoholId" : 1,
      "korName" : "๊ธ€๋ Œํ”ผ๋”• 12๋…„",
      "engName" : "Glenfiddich 12",
      "korCategoryName" : "์‹ฑ๊ธ€๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "imageUrl" : "https://example.com/image.jpg",
      "createdAt" : "2024-01-01T00:00:00",
      "modifiedAt" : "2024-06-01T00:00:00",
      "deletedAt" : null
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:21.940156174",
    "serverPathVersion" : "v1"
  }
}

6.3. ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์ƒ์„ฑ

  • ์ƒˆ๋กœ์šด ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • parentId๋ฅผ ์ง€์ •ํ•˜์—ฌ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

POST /admin/api/v1/tasting-tags

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

korName

String

ํƒœ๊ทธ ํ•œ๊ธ€๋ช… (ํ•„์ˆ˜)

engName

String

ํƒœ๊ทธ ์˜๋ฌธ๋ช… (ํ•„์ˆ˜)

icon

String

์•„์ด์ฝ˜ (Base64)

description

String

์„ค๋ช…

parentId

Null

๋ถ€๋ชจ ํƒœ๊ทธ ID (null์ด๋ฉด ๋ฃจํŠธ)

$ curl 'http://localhost:8080/tasting-tags' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "korName" : "๋ฐ”๋‹๋ผ",
  "engName" : "Vanilla",
  "icon" : "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
  "description" : "๋ฐ”๋‹๋ผ ํ–ฅ",
  "parentId" : null
}'
POST /tasting-tags HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 221
Host: localhost:8080

{
  "korName" : "๋ฐ”๋‹๋ผ",
  "engName" : "Vanilla",
  "icon" : "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
  "description" : "๋ฐ”๋‹๋ผ ํ–ฅ",
  "parentId" : null
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์ƒ์„ฑ๋œ ํƒœ๊ทธ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 408

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "TASTING_TAG_CREATED",
    "message" : "ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ๊ฐ€ ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:21"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:21.858811335",
    "serverPathVersion" : "v1"
  }
}

6.4. ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์ˆ˜์ •

  • ๊ธฐ์กด ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์ •๋ณด๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

PUT /admin/api/v1/tasting-tags/{tagId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 7. /tasting-tags/{tagId}
Parameter Description

tagId

ํƒœ๊ทธ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

korName

String

ํƒœ๊ทธ ํ•œ๊ธ€๋ช… (ํ•„์ˆ˜)

engName

String

ํƒœ๊ทธ ์˜๋ฌธ๋ช… (ํ•„์ˆ˜)

icon

String

์•„์ด์ฝ˜ (Base64)

description

String

์„ค๋ช…

parentId

Number

๋ถ€๋ชจ ํƒœ๊ทธ ID

$ curl 'http://localhost:8080/tasting-tags/1' -i -X PUT \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "korName" : "๋ฐ”๋‹๋ผ ์ˆ˜์ •",
  "engName" : "Vanilla Updated",
  "icon" : "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
  "description" : "์ˆ˜์ •๋œ ์„ค๋ช…"
}'
PUT /tasting-tags/1 HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 218
Host: localhost:8080

{
  "korName" : "๋ฐ”๋‹๋ผ ์ˆ˜์ •",
  "engName" : "Vanilla Updated",
  "icon" : "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
  "description" : "์ˆ˜์ •๋œ ์„ค๋ช…"
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์ˆ˜์ •๋œ ํƒœ๊ทธ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 408

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "TASTING_TAG_UPDATED",
    "message" : "ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ๊ฐ€ ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:22"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:22.123286378",
    "serverPathVersion" : "v1"
  }
}

6.5. ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์‚ญ์ œ

  • ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

  • ์ž์‹ ํƒœ๊ทธ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์‚ญ์ œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

DELETE /admin/api/v1/tasting-tags/{tagId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 8. /tasting-tags/{tagId}
Parameter Description

tagId

ํƒœ๊ทธ ID

$ curl 'http://localhost:8080/tasting-tags/1' -i -X DELETE
DELETE /tasting-tags/1 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์‚ญ์ œ๋œ ํƒœ๊ทธ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 407

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "TASTING_TAG_DELETED",
    "message" : "ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ๊ฐ€ ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:21"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:21.90514037",
    "serverPathVersion" : "v1"
  }
}

6.6. ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์—ฐ๊ฒฐ

  • ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ์— ์ˆ ์„ ๋ฒŒํฌ๋กœ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

POST /admin/api/v1/tasting-tags/{tagId}/alcohols

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 9. /tasting-tags/{tagId}/alcohols
Parameter Description

tagId

ํƒœ๊ทธ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

alcoholIds

Array

์—ฐ๊ฒฐํ•  ์œ„์Šคํ‚ค ID ๋ชฉ๋ก

$ curl 'http://localhost:8080/tasting-tags/1/alcohols' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "alcoholIds" : [ 1, 2, 3 ]
}'
POST /tasting-tags/1/alcohols HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 32
Host: localhost:8080

{
  "alcoholIds" : [ 1, 2, 3 ]
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

ํƒœ๊ทธ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 403

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "TASTING_TAG_ALCOHOL_ADDED",
    "message" : "์œ„์Šคํ‚ค๊ฐ€ ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:22"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:22.08892647",
    "serverPathVersion" : "v1"
  }
}

6.7. ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์—ฐ๊ฒฐ ํ•ด์ œ

  • ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ์—์„œ ์ˆ  ์—ฐ๊ฒฐ์„ ๋ฒŒํฌ๋กœ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

DELETE /admin/api/v1/tasting-tags/{tagId}/alcohols

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 10. /tasting-tags/{tagId}/alcohols
Parameter Description

tagId

ํƒœ๊ทธ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

alcoholIds

Array

ํ•ด์ œํ•  ์œ„์Šคํ‚ค ID ๋ชฉ๋ก

$ curl 'http://localhost:8080/tasting-tags/1/alcohols' -i -X DELETE \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "alcoholIds" : [ 1, 2 ]
}'
DELETE /tasting-tags/1/alcohols HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 29
Host: localhost:8080

{
  "alcoholIds" : [ 1, 2 ]
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

ํƒœ๊ทธ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 412

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "TASTING_TAG_ALCOHOL_REMOVED",
    "message" : "์œ„์Šคํ‚ค ์—ฐ๊ฒฐ์ด ํ•ด์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:22"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:22.06531487",
    "serverPathVersion" : "v1"
  }
}

7. Reference API

7.1. ์ง€์—ญ ๋ชฉ๋ก ์กฐํšŒ

  • ์ „์ฒด ์ง€์—ญ(๊ตญ๊ฐ€) ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ์ˆ ์˜ ์›์‚ฐ์ง€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/regions

์š”์ฒญ

$ curl 'http://localhost:8080/regions?keyword=&page=0&size=20&sortOrder=ASC' -i -X GET
GET /regions?keyword=&page=0&size=20&sortOrder=ASC HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Array

์ง€์—ญ ๋ชฉ๋ก

data[].id

Number

์ง€์—ญ ID

data[].korName

String

๊ตญ๊ฐ€ ํ•œ๊ธ€๋ช…

data[].engName

String

๊ตญ๊ฐ€ ์˜๋ฌธ๋ช…

data[].continent

String

๋Œ€๋ฅ™

data[].description

String

์„ค๋ช…

data[].createdAt

String

์ƒ์„ฑ์ผ์‹œ

data[].modifiedAt

String

์ˆ˜์ •์ผ์‹œ

data[].parentId

Number

์ƒ์œ„ ์ง€์—ญ ID

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.page

Number

ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ

meta.size

Number

ํŽ˜์ด์ง€ ํฌ๊ธฐ

meta.totalElements

Number

์ „์ฒด ์š”์†Œ ์ˆ˜

meta.totalPages

Number

์ „์ฒด ํŽ˜์ด์ง€ ์ˆ˜

meta.hasNext

Boolean

๋‹ค์Œ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1100

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "id" : 1,
    "korName" : "์Šค์ฝ”ํ‹€๋žœ๋“œ",
    "engName" : "Scotland",
    "continent" : "์œ ๋Ÿฝ",
    "description" : "์ง€์—ญ ์„ค๋ช… 1",
    "createdAt" : "2024-01-01T00:00:00",
    "modifiedAt" : "2024-06-01T00:00:00",
    "parentId" : null
  }, {
    "id" : 2,
    "korName" : "์•„์ผ๋žœ๋“œ",
    "engName" : "Ireland",
    "continent" : "์œ ๋Ÿฝ",
    "description" : "์ง€์—ญ ์„ค๋ช… 2",
    "createdAt" : "2024-01-02T00:00:00",
    "modifiedAt" : "2024-06-02T00:00:00",
    "parentId" : null
  }, {
    "id" : 3,
    "korName" : "์ผ๋ณธ",
    "engName" : "Japan",
    "continent" : "์•„์‹œ์•„",
    "description" : "์ง€์—ญ ์„ค๋ช… 3",
    "createdAt" : "2024-01-03T00:00:00",
    "modifiedAt" : "2024-06-03T00:00:00",
    "parentId" : null
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:21.261783701",
    "size" : 3,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 3
  }
}

7.2. ์ฆ๋ฅ˜์†Œ ๋ชฉ๋ก ์กฐํšŒ

  • ์ „์ฒด ์ฆ๋ฅ˜์†Œ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ์ˆ ์„ ์ƒ์‚ฐํ•˜๋Š” ์ฆ๋ฅ˜์†Œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/distilleries

์š”์ฒญ

$ curl 'http://localhost:8080/distilleries?keyword=&page=0&size=20&sortOrder=ASC' -i -X GET
GET /distilleries?keyword=&page=0&size=20&sortOrder=ASC HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Array

์ฆ๋ฅ˜์†Œ ๋ชฉ๋ก

data[].id

Number

์ฆ๋ฅ˜์†Œ ID

data[].korName

String

์ฆ๋ฅ˜์†Œ ํ•œ๊ธ€๋ช…

data[].engName

String

์ฆ๋ฅ˜์†Œ ์˜๋ฌธ๋ช…

data[].logoImgUrl

String

๋กœ๊ณ  ์ด๋ฏธ์ง€ URL

data[].createdAt

String

์ƒ์„ฑ์ผ์‹œ

data[].modifiedAt

String

์ˆ˜์ •์ผ์‹œ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.page

Number

ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ

meta.size

Number

ํŽ˜์ด์ง€ ํฌ๊ธฐ

meta.totalElements

Number

์ „์ฒด ์š”์†Œ ์ˆ˜

meta.totalPages

Number

์ „์ฒด ํŽ˜์ด์ง€ ์ˆ˜

meta.hasNext

Boolean

๋‹ค์Œ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 990

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "id" : 1,
    "korName" : "๊ธ€๋ Œํ”ผ๋”•",
    "engName" : "Glenfiddich",
    "logoImgUrl" : "https://example.com/logo1.png",
    "createdAt" : "2024-01-01T00:00:00",
    "modifiedAt" : "2024-06-01T00:00:00"
  }, {
    "id" : 2,
    "korName" : "๋งฅ์บ˜๋ž€",
    "engName" : "Macallan",
    "logoImgUrl" : "https://example.com/logo2.png",
    "createdAt" : "2024-01-02T00:00:00",
    "modifiedAt" : "2024-06-02T00:00:00"
  }, {
    "id" : 3,
    "korName" : "์•ผ๋งˆ์žํ‚ค",
    "engName" : "Yamazaki",
    "logoImgUrl" : "https://example.com/logo3.png",
    "createdAt" : "2024-01-03T00:00:00",
    "modifiedAt" : "2024-06-03T00:00:00"
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:20.719876052",
    "size" : 3,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 3
  }
}

8. Curation API

8.1. ํ๋ ˆ์ด์…˜ ๋ชฉ๋ก ์กฐํšŒ

  • ํ๋ ˆ์ด์…˜ ๋ชฉ๋ก์„ ํŽ˜์ด์ง€๋„ค์ด์…˜์œผ๋กœ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ํ‚ค์›Œ๋“œ ๋ฐ ํ™œ์„ฑํ™” ์ƒํƒœ๋กœ ํ•„ํ„ฐ๋ง์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/curations

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Parameter Description

keyword

๊ฒ€์ƒ‰์–ด (ํ๋ ˆ์ด์…˜๋ช…)

isActive

ํ™œ์„ฑํ™” ์ƒํƒœ ํ•„ํ„ฐ (true/false/null)

page

ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ (0๋ถ€ํ„ฐ ์‹œ์ž‘, ๊ธฐ๋ณธ๊ฐ’: 0)

size

ํŽ˜์ด์ง€ ํฌ๊ธฐ (๊ธฐ๋ณธ๊ฐ’: 20)

$ curl 'http://localhost:8080/curations?keyword=&isActive=true&page=0&size=20' -i -X GET
GET /curations?keyword=&isActive=true&page=0&size=20 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data[]

Array

ํ๋ ˆ์ด์…˜ ๋ชฉ๋ก

data[].id

Number

ํ๋ ˆ์ด์…˜ ID

data[].name

String

ํ๋ ˆ์ด์…˜๋ช…

data[].alcoholCount

Number

ํฌํ•จ๋œ ์œ„์Šคํ‚ค ์ˆ˜

data[].displayOrder

Number

๋…ธ์ถœ ์ˆœ์„œ

data[].isActive

Boolean

ํ™œ์„ฑํ™” ์ƒํƒœ

data[].createdAt

String

์ƒ์„ฑ์ผ์‹œ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.page

Number

ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ

meta.size

Number

ํŽ˜์ด์ง€ ํฌ๊ธฐ

meta.totalElements

Number

์ „์ฒด ์š”์†Œ ์ˆ˜

meta.totalPages

Number

์ „์ฒด ํŽ˜์ด์ง€ ์ˆ˜

meta.hasNext

Boolean

๋‹ค์Œ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 834

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "id" : 1,
    "name" : "ํ๋ ˆ์ด์…˜ 1",
    "alcoholCount" : 2,
    "displayOrder" : 1,
    "isActive" : true,
    "createdAt" : "2024-01-01T00:00:00"
  }, {
    "id" : 2,
    "name" : "ํ๋ ˆ์ด์…˜ 2",
    "alcoholCount" : 4,
    "displayOrder" : 2,
    "isActive" : true,
    "createdAt" : "2024-02-01T00:00:00"
  }, {
    "id" : 3,
    "name" : "ํ๋ ˆ์ด์…˜ 3",
    "alcoholCount" : 6,
    "displayOrder" : 3,
    "isActive" : true,
    "createdAt" : "2024-03-01T00:00:00"
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:24.199658286",
    "size" : 3,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 3
  }
}

8.2. ํ๋ ˆ์ด์…˜ ์ƒ์„ธ ์กฐํšŒ

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

  • ํฌํ•จ๋œ ์œ„์Šคํ‚ค ID ๋ชฉ๋ก์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/curations/{curationId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 11. /curations/{curationId}
Parameter Description

curationId

ํ๋ ˆ์ด์…˜ ID

$ curl 'http://localhost:8080/curations/1' -i -X GET
GET /curations/1 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

ํ๋ ˆ์ด์…˜ ์ƒ์„ธ ์ •๋ณด

data.id

Number

ํ๋ ˆ์ด์…˜ ID

data.name

String

ํ๋ ˆ์ด์…˜๋ช…

data.description

String

์„ค๋ช…

data.coverImageUrl

String

์ปค๋ฒ„ ์ด๋ฏธ์ง€ URL

data.displayOrder

Number

๋…ธ์ถœ ์ˆœ์„œ

data.isActive

Boolean

ํ™œ์„ฑํ™” ์ƒํƒœ

data.alcohols

Array

ํฌํ•จ๋œ ์œ„์Šคํ‚ค ๋ชฉ๋ก

data.alcohols[].alcoholId

Number

์œ„์Šคํ‚ค ID

data.alcohols[].korName

String

ํ•œ๊ธ€๋ช…

data.alcohols[].engName

String

์˜๋ฌธ๋ช…

data.alcohols[].korCategoryName

String

ํ•œ๊ธ€ ์นดํ…Œ๊ณ ๋ฆฌ๋ช…

data.alcohols[].engCategoryName

String

์˜๋ฌธ ์นดํ…Œ๊ณ ๋ฆฌ๋ช…

data.alcohols[].imageUrl

String

์ด๋ฏธ์ง€ URL

data.alcohols[].createdAt

String

์ƒ์„ฑ์ผ์‹œ

data.alcohols[].modifiedAt

String

์ˆ˜์ •์ผ์‹œ

data.alcohols[].deletedAt

String

์‚ญ์ œ์ผ์‹œ

data.createdAt

String

์ƒ์„ฑ์ผ์‹œ

data.modifiedAt

String

์ˆ˜์ •์ผ์‹œ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1627

{
  "success" : true,
  "code" : 200,
  "data" : {
    "id" : 1,
    "name" : "ํ…Œ์ŠคํŠธ ํ๋ ˆ์ด์…˜",
    "description" : "ํ๋ ˆ์ด์…˜ ์„ค๋ช…์ž…๋‹ˆ๋‹ค.",
    "coverImageUrl" : "https://example.com/cover.jpg",
    "displayOrder" : 1,
    "isActive" : true,
    "alcohols" : [ {
      "alcoholId" : 1,
      "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค 1",
      "engName" : "Test Whisky 1",
      "korCategoryName" : "์‹ฑ๊ธ€๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "imageUrl" : "https://example.com/image.jpg",
      "createdAt" : "2024-01-01T00:00:00",
      "modifiedAt" : "2024-06-01T00:00:00",
      "deletedAt" : null
    }, {
      "alcoholId" : 2,
      "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค 2",
      "engName" : "Test Whisky 2",
      "korCategoryName" : "์‹ฑ๊ธ€๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "imageUrl" : "https://example.com/image.jpg",
      "createdAt" : "2024-02-01T00:00:00",
      "modifiedAt" : "2024-07-01T00:00:00",
      "deletedAt" : null
    }, {
      "alcoholId" : 3,
      "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค 3",
      "engName" : "Test Whisky 3",
      "korCategoryName" : "์‹ฑ๊ธ€๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "imageUrl" : "https://example.com/image.jpg",
      "createdAt" : "2024-03-01T00:00:00",
      "modifiedAt" : "2024-08-01T00:00:00",
      "deletedAt" : null
    } ],
    "createdAt" : "2024-01-01T00:00:00",
    "modifiedAt" : "2024-06-01T00:00:00"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:24.14768919",
    "serverPathVersion" : "v1"
  }
}

8.3. ํ๋ ˆ์ด์…˜ ์ƒ์„ฑ

  • ์ƒˆ๋กœ์šด ํ๋ ˆ์ด์…˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • ์œ„์Šคํ‚ค ID ๋ชฉ๋ก์„ ํ•จ๊ป˜ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

POST /admin/api/v1/curations

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

name

String

ํ๋ ˆ์ด์…˜๋ช… (ํ•„์ˆ˜)

description

String

์„ค๋ช…

coverImageUrl

String

์ปค๋ฒ„ ์ด๋ฏธ์ง€ URL

displayOrder

Number

๋…ธ์ถœ ์ˆœ์„œ (๊ธฐ๋ณธ๊ฐ’: 0)

alcoholIds

Array

ํฌํ•จํ•  ์œ„์Šคํ‚ค ID ๋ชฉ๋ก

$ curl 'http://localhost:8080/curations' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "name" : "์ƒˆ ํ๋ ˆ์ด์…˜",
  "description" : "ํ๋ ˆ์ด์…˜ ์„ค๋ช…",
  "coverImageUrl" : "https://example.com/cover.jpg",
  "displayOrder" : 0,
  "alcoholIds" : [ ]
}'
POST /curations HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 171
Host: localhost:8080

{
  "name" : "์ƒˆ ํ๋ ˆ์ด์…˜",
  "description" : "ํ๋ ˆ์ด์…˜ ์„ค๋ช…",
  "coverImageUrl" : "https://example.com/cover.jpg",
  "displayOrder" : 0,
  "alcoholIds" : [ ]
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์ƒ์„ฑ๋œ ํ๋ ˆ์ด์…˜ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 398

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_CREATED",
    "message" : "ํ๋ ˆ์ด์…˜์ด ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:24"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:24.083119285",
    "serverPathVersion" : "v1"
  }
}

8.4. ํ๋ ˆ์ด์…˜ ์ˆ˜์ •

  • ๊ธฐ์กด ํ๋ ˆ์ด์…˜ ์ •๋ณด๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

PUT /admin/api/v1/curations/{curationId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 12. /curations/{curationId}
Parameter Description

curationId

ํ๋ ˆ์ด์…˜ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

name

String

ํ๋ ˆ์ด์…˜๋ช… (ํ•„์ˆ˜)

description

String

์„ค๋ช…

coverImageUrl

String

์ปค๋ฒ„ ์ด๋ฏธ์ง€ URL

displayOrder

Number

๋…ธ์ถœ ์ˆœ์„œ (ํ•„์ˆ˜)

isActive

Boolean

ํ™œ์„ฑํ™” ์ƒํƒœ (ํ•„์ˆ˜)

alcoholIds

Array

ํฌํ•จํ•  ์œ„์Šคํ‚ค ID ๋ชฉ๋ก

$ curl 'http://localhost:8080/curations/1' -i -X PUT \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "name" : "์ˆ˜์ •๋œ ํ๋ ˆ์ด์…˜",
  "description" : "์ˆ˜์ •๋œ ์„ค๋ช…",
  "coverImageUrl" : "https://example.com/updated.jpg",
  "displayOrder" : 1,
  "isActive" : true,
  "alcoholIds" : [ 1, 2 ]
}'
PUT /curations/1 HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 202
Host: localhost:8080

{
  "name" : "์ˆ˜์ •๋œ ํ๋ ˆ์ด์…˜",
  "description" : "์ˆ˜์ •๋œ ์„ค๋ช…",
  "coverImageUrl" : "https://example.com/updated.jpg",
  "displayOrder" : 1,
  "isActive" : true,
  "alcoholIds" : [ 1, 2 ]
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์ˆ˜์ •๋œ ํ๋ ˆ์ด์…˜ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 398

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_UPDATED",
    "message" : "ํ๋ ˆ์ด์…˜์ด ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:24"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:24.296623245",
    "serverPathVersion" : "v1"
  }
}

8.5. ํ๋ ˆ์ด์…˜ ์‚ญ์ œ

  • ํ๋ ˆ์ด์…˜์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

DELETE /admin/api/v1/curations/{curationId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 13. /curations/{curationId}
Parameter Description

curationId

ํ๋ ˆ์ด์…˜ ID

$ curl 'http://localhost:8080/curations/1' -i -X DELETE
DELETE /curations/1 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์‚ญ์ œ๋œ ํ๋ ˆ์ด์…˜ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 397

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_DELETED",
    "message" : "ํ๋ ˆ์ด์…˜์ด ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:24"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:24.12348378",
    "serverPathVersion" : "v1"
  }
}

8.6. ํ๋ ˆ์ด์…˜ ํ™œ์„ฑํ™” ์ƒํƒœ ๋ณ€๊ฒฝ

  • ํ๋ ˆ์ด์…˜์˜ ํ™œ์„ฑํ™” ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

  • ๋น„ํ™œ์„ฑํ™”๋œ ํ๋ ˆ์ด์…˜์€ ํด๋ผ์ด์–ธํŠธ์— ๋…ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

PATCH /admin/api/v1/curations/{curationId}/status

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 14. /curations/{curationId}/status
Parameter Description

curationId

ํ๋ ˆ์ด์…˜ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

isActive

Boolean

ํ™œ์„ฑํ™” ์ƒํƒœ (ํ•„์ˆ˜)

$ curl 'http://localhost:8080/curations/1/status' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "isActive" : false
}'
PATCH /curations/1/status HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 24
Host: localhost:8080

{
  "isActive" : false
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

ํ๋ ˆ์ด์…˜ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 421

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_STATUS_UPDATED",
    "message" : "ํ๋ ˆ์ด์…˜ ํ™œ์„ฑํ™” ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:24"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:24.36084034",
    "serverPathVersion" : "v1"
  }
}

8.7. ํ๋ ˆ์ด์…˜ ๋…ธ์ถœ ์ˆœ์„œ ๋ณ€๊ฒฝ

  • ํ๋ ˆ์ด์…˜์˜ ๋…ธ์ถœ ์ˆœ์„œ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

  • ์ˆซ์ž๊ฐ€ ์ž‘์„์ˆ˜๋ก ๋จผ์ € ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

PATCH /admin/api/v1/curations/{curationId}/display-order

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 15. /curations/{curationId}/display-order
Parameter Description

curationId

ํ๋ ˆ์ด์…˜ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

displayOrder

Number

๋…ธ์ถœ ์ˆœ์„œ (0 ์ด์ƒ, ํ•„์ˆ˜)

$ curl 'http://localhost:8080/curations/1/display-order' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "displayOrder" : 5
}'
PATCH /curations/1/display-order HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 24
Host: localhost:8080

{
  "displayOrder" : 5
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

ํ๋ ˆ์ด์…˜ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 426

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_DISPLAY_ORDER_UPDATED",
    "message" : "ํ๋ ˆ์ด์…˜ ๋…ธ์ถœ ์ˆœ์„œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:24"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:24.330518694",
    "serverPathVersion" : "v1"
  }
}

8.8. ํ๋ ˆ์ด์…˜์— ์œ„์Šคํ‚ค ์ถ”๊ฐ€

  • ํ๋ ˆ์ด์…˜์— ์œ„์Šคํ‚ค๋ฅผ ๋ฒŒํฌ๋กœ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

POST /admin/api/v1/curations/{curationId}/alcohols

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 16. /curations/{curationId}/alcohols
Parameter Description

curationId

ํ๋ ˆ์ด์…˜ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

alcoholIds

Array

์ถ”๊ฐ€ํ•  ์œ„์Šคํ‚ค ID ๋ชฉ๋ก (ํ•„์ˆ˜)

$ curl 'http://localhost:8080/curations/1/alcohols' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "alcoholIds" : [ 1, 2, 3 ]
}'
POST /curations/1/alcohols HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 32
Host: localhost:8080

{
  "alcoholIds" : [ 1, 2, 3 ]
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

ํ๋ ˆ์ด์…˜ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 416

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_ALCOHOL_ADDED",
    "message" : "ํ๋ ˆ์ด์…˜์— ์œ„์Šคํ‚ค๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:24"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:24.26161245",
    "serverPathVersion" : "v1"
  }
}

8.9. ํ๋ ˆ์ด์…˜์—์„œ ์œ„์Šคํ‚ค ์ œ๊ฑฐ

  • ํ๋ ˆ์ด์…˜์—์„œ ํŠน์ • ์œ„์Šคํ‚ค๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

DELETE /admin/api/v1/curations/{curationId}/alcohols/{alcoholId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 17. /curations/{curationId}/alcohols/{alcoholId}
Parameter Description

curationId

ํ๋ ˆ์ด์…˜ ID

alcoholId

์ œ๊ฑฐํ•  ์œ„์Šคํ‚ค ID

$ curl 'http://localhost:8080/curations/1/alcohols/5' -i -X DELETE
DELETE /curations/1/alcohols/5 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

ํ๋ ˆ์ด์…˜ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 421

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_ALCOHOL_REMOVED",
    "message" : "ํ๋ ˆ์ด์…˜์—์„œ ์œ„์Šคํ‚ค๊ฐ€ ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:24"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:24.24026806",
    "serverPathVersion" : "v1"
  }
}

9. Users API

9.1. ์œ ์ € ๋ชฉ๋ก ์กฐํšŒ

  • ์•ฑ ์‚ฌ์šฉ์ž(User) ๋ชฉ๋ก์„ ํŽ˜์ด์ง€๋„ค์ด์…˜์œผ๋กœ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ํ‚ค์›Œ๋“œ(๋‹‰๋„ค์ž„/์ด๋ฉ”์ผ), ์ƒํƒœ(ACTIVE/DELETED)๋กœ ํ•„ํ„ฐ๋ง์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • ํ™œ๋™ ์ง€ํ‘œ(๋ฆฌ๋ทฐ ์ˆ˜, ๋ณ„์  ์ˆ˜, ์ฐœ ์ˆ˜)๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

GET /admin/api/v1/users

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Parameter Description

keyword

๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ (๋‹‰๋„ค์ž„/์ด๋ฉ”์ผ)

status

์œ ์ € ์ƒํƒœ ํ•„ํ„ฐ (ACTIVE/DELETED)

sortType

์ •๋ ฌ ๊ธฐ์ค€ (CREATED_AT/NICK_NAME/EMAIL/RATING_COUNT/REVIEW_COUNT, ๊ธฐ๋ณธ๊ฐ’: CREATED_AT)

sortOrder

์ •๋ ฌ ๋ฐฉํ–ฅ (ASC/DESC, ๊ธฐ๋ณธ๊ฐ’: DESC)

page

ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ (0๋ถ€ํ„ฐ ์‹œ์ž‘, ๊ธฐ๋ณธ๊ฐ’: 0)

size

ํŽ˜์ด์ง€ ํฌ๊ธฐ (๊ธฐ๋ณธ๊ฐ’: 20)

$ curl 'http://localhost:8080/users?keyword=&status=ACTIVE&sortType=CREATED_AT&sortOrder=DESC&page=0&size=20' -i -X GET
GET /users?keyword=&status=ACTIVE&sortType=CREATED_AT&sortOrder=DESC&page=0&size=20 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data[]

Array

์œ ์ € ๋ชฉ๋ก

data[].userId

Number

์œ ์ € ID

data[].email

String

์ด๋ฉ”์ผ

data[].nickName

String

๋‹‰๋„ค์ž„

data[].imageUrl

Varies

ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

data[].role

String

์œ ์ € ๊ถŒํ•œ (ROLE_USER/ROLE_ADMIN)

data[].status

String

์œ ์ € ์ƒํƒœ (ACTIVE/DELETED)

data[].socialType

Array

์†Œ์…œ ๋กœ๊ทธ์ธ ํƒ€์ž… ๋ชฉ๋ก (KAKAO/NAVER/GOOGLE/APPLE)

data[].reviewCount

Number

๋ฆฌ๋ทฐ ์ˆ˜

data[].ratingCount

Number

๋ณ„์  ์ˆ˜

data[].picksCount

Number

์ฐœ ์ˆ˜

data[].createAt

String

๊ฐ€์ž…์ผ

data[].lastLoginAt

Varies

์ตœ์ข… ๋กœ๊ทธ์ธ์ผ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.page

Number

ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ

meta.size

Number

ํŽ˜์ด์ง€ ํฌ๊ธฐ

meta.totalElements

Number

์ „์ฒด ์š”์†Œ ์ˆ˜

meta.totalPages

Number

์ „์ฒด ํŽ˜์ด์ง€ ์ˆ˜

meta.hasNext

Boolean

๋‹ค์Œ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1059

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "userId" : 1,
    "email" : "user1@example.com",
    "nickName" : "์‚ฌ์šฉ์ž1",
    "imageUrl" : "https://img.example.com/1.jpg",
    "role" : "ROLE_USER",
    "status" : "ACTIVE",
    "socialType" : [ "KAKAO" ],
    "reviewCount" : 5,
    "ratingCount" : 3,
    "picksCount" : 2,
    "createAt" : "2025-01-15T10:00:00",
    "lastLoginAt" : "2026-04-01T14:30:00"
  }, {
    "userId" : 2,
    "email" : "user2@example.com",
    "nickName" : "์‚ฌ์šฉ์ž2",
    "imageUrl" : null,
    "role" : "ROLE_USER",
    "status" : "ACTIVE",
    "socialType" : [ "GOOGLE", "APPLE" ],
    "reviewCount" : 0,
    "ratingCount" : 1,
    "picksCount" : 0,
    "createAt" : "2025-06-20T09:00:00",
    "lastLoginAt" : null
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:25.596953928",
    "size" : 2,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 2
  }
}

10. Banner API

10.1. ๋ฐฐ๋„ˆ ๋ชฉ๋ก ์กฐํšŒ

  • ๋ฐฐ๋„ˆ ๋ชฉ๋ก์„ ํŽ˜์ด์ง€๋„ค์ด์…˜์œผ๋กœ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ํ‚ค์›Œ๋“œ, ํ™œ์„ฑํ™” ์ƒํƒœ, ๋ฐฐ๋„ˆ ์œ ํ˜•์œผ๋กœ ํ•„ํ„ฐ๋ง์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

BannerType (๋ฐฐ๋„ˆ ์œ ํ˜•)

๊ฐ’ ์„ค๋ช…

CURATION

ํ๋ ˆ์ด์…˜

AD

๊ด‘๊ณ 

SURVEY

์„ค๋ฌธ์ง€

PARTNERSHIP

์ œํœด

ETC

๊ธฐํƒ€

TextPosition (ํ…์ŠคํŠธ ์œ„์น˜)

๊ฐ’ ์„ค๋ช…

LT

์ขŒ์ƒ๋‹จ

LB

์ขŒํ•˜๋‹จ

RT

์šฐ์ƒ๋‹จ

RB

์šฐํ•˜๋‹จ

CENTER

์ค‘์•™

GET /admin/api/v1/banners

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Parameter Description

keyword

๊ฒ€์ƒ‰์–ด (๋ฐฐ๋„ˆ๋ช…)

isActive

ํ™œ์„ฑํ™” ์ƒํƒœ ํ•„ํ„ฐ (true/false/null)

bannerType

๋ฐฐ๋„ˆ ์œ ํ˜• ํ•„ํ„ฐ (CURATION/AD/SURVEY/PARTNERSHIP/ETC)

page

ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ (0๋ถ€ํ„ฐ ์‹œ์ž‘, ๊ธฐ๋ณธ๊ฐ’: 0)

size

ํŽ˜์ด์ง€ ํฌ๊ธฐ (๊ธฐ๋ณธ๊ฐ’: 20)

$ curl 'http://localhost:8080/banners?keyword=&isActive=true&bannerType=CURATION&page=0&size=20' -i -X GET
GET /banners?keyword=&isActive=true&bannerType=CURATION&page=0&size=20 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data[]

Array

๋ฐฐ๋„ˆ ๋ชฉ๋ก

data[].id

Number

๋ฐฐ๋„ˆ ID

data[].name

String

๋ฐฐ๋„ˆ๋ช…

data[].mediaType

String

๋ฏธ๋””์–ด ์œ ํ˜• (IMAGE, VIDEO). ํ”„๋ก ํŠธ์—”๋“œ์—์„œ img/video ํƒœ๊ทธ ๋ถ„๊ธฐ์šฉ

data[].bannerType

String

๋ฐฐ๋„ˆ ์œ ํ˜•

data[].sortOrder

Number

์ •๋ ฌ ์ˆœ์„œ

data[].isActive

Boolean

ํ™œ์„ฑํ™” ์ƒํƒœ

data[].startDate

Varies

์‹œ์ž‘์ผ์‹œ

data[].endDate

Varies

์ข…๋ฃŒ์ผ์‹œ

data[].createdAt

String

์ƒ์„ฑ์ผ์‹œ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.page

Number

ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ

meta.size

Number

ํŽ˜์ด์ง€ ํฌ๊ธฐ

meta.totalElements

Number

์ „์ฒด ์š”์†Œ ์ˆ˜

meta.totalPages

Number

์ „์ฒด ํŽ˜์ด์ง€ ์ˆ˜

meta.hasNext

Boolean

๋‹ค์Œ ํŽ˜์ด์ง€ ์กด์žฌ ์—ฌ๋ถ€

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 1047

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "id" : 1,
    "name" : "๋ฐฐ๋„ˆ 1",
    "mediaType" : "IMAGE",
    "bannerType" : "CURATION",
    "sortOrder" : 0,
    "isActive" : true,
    "startDate" : null,
    "endDate" : null,
    "createdAt" : "2024-01-01T00:00:00"
  }, {
    "id" : 2,
    "name" : "๋ฐฐ๋„ˆ 2",
    "mediaType" : "IMAGE",
    "bannerType" : "CURATION",
    "sortOrder" : 1,
    "isActive" : true,
    "startDate" : null,
    "endDate" : null,
    "createdAt" : "2024-02-01T00:00:00"
  }, {
    "id" : 3,
    "name" : "๋ฐฐ๋„ˆ 3",
    "mediaType" : "IMAGE",
    "bannerType" : "CURATION",
    "sortOrder" : 2,
    "isActive" : true,
    "startDate" : null,
    "endDate" : null,
    "createdAt" : "2024-03-01T00:00:00"
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:23.468667837",
    "size" : 3,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 3
  }
}

10.2. ๋ฐฐ๋„ˆ ์ƒ์„ธ ์กฐํšŒ

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

GET /admin/api/v1/banners/{bannerId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 18. /banners/{bannerId}
Parameter Description

bannerId

๋ฐฐ๋„ˆ ID

$ curl 'http://localhost:8080/banners/1' -i -X GET
GET /banners/1 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๋ฐฐ๋„ˆ ์ƒ์„ธ ์ •๋ณด

data.id

Number

๋ฐฐ๋„ˆ ID

data.name

String

๋ฐฐ๋„ˆ๋ช…

data.nameFontColor

String

๋ฐฐ๋„ˆ๋ช… ํฐํŠธ ์ƒ‰์ƒ (HEX)

data.descriptionA

String

๋ฐฐ๋„ˆ ์„ค๋ช…A

data.descriptionB

String

๋ฐฐ๋„ˆ ์„ค๋ช…B

data.descriptionFontColor

String

์„ค๋ช… ํฐํŠธ ์ƒ‰์ƒ (HEX)

data.imageUrl

String

์ด๋ฏธ์ง€ URL. [์ฃผ์˜] URL ํ˜•์‹ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์œ ํšจํ•œ URL์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

data.textPosition

String

ํ…์ŠคํŠธ ์œ„์น˜ (RT/CENTER/LB ๋“ฑ)

data.isExternalUrl

Boolean

์™ธ๋ถ€ URL ์—ฌ๋ถ€

data.targetUrl

Varies

์ด๋™ URL. [์ฃผ์˜] URL ํ˜•์‹ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์œ ํšจํ•œ URL์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

data.mediaType

String

๋ฏธ๋””์–ด ์œ ํ˜• (IMAGE, VIDEO). ํ”„๋ก ํŠธ์—”๋“œ์—์„œ img/video ํƒœ๊ทธ ๋ถ„๊ธฐ์šฉ

data.bannerType

String

๋ฐฐ๋„ˆ ์œ ํ˜•

data.sortOrder

Number

์ •๋ ฌ ์ˆœ์„œ

data.startDate

Varies

์‹œ์ž‘์ผ์‹œ

data.endDate

Varies

์ข…๋ฃŒ์ผ์‹œ

data.isActive

Boolean

ํ™œ์„ฑํ™” ์ƒํƒœ

data.createdAt

String

์ƒ์„ฑ์ผ์‹œ

data.modifiedAt

String

์ˆ˜์ •์ผ์‹œ

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 805

{
  "success" : true,
  "code" : 200,
  "data" : {
    "id" : 1,
    "name" : "ํ…Œ์ŠคํŠธ ๋ฐฐ๋„ˆ",
    "nameFontColor" : "#ffffff",
    "descriptionA" : "๋ฐฐ๋„ˆ ์„ค๋ช…A",
    "descriptionB" : "๋ฐฐ๋„ˆ ์„ค๋ช…B",
    "descriptionFontColor" : "#ffffff",
    "imageUrl" : "https://example.com/banner.jpg",
    "textPosition" : "RT",
    "isExternalUrl" : false,
    "targetUrl" : null,
    "mediaType" : "IMAGE",
    "bannerType" : "CURATION",
    "sortOrder" : 0,
    "startDate" : null,
    "endDate" : null,
    "isActive" : true,
    "createdAt" : "2024-01-01T00:00:00",
    "modifiedAt" : "2024-06-01T00:00:00"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:23.426479692",
    "serverPathVersion" : "v1"
  }
}

10.3. ๋ฐฐ๋„ˆ ์ƒ์„ฑ

  • ์ƒˆ๋กœ์šด ๋ฐฐ๋„ˆ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

  • URL ํ˜•์‹ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์œ ํšจํ•œ URL์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

POST /admin/api/v1/banners

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

name

String

๋ฐฐ๋„ˆ๋ช… (ํ•„์ˆ˜)

nameFontColor

String

๋ฐฐ๋„ˆ๋ช… ํฐํŠธ ์ƒ‰์ƒ (HEX, ๊ธฐ๋ณธ๊ฐ’: #ffffff)

descriptionA

String

๋ฐฐ๋„ˆ ์„ค๋ช…A (์ตœ๋Œ€ 50์ž)

descriptionB

String

๋ฐฐ๋„ˆ ์„ค๋ช…B (์ตœ๋Œ€ 50์ž)

descriptionFontColor

String

์„ค๋ช… ํฐํŠธ ์ƒ‰์ƒ (HEX, ๊ธฐ๋ณธ๊ฐ’: #ffffff)

imageUrl

String

์ด๋ฏธ์ง€ URL (ํ•„์ˆ˜). [์ฃผ์˜] URL ํ˜•์‹ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์œ ํšจํ•œ URL์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

textPosition

String

ํ…์ŠคํŠธ ์œ„์น˜ (RT/CENTER/LB ๋“ฑ, ๊ธฐ๋ณธ๊ฐ’: RT)

isExternalUrl

Boolean

์™ธ๋ถ€ URL ์—ฌ๋ถ€ (๊ธฐ๋ณธ๊ฐ’: false)

targetUrl

Varies

์ด๋™ URL (isExternalUrl=true ์‹œ ํ•„์ˆ˜). [์ฃผ์˜] URL ํ˜•์‹ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์œ ํšจํ•œ URL์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

mediaType

String

๋ฏธ๋””์–ด ์œ ํ˜• (IMAGE/VIDEO, ๊ธฐ๋ณธ๊ฐ’: IMAGE). ํ”„๋ก ํŠธ์—”๋“œ์—์„œ img/video ํƒœ๊ทธ ๋ถ„๊ธฐ์šฉ

bannerType

String

๋ฐฐ๋„ˆ ์œ ํ˜• (ํ•„์ˆ˜: CURATION/AD/SURVEY/PARTNERSHIP/ETC)

sortOrder

Number

์ •๋ ฌ ์ˆœ์„œ (0 ์ด์ƒ, ๊ธฐ๋ณธ๊ฐ’: 0)

startDate

Varies

์‹œ์ž‘์ผ์‹œ

endDate

Varies

์ข…๋ฃŒ์ผ์‹œ

$ curl 'http://localhost:8080/banners' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "name" : "์ƒˆ ๋ฐฐ๋„ˆ",
  "nameFontColor" : "#ffffff",
  "descriptionA" : "๋ฐฐ๋„ˆ ์„ค๋ช…A",
  "descriptionB" : "๋ฐฐ๋„ˆ ์„ค๋ช…B",
  "descriptionFontColor" : "#ffffff",
  "imageUrl" : "https://example.com/banner.jpg",
  "textPosition" : "RT",
  "isExternalUrl" : false,
  "targetUrl" : null,
  "mediaType" : "IMAGE",
  "bannerType" : "CURATION",
  "sortOrder" : 0,
  "startDate" : null,
  "endDate" : null
}'
POST /banners HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 408
Host: localhost:8080

{
  "name" : "์ƒˆ ๋ฐฐ๋„ˆ",
  "nameFontColor" : "#ffffff",
  "descriptionA" : "๋ฐฐ๋„ˆ ์„ค๋ช…A",
  "descriptionB" : "๋ฐฐ๋„ˆ ์„ค๋ช…B",
  "descriptionFontColor" : "#ffffff",
  "imageUrl" : "https://example.com/banner.jpg",
  "textPosition" : "RT",
  "isExternalUrl" : false,
  "targetUrl" : null,
  "mediaType" : "IMAGE",
  "bannerType" : "CURATION",
  "sortOrder" : 0,
  "startDate" : null,
  "endDate" : null
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์ƒ์„ฑ๋œ ๋ฐฐ๋„ˆ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 390

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "BANNER_CREATED",
    "message" : "๋ฐฐ๋„ˆ๊ฐ€ ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:23"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:23.359882666",
    "serverPathVersion" : "v1"
  }
}

10.4. ๋ฐฐ๋„ˆ ์ˆ˜์ •

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

PUT /admin/api/v1/banners/{bannerId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 19. /banners/{bannerId}
Parameter Description

bannerId

๋ฐฐ๋„ˆ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

name

String

๋ฐฐ๋„ˆ๋ช… (ํ•„์ˆ˜)

nameFontColor

String

๋ฐฐ๋„ˆ๋ช… ํฐํŠธ ์ƒ‰์ƒ (HEX)

descriptionA

String

๋ฐฐ๋„ˆ ์„ค๋ช…A (์ตœ๋Œ€ 50์ž)

descriptionB

String

๋ฐฐ๋„ˆ ์„ค๋ช…B (์ตœ๋Œ€ 50์ž)

descriptionFontColor

String

์„ค๋ช… ํฐํŠธ ์ƒ‰์ƒ (HEX)

imageUrl

String

์ด๋ฏธ์ง€ URL (ํ•„์ˆ˜). [์ฃผ์˜] URL ํ˜•์‹ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์œ ํšจํ•œ URL์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

textPosition

String

ํ…์ŠคํŠธ ์œ„์น˜ (RT/CENTER/LB ๋“ฑ)

isExternalUrl

Boolean

์™ธ๋ถ€ URL ์—ฌ๋ถ€

targetUrl

Varies

์ด๋™ URL (isExternalUrl=true ์‹œ ํ•„์ˆ˜). [์ฃผ์˜] URL ํ˜•์‹ ๊ฒ€์ฆ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์œ ํšจํ•œ URL์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค

mediaType

String

๋ฏธ๋””์–ด ์œ ํ˜• (IMAGE/VIDEO, ๋ฏธ์ž…๋ ฅ ์‹œ ๊ธฐ์กด ๊ฐ’ ์œ ์ง€). ํ”„๋ก ํŠธ์—”๋“œ์—์„œ img/video ํƒœ๊ทธ ๋ถ„๊ธฐ์šฉ

bannerType

String

๋ฐฐ๋„ˆ ์œ ํ˜• (ํ•„์ˆ˜: CURATION/AD/SURVEY/PARTNERSHIP/ETC)

sortOrder

Number

์ •๋ ฌ ์ˆœ์„œ (0 ์ด์ƒ, ํ•„์ˆ˜)

startDate

Varies

์‹œ์ž‘์ผ์‹œ

endDate

Varies

์ข…๋ฃŒ์ผ์‹œ

isActive

Boolean

ํ™œ์„ฑํ™” ์ƒํƒœ (ํ•„์ˆ˜)

$ curl 'http://localhost:8080/banners/1' -i -X PUT \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "name" : "์ˆ˜์ •๋œ ๋ฐฐ๋„ˆ",
  "nameFontColor" : "#000000",
  "descriptionA" : "์ˆ˜์ •๋œ ์„ค๋ช…A",
  "descriptionB" : "์ˆ˜์ •๋œ ์„ค๋ช…B",
  "descriptionFontColor" : "#000000",
  "imageUrl" : "https://example.com/updated.jpg",
  "textPosition" : "CENTER",
  "isExternalUrl" : false,
  "targetUrl" : null,
  "mediaType" : "IMAGE",
  "bannerType" : "CURATION",
  "sortOrder" : 1,
  "startDate" : null,
  "endDate" : null,
  "isActive" : true
}'
PUT /banners/1 HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 446
Host: localhost:8080

{
  "name" : "์ˆ˜์ •๋œ ๋ฐฐ๋„ˆ",
  "nameFontColor" : "#000000",
  "descriptionA" : "์ˆ˜์ •๋œ ์„ค๋ช…A",
  "descriptionB" : "์ˆ˜์ •๋œ ์„ค๋ช…B",
  "descriptionFontColor" : "#000000",
  "imageUrl" : "https://example.com/updated.jpg",
  "textPosition" : "CENTER",
  "isExternalUrl" : false,
  "targetUrl" : null,
  "mediaType" : "IMAGE",
  "bannerType" : "CURATION",
  "sortOrder" : 1,
  "startDate" : null,
  "endDate" : null,
  "isActive" : true
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์ˆ˜์ •๋œ ๋ฐฐ๋„ˆ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 390

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "BANNER_UPDATED",
    "message" : "๋ฐฐ๋„ˆ๊ฐ€ ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:23"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:23.532852151",
    "serverPathVersion" : "v1"
  }
}

10.5. ๋ฐฐ๋„ˆ ์‚ญ์ œ

  • ๋ฐฐ๋„ˆ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. (๋ฌผ๋ฆฌ ์‚ญ์ œ)

DELETE /admin/api/v1/banners/{bannerId}

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 20. /banners/{bannerId}
Parameter Description

bannerId

๋ฐฐ๋„ˆ ID

$ curl 'http://localhost:8080/banners/1' -i -X DELETE
DELETE /banners/1 HTTP/1.1
Host: localhost:8080

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

์‚ญ์ œ๋œ ๋ฐฐ๋„ˆ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 390

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "BANNER_DELETED",
    "message" : "๋ฐฐ๋„ˆ๊ฐ€ ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:23"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:23.398823329",
    "serverPathVersion" : "v1"
  }
}

10.6. ๋ฐฐ๋„ˆ ํ™œ์„ฑํ™” ์ƒํƒœ ๋ณ€๊ฒฝ

  • ๋ฐฐ๋„ˆ์˜ ํ™œ์„ฑํ™” ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

  • ๋น„ํ™œ์„ฑํ™”๋œ ๋ฐฐ๋„ˆ๋Š” ํด๋ผ์ด์–ธํŠธ์— ๋…ธ์ถœ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

PATCH /admin/api/v1/banners/{bannerId}/status

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 21. /banners/{bannerId}/status
Parameter Description

bannerId

๋ฐฐ๋„ˆ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

isActive

Boolean

ํ™œ์„ฑํ™” ์ƒํƒœ (ํ•„์ˆ˜)

$ curl 'http://localhost:8080/banners/1/status' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "isActive" : false
}'
PATCH /banners/1/status HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 24
Host: localhost:8080

{
  "isActive" : false
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

๋ฐฐ๋„ˆ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 414

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "BANNER_STATUS_UPDATED",
    "message" : "๋ฐฐ๋„ˆ ํ™œ์„ฑํ™” ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:23"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:23.594869493",
    "serverPathVersion" : "v1"
  }
}

10.7. ๋ฐฐ๋„ˆ ์ •๋ ฌ ์ˆœ์„œ ๋ณ€๊ฒฝ

  • ๋ฐฐ๋„ˆ์˜ ์ •๋ ฌ ์ˆœ์„œ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

  • ์ˆซ์ž๊ฐ€ ์ž‘์„์ˆ˜๋ก ๋จผ์ € ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

  • ๋™์ผ ์ˆœ์„œ ์ถฉ๋Œ ์‹œ ๊ธฐ์กด ๋ฐฐ๋„ˆ๋“ค์ด ์ž๋™์œผ๋กœ ๋ฆฌ์˜ค๋”๋ง๋ฉ๋‹ˆ๋‹ค.

PATCH /admin/api/v1/banners/{bannerId}/sort-order

๊ฒฝ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ

Table 22. /banners/{bannerId}/sort-order
Parameter Description

bannerId

๋ฐฐ๋„ˆ ID

์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

sortOrder

Number

์ •๋ ฌ ์ˆœ์„œ (0 ์ด์ƒ, ํ•„์ˆ˜)

$ curl 'http://localhost:8080/banners/1/sort-order' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "sortOrder" : 5
}'
PATCH /banners/1/sort-order HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 21
Host: localhost:8080

{
  "sortOrder" : 5
}

์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ

Path Type Description

success

Boolean

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

์‘๋‹ต ์ฝ”๋“œ

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

๊ฒฐ๊ณผ ๋ฉ”์‹œ์ง€

data.targetId

Number

๋ฐฐ๋„ˆ ID

data.responseAt

String

์‘๋‹ต ์‹œ๊ฐ„

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 415

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "BANNER_SORT_ORDER_UPDATED",
    "message" : "๋ฐฐ๋„ˆ ์ •๋ ฌ ์ˆœ์„œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-04-08 13:53:23"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-04-08T22:53:23.565872614",
    "serverPathVersion" : "v1"
  }
}