[λ°λΈμ½μ€] HTTP μνμ½λλ₯Ό νμ©ν μμΈμ²λ¦¬ κ³ λν(+νΈλ€λ¬, 리μ€λ, λ°°μ΄ λ©μλ)
πνΈλ€λ¬μ 리μ€λ
νΈλ€λ¬
μμ²μ μν΄ νΈμΆλλ λ©μλ
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() λ‘ μ½λκ° λ무 κΈΈμ΄μ Έμ μ½λκ° λ μ§§μμ§μ§ μλ κ² κ°μ§λ§..? μμΌλ‘ λ ν¨μ¨μ μΈ μ²λ¦¬ λ°©μμ λ°°μ°μ§ μμκΉ μΆμ΄ κΈ°λκ° λλ€.