Refribank BackEnd ๐Ÿฆ

image

๐Ÿ’ก The purpose of a project

First cooperation project

1๏ธโƒฃ Idea

์—ฌ๋Ÿฌ๋ถ„์˜ ๋ƒ‰์žฅ๊ณ ๋Š” ํ˜„์žฌ ์–ด๋–ค ์ƒํƒœ์ธ๊ฐ€์š”? ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์‹์žฌ๋ฃŒ๋กœ ์–ด๋–ค ์š”๋ฆฌ๋ฅผ ํ• ์ง€ ๊ณ ๋ฏผ์ด ๋˜๊ฑฐ๋‚˜ ๋˜๋Š” ์žŠํ˜€์ง„ ์‹์žฌ๋ฃŒ๊ฐ€ ์žˆ์ง€๋Š” ์•Š๋‚˜์š”?

์ด๋Ÿฌํ•œ ๊ณ ๋ฏผ์„ ๊ฐ€์ง„ 5๋ช…์˜ ํ•™์ƒ๋“ค์ด ์ œ์ž‘ํ•œ Refri Bank๋Š” ๋ƒ‰์žฅ๊ณ ๋ฅผ ์˜๋ฏธํ•˜๋Š” Refrigerator์™€ ๊ด€๋ฆฌ๋ฅผ ๋Œ€์‹ ์ˆ˜ํ–‰ํ•˜๋Š” Bank๋ฅผ ํ•ฉ์นœ ๋‹จ์–ด์ž…๋‹ˆ๋‹ค.

์ฒ˜์Œ์—” ๋‹จ์ˆœํžˆ ๋ƒ‰์žฅ๊ณ ์— ๋“ค์–ด์žˆ๋Š” ์‹์žฌ๋ฃŒ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜์žˆ๋Š” ๋ ˆ์‹œํ”ผ ์ถ”์ฒœ ์„œ๋น„์Šค๋ฅผ ๊ตฌ์ƒํ•˜์˜€์œผ๋‚˜, ์ถ”๊ฐ€์ ์œผ๋กœ ์ €ํฌ๊ฐ€ ๊ฐ€์ง„ ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ์‹ค์‹œ๊ฐ„ ์ธ๊ธฐ ๋ ˆ์‹œํ”ผ, ๋‚ด๊ฐ€ ๋“ฑ๋กํ•œ ์‹์žฌ๋ฃŒ์˜ ์œ ํ†ต๊ธฐํ•œ, ์žฌ๋ฃŒ๋‚˜ ์ œ๋ชฉ์„ ํ†ตํ•œ ๋ ˆ์‹œํ”ผ ๊ฒ€์ƒ‰๊ธฐ๋Šฅ, ์ž์œ ๊ฒŒ์‹œํŒ ๋“ฑ์„ ๋งŒ๋“ค์–ด ์ตœ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ์ž‘ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

์–ด์„œ ์‹ค์‹œ๊ฐ„์œผ๋กœ ์ธ๊ธฐ์žˆ๋Š” ๋ ˆ์‹œํ”ผ, ํ˜น์€ ๊ถ๊ธˆํ•œ ๋ ˆ์‹œํ”ผ๋ฅผ ๊ฒ€์ƒ‰ํ•ด๋ณด์„ธ์š”! ๋งŒ์•ฝ ํšŒ์›๊ฐ€์ž…์„ ํ•˜์‹œ๋ฉด ๋ƒ‰์žฅ๊ณ  ํŽ˜์ด์ง€์—์„œ ์‹์žฌ๋ฃŒ์˜ ์œ ํ†ต๊ธฐํ•œ์„ ํ‘œ์‹œํ•  ์ˆ˜์žˆ๊ณ , Refri Bank๋Š” ๋ƒ‰์žฅ๊ณ ์— ๋“ค์–ด์žˆ๋Š” ์‹์žฌ๋ฃŒ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํ•˜์—ฌ ์ถ”์ฒœ ๋ ˆ์‹œํ”ผ๋ฅผ ์ œ๊ณตํ•ด์ค๋‹ˆ๋‹ค.

2๏ธโƒฃ Technology stack

3๏ธโƒฃ Trouble

๐Ÿ”“ Communication
๐Ÿ”‘ ๋ชจ๋“  ํŒ€์›๋“ค์ด ํ˜‘์—… ๊ฒฝํ—˜์ด ๋‹จ ํ•œ๋ฒˆ๋„ ์กด์žฌํ•˜์ง€ ์•Š์•„, trouble์ด ์ž์ฃผ ๋ฐœ์ƒํ•˜์˜€๋‹ค.
๋ณ€์ˆ˜๋ช… ๊ทœ์น™์„ ์ง€ํ‚ค์ง€ ์•Š๊ฑฐ๋‚˜, git collision์ด ๋งค์šฐ ์ž์ฃผ ๋ฐœ์ƒํ•˜์˜€๊ณ , ํ”„๋กœ์ ํŠธ ๋งˆ๊ฐ ์ผ์ž๊ฐ€ ๋‹ค๊ฐ€์˜ฌ ์ˆ˜๋ก ์„œ๋กœ ๋งŽ์ด ๋‹คํˆฌ๊ธฐ๋„ ํ•˜์˜€๋‹ค.
๋‹คํˆด์ˆ˜๋Š” ์žˆ์œผ๋‚˜, ๊ฐ์ •์ด ์ƒํ•ด ์•ž์œผ๋กœ์˜ ์ž‘์—…์— ์˜ํ–ฅ์„ ์ฃผ๋Š” ๊ฒƒ์€ ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜์žˆ์—ˆ๊ธฐ์—, ๋‚˜๋Š” ํ•˜๋ฃจ์˜ ์ž‘์—…์ด ๋๋‚˜๊ณ  ๊ฐ์ž ๋‹ค๋ฅธ ํŒ€์›๋“ค์„ ์นญ์ฐฌํ•˜๋Š” ์นญ์ฐฌํ•˜๋Š” ์‹œ๊ฐ„์„ ๋งŒ๋“ค์—ˆ๊ณ , ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ฌด์‚ฌํžˆ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งˆ์น  ์ˆ˜์žˆ์—ˆ๋‹ค.

๐Ÿ”“ Crawling
๐Ÿ”‘ ํ•ด๋จน๋‚จ๋…€๋ผ๋Š” ์‚ฌ์ดํŠธ์—์„œ Crawling์„ ํ—ˆ์šฉํ•˜์—ฌ ํ•ด๋จน๋‚จ๋…€ ์‚ฌ์ดํŠธ๋ฅผ Crawling ํ•˜์˜€๋‹ค.

image

ํ•ด๋จน๋‚จ๋…€ ์‚ฌ์ดํŠธ๋Š” ๋ ˆ์‹œํ”ผ์— ๋Œ€ํ•œ ๋งŽ์€ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š”๋ฐ, ์šฐ๋ฆฌ๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋Š” ๋‹จ์ˆœํ–ˆ๋‹ค. ์žฌ๋ฃŒ, Kcal, ์กฐ๋ฆฌ ์‹œ๊ฐ„, ๋ ˆ์‹œํ”ผ ์ •๋ณด๋“ค์ด์˜€๋‹ค. Crawling์„ ๋‹ด๋‹นํ–ˆ๋˜ ์นœ๊ตฌ๊ฐ€ Crawling Logic์„ ๊ณ ๋ฏผํ•˜๊ณ  ์žˆ์—ˆ๊ณ , ๋‚˜๋Š” ์žฌ๊ท€๋ฌธ์„ ์ž‘์„ฑํ•˜์—ฌ ์ •์ƒ์ ์œผ๋กœ ์›ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋งŒ ๋ฝ‘์•„์˜ฌ ์ˆ˜์žˆ์—ˆ๋‹ค.

image
image

์ด ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ Recipe PK์— ๋”ฐ๋ฅธ REST API๋ฅผ ์ „์†กํ•ด์ฃผ์—ˆ๋‹ค.

๐Ÿ”“ GetRecipe Method
๐Ÿ”‘ ์•„๋ž˜์˜ ํ™”๋ฉด์—์„œ ๋ณด์ด๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด์ฃผ๊ธฐ ์œ„ํ•ด ๋ชจ๋“  Recipe๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” Method๊ฐ€ ํ•„์š”ํ–ˆ๊ณ , Method์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์ด ํ•„์š”ํ–ˆ๋‹ค.

image Method์™€ ์‚ฌ์šฉ๋œ query๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

const mainpage_request = {
  GetFoodMain : async (req,res)=>{
      const req_get_foodmain = new MainClass(req.body);
      const res_get_foodmain = await req_get_foodmain.GetFoodMain();
      return res.json(res_get_foodmain);
  }
}
class MainSql {
  static async GetFoodMain(req) {
      return new Promise((resolve, reject) => {
          const query = "SELECT * FROM FoodMain WHERE FoodN LIKE '%"+req.id+"%' ORDER BY likeit DESC";
          db.query(query ,(err, data) => {
              if (err) reject(`${err}`)
              resolve(data);
          });
      });
  }
}

ํ•œ๋ฒˆ์— ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ์— ๊ต‰์žฅํžˆ ๋น„ํšจ์œจ์ ์ฒ˜๋Ÿผ ๋ณด์ธ๋‹ค. ํ•˜์ง€๋งŒ, ๋ฐ์ดํ„ฐ๊ฐ€ ๊ทธ๋ฆฌ ๋งŽ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์‚ฐ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•˜์—ฌ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š” query๋ฌธ์„ ์ž‘์„ฑํ•˜์˜€๋‹ค.

๐Ÿ”“ Like Method
๐Ÿ”‘ ์•„๋ž˜์˜ ํ™”๋ฉด์„ ๋ณด๋ฉด, ๋ ˆ์‹œํ”ผ๋ณ„๋กœ ์ข‹์•„์š”๊ฐ€ ๋งŽ์€ ์ˆœ์„œ๋Œ€๋กœ ์ถ”์ฒœ ๋ ˆ์‹œํ”ผ๋ฅผ ๋ณด์—ฌ์ค€๋‹ค. ์ด๋ฅผ์œ„ํ•ด, ๋ ˆ์‹œํ”ผ์— ์ข‹์•„์š”๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜์žˆ๋Š” ๋ฒ„ํŠผ์ด ํ•„์š”ํ–ˆ๊ณ , ์ด ๊ฐ’์„ DB์— ์ €์žฅํ•ด์•ผ ํ–ˆ๋‹ค.

image
Like Method์— ๋Œ€ํ•œ ์š”๊ตฌ ์‚ฌํ•ญ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  1. Like button์— ๋Œ€ํ•œ ์ทจ์†Œ๋Š” ๋‹ค๋ฅธ ํŽ˜์ด์ง€์—์„œ ์ง„ํ–‰ํ•  ์ˆ˜์žˆ์Œ
  2. ํŠน์ • Recipe์— Like๋ฅผ ๋ˆ„๋ฅธ User๋Š” ๋˜ Like๋ฅผ ๋ˆ„๋ฅผ ์ˆ˜์—†์Œ

User์™€ Recipe๋Š” N:N ๊ด€๊ณ„์ด๋‹ค. ๋”ฐ๋ผ์„œ DB ๊ตฌ์กฐ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ์„ฑํ•˜์˜€๋‹ค.
image N : 1, 1 : N์œผ๋กœ ๊ด€๊ณ„๋ฅผ ํ’€์–ด ํŠน์ • Recipe์— ์ข‹์•„์š”๋ฅผ ๋ˆ„๋ฅธ User ์ •๋ณด๋ฅผ ๊ด€๋ฆฌํ•˜์˜€๋‹ค.
์ด๋•Œ ์‚ฌ์šฉ๋œ Method์™€ query๋Š” ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

const recipe_request = {
  AddLike : async (req, res) => {
      const req_add_like = new RecipeClass(req.body);
      const res_add_like = await req_add_like.AddLike();
      return res.json(res_add_like);
  }
}

class RecipeSql {
  static async AddLike(req) {
      return new Promise((resolve, reject) => {
          const squery = "SELECT * FROM likeit WHERE userid = (?) and foodid = (?) ";
          const lquery = "UPDATE FoodMain SET likeit = likeit+1 WHERE FoodId = (?);";
          const uquery = "INSERT INTO likeit(foodid, userid, foodname) VALUES(?, ?, ?);";
          db.query(squery, [req.userid, req.id], (err, length) => {
              if (err) reject(`${err}`);
              else if (length.length < 1) {
                  db.query(lquery, [req.id], (err, data) => {
                      if (err) reject(`${err}`);
                      else {
                          db.query(uquery, [req.id, req.userid, req.foodname], (err, check) => {
                              if (err) reject(`${err}`);
                              resolve({ success: true });
                          })
                      }
                  });
              }
              else {
                  resolve({ success: false })
              }
          });
      });
  }
}

๐Ÿ”“ shopping basket method.
๐Ÿ”‘ ์•„๋ž˜์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด User๊ฐ€ ์žฌ๋ฃŒ๋ฅผ ์„ ํƒํ•˜์—ฌ ๋‚˜๋งŒ์˜ ๋ƒ‰์žฅ๊ณ ์— ๋„ฃ์„ ์ˆ˜์žˆ๋‹ค.

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2022-04-07 แ„‹แ…ฉแ„’แ…ฎ 12 12 37

์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ์žฌ๋ฃŒ๋ฅผ ๋„ฃ์€ ๋’ค, submit button์„ ๋ˆ„๋ฅด๋ฉด, ์ด ์žฌ๋ฃŒ์— ๋”ฐ๋ผ ๋ ˆ์‹œํ”ผ๋ฅผ ์ถ”์ฒœํ•ด์ค€๋‹ค.
submit button์„ ๋ˆ„๋ฅด๋ฉด, User๊ฐ€ ์ถ”๊ฐ€ํ•œ Ingredient๊ฐ€ Update ๋˜์•ผ ํ•˜๊ณ , ์‚ฌ์šฉํ•œ ์ฟผ๋ฆฌ๋ฌธ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

static async UpdateRFG(user) {
      return new Promise(async (resolve, reject) => {
          const delete_query = "DELETE FROM UserRfg WHERE ID=(?)";
          const insert_query = "INSERT INTO UserRfg(ID, Igdname, Eprdate) VALUES(?, ?, ?);";
          db.query(delete_query, [user.id], (err) => {
              if (err) reject(`${err}`);
              else {
                  db.query(insert_query, [user.id, user.igdname, user.eprdate], (err) => {
                      if (err) reject(`${err}`);
                      else resolve({ success: true });
                  });
              }
          });
      });
  }

UserRfg๋Š” User๊ฐ€ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” Ingredient์— ๋Œ€ํ•œ Table์ด๋‹ค. ์—ฌ๊ธฐ์„œ ๊ธฐ์กด์— UserRfg์— ์ €์žฅํ•˜๊ณ  ์žˆ๋Š” Ingredient๋ฅผ ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ์ €์žฅํ•˜๊ณ , ๊ธฐ์กด์— ์ €์žฅํ•˜๊ณ  ์žˆ๋˜ Ingredient๋Š” ์ „๋ถ€ DELETEํ•œ๋‹ค. ๊ทธํ›„, ํ˜„์žฌ ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ๋“ค์–ด์žˆ๋Š” Ingredient๋ฅผ ๋‹ค์‹œ UserRfg์— ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•˜์˜€๋‹ค.

Ingredient์— ๋”ฐ๋ผ Recipe๋ฅผ ์ถ”์ฒœํ•ด์ฃผ๊ธฐ ์œ„ํ•œ Ingredient๊ฐ€ ํ•„์š”ํ–ˆ๋Š”๋ฐ, ์žฅ๋ฐ”๊ตฌ๋‹ˆ์— ๋“ค์–ด์žˆ๋Š” ๋žœ๋คํ•œ Ingredient 1๊ฐœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ถ”์ฒœํ•˜์˜€๋‹ค.
์‚ฌ์šฉํ•œ ์ฟผ๋ฆฌ๋ฌธ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 class RfgSql {

  static async GetIgdrc(req) {
      return new Promise((resolve, reject) => {
          const query = "SELECT * FROM FoodMain WHERE FoodId IN (SELECT  FoodId FROM FoodIgd WHERE IgdN1 LIKE '%" + req.igd + "%' OR  IgdN2 LIKE '%" + req.igd + "%' OR  IgdN3  LIKE '%" + req.igd + "%' OR  IgdN4  LIKE '%" + req.igd + "%'  OR  IgdN5  LIKE '%" + req.igd + "%' OR  IgdN6  LIKE '%" + req.igd + "%' OR  IgdN7  LIKE '%" + req.igd + "%' OR  IgdN8  LIKE '%" + req.igd + "%' OR  IgdN9  LIKE '%" + req.igd + "%' OR  IgdN10  LIKE '%" + req.igd + "%' OR  IgdN11  LIKE '%" + req.igd + "%' OR  IgdN12  LIKE '%" + req.igd + "%' OR  IgdN13  LIKE '%" + req.igd + "%' OR  IgdN14  LIKE '%" + req.igd + "%' OR  IgdN15 LIKE '%" + req.igd + "%')"
          db.query(query, (err, data) => {
              if (err) reject(`${err}`);
              resolve(data);
          });
      });
  }
}

์ฟผ๋ฆฌ๋ฌธ์„ ํ•˜๋“œ์ฝ”๋”ฉ ํ•˜์˜€๋‹ค. ๋ชจ๋“  ๋ ˆ์‹œํ”ผ๋Š” Ingredient๊ฐœ์ˆ˜๊ฐ€ ๋‹ฌ๋ž๋‹ค. ์–ด๋–ค ๊ฒƒ์€ 30๊ฐœ๊ฐ€ ๋„˜์–ด๊ฐ€๊ธฐ๋„ ํ•˜๊ณ  ์–ด๋–ค๊ฒƒ์€ 10๊ฐœ ์ดํ•˜์ด๊ธฐ๋„ ํ–ˆ๋‹ค. ๋”ฐ๋ผ์„œ Crawling์„ ์ง„ํ–‰ํ• ๋•Œ Ingredient๋ฅผ ์ตœ๋Œ€ 15๊ฐœ๋งŒ ๊ฐ€์ ธ์˜ค๊ธฐ๋กœ ๊ฒฐ์ •ํ•˜์˜€๊ณ , Ingredient Column์€ 15๋กœ ๊ณ ์ •์ด ๋˜์—ˆ์œผ๋ฉฐ, ๊ฒฐ๊ณผ๋ฌผ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

image

๐Ÿ”“ Recipe Likeit Method
๐Ÿ”‘ ์•„๋ž˜์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด User๋Š” Likeit button์„ ๋ˆ„๋ฅธ ๋ ˆ์‹œํ”ผ๋ฅผ ๋ณผ ์ˆ˜์žˆ๋‹ค.

image

Recipe์™€ User๋Š” N:N ๊ด€๊ณ„์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ํ’€์–ด๋‚ธ Likeit table์„ ์ด์šฉํ•˜์—ฌ ์ด๋ฅผ ๊ตฌํ˜„ํ•˜์˜€์œผ๋ฉฐ, ์‚ญ์ œ method๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ด๋‹ค. ์‚ฌ์šฉํ•œ ์ฟผ๋ฆฌ๋ฌธ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

static async Deletelikeit(req) {
      return new Promise((resolve, reject) => {
          const delete_likeit = "DELETE FROM likeit WHERE foodid=(?) and userid=(?);"
          db.query(delete_likeit, [req.number, req.userid], (err, length) => {
              if (err) reject(`${err}`);
              else {
                  resolve({ success: true })
              }
          })
      });
  }
}
class Mypagesql {
  static async likeitpage(user){
      return new Promise(async (resolve, reject) => {
          const query = "SELECT * FROM likeit WHERE userid = (?)"
          db.query(query,[user.id], (err,data) => {
              if (err) reject(`${err}`);
              else resolve({data});
          });
      });
  }
}

๐Ÿ”“ Board
๐Ÿ”‘ Board ๊ธฐ๋Šฅ์€ ๋‹จ์ˆœ CRUD๋งŒ์œผ๋กœ ๊ตฌํ˜„ํ•˜์˜€๊ณ , ๋Œ“๊ธ€์€ board_id, user_id๋ฅผ ์ €์žฅํ•˜๋Š” Reply table์„ ๊ตฌ์„ฑํ•˜์—ฌ N:N ๊ด€๊ณ„๋ฅผ ํ’€์–ด๋ƒˆ๋‹ค.
๊ฒฐ๊ณผ๋ฌผ๊ณผ ์‚ฌ์šฉํ•œ ์ฟผ๋ฆฌ๋ฌธ๋“ค์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

image

////////Reply////////
  static async AddReply(req) {
      console.log(req);
      return new Promise((resolve, reject) => {
          const query = "INSERT INTO Reply(number, userid, nickname, description, created) VALUES(?, ?, ?, ?, ?);"
          const ucount = "UPDATE freeboard SET count = count + 1 WHERE number =(?);"
          db.query(query, [req.number, req.userid, req.nickname, req.description, req.created], (err, data) => {
              console.log(req.created)
              if (err) reject(`${err}`);
              db.query(ucount, [req.number], (err) => {
                  if (err) reject(`${err}`);
                  resolve(data);
              });

          });
      });
  }

  static async GetReply(req) {
      return new Promise((resolve, reject) => {
          const query = "SELECT * FROM Reply WHERE number=(?);"
          db.query(query, [req], (err, data) => {
              if (err) reject(`${err}`);
              resolve(data);
          });
      });
  }

4๏ธโƒฃ What I learned

  1. communication
    ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ ๋‚˜์˜ ์ฃผ์žฅ์„ ํŽผ์น˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๊ทผ๊ฑฐ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์„ ๋ฐฐ์šฐ๊ฒŒ ๋˜์—ˆ๋‹ค.
  2. SQL ์ค‘์‹ฌ์ ์ธ ๊ฐœ๋ฐœ์˜ ๋ฌธ์ œ์ 
    ์ด ํ”„๋กœ์ ํŠธ๋Š” SQL์— ๊ต‰์žฅํžˆ ์˜์กด์ ์ด๋‹ค. ์ด๋•Œ SQL ์ค‘์‹ฌ์ ์ธ ๊ฐœ๋ฐœ์˜ ๋ฌธ์ œ์ ์„ ๋Š๋ผ๊ฒŒ ๋˜์—ˆ๊ณ , ํ›„์— ORM์„ ๊ณต๋ถ€ํ•˜๋ฉด์„œ ์ด์—๋Œ€ํ•ด ๋ธ”๋กœ๊ทธ์— ์ •๋ฆฌํ•˜์˜€๋‹ค.
    https://blog.naver.com/ds4ouj/222682683072
  3. ํšจ์œจ์„ฑ
    ํŠธ๋ž˜ํ”ฝ์„ ์ƒ๊ฐํ•˜์ง€ ์•Š๊ณ , ์„œ๋ฒ„ ๊ฐœ๋ฐœ์„ ํ–ˆ๋‹ค๋Š” ๋ฌธ์ œ์ ์„ ์•Œ๊ฒŒ๋˜์—ˆ๋‹ค.