Search

ํผ๊ทธ pug

pug

Node.js์—์„œ ์‚ฌ์šฉ๋˜๋Š” ํ…œํ”Œ๋ฆฟ ์—”์ง„
Pug๋Š” HTML๊ณผ JavaScript๋ฅผ ์กฐํ•ฉํ•œ ์–ธ์–ด๋กœ, HTML์˜ ์žฅ์ ์ธ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ JavaScript์˜ ๋™์  ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ํ™•์žฅ์ž : *.pug

์ฃผ์š” ๋ฌธ๋ฒ•

๊ตฌ๋ถ„
๋ฌธ๋ฒ•
์„ค๋ช…
๋ณ€์ˆ˜ ์‚ฝ์ž…
{{ variable }}
๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. #{ } ๋ณด๋‹ค ์„ฑ๋Šฅ์ด ์ข‹๋‹ค. - HTML ์„ HTML ์š”์†Œ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ถœ๋ ฅ
๋ณ€์ˆ˜ ์‚ฝ์ž…
#{ }
๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. - HTML ์„ HTML ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅ
์กฐ๊ฑด๋ฌธ
if (condition) { ... }
์กฐ๊ฑด์— ๋”ฐ๋ผ HTML์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
๋ฐ˜๋ณต๋ฌธ
each (item in array) { ... }
๋ฐฐ์—ด์˜ ์š”์†Œ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ HTML์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
ํ•จ์ˆ˜ ํ˜ธ์ถœ
{{ function(arguments) }}
ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ HTML์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„์—์„œ ๋ทฐ๋กœ ๋ณ€์ˆ˜ ์ „๋‹ฌ๋ฐฉ๋ฒ•

1.
res.render()์— ์ง์ ‘ ๋ณ€์ˆ˜ ์ „๋‹ฌ
2.
app.locals ์— ์ „์—ญ ๋ณ€์ˆ˜ ์„ค์ •
3.
res.locals์— ๋กœ์ปฌ ๋ณ€์ˆ˜ ์„ค์ •
4.
res.locals์— ๊ฐ์ฒด ์ „์ฒด๋ฅผ ์„ค์ •

res.render()์— ์ง์ ‘ ๋ณ€์ˆ˜ ์ „๋‹ฌ

โ€ข
js
app.get('/example', (req, res) => { res.render('example', { title: 'Express Example', message: 'Hello World' }); });
JavaScript
๋ณต์‚ฌ
โ€ข
pug
// example.pug h1= title p= message
JavaScript
๋ณต์‚ฌ

app.locals ์— ์ „์—ญ ๋ณ€์ˆ˜ ์„ค์ •

โ€ข
js
app.locals.title = 'Express Example';
JavaScript
๋ณต์‚ฌ
โ€ข
pug
// example.pug h1= title p= message
JavaScript
๋ณต์‚ฌ

res.locals ์— ๋ณ€์ˆ˜ ์„ค์ •

โ€ข
js
app.get('/example', (req, res) => { res.locals.title = 'Express Example'; res.render('example', { message: 'Hello World' }); });
JavaScript
๋ณต์‚ฌ
โ€ข
pug
// example.pug h1= title p= message
JavaScript
๋ณต์‚ฌ

res.locals ์— ๊ฐ์ฒด ์„ค์ •

โ€ข
js
app.get('/example', (req, res) => { res.locals.data = { title: 'Express Example', message: 'Hello World' }; res.render('example'); });
JavaScript
๋ณต์‚ฌ
โ€ข
pug
// example.pug h1= data.title p= data.message
JavaScript
๋ณต์‚ฌ

์ฃผ์š” ์˜ˆ์‹œ ์ฝ”๋“œ

Pug์—์„œ๋Š” - ๊ธฐํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JavaScript ์ฝ”๋“œ ๋ธ”๋ก์„ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ - var isAdmin = true์™€ ๊ฐ™์€ ์ฝ”๋“œ๋Š” Pug์—์„œ ์œ ํšจํ•œ ๋ฌธ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด Pug ํ…œํ”Œ๋ฆฟ์—์„œ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ณ  ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ณ€์ˆ˜ ์‚ฝ์ž…

// ๋ณ€์ˆ˜ ์‚ฝ์ž… ์˜ˆ์‹œ - var username = 'John Doe' h1 Welcome, {{username}}!
JavaScript
๋ณต์‚ฌ

์กฐ๊ฑด๋ฌธ

โ€ข
if
// ์กฐ๊ฑด๋ฌธ ์˜ˆ์‹œ - var isAdmin = true - var isUser = true if isAdmin p You are an admin. else if isUser p You are a User. else p You are not an admin.
JavaScript
๋ณต์‚ฌ
โ€ข
case
- var score = 'C' case score when 'A' p 'A' ํ•™์  ์ž…๋‹ˆ๋‹ค when 'B' p 'B' ํ•™์  ์ž…๋‹ˆ๋‹ค when 'C' p 'C' ํ•™์  ์ž…๋‹ˆ๋‹ค when 'D' p 'D' ํ•™์  ์ž…๋‹ˆ๋‹ค default P 'ํ•™๊ณ ' ์ž…๋‹ˆ๋‹ค
HTML
๋ณต์‚ฌ

๋ฐ˜๋ณต๋ฌธ

// ๋ฐ˜๋ณต๋ฌธ ์˜ˆ์‹œ - var fruits = ['Apple', 'Banana', 'Orange'] ul each fruit in fruits li= fruit
JavaScript
๋ณต์‚ฌ

ํ•จ์ˆ˜ ํ˜ธ์ถœ

// ํ•จ์ˆ˜ ํ˜ธ์ถœ ์˜ˆ์‹œ - function capitalize(str) { return str.toUpperCase(); } p= capitalize('hello, world!') p {{ capitalize('hello, world!') }}
JavaScript
๋ณต์‚ฌ

๊ฒŒ์‹œํŒ ์˜ˆ์‹œ์ฝ”๋“œ

1.
๋ผ์šฐํ„ฐ ํŒŒ์ผ ์ƒ์„ฑ ๋ฐ ์„ค์ •
2.
๋ผ์šฐํ„ฐ ์ •์˜
3.
pug ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ ์ž‘์„ฑ
4.
style.css ์—ฐ๊ฒฐ
5.
index.pug ์ž‘์„ฑ
6.
header, footer ์ถ”๊ฐ€
7.
๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž… ํ™”๋ฉด ์ž‘์„ฑ
8.
๊ฒŒ์‹œํŒ ํ™”๋ฉด ์ž‘์„ฑ

๋ผ์šฐํ„ฐ ํŒŒ์ผ ์ƒ์„ฑ ๋ฐ ์„ค์ •

1.
routes ํด๋” ์ƒ์„ฑ
2.
index.js, board.js ํŒŒ์ผ ์ƒ์„ฑ
3.
app.js ์— import ๋ฐ ๋ฏธ๋“ค์›จ์–ด ์„ค์ •

routes ํด๋” ์ƒ์„ฑ

index.js, board.js ํŒŒ์ผ ์ƒ์„ฑ

app.js ์— import ๋ฐ ๋ฏธ๋“ค์›จ์–ด ์„ค์ •

// ๐Ÿ‘ฉโ€๐Ÿ’ป ๋ผ์šฐํ„ฐ ๋ชจ๋“ˆ import const indexRouter = require('./routes/index'); const boardRouter = require('./routes/board');
JavaScript
๋ณต์‚ฌ
// ๐Ÿ‘ฉโ€๐Ÿ’ป ๋ผ์šฐํ„ฐ ์„ค์ • app.use('/', indexRouter); app.use('/board', boardRouter);
JavaScript
๋ณต์‚ฌ

๋ผ์šฐํ„ฐ ์ •์˜

1.
index.js
2.
board.js

index.js

const express = require('express'); const router = express.Router(); // GET / ๋ผ์šฐํ„ฐ router.get('/', (req, res) => { res.render('index', { title: 'Main' }); }); // ๋กœ๊ทธ์ธ router.get('/login', (req, res) => { res.render('login', { title: 'Login' }); }); // ํšŒ์›๊ฐ€์ž… router.get('/join', (req, res) => { res.render('join', { title: 'Join' }); }); module.exports = router;
JavaScript
๋ณต์‚ฌ

board.js

const express = require('express') const router = express.Router() let boardList = [ { title : '์ œ๋ชฉ1', writer : '์ž‘์„ฑ์ž1', content : '๋‚ด์šฉ1' }, { title : '์ œ๋ชฉ2', writer : '์ž‘์„ฑ์ž2', content : '๋‚ด์šฉ2' }, { title : '์ œ๋ชฉ3', writer : '์ž‘์„ฑ์ž3', content : '๋‚ด์šฉ3' }, ] // ๐Ÿ‘ฉโ€๐Ÿ’ป ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก router.get('/', (req, res) => { res.render('board/list', {boardList} ) }) // ๐Ÿ‘ฉโ€๐Ÿ’ป ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก router.get('/insert', (req, res) => { res.render('board/insert') }) // ๐Ÿ‘ฉโ€๐Ÿ’ป ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก router.post('/', (req, res) => { // ๊ตฌ์กฐ๋ถ„ํ•ดํ• ๋‹น const { title, writer, content } = req.body; // const title = req.body.title // const writer = req.body.writer // const content = req.body.content const newBoard = { title, writer, content }; boardList.push(newBoard); res.redirect('/board'); }); // ๐Ÿ‘ฉโ€๐Ÿ’ป ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ํŽ˜์ด์ง€ router.get('/update/:id', (req, res) => { console.log(`id : ${req.params.id}`); let id = req.params.id const board = boardList[id]; res.render('board/update', { board, id }); }); // ๐Ÿ‘ฉโ€๐Ÿ’ป ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • router.post('/update', (req, res) => { const { id, title, writer, content } = req.body; boardList[id] = { title, writer, content }; res.redirect(`/board/${id}`); }); // ๐Ÿ‘ฉโ€๐Ÿ’ป ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ router.post('/delete', (req, res) => { const id = req.params.id; boardList.splice(id, 1); res.redirect('/board'); }); // ๐Ÿ‘ฉโ€๐Ÿ’ป ๊ฒŒ์‹œ๊ธ€ ์ฝ๊ธฐ // ์š”์ฒญ ๊ฒฝ๋กœ์— ํŒŒ๋ผ๋ฏธํ„ฐ ๋งคํ•‘ ๋ฐฉ๋ฒ• โžก '/:ํŒŒ๋ผ๋ฏธํ„ฐ๋ช…' router.get('/:id', (req, res) => { console.log(`id : ${req.params.id}`); let id = req.params.id let board = boardList[id] res.render('board/read', {board, id}) }) module.exports = router;
JavaScript
๋ณต์‚ฌ

pug ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ ์ž‘์„ฑ

1.
layout.pug
doctype html html head title= title //- ์—ฌ๊ธฐ์— CSS ์—ฐ๊ฒฐ body block content
JavaScript
๋ณต์‚ฌ

style.css ์—ฐ๊ฒฐ

1.
public/css ํด๋” ์ƒ์„ฑ
2.
style.css ํŒŒ์ผ ์ƒ์„ฑ
3.
์Šคํƒ€์ผ ์ž‘์„ฑ

public/css ํด๋” ์ƒ์„ฑ

style.css ํŒŒ์ผ ์ƒ์„ฑ

์Šคํƒ€์ผ ์ž‘์„ฑ

* { margin: 0; padding: 0; box-sizing: border-box; } ul { list-style-type: none; } a { text-decoration: none; } body { font-family: Arial, sans-serif; } /* header */ header { display: flex; justify-content: space-between; align-items: center; background-color: #333; color: #fff; padding: 0 20px; text-align: center; height: 80px; } header h1 { margin: 0; } header nav { height: 100%; } header nav ul { height: 100%; } header nav li { display: inline-block; height: 100%; } header nav a { display: flex; justify-content: center; align-items: center; color: #fff; text-decoration: none; min-width: 100px; height: 100%; } header nav a:hover { background-color: #fff; color: #333; } /* footer */ footer { background-color: #333; color: #fff; padding: 10px; text-align: center; } .container { border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); padding: 20px; width: 300px; margin: 100px auto; } .container-md { border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); padding: 20px; width: 480px; margin: 100px auto; } .container-lg { border-radius: 8px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); padding: 20px; width: 1024px; margin: 100px auto; } .container h2 { text-align: center; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 8px; font-weight: bold; } .form-group input, .form-group .btn { display: inline-block; font-size: 14px; width: 100%; padding: 8px; border: 1px solid #ccc; border-radius: 4px; box-sizing: border-box; } .form-group .btn { text-align: center; background-color: #4caf50; color: #fff; border: none; border-radius: 4px; cursor: pointer; margin-bottom: 10px; } .form-group .btn:hover { background-color: #45a049; } /* table */ .table { width: 100%; border-collapse: collapse; margin-top: 20px; } .table th, .table td { border: 1px solid #ddd; padding: 8px; text-align: left; } .table th { background-color: #f2f2f2; } .table tr:hover { background-color: #f5f5f5; } /* button */ .btn-box { display: flex; justify-content: space-between; align-items: center; margin: 20px 0; } .btn { display: inline-block; text-align: center; font-size: 14px; padding: 8px 18px; box-sizing: border-box; background-color: #4caf50; color: #fff; border: none; border-radius: 4px; cursor: pointer; margin-bottom: 10px; }
JavaScript
๋ณต์‚ฌ

layout.pug

doctype html html head title= title link(rel='stylesheet', href='/css/style.css') body block content
HTML
๋ณต์‚ฌ

index.pug ์ž‘์„ฑ

extends layout block content div.container-lg h1= title h3 #{title} ํ™”๋ฉด์ž…๋‹ˆ๋‹ค
HTML
๋ณต์‚ฌ
1.
extends layout: ํ˜„์žฌ ํ…œํ”Œ๋ฆฟ์ด layout.pug๋ผ๋Š” ๋‹ค๋ฅธ ํ…œํ”Œ๋ฆฟ์„ ํ™•์žฅํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๊ธฐ๋ณธ ๋ ˆ์ด์•„์›ƒ์„ ์ •์˜ํ•˜๊ณ , ๋‹ค์–‘ํ•œ ํŽ˜์ด์ง€์—์„œ ์ด ๋ ˆ์ด์•„์›ƒ์„ ํ™•์žฅํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
2.
block content: ์ด ๋ถ€๋ถ„์€ layout.pug์—์„œ ์ •์˜ํ•œ block content์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค. block content๋Š” ๋‹ค๋ฅธ ํ…œํ”Œ๋ฆฟ์—์„œ ํ™•์žฅ๋  ๋•Œ ์ฑ„์›Œ์งˆ ๋ถ€๋ถ„์„ ์ •์˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
3.
div.container-lg: ์ด ๋ถ€๋ถ„์€ ํŠน์ • ํŽ˜์ด์ง€์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๊ฐ์‹ธ๋Š” div ์š”์†Œ๋กœ, Bootstrap์˜ container-lg ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปจํ…์ธ ์˜ ๋„ˆ๋น„๋ฅผ ์กฐ์ ˆํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
4.
h1= title: title ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ์ถœ๋ ฅํ•˜๋Š” ํ—ค๋”ฉ(์ œ๋ชฉ) ์š”์†Œ์ž…๋‹ˆ๋‹ค.
5.
h3 #{title} ํ™”๋ฉด์ž…๋‹ˆ๋‹ค: title ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ํฌํ•จํ•œ ๊ฐ„๋‹จํ•œ ์„ค๋ช…์„ ์ถœ๋ ฅํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ํ—ค๋”ฉ(๋ถ€์ œ๋ชฉ) ์š”์†Œ์ž…๋‹ˆ๋‹ค.

header, footer ์ถ”๊ฐ€

header.pug

header h1 Pug nav ul li a(href="/") Home li a(href="/login") Login li a(href="/board") Board
HTML
๋ณต์‚ฌ

footer.pug

footer p Copyright ยฉ 2023 Pug
HTML
๋ณต์‚ฌ

layout.pug

doctype html html head title= title link(rel='stylesheet', href='/css/style.css') body //- ์—ฌ๊ธฐ์— header ์ถ”๊ฐ€ include fragment/header.pug block content //- ์—ฌ๊ธฐ์— footer ์ถ”๊ฐ€ include fragment/footer.pug
HTML
๋ณต์‚ฌ

๋กœ๊ทธ์ธ, ํšŒ์›๊ฐ€์ž… ํ™”๋ฉด ์ž‘์„ฑ

login.pug

extends layout block content div.container h2 Login form div.form-group label(for="username") Username: input(type="text", id="username", name="username", required) div.form-group label(for="password") Password: input(type="password", id="password", name="password", required) div.form-group button.btn(type="submit") Login a.btn(href="/join") Sign Up
HTML
๋ณต์‚ฌ

join.pug

extends layout block content div.container h2 Sign Up form div.form-group label(for="username") Username: input(type="text", id="username", name="username", required) div.form-group label(for="email") Email: input(type="email", id="email", name="email", required) div.form-group label(for="password") Password: input(type="password", id="password", name="password", required) div.form-group button.btn(type="submit") Sign Up
HTML
๋ณต์‚ฌ

๊ฒŒ์‹œํŒ ํ™”๋ฉด ์ž‘์„ฑ

1.
board/list.pug (๋ชฉ๋ก)
2.
board/insert.pug (๊ธ€์“ฐ๊ธฐ)
3.
board/read.pug (๊ธ€์ฝ๊ธฐ)
4.
board/update.pug (๊ธ€์ˆ˜์ •)

board/list.pug

extends ../layout block content div.container-lg div.btn-box h1 ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก a.btn(href="/board/insert") ๊ธ€์“ฐ๊ธฐ table.table(border=1) thead tr th No th Title th Writer tbody each board, index in boardList tr td(width=80)= index td a(href=`/board/${index}`) #{board.title} td(width=200)= board.writer
HTML
๋ณต์‚ฌ

board/insert.pug

extends ../layout block content div.container-lg h1 ๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก form(action="/board", method="post") table.table.form-group(border=1) tr th(width="200") Title td input(type="text", name="title") tr th(width="200") Writer td input(type="text", name="writer") tr th(width="200") Content td input(type="text", name="content") div.btn-box a.btn(href="/board") ๋ชฉ๋ก button.btn(type="submit") ๋“ฑ๋ก
HTML
๋ณต์‚ฌ

board/read.pug

extends ../layout block content div.container-lg h1 #{board.title} table.table(border=1) tr th(width="200") No td #{id} tr th(width="200") Writer td #{board.writer} tr th(width="200") Content td #{board.content} div.btn-box a.btn(href="/board") ๋ชฉ๋ก a.btn(href=`/board/update/${id}`) ์ˆ˜์ •
HTML
๋ณต์‚ฌ

board/update.pug

extends ../layout block content div.container-lg h1 ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • form(action="/board/update", method="post") input(type="hidden", name="id" value=`${id}`) table.table.form-group(border=1) tr th(width="200") No td #{id} tr th(width="200") Title td input(type="text", name="title", value=`${board.title}`) tr th(width="200") Writer td input(type="text", name="writer", value=`${board.writer}`) tr th(width="200") Content td input(type="text", name="content", value=`${board.content}`) div.btn-box a.btn(href="/board") ๋ชฉ๋ก button.btn(type="submit") ์ˆ˜์ •
HTML
๋ณต์‚ฌ

app.js ์ „์ฒด์ฝ”๋“œ

const express = require('express'); const morgan = require('morgan'); const cookieParser = require('cookie-parser'); const session = require('express-session'); const path = require('path'); // ๐Ÿ‘ฉโ€๐Ÿ’ป ๋ผ์šฐํ„ฐ ๋ชจ๋“ˆ import const indexRouter = require('./routes/index'); const boardRouter = require('./routes/board'); const app = express(); // ํฌํŠธ ์„ค์ •: 3000 ์‚ฌ์šฉ app.set('port', 3000); // ๋ทฐ ์—”์ง„ ์„ค์ •: Pug๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์„ค์ • app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'pug'); // ๋กœ๊น… ๋ฏธ๋“ค์›จ์–ด ์„ค์ •: ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์—์„œ๋Š” dev ๋ชจ๋“œ๋กœ ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅ app.use(morgan('dev')); // ์ •์  ํŒŒ์ผ ์ œ๊ณต ๋ฏธ๋“ค์›จ์–ด ์„ค์ •: public ํด๋”๋ฅผ ์ •์  ํŒŒ์ผ ์ œ๊ณต ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์„ค์ • app.use('/', express.static(path.join(__dirname, 'public'))); // JSON ํŒŒ์‹ฑ ๋ฏธ๋“ค์›จ์–ด ์„ค์ • // - JSON ํ˜•์‹์˜ ์š”์ฒญ ๋ณธ๋ฌธ์„ ํŒŒ์‹ฑ // - URL ์ธ์ฝ”๋”ฉ๋œ ์š”์ฒญ ๋ณธ๋ฌธ์„ ํŒŒ์‹ฑ app.use(express.json()); app.use(express.urlencoded({ extended: false })); // cookie-parser ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฟ ํ‚ค๋ฅผ ํŒŒ์‹ฑํ•˜๋Š” ๋ถ€๋ถ„ app.use(cookieParser()); // Express ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์„ธ์…˜ ๋ฏธ๋“ค์›จ์–ด ์„ค์ • app.use(session({ resave: false, // ์„ธ์…˜ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฉด ์„œ๋ฒ„์— ๋‹ค์‹œ ์ €์žฅํ•˜์ง€ ์•Š์Œ saveUninitialized: false, // ์ดˆ๊ธฐํ™”๋˜์ง€ ์•Š์€ ์„ธ์…˜์„ ์ €์žฅ์†Œ์— ์ €์žฅํ•˜์ง€ ์•Š์Œ secret: 'session-secret', // ์„ธ์…˜ ์ฟ ํ‚ค ์„ค์ • cookie: { httpOnly: true, // ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ฟ ํ‚ค์— ์ ‘๊ทผํ•  ๋•Œ๋งŒ ๊ฐ€๋Šฅํ•˜๋„๋ก httpOnly ์†์„ฑ ์‚ฌ์šฉ secure: false, // HTTPS๊ฐ€ ์•„๋‹Œ ํ™˜๊ฒฝ์—์„œ๋„ ์ฟ ํ‚ค ์ „์†ก ํ—ˆ์šฉ }, name: 'session-cookie', // ์„ธ์…˜ ์ฟ ํ‚ค์˜ ์ด๋ฆ„ ์„ค์ • })); // ๐Ÿ‘ฉโ€๐Ÿ’ป ๋ผ์šฐํ„ฐ ์„ค์ • app.use('/', indexRouter); app.use('/board', boardRouter); // 404 ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด app.use((req, res, next) => { // ์š”์ฒญ๋œ ๊ฒฝ๋กœ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ 404 ์ƒํƒœ ์ฝ”๋“œ์™€ 'Not Found' ๋ฉ”์‹œ์ง€๋ฅผ ์‘๋‹ต์œผ๋กœ ์ „์†ก res.status(404).send('Not Found'); }); // ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฏธ๋“ค์›จ์–ด app.use((err, req, res, next) => { // ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์ฝ˜์†”์— ์ถœ๋ ฅํ•˜๊ณ  500 ์ƒํƒœ ์ฝ”๋“œ์™€ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ์‘๋‹ต์œผ๋กœ ์ „์†ก console.error(err); res.status(500).send(err.message); }); // Express ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ํŠน์ • ํฌํŠธ์—์„œ ์‹คํ–‰ํ•˜๋Š” ๋ถ€๋ถ„ app.listen(app.get('port'), () => { // ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋˜๋ฉด ์ฝ˜์†”์— ํ•ด๋‹น ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘์ž„์„ ์ถœ๋ ฅ console.log(app.get('port'), '๋ฒˆ ํฌํŠธ์—์„œ ๋Œ€๊ธฐ ์ค‘'); });
JavaScript
๋ณต์‚ฌ

์‹คํ–‰ ํ™”๋ฉด

/

๋ฉ”์ธํ™”๋ฉด

/login

๋กœ๊ทธ์ธ ํ™”๋ฉด

/join

ํšŒ์›๊ฐ€์ž… ํ™”๋ฉด

/board

๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก

/board/insert

๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก

/board/0

๊ฒŒ์‹œ๊ธ€ ์ฝ๊ธฐ

/board/update/0

๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •