๐ํธ๋ค๋ฌ์ ๋ฆฌ์ค๋
ํธ๋ค๋ฌ
์์ฒญ์ ์ํด ํธ์ถ๋๋ ๋ฉ์๋
HTTP ์์ฒญ์ด ๋ ์์ค๋ฉด ์๋์ผ๋ก ํธ์ถ๋๋ ํจ์๋ฅผ ์๋ฏธํ๋ค. Node.js์์๋ ์ฝ๋ฐฑ ํจ์ ํํ๋ก app.HTTPMethod(path, ํธ๋ค๋ฌ)
๊ตฌ์กฐ๋ก ์ฌ์ฉํ๋ค.
์๋ฅผ ๋ค์ด, Express์์ GET ์์ฒญ์ ์ฒ๋ฆฌํ๋ ํธ๋ค๋ฌ๋ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์๋ค.
app.get('/youtubers', function(req, res) {
//์ฌ๊ธฐ์ function(req, res) {} ๋ถ๋ถ์ด ํธ๋ค๋ฌ!!
res.json(youtubers);
});
ํธ๋ค๋ฌ์ ์ญํ ๊ณผ ๊ตฌ์กฐ
ํธ๋ค๋ฌ ํจ์๋ ์ผ๋ฐ์ ์ผ๋ก req
, res
๋ ๊ฐ์ ์ค์ํ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ๋๋ค.
req(request): ํด๋ผ์ด์ธํธ์ ์์ฒญ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ ๊ฐ์ฒด
req.params
: URL ๊ฒฝ๋ก์์ ์ถ์ถํ ๋งค๊ฐ๋ณ์req.query
: URL ์ฟผ๋ฆฌ ๋ฌธ์์ด์์ ์ถ์ถํ ๊ฐ์ฒดreq.body
: ์์ฒญ ๋ณธ๋ฌธ ๋ฐ์ดํฐreq.headers
: HTTP ํค๋ ์ ๋ณดreq.cookies
: ์ฟ ํค ์ ๋ณด
res(response): ํด๋ผ์ด์ธํธ์๊ฒ ๋ณด๋ผ ์๋ต์ ๊ตฌ์ฑํ๋ ๊ฐ์ฒด
res.send()
: ๋ค์ํ ์ ํ์ ์๋ต ์ ์กres.json()
: JSON ํ์์ ์๋ต ์ ์กres.status()
: HTTP ์ํ ์ฝ๋ ์ค์ res.redirect()
: ๋ค๋ฅธ URL๋ก ๋ฆฌ๋ค์ด๋ ํธres.render()
: ํ ํ๋ฆฟ ์์ง์ ์ฌ์ฉํ์ฌ ๋ทฐ ๋ ๋๋ง
์ ํ์ ์ผ๋ก, ์ธ ๋ฒ์งธ ๋งค๊ฐ๋ณ์์ธ next
๋ฅผ ๋ฐ์ ์๋ ์๋ค. ์ด๋ ๋ค์ ๋ฏธ๋ค์จ์ด ํจ์๋ก ์ ์ด๋ฅผ ๋๊ธฐ๋ ๋ฐ ์ฌ์ฉ๋๋ค.
app.get('/youtubers', function(req, res, next) {
//์ค๊ฐ ์ฒ๋ฆฌ ๋ก์ง
next(); //๋ค์ ๋ฏธ๋ค์จ์ด๋ก ์ ์ด ์ด๋
});
๋ฆฌ์ค๋
ํน์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋ ์คํ๋๋ ํจ์
๋ฆฌ์ค๋๋ Node.js์ ์ด๋ฒคํธ ๊ธฐ๋ฐ ์ํคํ ์ฒ์์ ํต์ฌ์ ์ธ ์ญํ ์ ํ๋ค. Express์์๋ ์ฃผ๋ก ์๋ฒ ๊ด๋ จ ์ด๋ฒคํธ์ ์ฒ๋ฆฌ์ ๋ฆฌ์ค๋๊ฐ ์ฌ์ฉ๋๋ค.
์๋ฒ ๋ฆฌ์ค๋
์๋ฒ ์์ ์ ํธ์ถ๋๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ๋ฆฌ์ค๋
const server = app.listen(3000, () => {
console.log('์๋ฒ๊ฐ 3000๋ฒ ํฌํธ์์ ์คํ ์ค์
๋๋ค');
});
ํ์ดํ ํจ์๊ฐ ๋ฆฌ์ค๋์ด๋ค.
์ด๋ฒคํธ ์ด๋ฏธํฐ์ ๋ฆฌ์คํฐ
Node.js๋ EventEmitter
ํด๋์ค๋ฅผ ํตํด ์ด๋ฒคํธ ๊ธฐ๋ฐ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํ๋ค. Express ์ ํ๋ฆฌ์ผ์ด์
๊ณผ HTTP ์๋ฒ๋ EventEmitter
์ ์์๋ฐ๋๋ค.
// HTTP ์๋ฒ ์ด๋ฒคํธ ๋ฆฌ์ค๋
server.on('error', (error) => {
if (error.syscall !== 'listen') throw error;
console.error(`์๋ฒ ์ค๋ฅ ๋ฐ์: ${error}`);
process.exit(1);
});
server.on('listening', () => {
const addr = server.address();
console.log(`์๋ฒ๊ฐ ${addr.port}๋ฒ ํฌํธ์์ ๋ฆฌ์ค๋ ์ค์
๋๋ค.`);
});
ํธ๋ค๋ฌ์ ๋ฆฌ์ค๋์ ์ฐจ์ด
- ํธ๋ค๋ฌ: HTTP ์์ฒญ์ ์ฒ๋ฆฌํ๋ ํจ์(req, res๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์)
- ๋ฆฌ์ค๋: ํน์ ์ด๋ฒคํธ ๋ฐ์ ์ ์คํ๋๋ ํจ์(์ด๋ฒคํธ ๊ด๋ จ ๋ฐ์ดํฐ๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์)
โญ ํธ๋ค๋ฌ๋ ๋ฆฌ์ค๋์ ํน์ ํํ๋ก ๋ณผ ์ ์๋ค. HTTP ์์ฒญ์ด๋ผ๋ ์ด๋ฒคํธ์ ๋ํ ๋ฆฌ์ค๋๊ฐ ๋ฐ๋ก ํธ๋ค๋ฌ!
๐find() ๋ฉ์๋
๋ฐฐ์ด์์ ํน์ ์กฐ๊ฑด์ ๋ง๋ ์์๋ฅผ ์ฐพ์ ๋, ์ผ๋ฐ์ ์ผ๋ก forEach
๋ฌธ์ ์ฌ์ฉํ์ฌ ๋ค์๊ณผ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋ค.
fruits.forEach((fruit) => {
if (fruit.id == id) {
findFruit = fruit;
}
});
ํ์ง๋ง, ์๋ฐ์คํฌ๋ฆฝํธ์ find()
๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์ด ์ฝ๋๋ฅผ ํ ์ค๋ก ์ค์ผ ์ ์๋ค.
var findFruit = fruits.find((fruit) => fruit.id == id);
โญ find() ๋ฉ์๋๋ ์กฐ๊ฑด์ ๋ง์กฑํ๋ ์ฒซ ๋ฒ์งธ ์์๋ฅผ ๋ฐํํ๋ฉฐ, ๋ง์กฑํ๋ ์์๊ฐ ์์ผ๋ฉด undefined๋ฅผ ๋ฐํํ๋ค.
๋ค๋ฅธ ์ ์ฉํ ๋ฉ์๋๋ค
find()
์ธ์๋ ๋ฐฐ์ด ์กฐ์์ ์ํ ์ฌ๋ฌ ์ ์ฉํ ๋ฉ์๋๋ค์ด ์๋ค.
filter()
์กฐ๊ฑด์ ๋ง์กฑํ๋ ๋ชจ๋ ์์๋ฅผ ๋ฐฐ์ด๋ก ๋ฐํ
const expensive = fruits.filter((fruit) => fruit.price > 1000);
map()
๋ฐฐ์ด์ ๊ฐ ์์๋ฅผ ๋ณํํ์ฌ ์ ๋ฐฐ์ด ๋ฐํ
const fruitNames = fruits.map((fruit) => fruit.name);
some()
ํ๋ ์ด์์ ์์๊ฐ ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง ํ์ธ(boolean ๋ฐํ)
const hasExpensive = fruits.some((fruit) => fruit.price > 1000);
every()
๋ชจ๋ ์์๊ฐ ์กฐ๊ฑด์ ๋ง์กฑํ๋์ง ํ์ธ(boolean ๋ฐํ)
const allFresh = fruits.every((fruit) => fruit.fresh === true);
โฌ๏ธ์ํ์ฝ๋๋ฅผ ํ์ฉํ์ฌ ์์ธ์ฒ๋ฆฌ ๊ณ ๋ํํ๊ธฐ
์ด์ ์๋ ์๋ต์ ๋ํ ์ํ ์ฝ๋๋ฅผ ๊ณ ๋ คํ์ง ์์ ์ฑ ์ฝ๋๋ฅผ ์์ฑํ์๋ค. ํ์ง๋ง, ์ํฉ์ ๋ง๋ ์ํ ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋ช ํํ ์๋ต์ ์ ๊ณตํ ์ ์๊ธฐ์ REST API๋ฅผ ๊ตฌ์ถํ ๋, ์ ์ ํ HTTP ์ํ ์ฝ๋๋ฅผ ๋ฐํํ๋ ๊ฒ์ด ๋งค์ฐ ์ค์ํ๋ค.
app.post("/test", function (req, res) {
const channelName = req.body.channelName;
if (channelName) {
db.set(id++, req.body);
res.status(201).json({
message: `${db.get(id - 1).channelName}๋์ ์ ํ๋ฒ ์ํ์ ์์ํฉ๋๋ค.`,
});
} else {
res.status(400).json({ message: "์์ฒญ๊ฐ์ ์ ๋๋ก ๋ณด๋ด์ฃผ์ธ์" });
}
});
201
: ๋ฆฌ์์ค ์์ฑ ์ฑ๊ณต(POST ์์ฒญ์ด ์ฑ๊ณต์ ์ผ๋ก ์ฒ๋ฆฌ๋จ)400
: ์๋ชป๋ ์์ฒญ(ํ์ํ ๋ฐ์ดํฐ๊ฐ ๋๋ฝ๋จ)
โญ์ํ ์ฝ๋๋ฅผ ํ์ฉํ ์๋ฌ์ฒ๋ฆฌ๋ API์ ๊ฐ๋ ์ฑ๊ณผ ์ฌ์ฉ์ฑ์ ํฌ๊ฒ ํฅ์ํ๋ค! ํด๋ผ์ด์ธํธ๋ ์ํ ์ฝ๋๋ง์ผ๋ก ์์ฒญ ์ฒ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋น ๋ฅด๊ฒ ํ์ ํ ์ ์๊ณ , ์ ์ ํ ํ์ ์กฐ์น๋ฅผ ์ทจํ ์ ์๋ค.
๐ฅ๋ฏธ๋ ํ๋ก์ ํธ
์ง๊ธ๊น์ง ๋ฐฐ์ด ๋ด์ฉ๋ค์ ํ์ฉํ์ฌ, ๊ฐ๋จํ ํ์๊ฐ์ API๋ฅผ ์ค์ตํด๋ณด์๋ค.
๊ตฌํ ๊ธฐ๋ฅ
ํ์
-๋ก๊ทธ์ธ
-ํ์๊ฐ์
-ํ์ ์ ๋ณด ์กฐํ
-ํ์ ํํด
์ฑ๋
-์ฑ๋ ์์ฑ
-์ฑ๋ ์์
-์ฑ๋ ์ญ์
ํ์์ ๊ณ์ 1๊ฐ ๋น ์ต๋ 100๊ฐ ์ฑ๋์ ๊ฐ์ง ์ ์๋ค.
API ์ค๊ณ
๋ก๊ทธ์ธ
method | post |
path | /login |
req | body(userId, password) |
res | 200: ${name} ๋ ๋ก๊ทธ์ธ ์ฑ๊ณต. 400: ์๋ชป๋ ์์ฒญ์ ๋๋ค. |
ํ์๊ฐ์
method | post |
path | /signup |
req | body(userId, password, name) |
res | 201: ${name} ๋ ํ์๊ฐ์
์ ํ์ํฉ๋๋ค. 400: ์์ฒญ๊ฐ์ ์ ๋๋ก ๋ณด๋ด์ฃผ์ธ์ |
ํ์ ์กฐํ(๊ฐ๋ณ)
method | get |
path | /users/:id |
req | params(id) |
res | 200: {userId, name} 404: ์กด์ฌํ์ง ์๋ ํ์์ ๋๋ค. |
ํ์ ํํด(๊ฐ๋ณ)
method | delete |
path | /users/:id |
req | params(id) |
res | 200: ํ์ํํด๊ฐ ์๋ฃ๋์์ต๋๋ค. 404: ์กด์ฌํ์ง ์๋ ํ์์ ๋๋ค. |
API ๊ตฌํ
ํ์๊ฐ์
app.post("/signup", function (req, res) {
if (req.body !== undefined && req.body.userID) {
db.set(id++, req.body);
res.status(201).json({
message: `${req.body.userID}๋ ํ์๊ฐ์
์ ํ์ํฉ๋๋ค.`,
});
} else {
res.status(400).json({ message: "์์ฒญ๊ฐ์ ์ ๋๋ก ๋ณด๋ด์ฃผ์ธ์" });
}
});
ํ์ ์กฐํ(๊ฐ๋ณ)
app.get("/users/:id", function (req, res) {
let { id } = req.params;
id = parseInt(id);
const user = db.get(id);
if (user == undefined) {
res.status(404).json({ message: "์กด์ฌํ์ง ์๋ ํ์์
๋๋ค" });
} else {
res.status(200).json({ userId: user.userId, name: user.name });
}
});
ํ์ ์ญ์ (๊ฐ๋ณ)
app.delete("/users/:id", function (req, res) {
let { id } = req.params;
id = parseInt(id);
const user = db.get(id);
if (user == undefined) {
res.status(404).json({ message: "์กด์ฌํ์ง ์๋ ํ์์
๋๋ค" });
} else {
db.delete(id);
res.status(200).json({ message: "ํ์ ํํด๊ฐ ์๋ฃ๋์์ต๋๋ค" });
}
});
์ํ ์ฝ๋๋ฅผ ํ์ฉํ ์์ธ ์ฒ๋ฆฌ๊ฐ ์ ๋ง ์ค์ํ๋ค๋ ๊ฒ์ ์ ์ ์์๋ค. ์ ์ ํ ์ํ ์ฝ๋๋ฅผ ํจ๊ป ์ ์กํ๋ API์ ํ์ง์ด ํฌ๊ฒ ํฅ์๋ ๊ฒ ์ฒ๋ผ ๋๊ปด์ก๋ค. 200, 201, 400, 404 ์ฝ๋๋ง์ผ๋ก๋ ์์ฒญ์ ๊ฒฐ๊ณผ๋ฅผ ๋น ๋ฅด๊ฒ ํ๋จํ ์ ์๋ค๋ ๊ฒ์ ์ ์ ์์๋ค.
์ด๋ฒ ํฌ์คํธ์์ ์ฐ์ง๋ ์์์ง๋ง, app.route()๋ฅผ ํ์ฉํ์ฌ ๋์ผํ ์๋ํฌ์ธํธ๋ฅผ ๊ฐ์ง API๋ค์ ๋ถ๊ธฐํ์ฌ ์ฝ๋๋ฅผ ๋ ๊น๋ํ๊ฒ ์ง๋ ๋ฐฉ๋ฒ์ ์ ๊น ๋ฐฐ์ ๋ค.์์ผ๋ก ๋ ๋ณต์กํ ๊ธฐ๋ฅ์ ๊ฐ์ง API๋ฅผ ๊ฐ๋ฐํ๊ฒ ๋ ํ ๋ฐ, ์ ๋ง ์ ์ฉํ๊ฒ ์ฐ์ด๊ฒ ๊ตฌ๋ ์๊ฐํ๋ค. .get().delete() ๋ก ์ฝ๋๊ฐ ๋๋ฌด ๊ธธ์ด์ ธ์ ์ฝ๋๊ฐ ๋ ์งง์์ง์ง ์๋ ๊ฒ ๊ฐ์ง๋ง..? ์์ผ๋ก ๋ ํจ์จ์ ์ธ ์ฒ๋ฆฌ ๋ฐฉ์์ ๋ฐฐ์ฐ์ง ์์๊น ์ถ์ด ๊ธฐ๋๊ฐ ๋๋ค.