Axios: axios.post ๋ฉ”์†Œ๋“œ์— ํ—ค๋” ์ถ”๊ฐ€ํ•˜๊ธฐ

์— ๋งŒ๋“  2017๋…„ 04์›” 24์ผ  ยท  17์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: axios/axios

์•ˆ๋…•,

๋„๋ฉ”์ธ ๊ฐ„ IP์— ๋Œ€ํ•œ ๊ฒŒ์‹œ ์š”์ฒญ์„ ์‹œ๋„ํ–ˆ๋Š”๋ฐ ๋‚ด ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  var authOptions = {
    method: 'POST',
    url: 'http://10.254.147.184:7777/auth/oauth/token',
    data: qs.stringify(data),
    headers: {
        'Authorization': 'Basic Y2xpZW50OnNlY3JldA==',
        'Content-Type': 'application/x-www-form-urlencoded'
    },
    json: true
  };
  return dispatch => {
    return axios(authOptions)
    .then(function(response){
      console.log(response.data);
      console.log(response.status);
    })
    .catch(function(error){
      console.log(error);
    });

๊ทธ๋Ÿฌ๋‚˜ ' headers '๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ๋งˆ๋‹ค ๋‚ด ์š”์ฒญ์€ 'POST' ๋ฉ”์„œ๋“œ์—์„œ 'OPTIONS'๋กœ ์ž๋™ ๋ฐ”๋€Œ๋Š”๋ฐ ์ด์œ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์— ๋Œ€ํ•œ ๋ฒ„๊ทธ๋‚˜ ๋‚ด๊ฐ€ ์ฐพ์ง€ ๋ชปํ•œ ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

ํŽธ์ง‘: ๋‚ด CORS ํ•„ํ„ฐ์—์„œ ํ—ˆ์šฉ๋œ ํ—ค๋”์— ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.


@jffernandez

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. Auth ํ—ค๋”๋ฅผ ์ƒ๋žตํ•˜๋ฉด POST, OPTIONS๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” Options ์š”์ฒญ์„ ๋ฐ›์€ ๋‹ค์Œ Authorization ํ—ค๋”(์˜ˆ์ƒ)๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— 403์„ ๋ฐ˜ํ™˜ํ•˜๋Š” POST๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.

ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์˜ต์…˜ ์š”์ฒญ๋งŒ ๋ฐ›๊ณ  POST๋ฅผ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

post("http://localhost:8080/foo", foo)

๋Œ€

post("http://localhost:8080/foo", foo, {
    headers: { Authorization: "Bearer " + token }
})

๋ชจ๋“  17 ๋Œ“๊ธ€

์ด๊ฒƒ์€ ๋ฒ„๊ทธ๊ฐ€ ์•„๋‹ˆ๋ฉฐ ์˜ˆ์ƒ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
ํ—ค๋”์™€ ์ฝ˜ํ…์ธ  ์œ ํ˜•์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS ๋ฌธ์„œ์— ๋ช…์‹œ๋œ ๋Œ€๋กœ ํ”„๋ฆฌํ”Œ๋ผ์ดํŠธ ์š”์ฒญ(๋‹จ์ˆœํ•œ ์š”์ฒญ์ด ์•„๋‹˜)์„ ์ƒ์„ฑํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.
๋”ฐ๋ผ์„œ ์ด ๋ชจ๋“œ์—์„œ๋Š” ๊ธฐ๋ณธ ์š”์ฒญ๋ณด๋‹ค OPTIONS ์š”์ฒญ์ด ๋จผ์ € ์‹คํ–‰๋˜๋ฏ€๋กœ ์„œ๋ฒ„๊ฐ€ OPTIONS ์š”์ฒญ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํŽธ์ง‘: ๋‚ด CORS ํ•„ํ„ฐ์—์„œ ํ—ˆ์šฉ๋œ ํ—ค๋”์— ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.


@jffernandez

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. Auth ํ—ค๋”๋ฅผ ์ƒ๋žตํ•˜๋ฉด POST, OPTIONS๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” Options ์š”์ฒญ์„ ๋ฐ›์€ ๋‹ค์Œ Authorization ํ—ค๋”(์˜ˆ์ƒ)๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— 403์„ ๋ฐ˜ํ™˜ํ•˜๋Š” POST๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.

ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์˜ต์…˜ ์š”์ฒญ๋งŒ ๋ฐ›๊ณ  POST๋ฅผ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

post("http://localhost:8080/foo", foo)

๋Œ€

post("http://localhost:8080/foo", foo, {
    headers: { Authorization: "Bearer " + token }
})

axios๊ฐ€ ์•„๋‹Œ CORS ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. ์ œ๊ณต๋œ ๋งํฌ @jffernandez ๋ฅผ ์‚ดํŽด๋ณด๊ฑฐ๋‚˜ ์—ฌ๊ธฐ์—์„œ ์œ ์‚ฌํ•œ ๋ฌธ์ œ๋ฅผ ์ฐพ์œผ์‹ญ์‹œ์˜ค.

๋„ค, CORS์— ๊ด€ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜์™€ ๊ฐ™์€ ๊ฒฝ์šฐ API ์„œ๋ฒ„์—์„œ ์ธ์ฆ๋œ Content-Type์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์—ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

AllowedHeaders : Content-Type ๋ฐ X-Requested-With
๊ทธ๋ฆฌ๊ณ  ๊ท€ํ•˜์˜ ๊ฒฝ์šฐ ์Šน์ธ.

๋ฌผ๋ก  OPTIONS ๋ฉ”์„œ๋“œ๋„ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

axios({ method: 'POST', url: 'you http api here', headers: {autorizacion: localStorage.token}, data: { user: 'name' } })

๋˜๋Š” ์ด CORS ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ๋…ธ๋“œ์— corsproxy ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ต์ฐจ ์ถœ์ฒ˜ ์˜ค๋ฅ˜์— ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜ ๋งํฌ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

https://github.com/gr2m/CORS-ํ”„๋ก์‹œ

````
๋กœ๊ทธ์ธ = () => {
console.log('๋กœ๊ทธ์ธ ํด๋ฆญ')
๋ฐ์ดํ„ฐ = JSON.stringify({
๋น„๋ฐ€๋ฒˆํ˜ธ: this.state.password,
์‚ฌ์šฉ์ž ์ด๋ฆ„: this.state.email
})

axios.post('url', data, {
    headers: {
        'Content-Type': 'application/json',
    }
}
)

}
```

์ด ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ•ด๊ฒฐ

   axios.post('http://localhost/M-Experience/resources/GETrends.php',
      {
        firstName: this.name
      },
      {
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
      });

์ด๊ฒƒ์ด ๋‚ด๊ฐ€ POST ์š”์ฒญ์„ ํฌ๋งทํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

    var postData = {
      email: "[email protected]",
      password: "password"
    };

    let axiosConfig = {
      headers: {
          'Content-Type': 'application/json;charset=UTF-8',
          "Access-Control-Allow-Origin": "*",
      }
    };

    axios.post('http://<host>:<port>/<path>', postData, axiosConfig)
    .then((res) => {
      console.log("RESPONSE RECEIVED: ", res);
    })
    .catch((err) => {
      console.log("AXIOS ERROR: ", err);
    })

cors ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ์ด ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. npm i --save cors ๋‹ค์Œ app.js ๊ฐ€์ ธ์˜ค๊ธฐ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

var cors = require('cors');
๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‚ด ๊ฒฝ์šฐ์—๋Š” ๋™์ผํ•œ ํŒŒ์ผ์—์„œ ์ด์™€ ๊ฐ™์ด ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๋ฃจํŠธ ํŒŒ์ผ์€ app.js์ž…๋‹ˆ๋‹ค.
app.use(cors());

๊ทธ๊ฒƒ์€ ๋‹น์‹ ์˜ cors ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค

@mirzaumersaleem ๋‚˜๋Š” cors๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์žˆ์ง€๋งŒ axios๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฑ์—”๋“œ์— ๊ฒŒ์‹œํ•˜๋ ค๊ณ  ํ•˜๋Š”๋ฐ 400 Bad ์š”์ฒญ์„ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

fetch๋Š” cors๋กœ ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ(๋ฐฑ์—”๋“œ์—๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์Œ), axios์—์„œ๋Š” ๋•Œ๋•Œ๋กœ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.

cors ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ์ด ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. npm i --save cors ๋‹ค์Œ app.js ๊ฐ€์ ธ์˜ค๊ธฐ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

var cors = require('cors');
๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‚ด ๊ฒฝ์šฐ์—๋Š” ๋™์ผํ•œ ํŒŒ์ผ์—์„œ ์ด์™€ ๊ฐ™์ด ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๋ฃจํŠธ ํŒŒ์ผ์€ app.js์ž…๋‹ˆ๋‹ค.
app.use(cors());

๊ทธ๊ฒƒ์€ ๋‹น์‹ ์˜ cors ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค

๋‚ด ์—ฌํ–‰์—์„œ CORS๋Š” ์„œ๋ฒ„(.net /java/node/php ๋“ฑ)์—์„œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํŽธ์ง‘: ๋‚ด CORS ํ•„ํ„ฐ์—์„œ ํ—ˆ์šฉ๋œ ํ—ค๋”์— ๊ถŒํ•œ ๋ถ€์—ฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

@jffernandez

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. Auth ํ—ค๋”๋ฅผ ์ƒ๋žตํ•˜๋ฉด POST, OPTIONS๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” Options ์š”์ฒญ์„ ๋ฐ›์€ ๋‹ค์Œ Authorization ํ—ค๋”(์˜ˆ์ƒ)๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— 403์„ ๋ฐ˜ํ™˜ํ•˜๋Š” POST๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.

ํ—ค๋”๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์˜ต์…˜ ์š”์ฒญ๋งŒ ๋ฐ›๊ณ  POST๋ฅผ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

post("http://localhost:8080/foo", foo)

๋Œ€

post("http://localhost:8080/foo", foo, {
    headers: { Authorization: "Bearer " + token }
})

๋น ๋ฅธ ๋Œ€๋‹ต์€ url ๋’ค์˜ ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜์™€ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๊ฐ€ ์ข…์ข… ์ž˜๋ชป ๋ฐฐ์น˜๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(์ฆ‰, axios(url, data, config)). ๋”ฐ๋ผ์„œ ๊ตฌ์„ฑ ๋ถ€๋ถ„์„ ์ƒ๋žตํ•˜๊ฑฐ๋‚˜ ๋ฐ์ดํ„ฐ์™€ ๊ตฌ์„ฑ์„ ์ „ํ™˜ํ•˜๋ฉด ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ localhost๋กœ ์ž‘์—…ํ•˜๋Š” ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ „ํ˜€ ๋ฌธ์ œ์—†์ด.

์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ€๋…์„ฑ์ด ์ข‹์ง€ ์•Š๋‹ค.

axios.request(๊ตฌ์„ฑ)
axios.get(url[, ๊ตฌ์„ฑ])
axios.delete(url[, ๊ตฌ์„ฑ])
axios.head(url[, ๊ตฌ์„ฑ])
axios.options(url[, ๊ตฌ์„ฑ])
axios.post(url[, ๋ฐ์ดํ„ฐ[, ๊ตฌ์„ฑ]])
axios.put(url[, ๋ฐ์ดํ„ฐ[, ๊ตฌ์„ฑ]])
axios.patch(url[, ๋ฐ์ดํ„ฐ[, ๊ตฌ์„ฑ]])

๋ชจ๋“  API๊ฐ€ ์ผ๊ด€์ ์ด๋ฉฐ
1) URL์„ ์ฒซ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ,
2) ๋‘ ๋ฒˆ์งธ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๊ตฌ์„ฑ(์„ ํƒ ์‚ฌํ•ญ),
3) ๋ฐ์ดํ„ฐ(์„ ํƒ์‚ฌํ•ญ)

๊ทธ๊ฒƒ์ด ์‚ฌ์šฉ์ž๋“ค์ด ๊ธฐ๋Œ€ํ•˜๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  axios๋Š” ๊ทธ ์ž‘์€ API ๊ฒฐ์ •์—์„œ ํฐ ๋ฌธ์ œ๋ฅผ ๋งŒ๋“ค์–ด ๊ฑฐ์˜ ๋ชจ๋“  ์‚ฌ๋žŒ๋“ค์ด ์ผ์ƒ์— ํ•œ ๋ฒˆ ์ด์ƒ ๊ฑฐ๊ธฐ์— ๊ฐ‡ํžˆ๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ•˜์‹ญ์‹œ์˜ค :

`
const ํ—ค๋” = {
'์ฝ˜ํ…์ธ  ์œ ํ˜•': '์‘์šฉ ํ”„๋กœ๊ทธ๋žจ/json',
'๊ถŒํ•œ ๋ถ€์—ฌ': 'JWT ํŽ˜ํŽ˜๊ฒŒ...'
}

axios.post(Helper.getUserAPI(), ๋ฐ์ดํ„ฐ, {
ํ—ค๋”: ํ—ค๋”
})
.then((์‘๋‹ต) => {
๋ณด๋‚ด๋‹ค({
์œ ํ˜•: FOUND_USER,
๋ฐ์ดํ„ฐ: ์‘๋‹ต.๋ฐ์ดํ„ฐ[0]
})
})
.catch((์˜ค๋ฅ˜) => {
๋ณด๋‚ด๋‹ค({
์œ ํ˜•: ERROR_FINDING_USER
})
})
`

์—ฌ๊ธฐ์—์„œ jquery๋กœ ๋™์ผํ•œ ๋ฌธ์ œ์— ์ง๋ฉดํ•˜๋ฉด ์š”์ฒญ์€ ์„ฑ๊ณตํ•˜์ง€๋งŒ axios๊ฐ€ ์žˆ๋Š” req๋ฅผ ๋ณด๋‚ผ ๋•Œ cors ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
๋‚ด ๋ถ€ํƒ--

      .post('https://test.pi.com/j_spring_security_check', {

        withCredentials: true,
        crossorigin: true,
        headers: {
          common:{
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'WithCredentials': true,
            'Access-Control-Allow-Origin': '*'
        }
      },
        data: JSON.stringify({
          j_username: email,
          j_password: password
        }),

        // proxy: {
        //   '/j_spring_security_check/*': 'https://devtest.pvai.com/j_spring_security_check',
        // }
      })

์ด๋“ค์€ ์„œ๋ฒ„์˜ ์‘๋‹ต ํ—ค๋”์ด๋ฉฐ ๋‚ด locahost ์ถœ์ฒ˜๊ฐ€ ํ—ˆ์šฉ๋˜๋ฉฐ ๋‚ด๊ฐ€ ๋ณด๋‚ด๋Š” ํ—ค๋”์™€ ๋ฉ”์†Œ๋“œ๋„ ํ—ˆ์šฉ๋ฉ๋‹ˆ๋‹ค.

access-control-allow-credentials: true
access-control-allow-headers: Authorization, X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept
access-control-allow-methods: POST, GET, OPTIONS
access-control-allow-origin: http://localhost:5000
access-control-expose-headers: Authorization
cache-control: no-cache, no-store, max-age=0, must-revalidate
content-length: 0
date: Wed, 11 Dec 2019 04:53:25 GMT
expires: 0
location: /authFailure
pragma: no-cache
status: 302
strict-transport-security: max-age=31536000 ; includeSubDomains
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block

์ด๊ฒƒ์ด ๋‚ด๊ฐ€ POST ์š”์ฒญ์„ ํฌ๋งทํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

    var postData = {
      email: "[email protected]",
      password: "password"
    };

    let axiosConfig = {
      headers: {
          'Content-Type': 'application/json;charset=UTF-8',
          "Access-Control-Allow-Origin": "*",
      }
    };

    axios.post('http://<host>:<port>/<path>', postData, axiosConfig)
    .then((res) => {
      console.log("RESPONSE RECEIVED: ", res);
    })
    .catch((err) => {
      console.log("AXIOS ERROR: ", err);
    })

๋•๋ถ„์— ํ•˜๋ฃจ๋ฅผ ๊ตฌํ–ˆ์Šต๋‹ˆ๋‹ค! ๋‚˜๋ฅผ ์œ„ํ•ด ์ผํ–ˆ๋‹ค

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰