241205 에이콘 아카데미 수업에 기반하여 작성되었음을 알립니다.
노드 실습 (get/post)
app.mjs
import express from 'express';
import cors from 'cors';
import path from 'path';
import { fileURLToPath } from 'url';
import gogekRouter from './routes/gogek.mjs';
import jikwonRouter from './routes/jikwon.mjs';
const app = express();
app.use(cors());
// cors 문제를 해결할 미들웨어 추가
app.use(express.json());
// json 파싱 미들웨어 추가
// (중간에서 req body 객체를 만든다. req.body.name ... req.body.age 이런식으로)
app.set('port', process.env.PORT || 3000); // 환경변수 port가 존재하면 해당 port를 쓰고 아니면 3000을 쓴다.
// __dirname을 esm 환경에서 사용하는 방법
const __filename = fileURLToPath(import.meta.url); // 현재 실행 중인 파일 경로
const __dirname = path.dirname(__filename); // 현재 실행 중인 디렉토리 경로
// 정적파일 디렉토리 정의
// public 디렉토리 내의 파일들은 브라우저에서 직접 접근이 가능해진다.
app.use(express.static(path.join(__dirname, 'public'))); // path.join() 경로를 연결시켜주는 메소드
// (req, res) 순서 중요
app.get('/', (req, res) => {
res.send('good');
});
app.use('/jikwon', jikwonRouter);
app.use('/gogek', gogekRouter);
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 웹 서버 서비스 시작!');
});
jikwon.mjs
import { Router } from "express";
import path from 'path';
import { fileURLToPath } from 'url';
const employees = [
{id:1, name:'염정섭'},
{id:2, name:'길준빈'},
{id:3, name:'홍희철'}
];
// __dirname을 esm 환경에서 사용하는 방법
const __filename = fileURLToPath(import.meta.url); // 현재 실행 중인 파일 경로
const __dirname = path.dirname(__filename); // 현재 실행 중인 디렉토리 경로
const router = Router();
... 생략
router.get('/employees', (req, res) => {
res.json(employees);
})
export default router;
디렉토리 내의 파일 접근하기!
router.post('/employees', (req, res) => {
const newEmployee = req.body;
if(!newEmployee || !newEmployee.name) {
return res.status(400).json({error : '직원 자료 이름을 입력해라!'});
}
employees.push(newEmployee);
res.status(201).json // 201은 create를 의미한다.
});
abc.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>직원 정보</h2>
<ul id="emp-list"></ul>
<div>
get : <button id="getemp">직원 자료 읽기</button>
</div>
<div>
post : <input type="text" id="empname" placeholder="직원명 입력" required/>
<button id="addemp">직원 자료 추가</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const empList = document.getElementById('emp-list');
const empName = document.getElementById('empname');
const btngetemp = document.getElementById('getemp');
const btnaddemp = document.getElementById('addemp');
// get 요청으로 직원 정보 읽기
btngetemp.addEventListener('click', () => {
fetch('/jikwon/employees') // url 전부 써주기
.then(response => response.json())
.then(data => {
empList.innerHTML = '';
data.forEach(emp => {
const li = document.createElement('li');
li.textContent = emp.name;
empList.appendChild(li);
});
})
.catch(error => {
console.error('직원 자료 읽기 오류', error);
})
});
// post 요청으로 직원 정보 배열에 추가
btnaddemp.addEventListener('click', () => {
const newEmp = {id: Date.now(), name:empName.value};
fetch('/jikwon/employees', {
method: 'POST',
headers: {
'Content-Type':'application/json',
},
body: JSON.stringify(newEmp)
})
.then(response => response.json())
.then(emp => {
const li = document.createElement('li');
li.textContent = emp.name;
empList.appendChild(li);
empName.value = '';
})
.catch(error => {
console.error('직원 자료 추가 오류', error);
})
});
});
</script>
</body>
</html>
정적 파일을 바로 부를수도 있다
노드 실습 (get/post, DB연동)
필요한 모듈을 모두 설치 후 진행한다.
server.mjs
import express from "express";
import cors from "cors";
import path from "path";
import mariadb from "mariadb";
import { fileURLToPath } from "url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = express();
app.set("port", process.env.PORT || 3000);
app.listen(app.get("port"), () => {
console.log(app.get("port"), "번 포트에서 웹 서버 서비스 시작!");
});
const pool = mariadb.createPool({
host: "localhost",
user: "root",
password: "1111",
database: "test",
connectionLimit: 5,
});
// 미들웨어 설정
app.use(cors());
app.use(express.json());
app.use(express.static(path.join(__dirname, "public")));
// ... 이런식으로 미들웨어를 계속 나열할 수 있다.
// sangdata 테이블 자료 읽기
app.get("/sangdata", async (req, res) => {
try {
const conn = await pool.getConnection();
const sangpums = await conn.query("select * from sangdata");
res.json(sangpums);
conn.release(); // finally에 걸어도 괜찮다.
} catch (error) {
res.status(500).json({error : "요청한 서버파일 오류!!"});
}
});
app.use((req, res, next) => {
res.status(404).send("페이지를 찾을 수 없어!");
//next(); 미들웨어간의 흐름을 제어하는 콜백
});
app.use((error, req, res, next) => {
console.error(error.stack);
res.status(500).send("요청한 서버파일 오류!!");
});
select.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
async function fetchSangdata(){
try {
const response = await fetch('/sangdata');
const data = await response.json();
const tableBody = document.getElementById('data-body');
tableBody.innerHTML = '';
data.forEach(row => {
const tr = document.createElement('tr');
tr.innerHTML = `
<td>${row.code}</td>
<td>${row.sang}</td>
<td>${row.su}</td>
<td>${row.dan}</td>
`;
tableBody.appendChild(tr);
})
} catch (error) {
console.error('읽기 오류 : ', error);
}
}
window.onload = fetchSangdata;
</script>
</head>
<body>
<h2>상품자료 보기</h2>
<table border="1">
<thead>
<tr>
<th>코드</th><th>품명</th><th>수량</th><th>단가</th>
</tr>
</thead>
<tbody id="data-body">
</tbody>
</table>
</body>
</html>
에러
🚨 404 ERROR
미들웨어로 걸어주었던 에러 코드가 get 요청보다 위에 있을 경우 404 에러가 발생하였다.
미들웨어는 정의된 순서대로 실행된다.
경로와 관련 없는 미들웨어(app.use)는 모든 요청을 가로채므로,
특정 경로를 처리하는 핸들러(app.get, app.post 등) 아래에 두어야 한다.
404와 같은 요청 미처리 상황을 처리하는 미들웨어는 가장 마지막에 위치해야 에러를 피할 수 있다.
코드 수정 후
결과
노드 실습 (쿠키)
cookie.mjs
import express from "express";
import path from "path";
import { fileURLToPath } from "url";
const app = express();
const __dirname = path.dirname(fileURLToPath(import.meta.url));
app.use(express.static(path.join(__dirname, 'public')));
app.set('port', process.env.PORT || 3000);
app.get('/', (req, res) => {
console.log(req.url, ' ', req.headers.cookie);
res.cookie('mycookie', 'test', {httpOnly:true, maxAge:3600000});
// httpOnly:true 클라이언트 브라우저에서 쿠키에 접근하지 못하도록 막음, XSS 방지
res.send('HELLO COOKIE');
});
app.get("/login", (req, res) => {
const {name} = req.query;
if(name){
res.cookie('username', name, {httpOnly:true});
res.send(`<h2>${name}님 로그인 성공</h2>`);
} else {
res.status(400).send('<b>이름을 입력해라!</b>');
}
});
app.listen(80, () => {
console.log("80번 포트에서 웹 서버 서비스 시작!");
});
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="/login">
<input type="text" id="name" name="name" placeholder="메세지" />
<button id="login">로그인</button>
</form>
</body>
</html>
쿠키 생성 확인
쿠키에 value 담아 출력
'Study > Acorn' 카테고리의 다른 글
241209 노드 (RESTful) (0) | 2024.12.09 |
---|---|
241206 노드 (세션) (0) | 2024.12.06 |
241204 노드 (웹서버 구축, npm, expess, 라우팅, express 라우팅) (0) | 2024.12.04 |
241203 노드 (이벤트 처리, DB 연결) (0) | 2024.12.03 |
241202 노드 (개요, CommonJs, ESM, 동기/비동기) (3) | 2024.12.02 |