KDT/TIL

8/29 TIL : JSDoc, ํ”„๋ ˆ์ž„์›Œํฌ ์—†์ด CRUD ๊ตฌํ˜„, JS module

ebulsok 2022. 9. 15. 23:53

๐Ÿ”Ž JSDoc /** */

  • ํŠน์ • ํ˜•ํƒœ๋กœ ์ฃผ์„์„ ๋‹ฌ๋ฉด ์ฃผ์„ ๋‚ด์šฉ์„ ํ†ตํ•ด ํ•จ์ˆ˜์˜ ๊ธฐ๋Šฅ, ๋งค๊ฐœ ๋ณ€์ˆ˜ ํƒ€์ž… ๋“ฑ์„ ๋ฏธ๋ฆฌ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ์Œ
  • ๊ฑฐ์˜ ํ‘œ์ค€ํ™”๊ฐ€ ๋˜์–ด์„œ vsCode, webstorm ๋“ฑ์—์„œ ๊ธฐ๋ณธ์œผ๋กœ ๊ธฐ๋Šฅ ์ œ๊ณต
/**
 * @param {string} name ์ด๋ฆ„
 * @param {number} age ๋‚˜์ด
 * @returns ์ด๋ฆ„๊ณผ ๋‚˜์ด๋ฅผ ๋ฐ›์•„์„œ ๋ฌธ์ž์—ด๋กœ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.
 * @todo ์ƒˆ๋กœ์šด ๋งค๊ฐœ๋ณ€์ˆ˜ ์ถ”๊ฐ€
 * @deprecated
 */
function hello(name, age) {
  return `๋‚ด ์ด๋ฆ„์€ ${name}์ด๊ณ  ๋‚˜์ด๋Š” ${age}์„ธ ์ž…๋‹ˆ๋‹ค.`;
}

 

๐Ÿšฉ JSDoc ๋ถ€๊ฐ€ ๊ธฐ๋Šฅ

  • @todo : ๋ฉ”๋ชจ์ฒ˜๋Ÿผ ์‚ฌ์šฉ
  • @deprecated : ๋” ์ด์ƒ ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๋•Œ
  • @type { ํƒ€์ž… ํ˜•ํƒœ } : ๋ณ€์ˆ˜์— ํŠน์ •
  • @typedef : JSDoc์˜ ๋‚ด์šฉ์„ ๋ณ€์ˆ˜์ฒ˜๋Ÿผ ์„ ์–ธํ•ด ๋†“๊ณ  @type { }๋กœ ๋‹ค๋ฅธ ๊ณณ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
/** @type {string} */
const test = 'hy';

/**
 * @typedef Post
 * @property {number} id
 * @property {string} title
 * @property {string} content
 */

/** @type {Post} */
const post = {
  id: 1,
  title: '์ œ๋ชฉ',
  content: '๋‚ด์šฉ',
};

๐Ÿ”Ž ํ”„๋ ˆ์ž„์›Œํฌ ์—†์ด ๋ธ”๋กœ๊ทธ CRUD ๊ตฌํ˜„ํ•˜๊ธฐ

// @ts-check
const http = require('http');

// DB ์—†์œผ๋ฏ€๋กœ ๋ฐ์ดํ„ฐ ๋ณ€์ˆ˜ ์„ ์–ธ
const posts = [
  {
    id: 1,
    title: 'first',
    content: 'hello, back-end',
  },
  {
    id: 2,
    title: 'second',
    content: 'hello, back-end',
  },
  {
    id: 3,
    title: 'third',
    content: 'hello, back-end',
  },
];

// ์„œ๋ฒ„ ์ •์˜
const server = http.createServer((req, res) => {
  res.setHeader('Content-Type', 'application/json; charset=utf-8');

  const urlArr = req.url ? req.url.split('/') : [];
  let id = -1;
  if (urlArr.length > 2) id = parseInt(urlArr[2], 10);

  /**
   * ๋ธ”๋กœ๊ทธ์šฉ ์„œ๋ฒ„ API ๊ตฌ์„ฑ
   *
   * GET /posts ๋ชฉ๋ก ๊ฐ€์ ธ์˜ค๊ธฐ
   * GET /posts/:id ๊ธ€ ๋‚ด์šฉ ๊ฐ€์ ธ์˜ค๊ธฐ
   * POST /posts ์ƒˆ๋กœ์šด ๊ธ€ ์˜ฌ๋ฆฌ๊ธฐ
   * PUT /posts/:id ๊ธฐ์กด ๊ธ€ ์ˆ˜์ •ํ•˜๊ธฐ
   * DELETE /posts/:id ๊ธฐ์กด ๊ธ€ ์‚ญ์ œํ•˜๊ธฐ
   */
  if (req.url === '/posts' && req.method === 'GET') {
    const result = {
      posts: posts.map((post) => ({
        id: post.id,
        title: post.title,
        content: post.content,
      })),
      totalCount: posts.length,
    };

    res.statusCode = 200;
    res.end(JSON.stringify(result));
    console.log('๋ธ”๋กœ๊ทธ์˜ ๊ธ€ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ค๋Š” API ์ž…๋‹ˆ๋‹ค.');
  } else if (id !== -1 && req.method === 'GET') {
    const result = posts.find((post) => post.id === id);

    if (result) {
      res.statusCode = 200;
      res.end(JSON.stringify(result));
      console.log('๋ธ”๋กœ๊ทธ์˜ ํŠน์ • ๊ธ€ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์˜ค๋Š” API ์ž…๋‹ˆ๋‹ค.');
    } else {
      res.statusCode = 404;
      res.end('ํฌ์ŠคํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
      console.log('ํ•ด๋‹น id๋ฅผ ๊ฐ€์ง€๋Š” ํฌ์ŠคํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
    }
  } else if (req.url === '/posts' && req.method === 'POST') {
    req.setEncoding('utf-8');
    req.on('data', (data) => {
      const newPost = JSON.parse(data);
      posts.push({
        id: posts[posts.length - 1].id + 1,
        title: newPost.title,
        content: newPost.content,
      });
    });

    res.statusCode = 200;
    res.end('์ƒˆ๋กœ์šด ๊ธ€์ด ๋“ฑ๋ก๋˜์—ˆ์Šต๋‹ˆ๋‹ค.');
    console.log('๋ธ”๋กœ๊ทธ์˜ ๊ธ€์„ ์˜ฌ๋ฆด ๋•Œ ํ˜ธ์ถœํ•  API ์ž…๋‹ˆ๋‹ค.');
  } else if (id !== -1 && req.method === 'PUT') {
    const result = posts.find((post) => post.id === id);

    if (result) {
      req.setEncoding('utf-8');
      req.on('data', (data) => {
        const modiPost = JSON.parse(data);
        if (modiPost.title) posts[id - 1].title = modiPost.title;
        if (modiPost.content) posts[id - 1].content = modiPost.content;
      });

      res.end('๊ธ€์ด ์ˆ˜์ •๋˜์—ˆ์Šต๋‹ˆ๋‹ค.');
      res.statusCode = 200;
      console.log('๋ธ”๋กœ๊ทธ์˜ ๊ธ€์„ ์ˆ˜์ •ํ•  ๋•Œ ํ˜ธ์ถœํ•  API ์ž…๋‹ˆ๋‹ค.');
    } else {
      res.statusCode = 404;
      res.end('ํฌ์ŠคํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
      console.log('ํ•ด๋‹น id๋ฅผ ๊ฐ€์ง€๋Š” ํฌ์ŠคํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
    }
  } else if (id !== -1 && req.method === 'DELETE') {
    const result = posts.find((post) => post.id === id);

    if (result) {
      posts.splice(id - 1, 1);

      res.statusCode = 200;
      res.end('๊ธ€์ด ์‚ญ์ œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.');
      console.log('๋ธ”๋กœ๊ทธ์˜ ๊ธ€์„ ์‚ญ์ œํ•  ๋•Œ ํ˜ธ์ถœํ•  API ์ž…๋‹ˆ๋‹ค.');
    } else {
      res.statusCode = 404;
      res.end('ํฌ์ŠคํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
      console.log('ํ•ด๋‹น id๋ฅผ ๊ฐ€์ง€๋Š” ํฌ์ŠคํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
    }
  } else {
    res.statusCode = 400;
    res.end('NOT FOUND');
    console.log('ํ•ด๋‹น API๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.');
  }
});

// ์„œ๋ฒ„ ์‹คํ–‰
const PORT = 4000;
server.listen(PORT, () => {
  console.log(`ํ•ด๋‹น ์„œ๋ฒ„๋Š” ${PORT}๋ฒˆ ํฌํŠธ์—์„œ ์ž‘๋™ ์ค‘์ž…๋‹ˆ๋‹ค.`); // ์„œ๋ฒ„ ์ฝ˜์†”
});

 

๐Ÿ”Ž Code Refactoring: ํ”„๋กœ๊ทธ๋žจ์˜ ๋™์ž‘์€ ๋ณ€ํ™”์‹œํ‚ค์ง€ ์•Š๊ณ  ๋‚ด๋ถ€ ๊ตฌ์กฐ๋ฅผ ๊ฐœ์„ ํ•˜๋Š”๊ฒƒ

  • ์›์‹œ๊ธฐ์ˆ  -> ์ƒˆ๋กœ์šด ๊ธฐ์ˆ 
  • ์ฝ”๋“œ ๋น„ํšจ์œจ -> ํšจ์œจ(๋ฐ˜๋ณต๋ฌธ ์ค„์ด๊ธฐ, ์ค‘๋ณต ๊ธฐ๋Šฅ ์ œ๊ฑฐ, ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ ์ฆ๋Œ€)
  • ์ฝ”๋“œ ๊ฐ€๋…์„ฑ, ํ™•์žฅ์„ฑ ๋†’์ด๊ธฐ

 

๐Ÿ”Ž JS Module

๐Ÿšฉ CommonJS ๋ฐฉ์‹

  • node.js์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋ชจ๋“ˆ ๋ฐฉ์‹
  • require / exports

1. ์ „์ฒด ๋ชจ๋“ˆ๋กœ์จ ๋‚ด๋ณด๋‚ด๊ณ , ์ „์ฒด๋ฅผ ํ•˜๋‚˜์˜ obj๋กœ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

// animal.js
const animals = ['dog', 'cat'];
function showAnimals() {
  animals.map((el) => console.log(el));
}
module.exports = {
  animals,
  showAnimals,
};

// module.js
const animals = require('./animals');
console.log(animals.animals);
animals.showAnimals();

2. ๋‚ด๋ณด๋‚ด๊ณ  ์‹ถ์€ ๊ฒƒ(๋ณ€์ˆ˜, ํ•จ์ˆ˜, ํด๋ž˜์Šค ๋“ฑ)์— exports๋ฅผ ๋ถ™์—ฌ์„œ ๋‚ด๋ณด๋‚ด๊ณ , ๊ฐ๊ฐ์„ ๋”ฐ๋กœ ์„ ์–ธํ•ด์„œ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•

// animal.js
const animals = ['dog', 'cat'];
exports.animals = animals;
exports.showAnimals = function showAnimals() {
  animals.map((el) => console.log(el));
};

// module.js
const { animals, showAnimals } = require('./animals');
console.log(animals);
showAnimals();

 

๐Ÿšฉ ES6๋ฐฉ์‹

  • 2015๋…„์— ES6๊ฐ€ ์—…๋ฐ์ดํŠธ๋˜๋ฉด์„œ ์ถ”๊ฐ€๋œ ๋ฐฉ์‹
  • ๋ธŒ๋ผ์šฐ์ €์—์„œ ๊ตฌ๋™๋˜๋Š” js์— ๋Œ€ํ•œ ๋ฌธ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์— node.js์—์„œ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋ณ„๋„ ์ฒ˜๋ฆฌ ํ•„์š”
  • package.json์— "type": "module" ์ถ”๊ฐ€ํ•˜๋ฉด ์‚ฌ์šฉ ๊ฐ€๋Šฅ
  • import / export

1. ์„ ์–ธ๋ถ€์— export ์‚ฌ์šฉ

// animal.js
export const animals = ['dog', 'cat'];
export function showAnimals() {
  animals.map((el) => console.log(el));
}

// module.js
import { animals, showAnimals } from './animals.js';
console.log(animals);
showAnimals();

2. ๋งˆ์ง€๋ง‰์— export ์‚ฌ์šฉ

// animal.js
const animals = ['dog', 'cat'];
function showAnimals() {
  animals.map((el) => console.log(el));
}
export { animals, showAnimals };

// module.js
import { animals, showAnimals } from './animals.js';
console.log(animals);
showAnimals();
  • ๊ฐ€์ ธ์˜ฌ ๊ฒƒ๋“ค์ด ๋งŽ์œผ๋ฉด * as๋ฅผ ์‚ฌ์šฉ
import * as animals from './animals.js';
console.log(animals.animals);
animals.showAnimals();
  • ๋ชจ๋“ˆ์ด๋ฆ„์„ ๋ฐ”๊พธ๊ณ  ์‹ถ์œผ๋ฉด ๋ชจ๋“ˆ์ด๋ฆ„ as ์ƒˆ๋กœ์šด๋ชจ๋“ˆ์ด๋ฆ„ ์œผ๋กœ ๋ณ€๊ฒฝ
// import
import { animals as ani, showAnimals as show } from './animals.js';
console.log(ani);
show();

// export
const animals = ['dog', 'cat'];
function showAnimals() {
  animals.map((el) => console.log(el));
}
export { animals as ani, showAnimals as show };

1. ๋ณต์ˆ˜์˜ export๊ฐ€ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ˜•ํƒœ์˜ ๋ชจ๋“ˆ

2. ํŒŒ์ผ ํ•˜๋‚˜์— ํ•˜๋‚˜์˜ ๊ฐœ์ฒด(obj, class)๋งŒ ์žˆ๋Š” ๋ชจ๋“ˆ - export default

// animal.js
export default class Animal {
  constructor() {
    this.animals = ['dog', 'cat'];
  }

  showAnimals() {
    this.animals.map((el) => console.log(el));
  }
}

// module.js
import Animal from './animals.js';
const ani = new Animal();
console.log(ani.animals);
ani.showAnimals();