Bottle Note API ๋ฌธ์„œ

๋ชฉ์ฐจ

1. ๊ฐœ์š” (overview)

ํ•ด๋‹น ํ”„๋กœ์ ํŠธ 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/api/v1/reports/user
Content-Type: application/json

{
  "userId": "์ผ", // ์ˆซ์ž ๊ฐ’์ด ํ•„์š”ํ•œ๋ฐ ๋ฌธ์ž์—ด ๊ฐ’์ด ๋“ค์–ด์˜จ ๊ฒฝ์šฐ
  "reportUserId": 0,
  "type": "SPAM",
  "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/api/v1/reports/user
Content-Type: application/json

{
  "userId": "", // ํ•„์ˆ˜์ ์ธ ๊ฐ’์ด ์—†๋Š” ๊ฒฝ์šฐ
  "reportUserId": 0,
  "type": "SPAM",
  "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"
  }
}
  • ๋ˆ„๋ฝ๋œ ์ •๋ณด๋Š” ์„œ๋ฒ„ ๋ฐฑ์—”๋“œ ํŒ€์—๊ฒŒ ๋ฌธ์˜ํ•ด์ฃผ์„ธ์š”.

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


1.4. ๊ณตํ†ต ์ธ์ฆ/์ธ๊ฐ€

๋ณดํ‹€๋…ธํŠธ ์„œ๋น„์Šค์—์„œ๋Š” ์ธ์ฆ์ด ํ•„์š”ํ•œ URL์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Authorization ํ—ค๋”์— ๋กœ๊ทธ์ธ ์‹œ ๋ฐœ๊ธ‰๋ฐ›์€ Access Token์„ ์ฒจ๋ถ€ํ•ด์„œ ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜ ์˜ˆ์‹œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ์„ ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ๋‚˜ Authorization ํ—ค๋”์— ์ฒจ๋ถ€ํ•œ ํ† ํฐ์— ๋”ฐ๋ผ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ์˜ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

  • Authorization ํ—ค๋”์— ์•ก์„ธ์Šค ํ† ํฐ์„ ์ฒจ๋ถ€ํ•˜์ง€ ์•Š์œผ๋ฉด ํ† ํฐ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค (400)

  • Authorization ํ—ค๋”์— ์ฒจ๋ถ€ํ•œ ํ† ํฐ์ด ์ž˜๋ชป ๋œ ํ† ํฐ์ด๋ฉด ์ž˜๋ชป๋œ ํ† ํฐ์ž…๋‹ˆ๋‹ค ๋ผ๋Š” ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค (401)

  • Authorizatioin ํ—ค๋”์— ์ฒจ๋ถ€ํ•œ ํ† ํฐ์ด ๋งŒ๋ฃŒ ๋œ ํ† ํฐ์ด๋ฉด ๋งŒ๋ฃŒ๋œ ํ† ํฐ์ž…๋‹ˆ๋‹ค ๋ผ๋Š” ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค (403)

2. ๊ณตํ†ต (common) API


2.1. ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๊ฒฝ๋กœ ์š”์ฒญ

์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œ ํ•˜๊ธฐ ์œ„ํ•œ ์—…๋กœ๋“œ ๊ฒฝ๋กœ๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€ ์—…๋กœ๋“œ๋Š” ์ธ์ฆ๋œ ์œ ์ €๋งŒ ์š”์ฒญ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์—…๋กœ๋“œ ์‹œ์—๋Š” S3๋ฅผ ๋Œ€์ƒ์œผ๋กœ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

aFE6gK2

์กฐํšŒ ์‹œ์—๋Š” CDN ์„œ๋น„์Šค๋ฅผ ํ†ตํ•ด ์ด๋ฏธ์ง€๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

oHOmiXo

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

GET /api/v1/s3/presign-url?rootPath=images&uploadSize=1&contentType=image%2Fjpeg HTTP/1.1
Host: api.bottle-note.com
Parameter Description

rootPath

์—…๋กœ๋“œ ํŒŒ์ผ ๊ฒฝ๋กœ (ํ•˜๋‹จ ์„ค๋ช… ์ฐธ์กฐ)

uploadSize

์—…๋กœ๋“œํ•  ์ด๋ฏธ์ง€์˜ ์‚ฌ์ด์ฆˆ ( ์ด๋ฏธ์ง€๋‹น 1๊ฐœ )

contentType

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

  • rootPath : ๋ฃจํŠธ ๊ฒฝ๋กœ๋กœ ๋ถ€ํ„ฐ ์ด๋ฏธ์ง€ ์ €์žฅ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค

    • rootPath ๊ฐ€ review ์ผ ๊ฒฝ์šฐ review/ ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ๋กœ๋กœ ์ด๋ฏธ์ง€๊ฐ€ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.

      • rootPath ๊ฐ€ review ์ผ ๊ฒฝ์šฐ ์„œ๋ฒ„ ์—์„œ๋Š” ํ•ด๋‹น ์—…๋กœ๋“œ์ผ๊ณผ ๋žœ๋คํ•œ UUID๋ฅผ ํ• ๋‹นํ•œ ๊ฒฝ๋กœ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

        • ex. review/20210101/random-uuid.jpg / user/profile/20210101/random-uuid.jpg

      • ์ด๋•Œ ์ด๋ฏธ์ง€์˜ ์›๋ณธ๋ช…์€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.(ํ˜„์žฌ๋กœ์„œ๋Š”)

    • rootPath๋Š” ํ•˜๋‚˜์˜ ๋””๋ ‰ํ† ๋ฆฌ๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ณ  ์ผ๊ด€๋œ ์ƒ์ˆ˜๋กœ ํ”„๋ก ํŠธ ์˜์—ญ์—์„œ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค .

      • ex) review, user/profile,user/album, product ๋“ฑ

    • ๋ฌธ์ž์—ด rootPath์˜ ์‹œ์ž‘๊ณผ ๋์˜ /์€ ๋ฌด์‹œ ๋ฉ๋‹ˆ๋‹ค.

  • ์ตœ์†Œ ํ•œ ๋””๋ ‰ํ† ๋ฆฌ ์ด์ƒ์˜ rootPath ๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • uploadSize๋Š” ์—…๋กœ๋“œํ•  ์‚ฌ์ง„์˜ ํฌ๊ธฐ๋งŒํผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

    • uploadSize๋Š” ์ตœ๋Œ€ 10์žฅ ๊นŒ์ง€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • uploadSize ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ 1์žฅ์ด ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.bucketName

String

๋ฒ„ํ‚ท ์ด๋ฆ„

data.uploadSize

Number

์—…๋กœ๋“œ ํŒŒ์ผ ์‚ฌ์ด์ฆˆ

data.expiryTime

Number

์—…๋กœ๋“œ URL ๋งŒ๋ฃŒ ์‹œ๊ฐ„(๋ถ„๋‹จ์œ„)

data.imageUploadInfo[].order

Number

์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์ˆœ์„œ

data.imageUploadInfo[].viewUrl

String

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

data.imageUploadInfo[].uploadUrl

String

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "bucketName" : "image-bucket",
    "uploadSize" : 1,
    "expiryTime" : 5,
    "imageUploadInfo" : [ {
      "order" : 1,
      "viewUrl" : "https://d1d1d1d1.cloudfront.net/images/1",
      "uploadUrl" : "https://bottlenote.s3.ap-northeast-2.amazonaws.com/images/1"
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 12, 342901447 ],
    "serverPathVersion" : "v1"
  }
}
  • uploadUrl ๋ฅผ ์ด์šฉํ•ด ์ด๋ฏธ์ง€๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ์—…๋กœ๋“œ ํ›„ order ์™€ viewUrl ๋Š” ์„œ๋ฒ„๋กœ ์ „๋‹ฌ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

    • ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฆฌ๋ทฐ ๋“ฑ๋ก์‹œ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์ฒ˜๋ฆฌ ํ›„ ๋ฆฌ๋ทฐ ๋“ฑ๋ก ์š”์ฒญ์‹œ order ์™€ viewUrl ๋ฅผ ํ•จ๊ป˜ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

    • ์—ฌ๋Ÿฌ์žฅ์˜ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์‹œ order`์™€ `viewUrl ๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ๋ฌถ์–ด์„œ ์ „๋‹ฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

  • expiryTime ์€ ๋ฐœ๊ธ‰ ๋ฐ›์€ uploadUrl ์˜ ๋งŒ๋ฃŒ ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.(๋‹จ์œ„ : ๋ถ„)

3. ๊ถŒํ•œ (auth) ๊ด€๋ จ API

3.2. Apple ๋กœ๊ทธ์ธ์šฉ Nonce ๋ฐœ๊ธ‰

  • Apple ๋กœ๊ทธ์ธ ํ”„๋กœ์„ธ์Šค์—์„œ ์‚ฌ์šฉํ•  ์ผํšŒ์„ฑ Nonce ๊ฐ’์„ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

  • ์ด Nonce๋Š” Apple ๋กœ๊ทธ์ธ ์‹œ ๋ณด์•ˆ์„ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

GET /api/v2/auth/apple/nonce

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

$ curl 'https://api.bottle-note.com/api/v2/auth/apple/nonce?_csrf=KNfV8gRYUwEetm0-x7tcRaIa_1teJXZKFixWdw7kZOJwLrL7Tua3wGE7MmQz0wlao5ZoJ8Aj0mNqRhVnJhxnETfTXYRJS4XM' -i -X GET \
    -H 'Content-Type: application/json;charset=UTF-8'
GET /api/v2/auth/apple/nonce?_csrf=KNfV8gRYUwEetm0-x7tcRaIa_1teJXZKFixWdw7kZOJwLrL7Tua3wGE7MmQz0wlao5ZoJ8Aj0mNqRhVnJhxnETfTXYRJS4XM HTTP/1.1
Content-Type: application/json;charset=UTF-8
Host: api.bottle-note.com

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

path type description

nonce

String

Apple ๋กœ๊ทธ์ธ์šฉ ์ผํšŒ์„ฑ Nonce ๊ฐ’

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 32

{
  "nonce" : "test-nonce-123"
}

3.3. Apple ๋กœ๊ทธ์ธ

  • Apple ID๋ฅผ ํ†ตํ•œ ๋กœ๊ทธ์ธ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • Apple์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ ID Token๊ณผ ์ด์ „์— ๋ฐœ๊ธ‰๋ฐ›์€ Nonce ๊ฐ’์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  • ์„ฑ๊ณต ์‹œ ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์€ HttpOnly ์ฟ ํ‚ค๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

  • ์ตœ์ดˆ ๋กœ๊ทธ์ธ ์‹œ isFirstLogin`์ด true๋กœ ๋ฐ˜ํ™˜๋˜๋ฉฐ, ์ž๋™ ์ƒ์„ฑ๋œ ๋‹‰๋„ค์ž„์ด `nickname ํ•„๋“œ์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

  • ๊ธฐ์กด ์‚ฌ์šฉ์ž์˜ ๊ฒฝ์šฐ `isFirstLogin`์ด false๋กœ ๋ฐ˜ํ™˜๋˜๋ฉฐ, ๊ธฐ์กด ๋‹‰๋„ค์ž„์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

POST /api/v2/auth/apple

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

$ curl 'https://api.bottle-note.com/api/v2/auth/apple?_csrf=zvqsDR6C_tDzMe8Dr5Ni0fPXadh_Unn-r10vxANatA17aj8HrMmaOCawx-XeV9lin75W48rnRLobMRzTzG4d_WZq1jRLXQk-' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "idToken" : "test-id-token",
  "nonce" : "test-nonce"
}'
POST /api/v2/auth/apple?_csrf=zvqsDR6C_tDzMe8Dr5Ni0fPXadh_Unn-r10vxANatA17aj8HrMmaOCawx-XeV9lin75W48rnRLobMRzTzG4d_WZq1jRLXQk- HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 59
Host: api.bottle-note.com

{
  "idToken" : "test-id-token",
  "nonce" : "test-nonce"
}
path type optional description

idToken

String

Apple์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ ID ํ† ํฐ

nonce

String

์ด์ „์— ๋ฐœ๊ธ‰๋ฐ›์€ Nonce ๊ฐ’

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

path type description

accessToken

String

๋ฐœ๊ธ‰๋œ ์•ก์„ธ์Šค ํ† ํฐ

isFirstLogin

Boolean

์ตœ์ดˆ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ (true: ์ตœ์ดˆ ๋กœ๊ทธ์ธ, false: ๊ธฐ์กด ์‚ฌ์šฉ์ž)

nickname

String

์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„ (์ตœ์ดˆ ๋กœ๊ทธ์ธ ์‹œ ์ž๋™ ์ƒ์„ฑ๋œ ๋‹‰๋„ค์ž„)

HTTP/1.1 200 OK
Set-Cookie: refresh-token=test-refresh-token; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly
Content-Type: application/json;charset=UTF-8
Content-Length: 107

{
  "accessToken" : "test-access-token",
  "isFirstLogin" : true,
  "nickname" : "๋ถ€๋“œ๋Ÿฌ์šด๋ชฐํŠธ1234"
}

3.4. Kakao ๋กœ๊ทธ์ธ

  • Kakao ID๋ฅผ ํ†ตํ•œ ๋กœ๊ทธ์ธ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  • Kakao์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ ์•ก์„ธ์Šค ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  • ์„ฑ๊ณต ์‹œ ์•ก์„ธ์Šค ํ† ํฐ์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์€ HttpOnly ์ฟ ํ‚ค๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

  • ์ตœ์ดˆ ๋กœ๊ทธ์ธ ์‹œ isFirstLogin`์ด true๋กœ ๋ฐ˜ํ™˜๋˜๋ฉฐ, ์ž๋™ ์ƒ์„ฑ๋œ ๋‹‰๋„ค์ž„์ด `nickname ํ•„๋“œ์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

  • ๊ธฐ์กด ์‚ฌ์šฉ์ž์˜ ๊ฒฝ์šฐ `isFirstLogin`์ด false๋กœ ๋ฐ˜ํ™˜๋˜๋ฉฐ, ๊ธฐ์กด ๋‹‰๋„ค์ž„์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

POST /api/v2/auth/kakao

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

$ curl 'https://api.bottle-note.com/api/v2/auth/kakao?_csrf=TohBpWz2jHuFuwAjIPyVAUqwSRqn1oUd9HFTr3CApeTmtIfYdrkknAiSvR2ojGQQFNGhMXqGZCKW5rcwkRI3zBa1x9eE0ePq' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "accessToken" : "test-kakao-access-token"
}'
POST /api/v2/auth/kakao?_csrf=TohBpWz2jHuFuwAjIPyVAUqwSRqn1oUd9HFTr3CApeTmtIfYdrkknAiSvR2ojGQQFNGhMXqGZCKW5rcwkRI3zBa1x9eE0ePq HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 47
Host: api.bottle-note.com

{
  "accessToken" : "test-kakao-access-token"
}
path type optional description

accessToken

String

์นด์นด์˜ค์—์„œ ๋ฐœ๊ธ‰๋ฐ›์€ ์•ก์„ธ์Šค ํ† ํฐ

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

path type description

accessToken

String

๋ฐœ๊ธ‰๋œ ์•ก์„ธ์Šค ํ† ํฐ

isFirstLogin

Boolean

์ตœ์ดˆ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ (true: ์ตœ์ดˆ ๋กœ๊ทธ์ธ, false: ๊ธฐ์กด ์‚ฌ์šฉ์ž)

nickname

String

์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„ (์ตœ์ดˆ ๋กœ๊ทธ์ธ ์‹œ ์ž๋™ ์ƒ์„ฑ๋œ ๋‹‰๋„ค์ž„)

HTTP/1.1 200 OK
Set-Cookie: refresh-token=test-refresh-token; Path=/; Max-Age=0; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Secure; HttpOnly
Content-Type: application/json;charset=UTF-8
Content-Length: 107

{
  "accessToken" : "test-access-token",
  "isFirstLogin" : true,
  "nickname" : "๋ถ€๋“œ๋Ÿฌ์šด๋ชฐํŠธ1234"
}

3.5. ๋ฃจํŠธ ๊ด€๋ฆฌ์ž ๊ถŒํ•œ ๊ฒ€์ฆ

  • ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ฃจํŠธ ๊ด€๋ฆฌ์ž ๊ถŒํ•œ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐœ๋ฐœ / ์šด์˜ ํ™˜๊ฒฝ์ด ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•œ์ง€ ๊ฒ€์ฆํ•˜๋Š”๋ฐ ํ™œ์šฉ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

GET /api/v2/auth/admin/permissions

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

$ curl 'https://api.bottle-note.com/api/v2/auth/admin/permissions?_csrf=uACQ097h6K0Ic2G-NBSo0No4Zdd2sEDFeAyGNDhPRK0CKCDyiDSht-vW2MglRVWPBTmcsu4BSLZOh3HoT2rlUVsuJp1gTRXA' -i -X GET \
    -H 'Content-Type: application/json;charset=UTF-8'
GET /api/v2/auth/admin/permissions?_csrf=uACQ097h6K0Ic2G-NBSo0No4Zdd2sEDFeAyGNDhPRK0CKCDyiDSht-vW2MglRVWPBTmcsu4BSLZOh3HoT2rlUVsuJp1gTRXA HTTP/1.1
Content-Type: application/json;charset=UTF-8
Host: api.bottle-note.com

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data

Boolean

๊ฒ€์ฆ ๊ฒฐ๊ณผ

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€(์—†์„ ๊ฒฝ์šฐ null)

meta.serverEncoding

String

์„œ๋ฒ„ ์ธ์ฝ”๋”ฉ ์ •๋„

meta.serverVersion

String

์„œ๋ฒ„ ๋ฒ„์ „

meta.serverPathVersion

String

์„œ๋ฒ„ ๊ฒฝ๋กœ ๋ฒ„์ „

meta.serverResponseTime

Array

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

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 251

{
  "success" : true,
  "code" : 200,
  "data" : true,
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 12, 824160578 ],
    "serverPathVersion" : "v1"
  }
}

4. ํšŒ์› (user) ๊ด€๋ จ API


4.1. ๋กœ๊ทธ์ธ

๊ธฐ๋ณธ์ ์ธ ์ธ์ฆ์€ ์†Œ์…œ๋กœ๊ทธ์ธ API ์„œ๋ฒ„์—์„œ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

๋ณดํ‹€๋…ธํŠธ ์„œ๋ฒ„์—์„œ๋Š” ๋‹‰๋„ค์ž„ ์ƒ์„ฑ์„ ํ•œ ๋’ค, AccessToken๊ณผ RefreshToken์„ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

  • AccessToken์€ Response Body๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

  • RefreshToken์€ Response Header์— Cookie์— ๋‹ด์•„ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

  • gender๋Š” MALE, FEMALE๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • socialType์€ KAKAO, NAVER, GOOGLE๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์†์„ฑ ์„ค๋ช…

accessToken

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

refreshToken

๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ

POST /api/v1/oauth/login

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

path type optional description

email

String

์ด๋ฉ”์ผ

socialUniqueId

String

์†Œ์…œ ๋กœ๊ทธ์ธ ์ œ๊ณต์ž์˜ ๊ณ ์œ  ์‹๋ณ„์ž

gender

String

O

์„ฑ๋ณ„

age

Number

O

๋‚˜์ด

socialType

String

์†Œ์…œ ๋กœ๊ทธ์ธ ํƒ€์ž…

{
  "email" : "cdm2883@naver.com",
  "socialUniqueId" : "",
  "socialType" : "KAKAO",
  "gender" : "MALE",
  "age" : 27
}

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.accessToken

String

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

data.isFirstLogin

Boolean

์ตœ์ดˆ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ (true: ์ตœ์ดˆ ๋กœ๊ทธ์ธ, false: ๊ธฐ์กด ์‚ฌ์šฉ์ž)

data.nickname

String

์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„ (์ตœ์ดˆ ๋กœ๊ทธ์ธ ์‹œ ์ž๋™ ์ƒ์„ฑ๋œ ๋‹‰๋„ค์ž„)

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€(์—†์„ ๊ฒฝ์šฐ null)

meta.serverEncoding

String

์„œ๋ฒ„ ์ธ์ฝ”๋”ฉ ์ •๋„

meta.serverVersion

String

์„œ๋ฒ„ ๋ฒ„์ „

meta.serverPathVersion

String

์„œ๋ฒ„ ๊ฒฝ๋กœ ๋ฒ„์ „

meta.serverResponseTime

Array

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

HTTP/1.1 200 OK
Set-Cookie: refresh-token=eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJn44WB44WBZ2dAbmF2ZXIuY29tIiwicm9sZXMiOiJST0xFX1VTRVIiLCJ1c2VySWQiOjE2LCJpYXQiOjE3MTQ5NzU2MjMsImV4cCI6MTcxNjE4NTIyM30.lvmPueUcOb1erv5Llo4qhEUQ_gtWrpFGbBHDw-Pi94qj8MGojoEI3ugdMo8PwoKgrVQZ_gBwBbytwjxh8XktUg; Path=/; Max-Age=1209600; Expires=Wed, 22 Apr 2026 13:53:13 GMT; Secure; HttpOnly
Content-Type: application/json;charset=UTF-8
Content-Length: 560

{
  "success" : true,
  "code" : 200,
  "data" : {
    "accessToken" : "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJn44WB44WBZ2dAbmF2ZXIuY29tIiwicm9sZXMiOiJST0xFX1VTRVIiLCJ1c2VySWQiOjE2LCJpYXQiOjE3MTQ5NzU2MjMsImV4cCI6MTcxNDk3NjUyM30.41SuOBgmX-sd8nrMbC-xm0kH6rbny_SMYCKWE4rNQEZgSrRPS0HvYv0X7E-weo6sHlWWm1OmiQgHl4-uy6-9ig",
    "isFirstLogin" : null,
    "nickname" : null
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 400701337 ],
    "serverPathVersion" : "v1"
  }
}

4.2. ๋ฒ ์ด์ง ํšŒ์›๊ฐ€์ž…

๊ฒŒ์ŠคํŠธ ๋กœ๊ทธ์ธ API

๋ฒ ์ด์ง ํšŒ์›๊ฐ€์ž… API

POST /api/v1/oauth/basic/signup
$ curl 'https://api.bottle-note.com/api/v1/oauth/basic/signup?_csrf=kBUc6KpG-SrvtYAeRpRtwI0Dz1brKD_W_0jsGm1rCksu-mgtoSJ_jMhxyknCjLcqJblZ8LRi4m_cGQj7yXCKLQsJPHwcyVxM' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "email" : "test@email.com",
  "password" : "test-password",
  "age" : 27,
  "gender" : null
}'

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

path type optional description

email

String

์ด๋ฉ”์ผ

password

String

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

age

Number

๋‚˜์ด

gender

Null

์„ฑ๋ณ„

{
  "email" : "test@email.com",
  "password" : "test-password",
  "age" : 27,
  "gender" : null
}

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

path type description

data

Object

๊ฒฐ๊ณผ

data.message

String

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

data.email

String

์ด๋ฉ”์ผ

data.nickname

String

๋‹‰๋„ค์ž„

data.accessToken

String

accessToken

data.refreshToken

String

refreshToken

{
  "success" : true,
  "code" : 200,
  "data" : {
    "message" : "๋ถ€๋“œ๋Ÿฌ์šด๋ชฐํŠธ๋‹˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค!",
    "email" : "test@email.com",
    "nickname" : "๋ถ€๋“œ๋Ÿฌ์šด๋ชฐํŠธ",
    "accessToken" : "access-token",
    "refreshToken" : "refresh-token"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 353453435 ],
    "serverPathVersion" : "v1"
  }
}

4.3. ๋ฒ ์ด์ง ๋กœ๊ทธ์ธ

๋ฒ ์ด์ง ํšŒ์›๊ฐ€์ž… API

POST /api/v1/oauth/basic/login
$ curl 'https://api.bottle-note.com/api/v1/oauth/basic/login?_csrf=NdjREKZFBr5gg-InPB6wc01eCXtL6jPaDg8yxWzrGN-GMvChBOjnJ8V2Z9hN5YAWBTOERStqJBp7iQL3OmoF_V3bee2_A8LA' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "email" : "test@email.com",
  "password" : "test-password"
}'

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

path type optional description

email

String

์ด๋ฉ”์ผ

password

String

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

{
  "email" : "test@email.com",
  "password" : "test-password"
}

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

path type description

data

Object

๊ฒฐ๊ณผ

data.accessToken

String

accessToken

data.isFirstLogin

Boolean

์ตœ์ดˆ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ (true: ์ตœ์ดˆ ๋กœ๊ทธ์ธ, false: ๊ธฐ์กด ์‚ฌ์šฉ์ž)

data.nickname

String

์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„ (์ตœ์ดˆ ๋กœ๊ทธ์ธ ์‹œ ์ž๋™ ์ƒ์„ฑ๋œ ๋‹‰๋„ค์ž„)

{
  "success" : true,
  "code" : 200,
  "data" : {
    "accessToken" : "access-token",
    "isFirstLogin" : null,
    "nickname" : null
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 425512373 ],
    "serverPathVersion" : "v1"
  }
}

4.4. ํ† ํฐ ์žฌ๋ฐœ๊ธ‰

ํ† ํฐ(์•ก์„ธ์Šคํ† ํฐ, ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ)์„ ์žฌ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

  • POST ์š”์ฒญ์˜ ํ—ค๋”์— ์ฒจ๋ถ€ ๋œ ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ์„ ํŒŒ์‹ฑํ•˜์—ฌ ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฒ€์ฆ์ด ํ†ต๊ณผ๋˜๋ฉด ์ƒˆ๋กœ์šด ์•ก์„ธ์Šคํ† ํฐ๊ณผ ๋ฆฌํ”„๋ ˆ์‰ฌ ํ† ํฐ์„ ๋ฐœ๊ธ‰ํ•ฉ๋‹ˆ๋‹ค.

  • AccessToken์€ Response Body๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

  • RefreshToken์€ Response Header์— Cookie์— ๋‹ด์•„ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

  • ๋ ˆํ”„๋ ˆ์‹œ ํ† ํฐ์ด null์ด๋ฉด ํ† ํฐ ๊ฒ€์ฆ ์‹œ UserException์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

POST /api/v1/oauth/reissue

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

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.accessToken

String

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

data.isFirstLogin

Boolean

์ตœ์ดˆ ๋กœ๊ทธ์ธ ์—ฌ๋ถ€ (true: ์ตœ์ดˆ ๋กœ๊ทธ์ธ, false: ๊ธฐ์กด ์‚ฌ์šฉ์ž)

data.nickname

String

์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„ (์ตœ์ดˆ ๋กœ๊ทธ์ธ ์‹œ ์ž๋™ ์ƒ์„ฑ๋œ ๋‹‰๋„ค์ž„)

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€(์—†์„ ๊ฒฝ์šฐ null)

meta.serverEncoding

String

์„œ๋ฒ„ ์ธ์ฝ”๋”ฉ ์ •๋„

meta.serverVersion

String

์„œ๋ฒ„ ๋ฒ„์ „

meta.serverPathVersion

String

์„œ๋ฒ„ ๊ฒฝ๋กœ ๋ฒ„์ „

meta.serverResponseTime

Array

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

HTTP/1.1 200 OK
Set-Cookie: refresh-token=new-refresh-token; Path=/; Max-Age=1209600; Expires=Wed, 22 Apr 2026 13:53:13 GMT; Secure; HttpOnly
Content-Type: application/json;charset=UTF-8
Content-Length: 341

{
  "success" : true,
  "code" : 200,
  "data" : {
    "accessToken" : "new-access-token",
    "isFirstLogin" : null,
    "nickname" : null
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 325834288 ],
    "serverPathVersion" : "v1"
  }
}

4.5. ๋‹‰๋„ค์ž„ ๋ณ€๊ฒฝ

๋‹‰๋„ค์ž„ ๋ณ€๊ฒฝ API๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋กœ๊ทธ์ธ ํ›„ ์ž์‹ ์˜ ๋‹‰๋„ค์ž„์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

๋‹‰๋„ค์ž„ ๋ณ€๊ฒฝ ์š”์ฒญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค:

  • ๋‹‰๋„ค์ž„์€ ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

  • ๋‹‰๋„ค์ž„์€ ์ตœ์†Œ 2์ž ์ด์ƒ, ์ตœ๋Œ€ 11์ž ์ดํ•˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋‹‰๋„ค์ž„์€ ํ•œ๊ธ€, ์˜๋ฌธ, ์ˆซ์ž๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋‹‰๋„ค์ž„์€ ๊ณต๋ฐฑ์„ ํฌํ•จํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

  • userId์™€ newNickname์€ ํ•„์ˆ˜ ์š”์ฒญ ํ•„๋“œ์ž…๋‹ˆ๋‹ค.

PATCH /api/v1/users/nickname

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

path type optional description

nickName

String

๋ณ€๊ฒฝํ•  ์ƒˆ ๋‹‰๋„ค์ž„

{
  "nickName" : "newNickname"
}

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.message

String

๋ฉ”์‹œ์ง€

data.userId

Number

์‚ฌ์šฉ์ž ID

data.beforeNickname

String

์ด์ „ ๋‹‰๋„ค์ž„

data.changedNickname

String

๋ณ€๊ฒฝ๋œ ๋‹‰๋„ค์ž„

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€(์—†์„ ๊ฒฝ์šฐ null)

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 419

{
  "success" : true,
  "code" : 200,
  "data" : {
    "message" : "๋‹‰๋„ค์ž„์ด ์„ฑ๊ณต์ ์œผ๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "userId" : 1,
    "beforeNickname" : "beforeNickname",
    "changedNickname" : "newNickname"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 14430000 ],
    "serverPathVersion" : "v1"
  }
}

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUIRED_USER_ID

BAD_REQUEST

์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๋งˆ์ดํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.

USER_NICKNAME_NOT_VALID

BAD_REQUEST

์ค‘๋ณต๋œ ๋‹‰๋„ค์ž„์ž…๋‹ˆ๋‹ค.

USER_NOT_FOUND

NOT_FOUND

์œ ์ €๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.


4.6. ํ”„๋กœํ•„ ๋ณ€๊ฒฝ

์‚ฌ์šฉ์ž์˜ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€ url์„ ๋ฐ›์•„์„œ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€ url์€ nullํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค. null์ผ ๊ฒฝ์šฐ ๊ธฐ๋ณธ ์ด๋ฏธ์ง€๋กœ ์ธ์‹ํ•ฉ๋‹ˆ๋‹ค.

===

PATCH /api/v1/users/profile-image

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

path type optional description

viewUrl

String

๋ณ€๊ฒฝํ•  ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

PATCH /api/v1/users/profile-image?_csrf=iFrV_B-b0-cjJvw5uuWTnRVRoKYiOkp3X4FD3l6X-bm8zvA3vG-0ySv45oMOEs4M3sinqyBkjZ8aWS9aaeJw7W-vzoCE-sAB HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 69
Host: api.bottle-note.com

{
  "viewUrl" : "https://api.bottle-note.com/new-profile-image.jpg"
}

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.userId

Number

์‚ฌ์šฉ์ž ID

data.profileImageUrl

String

๋ณ€๊ฒฝ๋œ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

data.callback

String

์ฝœ๋ฐฑ URL

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€(์—†์„ ๊ฒฝ์šฐ null)

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 395

{
  "success" : true,
  "code" : 200,
  "data" : {
    "userId" : 1,
    "profileImageUrl" : "http://example.com/new-profile-image.jpg",
    "callback" : "https://bottle-note.com/api/v1/users/1"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 39084323 ],
    "serverPathVersion" : "v1"
  }
}

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

USER_NOT_FOUND

NOT_FOUND

์œ ์ €๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

4.7. ํ˜„์žฌ ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž ๋ฉ”ํƒ€ ์ •๋ณด ์กฐํšŒ

ํ˜„์žฌ ์‚ฌ์šฉ์ž์˜ ๋ฉ”ํƒ€ ์ •๋ณด๋ฅผ ์กฐํšŒํ•œ๋‹ค.

์š”์ฒญ ์‹œ ์ถ”๊ฐ€์ ์ธ ํ•„์š” ์ •๋ณด๋“ค์€ ์ถ”ํ›„ ์ถ”๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋‹ค.

===

PATCH /api/v1/users/current

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

$ curl 'https://api.bottle-note.com/api/v1/users/current?_csrf=JCLDaY9cI09-4j8XZp2ifoW9y5yH9sAuQSuxPdFlwU2Mt4eDHBKnX7hpEnxT2g4lUrCWG7GP5qSzzqQDcBjTX7UEonS91bDn' -i -X GET \
    -H 'Content-Type: application/json;charset=UTF-8'

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.id

Number

ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ์œ ์ € ์•„์ด๋””

data.nickname

String

ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ์œ ์ € ๋‹‰๋„ค์ž„

data.imageUrl

String

ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ์œ ์ € ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 355

{
  "success" : true,
  "code" : 200,
  "data" : {
    "id" : 1,
    "nickname" : "๋กœ๊ทธ์ธํ•œ_์œ ์ €_๋‹‰๋„ค์ž„",
    "imageUrl" : "์—†์„์ˆ˜๋„ ์ž‡์Œ"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 518992248 ],
    "serverPathVersion" : "v1"
  }
}

4.8. ํšŒ์› ํƒˆํ‡ด

ํšŒ์›ํƒˆํ‡ด API์ž…๋‹ˆ๋‹ค.

  • Authorization ํ—ค๋”์— ์ฒจ๋ถ€ํ•œ ์•ก์„ธ์Šคํ† ํฐ์œผ๋กœ, ์œ ์ € ID๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ status ์ปฌ๋Ÿผ์ด DELETED ๋กœ ์ˆ˜์ •๋ฉ๋‹ˆ๋‹ค.

DELETE /api/v1/users

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.codeMessage

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ

data.message

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€

data.userId

Number

์œ ์ € ์•„์ด๋””

data.responseAt

String

์„œ๋ฒ„ ์‘๋‹ต ์ผ์‹œ

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 423

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "USER_WITHDRAW_SUCCESS",
    "message" : "์„ฑ๊ณต์ ์œผ๋กœ ํƒˆํ‡ด๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
    "userId" : 1,
    "responseAt" : "2026-04-08 13:53:13"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 540370865 ],
    "serverPathVersion" : "v1"
  }
}

4.9. ํšŒ์› ๋ณต๊ตฌ

ํšŒ์› ํƒˆํ‡ด ํ›„ ๋ณต๊ตฌ ์š”์ฒญ API์ž…๋‹ˆ๋‹ค.

POST /api/v1/oauth/restore
$ curl 'https://api.bottle-note.com/api/v1/oauth/restore?_csrf=ZlBxqVLD3vNao6FqIHYdFADRekeOVvF-gEJ5F29VwxfWGCnWA2hCmjP65sJ3lpdeFlspcWXiV3-2ZMBTuXtLIgplpXW0KR-3' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "email" : "test-email",
  "password" : "test-password"
}'

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

path type optional description

email

String

์ด๋ฉ”์ผ

password

String

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

POST /api/v1/oauth/restore?_csrf=ZlBxqVLD3vNao6FqIHYdFADRekeOVvF-gEJ5F29VwxfWGCnWA2hCmjP65sJ3lpdeFlspcWXiV3-2ZMBTuXtLIgplpXW0KR-3 HTTP/1.1
Content-Type: application/json;charset=UTF-8
Content-Length: 60
Host: api.bottle-note.com

{
  "email" : "test-email",
  "password" : "test-password"
}

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

path type description

data

String

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

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 264

{
  "success" : true,
  "code" : 200,
  "data" : "restore success",
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 464323739 ],
    "serverPathVersion" : "v1"
  }
}

4.10. ๋งˆ์ดํŽ˜์ด์ง€ ๊ธฐ๋ณธ์ •๋ณด ์กฐํšŒ

๋งˆ์ดํŽ˜์ด์ง€ ์ ‘๊ทผ์‹œ ๊ธฐ๋ณธ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

์กฐํšŒํ•  ์ˆ˜ ์žˆ๋Š” ์ •๋ณด๋Š”

  • ๋Œ€์ƒ ์‚ฌ์šฉ์ž์˜ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€

  • ๋Œ€์ƒ ์‚ฌ์šฉ์ž์˜ ๋‹‰๋„ค์ž„

  • ๋Œ€์ƒ ์‚ฌ์šฉ์ž๋ฅผ ํŒ”๋กœ์šฐํ•œ ์œ ์ € ์ˆ˜ (ํŒ”๋กœ์›Œ ์ˆ˜)

  • ๋Œ€์ƒ ์‚ฌ์šฉ์ž๊ฐ€ ํŒ”๋กœ์šฐํ•œ ์œ ์ € ์ˆ˜ (ํŒ”๋กœ์ž‰ ์ˆ˜)

  • ๋Œ€์ƒ ์‚ฌ์šฉ์ž๊ฐ€ ์œ„์Šคํ‚ค๋ฅผ ์ฐœํ•˜๊ธฐ ํ•œ ๊ฐฏ์ˆ˜

  • ๋Œ€์ƒ ์‚ฌ์šฉ์ž๊ฐ€ ์œ„์Šคํ‚ค์— ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ ๊ฐฏ์ˆ˜

  • ๋Œ€์ƒ ์‚ฌ์šฉ์ž๊ฐ€ ์œ„์Šคํ‚ค์— ํ‰๊ฐ€ํ•œ ๋ณ„์ ์˜ ๊ฐฏ์ˆ˜

  • ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž๊ฐ€ ๋Œ€์ƒ์‚ฌ์šฉ์ž๋ฅผ ํŒ”๋กœ์›Œ ํ•˜๋Š”์ง€ ์œ /๋ฌด

  • ๋กœ๊ทธ์ธ ์‚ฌ์šฉ์ž์™€ ๋งˆ์ดํŽ˜์ด์ง€ ๋Œ€์ƒ ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ™์€ ์‚ฌ์šฉ์ž์ธ์ง€ ์œ /๋ฌด

GET /api/mypage/{userId}

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

  • userId : string (path) - ๋Œ€์ƒ ์‚ฌ์šฉ์ž์˜ ์•„์ด๋””

$ curl 'https://api.bottle-note.com/api/v1/my-page/1?_csrf=m95ETQl9iWPoA5zdq-c6SrwnABmuYXQE9ypLT64xkxMcGQUso-khLjFOu1rFM67km8oOed1DLSCdUhIpwExzeZYA9XJ_LTRN' -i -X GET \
    -H 'Content-Type: application/json;charset=UTF-8'

์‘๋‹ต ๊ฒฐ๊ณผ

path type description

success

Boolean

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

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.userId

Number

์œ ์ € ์•„์ด๋””

data.nickName

String

์œ ์ € ๋‹‰๋„ค์ž„

data.imageUrl

String

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

data.reviewCount

Number

๋ฆฌ๋ทฐ ์ˆ˜

data.ratingCount

Number

ํ‰์  ์ˆ˜

data.pickCount

Number

์ฐœํ•œ ์ˆ˜

data.followerCount

Number

ํŒ”๋กœ์›Œ ์ˆ˜

data.followingCount

Number

ํŒ”๋กœ์ž‰ ์ˆ˜

data.isFollow

Boolean

ํŒ”๋กœ์šฐ ์—ฌ๋ถ€

data.isMyPage

Boolean

๋ณธ์ธ ์—ฌ๋ถ€

{
  "success" : true,
  "code" : 200,
  "data" : {
    "userId" : 1,
    "nickName" : "nickname",
    "imageUrl" : "imageUrl",
    "reviewCount" : 10,
    "ratingCount" : 20,
    "pickCount" : 30,
    "followerCount" : 40,
    "followingCount" : 50,
    "isFollow" : false,
    "isMyPage" : false
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 65821150 ],
    "serverPathVersion" : "v1"
  }
}

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

MYPAGE_NOT_ACCESSIBLE

FORBIDDEN

์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๋งˆ์ดํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.


4.11. ๋ฆฌ๋ทฐ ๋งˆ์ด๋ณดํ‹€ ์กฐํšŒ

  • ๋ฆฌ๋ทฐ ๋งˆ์ด ๋ณดํ‹€ ์กฐํšŒ API๋Š” ์‚ฌ์šฉ์ž ๊ฐ€ ์œ„์Šคํ‚ค์— ๋‹จ ๋ฆฌ๋ทฐ๋“ค์„ ์กฐํšŒํ•˜๋Š” API์ž…๋‹ˆ๋‹ค.

---
GET /api/v1/mypage/{userId}/my-bottle/reviews
---

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

  • userId : ์‚ฌ์šฉ์ž ID (์กฐํšŒ๋Œ€์ƒ ์‚ฌ์šฉ์ž)

Parameter Description

keyword

๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ

regionId

์ง€์—ญ ID

sortType

์ •๋ ฌ ํƒ€์ž…(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

sortOrder

์ •๋ ฌ ์ˆœ์„œ(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

cursor

์กฐํšŒ ํ•  ์‹œ์ž‘ ๊ธฐ์ค€ ์œ„์น˜

pageSize

์กฐํšŒ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

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

path type description

success

Boolean

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

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.userId

Number

์œ ์ € ์•„์ด๋””

data.isMyPage

Boolean

๋ณธ์ธ ์—ฌ๋ถ€

data.totalCount

Number

์ „์ฒด ๋ณดํ‹€ ์ˆ˜

data.myBottleList

Array

๋ณดํ‹€ ๋ชฉ๋ก

data.myBottleList[].baseMyBottleInfo.alcoholId

Number

์•Œ์ฝ”์˜ฌ ์•„์ด๋””

data.myBottleList[].baseMyBottleInfo.alcoholKorName

String

์•Œ์ฝ”์˜ฌ ํ•œ๊ธ€๋ช…

data.myBottleList[].baseMyBottleInfo.alcoholEngName

String

์•Œ์ฝ”์˜ฌ ์˜๋ฌธ๋ช…

data.myBottleList[].baseMyBottleInfo.korCategoryName

String

์•Œ์ฝ”์˜ฌ ์นดํ…Œ๊ณ ๋ฆฌ๋ช…

data.myBottleList[].baseMyBottleInfo.imageUrl

String

์•Œ์ฝ”์˜ฌ ์ด๋ฏธ์ง€ URL

data.myBottleList[].baseMyBottleInfo.isHot5

Boolean

HOT5 ์—ฌ๋ถ€

data.myBottleList[].reviewId

Number

๋ฆฌ๋ทฐ ID

data.myBottleList[].isMyReview

Boolean

๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

data.myBottleList[].reviewModifyAt

Array

๋ฆฌ๋ทฐ ๋งˆ์ง€๋ง‰ ์ˆ˜์ •์ผ

data.myBottleList[].reviewContent

String

๋ฆฌ๋ทฐ ๋‚ด์šฉ

data.myBottleList[].reviewTastingTags

Array

๋ฆฌ๋ทฐ ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ

data.myBottleList[].isBestReview

Boolean

๋ฒ ์ŠคํŠธ ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

meta.pageable

Object

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

meta.pageable.currentCursor

Null

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

meta.pageable.cursor

Null

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

meta.pageable.pageSize

Null

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Null

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

meta.searchParameters.keyword

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ๊ฒ€์ƒ‰์–ด

meta.searchParameters.regionId

Null

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ง€์—ญ ID

meta.searchParameters.sortType

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ •๋ ฌ ํƒ€์ž…

meta.searchParameters.sortOrder

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ •๋ ฌ ์ˆœ์„œ

meta.searchParameters.cursor

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ปค์„œ ๊ธฐ์ค€

meta.searchParameters.pageSize

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

์ •๋ ฌ ํƒ€์ž… (sortType)

LATEST

์ตœ์‹ 

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

MYBOTTLE_NOT_ACCESSIBLE

FORBIDDEN

์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๋งˆ์ด๋ณดํ‹€ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.

4.12. ๋ณ„์  ๋งˆ์ด๋ณดํ‹€ ์กฐํšŒ

  • ๋ณ„์  ๋งˆ์ด ๋ณดํ‹€ ์กฐํšŒ API๋Š” ์‚ฌ์šฉ์ž ๊ฐ€ ์œ„์Šคํ‚ค์— ๋‹จ ๋ณ„์ ๋“ค์„ ์กฐํšŒํ•˜๋Š” API์ž…๋‹ˆ๋‹ค.

---
GET /api/v1/mypage/{userId}/my-bottle/ratings
---

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

  • userId : ์‚ฌ์šฉ์ž ID (์กฐํšŒ๋Œ€์ƒ ์‚ฌ์šฉ์ž)

Parameter Description

keyword

๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ

regionId

์ง€์—ญ ID

sortType

์ •๋ ฌ ํƒ€์ž…(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

sortOrder

์ •๋ ฌ ์ˆœ์„œ(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

cursor

์กฐํšŒ ํ•  ์‹œ์ž‘ ๊ธฐ์ค€ ์œ„์น˜

pageSize

์กฐํšŒ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

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

path type description

success

Boolean

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

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.userId

Number

์œ ์ € ์•„์ด๋””

data.isMyPage

Boolean

๋ณธ์ธ ์—ฌ๋ถ€

data.totalCount

Number

์ „์ฒด ๋ณดํ‹€ ์ˆ˜

data.myBottleList

Array

๋ณดํ‹€ ๋ชฉ๋ก

data.myBottleList[].baseMyBottleInfo.alcoholId

Number

์•Œ์ฝ”์˜ฌ ์•„์ด๋””

data.myBottleList[].baseMyBottleInfo.alcoholKorName

String

์•Œ์ฝ”์˜ฌ ํ•œ๊ธ€๋ช…

data.myBottleList[].baseMyBottleInfo.alcoholEngName

String

์•Œ์ฝ”์˜ฌ ์˜๋ฌธ๋ช…

data.myBottleList[].baseMyBottleInfo.korCategoryName

String

์•Œ์ฝ”์˜ฌ ์นดํ…Œ๊ณ ๋ฆฌ๋ช…

data.myBottleList[].baseMyBottleInfo.imageUrl

String

์•Œ์ฝ”์˜ฌ ์ด๋ฏธ์ง€ URL

data.myBottleList[].baseMyBottleInfo.isHot5

Boolean

HOT5 ์—ฌ๋ถ€

data.myBottleList[].myRatingPoint

Number

๋‚ด ๋ณ„์ 

data.myBottleList[].averageRatingPoint

Number

์ „์ฒด ํ‰๊ท  ๋ณ„์ 

data.myBottleList[].averageRatingCount

Number

์ „์ฒด ํ‰๊ท  ๋ณ„์  ์ฐธ์—ฌ์ž ์ˆ˜

data.myBottleList[].ratingModifyAt

Array

๋ณ„์  ์ˆ˜์ •์‹œ๊ฐ„

meta.pageable

Object

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

meta.pageable.currentCursor

Null

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

meta.pageable.cursor

Null

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

meta.pageable.pageSize

Null

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Null

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

meta.searchParameters.keyword

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ๊ฒ€์ƒ‰์–ด

meta.searchParameters.regionId

Null

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ง€์—ญ ID

meta.searchParameters.sortType

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ •๋ ฌ ํƒ€์ž…

meta.searchParameters.sortOrder

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ •๋ ฌ ์ˆœ์„œ

meta.searchParameters.cursor

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ปค์„œ ๊ธฐ์ค€

meta.searchParameters.pageSize

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

์ •๋ ฌ ํƒ€์ž… (sortType)

LATEST

์ตœ์‹ 

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

MYBOTTLE_NOT_ACCESSIBLE

FORBIDDEN

์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๋งˆ์ด๋ณดํ‹€ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.

4.13. ์ฐœ ๋งˆ์ด๋ณดํ‹€ ์กฐํšŒ

  • ์ฐœ ๋งˆ์ด ๋ณดํ‹€ ์กฐํšŒ API๋Š” ์‚ฌ์šฉ์ž ๊ฐ€ ์œ„์Šคํ‚ค์— ๋‹จ ์ฐœ๋“ค์„ ์กฐํšŒํ•˜๋Š” API์ž…๋‹ˆ๋‹ค.

---
GET /api/v1/mypage/{userId}/my-bottle/picks
---

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

  • userId : ์‚ฌ์šฉ์ž ID (์กฐํšŒ๋Œ€์ƒ ์‚ฌ์šฉ์ž)

Parameter Description

keyword

๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ

regionId

์ง€์—ญ ID

sortType

์ •๋ ฌ ํƒ€์ž…(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

sortOrder

์ •๋ ฌ ์ˆœ์„œ(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

cursor

์กฐํšŒ ํ•  ์‹œ์ž‘ ๊ธฐ์ค€ ์œ„์น˜

pageSize

์กฐํšŒ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

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

path type description

success

Boolean

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

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.userId

Number

์œ ์ € ์•„์ด๋””

data.isMyPage

Boolean

๋ณธ์ธ ์—ฌ๋ถ€

data.totalCount

Number

์ „์ฒด ๋ณดํ‹€ ์ˆ˜

data.myBottleList

Array

๋ณดํ‹€ ๋ชฉ๋ก

data.myBottleList[].baseMyBottleInfo.alcoholId

Number

์•Œ์ฝ”์˜ฌ ์•„์ด๋””

data.myBottleList[].baseMyBottleInfo.alcoholKorName

String

์•Œ์ฝ”์˜ฌ ํ•œ๊ธ€๋ช…

data.myBottleList[].baseMyBottleInfo.alcoholEngName

String

์•Œ์ฝ”์˜ฌ ์˜๋ฌธ๋ช…

data.myBottleList[].baseMyBottleInfo.korCategoryName

String

์•Œ์ฝ”์˜ฌ ์นดํ…Œ๊ณ ๋ฆฌ๋ช…

data.myBottleList[].baseMyBottleInfo.imageUrl

String

์•Œ์ฝ”์˜ฌ ์ด๋ฏธ์ง€ URL

data.myBottleList[].baseMyBottleInfo.isHot5

Boolean

HOT5 ์—ฌ๋ถ€

data.myBottleList[].isPicked

Boolean

์ฐœ ์ƒํƒœ

data.myBottleList[].totalPicksCount

Number

์ „์ฒด ์ฐœํ•œ ์œ ์ € ์ˆ˜

meta.pageable

Object

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

meta.pageable.currentCursor

Null

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

meta.pageable.cursor

Null

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

meta.pageable.pageSize

Null

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Null

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

meta.searchParameters.keyword

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ๊ฒ€์ƒ‰์–ด

meta.searchParameters.regionId

Null

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ง€์—ญ ID

meta.searchParameters.sortType

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ •๋ ฌ ํƒ€์ž…

meta.searchParameters.sortOrder

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ •๋ ฌ ์ˆœ์„œ

meta.searchParameters.cursor

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ปค์„œ ๊ธฐ์ค€

meta.searchParameters.pageSize

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

์ •๋ ฌ ํƒ€์ž… (sortType)

LATEST

์ตœ์‹ 

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

MYBOTTLE_NOT_ACCESSIBLE

FORBIDDEN

์ ‘๊ทผํ•  ์ˆ˜ ์—†๋Š” ๋งˆ์ด๋ณดํ‹€ํŽ˜์ด์ง€์ž…๋‹ˆ๋‹ค.


4.14. ์‚ฌ์šฉ์ž ๋””๋ฐ”์ด์Šค ํ† ํฐ ์ €์žฅ

์‚ฌ์šฉ์ž ๋””๋ฐ”์ด์Šค ํ† ํฐ์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ† ํฐ์€ ํ•œ ์œ ์ €์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ๊ฐœ๊ฐ€ ๋“ฑ๋ก๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ‘ธ์‹œ ์•Œ๋ฆผ์€ ์ตœ์‹  ๊ฐฑ์‹ ์„ ๊ธฐ์ค€์œผ๋กœ 3๊ฐœ๊นŒ์ง€ ๋ฐœ์†ก๋ฉ๋‹ˆ๋‹ค.

  • ๋™์ผํ•œ ํ† ํฐ์œผ๋กœ ์žฌ ๋“ฑ๋ก์‹œ ๊ฐฑ์‹ ์˜ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

POST /api/v1/push/token

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

{
  "deviceToken" : "3c759897-3a3c-46fa-972e-8db381ea5bcb",
  "platform" : "IOS"
}
path type optional description

deviceToken

String

์ €์žฅ๋  ๋””๋ฐ”์ด์Šค ํ† ํฐ

platform

String

๋””๋ฐ”์ด์Šค ์ •๋ณด (IOS, ANDROID)

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

path type description

success

Boolean

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

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.deviceToken

String

์ €์žฅ๋œ ๋””๋ฐ”์ด์Šค ํ† ํฐ

data.platform

String

๋””๋ฐ”์ด์Šค ์ •๋ณด (IOS, ANDROID)

data.message

String

์‘๋‹ต ๋ฉ”์‹œ์ง€

{
  "success" : true,
  "code" : 200,
  "data" : {
    "deviceToken" : "3c759897-3a3c-46fa-972e-8db381ea5bcb",
    "platform" : "IOS",
    "message" : "DEVICE_TOKEN_SAVED"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 13, 688841535 ],
    "serverPathVersion" : "v1"
  }
}

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

DEVICE_TOKEN_REQUIRED

BAD_REQUEST

๋””๋ฐ”์ด์Šค ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

PLATFORM_REQUIRED

BAD_REQUEST

ํ”Œ๋žซํผ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.


5. ๋ฐฐ๋„ˆ (banner) ๊ด€๋ จ API

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

ํ™ˆ ํ™”๋ฉด์— ํ‘œ์‹œํ•  ํ™œ์„ฑํ™”๋œ ๋ฐฐ๋„ˆ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

๋ฐฐ๋„ˆ๋Š” sortOrder ๊ธฐ์ค€ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌ๋˜์–ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

GET /api/v1/banners?limit={limit}

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

Parameter Description

limit

์กฐํšŒํ•  ๋ฐฐ๋„ˆ ๊ฐœ์ˆ˜ (๊ธฐ๋ณธ๊ฐ’: 10, ์ตœ๋Œ€ ๊ถŒ์žฅ: 10)

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ (HTTP ์ƒํƒœ ์ฝ”๋“œ)

data

Array

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

data[].id

Number

๋ฐฐ๋„ˆ ๊ณ ์œ  ์‹๋ณ„์ž

data[].name

String

๋ฐฐ๋„ˆ๋ช…

data[].nameFontColor

String

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

data[].descriptionA

String

๋ฐฐ๋„ˆ ์„ค๋ช… ํŒŒํŠธ A

data[].descriptionB

String

๋ฐฐ๋„ˆ ์„ค๋ช… ํŒŒํŠธ B

data[].descriptionFontColor

String

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

data[].imageUrl

String

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

data[].textPosition

String

ํ…์ŠคํŠธ ์œ„์น˜ (ํ•˜๋‹จ TextPosition ์ฐธ์กฐ)

data[].targetUrl

String

ํด๋ฆญ ์‹œ ์ด๋™ํ•  URL

data[].isExternalUrl

Boolean

์™ธ๋ถ€ URL ์—ฌ๋ถ€ (true: ์™ธ๋ถ€, false: ๋‚ด๋ถ€)

data[].mediaType

String

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

data[].bannerType

String

๋ฐฐ๋„ˆ ์œ ํ˜• (ํ•˜๋‹จ BannerType ์ฐธ์กฐ)

data[].sortOrder

Number

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

data[].startDate

Array

๋…ธ์ถœ ์‹œ์ž‘์ผ์‹œ (nullable)

data[].endDate

Array

๋…ธ์ถœ ์ข…๋ฃŒ์ผ์‹œ (nullable)

errors

Array

์—๋Ÿฌ ๋ชฉ๋ก (์„ฑ๊ณต ์‹œ ๋นˆ ๋ฐฐ์—ด)

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "id" : 1,
    "name" : "์‹ ๊ทœ ์œ„์Šคํ‚ค ์ถœ์‹œ ์ด๋ฒคํŠธ",
    "nameFontColor" : "ffffff",
    "descriptionA" : "์‹ ๊ทœ ์œ„์Šคํ‚ค ์ถœ์‹œ ๊ธฐ๋…",
    "descriptionB" : "ํŠน๋ณ„ ์ด๋ฒคํŠธ๋ฅผ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.",
    "descriptionFontColor" : "ffffff",
    "imageUrl" : "https://cdn.bottle-note.com/banners/event1.jpg",
    "textPosition" : "LB",
    "targetUrl" : "/events/new-whiskey",
    "isExternalUrl" : false,
    "mediaType" : "IMAGE",
    "bannerType" : "CURATION",
    "sortOrder" : 0,
    "startDate" : [ 2025, 1, 1, 0, 0 ],
    "endDate" : [ 2025, 12, 31, 23, 59 ]
  }, {
    "id" : 2,
    "name" : "์‚ฌ์šฉ์ž ์„ค๋ฌธ์กฐ์‚ฌ",
    "nameFontColor" : "ffffff",
    "descriptionA" : "์„œ๋น„์Šค ๊ฐœ์„ ์„ ์œ„ํ•œ",
    "descriptionB" : "์„ค๋ฌธ์กฐ์‚ฌ์— ์ฐธ์—ฌํ•ด์ฃผ์„ธ์š”.",
    "descriptionFontColor" : "ffffff",
    "imageUrl" : "https://cdn.bottle-note.com/banners/survey.jpg",
    "textPosition" : "CENTER",
    "targetUrl" : "https://forms.google.com/survey123",
    "isExternalUrl" : true,
    "mediaType" : "IMAGE",
    "bannerType" : "SURVEY",
    "sortOrder" : 1,
    "startDate" : [ 2025, 6, 1, 0, 0 ],
    "endDate" : [ 2025, 6, 30, 23, 59 ]
  }, {
    "id" : 3,
    "name" : "์ œํœด ๋ธŒ๋žœ๋“œ ์†Œ๊ฐœ",
    "nameFontColor" : "ffffff",
    "descriptionA" : "์ƒˆ๋กœ์šด ์ œํœด ๋ธŒ๋žœ๋“œ๋ฅผ",
    "descriptionB" : "์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.",
    "descriptionFontColor" : "ffffff",
    "imageUrl" : "https://cdn.bottle-note.com/banners/partner.jpg",
    "textPosition" : "RT",
    "targetUrl" : "/partners/brand-abc",
    "isExternalUrl" : false,
    "mediaType" : "VIDEO",
    "bannerType" : "PARTNERSHIP",
    "sortOrder" : 2,
    "startDate" : null,
    "endDate" : null
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 682584333 ],
    "serverPathVersion" : "v1"
  }
}

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

๋ฐฐ๋„ˆ ๋‚ด ํ…์ŠคํŠธ๊ฐ€ ํ‘œ์‹œ๋  ์œ„์น˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์„ค๋ช…

LT

์ขŒ์ธก ์ƒ๋‹จ (Left Top)

LB

์ขŒ์ธก ํ•˜๋‹จ (Left Bottom)

RT

์šฐ์ธก ์ƒ๋‹จ (Right Top)

RB

์šฐ์ธก ํ•˜๋‹จ (Right Bottom)

CENTER

์ค‘์•™ (Center)

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

๋ฐฐ๋„ˆ์˜ ๋ชฉ์ ์— ๋”ฐ๋ฅธ ์œ ํ˜•์„ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์„ค๋ช…

SURVEY

์„ค๋ฌธ์กฐ์‚ฌ ๋ฐฐ๋„ˆ

CURATION

ํ๋ ˆ์ด์…˜ ๋ฐฐ๋„ˆ (์ถ”์ฒœ ์ฝ˜ํ…์ธ )

AD

๊ด‘๊ณ  ๋ฐฐ๋„ˆ

PARTNERSHIP

์ œํœด ๋ฐฐ๋„ˆ

ํด๋ผ์ด์–ธํŠธ ๊ตฌํ˜„ ๊ฐ€์ด๋“œ

1. ๋ฐฐ๋„ˆ ํด๋ฆญ ์‹œ ๋ผ์šฐํŒ… ์ฒ˜๋ฆฌ

if (banner.isExternalUrl) {
    // ์™ธ๋ถ€ ๋ธŒ๋ผ์šฐ์ € ๋˜๋Š” ์ธ์•ฑ ์›น๋ทฐ๋กœ ์—ด๊ธฐ
    openExternalBrowser(banner.targetUrl)
} else {
    // ์•ฑ ๋‚ด๋ถ€ ํ™”๋ฉด์œผ๋กœ ์ด๋™
    navigateToInternalRoute(banner.targetUrl)
}

2. ๋‚ด๋ถ€ URL ๋ผ์šฐํŒ… ์˜ˆ์‹œ

  • ํ˜‘์˜ ํ•„์š” (FE ํŽธํ•œ ๋ฐฉ์‹๋Œ€๋กœ)

3. ํ…์ŠคํŠธ ์˜ค๋ฒ„๋ ˆ์ด ๋ฐฐ์น˜

`textPosition`์— ๋”ฐ๋ผ ๋ฐฐ๋„ˆ ํ…์ŠคํŠธ๋ฅผ ์ด๋ฏธ์ง€ ์œ„์— ์˜ค๋ฒ„๋ ˆ์ดํ•ฉ๋‹ˆ๋‹ค.

  • name: ๋ฐฐ๋„ˆ ์ œ๋ชฉ (์ƒ‰์ƒ: nameFontColor)

  • descriptionA, descriptionB: ๋ฐฐ๋„ˆ ์„ค๋ช… 2์ค„ (์ƒ‰์ƒ: descriptionFontColor)

  • ์ƒ‰์ƒ ๊ฐ’์€ HEX ์ฝ”๋“œ (์˜ˆ: ffffff)

textPosition ๊ฐ’์— ๋”ฐ๋ผ ์ ์ ˆํ•œ ์œ„์น˜์— ํ…์ŠคํŠธ๋ฅผ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค.

ํ…์ŠคํŠธ ํฌ์ง€์…˜์— ๋”ฐ๋ฅธ name, description ์œ„์น˜ TEXT POSITION : ์ƒ์ˆ˜

  • LT (Left Top) : name : ์•„๋ž˜ / description : ์œ„

  • LB (Left Bottom) : name : ์œ„ / description : ์•„๋ž˜

  • RT (Right Top) : name : ์•„๋ž˜ / description : ์œ„

  • RB (Right Bottom) : name : ์œ„ / description : ์•„๋ž˜

  • CENTER (Center) : name : ์•„๋ž˜ / description : ์œ„

์ฐธ๊ณ  ์‚ฌํ•ญ

  • ๋น„ํ™œ์„ฑํ™”๋œ ๋ฐฐ๋„ˆ(isActive=false)๋Š” ์กฐํšŒ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • startDate/`endDate`๊ฐ€ null์ธ ๊ฒฝ์šฐ ์ƒ์‹œ ๋…ธ์ถœ ๋ฐฐ๋„ˆ์ž…๋‹ˆ๋‹ค.

  • `isExternalUrl=true`์ธ ๊ฒฝ์šฐ ์ƒˆ ์ฐฝ(๋˜๋Š” ์™ธ๋ถ€ ๋ธŒ๋ผ์šฐ์ €)์œผ๋กœ ์—ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ธฐ๋ณธ `limit`์€ 10์ด๋ฉฐ, ํ™ˆ ํ™”๋ฉด์—์„œ๋Š” ์ตœ๋Œ€ 10๊ฐœ๊นŒ์ง€ ๋…ธ์ถœ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.

6. ๋‘˜๋Ÿฌ๋ณด๊ธฐ (explore) ๊ด€๋ จ API

6.1. ์œ„์Šคํ‚ค ๋‘˜๋Ÿฌ๋ณด๊ธฐ(standard) API

  • ๊ธฐ๋ณธํ˜• ์œ„์Šคํ‚ค ๋‘˜๋Ÿฌ๋ณด๊ธฐ API๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

  • ์ •๋ ฌ ์˜ต์…˜์ด ์—†๋Š” API ์ž…๋‹ˆ๋‹ค ์‹œ๊ฐ„์ˆœ์œผ๋กœ ์ •๋ ฌ๋ฉ๋‹ˆ๋‹ค

  • ํ‚ค์›Œ๋“œ๋Š” ์ด๋ฆ„, ์นดํ…Œ๊ณ ๋ฆฌ, ์ง€์—ญ , ํƒœ๊ทธ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค.

  • ์—ฌ๋Ÿฌ ํ‚ค์›Œ๋“œ๋Š” ๋ชจ๋‘ AND ์กฐ๊ฑด์œผ๋กœ ๊ฒ€์ƒ‰๋ฉ๋‹ˆ๋‹ค (๋ชจ๋“  ํ‚ค์›Œ๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ํ•ญ๋ชฉ๋งŒ ๊ฒฐ๊ณผ์— ํ‘œ์‹œ)

keywords="keyword1"&keywords="keyword2"
- ํ˜•ํƒœ๋กœ ์—ฌ๋Ÿฌ ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.

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

$ curl 'https://api.bottle-note.com/api/v1/alcohols/explore/standard?keywords=keyword1&keywords=keyword2&cursor=0&size=10' -i -X GET
GET /api/v1/alcohols/explore/standard?keywords=keyword1&keywords=keyword2&cursor=0&size=10 HTTP/1.1
Host: api.bottle-note.com
Parameter Description

keywords

๊ฒ€์ƒ‰์–ด ๋ชฉ๋ก

cursor

์กฐํšŒ ํ•  ์‹œ์ž‘ ๊ธฐ์ค€ ์œ„์น˜

size

์กฐํšŒ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

์ „์ฒด ์ˆ  ๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ

data.items[].alcoholId

Number

์ˆ  ID

data.items[].alcoholUrlImg

String

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

data.items[].korName

String

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

data.items[].engName

String

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

data.items[].korCategory

String

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

data.items[].engCategory

String

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

data.items[].korRegion

String

์ˆ  ํ•œ๊ธ€ ์ง€์—ญ

data.items[].engRegion

String

์ˆ  ์˜๋ฌธ ์ง€์—ญ

data.items[].cask

String

์บ์Šคํฌ ์ •๋ณด

data.items[].abv

String

์•Œ์ฝ”์˜ฌ ๋„์ˆ˜

data.items[].korDistillery

String

ํ•œ๊ธ€ ์ฆ๋ฅ˜์†Œ ์ด๋ฆ„

data.items[].engDistillery

String

์˜๋ฌธ ์ฆ๋ฅ˜์†Œ ์ด๋ฆ„

data.items[].rating

Number

์ˆ  ํ‰์ 

data.items[].totalRatingsCount

Number

์ˆ  ํ‰์  ์ด ๊ฐœ์ˆ˜

data.items[].myRating

Number

๋‚ด ํ‰์ 

data.items[].myAvgRating

Number

๋‚ด ํ‰๊ท  ํ‰์ 

data.items[].isPicked

Boolean

์ˆ  ์ฐœ ์—ฌ๋ถ€

data.items[].alcoholsTastingTags

Array

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

meta.searchParameters.keywords

Array

๊ฒ€์ƒ‰์–ด ์ •๋ณด

meta.pageable

Object

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

meta.pageable.currentCursor

Number

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

meta.pageable.cursor

Number

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

meta.pageable.pageSize

Number

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Boolean

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 500,
    "items" : [ {
      "alcoholId" : 73,
      "alcoholUrlImg" : "https://static.whiskybase.com/storage/whiskies/73/404573-big.jpg",
      "korName" : "๊ธ€๋ Œ๋ฆฌ๋ฒณ 17๋…„ ๋ธ”๋ Œ๋””๋“œ ์œ„์Šคํ‚ค",
      "engName" : "Glenlivet 17 Years Blended",
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "Single Malt",
      "korRegion" : "์Šค์ฝ”ํ‹€๋žœ๋“œ/ํ•˜์ด๋žœ๋“œ",
      "engRegion" : "Scotland/Highlands",
      "cask" : "Pedro Ximenez Sherry Casks",
      "abv" : "51",
      "korDistillery" : "๊ธ€๋ Œ๋ฆฌ๋ฒณ ๋””์Šคํ‹ธ๋Ÿฌ๋ฆฌ",
      "engDistillery" : "Glenlivet Distillery",
      "rating" : 3.5,
      "totalRatingsCount" : 457,
      "myRating" : 1.0,
      "myAvgRating" : 2.5,
      "isPicked" : false,
      "alcoholsTastingTags" : [ "๊ณผ์ผํ–ฅ", "์˜คํฌํ–ฅ", "๊ฟ€ํ–ฅ", "์ดˆ์ฝœ๋ฆฟ", "ํ–ฅ๊ธ‹ํ•œ" ]
    }, {
      "alcoholId" : 63,
      "alcoholUrlImg" : "https://static.whiskybase.com/storage/whiskies/63/404563-big.jpg",
      "korName" : "๋ฐœ๋ฒ ๋‹ˆ 17๋…„ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ์œ„์Šคํ‚ค",
      "engName" : "Balvenie 17 Years Signature",
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "Single Malt",
      "korRegion" : "์Šค์ฝ”ํ‹€๋žœ๋“œ/ํ•˜์ด๋žœ๋“œ",
      "engRegion" : "Scotland/Highlands",
      "cask" : "Pedro Ximenez Sherry Casks",
      "abv" : "40",
      "korDistillery" : "๋ฐœ๋ฒ ๋‹ˆ ๋””์Šคํ‹ธ๋Ÿฌ๋ฆฌ",
      "engDistillery" : "Balvenie Distillery",
      "rating" : 3.5,
      "totalRatingsCount" : 155,
      "myRating" : 1.0,
      "myAvgRating" : 4.0,
      "isPicked" : false,
      "alcoholsTastingTags" : [ "์‹œํŠธ๋Ÿฌ์Šค", "๋ถ€๋“œ๋Ÿฌ์šด", "ํ–ฅ๊ธ‹ํ•œ", "๋ฐ”๋‹๋ผ" ]
    }, {
      "alcoholId" : 95,
      "alcoholUrlImg" : "https://static.whiskybase.com/storage/whiskies/95/404595-big.jpg",
      "korName" : "๊ธ€๋ Œํ”ผ๋”• 17๋…„ ์‹ฑ๊ธ€๋ชฐํŠธ ์œ„์Šคํ‚ค",
      "engName" : "Glenfiddich 17 Years Single Malt",
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "Single Malt",
      "korRegion" : "์Šค์ฝ”ํ‹€๋žœ๋“œ/ํ•˜์ด๋žœ๋“œ",
      "engRegion" : "Scotland/Highlands",
      "cask" : "Pedro Ximenez Sherry Casks",
      "abv" : "41",
      "korDistillery" : "๊ธ€๋ Œํ”ผ๋”• ๋””์Šคํ‹ธ๋Ÿฌ๋ฆฌ",
      "engDistillery" : "Glenfiddich Distillery",
      "rating" : 3.5,
      "totalRatingsCount" : 991,
      "myRating" : 3.5,
      "myAvgRating" : 0.5,
      "isPicked" : false,
      "alcoholsTastingTags" : [ "ํ”ผํŠธํ–ฅ", "๋‹ฌ๋‹ฌํ•œ" ]
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 8, 302090818 ],
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 0,
      "pageSize" : 10,
      "hasNext" : true
    },
    "searchParameters" : {
      "keywords" : [ "keyword1", "keyword2" ]
    },
    "serverPathVersion" : "v1"
  }
}

6.2. ๋ฆฌ๋ทฐ ๋‘˜๋Ÿฌ๋ณด๊ธฐ(standard) API

  • ๊ธฐ๋ณธํ˜• ๋ฆฌ๋ทฐ ๋‘˜๋Ÿฌ๋ณด๊ธฐ API๋กœ, ์‚ฌ์šฉ์ž๋“ค์ด ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ฆฌ๋ทฐ๋Š” ์ตœ์‹ ์ˆœ(์ˆ˜์ • ์‹œ๊ฐ„ ๊ธฐ์ค€)์œผ๋กœ ์ •๋ ฌ๋˜์–ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

  • ๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ๋Š” ์ž‘์„ฑ์ž ์ด๋ฆ„, ์ˆ  ์ด๋ฆ„, ๋ฆฌ๋ทฐ ๋‚ด์šฉ, ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

  • ์—ฌ๋Ÿฌ ํ‚ค์›Œ๋“œ ์ž…๋ ฅ ์‹œ AND ์กฐ๊ฑด์œผ๋กœ ๊ฒ€์ƒ‰๋ฉ๋‹ˆ๋‹ค(๋ชจ๋“  ํ‚ค์›Œ๋“œ๋ฅผ ํฌํ•จํ•˜๋Š” ๋ฆฌ๋ทฐ๋งŒ ๊ฒฐ๊ณผ์— ํ‘œ์‹œ).

keywords="keyword1"&keywords="keyword2"
- ํ˜•ํƒœ๋กœ ์—ฌ๋Ÿฌ ํ‚ค์›Œ๋“œ๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.

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

$ curl 'https://api.bottle-note.com/api/v1/reviews/explore/standard?keywords=%ED%82%A4%EC%9B%8C%EB%93%9C1&keywords=%ED%82%A4%EC%9B%8C%EB%93%9C2&cursor=0&size=20' -i -X GET
GET /api/v1/reviews/explore/standard?keywords=%ED%82%A4%EC%9B%8C%EB%93%9C1&keywords=%ED%82%A4%EC%9B%8C%EB%93%9C2&cursor=0&size=20 HTTP/1.1
Host: api.bottle-note.com
Parameter Description

keywords

๊ฒ€์ƒ‰์–ด ๋ชฉ๋ก (์ž‘์„ฑ์ž, ์ˆ  ์ด๋ฆ„, ๋ฆฌ๋ทฐ ๋‚ด์šฉ, ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ์—์„œ ๊ฒ€์ƒ‰)

cursor

์กฐํšŒ ํ•  ์‹œ์ž‘ ๊ธฐ์ค€ ์œ„์น˜

size

์กฐํšŒ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

์ „์ฒด ๋ฆฌ๋ทฐ ๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ

data.items[].userInfo.userId

Number

์‚ฌ์šฉ์ž ID

data.items[].userInfo.nickName

String

์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„

data.items[].userInfo.userProfileImage

String

์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

data.items[].isMyReview

Boolean

๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

data.items[].alcoholId

Number

์ˆ  ID

data.items[].alcoholName

String

์ˆ  ์ด๋ฆ„

data.items[].reviewId

Number

๋ฆฌ๋ทฐ ID

data.items[].reviewContent

String

๋ฆฌ๋ทฐ ๋‚ด์šฉ

data.items[].reviewRating

Number

๋ฆฌ๋ทฐ ํ‰์ 

data.items[].reviewTags

Array

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

data.items[].createAt

Array

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

data.items[].modifiedAt

Array

๋ฆฌ๋ทฐ ์ˆ˜์ • ์‹œ๊ฐ„

data.items[].totalImageCount

Number

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ ์ด ๊ฐœ์ˆ˜

data.items[].reviewImages

Array

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ URL ๋ชฉ๋ก

data.items[].isBestReview

Boolean

๋ฒ ์ŠคํŠธ ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

data.items[].likeCount

Number

์ข‹์•„์š” ์ˆ˜

data.items[].isLikedByMe

Boolean

๋‚ด๊ฐ€ ์ข‹์•„์š”ํ•œ ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

data.items[].replyCount

Number

๋Œ“๊ธ€ ์ˆ˜

data.items[].hasReplyByMe

Boolean

๋‚ด๊ฐ€ ๋Œ“๊ธ€์„ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

meta.searchParameters.keywords

Array

๊ฒ€์ƒ‰์–ด ์ •๋ณด

meta.pageable

Object

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

meta.pageable.currentCursor

Number

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

meta.pageable.cursor

Number

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

meta.pageable.pageSize

Number

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Boolean

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 500,
    "items" : [ {
      "userInfo" : {
        "userId" : 1,
        "nickName" : "์‚ฌ์šฉ์ž1",
        "userProfileImage" : "https://example.com/profile1.jpg"
      },
      "isMyReview" : true,
      "alcoholId" : 101,
      "alcoholName" : "์‹œ๊ทธ๋„ท ์œ„์Šคํ‚ค 1",
      "reviewId" : 1001,
      "reviewContent" : "์ด ์œ„์Šคํ‚ค๋Š” ์ •๋ง ๋ง›์žˆ์Šต๋‹ˆ๋‹ค. ๊ณผ์ผํ–ฅ๊ณผ ์˜คํฌํ–ฅ์ด ์ ˆ๋ฌ˜ํ•˜๊ฒŒ ์–ด์šฐ๋Ÿฌ์ ธ ์žˆ์–ด์š”. 1",
      "reviewRating" : 4.6,
      "reviewTags" : [ "๋‹ฌ๋‹ฌํ•œ", "๊ณผ์ผํ–ฅ", "์˜คํฌํ–ฅ" ],
      "createAt" : [ 2026, 4, 7, 13, 53, 11, 51120519 ],
      "modifiedAt" : [ 2026, 4, 8, 12, 53, 11, 51135787 ],
      "totalImageCount" : 2,
      "reviewImages" : [ "https://example.com/image1_1.jpg", "https://example.com/image1_2.jpg" ],
      "isBestReview" : false,
      "likeCount" : 10,
      "isLikedByMe" : false,
      "replyCount" : 5,
      "hasReplyByMe" : true
    }, {
      "userInfo" : {
        "userId" : 2,
        "nickName" : "์‚ฌ์šฉ์ž2",
        "userProfileImage" : "https://example.com/profile2.jpg"
      },
      "isMyReview" : false,
      "alcoholId" : 102,
      "alcoholName" : "์‹œ๊ทธ๋„ท ์œ„์Šคํ‚ค 2",
      "reviewId" : 1002,
      "reviewContent" : "์ด ์œ„์Šคํ‚ค๋Š” ์ •๋ง ๋ง›์žˆ์Šต๋‹ˆ๋‹ค. ๊ณผ์ผํ–ฅ๊ณผ ์˜คํฌํ–ฅ์ด ์ ˆ๋ฌ˜ํ•˜๊ฒŒ ์–ด์šฐ๋Ÿฌ์ ธ ์žˆ์–ด์š”. 2",
      "reviewRating" : 4.7,
      "reviewTags" : [ "๋‹ฌ๋‹ฌํ•œ", "๊ณผ์ผํ–ฅ", "์˜คํฌํ–ฅ" ],
      "createAt" : [ 2026, 4, 6, 13, 53, 11, 51186442 ],
      "modifiedAt" : [ 2026, 4, 8, 11, 53, 11, 51194096 ],
      "totalImageCount" : 2,
      "reviewImages" : [ "https://example.com/image2_1.jpg", "https://example.com/image2_2.jpg" ],
      "isBestReview" : true,
      "likeCount" : 20,
      "isLikedByMe" : false,
      "replyCount" : 10,
      "hasReplyByMe" : false
    }, {
      "userInfo" : {
        "userId" : 3,
        "nickName" : "์‚ฌ์šฉ์ž3",
        "userProfileImage" : "https://example.com/profile3.jpg"
      },
      "isMyReview" : false,
      "alcoholId" : 103,
      "alcoholName" : "์‹œ๊ทธ๋„ท ์œ„์Šคํ‚ค 3",
      "reviewId" : 1003,
      "reviewContent" : "์ด ์œ„์Šคํ‚ค๋Š” ์ •๋ง ๋ง›์žˆ์Šต๋‹ˆ๋‹ค. ๊ณผ์ผํ–ฅ๊ณผ ์˜คํฌํ–ฅ์ด ์ ˆ๋ฌ˜ํ•˜๊ฒŒ ์–ด์šฐ๋Ÿฌ์ ธ ์žˆ์–ด์š”. 3",
      "reviewRating" : 4.8,
      "reviewTags" : [ "๋‹ฌ๋‹ฌํ•œ", "๊ณผ์ผํ–ฅ", "์˜คํฌํ–ฅ" ],
      "createAt" : [ 2026, 4, 5, 13, 53, 11, 51229553 ],
      "modifiedAt" : [ 2026, 4, 8, 10, 53, 11, 51236095 ],
      "totalImageCount" : 2,
      "reviewImages" : [ "https://example.com/image3_1.jpg", "https://example.com/image3_2.jpg" ],
      "isBestReview" : false,
      "likeCount" : 30,
      "isLikedByMe" : true,
      "replyCount" : 15,
      "hasReplyByMe" : false
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 11, 54412745 ],
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 20,
      "pageSize" : 20,
      "hasNext" : true
    },
    "searchParameters" : {
      "keywords" : [ "ํ‚ค์›Œ๋“œ1", "ํ‚ค์›Œ๋“œ2" ]
    },
    "serverPathVersion" : "v1"
  }
}

7. ์ˆ  (alcohol) ๊ด€๋ จ API

7.1. ์ˆ (์œ„์Šคํ‚ค) ๋ชฉ๋ก ์กฐํšŒ

๊ฒ€์ƒ‰ ์กฐ๊ฑด์œผ๋กœ ์ˆ (์œ„์Šคํ‚ค) ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

๊ฒ€์ƒ‰์–ด๋ฅผ ํ†ตํ•ด ํ•„ํ„ฐ๋ง ๊ฐ€๋Šฅํ•œ ๋‚ด์—ญ

  • ์œ„์Šคํ‚ค ์ด๋ฆ„ (ํ•œ๊ธ€/์˜๋ฌธ)

  • ์นดํ…Œ๊ณ ๋ฆฌ (ํ•œ๊ธ€/์˜๋ฌธ)

  • ์ง€์—ญ (ํ•œ๊ธ€/์˜๋ฌธ)

  • ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ (ํ•œ๊ธ€/์˜๋ฌธ)

  • ํ๋ ˆ์ด์…˜ ํ‚ค์›Œ๋“œ (์‹œ์ฆŒ๋ณ„/์ƒํ™ฉ๋ณ„ ์ถ”์ฒœ ๋“ฑ)

    • ํ๋ ˆ์ด์…˜ ํ‚ค์›Œ๋“œ๋กœ ๊ฒ€์ƒ‰ ์‹œ, ํ•ด๋‹น ํ๋ ˆ์ด์…˜์— ํฌํ•จ๋œ ์œ„์Šคํ‚ค ๋ชฉ๋ก์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค

    • ์˜ˆ: ๋ด„ ์ถ”์ฒœ ์œ„์Šคํ‚ค, ์—ฌ๋ฆ„ ์ถ”์ฒœ ์œ„์Šคํ‚ค, ๋น„ ์˜ค๋Š” ๋‚  ์ถ”์ฒœ ์œ„์Šคํ‚ค ๋“ฑ

    • ํ๋ ˆ์ด์…˜ ํ‚ค์›Œ๋“œ๋Š” ๋™์ ์œผ๋กœ ๊ด€๋ฆฌ๋˜๋ฏ€๋กœ, ์ƒˆ๋กœ์šด ํ๋ ˆ์ด์…˜์ด ์ถ”๊ฐ€๋˜๊ฑฐ๋‚˜ ๊ธฐ์กด ํ๋ ˆ์ด์…˜์ด ์ˆ˜์ •๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

    • ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ๋ ˆ์ด์…˜ ํ‚ค์›Œ๋“œ ๋ชฉ๋ก์€ ํ๋ ˆ์ด์…˜ ํ‚ค์›Œ๋“œ ์กฐํšŒ API๋ฅผ ํ†ตํ•ด ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค

    • ํŠน์ • ํ๋ ˆ์ด์…˜์˜ ์œ„์Šคํ‚ค๋งŒ ์กฐํšŒํ•˜๋ ค๋ฉด ํ๋ ˆ์ด์…˜ ์œ„์Šคํ‚ค ๋ชฉ๋ก ์กฐํšŒ API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค

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

$ http GET 'https://api.bottle-note.com/api/v1/alcohols/search?keyword=glen&category=SINGLE_MALT&regionId=1&sortType=REVIEW&sortOrder=DESC&cursor=0&pageSize=3'
Parameter Description

keyword

๊ฒ€์ƒ‰์–ด (์•Œ์ฝ”์˜ฌ ์ด๋ฆ„, ์นดํ…Œ๊ณ ๋ฆฌ, ํƒœ์ŠคํŒ… ํƒœ๊ทธ๋กœ ๊ฒ€์ƒ‰) - ์—ฌ๋Ÿฌ ๋‹จ์–ด ์ž…๋ ฅ ์‹œ ๋„์–ด์“ฐ๊ธฐ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ AND ๊ฒ€์ƒ‰ - ์˜ˆ: '์กฐ๋‹ˆ ๋ธ”๋ž™' โ†’ '์กฐ๋‹ˆ’์™€ '๋ธ”๋ž™' ๋ชจ๋‘ ํฌํ•จ๋œ ๊ฒฐ๊ณผ

curationId

ํ๋ ˆ์ด์…˜ ID (ํŠน์ • ํ๋ ˆ์ด์…˜์— ํฌํ•จ๋œ ์•Œ์ฝ”์˜ฌ๋งŒ ํ•„ํ„ฐ๋ง) - keyword์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ ์‹œ curationId๊ฐ€ ์šฐ์„  ์ ์šฉ - ํ๋ ˆ์ด์…˜ ๋ชฉ๋ก์€ /api/v1/curations API์—์„œ ์กฐํšŒ ๊ฐ€๋Šฅ

category

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

regionId

์ง€์—ญ ID ํ•„ํ„ฐ (region API ์ฐธ์กฐ) - ์˜ˆ: 1=์Šค์ฝ”ํ‹€๋žœ๋“œ, 2=์•„์ผ๋žœ๋“œ ๋“ฑ

sortType

์ •๋ ฌ ํƒ€์ž… (๊ธฐ๋ณธ๊ฐ’: POPULAR) - POPULAR: ์ธ๊ธฐ์ˆœ - REVIEW: ๋ฆฌ๋ทฐ ๋งŽ์€ ์ˆœ - RATING: ํ‰์  ๋†’์€ ์ˆœ

sortOrder

์ •๋ ฌ ์ˆœ์„œ (๊ธฐ๋ณธ๊ฐ’: DESC) - DESC: ๋‚ด๋ฆผ์ฐจ์ˆœ - ASC: ์˜ค๋ฆ„์ฐจ์ˆœ

cursor

์ปค์„œ ํŽ˜์ด์ง€๋„ค์ด์…˜ ์‹œ์ž‘ ์œ„์น˜ (๊ธฐ๋ณธ๊ฐ’: 0) - ๋‹ค์Œ ํŽ˜์ด์ง€ ์กฐํšŒ ์‹œ ์ด์ „ ์‘๋‹ต์˜ cursor ๊ฐ’ ์‚ฌ์šฉ

pageSize

ํŽ˜์ด์ง€ ํฌ๊ธฐ (๊ธฐ๋ณธ๊ฐ’: 10) - ํ•œ ๋ฒˆ์— ์กฐํšŒํ•  ์•„์ดํ…œ ๊ฐœ์ˆ˜

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

์ „์ฒด ์ˆ  ๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ

data.alcohols[].alcoholId

Number

์ˆ  ID

data.alcohols[].imageUrl

String

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

data.alcohols[].korName

String

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

data.alcohols[].engName

String

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

data.alcohols[].korCategoryName

String

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

data.alcohols[].engCategoryName

String

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

data.alcohols[].rating

Number

์ˆ  ํ‰์ 

data.alcohols[].ratingCount

Number

์ˆ  ํ‰์  ๊ฐœ์ˆ˜

data.alcohols[].reviewCount

Number

์ˆ  ๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜

data.alcohols[].pickCount

Number

์ˆ  ์ฐœ ๊ฐœ์ˆ˜

data.alcohols[].isPicked

Boolean

์ˆ  ์ฐœ ์—ฌ๋ถ€

meta.pageable

Object

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

meta.pageable.currentCursor

Number

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

meta.pageable.cursor

Number

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

meta.pageable.pageSize

Number

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Boolean

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

meta.searchParameters.keyword

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ๋œ ๊ฒ€์ƒ‰์–ด (์ž…๋ ฅ๊ฐ’ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜)

meta.searchParameters.curationId

Null

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ๋œ ํ๋ ˆ์ด์…˜ ID (์ž…๋ ฅ๊ฐ’ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜)

meta.searchParameters.category

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ๋œ ์นดํ…Œ๊ณ ๋ฆฌ ํ•„ํ„ฐ

meta.searchParameters.regionId

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ๋œ ์ง€์—ญ ID ํ•„ํ„ฐ

meta.searchParameters.sortType

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ๋œ ์ •๋ ฌ ํƒ€์ž…

meta.searchParameters.sortOrder

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ๋œ ์ •๋ ฌ ์ˆœ์„œ

meta.searchParameters.cursor

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ๋œ ์ปค์„œ ์œ„์น˜

meta.searchParameters.pageSize

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ๋œ ํŽ˜์ด์ง€ ํฌ๊ธฐ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 5,
    "alcohols" : [ {
      "alcoholId" : 5,
      "korName" : "์•„๋…น 24๋…„",
      "engName" : "anCnoc 24-year-old",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "imageUrl" : "https://static.whiskybase.com/storage/whiskies/6/6/989/270671-big.jpg",
      "rating" : 4.5,
      "ratingCount" : 1,
      "reviewCount" : 0,
      "pickCount" : 1,
      "isPicked" : false
    }, {
      "alcoholId" : 1,
      "korName" : "๊ธ€๋ž˜์Šค๊ณ  1770 ์‹ฑ๊ธ€๋ชฐํŠธ ์Šค์นด์น˜ ์œ„์Šคํ‚ค",
      "engName" : "1770 Glasgow Single Malt",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "imageUrl" : "https://static.whiskybase.com/storage/whiskies/2/0/8916/404538-big.jpg",
      "rating" : 3.5,
      "ratingCount" : 3,
      "reviewCount" : 1,
      "pickCount" : 1,
      "isPicked" : true
    }, {
      "alcoholId" : 2,
      "korName" : "๊ธ€๋ž˜์Šค๊ณ  1770 ์‹ฑ๊ธ€๋ชฐํŠธ ์Šค์นด์น˜ ์œ„์Šคํ‚ค",
      "engName" : "1770 Glasgow Single Malt",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "imageUrl" : "https://static.whiskybase.com/storage/whiskies/2/0/8888/404535-big.jpg",
      "rating" : 3.5,
      "ratingCount" : 1,
      "reviewCount" : 0,
      "pickCount" : 1,
      "isPicked" : true
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 8, 807473955 ],
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 4,
      "pageSize" : 3,
      "hasNext" : true
    },
    "searchParameters" : {
      "keyword" : "glen",
      "curationId" : null,
      "category" : "SINGLE_MALT",
      "regionId" : 1,
      "sortType" : "REVIEW",
      "sortOrder" : "DESC",
      "cursor" : 0,
      "pageSize" : 3
    },
    "serverPathVersion" : "v1"
  }
}
์ •๋ ฌ ํƒ€์ž… (sortType)

POPULAR

์ธ๊ธฐ์ˆœ

RATING

๋ณ„์ ์ˆœ

PICK

์ฐœ์ˆœ

REVIEW

๋ฆฌ๋ทฐ์ˆœ

  • ํ•ด๋‹น ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ POPULAR ์ž…๋‹ˆ๋‹ค.

  • ํƒ€์ž…์ด ์ž˜๋ชป ์ „๋‹ฌ๋  ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

์ •๋ ฌ ๋ฐฉํ–ฅ (sortOrder)
  • ํ•ด๋‹น ์ •์˜๋Š” ์ •๋ ฌ ๋ฐฉํ–ฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค.

  • ์„œ๋น„์Šค์˜ ๋ชจ๋“  ์ •๋ ฌ ๊ด€๋ จ API์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

DESC

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

5 → 3 → 2 → 1

ASC

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

1 → 2 → 3 → 5

  • ๋žœ๋ค์˜ ๊ฒฝ์šฐ ์ •๋ ฌ ํƒ€์ž…์— ๋”ฐ๋ผ ์˜๋„์™€ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ•ด๋‹น ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ DESC(๋‚ด๋ฆผ์ฐจ์ˆœ) ์ž…๋‹ˆ๋‹ค.

  • ํƒ€์ž…์ด ์ž˜๋ชป ์ „๋‹ฌ๋  ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.


7.2. ์ˆ (์œ„์Šคํ‚ค) ์ƒ์„ธ ์กฐํšŒ

๊ฒ€์ƒ‰ ์กฐ๊ฑด์œผ๋กœ ์ˆ (์œ„์Šคํ‚ค) ์ •๋ณด๋ฅผ ์ƒ์„ธ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

๋…ธ์ถœ๋˜๋Š” ๊ฐ’์ด ๋งค์šฐ ๋งŽ๊ณ  ๋ณต์žกํ•˜๋‹ค ๋ณด๋‹ˆ ์ˆ˜์ • ์‚ฌํ•ญ์ด ๋ฐœ์ƒ ์‹œ ๋ฌธ์„œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š”๋ฐ ์‹œ๊ฐ„์ด ์†Œ์š”๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€์ ์ธ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•˜์‹  ๊ฒฝ์šฐ, ๋ฌธ์˜ํ•ด ์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

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

GET /api/v1/alcohols/{alcoholsId}
  • alcoholsId : ์กฐํšŒํ•  ์ˆ (์œ„์Šคํ‚ค)์˜ ID

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.alcohols.alcoholId

Number

์ˆ  ID

data.alcohols.alcoholUrlImg

String

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

data.alcohols.korName

String

์ˆ ์˜ ํ•œ๊ตญ์–ด ์ด๋ฆ„

data.alcohols.engName

String

์ˆ ์˜ ์˜์–ด ์ด๋ฆ„

data.alcohols.korCategory

String

์ˆ ์˜ ํ•œ๊ตญ์–ด ์นดํ…Œ๊ณ ๋ฆฌ

data.alcohols.engCategory

String

์ˆ ์˜ ์˜์–ด ์นดํ…Œ๊ณ ๋ฆฌ

data.alcohols.korRegion

String

์ˆ ์˜ ํ•œ๊ตญ์–ด ์ง€์—ญ

data.alcohols.engRegion

String

์ˆ ์˜ ์˜์–ด ์ง€์—ญ

data.alcohols.cask

String

์ˆ ์˜ ์ˆ™์„ฑ ์บ์Šคํฌ ์ •๋ณด

data.alcohols.abv

String

์ˆ ์˜ ๋„์ˆ˜

data.alcohols.korDistillery

String

์ˆ  ์ œ์กฐ์‚ฌ์˜ ํ•œ๊ตญ์–ด ์ด๋ฆ„

data.alcohols.engDistillery

String

์ˆ  ์ œ์กฐ์‚ฌ์˜ ์˜์–ด ์ด๋ฆ„

data.alcohols.rating

Number

์ˆ ์˜ ํ‰๊ท  ํ‰์ 

data.alcohols.totalRatingsCount

Number

์ด ํ‰์  ์ฐธ์—ฌ์ž ์ˆ˜

data.alcohols.myRating

Number

๋‚ด๊ฐ€ ์ค€ ํ‰์ 

data.alcohols.myAvgRating

Number

๋‚ด๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ์ค€ ํ‰๊ท  ํ‰์ (๋ฆฌ๋ทฐ์˜ ๋ณ„์ ์„ ๊ธฐ๋ฐ˜)

data.alcohols.isPicked

Boolean

๋‚ด๊ฐ€ ์ข‹์•„์š”ํ•œ ์ˆ ์ธ์ง€ ์—ฌ๋ถ€

data.alcohols.alcoholsTastingTags

Array

์ˆ ์˜ ํƒœ๊ทธ ๋ชฉ๋ก

data.friendsInfo.followerCount

Number

ํŒ”๋กœ์›Œ ์ˆ˜

data.friendsInfo.friends[].userImageUrl

String

์นœ๊ตฌ์˜ ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

data.friendsInfo.friends[].userId

Number

์นœ๊ตฌ์˜ ์‚ฌ์šฉ์ž ID

data.friendsInfo.friends[].nickName

String

์นœ๊ตฌ์˜ ๋‹‰๋„ค์ž„

data.friendsInfo.friends[].rating

Number

์นœ๊ตฌ์˜ ํ‰์ 

data.reviewInfo.totalCount

Number

ํ•ด๋‹น ์ˆ ์˜ ์ด ๋ฆฌ๋ทฐ ์ˆ˜

data.reviewInfo.reviewList[].reviewId

Number

๋ฆฌ๋ทฐ ID

data.reviewInfo.reviewList[].reviewContent

String

๋ฆฌ๋ทฐ ๋‚ด์šฉ

data.reviewInfo.reviewList[].price

Number

๋ฆฌ๋ทฐ ๊ฐ€๊ฒฉ

data.reviewInfo.reviewList[].sizeType

String

๋ฆฌ๋ทฐ ์‚ฌ์ด์ฆˆ ํƒ€์ž…

data.reviewInfo.reviewList[].likeCount

Number

๋ฆฌ๋ทฐ ์ข‹์•„์š” ์ˆ˜

data.reviewInfo.reviewList[].replyCount

Number

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

data.reviewInfo.reviewList[].reviewImageUrl

String

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ URL

data.reviewInfo.reviewList[].totalImageCount

Null

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ ์ด๊ฐœ์ˆ˜

data.reviewInfo.reviewList[].userInfo.userId

Number

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ž ID

data.reviewInfo.reviewList[].userInfo.nickName

String

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ž ๋‹‰๋„ค์ž„

data.reviewInfo.reviewList[].userInfo.userProfileImage

String

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ž ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

data.reviewInfo.reviewList[].rating

Number

๋ฆฌ๋ทฐ ํ‰์ 

data.reviewInfo.reviewList[].viewCount

Number

๋ฆฌ๋ทฐ ์กฐํšŒ์ˆ˜

data.reviewInfo.reviewList[].locationInfo

Object

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ •๋ณด

data.reviewInfo.reviewList[].locationInfo.name

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ๋ช…

data.reviewInfo.reviewList[].locationInfo.zipCode

Null

๋ฆฌ๋ทฐ ์žฅ์†Œ ์šฐํŽธ๋ฒˆํ˜ธ

data.reviewInfo.reviewList[].locationInfo.address

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ฃผ์†Œ

data.reviewInfo.reviewList[].locationInfo.detailAddress

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ƒ์„ธ ์ฃผ์†Œ

data.reviewInfo.reviewList[].locationInfo.category

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์นดํ…Œ๊ณ ๋ฆฌ

data.reviewInfo.reviewList[].locationInfo.mapUrl

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ง€๋„ URL

data.reviewInfo.reviewList[].locationInfo.latitude

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์œ„๋„

data.reviewInfo.reviewList[].locationInfo.longitude

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ๊ฒฝ๋„

data.reviewInfo.reviewList[].status

String

๋ฆฌ๋ทฐ ๊ณต๊ฐœ ์—ฌ๋ถ€ (PUBLIC/PRIVATE)

data.reviewInfo.reviewList[].isMyReview

Boolean

๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ์ธ์ง€ ์—ฌ๋ถ€

data.reviewInfo.reviewList[].isLikedByMe

Boolean

๋‚ด๊ฐ€ ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €๋Š”์ง€ ์—ฌ๋ถ€

data.reviewInfo.reviewList[].hasReplyByMe

Boolean

๋‚ด๊ฐ€ ๋Œ“๊ธ€์„ ๋‹ฌ์•˜๋Š”์ง€ ์—ฌ๋ถ€

data.reviewInfo.reviewList[].isBestReview

Boolean

๋ฒ ์ŠคํŠธ ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

data.reviewInfo.reviewList[].tastingTagList

Array

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

data.reviewInfo.reviewList[].createAt

Array

๋ฆฌ๋ทฐ ์ž‘์„ฑ ๋‚ ์งœ 'yyyyMMddHHmm' ํฌ๋งท

{
  "success" : true,
  "code" : 200,
  "data" : {
    "alcohols" : {
      "alcoholId" : 42,
      "alcoholUrlImg" : "https://static.whiskybase.com/storage/whiskies/42/404542-big.jpg",
      "korName" : "๊ธ€๋ Œํ”ผ๋”• 20๋…„ ๋”๋ธ” ์บ์Šคํฌ ์œ„์Šคํ‚ค",
      "engName" : "Glenfiddich 20 Years Double Cask",
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "Single Malt",
      "korRegion" : "์Šค์ฝ”ํ‹€๋žœ๋“œ/ํ•˜์ด๋žœ๋“œ",
      "engRegion" : "Scotland/Highlands",
      "cask" : "Ex-Bourbon Casks",
      "abv" : "42",
      "korDistillery" : "๊ธ€๋ Œํ”ผ๋”• ๋””์Šคํ‹ธ๋Ÿฌ๋ฆฌ",
      "engDistillery" : "Glenfiddich Distillery",
      "rating" : 3.5,
      "totalRatingsCount" : 778,
      "myRating" : 5.0,
      "myAvgRating" : 2.0,
      "isPicked" : true,
      "alcoholsTastingTags" : [ "๋‹ฌ๋‹ฌํ•œ", "๋ฐ”๋‹๋ผ", "ํ›„์ถ”ํ–ฅ์˜" ]
    },
    "friendsInfo" : {
      "followerCount" : 6,
      "friends" : [ {
        "userImageUrl" : "https://picsum.photos/600/600",
        "userId" : 1,
        "nickName" : "๋Š™์€์ฝ”๋ผ๋ฆฌ",
        "rating" : 4.5
      }, {
        "userImageUrl" : "https://picsum.photos/600/600",
        "userId" : 2,
        "nickName" : "๋‚˜๋ฌด์‚ฌ์ž",
        "rating" : 1.5
      }, {
        "userImageUrl" : "https://picsum.photos/600/600",
        "userId" : 3,
        "nickName" : "ํ”ผ์žํŒŒ์ธ์• ํ”Œ",
        "rating" : 3.0
      }, {
        "userImageUrl" : "https://picsum.photos/600/600",
        "userId" : 4,
        "nickName" : "๋ฉ˜ํ† ์Šค",
        "rating" : 0.5
      }, {
        "userImageUrl" : "https://picsum.photos/600/600",
        "userId" : 5,
        "nickName" : "๋ฏผํŠธ๋ง›์น˜ํ† ์Šค",
        "rating" : 5.0
      }, {
        "userImageUrl" : "https://picsum.photos/600/600",
        "userId" : 6,
        "nickName" : "๋ชฉ๋ฐ์ดํ„ฐ",
        "rating" : 1.0
      } ]
    },
    "reviewInfo" : {
      "totalCount" : 2,
      "reviewList" : [ {
        "reviewId" : 0,
        "reviewContent" : "์ข‹์€ ๋ฆฌ๋ทฐ์ž…๋‹ˆ๋‹ค (qCxdGFQlqb)",
        "reviewImageUrl" : "https://example.com/review-image.jpg",
        "createAt" : [ 2026, 4, 8, 13, 53, 8, 912395776 ],
        "totalImageCount" : null,
        "userInfo" : {
          "userId" : 1,
          "nickName" : "ํ™๊ธธ๋™",
          "userProfileImage" : "https://example.com/profile.jpg"
        },
        "isMyReview" : true,
        "status" : "PUBLIC",
        "isBestReview" : false,
        "locationInfo" : {
          "name" : "๋„์‹œ์ˆ ",
          "zipCode" : null,
          "address" : "์„œ์šธ ์†กํŒŒ๊ตฌ ์†กํŒŒ๋Œ€๋กœ 145",
          "detailAddress" : "2์ธต ๋„์‹œ์ˆ ",
          "category" : "์Œ์‹์  > ์ˆ ์ง‘ > ์นตํ…Œ์ผ๋ฐ”",
          "mapUrl" : "https://place.map.kakao.com/2088591613",
          "latitude" : "37.4835934678036",
          "longitude" : "127.122831408454"
        },
        "sizeType" : "BOTTLE",
        "price" : 100000,
        "rating" : 4.5,
        "likeCount" : 10,
        "replyCount" : 2,
        "isLikedByMe" : false,
        "hasReplyByMe" : true,
        "viewCount" : 0,
        "tastingTagList" : [ "๊ณผ์ผํ–ฅ", "๋ถ€๋“œ๋Ÿฌ์›€" ]
      }, {
        "reviewId" : 1,
        "reviewContent" : "์ข‹์€ ๋ฆฌ๋ทฐ์ž…๋‹ˆ๋‹ค (wiOpzrTmFJ)",
        "reviewImageUrl" : "https://example.com/review-image.jpg",
        "createAt" : [ 2026, 4, 8, 13, 53, 8, 912467059 ],
        "totalImageCount" : null,
        "userInfo" : {
          "userId" : 1,
          "nickName" : "ํ™๊ธธ๋™",
          "userProfileImage" : "https://example.com/profile.jpg"
        },
        "isMyReview" : true,
        "status" : "PUBLIC",
        "isBestReview" : false,
        "locationInfo" : {
          "name" : "๋„์‹œ์ˆ ",
          "zipCode" : null,
          "address" : "์„œ์šธ ์†กํŒŒ๊ตฌ ์†กํŒŒ๋Œ€๋กœ 145",
          "detailAddress" : "2์ธต ๋„์‹œ์ˆ ",
          "category" : "์Œ์‹์  > ์ˆ ์ง‘ > ์นตํ…Œ์ผ๋ฐ”",
          "mapUrl" : "https://place.map.kakao.com/2088591613",
          "latitude" : "37.4835934678036",
          "longitude" : "127.122831408454"
        },
        "sizeType" : "BOTTLE",
        "price" : 100000,
        "rating" : 4.5,
        "likeCount" : 10,
        "replyCount" : 2,
        "isLikedByMe" : false,
        "hasReplyByMe" : true,
        "viewCount" : 0,
        "tastingTagList" : [ "๊ณผ์ผํ–ฅ", "๋ถ€๋“œ๋Ÿฌ์›€" ]
      } ]
    }
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 8, 914952266 ],
    "serverPathVersion" : "v1"
  }
}
  • Boolean ์—ฌ๋ถ€๋Š” header์— bearer ํ† ํฐ์„ ์ฐธ์กฐํ•ด ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. Authorization: Bearer {token}

  • ๋ณ€์ˆ˜๋ช…์—์„œ ์ˆ˜์ •์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ, ๋ฌธ์˜ํ•ด ์ฃผ์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.


7.3. ์ˆ (์œ„์Šคํ‚ค) ์ฐœํ•˜๊ธฐ /์ฐœํ•˜๊ธฐ ํ•ด์ œ

์ˆ (์œ„์Šคํ‚ค)์˜ ์‹๋ณ„์ž์™€ ์กฐ๊ฑด๊ฐ’์„ ํ†ตํ•ด ์ฐœํ•˜๊ธฐ/์ฐœํ•˜๊ธฐ ํ•ด์ œ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜๋‹จ ์ƒ์ˆ˜๋ฅผ ํ†ตํ•ด ์ฐœํ•˜๊ธฐ์™€ ์ฐœํ•˜๊ธฐ ํ•ด์ œ๋ฅผ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

PUT apv/v1/picks

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

path type optional description

alcoholId

Number

์ฐœ ํ•  ์ˆ (์œ„์Šคํ‚ค)์˜ ์‹๋ณ„์ž

isPicked

String

์ฐœ ์—ฌ๋ถ€ (ํ•˜๋‹จ Picks Status ์ฐธ์กฐ)

{
  "alcoholId" : 1,
  "isPicked" : "PICK"
}

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.message

String

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

data.status

String

์—…๋ฐ์ดํŠธ๋œ ์ฐœ ์ƒํƒœ

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€(์—†์„ ๊ฒฝ์šฐ null)

{
  "success" : true,
  "code" : 200,
  "data" : {
    "message" : "์ •์ƒ์ ์œผ๋กœ ์ฐœํ•˜๊ธฐ ์ฒ˜๋ฆฌ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "status" : "PICK"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 344285923 ],
    "serverPathVersion" : "v1"
  }
}

Picks Status

์ฝ”๋“œ ์„ค๋ช…

PICK

์ฐœ ํ•˜๊ธฐ

UNPICK

์ฐœํ•˜๊ธฐ ํ•ด์ œ

Error code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

ALCOHOL_ID_REQUIRED

BAD_REQUEST

์•Œ์ฝ”์˜ฌ ์‹๋ณ„์ž๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

ALCOHOL_ID_MINIMUM

BAD_REQUEST

์•Œ์ฝ”์˜ฌ ์‹๋ณ„์ž๋Š” ์ตœ์†Œ 1 ์ด์ƒ ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

IS_PICKED_REQUIRED

BAD_REQUEST

์ฐœํ•˜๊ธฐ ์—ฌ๋ถ€๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

USER_NOT_FOUND

NOT_FOUND

์œ ์ €๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.


7.4. ์ง€์—ญ(๋ฆฌ์ „) ์ •๋ณด ์กฐํšŒ

๊ฒ€์ƒ‰ ์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์ง€์—ญ ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

์ง€์—ญ ์ •๋ณด๋Š” ์„œ๋ฒ„์˜ ๋กœ์ปฌ ์บ์‹œ๋กœ ๊ด€๋ฆฌ๋˜๋ฉฐ ์ผ ๋‹จ์œ„๋กœ ๊ฐฑ์‹ ๋ฉ๋‹ˆ๋‹ค.

GET /api/v1/regions

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data[].regionId

Number

์ง€์—ญ ID

data[].korName

String

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

data[].engName

String

์ง€์—ญ ์ด๋ฆ„

data[].description

String

์ง€์—ญ ์„ค๋ช…

data[].parentId

Number

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

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€(์—†์„ ๊ฒฝ์šฐ null)

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "regionId" : 1,
    "korName" : "์Šค์ฝ”ํ‹€๋žœ๋“œ/๋กœ์šฐ๋žœ๋“œ",
    "engName" : "Scotland/Lowlands",
    "description" : "๊ฐ€๋ฒผ์šด ๋ง›์ด ํŠน์ง•์ธ ๋กœ์šฐ๋žœ๋“œ ์œ„์Šคํ‚ค",
    "parentId" : 19
  }, {
    "regionId" : 2,
    "korName" : "์Šค์ฝ”ํ‹€๋žœ๋“œ/ํ•˜์ด๋žœ๋“œ",
    "engName" : "Scotland/Highlands",
    "description" : "๋ง›์˜ ๋‹ค์–‘์„ฑ์ด ํŠน์ง•์ธ ํ•˜์ด๋žœ๋“œ ์œ„์Šคํ‚ค, ํ•ด์•ˆ์˜ ์ง ๋ง›๋ถ€ํ„ฐ ๋‹ฌ์ฝคํ•˜๊ณ  ๊ณผ์ผ ๋ง›๊นŒ์ง€",
    "parentId" : 19
  }, {
    "regionId" : 3,
    "korName" : "์Šค์ฝ”ํ‹€๋žœ๋“œ/์•„์ผ๋žœ๋“œ",
    "engName" : "Scotland/Ireland",
    "description" : "๋ถ€๋“œ๋Ÿฌ์šด ๋ง›์ด ํŠน์ง•์ธ ์•„์ผ๋žœ๋“œ ์œ„์Šคํ‚ค",
    "parentId" : 19
  }, {
    "regionId" : 11,
    "korName" : "ํ”„๋ž‘์Šค",
    "engName" : "France",
    "description" : "์ฃผ๋กœ ๋ธŒ๋žœ๋””์™€ ์™€์ธ ์ƒ์‚ฐ์ง€๋กœ ์œ ๋ช…ํ•˜์ง€๋งŒ ์œ„์Šคํ‚ค๋„ ์ƒ์‚ฐ",
    "parentId" : null
  }, {
    "regionId" : 12,
    "korName" : "์Šค์›จ๋ด",
    "engName" : "Sweden",
    "description" : "์‹คํ—˜์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ๋งŒ๋“œ๋Š” ์Šค์›จ๋ด ์œ„์Šคํ‚ค",
    "parentId" : null
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 496791253 ],
    "serverPathVersion" : "v1"
  }
}

7.5. ์นดํ…Œ๊ณ ๋ฆฌ ๋ชฉ๋ก ์กฐํšŒ

์นดํ…Œ๊ณ ๋ฆฌ ๋ชฉ๋ก์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๋‹น ๊ธฐ๋Šฅ์€ ํ”„๋ก ํŠธ ๊ฐœ๋ฐœ ์‹œ ์‚ฌ์šฉ๋˜๋Š” ์นดํ…Œ๊ณ ๋ฆฌ ๊ฐ’์„ ๊ฒ€์ฆํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

  • ๊ฒ€์ƒ‰์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน ์ •๋ณด๋Š” ์ตœํ•˜๋‹จ ํ…Œ์ด๋ธ”์„ ์ฐธ๊ณ ํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

  • DB ์— ์ €์žฅ๋˜์–ด ๊ด€๋ฆฌ๋˜๋Š” ์นดํ…Œ๊ณ ๋ฆฌ์™€ ๊ฒ€์ƒ‰ ์กฐ๊ฑด์œผ๋กœ ๊ด€๋ฆฌ๋˜๋Š” ์นดํ…Œ๊ณ ๋ฆฌ๋Š” ๋ณ„๋„๋กœ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

  • ์˜ˆ๋ฅผ ๋“ค์–ด `Spirit`๋ผ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ ๋ช…์€ ์กด์žฌ ํ•˜๊ณ  ๋…ธ์ถœ๋„ ๋˜์ง€๋งŒ ๊ฒ€์ƒ‰ ์กฐ๊ฑด์œผ๋กœ๋Š” `ETC`๋ผ๋Š” ์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

  • ์ด๋Š” ์ถ”ํ›„ ํ™•์žฅ๋  ์—ฌ์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

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

GET /api/v1/alcohols/categories?type=WHISKY HTTP/1.1
Host: api.bottle-note.com
Parameter Description

type

์นดํ…Œ๊ณ ๋ฆฌ ํƒ€์ž… (ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

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

path type description

data[].korCategory

String

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

data[].engCategory

String

์นดํ…Œ๊ณ ๋ฆฌ ์˜์–ด ์ด๋ฆ„

data[].categoryGroup

String

์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน (์นดํ…Œ๊ณ ๋ฆฌ ๊ฒ€์ƒ‰ ์กฐ๊ฑด ์‚ฌ์šฉ ์‹œ ์‚ฌ์šฉ)

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "korCategory" : "SINGLE_MOLT",
    "engCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
    "categoryGroup" : "SINGLE_MALT"
  }, {
    "korCategory" : "BLENDED",
    "engCategory" : "๋ธ”๋ Œ๋””๋“œ",
    "categoryGroup" : "BLEND"
  }, {
    "korCategory" : "BOURBON",
    "engCategory" : "๋ฒ„๋ฒˆ",
    "categoryGroup" : "BOURBON"
  }, {
    "korCategory" : "RYE",
    "engCategory" : "๋ผ์ด",
    "categoryGroup" : "RYE"
  }, {
    "korCategory" : "OTHER",
    "engCategory" : "๊ธฐํƒ€",
    "categoryGroup" : "OTHER"
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 532099765 ],
    "serverPathVersion" : "v1"
  }
}
  • ์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃบ์€ ์‹ค์ œ ๊ฒ€์ƒ‰์‹œ ์‚ฌ์šฉ ๋˜๋Š” ์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉ ๋˜๋Š” ๊ฐ’ ์ž…๋‹ˆ๋‹ค.

  • ์•Œ์ฝ”์˜ฌ์˜ ๊ฒ€์ƒ‰ ์กฐ๊ฑด์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์กฐ๊ฑด์€ ์•„๋ž˜์˜ ํ‘œ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

  • '_' ๊ธฐํ˜ธ๊ฐ€ ํฌํ•จ๋œ ๊ฒฝ์šฐ ํ•ด๋‹น ๊ธฐํ˜ธ ๋ˆ„๋ฝ ์‹œ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์นดํ…Œ๊ณ ๋ฆฌ ๊ฒ€์ƒ‰ ์กฐ๊ฑด
์˜๋ฌธ ํ•œ๊ธ€

SINGLE_MALT

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

BLEND

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

BLENDED_MALT

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

BOURBON

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

RYE

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

OTHER

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

  • ์œ„์Šคํ‚ค๋ฅผ ์ œ์™ธํ•œ ์ˆ ์˜ ์ข…๋ฅ˜ ๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ๋˜๋Š” ์กฐ๊ฑด ๊ฐ’์ž…๋‹ˆ๋‹ค.

  • ํ˜„์žฌ๋กœ์„œ๋Š” ์œ„์Šคํ‚ค๋งŒ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน ์กฐ๊ฑด
์˜๋ฌธ ํ•œ๊ธ€

WHISKY

์œ„์Šคํ‚ค (๊ธฐ๋ณธ๊ฐ’)

RUM

๋Ÿผ

VODKA

๋ณด๋“œ์นด

GIN

์ง„

TEQUILA

๋ฐํ‚ฌ๋ผ

BRANDY

๋ธŒ๋žœ๋””

BEER

๋งฅ์ฃผ

WINE

์™€์ธ

ETC

๊ธฐํƒ€


7.6. ํ๋ ˆ์ด์…˜ ํ‚ค์›Œ๋“œ ์กฐํšŒ

ํ๋ ˆ์ด์…˜ ํ‚ค์›Œ๋“œ๋Š” ํŠน์ • ์ฃผ์ œ๋‚˜ ์ƒํ™ฉ์— ๋งž๋Š” ์œ„์Šคํ‚ค๋ฅผ ๋ชจ์•„๋†“์€ ์ปฌ๋ ‰์…˜์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด "๋ด„ ์ถ”์ฒœ ์œ„์Šคํ‚ค"๋ผ๋Š” ํ๋ ˆ์ด์…˜์€ ๋ด„์ฒ ์— ์–ด์šธ๋ฆฌ๋Š” ์œ„์Šคํ‚ค๋“ค์„ ๋ฏธ๋ฆฌ ์„ ์ •ํ•ด๋‘” ๋ชฉ๋ก์ด๋ฉฐ, "๋น„ ์˜ค๋Š” ๋‚  ์ถ”์ฒœ ์œ„์Šคํ‚ค"๋Š” ๋น„์˜ค๋Š” ๋‚  ๋ถ„์œ„๊ธฐ์— ๋งž๋Š” ์œ„์Šคํ‚ค๋“ค์„ ๋ชจ์•„๋†“์€ ์ปฌ๋ ‰์…˜์ž…๋‹ˆ๋‹ค.

๊ธฐ์กด์—๋Š” ์‹œ์ฆŒ๋ณ„ ์ถ”์ฒœ ํ‚ค์›Œ๋“œ(๋ด„/์—ฌ๋ฆ„/๊ฐ€์„/๊ฒจ์šธ/๋น„์˜ค๋Š”๋‚ )๊ฐ€ ์ฝ”๋“œ์— ๊ณ ์ •๋˜์–ด ์žˆ์—ˆ์ง€๋งŒ, ์ด์ œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋™์ ์œผ๋กœ ๊ด€๋ฆฌ๋˜์–ด ์ƒˆ๋กœ์šด ํ๋ ˆ์ด์…˜์„ ์ž์œ ๋กญ๊ฒŒ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ ํ๋ ˆ์ด์…˜์€ ์ด๋ฆ„, ์„ค๋ช…๊ณผ ํ•จ๊ป˜ ์ปค๋ฒ„ ์ด๋ฏธ์ง€(coverImageUrl)๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ์‹œ๊ฐ์ ์œผ๋กœ ๋งค๋ ฅ์ ์ธ UI ๊ตฌ์„ฑ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์ปค๋ฒ„ ์ด๋ฏธ์ง€ ๊ถŒ์žฅ ๊ทœ๊ฒฉ
16:9 ์™€์ด๋“œ ๋น„์œจ (์˜ˆ: 800x450px ๋˜๋Š” 1600x900px)์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค.
์œ„์Šคํ‚ค ๋ณ‘์ด๋‚˜ ๋ถ„์œ„๊ธฐ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฐ์Šคํฌํ†ฑ๊ณผ ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ ๋ชจ๋‘์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.
GET /api/v1/curations

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

Parameter Description

keyword

ํ๋ ˆ์ด์…˜ ํ‚ค์›Œ๋“œ ์ด๋ฆ„ ๊ฒ€์ƒ‰ (๋ถ€๋ถ„ ์ผ์น˜)

alcoholId

์œ„์Šคํ‚ค ์‹๋ณ„์ž๋กœ ๊ฒ€์ƒ‰ - ํ•ด๋‹น ID์˜ ์œ„์Šคํ‚ค๊ฐ€ ํฌํ•จ๋œ ํ๋ ˆ์ด์…˜ ์กฐํšŒ (์˜ˆ: alcoholId=123 ๊ฒ€์ƒ‰ ์‹œ ID๊ฐ€ 123์ธ ์œ„์Šคํ‚ค๊ฐ€ ํฌํ•จ๋œ ๋ชจ๋“  ํ๋ ˆ์ด์…˜ ๋ฐ˜ํ™˜)

cursor

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

pageSize

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

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

path type description

success

Boolean

์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.items

Array

ํ๋ ˆ์ด์…˜ ํ‚ค์›Œ๋“œ ๋ชฉ๋ก

data.items[].id

Number

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

data.items[].name

String

ํ๋ ˆ์ด์…˜ ์ด๋ฆ„

data.items[].description

String

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

data.items[].coverImageUrl

String

ํ๋ ˆ์ด์…˜ ์ปค๋ฒ„ ์ด๋ฏธ์ง€ URL

data.items[].alcoholCount

Number

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

data.items[].displayOrder

Number

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

data.pageable

Object

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

data.pageable.currentCursor

Number

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

data.pageable.cursor

Number

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

data.pageable.pageSize

Number

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

data.pageable.hasNext

Boolean

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

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.serverVersion

String

์„œ๋ฒ„ ๋ฒ„์ „

meta.serverEncoding

String

์„œ๋ฒ„ ์ธ์ฝ”๋”ฉ

meta.serverResponseTime

Array

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

meta.serverPathVersion

String

API ๊ฒฝ๋กœ ๋ฒ„์ „

errors

Array

์—๋Ÿฌ ์ •๋ณด

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "items" : [ {
      "id" : 1,
      "name" : "๋ด„ ์ถ”์ฒœ ์œ„์Šคํ‚ค",
      "description" : "๋ด„์— ์–ด์šธ๋ฆฌ๋Š” ์œ„์Šคํ‚ค ๋ชจ์Œ",
      "coverImageUrl" : "https://example.com/spring-whisky.jpg",
      "alcoholCount" : 10,
      "displayOrder" : 1
    }, {
      "id" : 2,
      "name" : "์—ฌ๋ฆ„ ์ถ”์ฒœ ์œ„์Šคํ‚ค",
      "description" : "์—ฌ๋ฆ„์— ์–ด์šธ๋ฆฌ๋Š” ์œ„์Šคํ‚ค ๋ชจ์Œ",
      "coverImageUrl" : "https://example.com/summer-whisky.jpg",
      "alcoholCount" : 8,
      "displayOrder" : 2
    } ],
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 10,
      "pageSize" : 10,
      "hasNext" : false
    }
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 150945785 ],
    "serverPathVersion" : "v1"
  }
}

์‚ฌ์šฉ ์˜ˆ์‹œ

  • ์ „์ฒด ํ๋ ˆ์ด์…˜ ๋ชฉ๋ก ์กฐํšŒ

    GET /api/v1/curations?cursor=0&pageSize=10

    ๋ด„/์—ฌ๋ฆ„/๊ฐ€์„/๊ฒจ์šธ ์ถ”์ฒœ ์œ„์Šคํ‚ค ๋“ฑ ๋ชจ๋“  ํ๋ ˆ์ด์…˜ ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ํŠน์ • ํ‚ค์›Œ๋“œ๋กœ ๊ฒ€์ƒ‰

    GET /api/v1/curations?keyword=๋ด„&cursor=0&pageSize=10

    "๋ด„"์ด๋ผ๋Š” ํ‚ค์›Œ๋“œ๊ฐ€ ํฌํ•จ๋œ ํ๋ ˆ์ด์…˜๋งŒ ํ•„ํ„ฐ๋งํ•˜์—ฌ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ํŠน์ • ์œ„์Šคํ‚ค๊ฐ€ ํฌํ•จ๋œ ํ๋ ˆ์ด์…˜ ๊ฒ€์ƒ‰

    GET /api/v1/curations?alcoholId=123&cursor=0&pageSize=10

    ID๊ฐ€ 123์ธ ์œ„์Šคํ‚ค๊ฐ€ ํฌํ•จ๋œ ๋ชจ๋“  ํ๋ ˆ์ด์…˜์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด "๊ธ€๋ Œํ”ผ๋”• 15๋…„"์ด "๋ด„ ์ถ”์ฒœ ์œ„์Šคํ‚ค"์™€ "๋น„์˜ค๋Š” ๋‚  ์ถ”์ฒœ ์œ„์Šคํ‚ค"์— ๋ชจ๋‘ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋ฉด ๋‘ ํ๋ ˆ์ด์…˜์ด ๋ชจ๋‘ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.


7.7. ํ๋ ˆ์ด์…˜ ์œ„์Šคํ‚ค ๋ชฉ๋ก ์กฐํšŒ

ํŠน์ • ํ๋ ˆ์ด์…˜์— ํฌํ•จ๋œ ์œ„์Šคํ‚ค ๋ชฉ๋ก์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

ํ๋ ˆ์ด์…˜ ๋ชฉ๋ก ์กฐํšŒ API์—์„œ ๋ฐ›์€ ํ๋ ˆ์ด์…˜ ID๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๋‹น ํ๋ ˆ์ด์…˜์— ์†ํ•œ ์œ„์Šคํ‚ค๋“ค์˜ ์ƒ์„ธ ์ •๋ณด(ํ‰์ , ๋ฆฌ๋ทฐ ์ˆ˜, ์ฐœ ํšŸ์ˆ˜ ๋“ฑ)๋ฅผ ํ•จ๊ป˜ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

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

Table 1. /api/v1/curations/{curationId}/alcohols
Parameter Description

curationId

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

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

Parameter Description

cursor

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

pageSize

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

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

path type description

success

Boolean

์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.items

Array

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

data.items[].alcoholId

Number

์œ„์Šคํ‚ค ID

data.items[].korName

String

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

data.items[].engName

String

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

data.items[].korCategoryName

String

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

data.items[].engCategoryName

String

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

data.items[].imageUrl

String

์ด๋ฏธ์ง€ URL

data.items[].rating

Number

ํ‰์ 

data.items[].ratingCount

Number

ํ‰์  ๊ฐœ์ˆ˜

data.items[].reviewCount

Number

๋ฆฌ๋ทฐ ๊ฐœ์ˆ˜

data.items[].pickCount

Number

์ฐœ ๊ฐœ์ˆ˜

data.items[].isPicked

Boolean

์ฐœ ์—ฌ๋ถ€

data.pageable

Object

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

data.pageable.currentCursor

Number

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

data.pageable.cursor

Number

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

data.pageable.pageSize

Number

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

data.pageable.hasNext

Boolean

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

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.serverVersion

String

์„œ๋ฒ„ ๋ฒ„์ „

meta.serverEncoding

String

์„œ๋ฒ„ ์ธ์ฝ”๋”ฉ

meta.serverResponseTime

Array

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

meta.serverPathVersion

String

API ๊ฒฝ๋กœ ๋ฒ„์ „

errors

Array

์—๋Ÿฌ ์ •๋ณด

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "items" : [ {
      "alcoholId" : 1,
      "korName" : "๊ธ€๋ Œํ”ผ๋”• 15๋…„",
      "engName" : "Glenfiddich 15",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "imageUrl" : "https://example.com/image.jpg",
      "rating" : 4.5,
      "ratingCount" : 100,
      "reviewCount" : 50,
      "pickCount" : 30,
      "isPicked" : false
    } ],
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 10,
      "pageSize" : 10,
      "hasNext" : false
    }
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 215090518 ],
    "serverPathVersion" : "v1"
  }
}

์‚ฌ์šฉ ์˜ˆ์‹œ

"๋ด„ ์ถ”์ฒœ ์œ„์Šคํ‚ค" ํ๋ ˆ์ด์…˜์˜ ID๊ฐ€ 1๋ฒˆ์ด๋ผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

GET /api/v1/curations/1/alcohols?cursor=0&pageSize=10

์ด ์š”์ฒญ์€ ๋ด„์ฒ ์— ์–ด์šธ๋ฆฌ๋Š” ์œ„์Šคํ‚ค ๋ชฉ๋ก๊ณผ ํ•จ๊ป˜ ๊ฐ ์œ„์Šคํ‚ค์˜ ํ‰์ , ๋ฆฌ๋ทฐ ์ˆ˜, ์ฐœ ํšŸ์ˆ˜ ๋“ฑ์˜ ์ •๋ณด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.


7.8. ์ฃผ๊ฐ„ ์ธ๊ธฐ ์œ„์Šคํ‚ค ์กฐํšŒ

์ฃผ๊ฐ„ ์ธ๊ธฐ ์œ„์Šคํ‚ค๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

parameter top์ด 10์ผ ๊ฒฝ์šฐ, ์ฃผ๊ฐ„ ์ธ๊ธฐ ์œ„์Šคํ‚ค 10๊ฐœ๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

parameter๊ฐ€ ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ ๊ฐ’์€ 5์ž…๋‹ˆ๋‹ค.

GET /api/v1/popular/week

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

Parameter Description

top

์กฐํšŒํ•  ์ฃผ๊ฐ„ ์ธ๊ธฐ ์ˆ  ๋ชฉ๋ก ์‚ฌ์ด์ฆˆ(๊ฐฏ์ˆ˜)

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

์ฃผ๊ฐ„ ์ธ๊ธฐ ์ˆ  ๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ

data.alcohols

Array

์ฃผ๊ฐ„ ์ธ๊ธฐ ์ˆ  ๋ฆฌ์ŠคํŠธ

data.alcohols[].alcoholId

Number

์ˆ  ID

data.alcohols[].korName

String

์ˆ  ์ด๋ฆ„

data.alcohols[].engName

String

์ˆ  ์˜๋ฌธ๋ช…

data.alcohols[].rating

Number

์ˆ ์˜ ํ‰๊ท  ํ‰์ 

data.alcohols[].ratingCount

Number

์ˆ ์˜ ํ‰์  ์ฐธ์—ฌ์ž ์ˆ˜

data.alcohols[].korCategory

String

์ˆ  ์นดํ…Œ๊ณ ๋ฆฌ

data.alcohols[].engCategory

String

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

data.alcohols[].imageUrl

String

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

data.alcohols[].isPicked

Boolean

๋‚ด๊ฐ€ ์ฐœํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€

data.alcohols[].popularScore

Number

์ธ๊ธฐ๋„ ์ ์ˆ˜

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 5,
    "alcohols" : [ {
      "alcoholId" : 1,
      "korName" : "๊ธ€๋ Œํ”ผ๋”•",
      "engName" : "Glenfiddich",
      "rating" : 1.0,
      "ratingCount" : 56,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.01
    }, {
      "alcoholId" : 2,
      "korName" : "๋งฅ์บ˜๋ž€",
      "engName" : "Macallan",
      "rating" : 0.5,
      "ratingCount" : 9,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : true,
      "popularScore" : 0.0
    }, {
      "alcoholId" : 3,
      "korName" : "๊ธ€๋ Œ๋ฆฌ๋ฒณ",
      "engName" : "Glenlivet",
      "rating" : 2.5,
      "ratingCount" : 4,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.01
    }, {
      "alcoholId" : 4,
      "korName" : "๋ฐœ๋ฒ ๋‹ˆ",
      "engName" : "Balvenie",
      "rating" : 2.0,
      "ratingCount" : 57,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : true,
      "popularScore" : 0.0
    }, {
      "alcoholId" : 5,
      "korName" : "๋ผํ”„๋กœ์ต",
      "engName" : "Laphroaig",
      "rating" : 1.0,
      "ratingCount" : 85,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.0
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 454730454 ],
    "serverPathVersion" : "v1"
  }
}

7.9. ๋ด„ ์‹œ์ฆŒ ์ธ๊ธฐ ์œ„์Šคํ‚ค ์กฐํšŒ

๋ด„ ์ธ๊ธฐ ์œ„์Šคํ‚ค๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/popular/spring

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

$ curl 'https://api.bottle-note.com/api/v1/popular/spring' -i -X GET

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data[].alcoholId

Number

์ˆ  ID

data[].korName

String

์ˆ  ์ด๋ฆ„

data[].engName

String

์ˆ  ์˜๋ฌธ๋ช…

data[].rating

Number

์ˆ ์˜ ํ‰๊ท  ํ‰์ 

data[].ratingCount

Number

์ˆ ์˜ ํ‰์  ์ฐธ์—ฌ์ž ์ˆ˜

data[].korCategory

String

์ˆ  ์นดํ…Œ๊ณ ๋ฆฌ

data[].engCategory

String

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

data[].imageUrl

String

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

data[].isPicked

Boolean

๋‚ด๊ฐ€ ์ฐœํ–ˆ๋Š”์ง€ ์—ฌ๋ถ€

data[].popularScore

Number

์ธ๊ธฐ๋„ ์ ์ˆ˜

{
  "success" : true,
  "code" : 200,
  "data" : [ {
    "alcoholId" : 1,
    "korName" : "๊ธ€๋ Œํ”ผ๋”•",
    "engName" : "Glenfiddich",
    "rating" : 0.5,
    "ratingCount" : 85,
    "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
    "engCategory" : "single molt",
    "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
    "isPicked" : false,
    "popularScore" : 0.01
  }, {
    "alcoholId" : 2,
    "korName" : "๋งฅ์บ˜๋ž€",
    "engName" : "Macallan",
    "rating" : 1.5,
    "ratingCount" : 81,
    "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
    "engCategory" : "single molt",
    "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
    "isPicked" : true,
    "popularScore" : 0.0
  }, {
    "alcoholId" : 3,
    "korName" : "๊ธ€๋ Œ๋ฆฌ๋ฒณ",
    "engName" : "Glenlivet",
    "rating" : 0.0,
    "ratingCount" : 63,
    "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
    "engCategory" : "single molt",
    "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
    "isPicked" : false,
    "popularScore" : 0.0
  }, {
    "alcoholId" : 4,
    "korName" : "๋ฐœ๋ฒ ๋‹ˆ",
    "engName" : "Balvenie",
    "rating" : 2.0,
    "ratingCount" : 80,
    "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
    "engCategory" : "single molt",
    "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
    "isPicked" : true,
    "popularScore" : 0.0
  }, {
    "alcoholId" : 5,
    "korName" : "๋ผํ”„๋กœ์ต",
    "engName" : "Laphroaig",
    "rating" : 0.0,
    "ratingCount" : 92,
    "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
    "engCategory" : "single molt",
    "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
    "isPicked" : false,
    "popularScore" : 0.0
  } ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 415019991 ],
    "serverPathVersion" : "v1"
  }
}

7.10. ์ฃผ๊ฐ„ ์กฐํšŒ์ˆ˜ ๊ธฐ๋ฐ˜ ์ธ๊ธฐ ์œ„์Šคํ‚ค ์กฐํšŒ

์ฃผ๊ฐ„ ์กฐํšŒ์ˆ˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ธ๊ธฐ ์œ„์Šคํ‚ค๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

์กฐํšŒ์ˆ˜๊ฐ€ ๋ถ€์กฑํ•œ ๊ฒฝ์šฐ ํ‰์ ์ด ๋†’์€ ์œ„์Šคํ‚ค๋กœ ์ฑ„์›Œ์„œ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/popular/view/week

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

Parameter Description

top

์กฐํšŒํ•  ์œ„์Šคํ‚ค ๊ฐœ์ˆ˜ (๊ธฐ๋ณธ๊ฐ’: 20)

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

์กฐํšŒ๋œ ์œ„์Šคํ‚ค ๊ฐœ์ˆ˜

data.alcohols

Array

์ฃผ๊ฐ„ ์กฐํšŒ์ˆ˜ ๊ธฐ๋ฐ˜ ์ธ๊ธฐ ์œ„์Šคํ‚ค ๋ฆฌ์ŠคํŠธ

data.alcohols[].alcoholId

Number

์œ„์Šคํ‚ค ID

data.alcohols[].korName

String

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

data.alcohols[].engName

String

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

data.alcohols[].rating

Number

ํ‰๊ท  ํ‰์ 

data.alcohols[].ratingCount

Number

ํ‰์  ์ฐธ์—ฌ์ž ์ˆ˜

data.alcohols[].korCategory

String

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

data.alcohols[].engCategory

String

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

data.alcohols[].imageUrl

String

์ด๋ฏธ์ง€ URL

data.alcohols[].isPicked

Boolean

์ฐœ ์—ฌ๋ถ€

data.alcohols[].popularScore

Number

์ธ๊ธฐ๋„ ์ ์ˆ˜ (์กฐํšŒ์ˆ˜ ๊ธฐ๋ฐ˜)

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 5,
    "alcohols" : [ {
      "alcoholId" : 1,
      "korName" : "๊ธ€๋ Œํ”ผ๋”•",
      "engName" : "Glenfiddich",
      "rating" : 1.0,
      "ratingCount" : 34,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.01
    }, {
      "alcoholId" : 2,
      "korName" : "๋งฅ์บ˜๋ž€",
      "engName" : "Macallan",
      "rating" : 0.0,
      "ratingCount" : 55,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : true,
      "popularScore" : 0.0
    }, {
      "alcoholId" : 3,
      "korName" : "๊ธ€๋ Œ๋ฆฌ๋ฒณ",
      "engName" : "Glenlivet",
      "rating" : 1.5,
      "ratingCount" : 92,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.0
    }, {
      "alcoholId" : 4,
      "korName" : "๋ฐœ๋ฒ ๋‹ˆ",
      "engName" : "Balvenie",
      "rating" : 2.0,
      "ratingCount" : 48,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : true,
      "popularScore" : 0.01
    }, {
      "alcoholId" : 5,
      "korName" : "๋ผํ”„๋กœ์ต",
      "engName" : "Laphroaig",
      "rating" : 1.5,
      "ratingCount" : 64,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.01
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 312404823 ],
    "serverPathVersion" : "v1"
  }
}

7.11. ์›”๊ฐ„ ์กฐํšŒ์ˆ˜ ๊ธฐ๋ฐ˜ ์ธ๊ธฐ ์œ„์Šคํ‚ค ์กฐํšŒ

์›”๊ฐ„ ์กฐํšŒ์ˆ˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ธ๊ธฐ ์œ„์Šคํ‚ค๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

์กฐํšŒ์ˆ˜๊ฐ€ ๋ถ€์กฑํ•œ ๊ฒฝ์šฐ ํ‰์ ์ด ๋†’์€ ์œ„์Šคํ‚ค๋กœ ์ฑ„์›Œ์„œ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/popular/view/monthly

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

Parameter Description

top

์กฐํšŒํ•  ์œ„์Šคํ‚ค ๊ฐœ์ˆ˜ (๊ธฐ๋ณธ๊ฐ’: 20)

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

์กฐํšŒ๋œ ์œ„์Šคํ‚ค ๊ฐœ์ˆ˜

data.alcohols

Array

์›”๊ฐ„ ์กฐํšŒ์ˆ˜ ๊ธฐ๋ฐ˜ ์ธ๊ธฐ ์œ„์Šคํ‚ค ๋ฆฌ์ŠคํŠธ

data.alcohols[].alcoholId

Number

์œ„์Šคํ‚ค ID

data.alcohols[].korName

String

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

data.alcohols[].engName

String

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

data.alcohols[].rating

Number

ํ‰๊ท  ํ‰์ 

data.alcohols[].ratingCount

Number

ํ‰์  ์ฐธ์—ฌ์ž ์ˆ˜

data.alcohols[].korCategory

String

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

data.alcohols[].engCategory

String

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

data.alcohols[].imageUrl

String

์ด๋ฏธ์ง€ URL

data.alcohols[].isPicked

Boolean

์ฐœ ์—ฌ๋ถ€

data.alcohols[].popularScore

Number

์ธ๊ธฐ๋„ ์ ์ˆ˜ (์กฐํšŒ์ˆ˜ ๊ธฐ๋ฐ˜)

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 5,
    "alcohols" : [ {
      "alcoholId" : 1,
      "korName" : "๊ธ€๋ Œํ”ผ๋”•",
      "engName" : "Glenfiddich",
      "rating" : 2.0,
      "ratingCount" : 35,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.01
    }, {
      "alcoholId" : 2,
      "korName" : "๋งฅ์บ˜๋ž€",
      "engName" : "Macallan",
      "rating" : 2.0,
      "ratingCount" : 40,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : true,
      "popularScore" : 0.01
    }, {
      "alcoholId" : 3,
      "korName" : "๊ธ€๋ Œ๋ฆฌ๋ฒณ",
      "engName" : "Glenlivet",
      "rating" : 2.0,
      "ratingCount" : 40,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.0
    }, {
      "alcoholId" : 4,
      "korName" : "๋ฐœ๋ฒ ๋‹ˆ",
      "engName" : "Balvenie",
      "rating" : 2.0,
      "ratingCount" : 72,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : true,
      "popularScore" : 0.01
    }, {
      "alcoholId" : 5,
      "korName" : "๋ผํ”„๋กœ์ต",
      "engName" : "Laphroaig",
      "rating" : 1.5,
      "ratingCount" : 22,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.01
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 373126595 ],
    "serverPathVersion" : "v1"
  }
}

7.12. ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ์ถ”์ถœ

๋ฌธ์žฅ(๋ฆฌ๋ทฐ ๋‚ด์šฉ ๋“ฑ)์—์„œ ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

  • ์ž…๋ ฅ๋œ ํ…์ŠคํŠธ์—์„œ ๋“ฑ๋ก๋œ ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ์™€ ๋งค์นญ๋˜๋Š” ๋‹จ์–ด๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

  • ๋ถ€๋ถ„ ๋งค์นญ์€ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. (์˜ˆ: "๋ฐ”๋‹๋ผ๋นˆ"์—์„œ "๋ฐ”๋‹๋ผ"๋Š” ์ถ”์ถœ๋˜์ง€ ์•Š์Œ)

  • ๋งค์นญ๋˜๋Š” ํƒœ๊ทธ๊ฐ€ ์—†์œผ๋ฉด ๋นˆ ๋ฐฐ์—ด์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

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

$ http GET 'http://localhost:8080/api/v1/tasting-tags/extract?text=%EB%B0%94%EB%8B%90%EB%9D%BC+%ED%96%A5%EC%9D%B4+%EC%A2%8B%EA%B3%A0+%EA%BF%80+%EA%B0%99%EC%9D%80+%EB%8B%A8%EB%A7%9B%EC%97%90+%EC%8A%A4%EB%AA%A8%ED%82%A4+%ED%95%A8%EC%9D%B4+%EB%8A%90%EA%BB%B4%EC%A0%B8%EC%9A%94'
Parameter Description

text

ํƒœ๊ทธ๋ฅผ ์ถ”์ถœํ•  ๋ฌธ์žฅ (๋ฆฌ๋ทฐ ๋‚ด์šฉ ๋“ฑ)

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

path type description

success

Boolean

์„ฑ๊ณต ์—ฌ๋ถ€

code

Number

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

data

Array

์ถ”์ถœ๋œ ํƒœ๊ทธ ์ด๋ฆ„ ๋ชฉ๋ก (๋ฌธ์ž์—ด ๋ฐฐ์—ด)

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.serverVersion

String

์„œ๋ฒ„ ๋ฒ„์ „

meta.serverEncoding

String

์„œ๋ฒ„ ์ธ์ฝ”๋”ฉ

meta.serverResponseTime

Array

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

meta.serverPathVersion

String

API ๊ฒฝ๋กœ ๋ฒ„์ „

errors

Array

์—๋Ÿฌ ์ •๋ณด

{
  "success" : true,
  "code" : 200,
  "data" : [ "๋ฐ”๋‹๋ผ", "๊ฟ€", "์Šค๋ชจํ‚ค" ],
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 618272428 ],
    "serverPathVersion" : "v1"
  }
}

8. ๋ฆฌ๋ทฐ (review) ๊ด€๋ จ API

8.1. ๋ฆฌ๋ทฐ ๋“ฑ๋ก

๋ฆฌ๋ทฐ ๋“ฑ๋ก ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. RequestBody๋กœ ์š”์ฒญ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

  • content๋Š” ๋ฐ˜๋“œ์‹œ ์กด์žฌํ•ด์•ผ ํ•˜๋ฉฐ 700์ž๋ฅผ ๋„˜์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

  • status์˜ ๊ธฐ๋ณธ๊ฐ’์€ PUBLIC์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.

  • locationInfo์™€ imageUrlList๋Š” NULL์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ์ง€๋Š” ์ตœ๋Œ€ 5์žฅ๊นŒ์ง€ ์—…๋กœ๋“œ๊ฐ€ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค.

  • tastingTagList๋Š” 15๊ฐœ๊นŒ์ง€ ํ—ˆ์šฉ๋˜๋ฉฐ, ๊ฐ tastingTag๋Š” ์ตœ๋Œ€ 12์ž ๊ธธ์ด๋กœ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค.

๋ฆฌ๋ทฐ ๋“ฑ๋ก์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ˆ˜ํ–‰๋˜๋ฉด, ์ €์žฅ๋œ ๋ฆฌ๋ทฐ์˜ ID์™€ ๋ฆฌ๋ทฐ ๋‚ด์šฉ, ๊ทธ๋ฆฌ๊ณ  ๋ฆฌ๋ทฐ๋ฅผ ์ž‘์„ฑํ•œ ์œ„์Šคํ‚ค์˜ ๋ฆฌ๋ทฐ ์กฐํšŒ URL์ด ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

POST /api/v1/reviews

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

path type optional description

alcoholId

Number

์ˆ  ID

content

String

๋ฆฌ๋ทฐ ๋‚ด์šฉ (์ตœ๋Œ€ 700์ž)

status

String

๋ฆฌ๋ทฐ ์ƒํƒœ

price

Number

๊ฐ€๊ฒฉ

sizeType

String

์ˆ  ํƒ€์ž… (์ž” or ๋ณ‘

locationInfo

Object

์œ„์น˜ ์ •๋ณด

locationInfo.locationName

String

O

์ƒํ˜ธ ๋ช…

locationInfo.zipCode

String

O

์šฐํŽธ๋ฒˆํ˜ธ

locationInfo.address

String

O

์ฃผ์†Œ

locationInfo.detailAddress

String

O

์ƒ์„ธ ์ฃผ์†Œ

locationInfo.category

String

O

์นดํ…Œ๊ณ ๋ฆฌ

locationInfo.mapUrl

String

O

์ง€๋„ URL

locationInfo.latitude

String

O

์œ„๋„(x์ขŒํ‘œ)

locationInfo.longitude

String

O

๊ฒฝ๋„(y์ขŒํ‘œ)

imageUrlList

Array

์ด๋ฏธ์ง€ URL ๋ชฉ๋ก

imageUrlList[].order

Number

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

imageUrlList[].viewUrl

String

์ด๋ฏธ์ง€ ๋ทฐ URL

tastingTagList[]

Array

ํ…Œ์ด์ŠคํŒ… ํƒœ๊ทธ ๋ชฉ๋ก (์ตœ๋Œ€ 15๊ฐœ)

rating

Number

๋ฆฌ๋ทฐ๋ณ„์  (ํ•ด๋‹น ๋ฆฌ๋ทฐ๋ฅผ ๋‚จ๊ธธ ์‹œ์ ์˜ ๋ณ„์  )

{
  "alcoholId" : 1,
  "status" : "PUBLIC",
  "content" : "๋ง›์žˆ์–ด์š”",
  "sizeType" : "GLASS",
  "price" : 30000,
  "locationInfo" : {
    "locationName" : "xxPub",
    "zipCode" : "12345",
    "address" : "์„œ์šธ์‹œ ๊ฐ•๋‚จ๊ตฌ ์ฒญ๋‹ด๋™",
    "detailAddress" : "xx๋นŒ๋”ฉ",
    "category" : "PUB",
    "mapUrl" : "https://api.bottle-note.com",
    "latitude" : "111.111",
    "longitude" : "222.222"
  },
  "imageUrlList" : [ {
    "order" : 1,
    "viewUrl" : "https://api.bottle-note.com/images/1"
  }, {
    "order" : 2,
    "viewUrl" : "https://api.bottle-note.com/images/2"
  }, {
    "order" : 3,
    "viewUrl" : "https://api.bottle-note.com/images/3"
  } ],
  "tastingTagList" : [ "ํ…Œ์ด์ŠคํŒ…ํƒœ๊ทธ1", "ํ…Œ์ด์ŠคํŒ…ํƒœ๊ทธ2", "ํ…Œ์ด์ŠคํŒ…ํƒœ๊ทธ3" ],
  "rating" : 0.5
}

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

path type description

success

Boolean

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

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.id

Number

์ƒ์„ฑ๋œ ๋ฆฌ๋ทฐ ID

data.content

String

๋ฆฌ๋ทฐ ๋‚ด์šฉ

data.callback

String

์ฝœ๋ฐฑ URL

errors

Array

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

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

meta.serverVersion

String

์„œ๋ฒ„ ๋ฒ„์ „

meta.serverEncoding

String

์„œ๋ฒ„ ์ธ์ฝ”๋”ฉ

meta.serverResponseTime

Array

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

meta.serverPathVersion

String

์„œ๋ฒ„ ๊ฒฝ๋กœ ๋ฒ„์ „

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 358

{
  "success" : true,
  "code" : 200,
  "data" : {
    "id" : 1,
    "content" : "๋ง›์žˆ์–ด์š”",
    "callback" : "https://bottle-note.com/api/v1/reviews/1"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 853543649 ],
    "serverPathVersion" : "v1"
  }
}

ReviewStatus

์ฝ”๋“œ ์„ค๋ช…

PUBLIC

๊ณต๊ฐœ(๊ธฐ๋ณธ ๊ฐ’)

PRIVATE

๋น„๊ณต๊ฐœ

SizeType

์ฝ”๋“œ ์„ค๋ช…

GLASS

์ž”

BOTTLE

๋ณ‘

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUIRED_REVIEW_ID

BAD_REQUEST

๋ฆฌ๋ทฐ ์•„์ด๋””๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

REVIEW_ID_MINIMUM

BAD_REQUEST

๋ฆฌ๋ทฐ ์‹๋ณ„์ž๋Š” ์ตœ์†Œ 1 ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

REVIEW_CONTENT_REQUIRED

BAD_REQUEST

๋ฆฌ๋ทฐ ๋‚ด์šฉ์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

REVIEW_CONTENT_MAXIMUM

BAD_REQUEST

๋ฆฌ๋ทฐ ๋‚ด์šฉ์˜ ์ตœ๋Œ€ ๊ธ€์ž์ˆ˜๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.

PRICE_MINIMUM

BAD_REQUEST

๊ฐ€๊ฒฉ์€ 0์› ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

PRICE_MAXIMUM

BAD_REQUEST

์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๊ฒฉ์˜ ๋ฒ”์œ„๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

ZIPCODE_ONLY_NUMBER

BAD_REQUEST

์šฐํŽธ๋ฒˆํ˜ธ๋Š” ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค

ZIPCODE_FORMAT

BAD_REQUEST

์šฐํŽธ๋ฒˆํ˜ธ๋Š” 5์ž๋ฆฌ์˜ ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค

8.2. ๋ฆฌ๋ทฐ ์กฐํšŒ

๋ฆฌ๋ทฐ ์กฐํšŒ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. PathVariable๋กœ alcoholId๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

PathVariable ์„ค๋ช…

alcoholId

์œ„์Šคํ‚ค ID

API EndPoint

GET /api/v1/reviews/{alcoholId}

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

$ http GET 'https://api.bottle-note.com/api/v1/reviews/1?sortType=POPULAR&sortOrder=DESC&cursor=0&pageSize=2'
Parameter Description

sortType

์ •๋ ฌ ํƒ€์ž…(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

sortOrder

์ •๋ ฌ ์ˆœ์„œ(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

cursor

์กฐํšŒ ํ•  ์‹œ์ž‘ ๊ธฐ์ค€ ์œ„์น˜

pageSize

์กฐํšŒ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

ํ•ด๋‹น ์ˆ ์˜ ์ด ๋ฆฌ๋ทฐ ์ˆ˜

data.reviewList[].reviewId

Number

๋ฆฌ๋ทฐ ID

data.reviewList[].reviewContent

String

๋ฆฌ๋ทฐ ๋‚ด์šฉ

data.reviewList[].price

Number

๋ฆฌ๋ทฐ ๊ฐ€๊ฒฉ

data.reviewList[].sizeType

String

๋ฆฌ๋ทฐ ์‚ฌ์ด์ฆˆ ํƒ€์ž…

data.reviewList[].likeCount

Number

๋ฆฌ๋ทฐ ์ข‹์•„์š” ์ˆ˜

data.reviewList[].replyCount

Number

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

data.reviewList[].reviewImageUrl

String

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ URL

data.reviewList[].totalImageCount

Null

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ ์ด ๊ฐœ์ˆ˜

data.reviewList[].userInfo.userId

Number

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ž ID

data.reviewList[].userInfo.nickName

String

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ž ๋‹‰๋„ค์ž„

data.reviewList[].userInfo.userProfileImage

String

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ž ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

data.reviewList[].rating

Number

๋ฆฌ๋ทฐ ํ‰์ 

data.reviewList[].viewCount

Number

๋ฆฌ๋ทฐ ์กฐํšŒ์ˆ˜

data.reviewList[].locationInfo

Object

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ •๋ณด

data.reviewList[].locationInfo.name

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ๋ช…

data.reviewList[].locationInfo.zipCode

Null

๋ฆฌ๋ทฐ ์žฅ์†Œ ์šฐํŽธ๋ฒˆํ˜ธ

data.reviewList[].locationInfo.address

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ฃผ์†Œ

data.reviewList[].locationInfo.detailAddress

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ƒ์„ธ ์ฃผ์†Œ

data.reviewList[].locationInfo.category

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์นดํ…Œ๊ณ ๋ฆฌ

data.reviewList[].locationInfo.mapUrl

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ง€๋„ URL

data.reviewList[].locationInfo.latitude

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์œ„๋„

data.reviewList[].locationInfo.longitude

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ๊ฒฝ๋„

data.reviewList[].status

String

๋ฆฌ๋ทฐ ๊ณต๊ฐœ ์—ฌ๋ถ€ (PUBLIC/PRIVATE)

data.reviewList[].isMyReview

Boolean

๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ์ธ์ง€ ์—ฌ๋ถ€

data.reviewList[].isLikedByMe

Boolean

๋‚ด๊ฐ€ ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €๋Š”์ง€ ์—ฌ๋ถ€

data.reviewList[].hasReplyByMe

Boolean

๋‚ด๊ฐ€ ๋Œ“๊ธ€์„ ๋‹ฌ์•˜๋Š”์ง€ ์—ฌ๋ถ€

data.reviewList[].isBestReview

Boolean

๋ฒ ์ŠคํŠธ ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

data.reviewList[].tastingTagList

Array

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

data.reviewList[].createAt

Array

๋ฆฌ๋ทฐ ์ž‘์„ฑ ๋‚ ์งœ 'yyyyMMddHHmm' ํฌ๋งท

meta.pageable

Object

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

meta.pageable.currentCursor

Number

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

meta.pageable.cursor

Number

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

meta.pageable.pageSize

Number

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Boolean

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 2,
    "reviewList" : [ {
      "reviewId" : 1,
      "reviewContent" : "๋ง›์žˆ์–ด์š”",
      "reviewImageUrl" : "https://example.com/review-image.jpg",
      "createAt" : [ 2026, 4, 8, 13, 53, 10, 977378253 ],
      "totalImageCount" : null,
      "userInfo" : {
        "userId" : 1,
        "nickName" : "ํ™๊ธธ๋™",
        "userProfileImage" : "https://example.com/profile.jpg"
      },
      "isMyReview" : true,
      "status" : "PUBLIC",
      "isBestReview" : false,
      "locationInfo" : {
        "name" : "๋„์‹œ์ˆ ",
        "zipCode" : null,
        "address" : "์„œ์šธ ์†กํŒŒ๊ตฌ ์†กํŒŒ๋Œ€๋กœ 145",
        "detailAddress" : "2์ธต ๋„์‹œ์ˆ ",
        "category" : "์Œ์‹์  > ์ˆ ์ง‘ > ์นตํ…Œ์ผ๋ฐ”",
        "mapUrl" : "https://place.map.kakao.com/2088591613",
        "latitude" : "37.4835934678036",
        "longitude" : "127.122831408454"
      },
      "sizeType" : "BOTTLE",
      "price" : 100000,
      "rating" : 4.5,
      "likeCount" : 10,
      "replyCount" : 2,
      "isLikedByMe" : false,
      "hasReplyByMe" : true,
      "viewCount" : 0,
      "tastingTagList" : [ "๊ณผ์ผํ–ฅ", "๋ถ€๋“œ๋Ÿฌ์›€" ]
    }, {
      "reviewId" : 2,
      "reviewContent" : "๋‚˜๋ฆ„ ๋จน์„๋งŒ ํ•˜๋„ค์š”",
      "reviewImageUrl" : "https://example.com/review-image.jpg",
      "createAt" : [ 2026, 4, 8, 13, 53, 10, 977389855 ],
      "totalImageCount" : null,
      "userInfo" : {
        "userId" : 1,
        "nickName" : "ํ™๊ธธ๋™",
        "userProfileImage" : "https://example.com/profile.jpg"
      },
      "isMyReview" : true,
      "status" : "PUBLIC",
      "isBestReview" : false,
      "locationInfo" : {
        "name" : "๋„์‹œ์ˆ ",
        "zipCode" : null,
        "address" : "์„œ์šธ ์†กํŒŒ๊ตฌ ์†กํŒŒ๋Œ€๋กœ 145",
        "detailAddress" : "2์ธต ๋„์‹œ์ˆ ",
        "category" : "์Œ์‹์  > ์ˆ ์ง‘ > ์นตํ…Œ์ผ๋ฐ”",
        "mapUrl" : "https://place.map.kakao.com/2088591613",
        "latitude" : "37.4835934678036",
        "longitude" : "127.122831408454"
      },
      "sizeType" : "BOTTLE",
      "price" : 110000,
      "rating" : 4.5,
      "likeCount" : 10,
      "replyCount" : 2,
      "isLikedByMe" : false,
      "hasReplyByMe" : true,
      "viewCount" : 0,
      "tastingTagList" : [ "๊ณผ์ผํ–ฅ", "๋ถ€๋“œ๋Ÿฌ์›€" ]
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 980313041 ],
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 1,
      "pageSize" : 2,
      "hasNext" : false
    },
    "serverPathVersion" : "v1"
  }
}
์ •๋ ฌ ํƒ€์ž… (sortType)

POPULAR

์ธ๊ธฐ์ˆœ

RATING

๋ณ„์ ์ˆœ

BOTTLE_PRICE

๋ณ‘ ๊ฐ€๊ฒฉ ์ˆœ

GLASS_PRICE

์ž” ๊ฐ€๊ฒฉ ์ˆœ

  • ํ•ด๋‹น ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ POPULAR ์ž…๋‹ˆ๋‹ค.

  • ํƒ€์ž…์ด ์ž˜๋ชป ์ „๋‹ฌ๋  ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

์ •๋ ฌ ๋ฐฉํ–ฅ (sortOrder)
  • ํ•ด๋‹น ์ •์˜๋Š” ์ •๋ ฌ ๋ฐฉํ–ฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค.

  • ์„œ๋น„์Šค์˜ ๋ชจ๋“  ์ •๋ ฌ ๊ด€๋ จ API์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

DESC

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

5 → 3 → 2 → 1

ASC

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

1 → 2 → 3 → 5

  • ๋žœ๋ค์˜ ๊ฒฝ์šฐ ์ •๋ ฌ ํƒ€์ž…์— ๋”ฐ๋ผ ์˜๋„์™€ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ•ด๋‹น ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ DESC(๋‚ด๋ฆผ์ฐจ์ˆœ) ์ž…๋‹ˆ๋‹ค.

  • ํƒ€์ž…์ด ์ž˜๋ชป ์ „๋‹ฌ๋  ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

8.3. ๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ ์กฐํšŒ

๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ ์กฐํšŒ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์š”์ฒญ ๊ฒฝ๋กœ์— ์กฐํšŒ ํ•  ์•Œ์ฝ”์˜ฌ์˜ ์‹๋ณ„์ž๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•Œ์ฝ”์˜ฌ์˜ ์‹๋ณ„์ž๋Š” Long ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

PathVariable ์„ค๋ช…

alcoholId

์œ„์Šคํ‚ค ID

API EndPoint

GET /api/v1/reviews/me/{alcoholId}

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

$ http GET 'https://api.bottle-note.com/api/v1/reviews/me/1?sortType=POPULAR&sortOrder=DESC&cursor=0&pageSize=2'
Parameter Description

sortType

์ •๋ ฌ ํƒ€์ž…(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

sortOrder

์ •๋ ฌ ์ˆœ์„œ(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

cursor

์กฐํšŒ ํ•  ์‹œ์ž‘ ๊ธฐ์ค€ ์œ„์น˜

pageSize

์กฐํšŒ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

ํ•ด๋‹น ์ˆ ์˜ ์ด ๋ฆฌ๋ทฐ ์ˆ˜

data.reviewList[].reviewId

Number

๋ฆฌ๋ทฐ ID

data.reviewList[].reviewContent

String

๋ฆฌ๋ทฐ ๋‚ด์šฉ

data.reviewList[].price

Number

๋ฆฌ๋ทฐ ๊ฐ€๊ฒฉ

data.reviewList[].sizeType

String

๋ฆฌ๋ทฐ ์‚ฌ์ด์ฆˆ ํƒ€์ž…

data.reviewList[].likeCount

Number

๋ฆฌ๋ทฐ ์ข‹์•„์š” ์ˆ˜

data.reviewList[].replyCount

Number

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

data.reviewList[].reviewImageUrl

String

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ URL

data.reviewList[].totalImageCount

Null

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ ์ด ๊ฐœ์ˆ˜

data.reviewList[].userInfo.userId

Number

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ž ID

data.reviewList[].userInfo.nickName

String

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ž ๋‹‰๋„ค์ž„

data.reviewList[].userInfo.userProfileImage

String

๋ฆฌ๋ทฐ ์ž‘์„ฑ์ž ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

data.reviewList[].rating

Number

๋ฆฌ๋ทฐ ํ‰์ 

data.reviewList[].viewCount

Number

๋ฆฌ๋ทฐ ์กฐํšŒ์ˆ˜

data.reviewList[].locationInfo

Object

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ •๋ณด

data.reviewList[].locationInfo.name

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ๋ช…

data.reviewList[].locationInfo.zipCode

Null

๋ฆฌ๋ทฐ ์žฅ์†Œ ์šฐํŽธ๋ฒˆํ˜ธ

data.reviewList[].locationInfo.address

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ฃผ์†Œ

data.reviewList[].locationInfo.detailAddress

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ƒ์„ธ ์ฃผ์†Œ

data.reviewList[].locationInfo.category

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์นดํ…Œ๊ณ ๋ฆฌ

data.reviewList[].locationInfo.mapUrl

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์ง€๋„ URL

data.reviewList[].locationInfo.latitude

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ์œ„๋„

data.reviewList[].locationInfo.longitude

String

๋ฆฌ๋ทฐ ์žฅ์†Œ ๊ฒฝ๋„

data.reviewList[].status

String

๋ฆฌ๋ทฐ ๊ณต๊ฐœ ์—ฌ๋ถ€ (PUBLIC/PRIVATE)

data.reviewList[].isMyReview

Boolean

๋‚ด๊ฐ€ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ์ธ์ง€ ์—ฌ๋ถ€

data.reviewList[].isLikedByMe

Boolean

๋‚ด๊ฐ€ ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €๋Š”์ง€ ์—ฌ๋ถ€

data.reviewList[].hasReplyByMe

Boolean

๋‚ด๊ฐ€ ๋Œ“๊ธ€์„ ๋‹ฌ์•˜๋Š”์ง€ ์—ฌ๋ถ€

data.reviewList[].isBestReview

Boolean

๋ฒ ์ŠคํŠธ ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

data.reviewList[].tastingTagList

Array

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

data.reviewList[].createAt

Array

๋ฆฌ๋ทฐ ์ž‘์„ฑ ๋‚ ์งœ 'yyyyMMddHHmm' ํฌ๋งท

meta.pageable

Object

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

meta.pageable.currentCursor

Number

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

meta.pageable.cursor

Number

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

meta.pageable.pageSize

Number

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Boolean

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 2,
    "reviewList" : [ {
      "reviewId" : 1,
      "reviewContent" : "๋ง›์žˆ์–ด์š”",
      "reviewImageUrl" : "https://example.com/review-image.jpg",
      "createAt" : [ 2026, 4, 8, 13, 53, 10, 743690547 ],
      "totalImageCount" : null,
      "userInfo" : {
        "userId" : 1,
        "nickName" : "ํ™๊ธธ๋™",
        "userProfileImage" : "https://example.com/profile.jpg"
      },
      "isMyReview" : true,
      "status" : "PUBLIC",
      "isBestReview" : false,
      "locationInfo" : {
        "name" : "๋„์‹œ์ˆ ",
        "zipCode" : null,
        "address" : "์„œ์šธ ์†กํŒŒ๊ตฌ ์†กํŒŒ๋Œ€๋กœ 145",
        "detailAddress" : "2์ธต ๋„์‹œ์ˆ ",
        "category" : "์Œ์‹์  > ์ˆ ์ง‘ > ์นตํ…Œ์ผ๋ฐ”",
        "mapUrl" : "https://place.map.kakao.com/2088591613",
        "latitude" : "37.4835934678036",
        "longitude" : "127.122831408454"
      },
      "sizeType" : "BOTTLE",
      "price" : 100000,
      "rating" : 4.5,
      "likeCount" : 10,
      "replyCount" : 2,
      "isLikedByMe" : false,
      "hasReplyByMe" : true,
      "viewCount" : 0,
      "tastingTagList" : [ "๊ณผ์ผํ–ฅ", "๋ถ€๋“œ๋Ÿฌ์›€" ]
    }, {
      "reviewId" : 2,
      "reviewContent" : "๋‚˜๋ฆ„ ๋จน์„๋งŒ ํ•˜๋„ค์š”",
      "reviewImageUrl" : "https://example.com/review-image.jpg",
      "createAt" : [ 2026, 4, 8, 13, 53, 10, 743707669 ],
      "totalImageCount" : null,
      "userInfo" : {
        "userId" : 1,
        "nickName" : "ํ™๊ธธ๋™",
        "userProfileImage" : "https://example.com/profile.jpg"
      },
      "isMyReview" : true,
      "status" : "PUBLIC",
      "isBestReview" : false,
      "locationInfo" : {
        "name" : "๋„์‹œ์ˆ ",
        "zipCode" : null,
        "address" : "์„œ์šธ ์†กํŒŒ๊ตฌ ์†กํŒŒ๋Œ€๋กœ 145",
        "detailAddress" : "2์ธต ๋„์‹œ์ˆ ",
        "category" : "์Œ์‹์  > ์ˆ ์ง‘ > ์นตํ…Œ์ผ๋ฐ”",
        "mapUrl" : "https://place.map.kakao.com/2088591613",
        "latitude" : "37.4835934678036",
        "longitude" : "127.122831408454"
      },
      "sizeType" : "BOTTLE",
      "price" : 110000,
      "rating" : 4.5,
      "likeCount" : 10,
      "replyCount" : 2,
      "isLikedByMe" : false,
      "hasReplyByMe" : true,
      "viewCount" : 0,
      "tastingTagList" : [ "๊ณผ์ผํ–ฅ", "๋ถ€๋“œ๋Ÿฌ์›€" ]
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 748219636 ],
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 1,
      "pageSize" : 2,
      "hasNext" : false
    },
    "serverPathVersion" : "v1"
  }
}
์ •๋ ฌ ํƒ€์ž… (sortType)

POPULAR

์ธ๊ธฐ์ˆœ

RATING

๋ณ„์ ์ˆœ

BOTTLE_PRICE

๋ณ‘ ๊ฐ€๊ฒฉ ์ˆœ

GLASS_PRICE

์ž” ๊ฐ€๊ฒฉ ์ˆœ

  • ํ•ด๋‹น ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ POPULAR ์ž…๋‹ˆ๋‹ค.

  • ํƒ€์ž…์ด ์ž˜๋ชป ์ „๋‹ฌ๋  ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

์ •๋ ฌ ๋ฐฉํ–ฅ (sortOrder)
  • ํ•ด๋‹น ์ •์˜๋Š” ์ •๋ ฌ ๋ฐฉํ–ฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค.

  • ์„œ๋น„์Šค์˜ ๋ชจ๋“  ์ •๋ ฌ ๊ด€๋ จ API์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

DESC

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

5 → 3 → 2 → 1

ASC

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

1 → 2 → 3 → 5

  • ๋žœ๋ค์˜ ๊ฒฝ์šฐ ์ •๋ ฌ ํƒ€์ž…์— ๋”ฐ๋ผ ์˜๋„์™€ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ•ด๋‹น ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ DESC(๋‚ด๋ฆผ์ฐจ์ˆœ) ์ž…๋‹ˆ๋‹ค.

  • ํƒ€์ž…์ด ์ž˜๋ชป ์ „๋‹ฌ๋  ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

8.4. ๋ฆฌ๋ทฐ ์ˆ˜์ •

๋ฆฌ๋ทฐ ์ˆ˜์ • ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. PathVariable๋กœ ReviewId๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์ „๋‹ฌํ•œ ReviewId๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ReviewException์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ˆ˜์ • ๋‚ด์šฉ์€ RequestBody๋กœ ์š”์ฒญ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

content(๋ฆฌ๋ทฐ ๋‚ด์šฉ)์˜ ๊ธธ์ด๋Š” 700์ž๋กœ ์ œํ•œ๋˜๋ฉฐ, price(๊ฐ€๊ฒฉ์€) 0 ~ 1์กฐ ๋ฒ”์œ„๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

ReviewStatus์™€ SizeType์€ ์•„๋ž˜ ENUM์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

PATCH /api/v1/reviews

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

  • Request Body ์˜ˆ์‹œ

์ˆ˜์ •ํ•˜์ง€ ์•Š์œผ๋ ค๋Š” ํ•„๋“œ๋Š” ๊ธฐ์กด์˜ ๊ฐ’์„ ์œ ์ง€ํ•˜๊ณ , ์ˆ˜์ •ํ•˜๋ ค๋Š” ํ•„๋“œ๋งŒ ์ˆ˜์ •๋œ ๊ฐ’์œผ๋กœ ์ฑ„์›Œ์„œ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

ํ•„๋“œ์˜ ๊ฐ’์ด NULL์ธ ๊ฒฝ์šฐ 400 Bad Request๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

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

ReviewStatus

์ฝ”๋“œ ์„ค๋ช…

PUBLIC

๊ณต๊ฐœ(๊ธฐ๋ณธ ๊ฐ’)

PRIVATE

๋น„๊ณต๊ฐœ

SizeType

์ฝ”๋“œ ์„ค๋ช…

GLASS

์ž”

BOTTLE

๋ณ‘

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REVIEW_CONTENT_REQUIRED

BAD_REQUEST

๋ฆฌ๋ทฐ ๋‚ด์šฉ์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

REVIEW_CONTENT_MAXIMUM

BAD_REQUEST

๋ฆฌ๋ทฐ ๋‚ด์šฉ์˜ ์ตœ๋Œ€ ๊ธ€์ž์ˆ˜๋ฅผ ์ดˆ๊ณผํ–ˆ์Šต๋‹ˆ๋‹ค.

PRICE_MINIMUM

BAD_REQUEST

๊ฐ€๊ฒฉ์€ 0์› ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

PRICE_MAXIMUM

BAD_REQUEST

์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๊ฒฉ์˜ ๋ฒ”์œ„๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.

REVIEW_DISPLAY_STATUS_NOT_EMPTY

BAD_REQUEST

๋ฆฌ๋ทฐ ๊ณต๊ฐœ/๋น„๊ณต๊ฐœ์ƒํƒœ๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

ZIPCODE_ONLY_NUMBER

BAD_REQUEST

์šฐํŽธ๋ฒˆํ˜ธ๋Š” ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค

ZIPCODE_FORMAT

BAD_REQUEST

์šฐํŽธ๋ฒˆํ˜ธ๋Š” 5์ž๋ฆฌ์˜ ์ˆซ์ž๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค

8.5. ๋ฆฌ๋ทฐ ์‚ญ์ œ

๋ฆฌ๋ทฐ ์‚ญ์ œ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๋งŒ ๋ฆฌ๋ทฐ๋ฅผ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๋Š” ์ž์‹ ์ด ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ๋งŒ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

API ์—”๋“œํฌ์ธํŠธ์— PathVariable๋กœ ReviewId๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์ „๋‹ฌํ•œ ReviewId์˜ ๋ฆฌ๋ทฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด(๋กœ๊ทธ์ธํ•œ ์œ ์ €๊ฐ€ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ๊ฐ€ ์•„๋‹˜) ReviewException์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

DELETE /api/v1/reviews/{reviewId}

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

  • PathVariable๋กœ reviewId๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.codeMessage

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ

data.message

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€

data.reviewId

Number

๋ฆฌ๋ทฐ ์•„์ด๋””

data.responseAt

String

์„œ๋ฒ„ ์‘๋‹ต ์ผ์‹œ

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 426

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "DELETE_SUCCESS",
    "message" : "๋ฆฌ๋ทฐ ์‚ญ์ œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "reviewId" : 1,
    "responseAt" : "2026-04-08 13:53:10"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 645955217 ],
    "serverPathVersion" : "v1"
  }
}

8.6. ๋ฆฌ๋ทฐ ์ƒ์„ธ์กฐํšŒ

๋ฆฌ๋ทฐ ์ƒ์„ธ์กฐํšŒ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

API ์—”๋“œํฌ์ธํŠธ์— PathVariable๋กœ ReviewId๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์ „๋‹ฌํ•œ ReviewId์˜ ๋ฆฌ๋ทฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด(๋กœ๊ทธ์ธํ•œ ์œ ์ €๊ฐ€ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ๊ฐ€ ์•„๋‹˜) ReviewException์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/reviews/detail/{reviewId}

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

  • PathVariable๋กœ reviewId๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

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

path type description

success

Boolean

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

code

Number

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

data.alcoholInfo.alcoholId

Number

์ˆ  ID

data.alcoholInfo.korName

String

์ˆ ์˜ ํ•œ๊ตญ์–ด ์ด๋ฆ„

data.alcoholInfo.engName

String

์ˆ ์˜ ์˜์–ด ์ด๋ฆ„

data.alcoholInfo.korCategoryName

String

์ˆ  ์นดํ…Œ๊ณ ๋ฆฌ์˜ ํ•œ๊ตญ์–ด ์ด๋ฆ„

data.alcoholInfo.engCategoryName

String

์ˆ  ์นดํ…Œ๊ณ ๋ฆฌ์˜ ์˜์–ด ์ด๋ฆ„

data.alcoholInfo.imageUrl

String

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

data.alcoholInfo.isPicked

Boolean

์„ ํƒ ์—ฌ๋ถ€

data.reviewInfo.reviewId

Number

๋ฆฌ๋ทฐ ID

data.reviewInfo.reviewContent

String

๋ฆฌ๋ทฐ ๋‚ด์šฉ

data.reviewInfo.price

Number

๊ฐ€๊ฒฉ

data.reviewInfo.sizeType

String

์‚ฌ์ด์ฆˆ ํƒ€์ž…

data.reviewInfo.likeCount

Number

์ข‹์•„์š” ๊ฐœ์ˆ˜

data.reviewInfo.replyCount

Number

๋Œ“๊ธ€ ๊ฐœ์ˆ˜

data.reviewInfo.reviewImageUrl

String

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ URL

data.reviewInfo.totalImageCount

Null

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ ์ด ๊ฐœ์ˆ˜

data.reviewInfo.userInfo

Object

์‚ฌ์šฉ์ž ์ •๋ณด

data.reviewInfo.userInfo.userId

Number

์‚ฌ์šฉ์ž ID

data.reviewInfo.userInfo.nickName

String

๋‹‰๋„ค์ž„

data.reviewInfo.userInfo.userProfileImage

String

์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

data.reviewInfo.rating

Number

ํ‰์ 

data.reviewInfo.viewCount

Number

์กฐํšŒ์ˆ˜

data.reviewInfo.locationInfo

Object

์œ„์น˜ ์ •๋ณด

data.reviewInfo.locationInfo.name

String

์ƒํ˜ธ ๋ช…

data.reviewInfo.locationInfo.zipCode

String

์šฐํŽธ๋ฒˆํ˜ธ

data.reviewInfo.locationInfo.address

String

์ฃผ์†Œ

data.reviewInfo.locationInfo.detailAddress

String

์ƒ์„ธ์ฃผ์†Œ

data.reviewInfo.locationInfo.category

String

์นดํ…Œ๊ณ ๋ฆฌ

data.reviewInfo.locationInfo.mapUrl

String

์ง€๋„ URL

data.reviewInfo.locationInfo.latitude

String

์œ„๋„

data.reviewInfo.locationInfo.longitude

String

๊ฒฝ๋„

data.reviewInfo.status

String

๋ฆฌ๋ทฐ ์ƒํƒœ

data.reviewInfo.isMyReview

Boolean

๋‚ด ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

data.reviewInfo.isLikedByMe

Boolean

๋‚ด๊ฐ€ ์ข‹์•„์š”๋ฅผ ๋ˆŒ๋ €๋Š”์ง€ ์—ฌ๋ถ€

data.reviewInfo.hasReplyByMe

Boolean

๋‚ด๊ฐ€ ๋Œ“๊ธ€์„ ๋‹ฌ์•˜๋Š”์ง€ ์—ฌ๋ถ€

data.reviewInfo.isBestReview

Boolean

๋ฒ ์ŠคํŠธ ๋ฆฌ๋ทฐ ์—ฌ๋ถ€

data.reviewInfo.tastingTagList

Array

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

data.reviewInfo.createAt

Array

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

data.reviewImageList

Array

๋ฆฌ๋ทฐ ์ด๋ฏธ์ง€ ๋ชฉ๋ก

data.reviewImageList[].order

Number

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

data.reviewImageList[].viewUrl

String

์ด๋ฏธ์ง€ URL

errors

Array

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

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 1825

{
  "success" : true,
  "code" : 200,
  "data" : {
    "alcoholInfo" : {
      "alcoholId" : 1,
      "korName" : "๊ธ€๋ž˜์Šค๊ณ  12๋…„์‚ฐ",
      "engName" : "1770 ๊ธ€๋ž˜์Šค๊ณ  ์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "imageUrl" : "ImageUrl",
      "isPicked" : false
    },
    "reviewInfo" : {
      "reviewId" : 1,
      "reviewContent" : "์ด๊ฒƒ์€ ์ƒ˜ํ”Œ ๋ฆฌ๋ทฐ์ž…๋‹ˆ๋‹ค.",
      "reviewImageUrl" : "https://example.com/review-image.jpg",
      "createAt" : [ 2026, 4, 8, 13, 53, 10, 891367345 ],
      "totalImageCount" : null,
      "userInfo" : {
        "userId" : 1,
        "nickName" : "ํ™๊ธธ๋™",
        "userProfileImage" : "https://example.com/profile.jpg"
      },
      "isMyReview" : true,
      "status" : "PUBLIC",
      "isBestReview" : false,
      "locationInfo" : {
        "name" : "๋„์‹œ์ˆ ",
        "zipCode" : null,
        "address" : "์„œ์šธ ์†กํŒŒ๊ตฌ ์†กํŒŒ๋Œ€๋กœ 145",
        "detailAddress" : "2์ธต ๋„์‹œ์ˆ ",
        "category" : "์Œ์‹์  > ์ˆ ์ง‘ > ์นตํ…Œ์ผ๋ฐ”",
        "mapUrl" : "https://place.map.kakao.com/2088591613",
        "latitude" : "37.4835934678036",
        "longitude" : "127.122831408454"
      },
      "sizeType" : "GLASS",
      "price" : 10000,
      "rating" : 4.5,
      "likeCount" : 10,
      "replyCount" : 2,
      "isLikedByMe" : false,
      "hasReplyByMe" : true,
      "viewCount" : 0,
      "tastingTagList" : [ "๊ณผ์ผํ–ฅ", "๋ถ€๋“œ๋Ÿฌ์›€" ]
    },
    "reviewImageList" : [ {
      "order" : 1,
      "viewUrl" : "https://bottlenote.s3.ap-northeast-2.amazonaws.com/images/1"
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 893302463 ],
    "serverPathVersion" : "v1"
  }
}

8.7. ๋ฆฌ๋ทฐ ์ƒํƒœ ๋ณ€๊ฒฝ

๋ฆฌ๋ทฐ ์ƒํƒœ ๋ณ€๊ฒฝ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๋งŒ ๋ฆฌ๋ทฐ์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž๋Š” ์ž์‹ ์ด ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ์˜ ์ƒํƒœ๋งŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

API ์—”๋“œํฌ์ธํŠธ์— PathVariable๋กœ ReviewId๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์ „๋‹ฌํ•œ ReviewId์˜ ๋ฆฌ๋ทฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด(๋กœ๊ทธ์ธํ•œ ์œ ์ €๊ฐ€ ์ž‘์„ฑํ•œ ๋ฆฌ๋ทฐ๊ฐ€ ์•„๋‹˜) ReviewException์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  RequestBody๋กœ ๋ณ€๊ฒฝํ•  ๋ฆฌ๋ทฐ์˜ ์ƒํƒœ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. (PRIVATE, PUBLIC)

ReqeuestBody๊ฐ€ null์ธ ๊ฒฝ์šฐ Validation์— ์˜ํ•ด REVIEW_STATUS_REQUIRED ์ฝ”๋“œ๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

PATCH /api/v1/reviews/{reviewId}/display

RequestBody ์–‘์‹

PUBLIC

๊ณต๊ฐœ

PRIVATE

๋น„๊ณต๊ฐœ

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

  • PathVariable๋กœ reviewId๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

  • RequestBody๋กœ status๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

path type optional description

status

String

๋ฆฌ๋ทฐ ์ƒํƒœ

{
  "status" : "PRIVATE"
}

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.codeMessage

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ

data.message

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€

data.reviewId

Number

๋ฆฌ๋ทฐ ์•„์ด๋””

data.responseAt

String

์„œ๋ฒ„ ์‘๋‹ต ์ผ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "PRIVATE_SUCCESS",
    "message" : "ํ•ด๋‹น ๋ฆฌ๋ทฐ๊ฐ€ ๋น„๊ณต๊ฐœ ์ฒ˜๋ฆฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "reviewId" : 1,
    "responseAt" : "2026-04-08 13:53:10"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 952047365 ],
    "serverPathVersion" : "v1"
  }
}

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REVIEW_NOT_EMPTY

BAD_REQUEST

๋ฆฌ๋ทฐ ์•„์ด๋””๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

REVIEW_DISPLAY_STATUS_NOT_EMPTY

BAD_REQUEST

๋ฆฌ๋ทฐ ๊ณต๊ฐœ/๋น„๊ณต๊ฐœ์ƒํƒœ๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

REVIEW_NOT_FOUND

BAD_REQUEST

๋ฆฌ๋ทฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค

8.8. ๋ฆฌ๋ทฐ ์ข‹์•„์š”

๋ฆฌ๋ทฐ์— ๋Œ€ํ•ด ์ข‹์•„์š” ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•œ API ์ž…๋‹ˆ๋‹ค.

์—…๋ฐ์ดํŠธ ์‹œ Acsess Token ์ด ํ•„์ˆ˜์ ์œผ๋กœ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ค‘๋ณต๋œ ์š”์ฒญ ์‹œ์—๋„ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  • ์ข‹์•„์š” ์š”์ฒญ ํ›„ ๋‹ค์‹œ ์ข‹์•„์š” ์š”์ฒญ ์‹œ ์ •์ƒ ์ฒ˜๋ฆฌ ( ๋ฎ์–ด์“ฐ๊ธฐ )

PUT /api/v1/likes

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

path type optional description

reviewId

Number

์ข‹์•„์š” ๋Œ€์ƒ ๋ฆฌ๋ทฐ์˜ ์‹๋ณ„์ž

status

String

์—…๋ฐ์ดํŠธ ํ•  ์ƒํƒœ ๊ฐ’ ํ•˜๋‹จ ์ฐธ์กฐ

{
  "reviewId" : 1,
  "status" : "LIKE"
}

์ข‹์•„์š” status enum ์ƒํƒœ๊ฐ’

  • ์ƒํƒœ ์š”์ฒญ์‹œ ํ•˜์œ„ ๊ฐ’์œผ๋กœ๋งŒ ์š”์ฒญ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

LIKE

์ข‹์•„์š”

DISLIKE

์ข‹์•„์š” ํ•ด์ œ

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

path type description

data.message

String

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

data.likesId

Number

์ข‹์•„์š” ๊ฒฐ๊ณผ ๊ฐ’ ์‹๋ณ„์ž

data.reviewId

Number

์ข‹์•„์š” ๋Œ€์ƒ ๋ฆฌ๋ทฐ์˜ ์‹๋ณ„์ž

data.userId

Number

์ข‹์•„์š”๋ฅผ ๋“ฑ๋กํ•œ ์‚ฌ์šฉ์ž ์‹๋ณ„์ž

data.userNickName

String

์ข‹์•„์š”๋ฅผ ๋“ฑ๋กํ•œ ์‚ฌ์šฉ์ž ๋‹‰๋„ค์ž„

data.status

String

์—…๋ฐ์ดํŠธ ๋œ ์ข‹์•„์š” ์ƒํƒœ ๊ฐ’

{
  "success" : true,
  "code" : 200,
  "data" : {
    "message" : "์ •์ƒ์ ์œผ๋กœ ์ข‹์•„์š” ์ฒ˜๋ฆฌ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "likesId" : 1,
    "reviewId" : 1,
    "userId" : 99,
    "userNickName" : "ํ•˜์˜คํ•˜์˜ค์ƒ",
    "status" : "LIKE"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 261247702 ],
    "serverPathVersion" : "v1"
  }
}

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REVIEW_NOT_EMPTY

BAD_REQUEST

๋ฆฌ๋ทฐ ์•„์ด๋””๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

REVIEW_DISPLAY_STATUS_NOT_EMPTY

BAD_REQUEST

๋ฆฌ๋ทฐ ๊ณต๊ฐœ/๋น„๊ณต๊ฐœ์ƒํƒœ๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

REVIEW_NOT_FOUND

BAD_REQUEST

๋ฆฌ๋ทฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค

9. ๋ฆฌ๋ทฐ ๋Œ“๊ธ€ (review reply) ๊ด€๋ จ API

9.1. ๋ฆฌ๋ทฐ ๋Œ“๊ธ€ ๋“ฑ๋ก

๋ฆฌ๋ทฐ์˜ ๋Œ“๊ธ€์„ ๋“ฑ๋ก ํ•˜๋Š” API ๋ฌธ์„œ์ž…๋‹ˆ๋‹ค.

PathVariable๋กœ ๋Œ“๊ธ€์ด ์ž‘์„ฑ๋˜๋Š” ๋Œ€์ƒ ๋ฆฌ๋ทฐ์˜ ์‹๋ณ„์ž๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

  • ๋Œ“๊ธ€์˜ ์ƒ์œ„๋Š” ํฌ๊ฒŒ ๋‘๊ฐ€์ง€๋กœ ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค

    • root reply id : ์ตœ์ƒ์œ„ ๋Œ“๊ธ€ ์‹๋ณ„์ž

    • parent reply id : ์ƒ์œ„ ๋Œ“๊ธ€ ์‹๋ณ„์ž

์ตœ์ƒ์œ„ ์‹๋ณ„์ž์˜ ๊ฒฝ์šฐ ์„œ๋ฒ„์—์„œ ํŒŒ์•…ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์œ„ ๋Œ“๊ธ€ ์‹๋ณ„์ž๋งŒ ์ „๋‹ฌ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด

โ”œโ”€โ”€ ์ฒซ๋ฒˆ์งธ ๋Œ“๊ธ€
โ””โ”€โ”€โ”€โ”œโ”€โ”€ ๋‘๋ฒˆ์งธ ๋Œ“๊ธ€
    โ””โ”€โ”€โ”€โ”€โ”œโ”€ ์„ธ๋ฒˆ์งธ ๋Œ“๊ธ€
         โ””โ”€โ”€โ”€โ”€ ๋„ค๋ฒˆ์งธ ๋Œ“๊ธ€
  • ์ฒซ๋ฒˆ์จฐ ๋Œ“๊ธ€์€ ์ƒ์œ„/์ตœ์ƒ์œ„ ๋ถ€๋ชจ๊ฐ€ ์—†๋Š” ๋Œ“๊ธ€์ž…๋‹ˆ๋‹ค.

  • ๋‘๋ฒˆ์งธ ๋Œ“๊ธ€์˜ ์ƒ์œ„ ๋ถ€๋ชจ์ด์ž ์ตœ์ƒ์œ„ ๋Œ“๊ธ€์€ ์ฒซ๋ฒˆ์งธ ๋Œ“๊ธ€์ž…๋‹ˆ๋‹ค.

  • ์„ธ๋ฒˆ์งธ ๋Œ“๊ธ€์˜ ์ƒ์œ„ ๋ถ€๋ชจ๋Š” ๋‘๋ฒˆ์งธ ๋Œ“๊ธ€์ด๊ณ  ์ตœ์ƒ์œ„ ๋Œ“๊ธ€ ์‹๋ณ„์ž๋Š” ์ฒซ๋ฒˆ์งธ ๋Œ“๊ธ€์˜ ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค.

  • ๋„ค๋ฒˆ์งธ ๋Œ“๊ธ€์˜ ์ƒ์œ„ ๋ถ€๋ชจ๋Š” ์„ธ๋ฒˆ์งธ ๋Œ“๊ธ€์ด๊ณ  ์ตœ์ƒ์œ„ ๋Œ“๊ธ€ ์‹๋ณ„์ž๋Š” ์ฒซ๋ฒˆ์งธ ๋Œ“๊ธ€์˜ ์‹๋ณ„์ž์ž…๋‹ˆ๋‹ค.

  • ๊ณ„์ธต ๊ตฌ์กฐ๋Š” ์ดํ•ด๋ฅผ ์‰ฝ๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•œ ์˜ˆ์‹œ์ด๋ฉฐ ์‹ค์ œ ์กฐํšŒ์‹œ์—๋Š” ์ตœ๋Œ€ 1Depth๋กœ ์กฐํšŒ๋ฉ๋‹ˆ๋‹ค.

API EndPoint

POST /api/v1/review/reply/register/{reviewId}
PathVariable ์„ค๋ช…

reviewId

๋ฆฌ๋ทฐ ์‹๋ณ„์ž

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

path type optional description

content

String

๋“ฑ๋กํ•  ๋Œ“๊ธ€ ๋‚ด์šฉ ๋ณธ๋ฌธ

parentReplyId

Null

O

์ƒ์œ„ ๋Œ“๊ธ€ ์‹๋ณ„์ž

{
  "content" : "์ด ๋ฆฌ๋ทฐ๋Š” ๋งค์šฐ ์œ ์ตํ•ฉ๋‹ˆ๋‹ค. ์ถ”์ฒœ์„ ์ค„๋งŒํ•˜๋„ค์š”.",
  "parentReplyId" : null
}

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

path type description

success

Boolean

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

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.codeMessage

String

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

data.message

String

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

data.reviewId

Number

๋Œ€์ƒ ๋ฆฌ๋ทฐ ์‹๋ณ„์ž

data.responseAt

String

์‘๋‹ต ์ผ์‹œ

errors

Array

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

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "SUCCESS_REGISTER_REPLY",
    "message" : "์„ฑ๊ณต์ ์œผ๋กœ ๋Œ“๊ธ€์„ ๋“ฑ๋กํ–ˆ์Šต๋‹ˆ๋‹ค.",
    "reviewId" : 1,
    "responseAt" : "2026-04-08 13:53:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 11, 395605649 ],
    "serverPathVersion" : "v1"
  }
}

9.2. ๋ฆฌ๋ทฐ ๋Œ“๊ธ€ ์‚ญ์ œ

๋ฆฌ๋ทฐ์˜ ๋Œ“๊ธ€ ๋ชฉ๋ก์„ ์‚ญ์ œ ํ•˜๋Š” API ๋ฌธ์„œ์ž…๋‹ˆ๋‹ค.

์‚ฌ์šฉ์ž์˜ ์ธ์ฆ ํ† ํฐ์ด ํ•„์ˆ˜์ ์œผ๋กœ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์‚ญ์ œ๋œ ๋Œ“๊ธ€์˜ ๊ฒฝ์šฐ `๋…ผ๋ฆฌ์  ์‚ญ์ œ`๋กœ ์‚ญ์ œ๋œ ๋Œ“๊ธ€์ด ํฌํ•จ๋œ ๋ชฉ๋ก์„ ์กฐํšŒ ์‹œ.

์‚ญ์ œ๋œ ๋Œ“๊ธ€์ž…๋‹ˆ๋‹ค ๋ผ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค.

API EndPoint

DELETE /api/v1/review/reply/{reviewId}/{replyId}

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

Table 2. /api/v1/review/reply/{reviewId}/{replyId}
Parameter Description

reviewId

๋Œ“๊ธ€์„ ์ž‘์„ฑ ๋Œ€์ƒ ๋ฆฌ๋ทฐ์˜ ์‹๋ณ„์ž

replyId

์‚ญ์ œํ•  ๋ฆฌ๋ทฐ ์‹๋ณ„์ž.

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

path type description

success

Boolean

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

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.codeMessage

String

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

data.message

String

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

data.reviewId

Number

๋Œ€์ƒ ๋ฆฌ๋ทฐ ์‹๋ณ„์ž

data.responseAt

String

์‘๋‹ต ์ผ์‹œ

errors

Array

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

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "SUCCESS_DELETE_REPLY",
    "message" : "์„ฑ๊ณต์ ์œผ๋กœ ๋Œ“๊ธ€์„ ์‚ญ์ œํ–ˆ์Šต๋‹ˆ๋‹ค.",
    "reviewId" : 1,
    "responseAt" : "2026-04-08 13:53:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 11, 147589193 ],
    "serverPathVersion" : "v1"
  }
}

9.3. ์ตœ์ƒ์œ„ ๋ฆฌ๋ทฐ ๋Œ“๊ธ€ ๋ชฉ๋ก ์กฐํšŒ

๋ฆฌ๋ทฐ์˜ ๋Œ“๊ธ€ ๋ชฉ๋ก์„ ์กฐํšŒ ํ•˜๋Š” API ๋ฌธ์„œ์ž…๋‹ˆ๋‹ค.

PathVariable๋กœ ๋Œ“๊ธ€์ด ์ž‘์„ฑ๋˜๋Š” ๋Œ€์ƒ ๋ฆฌ๋ทฐ์˜ ์‹๋ณ„์ž๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์ตœ์ƒ์œ„ ๋Œ“๊ธ€ ๋ชฉ๋ก๋งŒ ์กฐํšŒํ•˜๋Š” api์ž…๋‹ˆ๋‹ค.

  • ์ตœ์ƒ์œ„ ๋Œ“๊ธ€ : ๋ถ€๋ชจ ๋Œ“๊ธ€์ด ์—†๋Š” ๋Œ“๊ธ€

๊ตฌ์กฐ ์˜ˆ ).

a3qNSWs
  • ์ตœ์ƒ์œ„ ๋ฆฌ๋ทฐ ๋Œ“๊ธ€ ๋ชฉ๋ก ์กฐํšŒ API ๋ฅผ ํ†ตํ•ด Root Reply์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ํ•˜์œ„ ๋ฆฌ๋ทฐ ๋Œ“๊ธ€ ๋ชฉ๋ก ์กฐํšŒ API ๋ฅผ ํ†ตํ•ด Root Reply์— ๋Œ€ํ•œ ๋Œ€๋Œ“๊ธ€์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

API EndPoint

GET /api/v1/review/reply/{reviewId}

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

Table 3. /api/v1/review/reply/{reviewId}
Parameter Description

reviewId

๋Œ“๊ธ€์„ ์ž‘์„ฑ ๋Œ€์ƒ ๋ฆฌ๋ทฐ์˜ ์‹๋ณ„์ž

Parameter Description

cursor

ํŽ˜์ด์ง• ์ปค์„œ (์กฐํšŒ๋ฅผ ์‹œ์ž‘ํ•  ์œ„์น˜)

pageSize

ํŽ˜์ด์ง€ ํฌ๊ธฐ (ํ•œ๋ฒˆ์— ์กฐํšŒ๋  ๋ฐ์ดํ„ฐ ์–‘)

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

  • ๋‹‰๋„ค์ž„๊ณผ ๋‚ด์šฉ์€ ์˜ˆ์‹œ๋กœ๋งŒ ๋ด์ฃผ์„ธ์š” . ๋žœ๋ค์„ฑ ๋ฌธ์ž์—ด๋กœ ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

path type description

success

Boolean

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

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.totalCount

Number

์ „์ฒด ๋Œ“๊ธ€ ๊ฐฏ์ˆ˜

data.reviewReplies[].userId

Number

๋Œ“๊ธ€ ์ž‘์„ฑ์ž ์‹๋ณ„์ž

data.reviewReplies[].imageUrl

String

๋Œ“๊ธ€ ์ž‘์„ฑ์ž ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

data.reviewReplies[].nickName

String

๋Œ“๊ธ€ ์ž‘์„ฑ์ž ๋‹‰๋„ค์ž„

data.reviewReplies[].reviewReplyId

Number

๋Œ“๊ธ€ ์ž์ฒด ์‹๋ณ„์ž

data.reviewReplies[].reviewReplyContent

String

๋Œ“๊ธ€ ๋‚ด์šฉ

data.reviewReplies[].subReplyCount

Number

ํ•˜์œ„ ๋Œ“๊ธ€ ๊ฐฏ์ˆ˜

data.reviewReplies[].createAt

Array

๋Œ“๊ธ€ ์ž‘์„ฑ ์ผ์‹œ

data.reviewReplies[].status

Null

๋Œ“๊ธ€ ์ƒํƒœ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 5,
    "reviewReplies" : [ {
      "userId" : 0,
      "imageUrl" : "https://picsum.photos/500",
      "nickName" : "ugGCJbrGWj",
      "reviewReplyId" : 0,
      "reviewReplyContent" : "pyBxVQjRkvWtqwQsmEHOAbKmoLTnyzprKtssMLabfWPRjQQThZChzZRCIWrORyhegDIJQArRfGhJgDDnufStlgYwyiaSeugMojDEGiNxzllNUcXHOtXGtCNfGUNwAOjeyZwMxyLFNDLdHJIGnLTMWa",
      "subReplyCount" : 1,
      "status" : null,
      "createAt" : [ 2024, 7, 11, 0, 0 ]
    }, {
      "userId" : 1,
      "imageUrl" : "https://picsum.photos/500",
      "nickName" : "ERbjtuRDGw",
      "reviewReplyId" : 1,
      "reviewReplyContent" : "WuKHvvalMeiupsUkXUBOWxScokEnwwKaqzOVrFATtHiapPmEVhdeeEpWrJNbiuPdtMoApwSldDEJmppWdOpXdMUswBnsBRUaJiITWctEECaCmASiwPRQRopxHZukcniMsLPwuHTHuNLTUpNCzVwqod",
      "subReplyCount" : 4,
      "status" : null,
      "createAt" : [ 2024, 7, 11, 0, 0 ]
    }, {
      "userId" : 2,
      "imageUrl" : "https://picsum.photos/500",
      "nickName" : "QHIqGiPeER",
      "reviewReplyId" : 2,
      "reviewReplyContent" : "VgVBQeeHxxAdoDGHHEusBVmNIrBMrIzlyghprGAJIgUwAZITWTHwDhYWCYGEdDHUjgXavTJPMXnKZtCrgJuChsmpkxySknatuoUAtGjRZkkyTePqBOedqUBnBviYiBaMrWjrEgkqOqDPtVCXkporkN",
      "subReplyCount" : 2,
      "status" : null,
      "createAt" : [ 2024, 7, 11, 0, 0 ]
    }, {
      "userId" : 3,
      "imageUrl" : "https://picsum.photos/500",
      "nickName" : "XGvDrWgMzf",
      "reviewReplyId" : 3,
      "reviewReplyContent" : "BuxYjmHFWyfuXjxYfqGiQWvEDdtratZZwxaqlnLXQloDetuIrTKldbLbtiXWLWygvUYeMHpQKbCTBaBmonzoVPPyOiyREMuUhSEhaWkuDnPqqOqkMsPlCOfBVyUIQznroSVrzfFHHBDEfuyBxqlKqN",
      "subReplyCount" : 2,
      "status" : null,
      "createAt" : [ 2024, 7, 11, 0, 0 ]
    }, {
      "userId" : 4,
      "imageUrl" : "https://picsum.photos/500",
      "nickName" : "jToyJuRjWP",
      "reviewReplyId" : 4,
      "reviewReplyContent" : "YLAfujDWiSrkCQWvhMPVJFKFsnEPHyCNKPeucpuTFGbbFDJMDVvpmDPSqNuwLJeGRwvsipspXFvVtRxHONrVDUcHTciqBIwojVEuJNUNvisbbGdOwKRKdXKHCqrCMNSawKxPNQbGTHsKBRecsVGsXA",
      "subReplyCount" : 3,
      "status" : null,
      "createAt" : [ 2024, 7, 11, 0, 0 ]
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 11, 307837876 ],
    "serverPathVersion" : "v1"
  }
}

9.4. ํ•˜์œ„ ๋ฆฌ๋ทฐ ๋Œ“๊ธ€ ๋ชฉ๋ก ์กฐํšŒ

๋ฆฌ๋ทฐ์˜ ๋Œ€๋Œ“๊ธ€ ๋ชฉ๋ก์„ ์กฐํšŒํ•˜๋Š” API์ž…๋‹ˆ๋‹ค.

๊ฒฝ๋กœ์˜ rootReplyId ๋Š” ์ตœ์ƒ์œ„ ๋Œ“๊ธ€ ๋ชฉ๋ก ์กฐํšŒ API ํ†ตํ•ด ์กฐํšŒํ•œ ๋Œ“๊ธ€์˜ ์‹๋ณ„์ž๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

๊ตฌ์กฐ ์˜ˆ ).

a3qNSWs
  • ์ตœ์ƒ์œ„ ๋ฆฌ๋ทฐ ๋Œ“๊ธ€ ๋ชฉ๋ก ์กฐํšŒ API ๋ฅผ ํ†ตํ•ด Root Reply์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • ํ•˜์œ„ ๋ฆฌ๋ทฐ ๋Œ“๊ธ€ ๋ชฉ๋ก ์กฐํšŒ API ๋ฅผ ํ†ตํ•ด Root Reply์— ๋Œ€ํ•œ ๋Œ€๋Œ“๊ธ€์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

  • 2๋ฒˆ ๋Œ“๊ธ€์˜ ํ•˜์œ„ ๋Œ“๊ธ€์„ ์กฐํšŒ ํ•˜๊ธฐ ์œ„ํ•ด 2๋ฒˆ ๋Œ“๊ธ€์˜ ์‹๋ณ„์ž๋ฅผ pathVariable ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค

  • ๋Œ“๊ธ€์˜ ๊ด€๊ณ„๋Š” ์ตœ์ƒ์œ„ ๋Œ“๊ธ€::ํ•˜์œ„ ๋Œ“๊ธ€ ๊ณผ ๋ถ€๋ชจ ๋Œ“๊ธ€: ์ž์‹ ๋Œ“๊ธ€ ๊ด€๊ณ„๋กœ ๊ตฌ๋ถ„๋ฉ๋‹ˆ๋‹ค.

    • ์ตœ์ƒ์œ„ ๋Œ“๊ธ€::ํ•˜์œ„ ๋Œ“๊ธ€ :1:N์˜ ๊ด€๊ณ„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
      ์ตœ์ƒ์œ„ ๋Œ“๊ธ€๋งŒ ๋Œ€์ƒ์ด ๋ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • ๋ถ€๋ชจ ๋Œ“๊ธ€: ์ž์‹ ๋Œ“๊ธ€ : 1:N์˜ ๊ด€๊ณ„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
      ๋ถ€๋ชจ ๋Œ“๊ธ€์€ ์ตœ์ƒ์œ„ ๋Œ“๊ธ€์ด ์•„๋‹ˆ์—ฌ๋„ ๋Œ€์ƒ์ด ๋ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

      • 2-1๋ฒˆ ๋Œ“๊ธ€์˜ ์ƒ์œ„ ๋Œ“๊ธ€๊ณผ ์ตœ์ƒ์œ„ ๋Œ“๊ธ€์€ ๋ชจ๋‘ 2๋ฒˆ ๋Œ“๊ธ€์ž…๋‹ˆ๋‹ค.

      • 2-2๋ฒˆ ๋Œ“๊ธ€์˜ ์ƒ์œ„ ๋Œ“๊ธ€์€ 2-1๋ฒˆ ๋Œ“๊ธ€์ด๋ฉฐ ์ตœ์ƒ์œ„ ๋Œ“๊ธ€์€ 2๋ฒˆ ๋Œ“๊ธ€์ž…๋‹ˆ๋‹ค.

      • 2-3๋ฒˆ ๋Œ“๊ธ€์˜ ์ƒ์œ„ ๋Œ“๊ธ€์€ 2-1๋ฒˆ ๋Œ“๊ธ€์ด๋ฉฐ ์ตœ์ƒ์œ„ ๋Œ“๊ธ€์€ 2๋ฒˆ ๋Œ“๊ธ€์ž…๋‹ˆ๋‹ค.

      • 2-4๋ฒˆ ๋Œ“๊ธ€์˜ ์ƒ์œ„ ๋Œ“๊ธ€์€ 2-3๋ฒˆ ๋Œ“๊ธ€์ด๋ฉฐ ์ตœ์ƒ์œ„ ๋Œ“๊ธ€์€ 2๋ฒˆ ๋Œ“๊ธ€์ž…๋‹ˆ๋‹ค.

API EndPoint

GET /api/v1/review/reply/{reviewId}/sub/{rootReplyId}
  • reviewId : ๋ฆฌ๋ทฐ ์‹๋ณ„์ž

  • rootReplyId : ์ตœ์ƒ์œ„ ๋Œ“๊ธ€ ์‹๋ณ„์ž

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

Table 4. /api/v1/review/reply/{reviewId}/sub/{rootReplyId}
Parameter Description

reviewId

๋Œ“๊ธ€์„ ์ž‘์„ฑ ๋Œ€์ƒ ๋ฆฌ๋ทฐ์˜ ์‹๋ณ„์ž

rootReplyId

์ตœ์ƒ์œ„ ๋Œ“๊ธ€ ์‹๋ณ„์ž

Parameter Description

cursor

ํŽ˜์ด์ง• ์ปค์„œ (์กฐํšŒ๋ฅผ ์‹œ์ž‘ํ•  ์œ„์น˜)

pageSize

ํŽ˜์ด์ง€ ํฌ๊ธฐ (ํ•œ๋ฒˆ์— ์กฐํšŒ๋  ๋ฐ์ดํ„ฐ ์–‘)

  • ์ •๋ ฌ์€ ์ตœ์‹ ์ˆœ ์œผ๋กœ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

  • cursor ์™€ pageSize ์˜ ๊ธฐ๋ณธ๊ฐ’์€ ๊ฐ๊ฐ 0 , 50 ์ž…๋‹ˆ๋‹ค

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

  • ๋‹‰๋„ค์ž„๊ณผ ๋‚ด์šฉ์€ ์˜ˆ์‹œ๋กœ๋งŒ ๋ด์ฃผ์„ธ์š” . ๋žœ๋ค์„ฑ ๋ฌธ์ž์—ด๋กœ ๋…ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

path type description

success

Boolean

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

code

Number

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

data

Object

์‘๋‹ต ๋ฐ์ดํ„ฐ

data.totalCount

Number

์ „์ฒด ๋Œ“๊ธ€ ๊ฐฏ์ˆ˜

data.reviewReplies[].userId

Number

๋Œ“๊ธ€ ์ž‘์„ฑ์ž ์‹๋ณ„์ž

data.reviewReplies[].imageUrl

String

๋Œ“๊ธ€ ์ž‘์„ฑ์ž ํ”„๋กœํ•„ ์ด๋ฏธ์ง€ URL

data.reviewReplies[].nickName

String

๋Œ“๊ธ€ ์ž‘์„ฑ์ž ๋‹‰๋„ค์ž„

data.reviewReplies[].rootReviewId

Number

์ตœ์ƒ์œ„ ๋Œ“๊ธ€ ์‹๋ณ„์ž

data.reviewReplies[].parentReviewReplyId

Number

์ƒ์œ„ ๋Œ“๊ธ€ ์‹๋ณ„์ž

data.reviewReplies[].parentReviewReplyAuthor

String

์ƒ์œ„ ๋Œ“๊ธ€ ์ž‘์„ฑ์ž ๋‹‰๋„ค์ž„ (@ ๊ธฐํ˜ธ๋Š” ์ œ์™ธ)

data.reviewReplies[].reviewReplyId

Number

๋Œ“๊ธ€ ์ž์ฒด ์‹๋ณ„์ž

data.reviewReplies[].reviewReplyContent

String

๋Œ“๊ธ€ ๋‚ด์šฉ

data.reviewReplies[].createAt

Array

๋Œ“๊ธ€ ์ž‘์„ฑ ์ผ์‹œ

data.reviewReplies[].status

Null

๋Œ“๊ธ€ ์ƒํƒœ

meta

Object

๋ฉ”ํƒ€ ์ •๋ณด (ํ•ด๋‹น ์‘๋‹ต ๊ฐ’์€ ๋ณ„๋„์˜ ํŽ˜์ด์ง€ ์ •๋ณด๊ฐ€ ์ œ๊ณต๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.)

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 4,
    "reviewReplies" : [ {
      "userId" : 123,
      "imageUrl" : "https://picsum.photos/500",
      "nickName" : "PFPCFLXoVT",
      "rootReviewId" : 1,
      "parentReviewReplyId" : 1,
      "parentReviewReplyAuthor" : "@์ฉ์–ด๊ฐ€๋Š”๋ง๊ณ ",
      "reviewReplyId" : 1,
      "reviewReplyContent" : "GnXTMSbNWLTipGGmvXpADqPECnglrZiWXHSYZVWsFhFMGDUBFcRRpiCrpMgVaGhtMLNXQMWxfhbfXJZRqOhgzARaHWpQrcAPUtTXlHiyDDeAfzzIetJVJuuPAJtvqGRhtkUctkVCRCjhpBHhtEFCKq",
      "status" : null,
      "createAt" : [ 2024, 7, 11, 0, 0 ]
    }, {
      "userId" : 123,
      "imageUrl" : "https://picsum.photos/500",
      "nickName" : "HyorzrqyIz",
      "rootReviewId" : 1,
      "parentReviewReplyId" : 1,
      "parentReviewReplyAuthor" : "@์‹ ์„ ํ•œ๋ฐ˜๋‚˜๋‚˜",
      "reviewReplyId" : 2,
      "reviewReplyContent" : "ssOJLocwIyQxsIbuBvxUQeuvBTdIbLJhQVNYGXseKLGzzxznWdWnGxwaValJXiFQMIpCCMdwVtkIxHgpRKZXfntdnYSsSruLbvCPZhQAoHUYvjdqBOZaGRexPYfUJqtYhNqMlxzKcFeKllOFFFgBsl",
      "status" : null,
      "createAt" : [ 2024, 7, 11, 0, 0 ]
    }, {
      "userId" : 123,
      "imageUrl" : "https://picsum.photos/500",
      "nickName" : "pDmDotRtpz",
      "rootReviewId" : 1,
      "parentReviewReplyId" : 1,
      "parentReviewReplyAuthor" : "@์‹ ์„ ํ•œ๋ฐ˜๋‚˜๋‚˜",
      "reviewReplyId" : 3,
      "reviewReplyContent" : "hbesyLMJaaKyediTSSWDukKIniTVZJABKYijEiZUyPlyXqPyggDqlncgMBHnultgBdzPZZJpbZQKLAqwhyEhNEZVzZUbccrLRXtnuRSzyXRreabmDsfeXHnEGVRTBkoSNgZlIZfpZGTMNcSdPJKiRj",
      "status" : null,
      "createAt" : [ 2024, 7, 11, 0, 0 ]
    }, {
      "userId" : 123,
      "imageUrl" : "https://picsum.photos/500",
      "nickName" : "KknfCGsJrx",
      "rootReviewId" : 1,
      "parentReviewReplyId" : 1,
      "parentReviewReplyAuthor" : "@์ฉ์–ด๊ฐ€๋Š”๋ง๊ณ ",
      "reviewReplyId" : 4,
      "reviewReplyContent" : "fbULGrlJhMBHIbOVuEYwmVAYxftVKDqPQMVWSYafKGDURfVrlRHdkDLniHubgbcGOAwyZVvwLuKtewlHlWPVTZXPbDazfjoANExlxHupCVstOeuajtGAcubleudHlUancNoRjdhCdJKpMdBOtiTQUi",
      "status" : null,
      "createAt" : [ 2024, 7, 11, 0, 0 ]
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 11, 349730995 ],
    "serverPathVersion" : "v1"
  }
}

10. ์ง€์› (support) ๊ด€๋ จ API

10.1. ์‚ฌ์šฉ์ž ์ฐจ๋‹จ

ํŠน์ • ์‚ฌ์šฉ์ž๋ฅผ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค.

POST /api/v1/blocks

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

path type optional description

blockedUserId

Number

์ฐจ๋‹จํ•  ์‚ฌ์šฉ์ž ID

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

path type description

data.totalCount

Number

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ์ด ์ˆ˜

data.items

Array

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ๋ชฉ๋ก

data.items[].userId

Number

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ID

data.items[].userName

String

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ์ด๋ฆ„

data.items[].blockedAt

Array

์ฐจ๋‹จ๋œ ์‹œ๊ฐ

์ฐจ๋‹จ ์™„๋ฃŒ ํ›„ ํ˜„์žฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ฐจ๋‹จํ•œ ๋ชจ๋“  ์‚ฌ์šฉ์ž ๋ชฉ๋ก์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

10.2. ์ฐจ๋‹จ ํ•ด์ œ

์ฐจ๋‹จํ•œ ์‚ฌ์šฉ์ž๋ฅผ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

DELETE /api/v1/blocks/{blockedUserId}

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

Table 5. /api/v1/blocks/{blockedUserId}
Parameter Description

blockedUserId

์ฐจ๋‹จ ํ•ด์ œํ•  ์‚ฌ์šฉ์ž ID

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

path type description

data.totalCount

Number

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ์ด ์ˆ˜

data.items

Array

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ๋ชฉ๋ก

์ฐจ๋‹จ ํ•ด์ œ ํ›„ ํ˜„์žฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ฐจ๋‹จํ•œ ๋ชจ๋“  ์‚ฌ์šฉ์ž ๋ชฉ๋ก์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

10.3. ์ฐจ๋‹จ ๋ชฉ๋ก ์กฐํšŒ

ํ˜„์žฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ฐจ๋‹จํ•œ ์‚ฌ์šฉ์ž๋“ค์˜ ์ƒ์„ธ ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/blocks

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

path type description

data.totalCount

Number

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ์ด ์ˆ˜

data.items

Array

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ๋ชฉ๋ก

data.items[].userId

Number

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ID

data.items[].userName

String

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ์ด๋ฆ„

data.items[].blockedAt

Array

์ฐจ๋‹จ๋œ ์‹œ๊ฐ

๊ฐ ์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž์˜ ID, ์ด๋ฆ„, ์ฐจ๋‹จ ์‹œ๊ฐ ์ •๋ณด๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

10.4. ์ฐจ๋‹จ ์‚ฌ์šฉ์ž ID ๋ชฉ๋ก ์กฐํšŒ

๋น ๋ฅธ ์ฐจ๋‹จ ์—ฌ๋ถ€ ํ™•์ธ์„ ์œ„ํ•ด ์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ID๋งŒ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/blocks/ids

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

path type description

data

Array

์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž ID ๋ชฉ๋ก

ํด๋ผ์ด์–ธํŠธ์—์„œ ๋น ๋ฅธ ํ•„ํ„ฐ๋ง์ด๋‚˜ ๊ถŒํ•œ ์ฒดํฌ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

10.5. ์ฐจ๋‹จ ์—ฌ๋ถ€ ํ™•์ธ

ํŠน์ • ์‚ฌ์šฉ์ž๊ฐ€ ์ฐจ๋‹จ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/blocks/check/{targetUserId}

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

Table 6. /api/v1/blocks/check/{targetUserId}
Parameter Description

targetUserId

์ฐจ๋‹จ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ์‚ฌ์šฉ์ž ID

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

path type description

data

Boolean

์ฐจ๋‹จ ์—ฌ๋ถ€

10.6. ์ƒํ˜ธ ์ฐจ๋‹จ ์—ฌ๋ถ€ ํ™•์ธ

๋‘ ์‚ฌ์šฉ์ž๊ฐ€ ์„œ๋กœ ์ฐจ๋‹จํ–ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/blocks/mutual-check/{targetUserId}

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

Table 7. /api/v1/blocks/mutual-check/{targetUserId}
Parameter Description

targetUserId

์ƒํ˜ธ ์ฐจ๋‹จ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•  ์‚ฌ์šฉ์ž ID

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

path type description

data

Boolean

์ƒํ˜ธ ์ฐจ๋‹จ ์—ฌ๋ถ€

์ƒํ˜ธ ์ฐจ๋‹จ ์ƒํƒœ์—์„œ๋Š” ์–‘์ชฝ ๋ชจ๋‘ ์ƒ๋Œ€๋ฐฉ์˜ ์ฝ˜ํ…์ธ ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

10.7. ๋‚˜๋ฅผ ์ฐจ๋‹จํ•œ ์‚ฌ์šฉ์ž ์ˆ˜

ํ˜„์žฌ ์‚ฌ์šฉ์ž๋ฅผ ์ฐจ๋‹จํ•œ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๋“ค์˜ ์ˆ˜๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/blocks/stats/blocked-by-count

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

path type description

data

Number

๋‚˜๋ฅผ ์ฐจ๋‹จํ•œ ์‚ฌ์šฉ์ž ์ˆ˜

10.8. ๋‚ด๊ฐ€ ์ฐจ๋‹จํ•œ ์‚ฌ์šฉ์ž ์ˆ˜

ํ˜„์žฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ฐจ๋‹จํ•œ ์‚ฌ์šฉ์ž๋“ค์˜ ์ˆ˜๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/blocks/stats/blocking-count

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

path type description

data

Number

๋‚ด๊ฐ€ ์ฐจ๋‹จํ•œ ์‚ฌ์šฉ์ž ์ˆ˜

10.9. ์—๋Ÿฌ ์ฝ”๋“œ

์ฐจ๋‹จ API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํ™ฉ ์„ค๋ช…

400

์ž๊ธฐ ์ž์‹ ์„ ์ฐจ๋‹จํ•˜๋ ค๋Š” ๊ฒฝ์šฐ

์ž๊ธฐ ์ž์‹ ์€ ์ฐจ๋‹จํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

400

์ด๋ฏธ ์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž๋ฅผ ๋‹ค์‹œ ์ฐจ๋‹จํ•˜๋ ค๋Š” ๊ฒฝ์šฐ

์ด๋ฏธ ์ฐจ๋‹จ๋œ ์‚ฌ์šฉ์ž์ž…๋‹ˆ๋‹ค.

404

์กด์žฌํ•˜์ง€ ์•Š๋Š” ์‚ฌ์šฉ์ž๋ฅผ ์ฐจ๋‹จํ•˜๋ ค๋Š” ๊ฒฝ์šฐ

ํ•ด๋‹น ์‚ฌ์šฉ์ž๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

404

์ฐจ๋‹จํ•˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž๋ฅผ ํ•ด์ œํ•˜๋ ค๋Š” ๊ฒฝ์šฐ

์ฐจ๋‹จ ๊ด€๊ณ„๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

401

์ธ์ฆ๋˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž

๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  • ์ถ”๊ฐ€๋˜์ง€ ์•Š์€ ์—๋Ÿฌ ์ฝ”๋“œ๋Š” ์š”์ฒญ ๋ฐ”๋ž๋‹ˆ๋‹ค.

  • Request validation์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ ๊ณตํ†ต ์˜ˆ์™ธ๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

10.10. ์œ ์ € ์‹ ๊ณ  ์š”์ฒญ

ํŠน์ •ํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ๋ถ€์ ์ ˆํ•œ ํ–‰๋™์„ ํ–ˆ์„ ๋•Œ, ํ•ด๋‹น ์‚ฌ์šฉ์ž๋ฅผ ์‹ ๊ณ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

user report์˜ ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž๊ฐ„ ์‹ ๊ณ ๋กœ,

์‹ ๊ณ ์ž์™€ ํ”ผ์‹ ๊ณ ์ž๊ฐ€ ๋ชจ๋‘ ์‚ฌ์šฉ์ž์ธ ๊ฒฝ์šฐ์—๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์‹ ๊ณ  ์œ ํ˜• ์ฝ”๋“œ ์„ค๋ช…

SPAM

์ŠคํŒธ

INAPPROPRIATE_CONTENT

๋ถ€์ ์ ˆํ•œ ์ฝ˜ํ…์ธ 

FRAUD

์‚ฌ๊ธฐ

COPYRIGHT_INFRINGEMENT

์ €์ž‘๊ถŒ ์นจํ•ด

OTHER

๊ธฐํƒ€

์ถ”๊ฐ€๋˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™์€ ์‹ ๊ณ  ์œ ํ˜•์ด ์žˆ์œผ๋ฉด ์š”์ฒญ ๋ฐ”๋ž๋‹ˆ๋‹ค.


POST /api/v1/reports/user

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

path type optional description

reportUserId

Number

์‹ ๊ณ  ๋Œ€์ƒ์ž ์œ ์ € ID(์‹ ๊ณ ๋ฅผ ๋‹นํ•˜๋Š” ์œ ์ €

type

String

์‹ ๊ณ  ํƒ€์ž… ( SPAM , INAPPROPRIATE_CONTENT ,FRAUD ,COPYRIGHT_INFRINGEMENT ,OTHER )

content

String

์‹ ๊ณ  ๋‚ด์šฉ

{
  "reportUserId" : 2,
  "type" : "OTHER",
  "content" : "์‹ ๊ณ  ๋‚ด์šฉ ์ผ๋ผ ์ผ๋ผ ์ผ๋ผ "
}

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.message

String

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

data.reportId

Number

์ฒ˜๋ฆฌ๋œ ์‹ ๊ณ  ID

data.reportUserId

Number

์‹ ๊ณ  ๋Œ€์ƒ ์œ ์ € ID

data.reportUserName

String

์‹ ๊ณ  ๋Œ€์ƒ ์œ ์ € ์ด๋ฆ„

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€(์—†์„ ๊ฒฝ์šฐ null)

meta.serverEncoding

String

์„œ๋ฒ„ ์ธ์ฝ”๋”ฉ ์ •๋„

meta.serverVersion

String

์„œ๋ฒ„ ๋ฒ„์ „

meta.serverPathVersion

String

์„œ๋ฒ„ ๊ฒฝ๋กœ ๋ฒ„์ „

meta.serverResponseTime

Array

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "message" : "์‹ ๊ณ ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์ ‘์ˆ˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
    "reportId" : 1,
    "reportUserId" : 2,
    "reportUserName" : "์‹ ๊ณ ํ•œ ์œ ์ € ์ด๋ฆ„"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 12, 267365213 ],
    "serverPathVersion" : "v1"
  }
}
์ฝ”๋“œ ์˜ˆ์™ธ ์ƒํ™ฉ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€

400

`content`๊ฐ€ 300์ž๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ๊ฒฝ์šฐ

"`content`๋Š” 300์ž ์ด๋‚ด์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค."

400

์‹ ๊ณ ์ž๊ฐ€ ์ž์‹ ์„ ์‹ ๊ณ ํ•˜๋Š” ๊ฒฝ์šฐ

"์ž์‹ ์„ ์‹ ๊ณ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."

400

๋™์ผ ์œ ์ €์— ๋Œ€ํ•ด ์ผ๋‹น ์ตœ๋Œ€ ํ•œ๊ฑด์˜ ์‹ ๊ณ ๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ๊ฒฝ์šฐ

"๋™์ผ ์œ ์ €์— ๋Œ€ํ•ด ์ผ๋‹น ์ตœ๋Œ€ ํ•œ๊ฑด์˜ ์‹ ๊ณ ๋งŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค."

400

์‹ ๊ณ  ๋Œ€์ƒ ์‚ฌ์šฉ์ž๊ฐ€ ์ผ์ผ ์‹ ๊ณ  ํšŸ์ˆ˜ ์ œํ•œ์„ ์ดˆ๊ณผํ•˜๋Š” ๊ฒฝ์šฐ

"์ผ์ผ ์‹ ๊ณ  ํšŸ์ˆ˜ ์ œํ•œ์„ ์ดˆ๊ณผํ•˜์˜€์Šต๋‹ˆ๋‹ค."

404

์‹ ๊ณ  ๋Œ€์ƒ ์‚ฌ์šฉ์ž๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ

"์‹ ๊ณ  ๋Œ€์ƒ ์‚ฌ์šฉ์ž๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."

  • ์ถ”๊ฐ€๋˜์ง€ ์•Š์€ ์—๋Ÿฌ ์ฝ”๋“œ๋Š” ์š”์ฒญ ๋ฐ”๋ž๋‹ˆ๋‹ค.

  • request valid์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ ๊ณตํ†ต ์˜ˆ์™ธ๋ฅผ ํ†ตํ•ด ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

10.11. ๋ฌธ์˜ ๊ด€๋ฆฌ (help)

10.11.1. ๋ฌธ์˜๊ธ€ ์ž‘์„ฑ

์‚ฌ์šฉ์ž๋Š” ์‹œ์Šคํ…œ ๊ด€๋ฆฌ์ž์—๊ฒŒ ๋ฌธ์˜๊ธ€์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์˜๊ธ€ ์ œ๋ชฉ์€ null์ด๊ฑฐ๋‚˜ ๊ณต๋ฐฑ("")์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋ฌธ์˜๊ธ€ ๋‚ด์šฉ์€ null์ด๊ฑฐ๋‚˜ ๊ณต๋ฐฑ("")์ผ ์ˆ˜ ์—†์œผ๋ฉฐ, ์ตœ๋Œ€ 1000์ž๊นŒ์ง€ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค.

๋ฌธ์˜๊ธ€์˜ ํƒ€์ž…์€ ์•„๋ž˜ ํ‘œ๋กœ ๊ธฐ์ˆ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์˜๊ธ€ ํƒ€์ž… ์„ค๋ช…

WHISKEY

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

REVIEW

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

USER

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

ETC

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

POST /api/v1/help
์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ
path type optional description

title

String

๋ฌธ์˜๊ธ€ ์ œ๋ชฉ

content

String

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

type

String

๋ฌธ์˜๊ธ€ ํƒ€์ž… (WHISKEY, REVIEW, USER, ETC)

imageUrlList

Array

์ด๋ฏธ์ง€ URL ๋ชฉ๋ก

imageUrlList[].order

Number

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

imageUrlList[].viewUrl

String

์ด๋ฏธ์ง€ URL

{
  "title" : "๋ฌธ์˜ ์ œ๋ชฉ",
  "content" : "๋กœ๊ทธ์ธ์ด ์•ˆ๋ผ์š”",
  "type" : "USER",
  "imageUrlList" : [ {
    "order" : 1,
    "viewUrl" : "https://api.bottle-note.com/images/1"
  } ]
}
์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ
path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.codeMessage

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ

data.message

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€

data.helpId

Number

๋ฌธ์˜๊ธ€ ์•„์ด๋””

data.responseAt

String

์„œ๋ฒ„ ์‘๋‹ต ์ผ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "REGISTER_SUCCESS",
    "message" : "๋ฌธ์˜๊ธ€ ๋“ฑ๋ก์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
    "helpId" : 1,
    "responseAt" : "2026-04-08 13:53:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 12, 22225221 ],
    "serverPathVersion" : "v1"
  }
}
Error code
  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

TITLE_NOT_EMPTY

BAD_REQUEST

null์ž…๋‹ˆ๋‹ค. ํƒ€์ดํ‹€(์ œ๋ชฉ)์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.

CONTENT_NOT_EMPTY

BAD_REQUEST

null์ž…๋‹ˆ๋‹ค. ๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."

REQUIRED_HELP_TYPE

BAD_REQUEST

๋ฌธ์˜ ์œ ํ˜•์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.(WHISKEY, REVIEW, USER, ETC)

10.11.2. ๋ฌธ์˜๊ธ€ ๋ชฉ๋ก์กฐํšŒ

์‚ฌ์šฉ์ž๋Š” ๋“ฑ๋กํ•œ ๋ฌธ์˜๊ธ€์˜ ๋ชฉ๋ก์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ํ•œ ์œ ์ €๋งŒ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

QueryParam์œผ๋กœ cursor์™€ pageSize๋ฅผ ์ „๋‹ฌํ•˜๋ฉฐ, default ๊ฐ’์€ cursor๋Š” 0, pageSize๋Š” 10์ž…๋‹ˆ๋‹ค.

GET /api/v1/help
์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ
path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ

data.helpList[].helpId

Number

๋ฌธ์˜๊ธ€ ID

data.helpList[].title

String

๋ฌธ์˜๊ธ€ ์ œ๋ชฉ

data.helpList[].content

String

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

data.helpList[].createAt

Array

๋ฌธ์˜๊ธ€ ๋“ฑ๋ก์ผ์‹œ

data.helpList[].helpStatus

String

๋ฌธ์˜๊ธ€ ์ฒ˜๋ฆฌ์ƒํƒœ

meta.pageable

Object

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

meta.pageable.currentCursor

Number

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

meta.pageable.cursor

Number

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

meta.pageable.pageSize

Number

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Boolean

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 2,
    "helpList" : [ {
      "helpId" : 1,
      "title" : "์ œ๋ชฉ1",
      "content" : "test1",
      "createAt" : [ 2026, 4, 8, 13, 53, 12, 75221192 ],
      "helpStatus" : "WAITING"
    }, {
      "helpId" : 2,
      "title" : "์ œ๋ชฉ2",
      "content" : "test2",
      "createAt" : [ 2026, 4, 8, 13, 53, 12, 75237843 ],
      "helpStatus" : "WAITING"
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 12, 87650895 ],
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 1,
      "pageSize" : 2,
      "hasNext" : false
    },
    "serverPathVersion" : "v1"
  }
}
Error Code
  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

10.11.3. ๋ฌธ์˜๊ธ€ ์ƒ์„ธ์กฐํšŒ

์‚ฌ์šฉ์ž๋Š” ๋“ฑ๋กํ•œ ๋ฌธ์˜๊ธ€ ์ƒ์„ธ์กฐํšŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PathVariable๋กœ ๋ฌธ์˜๊ธ€์˜ id๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ํ•œ ์œ ์ €๋งŒ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฌธ์˜๊ธ€ id๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๊ฒฝ์šฐ HELP_NOT_FOUND ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/help/{helpId}
์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ
  • PathVariable๋กœ ๋ฌธ์˜๊ธ€์˜ id๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

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

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.helpId

Number

๋ฌธ์˜๊ธ€ ID

data.title

String

๋ฌธ์˜๊ธ€ ์ œ๋ชฉ

data.content

String

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

data.helpType

String

๋ฌธ์˜๊ธ€ ํƒ€์ž…

data.imageUrlList[].order

Number

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

data.imageUrlList[].viewUrl

String

์ด๋ฏธ์ง€ URL

data.createAt

Array

๋ฌธ์˜๊ธ€ ๋“ฑ๋ก์ผ์‹œ

data.adminId

Null

์‹œ์Šคํ…œ ๊ด€๋ฆฌ์ž ID

data.responseContent

Null

์‹œ์Šคํ…œ ๊ด€๋ฆฌ์ž ๋‹ต๋ณ€

data.lastModifyAt

Array

์ตœ์ข… ์ˆ˜์ • ์ผ์ž

data.statusType

Null

๋ฌธ์˜๊ธ€ ์ƒํƒœ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "helpId" : 1,
    "title" : "์ƒ์„ธ ์ œ๋ชฉ",
    "content" : "content",
    "helpType" : "USER",
    "imageUrlList" : [ {
      "order" : 1,
      "viewUrl" : "https://bottlenote.s3.ap-northeast-2.amazonaws.com/images/1"
    } ],
    "createAt" : [ 2026, 4, 8, 13, 53, 12, 41869405 ],
    "statusType" : null,
    "adminId" : null,
    "responseContent" : null,
    "lastModifyAt" : [ 2026, 4, 8, 13, 53, 12, 41864446 ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 12, 52156702 ],
    "serverPathVersion" : "v1"
  }
}
Error Code
  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

HELP_NOT_FOUND

NOT_FOUND

๋ฌธ์˜๊ธ€์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

10.11.4. ๋ฌธ์˜๊ธ€ ์ˆ˜์ •

์‚ฌ์šฉ์ž๋Š” ๋“ฑ๋กํ•œ ๋ฌธ์˜๊ธ€์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ˆ˜์ •ํ•˜๊ณ ์ž ํ•˜๋Š” ๋ฌธ์˜๊ธ€ ์ œ๋ชฉ, ๋‚ด์šฉ, ํƒ€์ž… ์€ null์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค

PathVariable๋กœ ๋ฌธ์˜๊ธ€์˜ id๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฌธ์˜๊ธ€ id๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๊ฒฝ์šฐ HELP_NOT_FOUND ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ํ•œ ์œ ์ €๋งŒ ์š”์ฒญ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๋ฌธ์˜๊ธ€์˜ ์ž‘์„ฑ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ HELP_NOT_AUTHORIZED ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

PATCH /api/v1/help/{helpId}
์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ
path type optional description

title

String

๋ฌธ์˜๊ธ€ ์ œ๋ชฉ

content

String

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

type

String

๋ฌธ์˜๊ธ€ ํƒ€์ž… (WHISKEY, REVIEW, USER, ETC)

imageUrlList

Array

์ด๋ฏธ์ง€ URL ๋ชฉ๋ก

imageUrlList[].order

Number

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

imageUrlList[].viewUrl

String

์ด๋ฏธ์ง€ URL

{
  "title" : "๋ฌธ์˜ ์ œ๋ชฉ",
  "content" : "๋กœ๊ทธ์ธ์ด ์•ˆ๋ผ์š”",
  "type" : "USER",
  "imageUrlList" : [ {
    "order" : 1,
    "viewUrl" : "https://api.bottle-note.com/images/1"
  } ]
}
์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ
path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.codeMessage

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ

data.message

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€

data.helpId

Number

๋ฌธ์˜๊ธ€ ์•„์ด๋””

data.responseAt

String

์„œ๋ฒ„ ์‘๋‹ต ์ผ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "MODIFY_SUCCESS",
    "message" : "๋ฌธ์˜๊ธ€ ์ˆ˜์ •์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
    "helpId" : 1,
    "responseAt" : "2026-04-08 13:53:12"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 12, 159529105 ],
    "serverPathVersion" : "v1"
  }
}
Error code
  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

TITLE_NOT_EMPTY

BAD_REQUEST

null์ž…๋‹ˆ๋‹ค. ํƒ€์ดํ‹€(์ œ๋ชฉ)์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”.

CONTENT_NOT_EMPTY

BAD_REQUEST

null์ž…๋‹ˆ๋‹ค. ๋‚ด์šฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”."

REQUIRED_HELP_TYPE

BAD_REQUEST

๋ฌธ์˜ ์œ ํ˜•์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.(WHISKEY, REVIEW, USER, ETC)

HELP_NOT_FOUND

NOT_FOUND

๋ฌธ์˜๊ธ€์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

HELP_NOT_AUTHORIZED

FORBIDDEN

๋ฌธ์˜๊ธ€ ์ˆ˜์ • ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.

10.11.5. ๋ฌธ์˜๊ธ€ ์‚ญ์ œ

์‚ฌ์šฉ์ž๋Š” ๋“ฑ๋กํ•œ ๋ฌธ์˜๊ธ€์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ฆฌ์ ์œผ๋กœ ์‚ญ์ œ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๋…ผ๋ฆฌ ์‚ญ์ œ๊ฐ€ ์ˆ˜ํ–‰๋˜๋ฉฐ status ์ปฌ๋Ÿผ์ด DELETED๋กœ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ.

PathVariable๋กœ ๋ฌธ์˜๊ธ€์˜ id๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฌธ์˜๊ธ€ id๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๊ฒฝ์šฐ HELP_NOT_FOUND ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ํ•œ ์œ ์ €๋งŒ ์š”์ฒญ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๋ฌธ์˜๊ธ€์˜ ์ž‘์„ฑ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ HELP_NOT_AUTHORIZED ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

PATCH /api/v1/help/{helpId}
์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ
path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.codeMessage

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ

data.message

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€

data.helpId

Number

๋ฌธ์˜๊ธ€ ์•„์ด๋””

data.responseAt

String

์„œ๋ฒ„ ์‘๋‹ต ์ผ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "DELETE_SUCCESS",
    "message" : "๋ฌธ์˜๊ธ€ ์‚ญ์ œ๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
    "helpId" : 1,
    "responseAt" : "2026-04-08 13:53:12"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 12, 118815863 ],
    "serverPathVersion" : "v1"
  }
}
Error code
  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

HELP_NOT_FOUND

NOT_FOUND

๋ฌธ์˜๊ธ€์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

HELP_NOT_AUTHORIZED

FORBIDDEN

๋ฌธ์˜๊ธ€ ์‚ญ์ œ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.

10.12. ๋น„์ฆˆ๋‹ˆ์Šค ๊ด€๋ฆฌ (business)

10.12.1. ๋น„์ฆˆ๋‹ˆ์Šค ๋ฌธ์˜ ๋“ฑ๋ก

์‚ฌ์šฉ์ž๋Š” ๋น„์ง€๋‹ˆ์Šค ๊ด€๋ จ ๋ฌธ์˜๋ฅผ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

POST /api/v1/business-support
์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ
path type optional description

title

String

๋ฌธ์˜ ์ œ๋ชฉ

content

String

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

contact

String

์—ฐ๋ฝ์ฒ˜

businessSupportType

String

๋ฌธ์˜ ์œ ํ˜• (EVENT, ADVERTISEMENT, ETC)

imageUrlList

Array

์ด๋ฏธ์ง€ URL ๋ชฉ๋ก

imageUrlList[].order

Number

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

imageUrlList[].viewUrl

String

์ด๋ฏธ์ง€ URL

{
  "title" : "๋น„์ฆˆ๋‹ˆ์Šค ๋ฌธ์˜ ์ œ๋ชฉ",
  "content" : "์ƒˆ๋กœ์šด ๋น„์ฆˆ๋‹ˆ์Šค ๋ฌธ์˜์ž…๋‹ˆ๋‹ค.",
  "contact" : "business@example.com",
  "businessSupportType" : "EVENT",
  "imageUrlList" : [ {
    "order" : 1,
    "viewUrl" : "https://api.bottle-note.com/image1.jpg"
  } ]
}
์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ
path type description

success

Boolean

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

code

Number

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

data.codeMessage

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ

data.message

String

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

data.id

Number

๋“ฑ๋ก๋œ ๋ฌธ์˜ ID

data.responseAt

String

์„œ๋ฒ„ ์‘๋‹ต ์ผ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "REGISTER_SUCCESS",
    "message" : "๋น„์ง€๋‹ˆ์Šค ๋ฌธ์˜๊ฐ€ ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
    "id" : 1,
    "responseAt" : "2026-04-08 13:53:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 11, 830525167 ],
    "serverPathVersion" : "v1"
  }
}

10.12.2. ๋น„์ฆˆ๋‹ˆ์Šค ๋ฌธ์˜ ๋ชฉ๋ก ์กฐํšŒ

์‚ฌ์šฉ์ž๋Š” ๋“ฑ๋กํ•œ ๋น„์ง€๋‹ˆ์Šค ๋ฌธ์˜๊ธ€์˜ ๋ชฉ๋ก์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ํ•œ ์œ ์ €๋งŒ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

QueryParam์œผ๋กœ cursor์™€ pageSize๋ฅผ ์ „๋‹ฌํ•˜๋ฉฐ, default ๊ฐ’์€ cursor๋Š” 0, pageSize๋Š” 10์ž…๋‹ˆ๋‹ค.

GET /api/v1/business-support
์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ
path type description

success

Boolean

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

code

Number

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

data.totalCount

Number

์ด ๋ฌธ์˜ ๊ฐœ์ˆ˜

data.items[].id

Number

๋ฌธ์˜ ID

data.items[].title

String

๋ฌธ์˜ ์ œ๋ชฉ

data.items[].content

String

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

data.items[].createAt

Array

๋ฌธ์˜ ์ƒ์„ฑ์ผ

data.items[].status

String

๋ฌธ์˜ ์ƒํƒœ (WAITING, ANSWERED ๋“ฑ)

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 2,
    "items" : [ {
      "id" : 2,
      "title" : "๋‘๋ฒˆ์งธ ๋ฌธ์˜ ์ œ๋ชฉ",
      "content" : "๋‘๋ฒˆ์งธ ๋ฌธ์˜",
      "createAt" : [ 2026, 4, 8, 13, 53, 11, 909923640 ],
      "status" : "WAITING"
    }, {
      "id" : 1,
      "title" : "์ฒซ๋ฒˆ์งธ ๋ฌธ์˜ ์ œ๋ชฉ",
      "content" : "์ฒซ๋ฒˆ์งธ ๋ฌธ์˜",
      "createAt" : [ 2026, 4, 7, 13, 53, 11, 910023597 ],
      "status" : "SUCCESS"
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 11, 913179248 ],
    "serverPathVersion" : "v1"
  }
}

10.12.3. ๋น„์ฆˆ๋‹ˆ์Šค ๋ฌธ์˜ ์ƒ์„ธ ์กฐํšŒ

์‚ฌ์šฉ์ž๋Š” ๋“ฑ๋กํ•œ ๋น„์ง€๋‹ˆ์Šค ๋ฌธ์˜๊ธ€ ์ƒ์„ธ์กฐํšŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PathVariable๋กœ ๋ฌธ์˜๊ธ€์˜ id๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ํ•œ ์œ ์ €๋งŒ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฌธ์˜๊ธ€ id๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๊ฒฝ์šฐ HELP_NOT_FOUND ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/business-support/{id}
์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ
  • PathVariable id : ๋ฌธ์˜ ์•„์ด๋””

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

success

Boolean

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

code

Number

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

data.id

Number

๋ฌธ์˜ ID

data.title

String

๋ฌธ์˜ ์ œ๋ชฉ

data.content

String

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

data.contact

String

์—ฐ๋ฝ์ฒ˜

data.businessSupportType

String

๋ฌธ์˜ ์œ ํ˜•

data.imageUrlList

Array

์ด๋ฏธ์ง€ URL ๋ชฉ๋ก

data.imageUrlList[].order

Number

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

data.imageUrlList[].viewUrl

String

์ด๋ฏธ์ง€ URL

data.createAt

Array

๋ฌธ์˜ ์ƒ์„ฑ์ผ

data.status

String

๋ฌธ์˜ ์ƒํƒœ

data.adminId

Number

๋‹ต๋ณ€ ๊ด€๋ฆฌ์ž ID

data.responseContent

String

๊ด€๋ฆฌ์ž ๋‹ต๋ณ€ ๋‚ด์šฉ

data.lastModifyAt

Array

์ตœ์ข… ์ˆ˜์ •์ผ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "id" : 1,
    "title" : "๋ฌธ์˜ ์ƒ์„ธ ์ œ๋ชฉ",
    "content" : "๋ฌธ์˜ ์ƒ์„ธ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.",
    "contact" : "test@example.com",
    "businessSupportType" : "EVENT",
    "imageUrlList" : [ {
      "order" : 1,
      "viewUrl" : "https://example.com/image1.jpg"
    } ],
    "createAt" : [ 2026, 4, 7, 13, 53, 11, 734159807 ],
    "status" : "SUCCESS",
    "adminId" : 100,
    "responseContent" : "๋‹ต๋ณ€ ๋“œ๋ฆฝ๋‹ˆ๋‹ค.",
    "lastModifyAt" : [ 2026, 4, 8, 13, 53, 11, 734399074 ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 11, 737117126 ],
    "serverPathVersion" : "v1"
  }
}

10.12.4. ๋น„์ฆˆ๋‹ˆ์Šค ๋ฌธ์˜ ์ˆ˜์ •

์‚ฌ์šฉ์ž๋Š” ๋“ฑ๋กํ•œ ๋น„์ง€๋‹ˆ์Šค ๋ฌธ์˜๊ธ€์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ˆ˜์ •ํ•˜๊ณ ์ž ํ•˜๋Š” ๋ฌธ์˜๊ธ€ ์ œ๋ชฉ, ๋‚ด์šฉ, ํƒ€์ž… ์€ null์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค

PathVariable๋กœ ๋ฌธ์˜๊ธ€์˜ id๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฌธ์˜๊ธ€ id๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๊ฒฝ์šฐ HELP_NOT_FOUND ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ํ•œ ์œ ์ €๋งŒ ์š”์ฒญ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๋ฌธ์˜๊ธ€์˜ ์ž‘์„ฑ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ HELP_NOT_AUTHORIZED ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

PATCH /api/v1/business-support/{id}
์š”์ฒญ ํŒŒ๋ผ๋ฏธํ„ฐ
path type optional description

title

String

์ˆ˜์ •ํ•  ์ œ๋ชฉ

content

String

์ˆ˜์ •ํ•  ๋‚ด์šฉ

contact

String

์ˆ˜์ •ํ•  ์—ฐ๋ฝ์ฒ˜

businessSupportType

String

์ˆ˜์ •ํ•  ๋ฌธ์˜ ์œ ํ˜•

imageUrlList

Array

์ˆ˜์ •ํ•  ์ด๋ฏธ์ง€ URL ๋ชฉ๋ก

imageUrlList[].order

Number

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

imageUrlList[].viewUrl

String

์ด๋ฏธ์ง€ URL

{
  "title" : "์ˆ˜์ •๋œ ์ œ๋ชฉ",
  "content" : "์ˆ˜์ •๋œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.",
  "contact" : "modified@example.com",
  "businessSupportType" : "ADVERTISEMENT",
  "imageUrlList" : [ {
    "order" : 1,
    "viewUrl" : "https://api.bottle-note.com/modified.jpg"
  } ]
}
์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ
path type description

success

Boolean

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

code

Number

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

data.codeMessage

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ

data.message

String

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

data.id

Number

์ˆ˜์ •๋œ ๋ฌธ์˜ ID

data.responseAt

String

์„œ๋ฒ„ ์‘๋‹ต ์ผ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "MODIFY_SUCCESS",
    "message" : "๋น„์ง€๋‹ˆ์Šค ๋ฌธ์˜๊ฐ€ ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
    "id" : 1,
    "responseAt" : "2026-04-08 13:53:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 11, 879981659 ],
    "serverPathVersion" : "v1"
  }
}

10.12.5. ๋น„์ฆˆ๋‹ˆ์Šค ๋ฌธ์˜ ์‚ญ์ œ

์‚ฌ์šฉ์ž๋Š” ๋“ฑ๋กํ•œ ๋ฌธ์˜๊ธ€์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ฆฌ์ ์œผ๋กœ ์‚ญ์ œ๋˜๋Š” ๊ฒƒ์ด ์•„๋‹Œ ๋…ผ๋ฆฌ ์‚ญ์ œ๊ฐ€ ์ˆ˜ํ–‰๋˜๋ฉฐ status ์ปฌ๋Ÿผ์ด DELETED๋กœ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ.

PathVariable๋กœ ๋ฌธ์˜๊ธ€์˜ id๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ฌธ์˜๊ธ€ id๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๊ฒฝ์šฐ HELP_NOT_FOUND ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋กœ๊ทธ์ธ ํ•œ ์œ ์ €๋งŒ ์š”์ฒญ์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๋ฌธ์˜๊ธ€์˜ ์ž‘์„ฑ์ž๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ HELP_NOT_AUTHORIZED ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

DELETE /api/v1/business-support/{id}
์‘๋‹ต ํŒŒ๋ผ๋ฏธํ„ฐ
path type description

success

Boolean

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

code

Number

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

data.codeMessage

String

์„ฑ๊ณต ๋ฉ”์‹œ์ง€ ์ฝ”๋“œ

data.message

String

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

data.id

Number

์‚ญ์ œ๋œ ๋ฌธ์˜ ID

data.responseAt

String

์„œ๋ฒ„ ์‘๋‹ต ์ผ์‹œ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "codeMessage" : "DELETE_SUCCESS",
    "message" : "๋น„์ง€๋‹ˆ์Šค ๋ฌธ์˜๊ฐ€ ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค",
    "id" : 1,
    "responseAt" : "2026-04-08 13:53:11"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 11, 777061622 ],
    "serverPathVersion" : "v1"
  }
}

11. ํŒ”๋กœ์šฐ (follow) ๊ด€๋ จ API

11.1. ํŒ”๋กœ์šฐ / ์–ธํŒ”๋กœ์šฐ ์—…๋ฐ์ดํŠธ

์œ ์ €๊ฐ„์˜ ํŒ”๋กœ์šฐ, ์–ธํŒ”๋กœ์šฐ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. FOLLOWING, UNFOLLOWING ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ฉ๋‹ˆ๋‹ค.

status ์„ค๋ช…

FOLLOWING

ํŒ”๋กœ์šฐ ์ƒํƒœ

UNFOLLOWING

์–ธํŒ”๋กœ์šฐ ์ƒํƒœ

API EndPoint

POST /api/v1/follow

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

$ curl 'https://api.bottle-note.com/api/v1/follow?_csrf=mqZNA0RsXxliCdZVY85NID_nu_AV_fGk8aMn-gCrrGSvjB2FqcN1NCBYbXhPPbJlAON5FVzSlsh2n5WJxZoQnjSZylaWtSW2' -i -X POST \
    -H 'Content-Type: application/json;charset=UTF-8' \
    -d '{
  "followUserId" : 1,
  "status" : "FOLLOWING"
}'
path type optional description

followUserId

Number

ํŒ”๋กœ์šฐํ•  ์œ ์ €์˜ ์•„์ด๋””

status

String

ํŒ”๋กœ์šฐ ์ƒํƒœ

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.followUserId

Number

ํŒ”๋กœ์šฐ ์œ ์ €์˜ ์•„์ด๋””

data.nickName

String

ํŒ”๋กœ์šฐ ์œ ์ €์˜ ๋‹‰๋„ค์ž„

data.imageUrl

String

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

data.message

String

๋ฉ”์‹œ์ง€

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€(์—†์„ ๊ฒฝ์šฐ null)

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

IS_NO_USER_ID_TO_FOLLOW

BAD_REQUEST

ํŒ”๋กœ์šฐ ํ•  ์œ ์ €์˜ ์•„์ด๋””๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

SELECT_FOLLOWING_OR_UNFOLLOW

BAD_REQUEST

FOLLOWING, UNFOLLOW ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”.

USER_NOT_FOUND

NOT_FOUND

์œ ์ €๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

CANNOT_FOLLOW_SELF

BAD_REQUEST

์ž๊ธฐ ์ž์‹ ์„ ํŒ”๋กœ์šฐ, ์–ธํŒ”๋กœ์šฐ ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

FOLLOW_NOT_FOUND

NOT_FOUND

ํŒ”๋กœ์šฐํ•  ๋Œ€์ƒ์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

11.2. ํŒ”๋กœ์›Œ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ

ํŒ”๋กœ์›Œ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์š”์ฒญ ๊ฒฝ๋กœ์— ์กฐํšŒํ•  ์œ ์ €์˜ ์‹๋ณ„์ž๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์œ ์ €์˜ ์‹๋ณ„์ž๋Š” Long ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

PathVariable ์„ค๋ช…

userId

์œ ์ € ID

API EndPoint

ํŒ”๋กœ์›Œ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ : ์กฐํšŒ ๋Œ€์ƒ ์‚ฌ์šฉ์ž๋ฅผ ํŒ”๋กœ์šฐ ํ•˜๊ณ  ์žˆ๋Š” ํƒ€ ์œ ์ €๋“ค์˜ ๋ชฉ๋ก ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/follow/{userId}/follower-list

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

Parameter Description

type

ํŒ”๋กœ์ž‰ or ํŒ”๋กœ์›Œ ์กฐํšŒ ์—ฌ๋ถ€ ์ฟผ๋ฆฌํŒŒ๋ผ๋ฏธํ„ฐ

cursor

์กฐํšŒ ํ•  ์‹œ์ž‘ ๊ธฐ์ค€ ์œ„์น˜

pageSize

์กฐํšŒ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

์ด ํŒ”๋กœ์šฐ ์ˆ˜

data.followerList[].userId

Number

ํŒ”๋กœ์›Œ ์œ ์ €์˜ ์•„์ด๋””

data.followerList[].followUserId

Number

ํŒ”๋กœ์šฐ ์œ ์ €์˜ ์•„์ด๋””

data.followerList[].followUserNickname

String

ํŒ”๋กœ์›Œ ์œ ์ €์˜ ๋‹‰๋„ค์ž„

data.followerList[].userProfileImage

String

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

data.followerList[].status

String

ํŒ”๋กœ์šฐ ์ƒํƒœ

data.followerList[].reviewCount

Number

๋ฆฌ๋ทฐ ์ˆ˜

data.followerList[].ratingCount

Number

ํ‰์  ์ˆ˜

meta.pageable

Object

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

meta.pageable.currentCursor

Null

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

meta.pageable.cursor

Number

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

meta.pageable.pageSize

Number

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Boolean

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 5,
    "followerList" : [ {
      "userId" : 1,
      "followUserId" : 1,
      "followUserNickname" : "nickName1",
      "userProfileImage" : "imageUrl1",
      "status" : "FOLLOWING",
      "reviewCount" : 10,
      "ratingCount" : 5
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 977372420 ],
    "pageable" : {
      "currentCursor" : null,
      "cursor" : 0,
      "pageSize" : 50,
      "hasNext" : false
    },
    "serverPathVersion" : "v1"
  }
}

11.3. ํŒ”๋กœ์ž‰ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ

ํŒ”๋กœ์ž‰ ์œ ์ € ๋ชฉ๋ก ๋ฆฌ์ŠคํŠธ ์กฐํšŒ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์š”์ฒญ ๊ฒฝ๋กœ์— ์กฐํšŒํ•  ์œ ์ €์˜ ์‹๋ณ„์ž๊ฐ€ ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์œ ์ €์˜ ์‹๋ณ„์ž๋Š” Long ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

PathVariable ์„ค๋ช…

userId

์œ ์ € ID

API EndPoint

ํŒ”๋กœ์ž‰ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ : ์กฐํšŒ ๋Œ€์ƒ ์‚ฌ์šฉ์ž๊ฐ€ ํŒ”๋กœ์ž‰ํ•œ ์œ ์ €๋ชฉ๋ก ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

GET /api/v1/follow/{userId}/following-list

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

Parameter Description

type

ํŒ”๋กœ์ž‰ or ํŒ”๋กœ์›Œ ์กฐํšŒ ์—ฌ๋ถ€ ์ฟผ๋ฆฌํŒŒ๋ผ๋ฏธํ„ฐ

cursor

์กฐํšŒ ํ•  ์‹œ์ž‘ ๊ธฐ์ค€ ์œ„์น˜

pageSize

์กฐํšŒ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

์ด ํŒ”๋กœ์šฐ ์ˆ˜

data.followerList[].userId

Number

ํŒ”๋กœ์›Œ ์œ ์ €์˜ ์•„์ด๋””

data.followerList[].followUserId

Number

ํŒ”๋กœ์šฐ ์œ ์ €์˜ ์•„์ด๋””

data.followerList[].followUserNickname

String

ํŒ”๋กœ์›Œ ์œ ์ €์˜ ๋‹‰๋„ค์ž„

data.followerList[].userProfileImage

String

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

data.followerList[].status

String

ํŒ”๋กœ์šฐ ์ƒํƒœ

data.followerList[].reviewCount

Number

๋ฆฌ๋ทฐ ์ˆ˜

data.followerList[].ratingCount

Number

ํ‰์  ์ˆ˜

meta.pageable

Object

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

meta.pageable.currentCursor

Null

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

meta.pageable.cursor

Number

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

meta.pageable.pageSize

Number

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Boolean

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 5,
    "followerList" : [ {
      "userId" : 1,
      "followUserId" : 1,
      "followUserNickname" : "nickName1",
      "userProfileImage" : "imageUrl1",
      "status" : "FOLLOWING",
      "reviewCount" : 10,
      "ratingCount" : 5
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 9, 977372420 ],
    "pageable" : {
      "currentCursor" : null,
      "cursor" : 0,
      "pageSize" : 50,
      "hasNext" : false
    },
    "serverPathVersion" : "v1"
  }
}

12. ๋ณ„์  (rating) ๊ด€๋ จ API

12.1. ๋ณ„์  ๋ชฉ๋ก ์กฐํšŒ

๋ณ„์  ์กฐํšŒ๋ฅผ ์œ„ํ•œ API ์ž…๋‹ˆ๋‹ค.

๋ฉ”๋‰ด๋ฐ”์˜ ํ•˜๋‹จ ๋ณ„์  ํŽ˜์ด์ง€๋ฅผ ์œ„ํ•œ API ์ž…๋‹ˆ๋‹ค.

GET /api/v1/rating

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

Parameter Description

keyword

๊ฒ€์ƒ‰์–ด

category

์นดํ…Œ๊ณ ๋ฆฌ (category API ์ฐธ์กฐ)

regionId

์ง€์—ญ ID (region API ์ฐธ์กฐ)

sortType

์ •๋ ฌ ํƒ€์ž…(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

sortOrder

์ •๋ ฌ ์ˆœ์„œ(ํ•ด๋‹น ๋ฌธ์„œ ํ•˜๋‹จ enum ์ฐธ์กฐ)

cursor

์กฐํšŒ ํ•  ์‹œ์ž‘ ๊ธฐ์ค€ ์œ„์น˜

pageSize

์กฐํšŒ ํ•  ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

{
  "keyword" : "์•ผ๋งˆ์žํ‚ค",
  "category" : "SINGLE_MALT",
  "regionId" : 1,
  "sortType" : "RANDOM",
  "sortOrder" : "DESC",
  "cursor" : 0,
  "pageSize" : 10
}
  • ์š”์ฒญ๊ฐ’์˜ ํ˜•ํƒœ๋Š” parameter ํ˜•์‹์œผ๋กœ ์š”์ฒญ๋˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.(์˜ˆ์‹œ๋Š” ํ‘œํ˜„์„ ์œ„ํ•œ JSON ํ˜•ํƒœ์ž…๋‹ˆ๋‹ค.)

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.totalCount

Number

์ „์ฒด ์ˆ  ๋ฆฌ์ŠคํŠธ์˜ ํฌ๊ธฐ

data.ratings[].alcoholId

Number

์ˆ  ID

data.ratings[].imageUrl

String

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

data.ratings[].korName

String

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

data.ratings[].engName

String

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

data.ratings[].korCategoryName

String

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

data.ratings[].engCategoryName

String

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

data.ratings[].isPicked

Boolean

์ˆ  ์ฐœ ์—ฌ๋ถ€

meta.pageable

Object

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

meta.pageable.currentCursor

Number

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

meta.pageable.cursor

Number

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

meta.pageable.pageSize

Number

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Boolean

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

meta.searchParameters.keyword

Null

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ๊ฒ€์ƒ‰์–ด

meta.searchParameters.category

Null

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์นดํ…Œ๊ณ ๋ฆฌ

meta.searchParameters.regionId

Null

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ง€์—ญ ID

meta.searchParameters.sortType

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ •๋ ฌ ํƒ€์ž…

meta.searchParameters.sortOrder

String

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ •๋ ฌ ์ˆœ์„œ

meta.searchParameters.cursor

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ์ปค์„œ ๊ธฐ์ค€

meta.searchParameters.pageSize

Number

๊ฒ€์ƒ‰ ์‹œ ์‚ฌ์šฉ ํ•œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 10,
    "ratings" : [ {
      "alcoholId" : 0,
      "imageUrl" : "nonImage",
      "korName" : "๊ธ€๋ Œ ์•Œ๋ผํ‚ค",
      "engName" : "Glen Araki",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "isPicked" : true
    }, {
      "alcoholId" : 1,
      "imageUrl" : "nonImage",
      "korName" : "๊ธ€๋ Œ ์•Œ๋ผํ‚ค",
      "engName" : "Glen Araki",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "isPicked" : false
    }, {
      "alcoholId" : 2,
      "imageUrl" : "nonImage",
      "korName" : "๊ธ€๋ Œ ์•Œ๋ผํ‚ค",
      "engName" : "Glen Araki",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "isPicked" : true
    }, {
      "alcoholId" : 3,
      "imageUrl" : "nonImage",
      "korName" : "๊ธ€๋ Œ ์•Œ๋ผํ‚ค",
      "engName" : "Glen Araki",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "isPicked" : false
    }, {
      "alcoholId" : 4,
      "imageUrl" : "nonImage",
      "korName" : "๊ธ€๋ Œ ์•Œ๋ผํ‚ค",
      "engName" : "Glen Araki",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "isPicked" : true
    }, {
      "alcoholId" : 5,
      "imageUrl" : "nonImage",
      "korName" : "๊ธ€๋ Œ ์•Œ๋ผํ‚ค",
      "engName" : "Glen Araki",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "isPicked" : false
    }, {
      "alcoholId" : 6,
      "imageUrl" : "nonImage",
      "korName" : "๊ธ€๋ Œ ์•Œ๋ผํ‚ค",
      "engName" : "Glen Araki",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "isPicked" : true
    }, {
      "alcoholId" : 7,
      "imageUrl" : "nonImage",
      "korName" : "๊ธ€๋ Œ ์•Œ๋ผํ‚ค",
      "engName" : "Glen Araki",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "isPicked" : false
    }, {
      "alcoholId" : 8,
      "imageUrl" : "nonImage",
      "korName" : "๊ธ€๋ Œ ์•Œ๋ผํ‚ค",
      "engName" : "Glen Araki",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "isPicked" : true
    }, {
      "alcoholId" : 9,
      "imageUrl" : "nonImage",
      "korName" : "๊ธ€๋ Œ ์•Œ๋ผํ‚ค",
      "engName" : "Glen Araki",
      "korCategoryName" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategoryName" : "Single Malt",
      "isPicked" : false
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 497488172 ],
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 0,
      "pageSize" : 10,
      "hasNext" : false
    },
    "searchParameters" : {
      "keyword" : null,
      "category" : null,
      "regionId" : null,
      "sortType" : "RANDOM",
      "sortOrder" : "DESC",
      "cursor" : 0,
      "pageSize" : 10
    },
    "serverPathVersion" : "v1"
  }
}
์ •๋ ฌ ํƒ€์ž… (sortType)
type description

RANDOM

๋žœ๋ค

POPULAR

์ธ๊ธฐ

RATING

๋ณ„์ 

PICK

์ฐœํ•˜๊ธฐ

REVIEW

๋ฆฌ๋ทฐ

  • ํ•ด๋‹น ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ POPULAR ์ž…๋‹ˆ๋‹ค.

  • ํƒ€์ž…์ด ์ž˜๋ชป ์ „๋‹ฌ๋  ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

์ •๋ ฌ ๋ฐฉํ–ฅ (sortOrder)
  • ํ•ด๋‹น ์ •์˜๋Š” ์ •๋ ฌ ๋ฐฉํ–ฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค.

  • ์„œ๋น„์Šค์˜ ๋ชจ๋“  ์ •๋ ฌ ๊ด€๋ จ API์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

DESC

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

5 → 3 → 2 → 1

ASC

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

1 → 2 → 3 → 5

  • ๋žœ๋ค์˜ ๊ฒฝ์šฐ ์ •๋ ฌ ํƒ€์ž…์— ๋”ฐ๋ผ ์˜๋„์™€ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ•ด๋‹น ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ DESC(๋‚ด๋ฆผ์ฐจ์ˆœ) ์ž…๋‹ˆ๋‹ค.

  • ํƒ€์ž…์ด ์ž˜๋ชป ์ „๋‹ฌ๋  ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

REQUEST_USER_ID

BAD_REQUEST

์š”์ฒญํ•œ ์œ ์ € ID๊ฐ€ ๋ถ€์ ์ ˆํ•ฉ๋‹ˆ๋‹ค.

12.2. ์œ ์ €์˜ ๋ณ„์  ์กฐํšŒ

ํŠน์ •ํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ •ํ•œ ์œ„์Šคํ‚ค์— ๋Œ€ํ•ด์„œ ์ค€ ๋ณ„์ ์„ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

ํ•„์ˆ˜์ ์œผ๋กœ ํ† ํฐ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋“ฑ๋ก๋œ ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ 0.0์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  • ์œ ํšจํ•˜์ง€ ์•Š์€ ์œ„์Šคํ‚ค ์‹๋ณ„์ž์ผ ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. (์•„๋ž˜ ์˜ˆ์‹œ ๊ฒฝ๋กœ์— -1 ๋ฅผ ๋„ฃ์—ˆ์„ ๊ฒฝ์šฐ)

{
  "success": false,
  "code": 400,
  "data": [],
  "errors": {
    "message": "์œ„์Šคํ‚ค๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."
  }
}
  • ์œ ํšจํ•˜์ง€ ์•Š์€ ์‚ฌ์šฉ์ž ์‹๋ณ„์ž์ผ ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. (์•„๋ž˜ ์˜ˆ์‹œ ๊ฒฝ๋กœ์— -1 ๋ฅผ ๋„ฃ์—ˆ์„ ๊ฒฝ์šฐ)

{
  "success": false,
  "code": 400,
  "data": [],
  "errors": {
    "message": "์š”์ฒญํ•œ ์œ ์ € ID๊ฐ€ ๋ถ€์ ์ ˆํ•ฉ๋‹ˆ๋‹ค."
  }
}
GET /api/v1/rating/{{alcoholId}}

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

Table 8. /api/v1/rating/{alcoholId}
Parameter Description

alcoholId

๋ณ„์ ์„ ์กฐํšŒํ•  ์œ„์Šคํ‚ค์˜ ์‹๋ณ„์ž

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.rating

Number

๋“ฑ๋ก๋œ ๋ณ„์ 

data.alcoholId

Number

๋ณ„์ ์„ ์ค€ ์œ„์Šคํ‚ค์˜ ์‹๋ณ„์ž

data.userId

Number

๋ณ„์ ์„ ์ค€ ์œ ์ €์˜ ์‹๋ณ„์ž

{
  "success" : true,
  "code" : 200,
  "data" : {
    "rating" : 5.0,
    "alcoholId" : 1,
    "userId" : 3
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 552621752 ],
    "serverPathVersion" : "v1"
  }
}

12.3. ๋ณ„์  ๋“ฑ๋ก

๋ณ„์  ๋“ฑ๋ก์„ ์œ„ํ•œ API ์ž…๋‹ˆ๋‹ค.

๋ณ„์  ๋“ฑ๋ก ์‹œ Acsess Token์ด ํ•„์ˆ˜์ ์œผ๋กœ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

POST /api/v1/rating/register

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

path type optional description

alcoholId

Number

๋ณ„์ ์„ ์ค„ ์œ„์Šคํ‚ค์˜ ์‹๋ณ„์ž

rating

Number

๋ณ„์  ( 0.0 ~ 5.0 ์‚ฌ์ด์˜ ๊ฐ’)

{
  "alcoholId" : 1,
  "rating" : 5.0
}
  • ๋ณ„์ ์˜ ๊ฒฝ์šฐ 0.5 ๋‹จ์œ„์˜ ๊ฐ’๋งŒ ์š”์ฒญ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  • ๋ณ„์ ์˜ ๋ฒ”์œ„๋Š” 0.0 ~ 5.0 ์ž…๋‹ˆ๋‹ค.

  • 0.0์œผ๋กœ ์—…๋ฐ์ดํŠธ ์‹œ ์ดํ›„ ์กฐํšŒ ์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฐ’์€ null ๋ฐ˜ํ™˜๋œ๋‹ค.

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

data.rating

String

๋“ฑ๋ก๋œ ๋ณ„์ 

data.message

String

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "rating" : "5.0",
    "message" : "๋ณ„์  ๋“ฑ๋ก ์„ฑ๊ณต"
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 460293002 ],
    "serverPathVersion" : "v1"
  }
}

Error Code

  • ํ•ด๋‹น API ์š”์ฒญ ์‹œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ์™ธ๋ฅผ ์„ค๋ช… ํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ ์ƒํƒœ ์„ค๋ช…

ALCOHOL_ID_REQUIRED

BAD_REQUEST

์•Œ์ฝ”์˜ฌ ์‹๋ณ„์ž๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

RATING_REQUIRED

BAD_REQUEST

๋ณ„์ ์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

REQUIRED_USER_ID

BAD_REQUEST

์œ ์ € ์•„์ด๋””๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.

USER_NOT_FOUND

NOT_FOUND

์œ ์ €๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

ALCOHOL_NOT_FOUND

NOT_FOUND

๋ฆฌ๋ทฐ ๋Œ€์ƒ ์•Œ์ฝœ์ด ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

13. ํžˆ์Šคํ† ๋ฆฌ(user history) ๊ด€๋ จ API

13.1. ์œ ์ € ํžˆ์Šคํ† ๋ฆฌ ๋ชฉ๋ก ์กฐํšŒ

๊ฒ€์ƒ‰ ์กฐ๊ฑด์œผ๋กœ ์œ ์ €์˜ ํžˆ์Šคํ† ๋ฆฌ ์ •๋ณด๋ฅผ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

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

$ http GET 'https://api.bottle-note.com/api/v1/history/1?keyword=%EA%B8%80%EB%A0%8C%ED%94%BC%EB%94%95&ratingPoint=5&historyReviewFilterType=ALL&picksStatus=PICK&startDate=2026-04-01T13%3A53%3A10.092428781&endDate=2026-04-08T13%3A53%3A10.092482261&sortOrder=DESC&cursor=1&pageSize=3' \
    'Content-Type:application/json;charset=UTF-8'
Parameter Description

keyword

๊ฒ€์ƒ‰ ํ‚ค์›Œ๋“œ

ratingPoint

ํ‰์  ๊ธฐ์ค€์  (์˜ˆ: 3.0)

historyReviewFilterType

ํ•„ํ„ฐ๋ง ์œ ํ˜• (์˜ˆ: ALL, BEST_REVIEW, REVIEW_LIKE, REVIEW_REPLY)

picksStatus

ํ”ฝ(pick) ์ƒํƒœ (์˜ˆ: PICK, UNPICK ๋“ฑ)

startDate

ํžˆ์Šคํ† ๋ฆฌ ์กฐํšŒ ์‹œ์ž‘ ์ผ์ž (yyyy-MM-dd)

endDate

ํžˆ์Šคํ† ๋ฆฌ ์กฐํšŒ ์ข…๋ฃŒ ์ผ์ž (yyyy-MM-dd)

sortOrder

์ •๋ ฌ ์ˆœ์„œ (ASC ๋˜๋Š” DESC)

cursor

ํ˜„์žฌ ์ปค์„œ(ํŽ˜์ด์ง•์šฉ)

pageSize

ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋ชฉ๋ก (์—†์„ ๊ฒฝ์šฐ ๋นˆ ๋ฐฐ์—ด)

data.totalCount

Number

์ „์ฒด ํžˆ์Šคํ† ๋ฆฌ ๊ฐœ์ˆ˜

data.subscriptionDate

Array

(๊ตฌ๋… ๋˜๋Š” ๊ฐ€์ž… ๋“ฑ) ๊ด€๋ จ ์ผ์‹œ

data.userHistories[]

Array

ํžˆ์Šคํ† ๋ฆฌ ์ƒ์„ธ ๋ชฉ๋ก

data.userHistories[].historyId

Number

ํžˆ์Šคํ† ๋ฆฌ ID

data.userHistories[].createdAt

Array

ํžˆ์Šคํ† ๋ฆฌ ์ƒ์„ฑ ์‹œ๊ฐ(yyyy-MM-dd’T’HH:mm:ss)

data.userHistories[].eventCategory

String

์ด๋ฒคํŠธ ์นดํ…Œ๊ณ ๋ฆฌ

data.userHistories[].eventType

String

์ด๋ฒคํŠธ ํƒ€์ž…

data.userHistories[].alcoholId

Number

์ˆ  ID (์—†์„ ๊ฒฝ์šฐ null)

data.userHistories[].alcoholName

String

์ˆ  ์ด๋ฆ„

data.userHistories[].imageUrl

String

์ด๋ฏธ์ง€ URL

data.userHistories[].redirectUrl

String

๋ฆฌ๋‹ค์ด๋ ‰ํŠธ URL

data.userHistories[].content

Null

ํžˆ์Šคํ† ๋ฆฌ ์ปจํ…์ธ 

data.userHistories[].dynamicMessage

Object

๋™์ ์œผ๋กœ ๊ตฌ์„ฑ๋˜๋Š” ๋ฉ”์‹œ์ง€ ๋‚ด์šฉ(key-value)

data.userHistories[].dynamicMessage.currentValue

String

๋™์  ๋ฉ”์‹œ์ง€์˜ ํ˜„์žฌ ๊ฐ’

meta.pageable

Object

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

meta.pageable.currentCursor

Number

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

meta.pageable.cursor

Number

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

meta.pageable.pageSize

Number

์กฐํšŒ๋œ ํŽ˜์ด์ง€ ์‚ฌ์ด์ฆˆ

meta.pageable.hasNext

Boolean

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

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 5,
    "subscriptionDate" : [ 2026, 4, 8, 13, 53, 10, 90729614 ],
    "userHistories" : [ {
      "historyId" : 1,
      "createdAt" : [ 2026, 4, 8, 13, 53, 10, 90103914 ],
      "eventCategory" : "PICK",
      "eventType" : "IS_PICK",
      "alcoholId" : 1,
      "alcoholName" : "์†Œ์ฃผ",
      "imageUrl" : "imageUrl",
      "redirectUrl" : "redirectUrl",
      "content" : null,
      "dynamicMessage" : null
    }, {
      "historyId" : 1,
      "createdAt" : [ 2026, 4, 8, 13, 53, 10, 90684760 ],
      "eventCategory" : "RATING",
      "eventType" : "REVIEW_CREATE",
      "alcoholId" : 1,
      "alcoholName" : "์†Œ์ฃผ",
      "imageUrl" : "imageUrl",
      "redirectUrl" : "redirectUrl",
      "content" : null,
      "dynamicMessage" : {
        "currentValue" : "4.0"
      }
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 105653640 ],
    "pageable" : {
      "currentCursor" : 0,
      "cursor" : 4,
      "pageSize" : 3,
      "hasNext" : true
    },
    "serverPathVersion" : "v1"
  }
}
์ •๋ ฌ ๋ฐฉํ–ฅ (sortOrder)
  • ํ•ด๋‹น ์ •์˜๋Š” ์ •๋ ฌ ๋ฐฉํ–ฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ’์ž…๋‹ˆ๋‹ค.

  • ์„œ๋น„์Šค์˜ ๋ชจ๋“  ์ •๋ ฌ ๊ด€๋ จ API์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

DESC

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

5 → 3 → 2 → 1

ASC

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

1 → 2 → 3 → 5

  • ๋žœ๋ค์˜ ๊ฒฝ์šฐ ์ •๋ ฌ ํƒ€์ž…์— ๋”ฐ๋ผ ์˜๋„์™€ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ•ด๋‹น ๊ฐ’์ด ์—†์„ ๊ฒฝ์šฐ ๊ธฐ๋ณธ๊ฐ’์€ DESC(๋‚ด๋ฆผ์ฐจ์ˆœ) ์ž…๋‹ˆ๋‹ค.

  • ํƒ€์ž…์ด ์ž˜๋ชป ์ „๋‹ฌ๋  ๊ฒฝ์šฐ ์˜ˆ์™ธ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. === ์œ ์ € ์•Œ์ฝ”์˜ฌ ์กฐํšŒ ํžˆ์Šคํ† ๋ฆฌ ์กฐํšŒ ===

์‚ฌ์šฉ์ž๊ฐ€ ์กฐํšŒํ•œ ์•Œ์ฝ”์˜ฌ ๋ชฉ๋ก์„ ํžˆ์Šคํ† ๋ฆฌ ํ˜•ํƒœ๋กœ ์กฐํšŒํ•ฉ๋‹ˆ๋‹ค.

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

$ curl 'https://api.bottle-note.com/api/v1/history/view/alcohols' -i -X GET \
    -H 'Content-Type: application/json;charset=UTF-8'

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

path type description

success

Boolean

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

code

Number

์‘๋‹ต ์ฝ”๋“œ(http status code)

errors

Array

์‘๋‹ต ์„ฑ๊ณต ์—ฌ๋ถ€๊ฐ€ false์ผ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋ชฉ๋ก (์—†์„ ๊ฒฝ์šฐ ๋นˆ ๋ฐฐ์—ด)

data.totalCount

Number

์ „์ฒด ์กฐํšŒ ์•Œ์ฝ”์˜ฌ ๊ฐœ์ˆ˜

data.items[].alcoholId

Number

์•Œ์ฝ”์˜ฌ ID

data.items[].korName

String

์•Œ์ฝ”์˜ฌ ํ•œ๊ธ€ ์ด๋ฆ„

data.items[].engName

String

์•Œ์ฝ”์˜ฌ ์˜์–ด ์ด๋ฆ„

data.items[].rating

Number

ํ‰์ 

data.items[].ratingCount

Number

ํ‰์  ๊ฐœ์ˆ˜

data.items[].korCategory

String

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

data.items[].engCategory

String

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

data.items[].imageUrl

String

์•Œ์ฝ”์˜ฌ ์ด๋ฏธ์ง€ URL

data.items[].isPicked

Boolean

์‚ฌ์šฉ์ž ์ฐœ ์—ฌ๋ถ€

data.items[].popularScore

Number

์•Œ์ฝ”์˜ฌ ์ธ๊ธฐ๋„ ์ ์ˆ˜

{
  "success" : true,
  "code" : 200,
  "data" : {
    "totalCount" : 3,
    "items" : [ {
      "alcoholId" : 1,
      "korName" : "๊ธ€๋ Œํ”ผ๋”•",
      "engName" : "engName",
      "rating" : 1.0,
      "ratingCount" : 47,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.0
    }, {
      "alcoholId" : 2,
      "korName" : "๊ธ€๋ Œํ”ผ๋”•",
      "engName" : "engName",
      "rating" : 0.0,
      "ratingCount" : 64,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : true,
      "popularScore" : 0.0
    }, {
      "alcoholId" : 3,
      "korName" : "๊ธ€๋ Œํ”ผ๋”•",
      "engName" : "engName",
      "rating" : 0.5,
      "ratingCount" : 75,
      "korCategory" : "์‹ฑ๊ธ€ ๋ชฐํŠธ",
      "engCategory" : "single molt",
      "imageUrl" : "https://i.imgur.com/TE2nmYV.png",
      "isPicked" : false,
      "popularScore" : 0.0
    } ]
  },
  "errors" : [ ],
  "meta" : {
    "serverVersion" : "1.0.0",
    "serverEncoding" : "UTF-8",
    "serverResponseTime" : [ 2026, 4, 8, 22, 53, 10, 167668109 ],
    "serverPathVersion" : "v1"
  }
}