๐Ÿšจ Axios Network Error ์˜ค๋ฅ˜ ํ•ด๊ฒฐ ์‚ฝ์งˆ๊ธฐ... ๐Ÿšจ

ํ˜œํ˜œยท2023๋…„ 11์›” 25์ผ
5

Error Note

๋ชฉ๋ก ๋ณด๊ธฐ
10/19
post-custom-banner

๐ŸŽฏ ๊ฐœ์š”

๋น„๊ต์  ์ˆœ์กฐ๋กญ...๊ฒŒ ํ”„๋กœ์ ํŠธ ์ฝ”๋”ฉ์„ ํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ํ™”์š”์ผ์— ๋งˆ์น˜ ์ž๋งŒํ•˜์ง€ ๋ง๋ผ๋Š”๋“ฏ์ด Axios network error๊ฐ€ ๋‚˜ํƒ€๋‚ฌ๋‹ค. ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ๋•Œ์˜€๋‹ค. ์šฐ๋ฆฌ ๋กœ์ง์€ ํ”„๋ก ํŠธ ์ชฝ์—์„œ ํŒŒ์ผ๋ช…์„ ์„œ๋ฒ„์— ๋ณด๋‚ด์ฃผ๋ฉด, ์„œ๋ฒ„๊ฐ€ S3์— pre-signed url์„ ์š”์ฒญํ•˜๊ณ , ๊ฑฐ๊ธฐ์„œ ๋ฐ›์•„์˜จ pre-signed url์„ ๋‹ค์‹œ ํ”„๋ก ํŠธ์— ๋ฐ˜ํ™˜ํ•ด์ฃผ์–ด์„œ ํ”„๋ก ํŠธ๊ฐ€ ๊ทธ url์— ๋ฐ”๋กœ ์ด๋ฏธ์ง€ put ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๋กœ์ง์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ pre-signed url์„ ๋ฐ›์•„์˜ค๋Š” ๊ฒƒ๊นŒ์ง€๋Š” ์ž˜ํ–ˆ๋Š”๋ฐ ํ”„๋ก ํŠธ ์ชฝ์—์„œ ๊ทธ url์— put ์š”์ฒญ์„ ๋ณด๋‚ด๋ ค๊ณ  ํ•˜๋‹ˆ๊นŒ ์ด๋Ÿฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค. ์‹ญ์ˆ˜๊ฐ€์ง€ ์ •๋„ ๋ฐฉ๋ฒ•์„ ์‹œ๋„ํ•ด ๋ดค๋Š”๋ฐ ํ•ด๊ฒฐ์ด ์•ˆ ๋˜์–ด์„œ ๋ธ”๋กœ๊ทธ์— ์˜ค๋ฅ˜ ํ•ด๊ฒฐ ์‚ฝ์งˆ๊ธฐ๋ผ๋„ ์ •๋ฆฌํ•ด ๋ณด๋ ค๊ณ  ํ•œ๋‹ค:) ์‰ฝ๊ฒŒ๋งŒ ์‚ด์•„๊ฐ€๋ฉด ์žฌ๋ฏธ์—†์–ด ๋น™๊ณ  ใ…‹

๐ŸŽฏ ๊ธฐ์กด ๋กœ์ง

axios.put(res.data.preSignedUrl, photo)
  .then((res) => {
  console.log(res);
}).catch((err) => {
  console.error(err);
})

๋งจ ์ฒ˜์Œ์— ์ž‘์„ฑํ–ˆ๋˜ ์ฝ”๋“œ๋Š” ์ด๊ฑฐ์˜€๋‹ค. ๋ ˆํผ ์—ฌ๋Ÿฌ ๊ฐœ ์ฐพ์•„๋ดค๋Š”๋ฐ ๋‹ค๋“ค ์ฝ”๋“œ๊ฐ€ ๋น„์Šท๋น„์Šทํ•˜๊ณ  ์–ด๋ ค์šธ ๊ฑฐ ์—†๋Š” ์ฝ”๋“œ๋ผ ์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ–ˆ๋Š”๋ฐ ์˜ค๋ฅ˜๊ฐ€ ๋‚  ์ค„์€...

pre-signed url์€ ์ฝ˜์†”์— ์ฐ์–ด ๋ณด๋ฉด ์ด๋Ÿฐ ์‹์œผ๋กœ ์ž˜ ๋œฌ๋‹ค.

photo ํŒŒ์ผ ๋ณ€์ˆ˜๋„ ์ฝ˜์†”์— ์ฐ์–ด๋ณด๋ฉด ์ด๋Ÿฐ ์‹์œผ๋กœ... ์ž˜ ๋œฌ๋‹ค.

๊ทผ๋ฐ ์š”์ฒญ์„ ๋ณด๋‚ด๋ณด๋ฉด axios network error๊ฐ€ ๋œฌ๋‹คใ…Žใ…Ž ์ด๋ฏธ ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์„ ์‹œ๋„ํ•ด ๋ณด์•˜๊ณ  ๋‹ค ์„ฑ๊ณตํ•˜์ง€ ๋ชป ํ–ˆ์ง€๋งŒ ๋ธ”๋กœ๊ทธ์— ์ •๋ฆฌํ•˜๋Š” ๊น€์— 1๋ถ€ํ„ฐ ๋‹ค์‹œ ์‹œ๋„ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค...

๐Ÿ’ก ๋ฐฉ๋ฒ• 1 : Content-type ์ง€์ •

์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ์š”์ฒญ์˜ ํ—ค๋”๋ฅผ ๋ณด๋ฉด Content-Type์ด application/x-www-form-urlencoded๋กœ ๋˜์–ด ์žˆ๋‹ค. Content-Type์€ ๋ณด๋‚ด๋Š” ์ž์›์˜ ํƒ€์ž…์„ ๋ช…์‹œํ•˜๋Š” ๋ถ€๋ถ„์ธ๋ฐ, ๋‚ด ํŒŒ์ผ์˜ ํƒ€์ž…์€ image/png์ธ๋ฐ ์ด ํƒ€์ž…์„ ๋”ฐ๋กœ ๋ช…์‹œํ•ด์ฃผ์ง€ ์•Š์•„ application/x-www-form-unlencoded๋กœ ๋ณด๋‚ด์ ธ์„œ ์ƒ๊ธฐ๋Š” ์˜ค๋ฅ˜์ธ๊ฐ€ ์‹ถ์—ˆ๋‹ค. (๋ฌผ๋ก  ํ™•์‹คํ•˜์ง€ ์•Š๋‹ค...)

axios.put(res.data.preSignedUrl, photo, {
  headers: {
    "Content-Type": photo.type
  }
})
  .then((res) => {
  console.log(res);
}).catch((err) => {
  console.error(err);
})

๊ทธ๋ž˜์„œ ์•ˆ์ „ํ•˜๊ฒŒ Content-type์„ ํ•ด๋‹น photo์˜ ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•˜์—ฌ ๋ณด๋‚ด๋ณด์•˜๋‹ค.

ํ•˜์ง€๋งŒ ์ด ๋ถ€๋ถ„์ด ๊ฐ™์•„๋„ ์—ฌ์ „ํžˆ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. ํƒ€์ž…์„ ๋ช…์‹œ์ ์œผ๋กœ image/png๋‚˜ image/* ๋“ฑ์œผ๋กœ ์ง€์ •ํ•ด๋„ ๊ฒฐ๊ณผ๋Š” ๊ฐ™์•˜๋‹ค.

๐Ÿ’ก ๋ฐฉ๋ฒ• 2 : fetch ๋ฉ”์†Œ๋“œ๋กœ ๋ณ€๊ฒฝ

reactjs - Axios AWS S3 Put Object: Error: Network Error

๋‚˜๋ž‘ ๊ฑฐ์˜ ๋น„์Šทํ•œ ๋ฌธ์ œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์‚ฌ๋žŒ์„ stackoverflow์—์„œ ์ฐพ์•˜๋Š”๋ฐ ์œ ์˜๋ฏธํ•œ ๋‹ต๋ณ€์€ ์—†๋Š” ๊ฒƒ ๊ฐ™์•˜๋‹ค... ์ด์œ ๋Š” ์ž˜ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ axios๋ฅผ fetch๋กœ ๋ฐ”๊ฟ”์„œ ๋œ๋‹ค๋Š” ์‚ฌ๋žŒ์ด ์žˆ๊ธธ๋ž˜ ๋‚˜๋„ ์‹œ๋„ํ•ด ๋ณด์•˜๋‹ค. ์‹ค์ œ๋กœ axios๊ฐ€ ์•„๋ฌด๋ฆฌ fetch ๊ธฐ๋ฐ˜์œผ๋กœ ๋Œ์•„๊ฐ„๋‹ค์ง€๋งŒ ๋‚ด๋ถ€ ๋กœ์ง์ด ๋‹ค๋ฅธ ์ ์ด ๋งŽ์•„์„œ ๋‚˜๋„ ์˜ˆ์ „์— axios๋ฅผ fetch๋กœ ๋ฐ”๊พธ๊ธฐ๋งŒ ํ–ˆ๋”๋‹ˆ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋œ ์ ์ด ์žˆ์—ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ข€ ๊ธฐ๋Œ€๋ฅผ ๊ฐ€์ง€๊ณ  ์‹œ๋„ํ•œ ๋ฐฉ๋ฒ•์ด์—ˆ๋Š”๋ฐ,,,

fetch(res.data.preSignedUrl, {
  'body': photo,
  'method': 'PUT',
  'headers': {
    "Content-Type": "image/*",
  }
}).then((res) => {
  console.log(res);
}).catch((err) => {
  console.error(err);
})

fetch ๋ฉ”์†Œ๋“œ๋Š” ๋” ๋ถˆ์นœ์ ˆํ•œ ์ด๋Ÿฐ ์˜ค๋ฅ˜๊ฐ€ ๋œฌ๋‹ค... Content-type์„ photo.type์œผ๋กœ ๋ฐ”๊ฟ”๋ณธ๋‹ค๋“ ์ง€, ์ฃผ์„ ์ฒ˜๋ฆฌ ํ•ด ๋ณธ๋‹ค๋“ ์ง€ ๋“ฑ๋“ฑ์„ ์‹œ๋„ํ•ด ๋ณด์•„๋„ ๊ฒฐ๊ณผ๋Š” ๊ฐ™๋‹ค.

๐Ÿ’ก ๋ฐฉ๋ฒ• 3 : ๋กœ์ปฌ ์„œ๋ฒ„ ๊ป๋‹ค ์ผœ ๋ณด๊ธฐ

์•ˆ ๋œ๋‹ค ๐Ÿ˜Ž ๋‡Œ๊ฐ€ ์•ฝ๊ฐ„ ๋…น์•„์„œ vscode ๊ป๋‹ค ์ผœ ๋ณด๊ธฐ, ์ปดํ“จํ„ฐ ๊ป๋‹ค ์ผœ ๋ณด๊ธฐ ์ด๋Ÿฐ ์›์‹œ์ ์ธ ๋ฐฉ๋ฒ•๊นŒ์ง€ ๋‹ค ํ•ด ๋ดค๋Š”๋ฐ ์•ˆ ๋จใ…‹

๐Ÿ’ก ๋ฐฉ๋ฒ• 4 : FormData๋กœ ๋ณด๋‚ด๊ธฐ

์‚ฌ์‹ค ์ด ๋ฐฉ๋ฒ•์€ ์•„๋‹ ๊ฒƒ ๊ฐ™์•˜๋Š”๋ฐ... ์ง€ํ‘ธ๋ผ๊ธฐ๋ผ๋„ ์žก๋Š” ์‹ฌ์ •์œผ๋กœ ์‹œ๋„ํ•ด ๋ณด์•˜๋‹ค.

const formData = new FormData();
formData.append(photo.name, photo);
axios.put(res.data.preSignedUrl, formData, {
  headers: {
    "Content-Type": "multipart/form-data",
  }
})
  .then((res) => {
  console.log(res);
}).catch((err) => {
  console.error(err);
})

์—ญ์‹œ ๋˜์ง€๋Š” ์•Š์•˜๋‹คใ…Žใ…Ž

const formData = new FormData();
formData.append('file', photo);
axios.put(res.data.preSignedUrl, formData, {
  headers: {
    "Content-Type": "multipart/form-data",
  }
})
  .then((res) => {
  console.log(res);
}).catch((err) => {
  console.error(err);
})

key ์ด๋ฆ„์„ file๋กœ ํ•ด์•ผ ๋œ๋‹ค๋Š” ๋ง๋„ ์žˆ๊ธธ๋ž˜ ํ•ด ๋ณด์•˜๋Š”๋ฐ ์•ˆ ๋œ๋‹ค.
Nestjs์—์„œ ํŒŒ์ผ ์—…๋กœ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ• 2ํŽธ - presigned url(with. presigned post)

์ฐธ๊ณ ๋กœ formData๊ฐ€ ์•„๋‹Œ ๊ทธ๋ƒฅ { file: photo } ๊ฐ์ฒด๋ฅผ body๋กœ ๋„ฃ๋Š” ๊ฒƒ๋„ ํ•ด ๋ณด์•˜๋Š”๋ฐ ์•ˆ ๋˜์—ˆ๋‹ค.

๐Ÿ’ก ๋ฐฉ๋ฒ• 5 : new Request() ๋กœ์ง์œผ๋กœ ์ˆ˜์ •ํ•˜๊ธฐ

fetch๋กœ ๋ณด๋‚ผ ์š”์ฒญ์„ new Request()๋กœ ์ƒ์„ฑํ•ด ๋ณด์•˜๋‹ค. ๊ทธ๋ƒฅ ์˜ˆ์ œ ์ฝ”๋“œ ์ค‘์— ์ด๋ ‡๊ฒŒ ์‹œ๋„ํ•ด ๋ณธ ์‚ฌ๋žŒ๋„ ์žˆ๊ธธ๋ž˜ ํ•ด ๋ณธ ๋ฐฉ๋ฒ•์ด๊ณ  ์‚ฌ์‹ค ์ด๊ฑธ๋กœ ํ•ด๊ฒฐ๋  ๊ฐ€๋Šฅ์„ฑ์€ ๋งค์šฐ ๋‚ฎ์•˜์ง€๋งŒ... (์™œ๋ƒ๋ฉด ๊ทธ๋ƒฅ ์›๋ž˜ ๋ณด๋‚ด๋˜ fetch๋ž‘ ๋˜‘๊ฐ™์œผ๋‹ˆ๊นŒ...) ํ˜น์‹œ๋‚˜ ๋‚ด๊ฐ€ ๋ชจ๋ฅด๊ณ  ์žˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ์„ ์ˆ˜๋„ ์žˆ์œผ๋‹ˆ๊นŒ ์‹œ๋„ํ•ด ๋ณธ ๋ฐฉ๋ฒ•์ด๋‹ค.

fetch(new Request(
  res.data.preSignedUrl, {
    method: 'PUT',
    body: photo,
    headers: new Headers({
      'Content-Type': "image/*",
    }),
  }
)).then((res) => {
  console.log(res);
}).catch((err) => {
  console.error(err);
})

์—ญ์‹œ ์•ˆ ๋œ๋‹ค ํ‚คํ‚ผ ๊ทผ๋ฐ ์ˆœ๊ฐ„ response๊ฐ€ ์ข€ ๋Š๋ฆฌ๊ฒŒ ์™€์„œ ๋œ ์ค„ ์•Œ๊ณ  ๊นœ์ง ๋†€๋žŒ ใ…‹ใ…‹

๐Ÿ’ก ๋ฐฉ๋ฒ• 6 : Binary ํŒŒ์ผ๋กœ ์ „์†ก

๋ฐฑ์—”๋“œ์—์„œ postman์œผ๋กœ ํ…Œ์ŠคํŠธํ•  ๋•Œ๋Š” ์ž˜ ๋ณด๋‚ด์ง€๊ธธ๋ž˜ ๋ด๋ดค๋Š”๋ฐ binary ํ˜•ํƒœ๋กœ ๋ณด๋‚ด๊ณ  ์žˆ๊ธธ๋ž˜ binary๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๋ณด๋‚ด๋ณด๋Š” ๋ฐฉ๋ฒ•๋„ ์‹œ๋„ํ•ด ๋ณด์•˜๋‹ค... ์‚ฌ์‹ค ๊ทธ๋ƒฅ File ๊ฐ์ฒด์งธ๋กœ ๋ณด๋‚ด๋ฉด ๋˜๋Š” ๊ฑฐ ์•„๋‹Œ๊ฐ€ ์‹ถ๊ธด ํ•œ๋ฐ ์ž๋™์œผ๋กœ ์„ค์ •๋˜๋Š” Content-Type์€ x-www-form-urlencoded๊ธธ๋ž˜ ํ˜น์‹œ๋‚˜ ํ•ด์„œ...

function readFileAsBinary(file: File) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onload = () => {
      const arrayBuffer = reader.result;
      resolve(arrayBuffer);
    };

    reader.onerror = reject;

    reader.readAsArrayBuffer(file);
  });
}
...
readFileAsBinary(photo)
  .then((response) => {
  axios.put(res.data.preSignedUrl, response)
    .then((res) => {
    console.log(res);
  }).catch((err) => {
    console.error(err);
  })
...

ํ•˜์ง€๋งŒ ์—ญ์‹œ ๋˜‘๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค...

readFileAsBinary(photo)
  .then((response) => {
  axios.put(res.data.preSignedUrl, response, {
    headers: {
      "Content-Type": 'application/octet-stream'
    }
  })
    .then((res) => {
    console.log(res);
  }).catch((err) => {
    console.error(err);
  })

ํ˜น์‹œ Content-Type์„ application/octet-stream์œผ๋กœ ์ง€์ •ํ•ด์ค˜ ๋ณด๋ฉด ์–ด๋–จ๊นŒ ์‹ถ์–ด์„œ ์ง€์ •ํ•ด ๋ดค๋Š”๋ฐ ํ•ด๊ฒฐ๋˜์ง€๋Š” ์•Š์•˜๋‹ค ใ…Žใ…Ž

๐Ÿ’ก ๋ฐฉ๋ฒ• 7 : ํŒŒ์ผ ํ™•์žฅ์ž ๋ฐ”๊ฟ”๋ณด๊ธฐ

png ํŒŒ์ผ๋กœ๋งŒ ํ…Œ์ŠคํŠธ ํ•ด ๋ณด์•˜๋Š”๋ฐ ํ˜น์‹œ ๋‹ค๋ฅธ ํ™•์žฅ์ž(jpg ๋“ฑ๋“ฑ...) ํŒŒ์ผ๋กœ ํ•˜๋ฉด ๋ ๊นŒ ์‹ถ์–ด์„œ ์‹œ๋„ํ•ด ๋ณด์•˜๋‹ค... ๊ทผ๋ฐ ์„œ๋ฒ„ ์ชฝ์—์„œ๋„ png ํŒŒ์ผ๋กœ ํ…Œ์ŠคํŠธํ–ˆ๊ณ  ์„ฑ๊ณตํ–ˆ์–ด์„œ ์ด๊ฑด ์•„๋‹Œ ๊ฒƒ ๊ฐ™์ง€๋งŒ ๊ทธ๋ž˜๋„...

์˜ˆ์ „์— ์ปจํผ๋Ÿฐ์Šค ๊ฐ€์„œ ์ฐ์—ˆ๋˜ ์‚ฌ์ง„์œผ๋กœ ํ•ด ๋ณด์•˜๋Š”๋ฐ ์•ˆ ๋œ๋‹ค ใ…Žใ…Ž

๐Ÿ’ก ๋ฐฉ๋ฒ• 8 : http๋กœ ์š”์ฒญ

pre-signed url์€ https๋กœ ๋˜์–ด ์žˆ๊ณ , ๋‚˜๋Š” ๋‚ด ๋กœ์ปฌ์—์„œ ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ๋•Œ๋ฌธ์— http๋กœ ๋˜์–ด ์žˆ๋‹ค. ํ˜น์‹œ ์ด๊ฒŒ ๋‹ฌ๋ผ์„œ ๋ฌธ์ œ์ธ๊ฐ€ ์‹ถ์–ด์„œ pre-signed url์„ http๋กœ ๋ฐ”๊พธ์–ด์„œ ์š”์ฒญํ•ด ๋ณด์•˜๋‹ค. ๋ฐ”๊ฟจ๋”๋‹ˆ ๋๋‹ค๋Š” ์‚ฌ๋žŒ์„ ๋ฐœ๊ฒฌํ•ด์„œ ํฌ๋ง์„ ๊ฐ€์ง€๊ณ  ์‹œ๋„ํ•ด ๋ณด์•˜๋‹ค. ์ฐธ๊ณ ํ•œ ๋งํฌ๋Š” ์—ฌ๊ธฐ์˜€๋‹ค.

const link = (res.data.preSignedUrl).replace(/https/, 'http');

axios.put(link, photo, {
  headers: {
    "Content-Type": photo.type
  }
}).then((res) => {
  console.log(res);
}).catch((err) => {
  console.error(err);
})

๋‚˜๋Š” ๋ฐ”๊ฟ”๋„ ์•ˆ ๋˜๋Š” ์‚ฌ๋žŒ์ด์—ˆ๋‹ค.

๐Ÿ’ก ๋ฐฉ๋ฒ• 9 : ์‰ฌ์—ˆ๋‹ค๊ฐ€ ๋‹ค์‹œ ํ•˜๊ธฐ

ใ…Œใ…‹ใ…‹
ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹
ํ™”์š”์ผ๋ถ€ํ„ฐ ์ด๊ฒƒ ๋•Œ๋ฌธ์— ๋ฏธ์น˜๊ฒŸ๋‹ค
์ž๋ ค๊ณ  ๋ˆ„์› ๋‹ค๊ฐ€๋„ ์ด๊ฑด๊ฐ€? ์‹ถ์œผ๋ฉด ๋‹ค์‹œ ์ผ์–ด๋‚˜์„œ ์ฝ”๋“œ ์น˜๊ณ  ์ด๋žฌ๋Š”๋ฐ
์ด๋ ‡๊ฒŒ ๋ฉฐ์น ๋™์•ˆ ํ•ด๊ฒฐ ์•ˆ ๋˜๋Š” ์˜ค๋ฅ˜ ๋„ˆ๋ฌด ์˜ค๋žœ๋งŒ์— ๋งŒ๋‚˜์„œ ๋ฉ˜ํƒˆ์ด ์•ฝํ•ด์กŒ๋‹ค...
๋Ÿฐ์นญ ๊ธฐ๊ฐ„์ด ์–ผ๋งˆ ๋‚จ์ง€ ์•Š์•„์„œ ์ด ๋ฌธ์ œ๋Š” ๋‚˜์ค‘์— ๋‹ค์‹œ ํ•ด๊ฒฐํ•ด ๋ณผ ์ˆ˜๋ฐ–์— ์—†์„ ๊ฒƒ ๊ฐ™๋‹ค.
๋ผˆ์•„ํ”„์ง€๋งŒ ์š”์ฆ˜ ์ž๋งŒํ–ˆ๋Š”๋ฐ ์•„์ง ๋ฉ€์—ˆ๋‹ค๋Š” ๊ฑธ ์•Œ๊ฒŒ ํ•ด ์ค€ ์ข‹์€ ๊ฒฝํ—˜์ด์—ˆ๋‹ค. ^^

profile
์‰ฝ๊ฒŒ๋งŒ์‚ด์•„๊ฐ€๋ฉด์žฌ๋ฏธ์—†์–ด๋น™๊ณ 
post-custom-banner

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

comment-user-thumbnail
2024๋…„ 3์›” 19์ผ

๋‹ต์„ ์ฐพ์œผ์…จ๊ธธ ๊ธฐ์›ํ•ฉ๋‹ˆ๋‹ค.
์ €๋„ ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋Š”๋ฐ,
ํŒŒ์ผ์ด ํด๋ผ์šฐ๋“œ์— ์žˆ๋Š” ๊ฒฝ์šฐ ์œ„์™€๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋„ค์š”.

2๊ฐœ์˜ ๋‹ต๊ธ€
comment-user-thumbnail
2024๋…„ 4์›” 1์ผ

๋ฐฉ๋ฒ• 9๊ฐ€ ๊ฐ€์žฅ ๋งˆ์Œ์— ๋“œ๋„ค์—ฌ

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ
comment-user-thumbnail
2024๋…„ 5์›” 21์ผ

zใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ ํ•˜,, ๊ฐ™์ด ๋ˆˆ๋ฌผ ํ˜๋ฆฌ๊ณ  ๊ฐ‘๋‹ˆ๋‹ค

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ
comment-user-thumbnail
2024๋…„ 5์›” 21์ผ

zใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ใ…‹ ํ•˜,, ๊ฐ™์ด ๋ˆˆ๋ฌผ ํ˜๋ฆฌ๊ณ  ๊ฐ‘๋‹ˆ๋‹ค

๋‹ต๊ธ€ ๋‹ฌ๊ธฐ
comment-user-thumbnail
2024๋…„ 9์›” 7์ผ

๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๊ฒช๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.. ํ•ด๊ฒฐํ–ˆ์„๊นŒ ํ•˜๋Š” ๋งˆ์Œ์œผ๋กœ ์Šคํฌ๋กค์„ ๋‚ด๋ ธ๋Š”๋ฐ ๋งˆ์ง€๋ง‰๊นŒ์ง€ ๊ณ ํ†ต๋ฐ›์œผ์…จ๊ตฐ์š” ใ… 

1๊ฐœ์˜ ๋‹ต๊ธ€