2023.03.23 TIL

์ •์Šน์›ยท2023๋…„ 3์›” 28์ผ
0
post-thumbnail
post-custom-banner

๐Ÿ“’ ๋ชฉ์ฐจ

๐Ÿ“Œ ๋ชจ๋ธ ์ •์˜ํ•˜๊ธฐ
๐Ÿ“Œ GET ๋ฐ์ดํ„ฐ ์กฐํšŒ
๐Ÿ“Œ POST ๋ฐ์ดํ„ฐ ๋“ฑ๋ก
๐Ÿ“Œ mongoose์˜ debug
๐Ÿ“Œ ddocker-compose์˜ volumes
๐Ÿ“Œ ์Šคํฌ๋ž˜ํ•‘ & ํฌ๋กค๋ง

๐Ÿ“Œ ๋ชจ๋ธ ์ •์˜ํ•˜๊ธฐ

โœ… model ๋งŒ๋“ค๊ธฐ

model์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ mongodb์— ์ €์žฅ๋˜๋Š” data ๊ตฌ์กฐ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ JSON ํ˜•ํƒœ๋กœ ์ €์žฅํ•œ ๊ฒƒ์ด๋‹ค.

model์— ์ž‘์„ฑํ•œ ๊ตฌ์กฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋ฐ์ดํ„ฐ๋ฅผ ์•Œ๋งž๊ฒŒ ์ €์žฅํ•œ๋‹ค.

// board.model.js

import mongoose from 'mongoose' // mongoose ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

// mongoose ์Šคํ‚ค๋งˆ๋Š” mongodb์— ์ €์žฅ๋˜๋Š” document data ๊ตฌ์กฐ์— ๊ด€ํ•œ ์ •๋ณด๋ฅผ JSON ํ˜•ํƒœ๋กœ ์ •์˜ํ•œ ๊ฒƒ
const boardSchema = new mongoose.Schema({
    writer: String,
    title: String,
    contents: String
})

export const Board = mongoose.model("Board", boardSchema)
// ์™ธ๋ถ€์—์„œ ์ ‘์†ํ•  ์ˆ˜ ์žˆ๋„๋ก exportํ•˜๊ธฐ

๐Ÿ“Œ GET ๋ฐ์ดํ„ฐ ์กฐํšŒ

result์— ๋‚ด์šฉ์„ ๋‹ด์•„ ์‘๋‹ต์œผ๋กœ ๋‚ด๋ณด๋‚ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

  • find() : ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค
  • findOne() : ํŠน์ • ๋ฐ์ดํ„ฐ๋งŒ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.
// index.js

import { Board } from './models/board.model.js' // index.js ํŒŒ์ผ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

const app = express()
app.use(cors())
app.use(express.json())
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerJsdoc(options)));
app.get('/boards', async (req, res) => {
  // 1. ๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” ๋กœ์ง => DB์— ์ ‘์†ํ•ด์„œ ๋ฐ์ดํ„ฐ ๊บผ๋‚ด์˜ค๊ธฐ
  const result = await Board.find()
  // find() : ๋ชจ๋“  ๋ฐ์ดํ„ฐ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉ,
  // findOne() : ํŠน์ • ๋ฐ์ดํ„ฐ๋งŒ ์กฐํšŒํ•  ๋•Œ ์‚ฌ์šฉ

  // 2. ๊บผ๋‚ด์˜จ ๊ฒฐ๊ณผ ์‘๋‹ต ์ฃผ๊ธฐ
  res.send(result)
})

๐Ÿ“Œ POST ๋ฐ์ดํ„ฐ ๋“ฑ๋ก

POST ์š”์ฒญ์„ ๋ฐ›์•˜์„ ๋•Œ, JSON ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์€ BODY์—์„œ ๊ฐ๊ฐ์˜ ์š”์†Œ๋ฅผ ํ•˜๋‚˜์”ฉ ๋นผ์™€ ์—ฐ๊ฒฐํ•ด ๋†“์€ mongodb์˜ boards collection์— ์ €์žฅํ•œ๋‹ค.

//index.js

app.post('/boards', async (req, res) => {
  console.log(req.body);

  // 1. ๋ฐ์ดํ„ฐ๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๋กœ์ง => DB์— ์ ‘์†ํ•ด์„œ ๋ฐ์ดํ„ฐ ์ €์žฅํ•˜๊ธฐ
  const board = new Board({
    writer: req.body.writer,
    title: req.body.title,
    contents: req.body.contents,
  });
  await board.save();

  // 2. ์ €์žฅ ๊ฒฐ๊ณผ ์‘๋‹ต ์ฃผ๊ธฐ
  res.send('๊ฒŒ์‹œ๋ฌผ ๋“ฑ๋ก์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค!!');
});

๐Ÿ“Œ mongoose์˜ debug

mongoose.set("debug", true)๋ฅผ ํ•˜๊ฒŒ ๋˜๋ฉด mongoose์— ๋Œ€ํ•œ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด, ๋””๋ฒ„๊น…์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค.

๋กœ๊ทธ๋ฅผ ํ†ตํ•ด db์— ์ €์žฅ๋˜๋Š” query๋ฌธ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

// index.js

// ์ƒ๋žต...

mongoose.set("debug", true) // ์ถ”๊ฐ€

// ๋ชฝ๊ณ DB ์ ‘์†!!
mongoose.connect("mongodb://my-database:27017/mydocker10")
  .then(() => console.log("db ์ ‘์†์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค."))
  .catch(() => console.log("db ์ ‘์†์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค."))

app.listen(4000, () => {
  console.log("๋ฐฑ์—”๋“œ API ์„œ๋ฒ„๊ฐ€ ์ผœ์กŒ์–ด์š”!!!")
})

๐Ÿ“Œ docker-compose์˜ volumes

docker-compose์˜ volumes๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด, ๋กœ์ปฌ์˜ ํŒŒ์ผ ๋‚ด์šฉ์„ ๋ณ€๊ฒฝํ•˜๋”๋ผ๋„ docker๋‚ด์˜ ํŒŒ์ผ์€ ๋ณ€๊ฒฝ๋˜์ง€
์•Š๋Š”๋‹ค.

๋”ฐ๋ผ์„œ ์•„๋ž˜์˜ ๋‘ ๋‘๊ฐ€์ง€ ์„ค์ •์„ ์™„๋ฃŒํ•˜๊ฒŒ ๋˜๋ฉด ๋„์ปค๋‚ด์—์„œ๋„ ๋งค๋ฒˆ build๋ฅผ ํ•˜์ง€ ์•Š๊ณ  ๋ณ€๊ฒฝ๋œ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

vlumes๋ฅผ ํ†ตํ•ด ๋กœ์ปฌ์˜ ์†Œ์Šค์ฝ”๋“œ์™€ ๋„์ปค๋‚ด์˜ ์†Œ์Šค์ฝ”๋“œ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. ๋กœ์ปฌ์—์„œ ์†Œ์Šค์ฝ”๋“œ ๋ณ€๊ฒฝํ•˜๋ฉด, docker๋‚ด์—๋„ ์ ์šฉํ•˜๊ธฐ
  2. docker๋‚ด์—์„œ nodemon์œผ๋กœ ์‹คํ–‰์‹œํ‚ค๊ธฐ
version: '3.7'

# ์ปดํ“จํ„ฐ๋“ค
services:

  # ์ปดํ“จํ„ฐ์ด๋ฆ„
  my-backend:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./index.js:/myfolder/index.js
      - ./email.js:/myfolder/email.js
    ports:
      - 4000:4000


  # ์ปดํ“จํ„ฐ์ด๋ฆ„
  my-database:
    image: mongo:5
    ports:
      - 27017:27017

๐Ÿ“Œ ์Šคํฌ๋ž˜ํ•‘ & ํฌ๋กค๋ง

โœ… ์Šคํฌ๋ž˜ํ•‘

ํŠน์ •ํ•œ ์›น ์‚ฌ์ดํŠธ์—์„œ ํ•ด๋‹น ์‚ฌ์ดํŠธ์˜ HTML์„ ๊ธ์–ด์˜ค๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜์™€ ๊ฐ™์ด ๋งํฌ๋ฅผ ๊ณต์œ ํ•˜๋ฉด ๋ฐ‘์— ์ž๋™์œผ๋กœ ์‚ฌ์ดํŠธ์˜ ์†Œ๊ฐœ์™€ ์ด๋ฏธ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

์œ ์ €๊ฐ€ ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ•ด์„œ ๋“ฑ๋กํ•  ๋•Œ, ๋ฐฑ์—”๋“œ API๋กœ ๊ธ€์˜ ๋‚ด์šฉ์„ ๋ณด๋‚ด์ฃผ๊ฒŒ๋œ๋‹ค. ์ด๋•Œ, ๊ธ€์˜ ๋‚ด์šฉ์— http๊ฐ€ ํฌํ•จ๋œ

URL์ด ์žˆ๋‹ค๋ฉด, ๊ทธ ์‚ฌ์ดํŠธ์— ์ ‘์†ํ•ด์„œ open graph๊ฐ€ ์žˆ๋Š” ๋‚ด์šฉ์„ ๊ธ์–ด์™€์„œ ์ €์žฅํ•œ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด,

๋‚˜์ค‘์— ๊ธ€์˜ ์ƒ์„ธ๋ณด๊ธฐ๋ฅผ ํ•  ๋•Œ, ์œ„์˜ ๋„ค์ด๋ฒ„ ์˜ˆ์‹œ์ฒ˜๋Ÿผ ์‚ฌ์ดํŠธ ์†Œ๊ฐœ๋ฅผ ๊ฐ™์ด ๋ณด์—ฌ์ฃผ๊ฒŒ ๋œ๋‹ค.

๋„ค์ด๋ฒ„์˜ ํŽ˜์ด์ง€๋ฅผ ํ™•์ธํ•ด๋ณด๋ฉด, <head> ํƒœ๊ทธ ์•ˆ์— meta ํƒœ๊ทธ๋“ค์ด ์žˆ๊ณ , ๊ทธ ์ค‘์—์„œ property๊ฐ€ og๋กœ ์‹œ์ž‘ํ•˜๋Š” ํƒœ๊ทธ๋“ค์ด ์žˆ๋‹ค.

//index.js

import axios from 'axios'
import cheerio from 'cheerio'

const createMessage = async () => {
    // ์ž…๋ ฅ๋œ ๋ฉ”์‹œ์ง€: "์•ˆ๋…•ํ•˜์„ธ์š”~ https://www.naver.com ์— ๋ฐฉ๋ฌธํ•ด ์ฃผ์„ธ์š”!"

    // 1. ์ž…๋ ฅ๋œ ๋ฉ”์‹œ์ง€์—์„œ http๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฌธ์žฅ์ด ์žˆ๋Š”์ง€ ๋จผ์ € ์ฐพ๊ธฐ!(.find() ๋“ฑ์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์‚ฌ์šฉํ•˜๊ธฐ)
    const url = "https://www.daum.net"

    // 2. axios.get์œผ๋กœ ์š”์ฒญํ•ด์„œ html์ฝ”๋“œ ๋ฐ›์•„์˜ค๊ธฐ => ์Šคํฌ๋ž˜ํ•‘
    const result = await axios.get(url)
    console.log(result.data)

    // 3. ์Šคํฌ๋ž˜ํ•‘ ๊ฒฐ๊ณผ(result)์—์„œ OG(์˜คํ”ˆ๊ทธ๋ž˜ํ”„) ์ฝ”๋“œ ๊ณจ๋ผ๋‚ด์„œ ๋ณ€์ˆ˜์— ์ €์žฅํ•˜๊ธฐ
    const $ = cheerio.load(result.data)
    $("meta").each((i, el) => {
        if($(el).attr("property") && $(el).attr("property").includes("og:")){
            const key = $(el).attr("property") // og:title, og:description, ...
            const value = $(el).attr("content") // ๋„ค์ด๋ฒ„, ๋„ค์ด๋ฒ„ ๋ฉ”์ธ์—์„œ ~~~
            console.log(key, value)
        }
    })

}

createMessage()

โœ… ํฌ๋กค๋ง

ํฌ๋กค๋ง์€ ์Šคํฌ๋ž˜ํ•‘์„ ์ •๊ธฐ์ ์œผ๋กœ ์ฃผ๊ธฐ์ ์œผ๋กœ ์—ฌ๋Ÿฌ๋ฒˆํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.


๐ŸŒˆ ์˜ค๋Š˜ ํ•˜๋ฃจ

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

post-custom-banner

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