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 /v1/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" : "so9UjlTPUTpQe0Buhh66pIeABCiGuFbq",
    "refreshToken" : "gUHtQCCqQIdn6jxUMUQHFVKwpv3rW3xj"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:09.860221286",
    "serverPathVersion" : "v1"
  }
}

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

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

POST /admin/api/v1/auth/refresh

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

Path Type Description

refreshToken

String

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

POST /v1/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" : "FSI4hpFmX8W3atOO7Rr75lOqn8pa1aZY",
    "refreshToken" : "OtauoJweEziJX1kjpZAR7kH0x0nVY5e1"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:09.886586895",
    "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 /v1/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: 379

{
  "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-07-06T01:33:09.82390184",
    "serverPathVersion" : "v1"
  }
}

2.4. ํƒˆํ‡ด

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

DELETE /admin/api/v1/auth/withdraw

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

Name Description

Authorization

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

DELETE /v1/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-07-06T01:33:09.778230037",
    "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/v1/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 /v1/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-07-05T16:33:05.780995547",
    "serverPathVersion" : "v1"
  }
}

3.2. ์ˆ (Alcohol) lookup ์กฐํšŒ

  • ๊ด€๋ฆฌ์ž ์„ ํƒ ์ปดํฌ๋„ŒํŠธ์—์„œ ์‚ฌ์šฉํ•  ํ•ต์‹ฌ ํ•„๋“œ ๊ธฐ๋ฐ˜์˜ ๊ณ ์† ์กฐํšŒ API์ž…๋‹ˆ๋‹ค.

  • ๋ณ„์ , ์ข‹์•„์š”, ๋ฆฌ๋ทฐ ์ˆ˜, ์‚ฌ์šฉ์ž pick ์—ฌ๋ถ€ ๊ฐ™์€ ์ง‘๊ณ„์„ฑ ๋ฐ์ดํ„ฐ๋Š” ํฌํ•จํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

GET /admin/api/v1/alcohols/lookup

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

Parameter Description

keyword

๊ฒ€์ƒ‰์–ด (์ด๋ฆ„, ์นดํ…Œ๊ณ ๋ฆฌ, ์ง€์—ญ, ์ฆ๋ฅ˜์†Œ ๋Œ€์ƒ)

category

์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน ํ•„ํ„ฐ. ALL ๋˜๋Š” ๋ฏธ์ „๋‹ฌ ์‹œ ์ „์ฒด

regionId

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

distilleryId

์ฆ๋ฅ˜์†Œ ID ํ•„ํ„ฐ

cursor

์ปค์„œ ์œ„์น˜ (๊ธฐ๋ณธ๊ฐ’: 0)

pageSize

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

$ curl 'http://localhost:8080/v1/alcohols/lookup?keyword=macallan&category=SINGLE_MALT&regionId=1&distilleryId=10&cursor=0&pageSize=20' -i -X GET
GET /v1/alcohols/lookup?keyword=macallan&category=SINGLE_MALT&regionId=1&distilleryId=10&cursor=0&pageSize=20 HTTP/1.1
Host: localhost:8080

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

Path Type Description

success

Boolean

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

code

Number

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

data

Array

์ˆ  lookup ๋ชฉ๋ก

data[].alcoholId

Number

์ˆ  ID

data[].korName

String

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

data[].engName

String

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

data[].korCategoryName

String

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

data[].engCategoryName

String

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

data[].categoryGroup

String

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

data[].regionId

Number

์ง€์—ญ ID

data[].korRegion

String

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

data[].engRegion

String

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

data[].distilleryId

Number

์ฆ๋ฅ˜์†Œ ID

data[].korDistillery

String

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

data[].engDistillery

String

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

data[].imageUrl

String

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

errors

Array

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

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.pageable

Object

ํŽ˜์ด์ง• ์ •๋ณด

meta.pageable.currentCursor

Number

์กฐํšŒ ์‹œ ๊ธฐ์ค€ ์ปค์„œ

meta.pageable.cursor

Number

๋‹ค์Œ ํŽ˜์ด์ง€ ์ปค์„œ

meta.pageable.pageSize

Number

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

meta.pageable.hasNext

Boolean

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

meta.searchParameters

Object

๊ฒ€์ƒ‰ ์กฐ๊ฑด

meta.searchParameters.keyword

String

๊ฒ€์ƒ‰์–ด

meta.searchParameters.category

String

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

meta.searchParameters.regionId

Number

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

meta.searchParameters.distilleryId

Number

์ฆ๋ฅ˜์†Œ ID ํ•„ํ„ฐ

meta.searchParameters.cursor

Number

์ปค์„œ ์œ„์น˜

meta.searchParameters.pageSize

Number

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

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

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "alcoholId" : 1,
    "korName" : "๋งฅ์บ˜๋ž€ 12๋…„",
    "engName" : "Macallan 12",
    "korCategoryName" : "์‹ฑ๊ธ€๋ชฐํŠธ",
    "engCategoryName" : "Single Malt",
    "categoryGroup" : "SINGLE_MALT",
    "regionId" : 1,
    "korRegion" : "์ŠคํŽ˜์ด์‚ฌ์ด๋“œ",
    "engRegion" : "Speyside",
    "distilleryId" : 10,
    "korDistillery" : "๋งฅ์บ˜๋ž€",
    "engDistillery" : "Macallan",
    "imageUrl" : "https://example.com/alcohol.png"
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:06.800911148",
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 20,
      "pageSize" : 20,
      "hasNext" : false
    },
    "searchParameters" : {
      "keyword" : "macallan",
      "category" : "SINGLE_MALT",
      "regionId" : 1,
      "distilleryId" : 10,
      "cursor" : 0,
      "pageSize" : 20
    },
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

Table 1. /v1/alcohols/{alcoholId}
Parameter Description

alcoholId

์ˆ  ID

$ curl 'http://localhost:8080/v1/alcohols/1' -i -X GET
GET /v1/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-07-06T01:33:06.616235582",
    "serverPathVersion" : "v1"
  }
}

3.4. ์ˆ (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/v1/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 /v1/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: 394

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "ALCOHOL_CREATED",
    "message" : "์œ„์Šคํ‚ค๊ฐ€ ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:06"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:07.001160527",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

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

Table 2. /v1/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/v1/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 /v1/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-07-05 16:33:07"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:07.037433776",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

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

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

Table 3. /v1/alcohols/{alcoholId}
Parameter Description

alcoholId

์‚ญ์ œํ•  ์ˆ  ID

$ curl 'http://localhost:8080/v1/alcohols/1' -i -X DELETE
DELETE /v1/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-07-05 16:33:06"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:06.579416643",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

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

Path Type Description

success

Boolean

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

code

Number

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

data

Object

categoryGroup๋ณ„ ์นดํ…Œ๊ณ ๋ฆฌ ๋ชฉ๋ก (SINGLE_MALT, BLEND, BLENDED_MALT, BOURBON, RYE, OTHER)

data.SINGLE_MALT

Array

์‹ฑ๊ธ€ ๋ชฐํŠธ ๊ทธ๋ฃน ์นดํ…Œ๊ณ ๋ฆฌ ๋ชฉ๋ก

data.SINGLE_MALT[].korCategory

String

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

data.SINGLE_MALT[].engCategory

String

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

data.BLEND

Array

๋ธ”๋ Œ๋””๋“œ ๊ทธ๋ฃน ์นดํ…Œ๊ณ ๋ฆฌ ๋ชฉ๋ก

data.BLEND[].korCategory

String

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

data.BLEND[].engCategory

String

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

data.BLENDED_MALT

Array

๋ธ”๋ Œ๋””๋“œ ๋ชฐํŠธ ๊ทธ๋ฃน ์นดํ…Œ๊ณ ๋ฆฌ ๋ชฉ๋ก

data.BLENDED_MALT[].korCategory

String

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

data.BLENDED_MALT[].engCategory

String

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

data.BOURBON

Array

๋ฒ„๋ฒˆ ๊ทธ๋ฃน ์นดํ…Œ๊ณ ๋ฆฌ ๋ชฉ๋ก

data.BOURBON[].korCategory

String

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

data.BOURBON[].engCategory

String

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

data.RYE

Array

๋ผ์ด ๊ทธ๋ฃน ์นดํ…Œ๊ณ ๋ฆฌ ๋ชฉ๋ก (๋ฐ์ดํ„ฐ ์—†์œผ๋ฉด ๋นˆ ๋ฐฐ์—ด)

data.OTHER

Array

๊ธฐํƒ€ ๊ทธ๋ฃน ์นดํ…Œ๊ณ ๋ฆฌ ๋ชฉ๋ก

data.OTHER[].korCategory

String

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

data.OTHER[].engCategory

String

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

errors

Array

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

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "SINGLE_MALT" : [ {
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "Single Malt"
    } ],
    "BLEND" : [ {
      "korCategory" : "๋ธ”๋ Œ๋””๋“œ",
      "engCategory" : "Blend"
    } ],
    "BLENDED_MALT" : [ {
      "korCategory" : "๋ธ”๋ Œ๋””๋“œ ๋ชฐํŠธ",
      "engCategory" : "Blended Malt"
    } ],
    "BOURBON" : [ {
      "korCategory" : "๋ฒ„๋ฒˆ",
      "engCategory" : "Bourbon"
    } ],
    "RYE" : [ ],
    "OTHER" : [ {
      "korCategory" : "ํ…Œ๋„ค์‹œ",
      "engCategory" : "Tennessee"
    }, {
      "korCategory" : "์ฝ˜",
      "engCategory" : "Corn"
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:06.701321869",
    "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 /v1/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-07-05T16:33:12.805268811"
      } ]
    },
    "cursorPageable" : {
      "currentCursor" : 0,
      "cursor" : 20,
      "pageSize" : 20,
      "hasNext" : false
    }
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:12.809138529",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

Name Description

Authorization

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

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

Table 4. /v1/helps/{helpId}
Parameter Description

helpId

๋ฌธ์˜ ID

GET /v1/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-07-05T16:33:12.732184289",
    "lastModifyAt" : "2026-07-05T16:33:12.732196077"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:12.739978737",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

Name Description

Authorization

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

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

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

helpId

๋ฌธ์˜ ID

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

Path Type Description

responseContent

String

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

status

String

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

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

๊ฐ’ ์„ค๋ช…

WAITING

๋Œ€๊ธฐ์ค‘

SUCCESS

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

REJECT

๋ฐ˜๋ ค

DELETED

์‚ญ์ œ

POST /v1/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: 341

{
  "success" : true,
  "code" : 200,
  "data" : {
    "helpId" : 1,
    "status" : "SUCCESS",
    "message" : "๋‹ต๋ณ€์ด ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค."
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:12.789279398",
    "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 /v1/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-07-06T01:33:12.258145839",
    "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/v1/tasting-tags?keyword=&page=0&size=20&sortOrder=ASC' -i -X GET
GET /v1/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-07-06T01:33:09.202319782",
    "size" : 3,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 3
  }
}

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

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

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

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

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

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

tagId

ํƒœ๊ทธ ID

$ curl 'http://localhost:8080/v1/tasting-tags/1' -i -X GET
GET /v1/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-07-06T01:33:09.149837144",
    "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/v1/tasting-tags' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "korName" : "๋ฐ”๋‹๋ผ",
  "engName" : "Vanilla",
  "icon" : "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
  "description" : "๋ฐ”๋‹๋ผ ํ–ฅ",
  "parentId" : null
}'
POST /v1/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-07-05 16:33:09"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:09.088396437",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

Table 7. /v1/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/v1/tasting-tags/1' -i -X PUT \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "korName" : "๋ฐ”๋‹๋ผ ์ˆ˜์ •",
  "engName" : "Vanilla Updated",
  "icon" : "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
  "description" : "์ˆ˜์ •๋œ ์„ค๋ช…"
}'
PUT /v1/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-07-05 16:33:09"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:09.293479321",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

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

tagId

ํƒœ๊ทธ ID

$ curl 'http://localhost:8080/v1/tasting-tags/1' -i -X DELETE
DELETE /v1/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: 408

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "TASTING_TAG_DELETED",
    "message" : "ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ๊ฐ€ ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:09"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:09.124509858",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

tagId

ํƒœ๊ทธ ID

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

Path Type Description

alcoholIds

Array

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

$ curl 'http://localhost:8080/v1/tasting-tags/1/alcohols' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "alcoholIds" : [ 1, 2, 3 ]
}'
POST /v1/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: 404

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "TASTING_TAG_ALCOHOL_ADDED",
    "message" : "์œ„์Šคํ‚ค๊ฐ€ ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:09"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:09.267410654",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

tagId

ํƒœ๊ทธ ID

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

Path Type Description

alcoholIds

Array

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

$ curl 'http://localhost:8080/v1/tasting-tags/1/alcohols' -i -X DELETE \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "alcoholIds" : [ 1, 2 ]
}'
DELETE /v1/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: 413

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "TASTING_TAG_ALCOHOL_REMOVED",
    "message" : "์œ„์Šคํ‚ค ์—ฐ๊ฒฐ์ด ํ•ด์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:09"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:09.242324704",
    "serverPathVersion" : "v1"
  }
}

7. Reference API

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

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

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

GET /admin/api/v1/regions

์š”์ฒญ

$ curl 'http://localhost:8080/v1/regions?keyword=&page=0&size=20&sortOrder=ASC' -i -X GET
GET /v1/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[].imageUrl

String

๋Œ€ํ‘œ ์ด๋ฏธ์ง€ URL

data[].createdAt

String

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

data[].modifiedAt

String

์ˆ˜์ •์ผ์‹œ

data[].parentId

Number

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

data[].sortOrder

Number

์ •๋ ฌ ์ˆœ์„œ (๋ฏธ์„ค์ •: 9999)

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: 1328

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "id" : 1,
    "korName" : "์Šค์ฝ”ํ‹€๋žœ๋“œ",
    "engName" : "Scotland",
    "continent" : "์œ ๋Ÿฝ",
    "description" : "์ง€์—ญ ์„ค๋ช… 1",
    "imageUrl" : "https://example.com/region1.png",
    "createdAt" : "2024-01-01T00:00:00",
    "modifiedAt" : "2024-06-01T00:00:00",
    "parentId" : null,
    "sortOrder" : 9999
  }, {
    "id" : 2,
    "korName" : "์•„์ผ๋žœ๋“œ",
    "engName" : "Ireland",
    "continent" : "์œ ๋Ÿฝ",
    "description" : "์ง€์—ญ ์„ค๋ช… 2",
    "imageUrl" : "https://example.com/region2.png",
    "createdAt" : "2024-01-02T00:00:00",
    "modifiedAt" : "2024-06-02T00:00:00",
    "parentId" : null,
    "sortOrder" : 9999
  }, {
    "id" : 3,
    "korName" : "์ผ๋ณธ",
    "engName" : "Japan",
    "continent" : "์•„์‹œ์•„",
    "description" : "์ง€์—ญ ์„ค๋ช… 3",
    "imageUrl" : "https://example.com/region3.png",
    "createdAt" : "2024-01-03T00:00:00",
    "modifiedAt" : "2024-06-03T00:00:00",
    "parentId" : null,
    "sortOrder" : 9999
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:08.522876061",
    "size" : 3,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 3
  }
}

7.2. ์ง€์—ญ bulk reorder

  • ์ „์ฒด ์ง€์—ญ ๋ชฉ๋ก์—์„œ ์š”์ฒญํ•œ ์ง€์—ญ์„ ๋งจ ์•ž ์ •๋ ฌ ์Šฌ๋กฏ์œผ๋กœ ์žฌ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

  • ์š”์ฒญ ID๋Š” 1๊ฐœ ์ด์ƒ 100๊ฐœ ์ดํ•˜์ž…๋‹ˆ๋‹ค.

  • ์ „์ฒด ์ง€์—ญ ์ •๋ ฌ๊ณผ ํŠน์ • ๋ถ€๋ชจ์˜ ์ž์‹ ์ง€์—ญ ์ •๋ ฌ์€ scope๊ฐ€ ๋‹ค๋ฅด๋ฏ€๋กœ API๋ฅผ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

PATCH /admin/api/v1/regions/bulk/reorder
{ "ids": [3, 1, 6, 5] }

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

Path Type Description

ids

Array

๋งจ ์•ž ๊ตฌ๊ฐ„์œผ๋กœ ์˜ฌ๋ฆด ์ง€์—ญ ID ๋ชฉ๋ก (1~100๊ฐœ). ๋ฐฐ์—ด ์ˆœ์„œ๊ฐ€ ์ตœ์ข… ์ƒ๋Œ€ ์ˆœ์„œ์ž…๋‹ˆ๋‹ค

$ curl 'http://localhost:8080/v1/regions/bulk/reorder' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "ids" : [ 3, 1, 6, 5 ]
}'
PATCH /v1/regions/bulk/reorder HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 28
Host: localhost:8080

{
  "ids" : [ 3, 1, 6, 5 ]
}

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

Path Type Description

success

Boolean

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

code

Number

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

data.code

String

์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

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

data.targetId

Varies

๋Œ€์ƒ ID. ์ „์ฒด bulk reorder๋Š” null, ์ž์‹ ์ง€์—ญ bulk reorder๋Š” parentId

data.responseAt

String

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

errors

Array

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

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "REGION_SORT_ORDER_UPDATED",
    "message" : "์ง€์—ญ ์ •๋ ฌ ์ˆœ์„œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : null,
    "responseAt" : "2026-07-05 16:33:08"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:08.574603316",
    "serverPathVersion" : "v1"
  }
}

7.3. ์ž์‹ ์ง€์—ญ bulk reorder

  • ํŠน์ • ๋ถ€๋ชจ ์ง€์—ญ์˜ ์ง์ ‘ ์ž์‹ ์ง€์—ญ๋งŒ ๋งจ ์•ž ์ •๋ ฌ ์Šฌ๋กฏ์œผ๋กœ ์žฌ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

  • `{parentId}`์˜ ์ง์ ‘ ์ž์‹์ด ์•„๋‹Œ ์ง€์—ญ ID๊ฐ€ ํฌํ•จ๋˜๋ฉด ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค.

PATCH /admin/api/v1/regions/{parentId}/children/bulk/reorder
๋ถ€๋ชจ ์ง€์—ญ ID = 1

๋ณ€๊ฒฝ ์ „

์ •๋ ฌ ์Šฌ๋กฏ:       1    10    20    30
              +----+-----+-----+-----+
์ž์‹ ์ง€์—ญ ID: | 11 |  1  |  3  |  5  |
              +----+-----+-----+-----+

์š”์ฒญ

{ "ids": [3, 1] }

๋ณ€๊ฒฝ ํ›„

์ •๋ ฌ ์Šฌ๋กฏ:       1    10    20    30
              +----+-----+-----+-----+
์ž์‹ ์ง€์—ญ ID: |  3 |  1  | 11  |  5  |
              +----+-----+-----+-----+

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

Table 11. /v1/regions/{parentId}/children/bulk/reorder
Parameter Description

parentId

๋ถ€๋ชจ ์ง€์—ญ ID

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

Path Type Description

ids

Array

๋งจ ์•ž ๊ตฌ๊ฐ„์œผ๋กœ ์˜ฌ๋ฆด ์ง์ ‘ ์ž์‹ ์ง€์—ญ ID ๋ชฉ๋ก (1~100๊ฐœ). ๋ฐฐ์—ด ์ˆœ์„œ๊ฐ€ ์ตœ์ข… ์ƒ๋Œ€ ์ˆœ์„œ์ž…๋‹ˆ๋‹ค

$ curl 'http://localhost:8080/v1/regions/1/children/bulk/reorder' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "ids" : [ 30, 10, 60, 50 ]
}'
PATCH /v1/regions/1/children/bulk/reorder HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 32
Host: localhost:8080

{
  "ids" : [ 30, 10, 60, 50 ]
}

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

Path Type Description

success

Boolean

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

code

Number

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

data.code

String

์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

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

data.targetId

Varies

๋Œ€์ƒ ID. ์ „์ฒด bulk reorder๋Š” null, ์ž์‹ ์ง€์—ญ bulk reorder๋Š” parentId

data.responseAt

String

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

errors

Array

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

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "REGION_SORT_ORDER_UPDATED",
    "message" : "์ง€์—ญ ์ •๋ ฌ ์ˆœ์„œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:08"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:08.593275258",
    "serverPathVersion" : "v1"
  }
}

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

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

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

GET /admin/api/v1/distilleries

์š”์ฒญ

$ curl 'http://localhost:8080/v1/distilleries?keyword=&page=0&size=20&sortOrder=ASC' -i -X GET
GET /v1/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[].imageUrl

String

์ฆ๋ฅ˜์†Œ ์ด๋ฏธ์ง€ URL

data[].createdAt

String

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

data[].modifiedAt

String

์ˆ˜์ •์ผ์‹œ

data[].sortOrder

Number

์ •๋ ฌ ์ˆœ์„œ (๋ฏธ์„ค์ •: 9999)

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: 1056

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

7.5. ์ฆ๋ฅ˜์†Œ bulk reorder

  • ์ „์ฒด ์ฆ๋ฅ˜์†Œ ๋ชฉ๋ก์—์„œ ์š”์ฒญํ•œ ์ฆ๋ฅ˜์†Œ๋ฅผ ๋งจ ์•ž ์ •๋ ฌ ์Šฌ๋กฏ์œผ๋กœ ์žฌ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

  • ์š”์ฒญ ID๋Š” 1๊ฐœ ์ด์ƒ 100๊ฐœ ์ดํ•˜์ž…๋‹ˆ๋‹ค.

  • ๊ธฐ์กด ๋‹จ๊ฑด ์ •๋ ฌ API๋Š” ํŠน์ • ์ฆ๋ฅ˜์†Œ 1๊ฐœ์˜ `sortOrder`๋ฅผ ์ง€์ • ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ณ , bulk reorder๋Š” ์—ฌ๋Ÿฌ ์ฆ๋ฅ˜์†Œ์˜ ์ƒ๋Œ€ ์ˆœ์„œ๋ฅผ ํ•œ ๋ฒˆ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

PATCH /admin/api/v1/distilleries/bulk/reorder
{ "ids": [3, 1, 6, 5] }
๋ณ€๊ฒฝ ์ „

์ •๋ ฌ ์Šฌ๋กฏ:    1    10    20    30    40
           +----+-----+-----+-----+-----+
์ฆ๋ฅ˜์†Œ ID: | 11 |  1  |  3  |  5  |  6  |
           +----+-----+-----+-----+-----+

๋ณ€๊ฒฝ ํ›„

์ •๋ ฌ ์Šฌ๋กฏ:    1    10    20    30    40
           +----+-----+-----+-----+-----+
์ฆ๋ฅ˜์†Œ ID: |  3 |  1  |  6  |  5  | 11  |
           +----+-----+-----+-----+-----+

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

Path Type Description

ids

Array

๋งจ ์•ž ๊ตฌ๊ฐ„์œผ๋กœ ์˜ฌ๋ฆด ์ฆ๋ฅ˜์†Œ ID ๋ชฉ๋ก (1~100๊ฐœ). ๋ฐฐ์—ด ์ˆœ์„œ๊ฐ€ ์ตœ์ข… ์ƒ๋Œ€ ์ˆœ์„œ์ž…๋‹ˆ๋‹ค

$ curl 'http://localhost:8080/v1/distilleries/bulk/reorder' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "ids" : [ 3, 1, 6, 5 ]
}'
PATCH /v1/distilleries/bulk/reorder HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 28
Host: localhost:8080

{
  "ids" : [ 3, 1, 6, 5 ]
}

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

Path Type Description

success

Boolean

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

code

Number

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

data.code

String

์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ์ฝ”๋“œ

data.message

String

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

data.targetId

Null

bulk reorder๋Š” ๋‹จ์ผ ๋Œ€์ƒ ID๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

data.responseAt

String

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

errors

Array

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

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "DISTILLERY_SORT_ORDER_UPDATED",
    "message" : "์ฆ๋ฅ˜์†Œ ์ •๋ ฌ ์ˆœ์„œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : null,
    "responseAt" : "2026-07-05 16:33:07"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:07.886636975",
    "serverPathVersion" : "v1"
  }
}

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/v1/curations?keyword=&isActive=true&page=0&size=20' -i -X GET
GET /v1/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: 831

{
  "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-07-06T01:33:11.197298",
    "size" : 3,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 3
  }
}

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

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

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

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

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

Table 12. /v1/curations/{curationId}
Parameter Description

curationId

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

$ curl 'http://localhost:8080/v1/curations/1' -i -X GET
GET /v1/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: 1628

{
  "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-07-06T01:33:11.163510897",
    "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/v1/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 /v1/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-07-05 16:33:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.109008027",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

Table 13. /v1/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/v1/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 /v1/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-07-05 16:33:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.297254993",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

curationId

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

$ curl 'http://localhost:8080/v1/curations/1' -i -X DELETE
DELETE /v1/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: 398

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_DELETED",
    "message" : "ํ๋ ˆ์ด์…˜์ด ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.138638518",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

Table 15. /v1/curations/{curationId}/status
Parameter Description

curationId

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

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

Path Type Description

isActive

Boolean

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

$ curl 'http://localhost:8080/v1/curations/1/status' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "isActive" : false
}'
PATCH /v1/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: 422

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_STATUS_UPDATED",
    "message" : "ํ๋ ˆ์ด์…˜ ํ™œ์„ฑํ™” ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.351483218",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

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

curationId

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

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

Path Type Description

displayOrder

Number

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

$ curl 'http://localhost:8080/v1/curations/1/display-order' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "displayOrder" : 5
}'
PATCH /v1/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: 425

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_DISPLAY_ORDER_UPDATED",
    "message" : "ํ๋ ˆ์ด์…˜ ๋…ธ์ถœ ์ˆœ์„œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.32332855",
    "serverPathVersion" : "v1"
  }
}

8.8. ํ๋ ˆ์ด์…˜ bulk reorder

  • ์—ฌ๋Ÿฌ ํ๋ ˆ์ด์…˜์„ ํ•œ ๋ฒˆ์— ์ •๋ ฌ ๋ชฉ๋ก์˜ ๋งจ ์•ž์œผ๋กœ ์žฌ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ธฐ์กด ๋‹จ๊ฑด API๋Š” ํŠน์ • ํ๋ ˆ์ด์…˜ 1๊ฐœ์˜ `displayOrder`๋ฅผ ์ง€์ • ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

  • bulk reorder API๋Š” ์š”์ฒญํ•œ `ids`๋ฅผ ๋ฐฐ์—ด ์ˆœ์„œ๋Œ€๋กœ ์•ž์ชฝ ์ •๋ ฌ ์Šฌ๋กฏ์— ๋ฐฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

  • ์š”์ฒญ ID๋Š” 1๊ฐœ ์ด์ƒ 100๊ฐœ ์ดํ•˜์ž…๋‹ˆ๋‹ค.

  • ๋น„ํ™œ์„ฑ ๋˜๋Š” ๋ฏธ๋…ธ์ถœ ํ๋ ˆ์ด์…˜๋„ ์ •๋ ฌ๊ฐ’์€ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. ํ™œ์„ฑ ํ๋ ˆ์ด์…˜๋งŒ ์กฐํšŒํ•˜๋ฉด `displayOrder`๊ฐ€ `1,3,5`์ฒ˜๋Ÿผ ์—ฐ์†๋˜์ง€ ์•Š์•„ ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PATCH /admin/api/v1/curations/bulk/reorder
{ "ids": [3, 1, 6, 5] }
๋ณ€๊ฒฝ ์ „

์ •๋ ฌ ์Šฌ๋กฏ:      1    10    20    30    40
             +----+-----+-----+-----+-----+
ํ๋ ˆ์ด์…˜ ID: | 11 |  1  |  3  |  5  |  6  |
             +----+-----+-----+-----+-----+

๋ณ€๊ฒฝ ํ›„

์ •๋ ฌ ์Šฌ๋กฏ:      1    10    20    30    40
             +----+-----+-----+-----+-----+
ํ๋ ˆ์ด์…˜ ID: |  3 |  1  |  6  |  5  | 11  |
             +----+-----+-----+-----+-----+

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

Path Type Description

ids

Array

๋งจ ์•ž ๊ตฌ๊ฐ„์œผ๋กœ ์˜ฌ๋ฆด ํ๋ ˆ์ด์…˜ ID ๋ชฉ๋ก (1~100๊ฐœ). ๋ฐฐ์—ด ์ˆœ์„œ๊ฐ€ ์ตœ์ข… ์ƒ๋Œ€ ์ˆœ์„œ์ž…๋‹ˆ๋‹ค

$ curl 'http://localhost:8080/v1/curations/bulk/reorder' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "ids" : [ 3, 1, 6, 5 ]
}'
PATCH /v1/curations/bulk/reorder HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 28
Host: localhost:8080

{
  "ids" : [ 3, 1, 6, 5 ]
}

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

Path Type Description

success

Boolean

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

code

Number

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

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

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

data.message

String

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

data.targetId

Null

bulk reorder๋Š” ๋‹จ์ผ ๋Œ€์ƒ ID๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

data.responseAt

String

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

errors

Array

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

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_DISPLAY_ORDER_UPDATED",
    "message" : "ํ๋ ˆ์ด์…˜ ๋…ธ์ถœ ์ˆœ์„œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : null,
    "responseAt" : "2026-07-05 16:33:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.272890603",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

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

curationId

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

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

Path Type Description

alcoholIds

Array

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

$ curl 'http://localhost:8080/v1/curations/1/alcohols' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "alcoholIds" : [ 1, 2, 3 ]
}'
POST /v1/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: 417

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_ALCOHOL_ADDED",
    "message" : "ํ๋ ˆ์ด์…˜์— ์œ„์Šคํ‚ค๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.249372254",
    "serverPathVersion" : "v1"
  }
}

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

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

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

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

Table 18. /v1/curations/{curationId}/alcohols/{alcoholId}
Parameter Description

curationId

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

alcoholId

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

$ curl 'http://localhost:8080/v1/curations/1/alcohols/5' -i -X DELETE
DELETE /v1/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-07-05 16:33:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.22730451",
    "serverPathVersion" : "v1"
  }
}

8.11. ํ๋ ˆ์ด์…˜ ์ŠคํŽ™ ๋ชฉ๋ก ์กฐํšŒ

  • ๋ฆฌ์†Œ์Šค OpenAPI spec์—์„œ ๋™๊ธฐํ™”๋œ ํ๋ ˆ์ด์…˜ ์ŠคํŽ™ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ํ๋ ˆ์ด์…˜ ์ƒ์„ฑ/์ˆ˜์ • payload๋Š” ์ด ์ŠคํŽ™์˜ requestSpec ๊ธฐ์ค€์œผ๋กœ ๊ฒ€์ฆ๋ฉ๋‹ˆ๋‹ค.

GET /admin/api/v2/curation-specs

์š”์ฒญ ์˜ˆ์‹œ

$ curl 'http://localhost:8080/v2/curation-specs' -i -X GET
GET /v2/curation-specs HTTP/1.1
Host: localhost:8080

์‘๋‹ต ์˜ˆ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "id" : 1,
    "code" : "RECOMMENDED_WHISKY",
    "name" : "์ถ”์ฒœ ์œ„์Šคํ‚ค",
    "description" : "์ถ”์ฒœ ์œ„์Šคํ‚ค ์นด๋“œ ๋ชฉ๋ก",
    "version" : 1,
    "isActive" : true
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.756323659",
    "serverPathVersion" : "v1"
  }
}

8.12. ํ๋ ˆ์ด์…˜ ์ŠคํŽ™ ์ƒ์„ธ ์กฐํšŒ

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

GET /admin/api/v2/curation-specs/{specId}

์š”์ฒญ ์˜ˆ์‹œ

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

์‘๋‹ต ์˜ˆ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "id" : 1,
    "code" : "RECOMMENDED_WHISKY",
    "name" : "์ถ”์ฒœ ์œ„์Šคํ‚ค",
    "description" : "์ถ”์ฒœ ์œ„์Šคํ‚ค ์นด๋“œ ๋ชฉ๋ก",
    "hydratorKey" : "alcohol",
    "version" : 1,
    "isActive" : true,
    "requestSpec" : {
      "type" : "object",
      "required" : [ "source", "alcohol" ]
    },
    "responseSpec" : {
      "type" : "object"
    }
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.836636938",
    "serverPathVersion" : "v1"
  }
}

8.13. Spec ๊ธฐ๋ฐ˜ ํ๋ ˆ์ด์…˜ ๋ชฉ๋ก ์กฐํšŒ

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

  • ํ‚ค์›Œ๋“œ์™€ ํ™œ์„ฑ ์ƒํƒœ ์กฐ๊ฑด์œผ๋กœ ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

GET /admin/api/v2/curations

์š”์ฒญ ์˜ˆ์‹œ

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

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

Parameter Description

keyword

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

code

ํ๋ ˆ์ด์…˜ ์ŠคํŽ™ ์ฝ”๋“œ exact match ํ•„ํ„ฐ

isActive

ํ™œ์„ฑ ์ƒํƒœ ํ•„ํ„ฐ

page

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

size

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

์‘๋‹ต ์˜ˆ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "id" : 1,
    "specId" : 1,
    "specCode" : "RECOMMENDED_WHISKY",
    "name" : "๋น„ ์˜ค๋Š” ๋‚  ์œ„์Šคํ‚ค",
    "displayOrder" : 1,
    "isActive" : true,
    "createdAt" : "2026-05-15T00:00:00"
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.787052633",
    "size" : 1,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 1
  }
}

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

  • ํŠน์ • spec ๊ธฐ๋ฐ˜ ํ๋ ˆ์ด์…˜์˜ ๋ฉ”ํƒ€ ์ •๋ณด, ์ŠคํŽ™, ์›๋ณธ payload๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

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

์š”์ฒญ ์˜ˆ์‹œ

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

์‘๋‹ต ์˜ˆ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "id" : 1,
    "name" : "๋น„ ์˜ค๋Š” ๋‚  ์œ„์Šคํ‚ค",
    "description" : "์Šค๋ชจํ‚ค ์œ„์Šคํ‚ค ์ถ”์ฒœ",
    "coverImageUrl" : "https://cdn.example.com/cover.jpg",
    "imageUrls" : [ "https://cdn.example.com/cover.jpg" ],
    "exposureStartDate" : "2026-06-01",
    "exposureEndDate" : "2026-06-30",
    "displayOrder" : 1,
    "isActive" : true,
    "createdAt" : "2026-05-15T00:00:00",
    "modifiedAt" : "2026-05-15T00:00:00",
    "spec" : {
      "id" : 1,
      "code" : "RECOMMENDED_WHISKY",
      "name" : "์ถ”์ฒœ ์œ„์Šคํ‚ค",
      "description" : "์ถ”์ฒœ ์œ„์Šคํ‚ค ์นด๋“œ ๋ชฉ๋ก",
      "hydratorKey" : "alcohol",
      "version" : 1,
      "isActive" : true,
      "requestSpec" : {
        "type" : "object",
        "required" : [ "source", "alcohol" ]
      },
      "responseSpec" : {
        "type" : "object"
      }
    },
    "payload" : {
      "source" : "BOTTLE_NOTE",
      "alcohol" : {
        "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค"
      }
    }
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.80862729",
    "serverPathVersion" : "v1"
  }
}

8.15. Spec ๊ธฐ๋ฐ˜ ํ๋ ˆ์ด์…˜ ์ƒ์„ฑ

  • ์„ ํƒํ•œ spec์˜ requestSpec ๊ธฐ์ค€์œผ๋กœ payload๋ฅผ ๊ฒ€์ฆํ•œ ๋’ค ํ๋ ˆ์ด์…˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

POST /admin/api/v2/curations

์š”์ฒญ ์˜ˆ์‹œ

$ curl 'http://localhost:8080/v2/curations' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "specId" : 1,
  "name" : "๋น„ ์˜ค๋Š” ๋‚  ์œ„์Šคํ‚ค",
  "description" : "์Šค๋ชจํ‚ค ์œ„์Šคํ‚ค ์ถ”์ฒœ",
  "imageUrls" : [ "https://cdn.example.com/cover.jpg" ],
  "exposureStartDate" : "2026-06-01",
  "exposureEndDate" : "2026-06-30",
  "displayOrder" : 1,
  "isActive" : true,
  "payload" : {
    "source" : "BOTTLE_NOTE",
    "alcohol" : {
      "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค"
    }
  }
}'
POST /v2/curations HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 394
Host: localhost:8080

{
  "specId" : 1,
  "name" : "๋น„ ์˜ค๋Š” ๋‚  ์œ„์Šคํ‚ค",
  "description" : "์Šค๋ชจํ‚ค ์œ„์Šคํ‚ค ์ถ”์ฒœ",
  "imageUrls" : [ "https://cdn.example.com/cover.jpg" ],
  "exposureStartDate" : "2026-06-01",
  "exposureEndDate" : "2026-06-30",
  "displayOrder" : 1,
  "isActive" : true,
  "payload" : {
    "source" : "BOTTLE_NOTE",
    "alcohol" : {
      "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค"
    }
  }
}
{
  "specId" : 1,
  "name" : "๋น„ ์˜ค๋Š” ๋‚  ์œ„์Šคํ‚ค",
  "description" : "์Šค๋ชจํ‚ค ์œ„์Šคํ‚ค ์ถ”์ฒœ",
  "imageUrls" : [ "https://cdn.example.com/cover.jpg" ],
  "exposureStartDate" : "2026-06-01",
  "exposureEndDate" : "2026-06-30",
  "displayOrder" : 1,
  "isActive" : true,
  "payload" : {
    "source" : "BOTTLE_NOTE",
    "alcohol" : {
      "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค"
    }
  }
}

์‘๋‹ต ์˜ˆ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_CREATED",
    "message" : "ํ๋ ˆ์ด์…˜์ด ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.739643811",
    "serverPathVersion" : "v1"
  }
}

8.16. Spec ๊ธฐ๋ฐ˜ ํ๋ ˆ์ด์…˜ ์ˆ˜์ •

  • ๊ธฐ์กด spec ๊ธฐ๋ฐ˜ ํ๋ ˆ์ด์…˜์˜ ๋ฉ”ํƒ€ ์ •๋ณด์™€ payload๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.

  • ์ˆ˜์ • payload๋„ requestSpec ๊ธฐ์ค€์œผ๋กœ ๊ฒ€์ฆ๋ฉ๋‹ˆ๋‹ค.

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

์š”์ฒญ ์˜ˆ์‹œ

$ curl 'http://localhost:8080/v2/curations/1' -i -X PUT \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "specId" : 1,
  "name" : "์ˆ˜์ •๋œ ํ๋ ˆ์ด์…˜",
  "description" : "์Šค๋ชจํ‚ค ์œ„์Šคํ‚ค ์ถ”์ฒœ",
  "imageUrls" : [ "https://cdn.example.com/cover.jpg" ],
  "exposureStartDate" : "2026-06-01",
  "exposureEndDate" : "2026-06-30",
  "displayOrder" : 1,
  "isActive" : true,
  "payload" : {
    "source" : "BOTTLE_NOTE",
    "alcohol" : {
      "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค"
    }
  }
}'
PUT /v2/curations/1 HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 392
Host: localhost:8080

{
  "specId" : 1,
  "name" : "์ˆ˜์ •๋œ ํ๋ ˆ์ด์…˜",
  "description" : "์Šค๋ชจํ‚ค ์œ„์Šคํ‚ค ์ถ”์ฒœ",
  "imageUrls" : [ "https://cdn.example.com/cover.jpg" ],
  "exposureStartDate" : "2026-06-01",
  "exposureEndDate" : "2026-06-30",
  "displayOrder" : 1,
  "isActive" : true,
  "payload" : {
    "source" : "BOTTLE_NOTE",
    "alcohol" : {
      "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค"
    }
  }
}
{
  "specId" : 1,
  "name" : "์ˆ˜์ •๋œ ํ๋ ˆ์ด์…˜",
  "description" : "์Šค๋ชจํ‚ค ์œ„์Šคํ‚ค ์ถ”์ฒœ",
  "imageUrls" : [ "https://cdn.example.com/cover.jpg" ],
  "exposureStartDate" : "2026-06-01",
  "exposureEndDate" : "2026-06-30",
  "displayOrder" : 1,
  "isActive" : true,
  "payload" : {
    "source" : "BOTTLE_NOTE",
    "alcohol" : {
      "korName" : "ํ…Œ์ŠคํŠธ ์œ„์Šคํ‚ค"
    }
  }
}

์‘๋‹ต ์˜ˆ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "CURATION_UPDATED",
    "message" : "ํ๋ ˆ์ด์…˜์ด ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : 1,
    "responseAt" : "2026-07-05 16:33:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:11.778027752",
    "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/v1/users?keyword=&status=ACTIVE&sortType=CREATED_AT&sortOrder=DESC&page=0&size=20' -i -X GET
GET /v1/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-07-06T01:33:13.608269251",
    "size" : 2,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 2
  }
}

10. Review API

10.1. ๋ฆฌ๋ทฐ ๋ชฉ๋ก ์กฐํšŒ

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

  • ์ˆ , ์ž‘์„ฑ์ž, ํ™œ์„ฑ ์ƒํƒœ, ๋…ธ์ถœ ์ƒํƒœ, ํ‚ค์›Œ๋“œ, ์ž‘์„ฑ์ผ์‹œ ๋ฒ”์œ„๋กœ ํ•„ํ„ฐ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • `sortType`์€ ์ •๋ ฌ ๊ธฐ์ค€์„, `sortOrder`๋Š” ์„ ํƒํ•œ ๊ธฐ์ค€์˜ ์ •๋ ฌ ๋ฐฉํ–ฅ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

  • ๊ธฐ๋ณธ ์ •๋ ฌ์€ ์ž‘์„ฑ์ผ์‹œ ๊ธฐ์ค€ ๋‚ด๋ฆผ์ฐจ์ˆœ์ž…๋‹ˆ๋‹ค.

GET /admin/api/v1/reviews

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

Parameter Description

alcoholId

์ˆ  ID ํ•„ํ„ฐ

userId

์ž‘์„ฑ์ž ์œ ์ € ID ํ•„ํ„ฐ

activeStatus

๋ฆฌ๋ทฐ ํ™œ์„ฑ ์ƒํƒœ ํ•„ํ„ฐ (ACTIVE/DELETED/DISABLED)

displayStatus

๋ฆฌ๋ทฐ ๋…ธ์ถœ ์ƒํƒœ ํ•„ํ„ฐ (PUBLIC/PRIVATE)

keyword

๊ฒ€์ƒ‰์–ด (๋ฆฌ๋ทฐ ๋ณธ๋ฌธ/์ž‘์„ฑ์ž ๋‹‰๋„ค์ž„/์ž‘์„ฑ์ž ์ด๋ฉ”์ผ/์ˆ  ํ•œ๊ธ€๋ช…/์ˆ  ์˜๋ฌธ๋ช…)

createdFrom

์ž‘์„ฑ์ผ์‹œ ์‹œ์ž‘ ๋ฒ”์œ„ (ISO-8601 LocalDateTime)

createdTo

์ž‘์„ฑ์ผ์‹œ ์ข…๋ฃŒ ๋ฒ”์œ„ (ISO-8601 LocalDateTime)

sortType

์ •๋ ฌ ๊ธฐ์ค€ (๊ธฐ๋ณธ๊ฐ’: CREATED_AT, ์ƒ์„ธ ๊ฐ’์€ AdminReviewSortType ํ‘œ ์ฐธ์กฐ)

sortOrder

์ •๋ ฌ ๋ฐฉํ–ฅ (๊ธฐ๋ณธ๊ฐ’: DESC, ์ƒ์„ธ ๊ฐ’์€ SortOrder ํ‘œ ์ฐธ์กฐ)

page

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

size

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

AdminReviewSortType (๊ด€๋ฆฌ์ž ๋ฆฌ๋ทฐ ์ •๋ ฌ ๊ธฐ์ค€)

๊ฐ’ ์„ค๋ช…

CREATED_AT

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ผ์‹œ ๊ธฐ์ค€ ์ •๋ ฌ

REPLY_COUNT

๋ฆฌ๋ทฐ ๋Œ“๊ธ€ ์ˆ˜ ๊ธฐ์ค€ ์ •๋ ฌ

UPDATED_AT

๋ฆฌ๋ทฐ ์ตœ์ข… ์ˆ˜์ •์ผ์‹œ ๊ธฐ์ค€ ์ •๋ ฌ

SortOrder (์ •๋ ฌ ๋ฐฉํ–ฅ)

๊ฐ’ ์„ค๋ช…

DESC

๋‚ด๋ฆผ์ฐจ์ˆœ ์ •๋ ฌ

ASC

์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ

$ curl 'http://localhost:8080/v1/reviews?alcoholId=101&userId=1001&activeStatus=ACTIVE&displayStatus=PUBLIC&keyword=%EA%B8%80%EB%A0%8C&createdFrom=2026-01-01T00%3A00%3A00&createdTo=2026-01-31T23%3A59%3A59&sortType=CREATED_AT&sortOrder=DESC&page=0&size=20' -i -X GET
GET /v1/reviews?alcoholId=101&userId=1001&activeStatus=ACTIVE&displayStatus=PUBLIC&keyword=%EA%B8%80%EB%A0%8C&createdFrom=2026-01-01T00%3A00%3A00&createdTo=2026-01-31T23%3A59%3A59&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[].reviewId

Number

๋ฆฌ๋ทฐ ID

data[].alcoholId

Number

์ˆ  ID

data[].alcoholName

String

์ˆ  ์ด๋ฆ„

data[].userId

Number

์ž‘์„ฑ์ž ์œ ์ € ID

data[].userNickname

String

์ž‘์„ฑ์ž ๋‹‰๋„ค์ž„

data[].content

String

๋ฆฌ๋ทฐ ๋ณธ๋ฌธ

data[].reviewRating

Number

๋ฆฌ๋ทฐ ํ‰์ 

data[].activeStatus

String

๋ฆฌ๋ทฐ ํ™œ์„ฑ ์ƒํƒœ (ACTIVE/DELETED/DISABLED)

data[].displayStatus

String

๋ฆฌ๋ทฐ ๋…ธ์ถœ ์ƒํƒœ (PUBLIC/PRIVATE)

data[].replyCount

Number

๋Œ“๊ธ€ ์ˆ˜

data[].createAt

String

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ผ์‹œ

data[].lastModifyAt

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: 1170

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "reviewId" : 1,
    "alcoholId" : 101,
    "alcoholName" : "๊ธ€๋ Œํ”ผ๋”• 12๋…„",
    "userId" : 1001,
    "userNickname" : "reviewer1",
    "content" : "ํ–ฅ์ด ํ’๋ถ€ํ•˜๊ณ  ๊ท ํ˜•๊ฐ์ด ์ข‹์Šต๋‹ˆ๋‹ค.",
    "reviewRating" : 4.5,
    "activeStatus" : "ACTIVE",
    "displayStatus" : "PUBLIC",
    "replyCount" : 3,
    "createAt" : "2026-01-10T10:30:00",
    "lastModifyAt" : "2026-01-12T09:15:00"
  }, {
    "reviewId" : 2,
    "alcoholId" : 102,
    "alcoholName" : "๋งฅ์ผˆ๋ž€ 12๋…„",
    "userId" : 1002,
    "userNickname" : "reviewer2",
    "content" : "๋น„๊ณต๊ฐœ ์ฒ˜๋ฆฌ๋œ ์šด์˜ ํ™•์ธ ๋Œ€์ƒ ๋ฆฌ๋ทฐ์ž…๋‹ˆ๋‹ค.",
    "reviewRating" : 3.0,
    "activeStatus" : "DISABLED",
    "displayStatus" : "PRIVATE",
    "replyCount" : 0,
    "createAt" : "2026-01-09T18:00:00",
    "lastModifyAt" : "2026-01-09T18:00:00"
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:13.188383406",
    "size" : 2,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 2
  }
}

11. Banner API

11.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/v1/banners?keyword=&isActive=true&bannerType=CURATION&page=0&size=20' -i -X GET
GET /v1/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-07-06T01:33:10.461822131",
    "size" : 3,
    "totalPages" : 1,
    "hasNext" : false,
    "page" : 0,
    "serverPathVersion" : "v1",
    "totalElements" : 3
  }
}

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

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

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

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

Table 19. /v1/banners/{bannerId}
Parameter Description

bannerId

๋ฐฐ๋„ˆ ID

$ curl 'http://localhost:8080/v1/banners/1' -i -X GET
GET /v1/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-07-06T01:33:10.425944503",
    "serverPathVersion" : "v1"
  }
}

11.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/v1/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 /v1/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-07-05 16:33:10"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:10.370358283",
    "serverPathVersion" : "v1"
  }
}

11.4. ๋ฐฐ๋„ˆ ์ˆ˜์ •

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

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

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

Table 20. /v1/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/v1/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 /v1/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-07-05 16:33:10"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:10.546527318",
    "serverPathVersion" : "v1"
  }
}

11.5. ๋ฐฐ๋„ˆ ์‚ญ์ œ

  • ๋ฐฐ๋„ˆ๋ฅผ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. (๋ฌผ๋ฆฌ ์‚ญ์ œ)

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

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

Table 21. /v1/banners/{bannerId}
Parameter Description

bannerId

๋ฐฐ๋„ˆ ID

$ curl 'http://localhost:8080/v1/banners/1' -i -X DELETE
DELETE /v1/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-07-05 16:33:10"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:10.403282881",
    "serverPathVersion" : "v1"
  }
}

11.6. ๋ฐฐ๋„ˆ ํ™œ์„ฑํ™” ์ƒํƒœ ๋ณ€๊ฒฝ

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

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

PATCH /admin/api/v1/banners/{bannerId}/status

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

Table 22. /v1/banners/{bannerId}/status
Parameter Description

bannerId

๋ฐฐ๋„ˆ ID

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

Path Type Description

isActive

Boolean

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

$ curl 'http://localhost:8080/v1/banners/1/status' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "isActive" : false
}'
PATCH /v1/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-07-05 16:33:10"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:10.604298085",
    "serverPathVersion" : "v1"
  }
}

11.7. ๋ฐฐ๋„ˆ ์ •๋ ฌ ์ˆœ์„œ ๋ณ€๊ฒฝ

  • ๋ฐฐ๋„ˆ์˜ ์ •๋ ฌ ์ˆœ์„œ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

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

  • ๋™์ผ ์ˆœ์„œ ์ถฉ๋Œ ์‹œ ๊ธฐ์กด ๋ฐฐ๋„ˆ๋“ค์ด ์ž๋™์œผ๋กœ ๋ฆฌ์˜ค๋”๋ง๋ฉ๋‹ˆ๋‹ค.

PATCH /admin/api/v1/banners/{bannerId}/sort-order

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

Table 23. /v1/banners/{bannerId}/sort-order
Parameter Description

bannerId

๋ฐฐ๋„ˆ ID

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

Path Type Description

sortOrder

Number

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

$ curl 'http://localhost:8080/v1/banners/1/sort-order' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "sortOrder" : 5
}'
PATCH /v1/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-07-05 16:33:10"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:10.578281714",
    "serverPathVersion" : "v1"
  }
}

11.8. ๋ฐฐ๋„ˆ bulk reorder

  • ์—ฌ๋Ÿฌ ๋ฐฐ๋„ˆ๋ฅผ ํ•œ ๋ฒˆ์— ์ •๋ ฌ ๋ชฉ๋ก์˜ ๋งจ ์•ž์œผ๋กœ ์žฌ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ธฐ์กด ๋‹จ๊ฑด API๋Š” ํŠน์ • ๋ฐฐ๋„ˆ 1๊ฐœ์˜ `sortOrder`๋ฅผ ์ง€์ • ๊ฐ’์œผ๋กœ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

  • bulk reorder API๋Š” ์š”์ฒญํ•œ `ids`๋ฅผ ๋ฐฐ์—ด ์ˆœ์„œ๋Œ€๋กœ ์•ž์ชฝ ์ •๋ ฌ ์Šฌ๋กฏ์— ๋ฐฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

  • ์š”์ฒญ ID๋Š” 1๊ฐœ ์ด์ƒ 100๊ฐœ ์ดํ•˜์ž…๋‹ˆ๋‹ค.

  • ๋น„ํ™œ์„ฑ ๋ฐฐ๋„ˆ๋„ ์ •๋ ฌ๊ฐ’์€ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. `isActive=true`๋กœ ์กฐํšŒํ•˜๋ฉด ํ™”๋ฉด์—๋Š” ๋ณด์ด์ง€ ์•Š์•„๋„ bulk reorder ๊ฒฐ๊ณผ๋กœ ๋’ค๋กœ ๋ฐ€๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PATCH /admin/api/v1/banners/bulk/reorder
{ "ids": [3, 1, 6, 5] }
๋ณ€๊ฒฝ ์ „

์ •๋ ฌ ์Šฌ๋กฏ:   1    10    20    30    40
          +----+-----+-----+-----+-----+
๋ฐฐ๋„ˆ ID:  | 11 |  1  |  3  |  5  |  6  |
          +----+-----+-----+-----+-----+

๋ณ€๊ฒฝ ํ›„

์ •๋ ฌ ์Šฌ๋กฏ:   1    10    20    30    40
          +----+-----+-----+-----+-----+
๋ฐฐ๋„ˆ ID:  |  3 |  1  |  6  |  5  | 11  |
          +----+-----+-----+-----+-----+

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

Path Type Description

ids

Array

๋งจ ์•ž ๊ตฌ๊ฐ„์œผ๋กœ ์˜ฌ๋ฆด ๋ฐฐ๋„ˆ ID ๋ชฉ๋ก (1~100๊ฐœ). ๋ฐฐ์—ด ์ˆœ์„œ๊ฐ€ ์ตœ์ข… ์ƒ๋Œ€ ์ˆœ์„œ์ž…๋‹ˆ๋‹ค

$ curl 'http://localhost:8080/v1/banners/bulk/reorder' -i -X PATCH \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "ids" : [ 3, 1, 6, 5 ]
}'
PATCH /v1/banners/bulk/reorder HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 28
Host: localhost:8080

{
  "ids" : [ 3, 1, 6, 5 ]
}

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

Path Type Description

success

Boolean

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

code

Number

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

data

Object

๊ฒฐ๊ณผ ์ •๋ณด

data.code

String

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

data.message

String

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

data.targetId

Null

bulk reorder๋Š” ๋‹จ์ผ ๋Œ€์ƒ ID๋ฅผ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

data.responseAt

String

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

errors

Array

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

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "code" : "BANNER_SORT_ORDER_UPDATED",
    "message" : "๋ฐฐ๋„ˆ ์ •๋ ฌ ์ˆœ์„œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "targetId" : null,
    "responseAt" : "2026-07-05 16:33:10"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : "2026-07-06T01:33:10.504580583",
    "serverPathVersion" : "v1"
  }
}