๐ฅ TIL #1. Node์ ๋ํ ์ดํด์ ๋ง๋ณด๊ธฐ
๐ Today I learned
- node ๊ณต๋ถ๋ฅผ ์ํด ์์์ผ ํ ์ง์
- node ๋ก server ์คํ ํด๋ณด๊ธฐ
- express๋ก routing ๊ฐ์ํ ํ๊ธฐ
- ๊ฐ๋ฐ์ ์ํด ์์์ผ ํ ๊ธฐ์ (์๋ฒ ์๋ ์ฌ์คํ, npm)
1. node ๊ณต๋ถ๋ฅผ ์ํด ์์์ผ ํ ์ง์
node๋ ๋น๋๊ธฐ(Asynchronous) ์ด๋ฒคํธ ๊ธฐ๋ฐ(event-driven) javascript runtime ํ๊ฒฝ์ด๋ค.
1. ๋น๋๊ธฐ(Asynchronous)
๋น๋๊ธฐ๋ ์ฌ๋ฌ๊ฐ์ง ์์ ์ ๋์์ ํ๋ ๊ฒ์ ์๋ฏธํ๋ค. ์๋ก ์ง์์ผ์ ์๊ฐํด๋ณด์.
๋นจ๋, ์ค๊ฑฐ์ง๋ฅผ ํด์ผ ํ๋ ์ํฉ์ผ ๋ ์ฐ๋ฆฌ๋ '๋นจ๋'๋ผ๋ ์์ ์ ์ธํ๊ธฐ์๊ฒ ๋งก๊ธฐ๊ณ ์ค๊ฑฐ์ง๋ฅผ ํ ๊ฒ์ด๋ค. ๋ ๊ฐ์ง ์์ ์ด ๋์์ ์ฒ๋ฆฌ๋๋ฏ๋ก ์ด๋ฅผ ๋น๋๊ธฐ๋ผ ํ ์ ์๋ค. ๋ง์ฝ ์ฐ๋ฆฌ๊ฐ ์๋นจ๋๋ฅผ ํด์ผ ํ๋ ์ํฉ์ด๋ฉด ๋นจ๋์ ์ค๊ฑฐ์ง๋ฅผ ์์ฐจ์ ์ผ๋ก ์งํํด์ผ ํ๋๋ฐ ์ด๋ ๋๊ธฐ ์ฒ๋ฆฌ์ด๋ค.
์ธํ๊ธฐ๋ ๋ํ์ ๋๋ถ์ ์ฐ๋ฆฌ๋ ์๊ฐ์ ์๋ ์ ์๋ค.2. ๋น๋๊ธฐ(Asynchronous) ์ด๋ฒคํธ ๊ธฐ๋ฐ(event-driven)
node ํ๊ฒฝ์์ event๋ ํ๋์ ์์ฒญ(http request)๊ณผ ๊ฐ๋ค.
'๋น๋๊ธฐ ์ด๋ฒคํธ ๊ธฐ๋ฐ'์ '๋น๋๊ธฐ๋ก ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌ'๋ฅผ ์๋ฏธํ๋ฉฐ client์ ์์ฒญ์ ๋ํ ์ฒ๋ฆฌ๊ฐ ๋๋๊ธฐ ์ ์ ๋ค์ client์ ์์ฒญ์ ๋ฐ์ ์ฒ๋ฆฌํ๋ ๊ฒ์ ๋งํ๋ค. ์ฆ, ํ ์์ ์์ ์ฌ๋ฌ ์์ฒญ์ ์ฒ๋ฆฌ ํ ์ ์๋ค. ์ฌ๊ธฐ์ 'single thread' ๊ฐ ๋ฑ์ฅํ๋ค.
ํ๋์ request๊ฐ ์์ ๋์ ์ฒ๋ฆฌ ๋ฃจํด์ ์๊ฐํด ๋ณด์.GET method๋ก ์ ๋ณด ๋ชฉ๋ก์ ๋ฌ๋ผ๋ ์์ฒญ์ผ ๊ฒฝ์ฐ ์ฒ๋ฆฌ๋ฅผ ์ํด Database์ ์ ๊ทผ, ํ์ํ data๋ฅผ ์์งํ์ฌ ์๋ตํด์ผ ํ๋ค. ์ด๋ Heavy loadํ ์์ ์ผ๋ก single thread์์ ์ฒ๋ฆฌํ์ง ์๊ณ INTENSIVE OPERATION(C++ thread pool) ์ ๋์ ์ฒ๋ฆฌํ ๋ก ์์ํ๋ค.
์ฆ single thread๋ ์ด๋ฒคํธ(์์ฒญ)์ ๋ํ ์ฒ๋ฆฌ(์๋ต)๋ง ๋ด๋นํ๋ค.๋จ์ง Javascript๋ก ์ฝ๋๋ฅผ ์์ฑํ ๋ฟ์ธ๋ฐ ์ด๋ป๊ฒ ์ด๋ฐ๊ฒ ๊ฐ๋ฅํ ๊น?
3. Javascript runtime ํ๊ฒฝ(chrome V8 Engine)
Javascript runtime ํ๊ฒฝ์ด๋?
JavaScript ๋ก ์ง์ฌ์ง ์์ค์ฝ๋๋ฅผ CPU๊ฐ ์ดํดํ ์ ์๋ ๊ธฐ๊ณ์ด(ex. 0๊ณผ 1๋ก ์ด๋ฃจ์ด์ง bytecode)๋ก ๋ณํ์ํค๊ณ ๋ํ ํ๋ก๊ทธ๋จ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๊ด๋ฆฌํ๋ ์์คํ
์ด๋ฐ ํ๊ฒฝ์ ๊ฐ๋ฅํ๊ฒ๋ ํ๋๊ฒ์ด chrome V8 Engine์ด๋ค. google web browser์์ ์ฌ์ฉ๋๋ ์์ง์ผ๋ก ์ด๋ฅผ browser ์์ด ์๋ํ ์ ์๋๋ก ๋ง๋ ๊ฒ์ด ๋ฐ๋ก node์ด๋ค.
2. node๋ก server ์คํ ํด๋ณด๊ธฐ
์๋ ์ฝ๋๋ http ๋ชจ๋์ ์ด์ฉํด server ์์ฑ ๋ฐ listening ํ๋๋ก ๊ตฌํํ ์ฝ๋์ด๋ค.
createServer() ํธ์ถ์ ํตํด ์น์๋ฒ๋ฅผ ๋ง๋ค ์ ์๋ค. ํธ์ถ์ ์ฃผ์ ํ๋ callback ํจ์๋ http request๊ฐ ์ฌ๋๋ง๋ค ํธ์ถ๋๋๋ฐ ์ด ๋ node ๊ฐ ํธ๋์ญ์ ์ ๋ค๋ฃจ๊ธฐ ์ํด request, response ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ค.
req ๊ฐ์ฒด์ 'url' ๋ฐ 'method' ์์ฑ์ ์ด์ฉ, routing ํ ์ ์์ผ๋ฉฐ ์ฌ๊ธฐ์ sendPosts๋ผ๋ ํจ์๊ฐ ์๋ต์ฒ๋ฆฌํ๋๋ก ๊ตฌํํ๋ค.
์๋ต(res)์ header์ content-type๋ฅผ json์ผ๋ก ์ค์ , ์๋ต์ jsonํ์์ผ๋ก ํ ๊ฒ์์ ์ง์ ํ๋ค.
require๋ ์ ์ญ ๋๋ ์ฌ์ฉ์ module์ importํ๋ ๊ธฐ๋ฅ์ด๋ค.// chapter1.js const http = require('http') const {sendPosts} = require('./sendPosts') const server = http.createServer((req, res) => { const {url, method} = req console.log(url, ' ', method) console.log('run server') res.setHeader('Content-Type', 'application/json') if (url === '/products' && method === 'GET') { sendPosts(res) return } res.end(JSON.stringify({message:'answer.'})) }) const PORT = 8000 server.listen(PORT, () => { console.log(`Server is listening on PORT ${PORT}`) })
์๋ ์ฝ๋๋ chapter1.js์์ /products routing์ ๋ํ ์ฒ๋ฆฌ๋ฅผ ํ๋ ํจ์๋ฅผ ๋ณ๋๋ก ์ ์ํ js ํ์ผ์ด๋ค.
ํธ์ถ์ res๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ res์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ฃผ๋ ํ์์ผ๋ก ๊ฐ์ฒด๋ฅผ Json.stringify()๋ฅผ ์ด์ฉํ์ฌ json ๋ฌธ์์ด๋ก converting ํ๋ค.
๋ง์ง๋ง ์ค์ module.exports ์ ํจ์๋ฅผ ๊ฐ์ฒด๋ก ์ง์ด๋ฃ๊ณ ์๋ค.
์ธ๋ถ๋ก exportํ ํจ์๋ module.exports์ ๋ฃ์ด์ผ ํ๋๋ฐ 'property:value' ํ์์ด ์ฐ๋ฆฌ๊ฐ ์๋ ๊ฐ์ฒด ์์ฑ ๋ฐฉ์์ด๋ property์ value๊ฐ ๊ฐ์ผ๋ฉด ์๋์ฒ๋ผ ํ๋๋ก ์ ๋ ฅํด๋ ๋๋ค.// sendPosts.js const sendPosts = (res) => { res.end( JSON.stringify({ products: [{ id: 1, title: "node", description: "node.js is awesome" }, { id: 2, title: "express", description: "express is a server-side framework for node.js" } ] })) } module.exports = { sendPosts } // withoutExpress.js ์์ ์ฌ์ฉํ๊ธฐ ์ํด ๋ชจ๋๋ก ๋ด๋ณด๋ธ๋ค.
์ด ์ํ๋ก node๋ก chapter1.js๋ฅผ ์คํํ๋ฉด ์๋์ ๊ฐ์ ํ๋ฉด์ด ๋์จ๋ค.
๊ทธ๋ฆฌ๊ณ 'http'๋ฅผ ์ด์ฉํด ์์ฒญ์ ํด๋ณด๋ฉด ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
3. express๋ก routing ๊ฐ์ํ ํ๊ธฐ
express ๋?
express๋ node.js๋ฅผ ์ํ ๋น ๋ฅด๊ณ ๊ฐ๋ฐฉ์ ์ธ ๊ฐ๊ฒฐํ web framework
express reference์์์ Server ์์ฑ ๋ฐ routing ํ๋ ๋ฐฉ๋ฒ์ ์ ์ ์๊ฐํ์๋ค. request์ url ๊ณผ method๋ฅผ ์ฒดํฌ, ํด๋น routing์ ๋์ํ ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐฉ์์ด์๋๋ฐ ๋ญ๊ฐ ๋ณต์กํด ๋ณด์ธ๋ค. routing๋์์ด ๋ง์์ง๋ฉด ์ if๋ฌธ์ด ์ ์ ๋ง์์ง ๊ฒ์ด๋ฏ๋ก condition ์ฒดํฌ ๋ฐฉ์๋ณด๋ค ๊น๋ํ ์ฝ๋๊ฐ ํ์ํ๋ค.
express๋ ์ด๋ฐ ์์ ์์๋ฅผ ๊ฐ์ํํ์ฌ ๊ฐ๋ฐ ์ฑ๋ฅ ํฅ์์ ๋์์ ์ค ์ ์๋ค.
์ฐ์ express๋ฅผ ์ค์นํด ๋ณด์.npm install express
npm(Node Package Manager) ์ node์์ ์ฌ์ฉํ๋ package๋ค์ ๊ด๋ฆฌํ๋ ํ๋ก๊ทธ๋จ์ด๋ค. node๋ฅผ ์ค์นํ๋ฉด ๊ฐ์ด ์ค์น๋๋ฉฐ python์ pip์ ๋น์ทํ๋ค.
express ์ค์น๊ฐ ๋์๋ค๋ฉด ์๋ ์ฝ๋๋ฅผ ๋ณด์.// express.js const http = require('http') const express = require('express') //const {sendPosts} = require('./sendPosts') const {hello, sendPosts} = require('./functions') // app => application // Backend ๋จ์์ ๋์๊ฐ application const app = express() app.get('/', hello) app.get('/products', sendPosts) const server = http.createServer(app) const PORT = 8000 server.listen(PORT, () => { console.log(`running server ${PORT}`) })
์ ์ฝ๋๋ chapter1.js์ ๋์ผํ ์์ (web server ์คํ ๋ฐ 'products' routing)์ ํ๋ค.
express ๊ฐ์ฒด๋ฅผ ์์ฑ, http request์ ๋ํด url, method ์ฒดํฌํ๋ ๊ณผ์ ๋์ express ๊ฐ์ฒด์ ํจ์๋ฅผ ํธ์ถํ๋ ๋ฐฉ์์ผ๋ก routing ์ ์ ์ํ๋ค.
๊ทธ๋ฆฌ๊ณ express ๊ฐ์ฒด๋ฅผ createServer() ํธ์ถ์ ์ฃผ์ ํ๊ณ listen()ํ๋ฉด ๋์ด๋ค.
์ด์ฒ๋ผ express๋ ๊ฐ๋ฐ์๊ฐ ๊ณ ๋ คํด์ผ ํ๋ ์์ํ ๋ถ๋ถ์ ๋์ ์ฒ๋ฆฌํด์ค๋ค. routing์ ๋ฌผ๋ก middleware๋ผ๋ ๊ธฐ๋ฅ(like decorator) ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
4. ๊ฐ๋ฐ์ ์ํด ์์์ผ ํ ๊ธฐ์ (์๋ฒ ์๋ ์ฌ์คํ, npm)
๋ด๊ฐ ๋ง๋ node๋ฅผ ๋ค๋ฅธ ์ฅ๋น์์ ์คํํ๋ ค๋ฉด ๋ญ๊ฐ ํ์ํ ๊น? ๋จผ์ node๋ฅผ ๊ฐ๋ฐํ๋ฉด์ npm์ผ๋ก ์ค์นํ๋ package๋ค์ด ๊ทธ ์ฅ๋น์์ ์ค์น๊ฐ ๋์ด์ผ ํ ๊ฒ์ด๋ค. ์ด์ ๋ํ script๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.
npm init -y (์ค์น๋ package ์ ๋ณด)
์๋ ๊ฐ๋ฐ์ด ์๋ฃ๋ node์์ npm ๋ช ๋ น์ผ๋ก ํ์ฌ node๊ฐ dependency ์ค์ธ package ์ ๋ณด๋ฅผ package.json ํ์ผ๋ก ์์ฑํ๋ค.
์์์ ์์ ํ ์ฝ๋ ๊ธฐ์ค์ผ๋ก package.json์ด ์์ฑ๋ ๋ด์ฉ์ ์๋์ ๊ฐ๋ค{ "name": "JunSession", "version": "1.0.0", "description": "", "main": "chapter1.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "nodemon express.js" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "express": "^4.17.1" }, "devDependencies": { "nodemon": "^2.0.6" } }
'name'์๋ 'main'์ ํด๋นํ๋ jsํ์ผ์ด ์์นํ ํด๋๋ช ์ด ๋ค์ด๊ฐ๋ค.
๋ฐ์ 'dependencies'๋ฅผ ๋ณด๋ฉด 'express'๊ฐ version ์ ๋ณด์ ํจ๊ป ๋ค์ด๊ฐ ์๋ ๊ฒ์ ํ์ธ ํ ์ ์๋ค. npm์ผ๋ก package๋ฅผ ์ค์นํ๋ฉด 'dependencies' ์ ํญ๋ชฉ์ ๊ณ์ ์ถ๊ฐ๋๋ค.
๋ฐ์ 'devDependencies' ๋ ๊ฐ๋ฐ์ฉ์ผ๋ก ์ค์นํ package๋ฅผ ์๋ฏธํ๋ค. ๊ฐ๋ฐ์์๋ง ์ฌ์ฉ๋๋ฉฐ ์ค์ ๋ฐฐํฌ๋์ด ์ค์น๋ ๋ ํฌํจ๋์ง ์๋๋ค.package๋ฅผ ๊ฐ๋ฐ์ฉ์ผ๋ก ์ค์นํ๋ ๋ช ๋ น์ ์๋์ ๊ฐ๋ค.
npm install -D {์ค์นํ package ์ด๋ฆ} (์ฌ๊ธฐ์๋ nodemon) # -D ์ต์ ์ ๋ฃ์ผ๋ฉด ๊ฐ๋ฐ์ฉ์์ ์๋ฏธ
์์์ nodemon ์ด๋ package๋ฅผ ๊ฐ๋ฐ์ฉ์ผ๋ก ์ค์นํ ๊ฒ์ ์ ์ ์๋ค.
nodemon์ server ๊ธฐ๋ ์ค์ node source๋ฅผ ์์ ํ๋ฉด ์๋์ผ๋ก server๋ฅผ ์ฌ์์ํ๋๋ก ํด์ฃผ๋ package์ด๋ค. nodemon ์ ๊ตฌ๋ํ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ๋ค.
- package.json ์์ "scripts"์ "dev":"nodemon express.js" ์ถ๊ฐ.
(key๋ ๋ช ๋ น์ด์ด๊ณ value๋ ์ค์ ๋ก ์คํํ๋ ๋ช ๋ น)- ์๋ npm ๋ช ๋ น์ ํตํด ์คํ.
npm run dev
์ ์ ์คํ์ ์๋์ ๊ฐ์ ํ๋ฉด์ด ๋์จ๋ค.
์ด ์ํ์์ ์ฝ๋๋ฅผ ์์ ํ๋ฉด ์๋ฒ๋ ์ฌ์คํ ๋๋ค.
Author And Source
์ด ๋ฌธ์ ์ ๊ดํ์ฌ(๐ฅ TIL #1. Node์ ๋ํ ์ดํด์ ๋ง๋ณด๊ธฐ), ์ฐ๋ฆฌ๋ ์ด๊ณณ์์ ๋ ๋ง์ ์๋ฃ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ๋งํฌ๋ฅผ ํด๋ฆญํ์ฌ ๋ณด์๋ค https://velog.io/@jinybear/TIL-1.-Node์-๋ํ-์ดํด์-๋ง๋ณด๊ธฐ์ ์ ๊ท์: ์์์ ์ ๋ณด๊ฐ ์์์ URL์ ํฌํจ๋์ด ์์ผ๋ฉฐ ์ ์๊ถ์ ์์์ ์์ ์ ๋๋ค.
์ฐ์ํ ๊ฐ๋ฐ์ ์ฝํ ์ธ ๋ฐ๊ฒฌ์ ์ ๋ (Collection and Share based on the CC Protocol.)
์ข์ ์นํ์ด์ง ์ฆ๊ฒจ์ฐพ๊ธฐ
๊ฐ๋ฐ์ ์ฐ์ ์ฌ์ดํธ ์์ง
๊ฐ๋ฐ์๊ฐ ์์์ผ ํ ํ์ ์ฌ์ดํธ 100์ ์ถ์ฒ ์ฐ๋ฆฌ๋ ๋น์ ์ ์ํด 100๊ฐ์ ์์ฃผ ์ฌ์ฉํ๋ ๊ฐ๋ฐ์ ํ์ต ์ฌ์ดํธ๋ฅผ ์ ๋ฆฌํ์ต๋๋ค