๐ Node JS๋
๋ ธ๋ JS๋ ๋ธ๋ผ์ฐ์ ๋ฐ์์๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ ์ ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฐํ์ ํ๊ฒฝ์ด๋ค. single thread ์ธ์ด์ธ Javascript๊ฐ ๋ธ๋ผ์ฐ์ ์์์ browser API๋ฅผ ์ด์ฉํ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ก ๋ค์ํ ์ผ์ ์ฒ๋ฆฌํ ์ ์์๋ ๊ฒ ์ฒ๋ผ, Node JS ๋ํ, ์์ฒด API๋ฅผ ์ด์ฉํด์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ด์ฉํด ๋ค์ํ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์๊ณ , brower์ฒ๋ผ Event๋ฅผ ํตํด์ ์ฝ๋ฐฑ์ ์คํํ๋ ํน์ง์ ๊ฐ์ง๋ค.
์ด๋ฌํ ๊ธฐ๋ฅ์ค์์ ๋์๊ฒ ํ์ฌ ํ์ํ ๋ ธ๋ JS์ ๊ธฐ๋ฅ์ API ์๋ฒ๋ฅผ ๋ง๋๋ ๊ฒ์ผ๋ก, ์๋ฒ๋ฅผ ๋ง๋ค๊ธฐ ์ํ ๊ธฐ์ด API๋ค์ ๋จผ์ ์ ๋ฆฌํ๊ณ ์๋ฒ๋ฅผ ๋ง๋๋ ๊ณผ์ ์ ์ ๋ฆฌํด๋ณด๋ ค ํ๋ค.
Module system
๋ ธ๋์ ๋ชจ๋์์คํ ์ ์์ฒด์ ์ธ require(module)์ด๋ผ๋ ํจ์๋ฅผ ํตํด์ ๋ฐ์์ฌ ์ ์๋ค. ํ์ฌ๋ ์๋ฐ์คํฌ๋ฆฝํธ ์์ฒด์ import/export๋ ์ด์ฉ๊ฐ๋ฅํ๋ฐ, npm์ package.json์ "type":"module"๋ก ์ถ๊ฐํด์ฃผ์ด์ผํ๋ค.
Path
๋ง๊ทธ๋๋ก ๊ฒฝ๋ก๋ฅผ ๋ฐ์์ฌ ์ ์๋ ๋ชจ๋๋ก, ๋ค์ํ ๋๋ ํ ๋ฆฌ, ํ์ผ ๋ฑ์ ๋ฐ์์ฌ ์ ์๋ API์ด๋ค.
path.basename(__filename) //ํ์ฌ ํ์ผ์ ๊ฒฝ๋ก
path.extname(__filename) //ํ์ฌํ์ผ์ ํ์ฅ์
path.join(__dirname, "image") //ํ์ฌํด๋์ image ํ์ผ์ ๊ฒฝ๋กFile system
ํ์ผ ์์คํ ๋ชจ๋์ ํ์ผ, ํด๋๋ฅผ ์ฝ๊ณ ์ฐ๊ณ ์ด๋ํ๋ ๋ฑ์ ์ผ์ ํ ์ ์๋ api๋ก script๋ก ์์ฑ์ ์๋ํ ํ๋ก๊ทธ๋จ๋ ๋ง๋ค ์ ์๋ค.
์๋ฒ๋ฅผ ๋ง๋ค๊ณ ๋์ ๋ด ์ปดํจํฐ ๋ด์ ํ์ผ๋ค์ ์ ๋ฆฌํ๋ ์คํฌ๋ฆฝํธ๋ฅผ ๋ง๋๋ ์ฐ์ต๋ ํด๋ณด๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
fs.renameSync(oldPath,newPath) //๋๊ธฐ์ ์ผ๋ก ํ์ผ์ ์ด๋์์ผ
fs.rename(oldPath,newPath,(error,data)=>{...}) //๋น๋๊ธฐ์ ์ผ๋ก ํ์ผ์ ์ด๋์์ผ
fs.promises // promise๋ฅผ ์ด์ฉํด ๋น๋๊ธฐ์ ์ผ๋ก ํ์ผ ์์คํ
์ ์์ฑ
fs.readFile(file, option)//๋น๋๊ธฐ์ ์ผ๋ก option์ผ๋ก ์ธ์ฝ๋ฉ๋ฐฉ์ ๋ฑ์ ์ ํด์ ํ์ผ์ ์ฝ์ด
fs.writeFile(file, data) //๋น๋๊ธฐ์ ์ผ๋ก ํด๋น ํ์ผ์ ๋ฐ์ดํฐ๋ฅผ ์๋ก ์์ฑํ๋ค
fs.appendFile(file, data) //๋น๋๊ธฐ์ ์ผ๋ก ํด๋น ํ์ผ์ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐ ์์ฑํ๋ค๋ฒํผ์ ์คํธ๋ฆผ
๋ฒํผ์ ์คํธ๋ฆผ์ ๋๋ฌด๋๋ ์ต์ํ๊ฒ ๋ง์ด ๋ค์ด์จ ๊ฐ๋ ๋ค์ด๋ค. ๋ฒํผ๋ ๋ฐ์ดํฐ ์กฐ๊ฐ์ผ๋ก ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ํ๋ฒ์ ๋ค ๋ณด๋ด๋ ๊ฒ์ด ์๋๋ผ ๋ฐ์ดํฐ๋ฅผ ๋ฒํผ๋ก ์กฐ๊ธ์ฉ ์๋ผ์ ๋ณด๋ธ๋ค. ์ด๋ ๊ฒ ๋ฐ์ดํฐ ์กฐ๊ฐ์ ๋ณด๋ด๋ ๊ณผ์ ์ ์คํธ๋ฆฌ๋ฐ์ด๋ผ๊ณ ํ๊ณ , ์ฌ์ฉ์๊ฐ ๋ฐ๋ ๋ฐ์ดํฐ์ ์๋๊ฐ ๋ณด๋ด๋ ๋ฐ์ดํฐ ์๋๋ณด๋ค ๋น ๋ฅด๋ค๋ฉด, ํ๋ฉด์ด ๋ณด์ด์ง ์๋ ๋ฑ์ ์ผ์ด ์ผ์ด๋๋๋ฐ ์ด๋ฐ ํ์์ ์ฐ๋ฆฌ๊ฐ ํํ ์ด์ผ๊ธฐํ๋ ๋ฒํผ๋ง์ด ๊ฑธ๋ฆฐ๋ค๋ ์ผ์ด๋ค.
์ด๋ ๊ฒ ๋ฒํผ์ ์คํธ๋ฆผ์ ์ด์ฉํ๋ฉด ํ๋ฒ์ ๋ค ๋ณด๋ด์, ๋ค ๋ฐ์๋๊น์ง ์ฌ์ฉ์๊ฐ ๋ณผ ์ ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ด์ ๋ฉ๋ชจ๋ฆฌํจ์จ๊ณผ ์๊ฐ ํจ์จ์ด ์ข์ ์ฅ์ ์ ๊ฐ์ง๋ค.
[์ฌ์ง ์ถ์ฒ: ์นด๋ ์ ํฐ์คํ ๋ฆฌ ]
const buf = Buffer.from("hello") //<Buffer 68 65 6c 6c 6f>
const buf2 = Buffer.from("hello") //<Buffer 68 65 6c 6c 6f>
const newBuf = Buffer.concat([buf, buf2]) //<Buffer 68 65 6c 6c 6f 68 65 6c 6c 6f> ๋ฒํผ ์ด์ด๋ถ์ด๊ธฐ
const fs = require("fs")
const data = []
const readStream = fs
.createReadStream(ํ์ผ, option)
.on("data", chunk => {
// ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ฌ ๋ ๋ง๋ค ์คํํด
data.push(chunk)
})
.on("end", () => {
console.log(data.join("")) // ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฐ์ผ๋ฉด ์คํํด
})
.on("error", error => console.log(error)) // ์๋ฌ ๋ฐ์์ ์คํํดstream์ ๊ณต๋ถํ๊ณ ๋๋ ๊ฐ์ฅ ํฐ ์ฅ์ ์ piping์ด ๊ฐ๋ฅํ๋ค๋ ์ ์ด๋ค. piping์ stream๋ค์ ์ด์ด์ฃผ๋ ๊ฒ์ผ๋ก stream์ ๊ฒฐ๊ณผ๋ค์ chaining์ด ๊ฐ๋ฅํ๋ค.
const readStream = fs.readStream("./ex1.txt")
const writeStream = fs.createWriteStream("./ex2.txt")
readSream.pipe(writeStream) //ex1.txt์ ์ฝ๊ณ ex2.txt์ ์ฐ๋ ํ์ดํ์๋ฒ ์ ์
์์ ์ ๋ฆฌํ Node JS API๋ค๊ณผ HTTP ์ง์๋ค์ ์ด์ฉํด์ ๊ฐ๋จํ ์๋ฒ๋ฅผ ๋ง๋ค์ด๋ณด์๋ค.
์๋ฒ์ฌ์ด๋ ๋ ๋๋ง
Node ์๋ฒ๋ flask๋ฅผ ์ฌ์ฉํ์ ๋์ ๋์ผํ๊ฒ, request๋ก ๋ฐ์ ์์ฒญ์ ๋ฐ๋ผ response๋ก ํด๋นํ๋ html์ ๋ณด์ฌ์ฃผ๋ ์๋ฒ๋ฅผ ๋จผ์ ์ ์ํ๋ค. ๊ณผ์ ์ ๋ค์๊ณผ ๊ฐ์ด ์ ๋ฆฌํ ์ ์๋ค.
- http๋ชจ๋์ ์ด์ฉํด์ ์๋ฒ๋ฅผ ๋ง๋ ๋ค.
- ์๋ฒ์ ๋ฐ์ request์ url์ ๋ฐ๋ผ html์ ๋ณด๋ธ๋ค.
file์ ์ฝ๋ ๋ฐฉ๋ฒ์ผ๋ก fs.readFile์ผ๋ก ํ ์๋ ์์ง๋ง buffer์ stream์ ํจ์จ์ด ๋ ์ข๊ธฐ ๋๋ฌธ์ createReadStream์ ์ด์ฉํ๋ค.
stream์ผ๋ก ๋ฐ์์จ buffer ๋ฐ์ดํฐ๋ฅผ pipe๋ฅผ ์ด์ฉํด์ response๋ก ๋ณด๋ด๋ฉด, res.end()๋ฅผ ํ์ง ์์๋ ๋ฐ์ดํฐ๊ฐ ๋ค ๋ฐ์์ง๋ฉด
pipe๊ฐ ์๋์ผ๋ก ๋๋ด์ค์ ์ฝ๋๊ฐ ๋ ๊ฐ๋จํด์ง๋ค.
const http = require("http")
const fs = require("fs")
const path = require("path")
const server = http.createServer((req, res) => {
const url = req.url
const filePath = path.join(__dirname)
res.setHeader("content-Type", "text/html") //์ด๋ค ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ์ง๋ฅผ ๋ด์
if (url === "/") {
fs.createReadStream(`${filePath}/template/index.html`).pipe(res) //html์ ๋ฒํผ๋ก ์ฝ์ด์ ์ฝ์ ๋ฐ์ดํฐ๋ฅผ response๋ก ํ๋ ค๋ณด๋ด์ค
} else if (url === "/courses") {
fs.createReadStream(`${filePath}/template/courses.html`).pipe(res)
} else {
fs.createReadStream(`${filePath}/template/not-found.html`).pipe(res)
}
})
server.listen(8080)JSON์ ์ด์ฉํ ์๋ฒ
JSON์ Javascript Object Notation์ ์ฝ์๋ก ๋คํธ์ํฌํต์ ์ ์ํ ๊ตฌ์กฐํ๋ ๋ฐ์ดํฐ๋ฅผ ์๋ฏธํ๋ค. ์์ ์ ๋ฆฌํ์๋ HTTP ํต์ ์ผ๋ก ๋ฐ์ request์ ๋ฐ๋ผ ํด๋นํ๋ ์๋ต์ ๋ณด๋ด์ค๋, ์์ฒญ์์ ์๊ตฌํ๋ ๋ฐ์ดํฐ๋ฅผ body์ ๋ด์์ ๋ณด๋ด์ค ๋, JSON์ผ๋ก ์ ๋ฌํ ์ ์๋ค. ๊ฐ๋จํ๊ฒ ๋ฐฐ์ด์ GET์ด๋ POST๋ฅผ ์ด์ฉํด์ JSON์ผ๋ก ๋ณด๋ด์ฃผ๋ ์๋ฒ๋ฅผ ๋ง๋ค์๋ค. ์์ ์๋ฒ์ ๋ค๋ฅด๊ฒ request์ method๋ณ๋ก ๋ค๋ฅธ ์๋ต์ ๋ณด๋ด์ฃผ์ด์ผํ๊ณ , ์ ์ ํ status_code๋ฅผ ํจ๊ป ๋ด์์ฃผ์ด์ผํ๋ค.
(GET์ด ์ฑ๊ณตํ๋ฉด 200, POST๊ฐ ์ฑ๊ณตํ๋ฉด 201)
const arr = [1, 2, 3]
const server = http.createServer((req, res) => {
const method = req.method
if (method === "GET") {
res.writeHead(200, { "Content-Type": "application/json" }) //head์ status_code, content-type์ ๋ด์
res.end(JSON.stringify(arr)) //์ํ๋๊ฑธ ๋ด์์ ๋ณด๋ด์ค
} else if (method === "POST") {
const body = []
req.on("data", chunk => {
body.push(chunk)
}) //req๋ก ์จ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์
req.on("end", () => {
const item = Buffer.concat(body).toString() //๋ฒํผ๋ก ๋ฐ์์จ ๋ฐ์ดํฐ๋ฅผ ์ด์ด
arr.push(JSON.parse(item))
res.writeHead(201)
res.end() //์๋ฌด๊ฒ๋ ๋ด์ง ์์
})
}
})
server.listen(8080)