app.js : node.js를 통해 서버 코드를 적어놓는 곳
restaurants.json : 식당 정보들을 저장해놓은 파일(식당들은 이름, 주소등을 가진 객체로서 저장된다.)
restaurant-item.ejs: ejs의 include 기능을 통해 restaurants.ejs의 식당 출력 내용을 묶어둔 것
404.ejs: page not found 표시하는 페이지

이런 식으로 내가 등록한 식당들을 /restaurants 페이지에 for문으로 추가를 해놓았다.
그리고 'View Restaurant'을 누르면 그 식당에 대한 자세한 설명이 있는 페이지로 이동하고 싶다고 하자.
그럼 첫번째 식당의 페이지는 '/restaurants/r1', 두 번째는 '/restaurants/r2' 이런 식으로 될 텐데
app.get("/restaurants/r1",....)
app.get("/restaurants/r2",....)
app.get("/restaurants/r3",....)
.
.
.
이런 식으로 다 app.js에 적어야 할까..?
당연히 너무 비효율적이고 다른 방법이 필요하다.
이런 경우에는
app.get("/restaurants/:id", function (req, res) {
const restaurantId = req.params.id;
res.render("restaurant-detail", {rid: restaurantId});
});
이런 식으로 콜론(:)뒤에 변수를 넣어주면 된다. 그러면 "/restaurants/r1"로 이동하면 r1이, restaurants/r2"로 이동하면 r2가 id가 되는 형태이다.
그리고 밑에서 id를 req.params.id로 가져와서 페이지에 전달도 가능하다.
<!-- restaurant-item.ejs -->
<li class="restaurant-item">
<article>
<h2><%= restaurant.name %></h2>
<div class="restaurant-meta">
<p><%= restaurant.cuisine %></p>
<p><%= restaurant.address %></p>
</div>
<p>
<%= restaurant.description %>
</p>
<div class="restaurant-actions">
<a href="restaurants/r1">View Restaurant</a>
</div>
</article>
</li>
위와 같이 하고 "/restaurants/r1"로 접속할 수 있게 만들어 놓고 막상 접속을 해보면 css가 적용되어 있지 않다.
위에서 a 태그의 href를 restaurants/r1으로 했는데, 이는 이 요청이 일어난 곳에서의 상대경로이다.
지금까지는 /...이었기에 문제가 상관없었다. 하지만 이번에는 /.../...(/restaurants/r1)으로 두번 들어갔기에 상대경로가 틀린 것이다.
그래서 절대 경로로 만들기 위해 앞에 /를 붙여줘야 한다.
이렇게
<a href="/restaurants/r1">View Restaurant</a>
위에서는
<a href="/restaurants/r1">View Restaurant</a>
와 같이 test용으로 r1 이렇게 하나를 고정시켜놓았다.
이제 동적으로 id를 불러와보자.
우선 data를 저장해둔 restaurant.json 파일의 식당에 id라는 index를 추가했다.
예시)
{
"id":"r1",
"name":"3훈비 병사식당",
"address":"제3훈련비행단 사천 경남 대한민국",
"cuisine":"급식",
"website":"https://intranet.meal.com",
"description":"Because I eat in the restaurant everyday"
}
그런 다음에 restaurant-item.ejs에
<a href="/restaurants/<%= restaurant.id %>">View Restaurant</a>
이런식으로 ejs를 이용해서 수정을 해주면 된다.
또한 앞으로 식당 데이터를 추가할 때, 자동으로 id도 추가가 되야하는데 식당 이름이 겹치거나 같은 식당을 넣을 수도 있기에 이런 id를 추가해주는 패키지 uuid를 추가하고 app.js에
const uuid =require("uuid");// 이 부분이 추가된 부분!!!
app.post("/recommend", function(req, res) {
const restaurant = req.body; //object save
restaurant.id = uuid.v4(); // 이 부분이 추가된 부분!!!
const filePath = path.join(__dirname, "data", "restaurants.json");
const fileData = fs.readFileSync(filePath);
const storedRestaurants = JSON.parse(fileData);
storedRestaurants.push(restaurant);
fs.writeFileSync(filePath, JSON.stringify((storedRestaurants)));
res.redirect("/confirm");
});
위와 같이 uuid 객체를 불러온다음 식당을 등록하는 app.post("/recommend")에서 uuid를 통해 등록하는 식당 객체의 id를 부여해줄 수 있다.
/restaurants/식당id 이런식으로 들어가는데 예를 들어 없는 식당 id '/restaurants/r500' 이런식으로 들어갈 경우 계속 로딩하다가 time-out이 뜬다.
그 이유는 단순하다.
app.get("/restaurants/:id", function (req, res) {
const restaurantId = req.params.id;
const filePath = path.join(__dirname, "data", "restaurants.json");
const fileData = fs.readFileSync(filePath);
const storedRestaurants = JSON.parse(fileData);
for(const restaurant of storedRestaurants) {
if(restaurant.id== restaurantId) {
return res.render("restaurant-detail", {restaurant: restaurant});
}
}
});
우리가 오류에 대해 처리하는 코드를 작성하지 않아 아무것도 반환하지 않기에 계속 기다리다가 time-out이 뜨는 것이다.
그러니 단순하게 404.ejs: page not found 표시하는 페이지를 만들고 마지막에 넣어주면 된다.
app.get("/restaurants/:id", function (req, res) {
const restaurantId = req.params.id;
const filePath = path.join(__dirname, "data", "restaurants.json");
const fileData = fs.readFileSync(filePath);
const storedRestaurants = JSON.parse(fileData);
for(const restaurant of storedRestaurants) {
if(restaurant.id== restaurantId) {
return res.render("restaurant-detail", {restaurant: restaurant});
}
}
res.render('404');// 이 부분이 추가된 부분!!!
});
참고로 나는 404.ejs를 그냥 만들어 놓아서 처음에 error가 발생했는데 우리가 위에
app.set("views", path.join(__dirname, "views"));
app.set("view engine", "ejs");
ejs를 views 폴더에 있는 파일들을 읽는 template engine이기에 views 파일에 꼭 넣어야 한다.
그냥 restaurants를 retaurant 이런 식으로 오타를 칠 수도 있다.
이런 경우에는 파일을 못찾아서 못생긴 화면이 뜨는데 이런 경우에도 404를 띄우려면
'미들웨어'를 사용해야 한다.
app.use(express.static("public")); // css, js file request solution
app.use(express.urlencoded({extended: false}));
위에서 이렇게 use해서 모든 요청에 관한 것을 정의하는 것을 미들웨어라고 했다.
그럼 app.js에서 모든 get들에 다 튕겨서 잘못된 url일 때, 마지막 줄에
app.use(function(req,res) {
res.render("404");
});
이렇게 미들웨어를 이용해서 404를 표시해주면, 잘못된 url을 쳐도 404.ejs로 이어진다.
서버에서 문제가 생겨서 페이지가 로드되지 않을 수도 있다.
이 경우는 client 오류인 400대 오류가 아닌 500 오류를 표시해줘야 한다.
500.ejs를 404.ejs와 비슷하게 만들어줬다고 하고 출력하는 법을 보자.
똑같이 미들웨어를 사용하는데 평소처럼 2개의 parameter가 아니라 4개의 parameter를 사용한다.
app.use(function(error, req, res, next) {
res.render("500");
});
이렇게 4개의 파라미터를 사용하면 express가 기본 오류 핸들러로 이 코드를 사용한다고 한다.
나도 아직은 잘..ㅎ
점점 더 복잡해지고 구조화되고 오류 같은 디테일도 생긴다는게 보인다.
안할 것 같긴 하지만 시간이 된다면 파일간 구조를 그려보는 것도 괜찮을 정도로 파일 수가 상당히 늘었다.
이런 것들이 앞으로 나의 토이 프로젝트나 개발 활동에 더욱 풍부한 선택지와 디테일을 넣어줄 것 같다.
그럼 오늘은 여기까지:)
