Unit10 - [Web Server] ๊ธฐ์ดˆ - 2

๊ฐ•์„ฑ์ผยท2023๋…„ 6์›” 2์ผ
0
post-thumbnail

โœ… TIL


์˜ค๋Š˜์€ ์–ด์ œ ๋งŒ๋“  mini-node server๋ฅผ ๊ณต์‹ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ, express๋กœ ๋ฆฌํŒฉํ† ๋งํ•ด๋ณผ ์˜ˆ์ •์ด๋‹ค - Express ๊ณต์‹ ๋ฌธ์„œ


Refactor Express


MERN stack์€ JS ์ƒํƒœ๊ณ„์—์„œ ์ธ๊ธฐ ์žˆ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์ธ MongoDB, Express, React, Node.js๋ฅผ ์ง€์นญํ•œ๋‹ค.
์ด ์ค‘์—์„œ Express๋Š” Node.js ํ™˜๊ฒฝ์—์„œ ์›น ์„œ๋ฒ„, ๋˜๋Š” API ์„œ๋ฒ„๋ฅผ ์ œ์ž‘ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ์ธ๊ธฐ ์žˆ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ๋‹ค.

Express๋กœ ๊ตฌํ˜„ํ•œ ์„œ๋ฒ„๊ฐ€ Node.js HTTP ๋ชจ๋“ˆ๋กœ ์ž‘์„ฑํ•œ ์„œ๋ฒ„์™€ ๋‹ค๋ฅธ ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ผ์šฐํ„ฐ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.


Express ์‹œ์ž‘ํ•˜๊ธฐ


1. Express ์„ค์น˜

npm install express

2. ๊ฐ„๋‹จํ•œ ์›น ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

3. ๋ผ์šฐํŒ…: ๋ฉ”์„œ๋“œ์™€ url์— ๋”ฐ๋ผ ๋ถ„๊ธฐ(Routing)ํ•˜๊ธฐ

๋ฉ”์„œ๋“œ์™€ url(/lower, /upper ๋“ฑ)๋กœ ๋ถ„๊ธฐ์ ์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ๋ผ์šฐํŒ…(Routing)์ด๋ผ๊ณ  ํ•œ๋‹ค.

ํด๋ผ์ด์–ธํŠธ๋Š” HTTP ์š”์ฒญ ๋ฉ”์„œ๋“œ(GET, POST ๋“ฑ)์™€ ํ•จ๊ป˜ ์„œ๋ฒ„์˜ ํŠน์ • URI(๋˜๋Š” ๊ฒฝ๋กœ)๋กœ HTTP ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
๋ผ์šฐํŒ…์€ ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์— ํ•ด๋‹นํ•˜๋Š” Endpoint์— ๋”ฐ๋ผ ์„œ๋ฒ„๊ฐ€ ์‘๋‹ตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ถ”๊ฐ€์ ์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , ์ˆœ์ˆ˜ํ•œ Node.js๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.


const requestHandler = (req, res) => {
  if(req.url === '/lower') {
    if (req.method === 'GET') {
      res.end(data)
    } else if (req.method === 'POST') {
      req.on('data', (req, res) => {
        // do something ...
      })
    }
  }
}

๋ฐ˜๋ฉด์— Express๋Š” ํ”„๋ ˆ์ž„์›Œํฌ ์ž์ฒด์—์„œ ๋ผ์šฐํ„ฐ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.
Express์˜ ๋ผ์šฐํ„ฐ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ง๊ด€์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

const router = express.Router()

router.get('/lower', (req, res) => {
  res.send(data);
})

router.post('/lower', (req, res) => {
  // do something
})


Middleware 1

์ž๋™์ฐจ ๊ณต์žฅ์—์„œ๋Š” ์ปจ๋ฒ ์ด์–ด ๋ฒจํŠธ ์œ„์— ์˜ฌ๋ ค์ง„ ์ž๋™์ฐจ์˜ ๋ผˆ๋Œ€์—, ๊ณต์ •๋งˆ๋‹ค ๋ถ€ํ’ˆ์„ ์ถ”๊ฐ€ํ•œ๋‹ค.
๋ชจ๋“  ๋ถ€ํ’ˆ์ด ์ถ”๊ฐ€๋˜๋ฉด ์™„์„ฑ๋œ ์ž๋™์ฐจ๊ฐ€, ์–ด๋”˜๊ฐ€ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ถˆ๋Ÿ‰ํ’ˆ์ด ๊ฒฐ๊ณผ๋ฌผ๋กœ ๋‚˜์˜ค๊ฒŒ ๋œ๋‹ค.

๋ฏธ๋“ค์›จ์–ด(Middleware)๋Š” ์ž๋™์ฐจ ๊ณต์žฅ์˜ ๊ณต์ •๊ณผ ๋น„์Šทํ•˜๋‹ค.
์ปจ๋ฒ ์ด์–ด ๋ฒจํŠธ ์œ„์— ์˜ฌ๋ผ๊ฐ€ ์žˆ๋Š” ์š”์ฒญ(Request)์— ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์„ ๋”ํ•˜๊ฑฐ๋‚˜, ๋ถˆ๋Ÿ‰ํ’ˆ์„ ๋ฐ–์œผ๋กœ ๊ฑท์–ด๋‚ด๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

๋ฏธ๋“ค์›จ์–ด๋Š” express์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.



์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด


๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ƒํ™ฉ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. POST ์š”์ฒญ ๋“ฑ์— ํฌํ•จ๋œ body(payload)๋ฅผ ๊ตฌ์กฐํ™”ํ•  ๋•Œ(์‰ฝ๊ฒŒ ์–ป์–ด๋‚ด๊ณ ์ž ํ•  ๋•Œ)
  2. ๋ชจ๋“  ์š”์ฒญ/์‘๋‹ต์— CORS ํ—ค๋”๋ฅผ ๋ถ™์—ฌ์•ผ ํ•  ๋•Œ
  3. ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด url์ด๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ™•์ธํ•  ๋•Œ
  4. ์š”์ฒญ ํ—ค๋”์— ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์žˆ๋Š”์ง€ ํ™•์ธํ•  ๋•Œ

๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ด์šฉํ•˜๋ฉด Node.js ๋งŒ์œผ๋กœ ๊ตฌํ˜„ํ•œ ์„œ๋ฒ„์—์„œ๋Š” ๋ฒˆ๊ฑฐ๋กœ์šธ ์ˆ˜ ์žˆ๋Š” ์ž‘์—…์„ ๋ณด๋‹ค ์‰ฝ๊ฒŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.


case 1: POST ์š”์ฒญ ๋“ฑ์— ํฌํ•จ๋œ body(payload)๋ฅผ ๊ตฌ์กฐํ™”ํ•  ๋•Œ

// Node.js๋กœ HTTP ์š”์ฒญ body๋ฅผ ๋ฐ›๋Š” ์ฝ”๋“œ

let body = [];
request.on('data', (chunk) => {
  body.push(chunk);
}).on('end', () => {
  body = Buffer.concat(body).toString();
  // body ๋ณ€์ˆ˜์—๋Š” ๋ฌธ์ž์—ด ํ˜•ํƒœ๋กœ payload๊ฐ€ ๋‹ด๊ฒจ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.
});

// express.json()์„ ์ด์šฉํ•œ ์ฝ”๋“œ

const jsonParser = express.json();

// ์ƒ๋žต
app.post('/api/users', jsonParser, function (req, res) {

})


Node.js๋กœ HTTP body(payload)๋ฅผ ๋ฐ›์„ ๋•Œ๋Š” Buffer๋ฅผ ์กฐํ•ฉํ•ด์„œ ๋‹ค์†Œ ๋ณต์žกํ•œ ๋ฐฉ์‹์œผ๋กœ body๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.
๋„คํŠธ์›Œํฌ์ƒ์˜ chunk๋ฅผ ํ•ฉ์น˜๊ณ , buffer๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค.

Express๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด ๊ณผ์ •์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
Express v4.16.0๋ถ€ํ„ฐ๋Š” body-parser๋ฅผ ๋”ฐ๋กœ ์„ค์น˜ํ•˜์ง€ ์•Š๊ณ , Express ๋‚ด์žฅ ๋ฏธ๋“ค์›จ์–ด์ธ express.json()์„ ์‚ฌ์šฉํ•œ๋‹ค.


case 2: ๋ชจ๋“  ์š”์ฒญ/์‘๋‹ต์— CORS ํ—ค๋”๋ฅผ ๋ถ™์ผ ๋•Œ

const defaultCorsHeader = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Accept',
  'Access-Control-Max-Age': 10
};

...

if (req.method === 'OPTIONS') {
  res.writeHead(200, defaultCorsHeader);
  res.end()
}

// npm์œผ๋กœ cors ์„ค์น˜
npm install cors

// ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด CORS ํ—ˆ์šฉ โœจ
const cors = require('cors');
...
app.use(cors());

// ํŠน์ • ์š”์ฒญ์— ๋Œ€ํ•ด CORS ํ—ˆ์šฉ
const cors = require('cors')
...
app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})


Node.js HTTP ๋ชจ๋“ˆ์„ ์ด์šฉํ•œ ์ฝ”๋“œ์— CORS ํ—ค๋”๋ฅผ ๋ถ™์ด๋ ค๋ฉด, ์‘๋‹ต ๊ฐ์ฒด์˜ writeHead ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
Node.js์—์„œ๋Š” ์ด ๋ฉ”์„œ๋“œ ๋“ฑ์„ ์ด์šฉํ•˜์—ฌ ๋ผ์šฐํŒ…๋งˆ๋‹ค ํ—ค๋”๋ฅผ ๋งค๋ฒˆ ๋„ฃ์–ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
๊ทธ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, OPTIONS ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ๋ผ์šฐํŒ…๋„ ๋”ฐ๋กœ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

cors ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด ๊ณผ์ •์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


๐Ÿ’ก ๋ฏธ๋“ค์›จ์–ด ์ž‘๋™ ์›๋ฆฌ ์ดํ•ดํ•˜๊ธฐ

  1. POST ์š”์ฒญ ๋“ฑ์— ํฌํ•จ๋œ body(payload)๋ฅผ ๊ตฌ์กฐํ™”ํ•  ๋•Œ(์‰ฝ๊ฒŒ ์–ป์–ด๋‚ด๊ณ ์ž ํ•  ๋•Œ)
  2. ๋ชจ๋“  ์š”์ฒญ/์‘๋‹ต์— CORS ํ—ค๋”๋ฅผ ๋ถ™์—ฌ์•ผ ํ•  ๋•Œ
  3. ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด url์ด๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ™•์ธํ•  ๋•Œ
  4. ์š”์ฒญ ํ—ค๋”์— ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์žˆ๋Š”์ง€ ํ™•์ธํ•  ๋•Œ

case 3: ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด url์ด๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ™•์ธํ•  ๋•Œ

๋ฏธ๋“ค์›จ์–ด๋Š” ๋ง ๊ทธ๋Œ€๋กœ ํ”„๋กœ์„ธ์Šค ์ค‘๊ฐ„์— ๊ด€์—ฌํ•˜์—ฌ ํŠน์ • ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

์ˆ˜๋งŽ์€ ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์žˆ์ง€๋งŒ, ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๋ฏธ๋“ค์›จ์–ด ๋กœ๊ฑฐ(logger)๋ฅผ ์˜ˆ๋กœ ๋“ค๊ฒ ๋‹ค.
๋กœ๊ฑฐ๋Š” ๋””๋ฒ„๊น…์ด๋‚˜, ์„œ๋ฒ„ ๊ด€๋ฆฌ์— ๋„์›€์ด ๋˜๊ธฐ ์œ„ํ•ด console.log๋กœ ์ ์ ˆํ•œ ๋ฐ์ดํ„ฐ๋‚˜ ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

๋ฐ์ดํ„ฐ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๊ฑฐ์น˜๋Š” ๋™์•ˆ ์‘๋‹ตํ•  ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค๋ฉด,
๋ฏธ๋“ค์›จ์–ด ์‚ฌ์ด์‚ฌ์ด์— ๋กœ๊ฑฐ๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ ํ˜„์žฌ ๋ฐ์ดํ„ฐ๋ฅผ ํ™•์ธํ•˜๊ฑฐ๋‚˜, ๋””๋ฒ„๊น…์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์œ„ ๊ทธ๋ฆผ์€ endpoint๊ฐ€ /์ด๋ฉด์„œ, ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ GET ์š”์ฒญ์„ ๋ฐ›์•˜์„ ๋•Œ ์ ์šฉ๋˜๋Š” ๋ฏธ๋“ค์›จ์–ด๋‹ค.
ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ˆœ์„œ์— ์œ ์˜ํ•ด์•ผ ํ•œ๋‹ค.
req, res๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ž˜ ์•„๋Š” ์š”์ฒญ(request), ์‘๋‹ต(response)์ด๊ณ  next๋Š” ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.


case 4: ์š”์ฒญ ํ—ค๋”์— ์‚ฌ์šฉ์ž ์ธ์ฆ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์žˆ๋Š”์ง€ ํ™•์ธํ•  ๋•Œ

app.use((req, res, next) => {
  // ํ† ํฐ์ด ์žˆ๋Š”์ง€ ํ™•์ธ, ์—†์œผ๋ฉด ๋ฐ›์•„์ค„ ์ˆ˜ ์—†์Œ.
  if(req.headers.token){
    req.isLoggedIn = true;
    next();
  } else {
    res.status(400).send('invalid user')
  }
})


HTTP ์š”์ฒญ์—์„œ ํ† ํฐ์ด ์žˆ๋Š”์ง€๋ฅผ ํŒ๋‹จํ•˜์—ฌ, ์ด๋ฏธ ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž์ผ ๊ฒฝ์šฐ ์„ฑ๊ณต, ์•„๋‹ ๊ฒฝ์šฐ ์—๋Ÿฌ๋ฅผ ๋ณด๋‚ด๋Š” ๋ฏธ๋“ค์›จ์–ด ์˜ˆ์ œ์ด๋‹ค.



๐Ÿ’ฌ Sprint Review


Node.js HTTP ๋ชจ๋“ˆ์„ ์ด์šฉํ•œ ์ฝ”๋“œ๋ฅผ Express๋กœ ๋ณ€ํ™˜ํ•˜๋ฉด์„œ ์ฐพ์€ ํ‚คํฌ์ธํŠธ๊ฐ€ ๋”ฑ 3๊ฐœ ์žˆ์—ˆ๋‹ค.

  1. Express, Cors package ์„ค์น˜
  2. ํ•œ ํฌํŠธ์— ํ•œ ์„œ๋ฒ„๋งŒ ๊ฐ€๋Šฅ
  3. express์˜ ๋ฐ˜์‘ ๊ฐ’์ธ res.send๋Š” ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์„ ์‚ฌ์šฉํ•ด์„œ ํ‘œํ˜„

3๋ฒˆ์„ ์ถ”๊ฐ€ ์„ค๋ช…ํ•˜๋ฉด, ๋‘˜์˜ ์ฐจ์ด์ ์€ ๋”์šฑ ๋” ๋“œ๋Ÿฌ๋‚œ๋‹ค.

Express์—์„œ๋Š” res.send({ convertedText })์™€ ๊ฐ™์ด ๊ฐ์ฒด ๋ฆฌํ„ฐ๋Ÿด์„ ์‚ฌ์šฉํ•˜์—ฌ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด์ง€๋งŒ,
์ˆœ์ˆ˜ํ•œ Node.js HTTP ๋ชจ๋“ˆ์—์„œ๋Š” response.end(convertedText)์™€ ๊ฐ™์ด ์‘๋‹ต ๋ณธ๋ฌธ์„ ์ง์ ‘ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

์ด์ œ ๊ธฐ์กด ์ฝ”๋“œ์™€ express ๋ฒ„์ „ ์ฝ”๋“œ๋ฅผ ์˜ฌ๋ ค๋ณด๊ฒ ๋‹ค.


// ๊ธฐ์กด ์ฝ”๋“œ

const http = require("http");

const PORT = 4999;

const ip = "localhost";

const server = http.createServer((request, response) => {
  // GET / ์š”์ฒญ ์ฒ˜๋ฆฌ
  if (request.method === "GET" && request.url === "/") {
    response.writeHead(200, defaultCorsHeader); // 200 OK ์‘๋‹ต ์ฝ”๋“œ์™€ CORS ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜
    response.end("hello mini-server sprints"); // "hello mini-server sprints"๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋ƒ„
  }

  // OPTIONS ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ
  else if (request.method === "OPTIONS") {
    response.writeHead(204, defaultCorsHeader); // 204 No Content ์‘๋‹ต ์ฝ”๋“œ์™€ CORS ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜
    response.end();
    return;
  }

  // POST /lower ์š”์ฒญ ์ฒ˜๋ฆฌ
  else if (request.method === "POST" && request.url === "/lower") {
    let requestBody = "";

    request.on("data", (text) => {
      requestBody += text.toString();
    });

    request.on("end", () => {
      const convertedText = requestBody.toLowerCase(); // ๋ฐ›์€ ํ…์ŠคํŠธ๋ฅผ ์†Œ๋ฌธ์ž๋กœ ๋ณ€ํ™˜
      response.writeHead(200, defaultCorsHeader); // 200 OK ์‘๋‹ต ์ฝ”๋“œ์™€ CORS ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜
      response.end(convertedText); // ๋ณ€ํ™˜๋œ ํ…์ŠคํŠธ๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋ƒ„
    });
  }
  // POST /upper ์š”์ฒญ ์ฒ˜๋ฆฌ
  else if (request.method === "POST" && request.url === "/upper") {
    let requestBody = "";

    request.on("data", (text) => {
      requestBody += text.toString();
    });

    request.on("end", () => {
      const convertedText = requestBody.toUpperCase(); // ๋ฐ›์€ ํ…์ŠคํŠธ๋ฅผ ๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜
      response.writeHead(200, defaultCorsHeader); // 200 OK ์‘๋‹ต ์ฝ”๋“œ์™€ CORS ํ—ค๋”๋ฅผ ๋ฐ˜ํ™˜
      response.end(convertedText); // ๋ณ€ํ™˜๋œ ํ…์ŠคํŠธ๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋ƒ„
    });
  }
  // ๊ทธ ์™ธ์˜ ์š”์ฒญ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ (404 Not Found)
  else {
    response.statusCode = 404; // 404 Not Found ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ์„ค์ •
    response.end(); // ์‘๋‹ต ์ข…๋ฃŒ
  }
  console.log(
    `http request method is ${request.method}, url is ${request.url}`
  );
});

server.listen(PORT, ip, () => {
  console.log(`http server listen on ${ip}:${PORT}`);
});

// ์‘๋‹ต ํ—ค๋”
const defaultCorsHeader = {
  "Access-Control-Allow-Origin": "*", // ๋ชจ๋“  ์ถœ์ฒ˜์—์„œ์˜ ์š”์ฒญ์„ ํ—ˆ์šฉ
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", // ์›ํ•˜๋Š” HTTP ๋ฉ”์„œ๋“œ๋ฅผ ๋ช…์‹œ
  "Access-Control-Allow-Headers": "Content-Type, Accept", // ํ—ˆ์šฉํ•˜๋Š” ์š”์ฒญ ํ—ค๋”๋ฅผ ๋ช…์‹œ
  "Access-Control-Max-Age": 10, // Preflight ์š”์ฒญ์˜ ์บ์‹ฑ ์‹œ๊ฐ„์„ ์„ค์ •
};

// Express ์ฝ”๋“œ

const express = require("express");
const app = express(); // Express ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ƒ์„ฑ

const PORT = 3999; // ๊ธฐ์กด basic ์„œ๋ฒ„์™€ port ๋ฒˆํ˜ธ ๋‹ค๋ฅด๊ฒŒ
const ip = "localhost";
const cors = require("cors");

app.use(cors());

// JSON ํŒŒ์‹ฑ์„ ์œ„ํ•œ ๋ฏธ๋“ค์›จ์–ด ๋“ฑ๋ก
// ์ด ์„ค์ •์ด ๋น ์ง€๋ฉด ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ฒ„๋กœ ์ž˜๋ชป๋œ ์š”์ฒญ์„ ๋ณด๋ƒˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์˜ค๋ฅ˜,
// ์„œ๋ฒ„์—์„œ ์ „์†กํ•œ ์‘๋‹ต์ด JSON ํ˜•์‹์ด ์•„๋‹ˆ๋ผ HTML ํ˜•์‹์œผ๋กœ ๋„์ฐฉํ•จ
app.use(express.json({ strict: false })); // ์ด๋ฒˆ ๊ฒฝ์šฐ๋Š” json์„ ๋ฐฐ์—ด์ด๋‚˜ ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ๋ฌธ์ž์—ด๋กœ ๋ณด๋‚ด๊ธฐ๋•Œ๋ฌธ์— strict: false

// GET / ์š”์ฒญ ์ฒ˜๋ฆฌ
app.get("/", (req, res) => {
  res.send("hello mini-server sprints"); // "hello mini-server sprints"๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋ƒ„
});

// OPTIONS ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ
app.options("/", (req, res) => {
  res.sendStatus(204); // 204 No Content ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜
});

// POST /upper ์š”์ฒญ ์ฒ˜๋ฆฌ
app.post("/upper", (req, res) => {
  const requestBody = req.body;
  const convertedText = requestBody.toUpperCase(); // ๋ฐ›์€ ํ…์ŠคํŠธ๋ฅผ ๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜
  res.send({ convertedText }); // ๋ณ€ํ™˜๋œ ํ…์ŠคํŠธ๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋ƒ„
});

// POST /lower ์š”์ฒญ ์ฒ˜๋ฆฌ
app.post("/lower", (req, res) => {
  const requestBody = req.body;
  const convertedText = requestBody.toLowerCase(); // ๋ฐ›์€ ํ…์ŠคํŠธ๋ฅผ ์†Œ๋ฌธ์ž๋กœ ๋ณ€ํ™˜
  res.send({ convertedText }); // ๋ณ€ํ™˜๋œ ํ…์ŠคํŠธ๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋ƒ„
});

// ๊ทธ ์™ธ์˜ ์š”์ฒญ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ (404 Not Found)
app.use((req, res) => {
  res.sendStatus(404); // 404 Not Found ์‘๋‹ต ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜
});

// ์„œ๋ฒ„ ์‹œ์ž‘
app.listen(PORT, ip, () => {
  console.log(`Express server listening on ${ip}:${PORT}`);
});


ํ™•์‹คํžˆ express ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง„ ๊ฒƒ์„ ํ•œ ๋ˆˆ์—๋„ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ๋‹ค.

์‚ฌ์‹ค ํ‚ค ํฌ์ธํŠธ 3๊ฐœ๋Š” ๋‚ด๊ฐ€ ์ฝ”๋“œ ์งœ๋ฉด์„œ ๋นผ๋จน๊ณ , ์˜ค๋ฅ˜๋ฅผ ๋„์› ๋˜ ์ผ€์ด์Šค๋ผ ์•ž์œผ๋กœ๋„ ์ ˆ๋Œ€ ์•ˆ ๊นŒ๋จน์„ ๊ฒƒ ๊ฐ™๋‹ค ๐Ÿ˜…

profile
์•„์ด๋””์–ด๊ฐ€ ๋„˜์น˜๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ ๊ฟˆ๊ฟ‰๋‹ˆ๋‹ค ๐Ÿ”ฅ

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