๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
React

[React, JS, TS] ๊ฐ„๊ฒฐํ•œ import๋ฅผ ์œ„ํ•œ index(barrel) ํŒŒ์ผ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด๋ณด์ž

by LasBe 2023. 11. 7.
๋ฐ˜์‘ํ˜•

๐Ÿ“’ JavaScript, Barrel ํŒŒ์ผ


์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ํŠน์ • ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์˜ ์—ฌ๋Ÿฌ ๋ชจ๋“ˆ์„ ํ•˜๋‚˜์˜ ํŒŒ์ผ์—์„œ re-export ํ•จ์œผ๋กœ์จ

๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ ๊ฐ„๊ฒฐํ•œ import๋ฌธ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” index ํŒŒ์ผ์„ Barrel ํŒŒ์ผ์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

์ฒ˜์Œ์—” Barrel์ด๋ž€ ๋ช…์นญ์„ ๋ชฐ๋ผ ๊ทธ๋ƒฅ ์ธ๋ฑ์‹ฑํ•œ๋‹ค๊ณ  ํ•˜๋ฉฐ 1๋…„ ๋™์•ˆ ๊ฒ€์ƒ‰๋„ ์ œ๋Œ€๋กœ ๋ชปํ–ˆ์—ˆ๋Š”๋ฐ,

์ตœ๊ทผ ์•„ํ‹ฐํด์„ ๋ณด๋‹ค ์ด๋Ÿฌํ•œ index ํŒŒ์ผ์„ Barrel์ด๋ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด๊ณค ์†์ด ์‹œ์›ํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

 

๋ญ ์–ด์จŒ๋“  ๋‹ค๋“ค ์•„์‹œ๊ฒ ์ง€๋งŒ ๋‹ค์Œ ์ฝ”๋“œ๋“ค์€ ์ฃผ๋กœ index.js, index.ts๋กœ ์‚ฌ์šฉ๋˜๋Š” Barrel ํŒŒ์ผ์˜ ์ผ๋ฐ˜์ ์ธ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.

//barrel ์ ์šฉ ์ „
import { ModuleA } from 'utils/ModduleA';
import { ModuleB } from 'utils/ModduleB';
import { ModuleC } from 'utils/ModduleC';

์œ„์™€ ๊ฐ™์ด ํŒŒ์ผ๋‹น ํ•œ์ค„ ์”ฉ ๋Š˜์–ด๋‚ฌ๋˜ import๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์€ Barrel ํŒŒ์ผ์„ ์ ์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

// utils/index.ts
export { default as ModuleA } from './ModuleA';
export { default as ModuleB } from './ModuleB';
export { default as ModuleC } from './ModuleC';
// barrel ์ ์šฉ ํ›„
import { ModuleA, ModuleB, ModuleC } from 'utils';

๐Ÿ“Œ ๋„ˆ๋ฌด๋‚˜ ๊ท€์ฐฎ์€ Barrel ํŒŒ์ผ ์ž‘์„ฑ

์ฝ”๋“œ ๋ผ์ธ์ด ๊ธธ์–ด์ง€๋Š”๊ฑธ ๋„ˆ๋ฌด๋‚˜ ์‹ซ์–ดํ•˜๋Š” ์ €์—๊ฒŒ Barrel ํŒŒ์ผ์€ ๊ฐ€๋ญ„์— ๋‹จ ๋น„ ๊ฐ™์€ ์กด์žฌ์˜€์œผ๋‚˜,

๋ฌธ์ œ๋Š” ํŒŒ์ผ์ด ์ถ”๊ฐ€๋˜๊ฑฐ๋‚˜ ์‚ญ์ œ๋˜๋ฉด ๊ทธ๊ฑฐ์— ๋Œ€ํ•ญํ•ด Barrel ํŒŒ์ผ์„ ์ผ์ผ์ด ์ˆ˜์ž‘์—…์œผ๋กœ ์ˆ˜์ •ํ•ด์ฃผ์–ด์•ผ ํ–ˆ๊ณ ,

์ด์ „์— ๋ชจ๋ฅด๊ณ  ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์•˜๋˜ ํŒŒ์ผ์€ ๋˜ ์–ด๋”˜๊ฐ€ ํ•œ ์ค„์˜ import ๋ผ์ธ์ด ๋˜์–ด ์ €๋ฅผ ๊ดด๋กญํ˜”์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋‹ค ์–ด๋Š๋‚  ๋ฌธ๋“ Node.js์˜ fs ๋ชจ๋“ˆ์„ ์ด์šฉํ•œ๋‹ค๋ฉด ๋‹จ ํ•œ ์ค„์˜ ํ„ฐ๋ฏธ๋„ ๋ช…๋ น์–ด๋กœ

Barrel ํŒŒ์ผ์„ ์ž๋™ํ™”ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ์Šค์ณ ์ง€๋‚˜๊ฐ”์Šต๋‹ˆ๋‹ค.


๐Ÿ“Œ Barrel ํŒŒ์ผ ์ž๋™ํ™” ์Šคํฌ๋ฆฝํŠธ

 

GitHub - LasBe-code/generate-barrel-file: JavaScript, TypeScript์—์„œ index(barrel) ํŒŒ์ผ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋Š” ์Šค

JavaScript, TypeScript์—์„œ index(barrel) ํŒŒ์ผ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋Š” ์Šคํฌ๋ฆฝํŠธ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. - GitHub - LasBe-code/generate-barrel-file: JavaScript, TypeScript์—์„œ index(barrel) ํŒŒ์ผ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์ฃผ๋Š” ์Šคํฌ๋ฆฝํŠธ ์˜ˆ

github.com

๋ฐฐ๋Ÿด ํŒŒ์ผ ์ž๋™ ์ƒ์„ฑ ์Šคํฌ๋ฆฝํŠธ ์ ์šฉ ์˜ˆ์ œ๋Š” ์ œ ๊นƒํ—ˆ๋ธŒ์— ์˜ฌ๋ ค๋†จ์œผ๋‹ˆ ์ฐธ๊ณ ํ•ด ์ฃผ์„ธ์š”.


const fs = require('fs');

JavaScript์˜ fs ๋ชจ๋“ˆ์€ Node.js์˜ ํ•ต์‹ฌ ๋ชจ๋“ˆ ์ค‘ ํ•˜๋‚˜๋กœ,

ํŒŒ์ผ ์‹œ์Šคํ…œ์— ์ ‘๊ทผํ•˜์—ฌ ํŒŒ์ผ์„ ์ฝ๊ณ , ์“ฐ๊ณ , ์ˆ˜์ •ํ•˜๊ณ , ์‚ญ์ œํ•˜๋Š” ๋“ฑ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ์ด์šฉํ•œ๋‹ค๋ฉด ํ˜„์žฌ ํ”„๋กœ์ ํŠธ์˜ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ฝ๊ณ  ๋ถ„์„ํ•ด

์žฌ๊ท€์ ์œผ๋กœ ํด๋”์˜ ํด๋”๋ฅผ ํŒŒ๊ณ  ๋“ค์–ด๊ฐ€ Barrel ํŒŒ์ผ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค ์ƒ๊ฐํ–ˆ๊ณ ,

chatGPT์˜ ๋„์›€์„ ๋ฐ›์•„ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์™„์„ฑ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์„œ ์ง์ ‘ ์‚ฌ์šฉํ•˜์‹ค ๋•Œ๋Š” ๋‹ค์Œ 3๊ฐ€์ง€๋งŒ ์ง์ ‘ ์ˆ˜์ •ํ•ด ์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

  1. ํ™•์žฅ์ž ๋ช… ๋ณ€๊ฒฝ์„ ์œ„ํ•œ isJavaScript ๋ณ€์ˆ˜ ์ˆ˜์ •
  2. Barrel ํŒŒ์ผ์„ ์ƒ์„ฑํ•  ๋””๋ ‰ํ† ๋ฆฌ ๋ชฉ๋ก
  3. Barrel ํŒŒ์ผ์—์„œ export ํ•˜์ง€ ์•Š์„ ์˜ˆ์™ธ ํŒŒ์ผ ์ด๋ฆ„ ๋ชฉ๋ก
const fs = require('fs'); // ํŒŒ์ผ ์‹œ์Šคํ…œ ๋ชจ๋“ˆ ์‚ฌ์šฉ
const path = require('path'); // ๊ฒฝ๋กœ ๊ด€๋ จ ๋ชจ๋“ˆ ์‚ฌ์šฉ

// ์†Œ์Šค ์ฝ”๋“œ ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ ์„ค์ •
const srcFolderPath = path.join(__dirname, 'src');
let count = 0;

// (์ง์ ‘ ์ˆ˜์ •) index.js = true, index.ts = false
const isJavaScript = false;
const extension = isJavaScript ? 'js' : 'ts';

// (์ง์ ‘ ์ˆ˜์ •) ์ฒ˜๋ฆฌ ๋Œ€์ƒ ๋””๋ ‰ํ† ๋ฆฌ ๋ชฉ๋ก
const targetFolderList = ['apis', 'components', 'constants', 'hooks', 'pages', 'states'];

// (์ง์ ‘ ์ˆ˜์ •) ์˜ˆ์™ธ ํŒŒ์ผ ๋ชฉ๋ก
const exceptionFileList = ['exception'];

targetFolderList.forEach((folder) => {
  const folderPath = path.join(srcFolderPath, folder); // ๋Œ€์ƒ ํด๋”์˜ ์ „์ฒด ๊ฒฝ๋กœ ์ƒ์„ฑ
  if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) {
    generateIndexFile(folderPath); // ๋Œ€์ƒ ํด๋”์—์„œ index.js(ts) ํŒŒ์ผ ์ƒ์„ฑ ํ•จ์ˆ˜ ํ˜ธ์ถœ
  }
});

// ์ง€์ •๋œ ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์˜ ํŒŒ์ผ๋“ค์„ ๊ธฐ๋ฐ˜์œผ๋กœ index.js(ts) ํŒŒ์ผ์„ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜
function generateIndexFile(directoryPath) {
  // ํ˜„์žฌ ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์˜ index.js(ts) ํŒŒ์ผ ๊ฒฝ๋กœ ์ƒ์„ฑ
  const indexFilePath = path.join(directoryPath, `index.${extension}`);

  // ํ˜„์žฌ ์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ๊ณผ์˜ ์ƒ๋Œ€ ๊ฒฝ๋กœ ๊ณ„์‚ฐ
  const relativePath = path.relative(__dirname, indexFilePath);

  const files = fs.readdirSync(directoryPath); // ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด์˜ ํŒŒ์ผ ๋ชฉ๋ก์„ ์ฝ์–ด์˜ด

  const exportStatementList = []; // export ๊ตฌ๋ฌธ์„ ๋‹ด์„ ๋ฐฐ์—ด

  files.forEach((file) => {
    // ํŒŒ์ผ์˜ ์ „์ฒด ๊ฒฝ๋กœ ์ƒ์„ฑ
    const filePath = path.join(directoryPath, file);

    // ํ™•์žฅ์ž๋ฅผ ์ œ์™ธํ•œ ํŒŒ์ผ ์ด๋ฆ„ ์ถ”์ถœ
    const fileNameWithoutExtension = path.basename(file, path.extname(file));

    // ์˜ˆ์™ธ ํŒŒ์ผ ๋ชฉ๋ก์— ํฌํ•จ๋˜๋Š”์ง€ ํ™•์ธ
    const isException = exceptionFileList.some((exceptionFileName) =>
      exceptionFileName.toLowerCase().includes(fileNameWithoutExtension.toLowerCase()),
    );

    if (isException) return; // ์˜ˆ์™ธ ํŒŒ์ผ์ธ ๊ฒฝ์šฐ, ๋‹ค์Œ ํŒŒ์ผ๋กœ ๋„˜์–ด๊ฐ

    if (
      fs.statSync(filePath).isFile() &&
      (file.endsWith(`.${extension}`) || file.endsWith(`.${extension}x`)) &&
      file !== `index.${extension}`
    ) {
      // ํŒŒ์ผ์ด ์กด์žฌํ•˜๊ณ  ํ™•์žฅ์ž๊ฐ€ .js(ts) ๋˜๋Š” .jsx(tsx)์ด๋ฉฐ, ํŒŒ์ผ ์ด๋ฆ„์ด index.js(ts)๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ
      exportStatementList.push(`export * from './${fileNameWithoutExtension}';`);
    } else if (fs.statSync(filePath).isDirectory() && file !== `index.${extension}`) {
      // ๋””๋ ‰ํ† ๋ฆฌ์ธ ๊ฒฝ์šฐ, ํŒŒ์ผ ์ด๋ฆ„์ด index.js(ts)๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ
      exportStatementList.push(`export * from './${fileNameWithoutExtension}';`);
      generateIndexFile(filePath); // ์žฌ๊ท€์ ์œผ๋กœ ํ•˜์œ„ ๋””๋ ‰ํ† ๋ฆฌ ์ฒ˜๋ฆฌ
    }
  });

  const content = exportStatementList.join('\n'); // export ๊ตฌ๋ฌธ์„ ์ค„ ๋ฐ”๊ฟˆ์œผ๋กœ ์—ฐ๊ฒฐํ•˜์—ฌ ๋‚ด์šฉ ์ƒ์„ฑ
  fs.writeFileSync(indexFilePath, content); // ์ƒ์„ฑ๋œ ๋‚ด์šฉ์„ index.js(ts) ํŒŒ์ผ์— ์“ฐ๊ธฐ

  console.log(`${++count} ${`\t`} ${relativePath}`);
}

๐Ÿ”Ž ์‚ฌ์šฉ ๋ฐฉ๋ฒ•

์œ„์™€ ๊ฐ™์ด ํ”„๋กœ์ ํŠธ root ๊ฒฝ๋กœ์— ํ•ด๋‹น ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด ์ค๋‹ˆ๋‹ค.

 

๊ทธ๋‹ค์Œ package.json ํŒŒ์ผ์˜ scripts ๋ถ€๋ถ„์— node๋กœ ํ•ด๋‹น ํŒŒ์ผ์„ ์‹คํ–‰์‹œํ‚ค๋Š” ๋ช…๋ น์–ด๋ฅผ ์ง€์ •ํ•ด ์ค€ ๋’ค,
$ npm run barrel ์„ ํ„ฐ๋ฏธ๋„์— ์ž…๋ ฅํ•˜๋ฉด ์œ„ ์ฝ”๋“œ์—์„œ ์ง€์ •ํ–ˆ๋˜ ๋””๋ ‰ํ† ๋ฆฌ์˜ Barrel ํŒŒ์ผ์ด ์ž๋™ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.


๐Ÿ”Ž ์ ์šฉ ์ „


๐Ÿ”Ž ์ ์šฉ ํ›„


๐Ÿ”Ž ์ฃผ์˜ ์‚ฌํ•ญ

src ํด๋”์˜ ๋ฐ”๋กœ ์•„๋ž˜ ์ž์‹ ํด๋”๋“ค์ด export ๊ฒฝ๋กœ์˜ root๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ ‡๊ธฐ์— ๋ชจ๋“  ๋ชจ๋“ˆ๋“ค์ด export root ๊ฒฝ๋กœ์˜ ์ด๋ฆ„์œผ๋กœ export ๋˜์–ด์„œ
ํด๋” ๋ช…, ํŒŒ์ผ ๋ช…, ํ•จ์ˆ˜ ๋ช…, ๋ณ€์ˆ˜ ๋ช…์€ ๋ฐ˜๋“œ์‹œ ์ค‘๋ณต๋˜์ง€ ์•Š๊ณ  unique **ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

ex) export root = @pages, @hooks, @components...

 

 

๐Ÿ“’ Barrel ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ๋ผ?


 

[Korean FE Article] ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—์ฝ”์‹œ์Šคํ…œ์˜ ์†๋„ ํ–ฅ์ƒ - ๋ฐฐ๋Ÿด(Barrel) ํŒŒ์ผ์˜ ๋Œ€์‹คํŒจ

๊ธ€ ๋งํฌ: https://github.com/yeonjuan/dev-blog/blob/master/JavaScript/speeding-up-the-javascript-ecosystem-the-barrel-file-debacle.md ์†Œ๊ฐœ ๋ฐฐ๋Ÿด(Barrel) ํŒŒ์ผ์„ ๋งŽ์ด ์‚ฌ์šฉํ•˜๊ณ  ๊ณ„์‹ ๋‚˜์š”? ๋ฐฐ๋Ÿด ํŒŒ์ผ์€ index.js ์ฒ˜๋Ÿผ ํŠน์ • ํŒŒ์ผ์—์„œ

kofearticle.substack.com

 

์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ๋„ˆ๋ฌด ์‹ ๋‚˜์„œ ํ”„๋กœ์ ํŠธ์˜ ๋ช‡๋ช‡ ๋””๋ ‰ํ† ๋ฆฌ์— ๋ฐฐ๋Ÿด ํŒŒ์ผ์„ ์ ์šฉํ•œ๋‹ค๊ณ 

๋ฐ˜๋‚˜์ ˆ๋™์•ˆ ๋ชจ๋“  ํด๋”์˜ ์ค‘๋ณต์„ ์—†์• ์„œ ์™„์„ฑํ•œ ํ›„ ์ด ๊ธ€์„ ๋ด๋ฒ„๋ ธ์Šต๋‹ˆ๋‹ค…

 

๋ญ”๊ฐ€ ๋‹น์—ฐํžˆ ๋ชจ๋“  ํŒŒ์ผ์„ ๋ชจ์•„์„œ ๋‚ด๋ณด๋‚ด๊ธฐ ํ•˜๋ฉด ์„ฑ๋Šฅ์ƒ์œผ๋กœ ๋ถˆ๋ฆฌํ•จ์ด ์žˆ์„ ๊ฑฐ๋ผ ์ƒ๊ฐ์€ ํ–ˆ์œผ๋‚˜

์œ„ ๊ธ€์—์„œ ๋„ˆ๋ฌด๋‚˜ ๋ฌด์‹œ๋ฌด์‹œํ•˜๊ฒŒ ๋งํ•˜๊ธธ๋ž˜ ๋ฐ˜๋‚˜์ ˆ์„ ๋‚ญ๋น„ํ–ˆ๋‚˜ ์‹ถ์–ด ์ขŒ์ ˆํ–ˆ์Šต๋‹ˆ๋‹ค.

 

ํ•˜๋ฃจ์ข…์ผ ๊ณ ๋ฏผํ•œ ๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜์ž๋ฉด “๊ทธ๋ƒฅ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ๋” ๋‚ซ๋‹ค” ์ž…๋‹ˆ๋‹ค.

 

๊ทธ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.


๐Ÿ“Œ ๋Ÿฐํƒ€์ž„์—์„œ๋Š” ๋˜‘๊ฐ™๋‹ค

์œ„ ๊ธ€์—์„œ๋„ ์•Œ ์ˆ˜ ์žˆ๋‹ค์‹œํ”ผ ๋Ÿฐํƒ€์ž„์—๋Š” ์ง€์žฅ์ด ์—†์Šต๋‹ˆ๋‹ค.

 

์ฆ‰, ์‹ค์ œ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ์šฉ์ž๋Š” ๋ฐฐ๋Ÿด์„ ์‚ฌ์šฉํ•˜๋‚˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋‚˜ ๋˜‘๊ฐ™๋‹ค๋Š” ๋ง์ž…๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋Š” ๋ถ€๋ถ„์€ ๋Œ€๋ถ€๋ถ„ ๊ฐœ๋ฐœ ๋‹จ๊ณ„์—์„œ ์กฐ๊ธˆ ๋” ์‹œ๊ฐ„์ด ์ง€์—ฐ๋œ๋‹ค๋Š” ๊ฒƒ์ธ๋ฐ
์š”์ฆ˜ ์ปดํ“จํŒ… ํŒŒ์›Œ๊ฐ€ ์›Œ๋‚™ ์ƒํ–ฅํ‰์ค€ํ™”๋ฅผ ์ด๋ค˜๊ธฐ๋„ ํ•˜๊ณ ,
๋ช‡์‹ญ ์ค„์˜ import ๋ผ์ธ์„ ๋ณด๋ฉฐ ํ™”๊ฐ€ ์น˜์†Ÿ๋Š” ๊ฒƒ๋ณด๋‹ค ์‹œ๊ฐ„์ด ์กฐ๊ธˆ ๋” ๊ฑธ๋ฆฌ๋Š” ๊ฒŒ ํ›จ์”ฌ ๋‚ซ๋‹ค๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ์—ฌ๋Ÿฌ๋ถ„์€ ๊ฐ์ž์˜ ํ™•์‹คํ•œ ๊ฐ€์น˜ํŒ๋‹จ์œผ๋กœ ๋ฐฐ๋ŸดํŒŒ์ผ์˜ ์‚ฌ์šฉ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜์‹œ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค!

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€


์˜คํ”ˆ ์ฑ„ํŒ