๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Dev.log/Node.js

[Node.js ๊ต๊ณผ์„œ] #20. ์ต์Šคํ”„๋ ˆ์Šค ์›น ์„œ๋ฒ„ ๋งŒ๋“ค๊ธฐ - ๋ฏธ๋“ค์›จ์–ด

๋ฏธ๋“ค์›จ์–ด

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

 

๋ฏธ๋“ค์›จ์–ด๋Š” ์ฃผ๋กœ app.use์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋œ๋‹ค.

 

 

app.use์˜ ์ธ์ž๋กœ ๋“ค์–ด ์žˆ๋Š” ํ•จ์ˆ˜๊ฐ€ ๋ฏธ๋“ค์›จ์–ด์ด๋‹ค. ๋ฏธ๋“ค์›จ์–ด๋Š” use ๋ฉ”์„œ๋“œ๋กœ app์— ์žฅ์ฐฉํ•œ๋‹ค. ์ œ์ผ ์œ„์˜ logger('dev')๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜์—ฌ ๋ฏธ๋“ค์›จ์–ด๋“ค์„ ์ˆœ์ฐจ์ ์œผ๋กœ ๊ฑฐ์นœ ํ›„ ๋ผ์šฐํ„ฐ์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ์‘๋‹ต์„ ๋ณด๋‚ธ๋‹ค.

 

1. ์ปค์Šคํ…€ ๋ฏธ๋“ค์›จ์–ด ๋งŒ๋“ค๊ธฐ

์š”์ฒญ์ด ๋“ค์–ด์˜ฌ ๋•Œ ์ฝ˜์†”์— ๋ฉ”์‹œ์ง€๋ฅผ ์ฐ๋Š” ๋‹จ์ˆœํ•œ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž. app.js์—์„œ logger๋ณด๋‹ค ์œ„์— ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์ ์–ด์ค€๋‹ค.

 

 

app.js ํŒŒ์ผ์„ ์ €์žฅํ•˜๊ณ  ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

 

์„œ๋ฒ„ ์‹คํ–‰ ์‹œ

 

localhost:3000 ์ ‘์† ์‹œ

 

localhost:3000 ์ ‘์† ์‹œ ์ฝ˜์†” ํ™•์ธ

 

์š”์ฒญ ๋‘ ๊ฐœ, ์ฆ‰ GET /์™€ GET /stylesheet.style.css๊ฐ€ ์„œ๋ฒ„๋กœ ์ „๋‹ฌ๋˜์—ˆ๋‹ค. ๊ฐ๊ฐ์˜ ์š”์ฒญ์ด ๋ชจ๋‘ ๋ฐฉ๊ธˆ ๋งŒ๋“  ์ปค์Šคํ…€ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์ž‘๋™์‹œ์ผฐ๋‹ค. ์ด๋ ‡๊ฒŒ ์„œ๋ฒ„๊ฐ€ ๋ฐ›์€ ์š”์ฒญ์€ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ํƒ€๊ณ  ๋ผ์šฐํ„ฐ๊นŒ์ง€ ์ „๋‹ฌ๋œ๋‹ค.

์ฃผ์˜ํ•ด์•ผํ•  ์ ์ด ์žˆ๋‹ค. ๋ฐ˜๋“œ์‹œ ๋ฏธ๋“ค์›จ์–ด ์•ˆ์—์„œ next()๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐ„๋‹ค. logger๋‚˜ express.json, express.urlencoded, cookieParser, express.static ๋ชจ๋‘ ๋‚ด๋ถ€์ ์œผ๋กœ๋Š” next()๋ฅผ ํ˜ธ์ถœํ•˜๋ฏ€๋กœ ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค. next()๋Š” ๋ฏธ๋“ค์›จ์–ด์˜ ํ๋ฆ„์„ ์ œ์–ดํ•˜๋Š” ํ•ต์‹ฌ์ ์ธ ํ•จ์ˆ˜์ด๋‹ค.

ํ™•์ธ์„ ์œ„ํ•ด next()๋ฅผ ๋นผ๋ณด์ž.

 

 

next()๋ฅผ ์ฃผ์„์ฒ˜๋ฆฌํ•œ ํ›„ localhost:3000 ์ ‘์†ํ–ˆ์„ ์‹œ ์ฝ˜์†”

 

next()๋ฅผ ์ฃผ์„์ฒ˜๋ฆฌํ•œ ํ›„ localhost:3000 ์ ‘์†ํ–ˆ์„ ์‹œ ์‘๋‹ต์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์Œ

 

์žฌ์‹คํ–‰ ํ›„ ๋‹ค์‹œ ์ ‘์†ํ•˜๋ฉด ์•„๋ฌด๋Ÿฐ ์‘๋‹ต์ด ์—†๋‹ค. ๋ธŒ๋ผ์šฐ์ €์—์„œ๋„ ๊ณ„์† ๋กœ๋”ฉ ํ‘œ์‹œ๊ฐ€ ๋œฌ๋‹ค. next()๋ฅผ ๋„ฃ์ง€ ์•Š์•„ ์ปค์Šคํ…€ ๋ฏธ๋“ค์›จ์–ด์—์„œ ์š”์ฒญ์˜ ํ๋ฆ„์ด ๋Š๊ฒจ๋ฒ„๋ฆฐ ๊ฒƒ์ด๋‹ค.

next() ํ•จ์ˆ˜์—๋Š” ๋ช‡ ๊ฐ€์ง€ ๊ธฐ๋Šฅ์ด ๋” ์žˆ๋‹ค. ์ธ์ž์˜ ์ข…๋ฅ˜๋กœ ๊ธฐ๋Šฅ์ด ๊ตฌ๋ถ„๋œ๋‹ค. ์ธ์ž๋ฅผ ์•„๋ฌด๊ฒƒ๋„ ๋„ฃ์ง€ ์•Š์œผ๋ฉด ๋‹จ์ˆœํ•˜๊ฒŒ ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐ€๊ณ , ์ธ์ž๋กœ route๋ฅผ ๋„ฃ์œผ๋ฉด ํŠน์ˆ˜ํ•œ ๊ธฐ๋Šฅ์„ ํ•œ๋‹ค. (์ถ”ํ›„ ๋‹ค๋ฃฐ ์˜ˆ์ •) route ์™ธ์˜ ๋‹ค๋ฅธ ๊ฐ’์„ ๋„ฃ์œผ๋ฉด ๋‹ค๋ฅธ ๋ฏธ๋“ค์›จ์–ด๋‚˜ ๋ผ์šฐํ„ฐ๋ฅผ ๊ฑด๋„ˆ๋›ฐ๊ณ  ๋ฐ”๋กœ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ๋กœ ์ด๋™ํ•œ๋‹ค. ๋„ฃ์–ด์ค€ ๊ฐ’์€ ์—๋Ÿฌ์— ๋Œ€ํ•œ ๋‚ด์šฉ์œผ๋กœ ๊ฐ„์ฃผ๋œ๋‹ค.

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

 

 

๋ผ์šฐํ„ฐ ๋‹ค์Œ์— ๋‚˜์˜ค๋Š” ์ด ๋ถ€๋ถ„์ด 404 ์—๋Ÿฌ๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ๋ฏธ๋“ค์›จ์–ด์ด๋‹ค. ๋ผ์šฐํ„ฐ์—์„œ ์š”์ฒญ์ด ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์œผ๋ฉด(์ผ์น˜ํ•˜๋Š” ์ฃผ์†Œ๊ฐ€ ์—†๋‹ค๋ฉด) ์š”์ฒญ์€ ๋ผ์šฐํ„ฐ ๋‹ค์Œ์— ์œ„์น˜ํ•œ ์ด ๋ฏธ๋“ค์›จ์–ด๋กœ ์˜ค๊ฒŒ ๋œ๋‹ค. http-errors(createError) ํŒจํ‚ค์ง€๊ฐ€ 404 ์—๋Ÿฌ๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๊ณ , ์ด ์—๋Ÿฌ๋ฅผ next์— ๋‹ด์•„ ์—๋Ÿฌ ํ•ธ๋“ค๋Ÿฌ๋กœ ๋ณด๋‚ด๊ณ  ์žˆ๋‹ค. ์—๋Ÿฌ ํ•ธ๋“ค๋ง ๋ฏธ๋“ค์›จ์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ๊ฒผ๋‹ค.

 

 

๋‹ค๋ฅธ ๋ฏธ๋“ค์›จ์–ด์™€ ๋‹ค๋ฅด๊ฒŒ ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋„ค ๊ฐœ์ด๋‹ค. req ์ „์— err๋ผ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค. next ํ•จ์ˆ˜์— ๋„ฃ์–ด์ค€ ์ธ์ž๊ฐ€ err ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์—ฐ๊ฒฐ๋œ๋‹ค. ์—๋Ÿฌ ํ•ธ๋“ค๋ง ๋ฏธ๋“ค์›จ์–ด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ฏธ๋“ค์›จ์–ด ์ค‘ ์ œ์ผ ์•„๋ž˜์— ์œ„์น˜ํ•˜์—ฌ ์œ„์— ์žˆ๋Š” ๋ฏธ๋“ค์›จ์–ด์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์—๋Ÿฌ๋ฅผ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•œ๋‹ค.

์ด๋ฒˆ์—๋Š” app.user์˜ ์‘์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž. ํ•˜๋‚˜์˜ use์— ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ ์žฅ์ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ˆœ์„œ๋Œ€๋กœ ์‹คํ–‰๋œ๋‹ค.

 

 

์ด ์„ฑ์งˆ์„ ํ™œ์šฉํ•˜์—ฌ Express-generator๊ฐ€ ์ƒ์„ฑํ•œ ์ฝ”๋“œ๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

 

 

next๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์œผ๋ฉด ๋‹ค์Œ ๋ฏธ๋“ค์›จ์–ด๋กœ ๋„˜์–ด๊ฐ€์ง€ ์•Š๋Š”๋‹ค๋Š” ์„ฑ์งˆ์„ ์‚ฌ์šฉํ•ด์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฏธ๋“ค์›จ์–ด๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

 

 

2. morgan

ํ˜„์žฌ ์ฝ˜์†”์— ๋‚˜์˜ค๋Š” GET / 200 51.267 ms - 1539 ๊ฐ™์€ ๋กœ๊ทธ๋Š” ๋ชจ๋‘ morgan ๋ฏธ๋“ค์›จ์–ด์—์„œ ๋‚˜์˜ค๋Š” ๊ฒƒ์ด๋‹ค. ์š”์ฒญ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ฝ˜์†”์— ๊ธฐ๋กํ•ด์ค€๋‹ค.

morgan ๋ฏธ๋“ค์›จ์–ด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•œ๋‹ค.

 

...
var logger = require('morgan');
...
app.use(logger('dev'));
...

 

ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ dev ๋Œ€์‹  short, common, combined ๋“ฑ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ธ์ž์— ๋”ฐ๋ผ ์ฝ˜์†”์— ๋‚˜์˜ค๋Š” ๋กœ๊ทธ๊ฐ€ ๋‹ค๋ฅด๋‹ค. dev์ธ ๊ฒฝ์šฐ GET / 200 51.267 ms - 1539 ์˜ ์˜๋ฏธ๋Š” ์ˆœ์„œ๋Œ€๋กœ HTTP ์š”์ฒญ(GET) ์ฃผ์†Œ(/) HTTP ์ƒํƒœ์ฝ”๋“œ(200) ์‘๋‹ต์†๋„(51.267ms) - ์‘๋‹ต๋ฐ”์ดํŠธ(1539) ์ด๋‹ค.

๋ณดํ†ต ๊ฐœ๋ฐœ ์‹œ์—๋Š” short๋‚˜ dev๋ฅผ ๋งŽ์ด ์“ฐ๊ณ , ๋ฐฐํฌ ์‹œ์—๋Š” common์ด๋‚˜ combined๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค. 

 

 

 

 

 

์ฝ˜์†”๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํŒŒ์ผ์ด๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋กœ๊ทธ๋ฅผ ๋‚จ๊ธธ ์ˆ˜๋„ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ž‘์—…์„ ํ•  ๋•Œ๋Š” winston ๋ชจ๋“ˆ์„ ๋” ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค.

3. body-parser

์š”์ฒญ์˜ ๋ณธ๋ฌธ์„ ํ•ด์„ํ•ด์ฃผ๋Š” ๋ฏธ๋“ค์›จ์–ด์ด๋‹ค. ๋ณดํ†ต ํผ ๋ฐ์ดํ„ฐ๋‚˜ AJAX ์š”์ฒญ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.

 

...
var bodyParser = require('body-parser');
...
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false});
...

 

์šฐ๋ฆฌ๊ฐ€ ์ƒ์„ฑํ•œ app.js์—์„œ๋Š” body-parser๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•˜๋‹ค. ์ต์Šคํ”„๋ ˆ์Šค 4.16.0 ๋ฒ„์ „๋ถ€ํ„ฐ body-parser์˜ ์ผ๋ถ€ ๊ธฐ๋Šฅ์ด ์ต์Šคํ”„๋ ˆ์Šค์— ๋‚ด์žฅ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๊ทธ๋ž˜์„œ body-parser๋ฅผ ์„ค์น˜ํ•˜์ง€ ์•Š๊ณ ๋„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

 

๋‹จ, body-parser๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค. body-parser๋Š” JSON๊ณผ URL-encoded ํ˜•์‹์˜ ๋ณธ๋ฌธ ์™ธ์—๋„ Raw, Text ํ˜•์‹์˜ ๋ณธ๋ฌธ์„ ์ถ”๊ฐ€๋กœ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋‹ค.

Raw๋Š” ๋ณธ๋ฌธ์ด ๋ฒ„ํผ ๋ฐ์ดํ„ฐ์ผ ๋•Œ, Text๋Š” ๋ณธ๋ฌธ์ด ํ…์ŠคํŠธ ๋ฐ์ดํ„ฐ์ผ ๋•Œ ํ•ด์„ํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด์ด๋‹ค. ์„œ๋น„์Šค์— ์ ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด body-parser๋ฅผ ์„ค์น˜ํ•œ ํ›„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถ”๊ฐ€ํ•œ๋‹ค.

 

app.use(bodyParser.raw());
app.use(bodyParser.text());

 

JSON์€ JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ ๋ฐฉ์‹์ด๊ณ , URL-encoded๋Š” ์ฃผ์†Œ ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๋Š” ๋ฐฉ์‹์ด๋‹ค. ๋ณดํ†ต ํผ ์ „์†ก์ด URL-encoded ๋ฐฉ์‹์„ ์ฃผ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. urlencoded ๋ฉ”์„œ๋“œ๋ฅผ ๋ณด๋ฉด { extended: false }๋ผ๋Š” ์˜ต์…˜์ด ๋“ค์–ด ์žˆ๋‹ค. ์ด ์˜ต์…˜์ด false๋ฉด ๋…ธ๋“œ์˜ querystring ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ํ•ด์„ํ•˜๊ณ , true๋ฉด qs ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ํ•ด์„ํ•œ๋‹ค. qs ๋ชจ๋“ˆ์€ ๋‚ด์žฅ ๋ชจ๋“ˆ์ด ์•„๋‹ˆ๋ผ npm ํŒจํ‚ค์ง€์ด๋ฉฐ, querystring ๋ชจ๋“ˆ์˜ ๊ธฐ๋Šฅ์„ ์กฐ๊ธˆ ๋” ํ™•์žฅํ•œ ๋ชจ๋“ˆ์ด๋‹ค.

์ด์ „์— POST์™€ PUT ์š”์ฒญ์˜ ๋ณธ๋ฌธ์„ ์ „๋‹ฌ๋ฐ›์œผ๋ ค๋ฉด req.on('data')์™€ req.on('end')๋กœ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์—ˆ๋Š”๋ฐ body-parser๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ๋Ÿด ํ•„์š”๊ฐ€ ์—†๋‹ค. ์ด ํŒจํ‚ค์ง€๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ ๋ณธ๋ฌธ์„ ํ•ด์„ํ•ด req.body์— ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด JSON ํ˜•์‹์œผ๋กœ {name: 'zerocho', book: 'nodejs'}๋ฅผ ๋ณธ๋ฌธ์œผ๋กœ ๋ณด๋‚ธ๋‹ค๋ฉด req.body์— ๊ทธ๋Œ€๋กœ ๋“ค์–ด๊ฐ„๋‹ค. URL-encoded ํ˜•์‹์œผ๋กœ name=zerocho&book=nodejs๋ฅผ ๋ณธ๋ฌธ์œผ๋กœ ๋ณด๋‚ธ๋‹ค๋ฉด req.body์— {name: 'zerocho', book: 'nodejs'}๊ฐ€ ๋“ค์–ด๊ฐ„๋‹ค.

body-parser๊ฐ€ ๋ชจ๋“  ๋ณธ๋ฌธ์„ ํ•ด์„ํ•ด์ฃผ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. multipart/form-data ๊ฐ™์€ ํผ์„ ํ†ตํ•ด ์ „์†ก๋œ ๋ฐ์ดํ„ฐ๋Š” ํ•ด์„ํ•˜์ง€ ๋ชปํ•œ๋‹ค. ์ด๋Š” ๋‹ค๋ฅธ ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•ด์„œ ํ•ด์„ํ•ด์•ผ ํ•œ๋‹ค.

4. cookie-parser

cookie-parser๋Š” ์š”์ฒญ์— ๋™๋ด‰๋œ ์ฟ ํ‚ค๋ฅผ ํ•ด์„ํ•ด์ค€๋‹ค. 

 

...
var cookieParser = require('cookie-parser');
...
app.use(cookieParser());
...

 

ํ•ด์„๋œ ์ฟ ํ‚ค๋“ค์€ req.cookies ๊ฐ์ฒด์— ๋“ค์–ด๊ฐ„๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, name=zerocho ์ฟ ํ‚ค๋ฅผ ๋ณด๋ƒˆ๋‹ค๋ฉด req.cookies๋Š” { name: 'zerocho' }๊ฐ€ ๋œ๋‹ค.

 

app.use(cookieparser('secret code');

 

์ด์™€ ๊ฐ™์ด ์ฒซ ๋ฒˆ์งธ ์ธ์ž๋กœ ๋ฌธ์ž์—ด์„ ๋„ฃ์–ด์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ด์ œ ์ฟ ํ‚ค๋“ค์€ ์ œ๊ณตํ•œ ๋ฌธ์ž์—ด๋กœ ์„œ๋ช…๋œ ์ฟ ํ‚ค๊ฐ€ ๋œ๋‹ค. ์„œ๋ช…๋œ ์ฟ ํ‚ค๋Š” ํด๋ผ์ด์–ธํŠธ์—์„œ ์ˆ˜์ •ํ–ˆ์„ ๋•Œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์ฟ ํ‚ค๋กœ ์œ„ํ—˜ํ•œ ํ–‰๋™์„ ํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

5. static

static ๋ฏธ๋“ค์›จ์–ด๋Š” ์ •์ ์ธ ํŒŒ์ผ๋“ค์„ ์ œ๊ณตํ•œ๋‹ค. ์ต์Šคํ”„๋ ˆ์Šค๋ฅผ ์„ค์น˜ํ•˜๋ฉด ๋”ฐ๋ผ์˜ค๋ฏ€๋กœ ๋”ฐ๋กœ ์„ค์น˜ํ•  ํ•„์š”๋Š” ์—†๋‹ค.

 

...
app.use(express.static(path.join(__dirname, 'public')));
...

 

ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ •์  ํŒŒ์ผ๋“ค์ด ๋‹ด๊ฒจ ์žˆ๋Š” ํด๋”๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋œ๋‹ค. ํ˜„์žฌ public ํด๋”๊ฐ€ ์ง€์ •๋˜์–ด ์žˆ๋‹ค. public/stylesheets/style.css๋Š” http://localhost:3000/stylesheets/style.css๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. 

์‹ค์ œ ์„œ๋ฒ„์˜ ํด๋” ๊ฒฝ๋กœ์—๋Š” public์ด ๋“ค์–ด ์žˆ์ง€๋งŒ, ์š”์ฒญ ์ฃผ์†Œ์—๋Š” public์ด ๋“ค์–ด ์žˆ์ง€ ์•Š๋‹ค๋Š” ์ ์„ ์ฃผ๋ชฉํ•ด์•ผ ํ•œ๋‹ค. ์„œ๋ฒ„์˜ ํด๋” ๊ฒฝ๋กœ์™€ ์š”์ฒญ ๊ฒฝ๋กœ๊ฐ€ ๋‹ค๋ฅด๋ฏ€๋กœ ์™ธ๋ถ€์ธ์ด ์„œ๋ฒ„์˜ ๊ตฌ์กฐ๋ฅผ ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์—†๋‹ค. ์ด๋Š” ๋ณด์•ˆ์— ํฐ ๋„์›€์ด ๋œ๋‹ค.

๋˜ํ•œ, ์ •์ž‘ ํŒŒ์ผ๋“ค์„ ์•Œ์•„์„œ ์ œ๊ณตํ•ด์ฃผ๋ฏ€๋กœ ์ด์ „ ์˜ˆ์ œ์ฒ˜๋Ÿผ fs.readFile๋กœ ํŒŒ์ผ์„ ์ง์ ‘ ์ฝ์–ด์„œ ์ „์†กํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

 

app.use('/img', express.static(path.join(__dirname, 'public')));

์ด์™€ ๊ฐ™์ด ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•  ์ฃผ์†Œ๋ฅผ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. public ํด๋” ์•ˆ์— abc.png๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด ์•ž์— /img ๊ฒฝ๋กœ๋ฅผ ๋ถ™์ธ http://localhost:3000/img/abc.png ์ฃผ์†Œ๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

static ๋ฏธ๋“ค์›จ์–ด๋Š” ์š”์ฒญ์— ๋ถ€ํ•ฉํ•˜๋Š” ์ •์  ํŒŒ์ผ์„ ๋ฐœ๊ฒฌํ•œ ๊ฒฝ์šฐ ์‘๋‹ต์œผ๋กœ ํ•ด๋‹น ํŒŒ์ผ์„ ์ „์†กํ•œ๋‹ค. ์ด ๊ฒฝ์šฐ ์‘๋‹ต์„ ๋ณด๋ƒˆ์œผ๋ฏ€๋กœ ๋‹ค์Œ์— ๋‚˜์˜ค๋Š” ๋ผ์šฐํ„ฐ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค. ๋งŒ์•ฝ ํŒŒ์ผ์„ ์ฐพ์ง€ ๋ชปํ•˜๋ฉด ์š”์ฒญ์„ ๋ผ์šฐํ„ฐ๋กœ ๋„˜๊ธด๋‹ค.

์ด๋ ‡๊ฒŒ ์ž์ฒด์ ์œผ๋กœ ์ •์  ํŒŒ์ผ ๋ผ์šฐํ„ฐ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋ฏ€๋กœ ์ตœ๋Œ€ํ•œ ์œ„์ชฝ์— ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๊ทธ๋ž˜์•ผ ์„œ๋ฒ„๊ฐ€ ์“ธ๋ฐ์—†๋Š” ๋ฏธ๋“ค์›จ์–ด ์ž‘์—…์„ ํ•˜๋Š” ๊ฒƒ์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

๊ธฐ์กด ์ฝ”๋“œ์—์„œ๋Š” morgan, json, urlencoded, cookie-parser ๋ฏธ๋“ค์›จ์–ด๋ฅผ ๊ฑฐ์ณ์•ผ static ๋ฏธ๋“ค์›จ์–ด์— ๋„๋‹ฌํ•œ๋‹ค. ์š”์ฒญ์„ ๊ธฐ๋กํ•˜๋Š” morgan์„ ์ œ์™ธํ•˜๊ณ  ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์˜ํ–ฅ์„ ๋ผ์น˜์ง€ ์•Š๋Š” json, urlencoded, cookie-parser๋ฅผ ๊ฑฐ์น˜๋Š” ๊ฒƒ์€ ๋‚ญ๋น„์ด๋‹ค. ๋”ฐ๋ผ์„œ ์ˆœ์„œ๋ฅผ ๋ฐ”๊ฟ”์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์ฐธ๊ณ ๋กœ ์„œ๋น„์Šค์— ๋”ฐ๋ผ ์ฟ ํ‚ค ๊ฐ™์€ ๊ฒƒ์ด ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์˜ํ–ฅ์„ ๋ผ์น  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ์ž์‹ ์˜ ์„œ๋น„์Šค์— ๋งž๋Š” ์œ„์น˜๋ฅผ ์„ ํƒํ•ด์•ผ ํ•œ๋‹ค.

6. express-session

์„ธ์…˜ ๊ด€๋ฆฌ์šฉ ๋ฏธ๋“ค์›จ์–ด์ด๋‹ค. ๋กœ๊ทธ์ธ ๋“ฑ์˜ ์ด์œ ๋กœ ์„ธ์…˜์„ ๊ตฌํ˜„ํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•˜๋‹ค. express-generator๋กœ๋Š” ์„ค์น˜๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ง์ ‘ ์„ค์น˜ํ•ด์•ผ ํ•œ๋‹ค.

 

 

์„ค์น˜ ํ›„ app.js์— express-session์„ ์—ฐ๊ฒฐํ•œ๋‹ค.

 

...
var session = require('express-session');
...
app.use(cookieParser());
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: 'secret code',
  cookie: {
    httpOnly: true,
    secure: false
  }
}));
...

 

express-session 1.5 ๋ฒ„์ „ ์ด์ „์—๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ cookie-parser๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด์„œ cookie-parser ๋ฏธ๋“ค์›จ์–ด๋ณด๋‹ค ๋’ค์— ์œ„์น˜ํ•ด์•ผ ํ–ˆ์ง€๋งŒ, 1.5 ๋ฒ„์ „ ์ดํ›„๋ถ€ํ„ฐ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ฒŒ ๋˜์–ด ์ˆœ์„œ๊ฐ€ ์ƒ๊ด€ ์—†์–ด์กŒ๋‹ค. ๊ทธ๋ž˜๋„ ํ˜„์žฌ ์–ด๋–ค ๋ฒ„์ „์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”์ง€ ๋ชจ๋ฅธ๋‹ค๋ฉด cookie-parser ๋ฏธ๋“ค์›จ์–ด ๋’ค์— ๋†“๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•˜๋‹ค.

express-session์€ ์ธ์ž๋กœ ์„ธ์…˜์— ๋Œ€ํ•œ ์„ค์ •์„ ๋ฐ›๋Š”๋‹ค.

  • resave : ์š”์ฒญ์ด ์™”์„ ๋•Œ ์„ธ์…˜์— ์ˆ˜์ •์‚ฌํ•ญ์ด ์ƒ๊ธฐ์ง€ ์•Š๋”๋ผ๋„ ์„ธ์…˜์„ ๋‹ค์‹œ ์ €์žฅํ• ์ง€์— ๋Œ€ํ•œ ์„ค์ •์ด๋‹ค.
  • saveUninitialized : ์„ธ์…˜์— ์ €์žฅํ•  ๋‚ด์—ญ์ด ์—†๋”๋ผ๋„ ์„ธ์…˜์„ ์ €์žฅํ• ์ง€์— ๋Œ€ํ•œ ์„ค์ •์ด๋‹ค. ๋ณดํ†ต ๋ฐฉ๋ฌธ์ž๋ฅผ ์ถ”์ ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.
  • secret : ํ•„์ˆ˜ ํ•ญ๋ชฉ์œผ๋กœ cookie-parser์˜ ๋น„๋ฐ€ํ‚ค์™€ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค. express-session์€ ์„ธ์…˜ ๊ด€๋ฆฌ ์‹œ ํด๋ผ์ด์–ธํŠธ์— ์ฟ ํ‚ค๋ฅผ ๋ณด๋‚ธ๋‹ค. ์ด๋ฅผ ์„ธ์…˜ ์ฟ ํ‚ค๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. ์•ˆ์ „ํ•˜๊ฒŒ ์ฟ ํ‚ค๋ฅผ ์ „์†กํ•˜๋ ค๋ฉด ์ฟ ํ‚ค์— ์„œ๋ช…์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜๊ณ , ์ฟ ํ‚ค๋ฅผ ์„œ๋ช…ํ•˜๋Š” ๋ฐ secret์˜ ๊ฐ’์ด ํ•„์š”ํ•˜๋‹ค. cookie-parser์˜ secret๊ณผ ๊ฐ™๊ฒŒ ์„ค์ •ํ•ด์•ผ ํ•œ๋‹ค.
  • cookie : ์„ธ์…˜ ์ฟ ํ‚ค์— ๋Œ€ํ•œ ์„ค์ •์ด๋‹ค. maxAge, domain, path, expires, sameSite, httpOnly, secure ๋“ฑ ์ผ๋ฐ˜์ ์ธ ์ฟ ํ‚ค ์˜ต์…˜์ด ๋ชจ๋‘ ์ œ๊ณต๋œ๋‹ค.

express-session์€ req ๊ฐ์ฒด ์•ˆ์— req.session ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค. ์ด ๊ฐ์ฒด์— ๊ฐ’์„ ๋Œ€์ž…ํ•˜๊ฑฐ๋‚˜ ์‚ญ์ œํ•ด์„œ ์„ธ์…˜์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‚˜์ค‘์— ์„ธ์…˜์„ ํ•œ ๋ฒˆ์— ์‚ญ์ œํ•˜๋ ค๋ฉด req.session.destroy() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค. ํ˜„์žฌ ์„ธ์…˜์˜ ์•„์ด๋””๋Š” req.sessionId๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

7. connect-flash

์ƒ๋Œ€์ ์œผ๋กœ ์ค‘์š”๋„๊ฐ€ ๋–จ์–ด์ง€๋Š” ๋ฏธ๋“ค์›จ์–ด์ด๋‹ค. ํ•˜์ง€๋งŒ ์ผํšŒ์„ฑ ๋ฉ”์‹œ์ง€๋“ค์„ ์›น ๋ธŒ๋ผ์šฐ์ €์— ๋‚˜ํƒ€๋‚ผ ๋•Œ ์ข‹๋‹ค. express-session๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ง์ ‘ ์„ค์น˜ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 

 

connect-flash ๋ฏธ๋“ค์›จ์–ด๋Š” cookie-parser์™€ express-session์„ ์ด์šฉํ•˜๋ฏ€๋กœ ์ด๋“ค๋ณด๋‹ค๋Š” ๋’ค์— ์œ„์น˜ํ•ด์•ผ ํ•œ๋‹ค.

 

...
var session = require('express-session');
var flash = require('connect-flash');
...
app.use(session({
  resave: false,
  saveUninitialized: false,
  secret: 'secret code',
  cookie: {
    httpOnly: true,
    secure: false
  }
}));
app.use(flash());
...

 

flash ๋ฏธ๋“ค์›จ์–ด๋Š” req ๊ฐ์ฒด์— req.flash ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. req.flash(ํ‚ค, ๊ฐ’)์œผ๋กœ ํ•ด๋‹น ํ‚ค์— ๊ฐ’์„ ์„ค์ •ํ•˜๊ณ , req.flash(ํ‚ค)๋กœ ํ•ด๋‹น ํ‚ค์— ๋Œ€ํ•œ ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜จ๋‹ค. 

 

routes/users.js

 

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