๐ŸŒˆ Express ์ฐ๋จนํ•˜๊ธฐ(0)

Lee Jooamยท2022๋…„ 7์›” 11์ผ
0

๐Ÿ›  NodeJS?

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋ธŒ๋ผ์šฐ์ € ์œ„์—์„œ ๋™์ž‘ํ•˜๊ธฐ ์œ„ํ•ด ํƒ„์ƒํ•œ ์–ธ์–ด๋‹ค. ๋ธŒ๋ผ์šฐ์ €์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์ด ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋Ÿฐํƒ€์ž„์ด์—ˆ์ง€๋งŒ, NodeJS๊ฐ€ ํƒ„์ƒํ•˜๋ฉด์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๋˜๋‹ค๋ฅธ ํ™˜๊ฒฝ์—์„œ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

์ฆ‰ NodeJS๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๋˜๋‹ค๋ฅธ ๋Ÿฐํƒ€์ž„์ธ ์…ˆ์ด๋‹ค(์ƒˆ๋กœ์šด ์–ธ์–ด๊ฐ€ ์•„๋‹˜). ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์•„๋‹Œ ํ™˜๊ฒฝ์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋œ๋‹ค๋Š” ๊ฒŒ ์–ด๋–ค ์˜๋ฏธ๊ฐ€ ์žˆ์„๊นŒ?

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

๋‚ฎ์€ ๋Ÿฌ๋‹์ปค๋ธŒ์™€ ์ ์ ˆํ•œ ์„ฑ๋Šฅ์ด ํ˜„์žฌ NodeJS ์‚ฌ์šฉ๋Ÿ‰์„ ์ฆ๊ฐ€์‹œํ‚ค๋Š”๋ฐ ํฐ ์—ญํ• ์„ ํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

๐Ÿ•น Express

NodeJS ํ™˜๊ฒฝ์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ๊ตฌํ˜„ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ง์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ๋งŒ๋“  ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ง๋„ ํฌํ•จํ•œ๋‹ค. ๋ชจ๋“  ํ™˜๊ฒฝ์ด ๊ทธ๋ ‡๋“ฏ์ด ๋ฐ”๋‹๋ผ ํ™˜๊ฒฝ์—์„œ๋Š” ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“ค๊ธฐ ์‰ฝ์ง€ ์•Š๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ๋ฆฌ์•กํŠธ, ๋ทฐ, ์•ต๊ทค๋Ÿฌ ๋“ฑ ํ”„๋ก ํŠธ์—”๋“œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ/ํ”„๋ ˆ์ž„์›Œํฌ ๋“ฑ์ด ์ƒ๊ฒจ๋‚ฌ๊ณ  ์ด๊ฒƒ์€ ๋ฐฑ์—”๋“œ์—์„œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋‹ค. ๊ทธ ์ค‘ ํ•˜๋‚˜๊ฐ€ ExpressJS์ด๋ฉฐ ์ „์„ธ๊ณ„์ ์œผ๋กœ ๋†’์€ ์ ์œ ์œจ์„ ๊ฐ€์ง„ ๋ฐฑ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ ์ค‘ ํ•˜๋‚˜๋‹ค.

Express ์žฅ์ 

Express์˜ ๊ฐ€์žฅ ํฐ ์žฅ์ ์œผ๋กœ๋Š” ์†์‰ฌ์šด ์‚ฌ์šฉ๋ฒ•์ด ์žˆ๋‹ค. ๋˜ํ•œ ์œ ์—ฐํ•œ ๋ฏธ๋“ค์›จ์–ด์˜ ์ถ”๊ฐ€๋กœ ์‚ฌ์šฉ์ž๊ฐ€ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ์„ ํšจ์œจ์ ์œผ๋กœ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋†’์€ ์ ์œ ์œจ์„ ์ง€๋‹Œ ๋งŒํผ ํฐ ๊ทœ๋ชจ์˜ ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ํ™œ์„ฑํ™”๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ๋„ ์žฅ์  ์ค‘ ํ•˜๋‚˜๋‹ค.

Express ๋‹จ์ 

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

1๏ธโƒฃ ์‹œ์ž‘ํ•˜๊ธฐ

npm install express
npm install cors

์šฐ์„  express ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์•ผํ•œ๋‹ค. ์ง€๊ธˆ ํ™˜๊ฒฝ์—์„œ๋Š” ํ”„๋ก ํŠธ์—”๋“œ๋ฅผ 5500 ํฌํŠธ๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” live-server ์ต์Šคํ…์…˜์„ ์‚ฌ์šฉํ•˜๊ณ , express๋ฅผ ์ด์šฉํ•œ ๋ฐฑ์—”๋“œ ์„œ๋ฒ„๋Š” 8080 ํฌํŠธ๋กœ ์„ค์ •ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— cross-origin ํ™˜๊ฒฝ์ด ๋œ๋‹ค.

CORS๋ฅผ ์„ค์ •ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด cors ํŒจํ‚ค์ง€๋„ ํ•จ๊ป˜ ์„ค์น˜ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ESmodule ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด package.json์— type์„ module๋กœ ์„ค์ •ํ–ˆ๋‹ค.

import express from 'express';
import cors from 'cors';
import api from './api/index.js';

const app = express();
const port = 8080;

app.use(cors({ origin: 'http://127.0.0.1:5500', credentials: true }));
app.use(express.json());
app.use(cookieMiddleware);
app.use('/api', api);

app.listen(port, () => {
  console.log('app is listening on port ' + port);
});

๊ฐ„๋‹จํ•œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š” ์ฝ”๋“œ์ด๋‹ค. use๋Š” ๋ฏธ๋“ค์›จ์–ด ์„ค์ •, listen์€ ๊ณต์‹๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด Node์˜ http.Server.listen() ๋ฉ”์†Œ๋“œ์˜ identical์ด๋ผ๊ณ  ํ•œ๋‹ค.

๋ฏธ๋“ค์›จ์–ด๋Š” ์ปดํ“จํ„ฐ ๊ณตํ•™์—์„œ ๋„“์€ ๋œป์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ ์‰ฝ๊ฒŒ ํ‘œํ˜„ํ•˜์ž๋ฉด ๊ณผ์ •์˜ ์ค‘๊ฐ„์—์„œ ํŠน์ •ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•˜๋Š” ํ•˜๋“œ์›จ์–ด ๋˜๋Š” ์†Œํ”„ํŠธ์›จ์–ด์ด๋‹ค.

ํ˜„์žฌ ์ฝ”๋“œ์— ๋”ฐ๋ฅด๋ฉด app์ด๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์„ ์–ธ๋œ express ์•ฑ์ด 3๊ฐœ์˜ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. Express ๋ฏธ๋“ค์›จ์–ด๋Š” ํฌ๊ฒŒ 3๊ฐ€์ง€๋กœ ๋ถ„๋ฅ˜ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ฒซ ๋ฒˆ์งธ๋Š” ๋ชจ๋“  ์š”์ฒญ์— ๋Œ€ํ•ด ํŠน์ • ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด, ๋‘ ๋ฒˆ์งธ๋Š” ํŠน์ • ๊ฒฝ๋กœ์— ๋Œ€ํ•ด์„œ๋งŒ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” path ๋ฏธ๋“ค์›จ์–ด, ๋งˆ์ง€๋ง‰์œผ๋กœ err๋ฅผ ํ•ธ๋“ค๋งํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด์ด๋‹ค.

์œ„์˜ ์˜ˆ์‹œ์—์„œ๋Š” ์ฒซ ๋ฒˆ์งธ ํ˜•ํƒœ์˜ ๋ฏธ๋“ค์›จ์–ด์™€ api ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” path ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค.

cors๋Š” ํฌ๋กœ์Šค ์˜ค๋ฆฌ์ง„ ์„ค์ •์„ ์œ„ํ•œ ๋ฏธ๋“ค์›จ์–ด, express.json()์€ ์š”์ฒญ์˜ Content-Type ํ—ค๋”๋ฅผ ํ™•์ธํ•ด json ํ˜•ํƒœ๋กœ ๋“ค์–ด์˜ค๋Š” ํŽ˜์ด๋กœ๋“œ๋“ค์„ ํŒŒ์‹ฑํ•ด์ค€๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ body-parser ๋ชจ๋“ˆ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ์žˆ๋‹ค.

cookieMiddleware๋Š” ๋”ฐ๋กœ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ธ๋ฐ, request์˜ ํ—ค๋”์— ์žˆ๋Š” ์ฟ ํ‚ค string์„ ์กฐํšŒํ•ด ๊ฐ์ฒด ํ˜•ํƒœ๋กœ request์— cookies๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

์‚ฌ์‹ค ๊ฐ™์€ ์ž‘์—…์„ ํ•ด์ฃผ๋Š” cookieParser๋ผ๋Š” ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ์กด์žฌํ•˜์ง€๋งŒ ๊ทธ๋ƒฅ ๊ตฌํ˜„ํ•ด๋ดค๋‹ค.

2๏ธโƒฃ ๋ผ์šฐํŒ… ์„ค์ •

์ด๋ฒˆ ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ api ๊ฒฝ๋กœ๋กœ ๋ณด๋‚ธ ์š”์ฒญ๋“ค์„ ๋‹ค๋ฅธ ๋ผ์šฐํ„ฐ์—์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค. ์œ„์— ์„ค๋ช…ํ–ˆ๋˜๋Œ€๋กœ api path๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด๊ฐ€ ํ•„์š”ํ•œ๋ฐ, ๊ตฌํ˜„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

// /api/index.js
import { Router } from 'express';
import sessionMiddleware from '../middleware/sessionMiddleware.js';
import auth from './auth/index.js';
import board from './board/index.js';

const router = Router();

router.use('/auth', sessionMiddleware, auth);
router.use('/board', board);

export default router;

A router object is an isolated instance of middleware and routes

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

ํ˜„์žฌ ์ฝ”๋“œ์—์„œ๋Š” api ๋ผ์šฐํ„ฐ๊ฐ€ auth, board ๋ผ์šฐํ„ฐ๋ฅผ ๊ฐ๊ฐ์˜ ๊ฒฝ๋กœ์— ์—ฐ๊ฒฐํ•˜๊ณ  ์žˆ๋‹ค.

// api/auth/index.js
import { Router } from 'express';

const router = Router();

router.post('/login', (req, res) => {
  res.status(200).json({ text: '์•ˆ๋…•ํ•˜์„ธ์š”!' });
});

export default router;

auth ๋ผ์šฐํ„ฐ์—์„œ login ๊ฒฝ๋กœ๋กœ ๋“ค์–ด์˜ค๋Š” POST ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” callback์„ ๋“ฑ๋กํ–ˆ๋‹ค. response ๊ฐ์ฒด์— status ์ฝ”๋“œ์™€ json ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค.

3๏ธโƒฃ ํ”„๋ก ํŠธ์—”๋“œ

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="./index.js" defer></script>
    <link rel="stylesheet" href="./style.css" />
    <title>Document</title>
  </head>
  <body>
    <h1>Title</h1>
    <div>
      <button class="login">login</button>
    </div>
  </body>
</html>
async function login() {
  const response = await fetch('http://localhost:8080/api/auth/login', {
    method: 'POST',
    credentials: 'include',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      userId: 'lee',
      password: '1234',
    }),
  }).then((res) => {
    return res.json();
  });

  console.log(response);
}

(function () {
  const loginBtn = document.querySelector('.login');

  loginBtn.addEventListener('click', login);
})();

ํ”„๋ก ํŠธ์—”๋“œ์—์„œ๋Š” ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ์„ ํด๋ฆญ ์‹œ ์ต์Šคํ”„๋ ˆ์Šค ์•ฑ์— ์„ค์ •ํ•œ ๊ฒฝ๋กœ์ธ api/auth/login์œผ๋กœ POST ์š”์ฒญ์„ ๋ณด๋‚ด๋„๋ก ํ–ˆ๋‹ค. ํ˜„์žฌ ์•ฑ์—์„œ 8080 ํฌํŠธ๋กœ ์„œ๋ฒ„๋ฅผ ์—ด์—ˆ๊ธฐ ๋•Œ๋ฌธ์— localhost:8080์ด ๋ฒ ์ด์Šค ์ฃผ์†Œ๊ฐ€ ๋œ๋‹ค.

ํ”„๋ก ํŠธ์—”๋“œ์˜ ์‹คํ–‰์€ live server ์ต์Šคํ…์…˜, ๋ฐฑ์—”๋“œ์˜ ์‹คํ–‰์€ node ๋ช…๋ น์–ด๋กœ ํ•œ๋‹ค.

ํ”„๋กœ์ ํŠธ์˜ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

node src/app

๋‹ค์Œ ๋ช…๋ น์–ด๋กœ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ณ  live server ๊ฐ€๋™ ๋ช…๋ น์–ด๋กœ ํ”„๋ก ํŠธ์—”๋“œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰์‹œํ‚จ๋‹ค.

๊ฐœ๋ฐœ์ž ๋„๊ตฌ๋ฅผ ํ†ตํ•ด ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ถœ๋ ฅ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๐Ÿ˜ƒ

๋‹ค์Œ ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ์„œ๋ฒ„์—์„œ set-cookie๋ฅผ ํ•˜๋Š” ๋ฒ•์— ๋Œ€ํ•ด ํฌ์ŠคํŒ… ํ•  ์˜ˆ์ •์ด๋‹ค ใ…Žใ…Ž.

profile
ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž๋กœ ๊ฑธ์–ด๊ฐ€๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

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