[Cloud Vision API] Detect Labels, Faces, and Landmarks in images with the Cloud Vision API

yejinยท2026๋…„ 4์›” 14์ผ

Google Skills

๋ชฉ๋ก ๋ณด๊ธฐ
3/46

Course

Analyze Images with the Cloud Vision API

Lab

๋ชฉ๋ก

  • APIs Explorer: Qwik Start
  • Extract, Analyze, and Translate Text from Images with the Cloud ML APIs
  • Detect Labels, Faces, and Landmarks in images with the Cloud Vision API โฌ…๏ธ ์˜ค๋Š˜ ํ•™์Šตํ•  Lab!
  • Analyze Images with the Cloud Vision API: Challenge Lab
  • Claim credential (๋ชจ๋“  ๊ฐ•์˜๋ฅผ ์ˆ˜๋ฃŒํ•ด์•ผ Skill badge ์ทจ๋“ ๊ฐ€๋Šฅ!โœจ)

๐ŸŒ Detect Labels, Faces, and Landmarks in images with the Cloud Vision APIs

๊ฐœ์š”

Cloud Vision API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€์—์„œ ๊ฐ์ฒด, ์–ผ๊ตด, ๋žœ๋“œ๋งˆํฌ๋ฅผ ๊ฐ์ง€ํ•ด๋ณด๊ธฐ

์‹ค์Šต์ž๋ฃŒ

  • ๋ผ๋ฒจ ์ธ์‹ ์ด๋ฏธ์ง€:
  • ์–ผ๊ตด ์ธ์‹ ์ด๋ฏธ์ง€:
  • ๋žœ๋“œ๋งˆํฌ ์ด๋ฏธ์ง€:

์‹ค์Šต๊ณผ์ •

(1) ๋กœ๊ทธ์ธ ํ›„ Cloud Shell ์—ด๊ธฐ



(2) API ํ‚ค ์ƒ์„ฑ


โžก๏ธ ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฉ”๋‰ด > APIs & Services > Credentials > API Key

Select API restrictions ์ค‘ ์„ ํƒํ•  API ํ•ญ๋ชฉ๋“ค

  • Cloud Vision API
  • Cloud Translation API
  • Cloud Natural Language API

โžก๏ธ ์ƒ์„ฑ ํ›„ API Key ๊ฐ’ ๋ณต์‚ฌํ•ด๋‘๊ธฐ

(3) ํ™˜๊ฒฝ๋ณ€์ˆ˜์— API ํ‚ค ๋“ฑ๋ก

#๋“ฑ๋ก
export API_KEY={API_KEY}
#ํ™•์ธ
echo $API_KEY

(4) Cloud Storage Bucket์— ์ด๋ฏธ์ง€ ๋“ฑ๋ก

์ด๋ฏธ์ง€ ๋“ฑ๋ก ๋ฐ ์ด๋ฏธ์ง€ ์ ‘๊ทผ ๊ถŒํ•œ์€ ์ด์ „ ํฌ์ŠคํŠธ ์ฐธ๊ณ !


(5) Request ์ƒ์„ฑ


โžก๏ธ Cloud Shell > Open Editor ๋ฒ„ํŠผ ํด๋ฆญ


โžก๏ธ request.json ํŒŒ์ผ ์ƒ์„ฑ ํ›„ ์•ˆ์— ๋‚ด์šฉ์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑ
โžก๏ธ Editor ๋‚ด์—์„œ ๋ณธ์ธ์˜ ํด๋”์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ฆฌ๋ฉด ํŒŒ์ผ ์ถ”๊ฐ€ ์•„์ด์ฝ˜์ด ๋‚˜ํƒ€๋‚œ๋‹ค.

{
  "requests": [
      {
        "image": {
          "source": {
              "gcsImageUri": "gs://PROJECT_ID-bucket/donuts.png" #๋ณธ์ธ์˜ Bucket์— ์—…๋กœ๋“œ๋œ ํŒŒ์ผ ์ฃผ์†Œ
          }
        },
        "features": [
          {
            "type": "LABEL_DETECTION",
            "maxResults": 10
          }
        ]
      }
  ]
}

(6) Gemini for Google Cloud API ์‚ฌ์šฉ ์„ค์ •

# Request
gcloud services enable cloudaicompanion.googleapis.com
# Response
Operation "operations/acat.p2-xxxx-xxx" finished successfully.


โžก๏ธ ํ™”๋ฉด ์ขŒ์ธก ํ•˜๋‹จ์˜ Cloud Code - ํ”„๋กœ์ ํŠธ ์—†์Œ > Select a Google Cloud project > Project ID ์„ ํƒํ•˜์—ฌ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์Šน์ธ
โžก๏ธ ์ƒํƒœ ํ‘œ์‹œ์ค„์˜ Cloud Code ์ƒํƒœ ๋ฉ”์‹œ์ง€์— Google Cloud ํ”„๋กœ์ ํŠธ(Project ID)๊ฐ€ ํ‘œ์‹œ๋˜๋ฉด ์™„๋ฃŒ!


(7) [Cloud Vision API] - ๋ผ๋ฒจ ์ธ์‹

curl -s -X POST -H "Content-Type: application/json" --data-binary @request.json  https://vision.googleapis.com/v1/images:annotate?key=${API_KEY} -o label_detection.json && cat label_detection.json

โžก๏ธ ํ„ฐ๋ฏธ๋„์—์„œ curl์„ ์‚ฌ์šฉํ•˜์—ฌ Cloud Vision API๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  label_detection.json ํŒŒ์ผ์— ์‘๋‹ต์„ ์ €์žฅ

{
  "responses": [
    {
      "labelAnnotations": [
        {
          "mid": "/m/01dk8s",
          "description": "Powdered sugar",
          "score": 0.9861496,
          "topicality": 0.9861496
        },
        {
          "mid": "/m/01wydv",
          "description": "Beignet",
          "score": 0.9565117,
          "topicality": 0.9565117
        },
        {
          "mid": "/m/02wbm",
          "description": "Food",
          "score": 0.9424965,
          "topicality": 0.9424965
        },
        {
          "mid": "/m/0hnyx",
          "description": "Pastry",
          "score": 0.8173416,
          "topicality": 0.8173416
        },
        {
          "mid": "/m/02q08p0",
          "description": "Dish",
          "score": 0.8076026,
          "topicality": 0.8076026
        },
        {
          "mid": "/m/01ykh",
          "description": "Cuisine",
          "score": 0.79036003,
          "topicality": 0.79036003
        },
        {
          "mid": "/m/03nsjgy",
          "description": "Kourabiedes",
          "score": 0.77726763,
          "topicality": 0.77726763
        },
        {
          "mid": "/m/06gd3r",
          "description": "Angel wings",
          "score": 0.73792106,
          "topicality": 0.73792106
        },
        {
          "mid": "/m/06x4c",
          "description": "Sugar",
          "score": 0.71921736,
          "topicality": 0.71921736
        },
        {
          "mid": "/m/01zl9v",
          "description": "Zeppole",
          "score": 0.7111677,
          "topicality": 0.7111677
        }
      ]
    }
  ]
}

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

  • description: ํ•ญ๋ชฉ์˜ ์ด๋ฆ„
  • score: ์„ค๋ช…๊ณผ ์ด๋ฏธ์ง€ ๋‚ด์šฉ์˜ ์ผ์น˜์— ๋Œ€ํ•œ ์‹ ๋ขฐ ์ˆ˜์ค€์„ 0~1 ์‚ฌ์ด์˜ ์ˆซ์ž๋กœ ๋‚˜ํƒ€๋ƒ„
  • mid: Google ์ง€์‹ ๊ทธ๋ž˜ํ”„์—์„œ ํ•ด๋‹น ํ•ญ๋ชฉ์˜ mid ๊ฐ’์— ๋งคํ•‘๋œ ๊ฐ’

๐Ÿ’ก ์ข…ํ•ฉ์ ์œผ๋กœ ์‘๋‹ต ๊ฒฐ๊ณผ๋ฅผ ํ•ด์„ํ–ˆ์„ ๋•Œ, API๊ฐ€ ์ด ๋„๋„›์ด ์Šˆ๊ฐ€ ํŒŒ์šฐ๋” ๋„๋„›์ด๋ผ๋Š” ๊ตฌ์ฒด์ ์ธ ์œ ํ˜•์„ ์‹๋ณ„!


(8) ๋ผ๋ฒจ ์ธ์‹ > Gemini Code Assist ์‚ฌ์šฉํ•˜์—ฌ ์‘๋‹ต ์„ค๋ช… ์š”์ฒญ


โžก๏ธ Gemini Code Assist: ์Šค๋งˆํŠธ ์ž‘์—… ์•„์ด์ฝ˜ ํด๋ฆญ > ํ”„๋กฌํ”„ํŠธ ๋‚ด์šฉ ์ž‘์„ฑ

You are a Machine Learning Engineer at Cymbal AI. A new team member needs help understanding this Cloud Vision API response. Explain the label_detection.json file in detail. Break down its key components and their function within the JSON code.

For the suggested improvements, don't make any changes to the file's content.

โžก๏ธ Gemini Code Assist: ์Šค๋งˆํŠธ ์ž‘์—… ์•„์ด์ฝ˜ ํด๋ฆญ > ํ”„๋กฌํ”„ํŠธ ๋‚ด์šฉ ์ž‘์„ฑ

โžก๏ธ label_detection.json ์ฝ”๋“œ์˜ Cloud Vision API ์‘๋‹ต์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์ด Gemini Code Assist ์ฑ„ํŒ…์— ํ‘œ์‹œ๋œ๋‹ค!


(9) [Cloud Vision API] - ์›น ๊ฐ์ง€ ์ˆ˜ํ–‰์„ ์œ„ํ•œ ์š”์ฒญ ํŒŒ์ผ ๋‚ด์šฉ ์ˆ˜์ •


โžก๏ธ request.json ํŒŒ์ผ ์„ ํƒ > Gemini Code Assist:์Šค๋งˆํŠธ ์ž‘์—… > ํ”„๋กฌํ”„ํŠธ ์ž…๋ ฅ ํ›„ Enter > Gemini Diff ๋ทฐ์— ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋˜๋ฉด ๋ชจ๋“  ๋ณ€๊ฒฝ์‚ฌํ•ญ ์ ์šฉ์„ ํด๋ฆญ

In the request.json file, update the features list, change type from LABEL_DETECTION to WEB_DETECTION.

{
  "requests": [
      {
        "image": {
          "source": {
              "gcsImageUri": "gs://PROJECT_ID-bucket/donuts.png"
          }
        },
        "features": [
          {
            "type": "WEB_DETECTION",
            "maxResults": 10
          }
        ]
      }
  ]
}

โžก๏ธ request.json ํŒŒ์ผ ๋‚ด์šฉ์ด ํ”„๋กฌํ”„ํŠธ์— ์ž…๋ ฅํ•œ ๋‚ด์šฉ ๋ฐ”ํƒ•์œผ๋กœ ์ˆ˜์ •๋œ๋‹ค.


(10) [Cloud Vision API] - ์›น ๊ฐ์ง€ ์ˆ˜ํ–‰

curl -s -X POST -H "Content-Type: application/json" --data-binary @request.json  https://vision.googleapis.com/v1/images:annotate?key=${API_KEY}

โžก๏ธ ํ„ฐ๋ฏธ๋„์—์„œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜์—ฌ Cloud Vision API ํ˜ธ์ถœํ•˜๊ณ , ์ด ์ด๋ฏธ์ง€๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํ•ญ๋ชฉ ์‚ดํŽด๋ณด๊ธฐ

{
  "responses": [
    {
      "webDetection": {
        "webEntities": [
          {
            "entityId": "/m/06_dn",
            "score": 1.1010823,
            "description": "Snow"
          },
          {
            "entityId": "/m/0csby",
            "score": 0.4279,
            "description": "Cloud"
          },
      	...
     "fullMatchingImages": [
          {
            "url": "https://cdn.qwiklabs.com/V4PmEUI7yXdKpytLNRqwV%2ByGHqym%2BfhdktVi8nj4pPs%3D"
          },
          {
            "url": "https://miro.medium.com/v2/resize:fit:1400/1*JSX2yNORAAOxdGoU17c4_A.png"
          }
        ],
        "pagesWithMatchingImages": [
          {
            "url": "https://www.youtube.com/watch?v=KzEFdedw-9o",
            "pageTitle": "Snow, and stuff about it you might not know - YouTube"
          },
          {
            "url": "https://www.youtube.com/watch?v=ubUlXd0VcTk",
            "pageTitle": "Backyard Science: What Is So Cool About Snow? - YouTube"
          },
     ...
    "visuallySimilarImages": [
          {
            "url": "https://images.nationalgeographic.org/image/upload/v1638889943/EducationHub/photos/beignets.jpg"
          },
          {
            "url": "https://i0.wp.com/www.middleeastmonitor.com/wp-content/uploads/2023/09/thumbnail_website-31.jpg?fit=1200%2C800&ssl=1"
          },
     ...

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

  • webEntities: ์ด ์ด๋ฏธ์ง€๋Š” Cloud ML API์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ ํ”„๋ ˆ์  ํ…Œ์ด์…˜์—์„œ ์‚ฌ์šฉ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— API์—์„œ "๋จธ์‹  ๋Ÿฌ๋‹"๊ณผ "Google Cloud Platform" ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ฐพ์•˜๋‹ค.
  • fullMatchingImages, partialMatchingImages, pagesWithMatchingImages ๋ถ€๋ถ„์˜ URL์„ ์‚ดํŽด๋ณด๋ฉด ๋งŽ์€ URL์ด ์ด ๋žฉ ์‚ฌ์ดํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.
  • visuallySimilarImages: ์™„์ „ํžˆ ๋˜‘๊ฐ™์€ ์ด๋ฏธ์ง€๊ฐ€ ์•„๋‹Œ ๋‹ค๋ฅธ ์ด๋ฏธ์ง€๋ฅผ ์ฐพ๊ณ  ์‹ถ์„ ๋•Œ ์ฐธ๊ณ ํ•˜๋ฉด ๋œ๋‹ค.

(11) [Cloud Vision API] - ์–ผ๊ตด ์ธ์‹ ์ˆ˜ํ–‰์„ ์œ„ํ•œ ์ค€๋น„ ๋‹จ๊ณ„

1) Cloud Storage > Bucket > ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๋ฐ ์ ‘๊ทผ ๊ถŒํ•œ ์„ค์ •

2) ์š”์ฒญ ํŒŒ์ผ ์—…๋ฐ์ดํŠธ

Update the JSON file request.json to achieve three specific changes:

* Update the gcsImageUri value from donuts.png to selfie.png.
* Replace the existing features array with two new feature types: FACE_DETECTION and LANDMARK_DETECTION.
* Don't want maxResults result.

โžก๏ธ request.json > ํ”„๋กฌํ”„ํŠธ ๋ฉ”์‹œ์ง€ ์ž…๋ ฅ > Gemini Diff ๋ทฐ์— ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋˜๋ฉด ๋ชจ๋“  ๋ณ€๊ฒฝ์‚ฌํ•ญ ์ ์šฉ์„ ํด๋ฆญ


(12) [Cloud Vision API] - ์–ผ๊ตด ์ธ์‹ ์ˆ˜ํ–‰

curl -s -X POST -H "Content-Type: application/json" --data-binary @request.json  https://vision.googleapis.com/v1/images:annotate?key=${API_KEY}

โžก๏ธ ํ„ฐ๋ฏธ๋„์—์„œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜์—ฌ Cloud Vision API ํ˜ธ์ถœํ•˜๊ณ , ์ด ์ด๋ฏธ์ง€๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํ•ญ๋ชฉ ์‚ดํŽด๋ณด๊ธฐ

{
      "faceAnnotations": [
        {
          "boundingPoly": {
            "vertices": [
              {
                "x": 669,
                "y": 324
              },
              ...
            ]
          },
          "fdBoundingPoly": {
            ...
          },
          "landmarks": [
            {
              "type": "LEFT_EYE",
              "position": {
                "x": 692.05646,
                "y": 372.95868,
                "z": -0.00025268539
              }
            },
            ...
          ],
          "rollAngle": 0.21619819,
          "panAngle": -23.027969,
          "tiltAngle": -1.5531756,
          "detectionConfidence": 0.72354823,
          "landmarkingConfidence": 0.20047489,
          "joyLikelihood": "LIKELY",
          "sorrowLikelihood": "VERY_UNLIKELY",
          "angerLikelihood": "VERY_UNLIKELY",
          "surpriseLikelihood": "VERY_UNLIKELY",
          "underExposedLikelihood": "VERY_UNLIKELY",
          "blurredLikelihood": "VERY_UNLIKELY",
          "headwearLikelihood": "VERY_LIKELY"
        }
        ...
     }
}

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

  • boundingPoly:์–ผ๊ตด ์ด๋ฏธ์ง€์˜ ์ฃผ๋ณ€ x, y ์ขŒํ‘œ ์ œ๊ณต
  • fdBoundingPoly: boundingPoly๋ณด๋‹ค ์ž‘์€ ์ƒ์ž๋กœ, ์–ผ๊ตด์˜ ํ”ผ๋ถ€ ๋ถ€๋ถ„์— ์ง‘์ค‘
  • landmarks: ์–ผ๊ตด์˜ ๊ฐ ํŠน์ง•์— ๋Œ€ํ•œ ๊ฐ์ฒด์˜ ๋ฐฐ์—ด

(13) [Cloud Vision API] - ๋žœ๋“œ๋งˆํฌ ์ฃผ์„ ์ˆ˜ํ–‰์„ ์œ„ํ•œ ์ค€๋น„ ๋‹จ๊ณ„

1) Cloud Storage > Bucket > ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๋ฐ ์ ‘๊ทผ ๊ถŒํ•œ ์„ค์ •

2) request.json > ์š”์ฒญ ํŒŒ์ผ ๋‚ด์šฉ ์—…๋ฐ์ดํŠธ

{
  "requests": [
      {
        "image": {
          "source": {
              "gcsImageUri": "gs://PROJECT_ID-bucket/city.png"
          }
        },
        "features": [
          {
            "type": "LANDMARK_DETECTION",
            "maxResults": 10
          }
        ]
      }
  ]
}

(14) [Cloud Vision API] - ๋žœ๋“œ๋งˆํฌ ์ฃผ์„ ์ˆ˜ํ–‰

curl -s -X POST -H "Content-Type: application/json" --data-binary @request.json  https://vision.googleapis.com/v1/images:annotate?key=${API_KEY}

โžก๏ธ ํ„ฐ๋ฏธ๋„์—์„œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜์—ฌ Cloud Vision API ํ˜ธ์ถœํ•˜๊ณ , ์ด ์ด๋ฏธ์ง€๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํ•ญ๋ชฉ ์‚ดํŽด๋ณด๊ธฐ

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

  • mid: ๋žœ๋“œ๋งˆํฌ์˜ mid ๊ฐ’
  • description: ๋žœ๋“œ๋งˆํฌ ์ด๋ฆ„
  • score: ์‹ ๋ขฐ๋„ ์ ์ˆ˜
  • boundingPoly: ์ด๋ฏธ์ง€์—์„œ ๋žœ๋“œ๋งˆํฌ๊ฐ€ ์‹๋ณ„๋œ ์˜์—ญ
  • locations : ์‚ฌ์ง„์˜ ์œ„๋„ ๋ฐ ๊ฒฝ๋„ ์ขŒํ‘œ๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ํ‚ค

๐Ÿ’กAPI ์‘๋‹ต ๊ฒฐ๊ณผ๋ฅผ ๋ถ„์„ํ•œ ๊ฒฐ๊ณผ, ์‚ฌ์ง„์ด ์ดฌ์˜๋œ ์žฅ์†Œ๋ฅผ ์‹๋ณ„ํ•˜๊ณ  ํ•ด๋‹น ์œ„์น˜์˜ ์ง€๋„ ์ขŒํ‘œ(๋Ÿฌ์‹œ์•„ ๋ชจ์Šคํฌ๋ฐ” ๋ถ‰์€ ๊ด‘์žฅ์˜ ์„ฑ ๋ฐ”์‹ค๋ฆฌ ์„ฑ๋‹น)๋ฅผ ์ œ๊ณตํ•จ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.


(15) [Cloud Vision API] - ๊ฐ์ฒด ํ˜„์ง€ํ™” ์ˆ˜ํ–‰์„ ์œ„ํ•œ ์ค€๋น„ ๋‹จ๊ณ„


โžก๏ธ request.json > ์š”์ฒญ ํŒŒ์ผ ๋‚ด์šฉ ์—…๋ฐ์ดํŠธ

{
  "requests": [
    {
      "image": {
        "source": {
          "imageUri": "https://cloud.google.com/vision/docs/images/bicycle_example.png"
        }
      },
      "features": [
        {
          "maxResults": 10,
          "type": "OBJECT_LOCALIZATION"
        }
      ]
    }
  ]
}

(16) [Cloud Vision API] - ๊ฐ์ฒด ํ˜„์ง€ํ™” ์ˆ˜ํ–‰

curl -s -X POST -H "Content-Type: application/json" --data-binary @request.json  https://vision.googleapis.com/v1/images:annotate?key=${API_KEY}

โžก๏ธ ํ„ฐ๋ฏธ๋„์—์„œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜์—ฌ Cloud Vision API ํ˜ธ์ถœํ•˜๊ณ , ์ด ์ด๋ฏธ์ง€๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ํ•ญ๋ชฉ ์‚ดํŽด๋ณด๊ธฐ

{
  "responses": [
    {
      "localizedObjectAnnotations": [
        {
          "mid": "/m/01bqk0",
          "name": "Bicycle wheel",
          "score": 0.89648587,
          "boundingPoly": {
            "normalizedVertices": [
              {
                "x": 0.32076266,
                "y": 0.78941387
              },
              {
                "x": 0.43812272,
                "y": 0.78941387
              },
              {
                "x": 0.43812272,
                "y": 0.97331065
              },
              {
                "x": 0.32076266,
                "y": 0.97331065
              }
            ]
          }
        },
        {
          "mid": "/m/0199g",
          "name": "Bicycle",
          "score": 0.886761,
          "boundingPoly": {
            "normalizedVertices": [
              {
                "x": 0.312,
                "y": 0.6616471
              },
              {
                "x": 0.638353,
                "y": 0.6616471
              },
              {
                "x": 0.638353,
                "y": 0.9705882
              },
              {
                "x": 0.312,
                "y": 0.9705882
              }
            ]
          }
        },
...

์‘๋‹ต ๊ฒฐ๊ณผ ๋ถ„์„๐Ÿ’ก

Vision API๊ฐ€ ์ด ์‚ฌ์ง„์—์„œ ์ž์ „๊ฑฐ์™€ ์ž์ „๊ฑฐ ๋ฐ”ํ€ด๋ฅผ ์‹๋ณ„ํ–ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค!

profile
์ƒˆ์‹น ๊ฐœ๋ฐœ์ž

0๊ฐœ์˜ ๋Œ“๊ธ€