게시판의 경우는 글 제목을 클릭하면 상세페이지로 이동한다
detail/글 id
에 따라 해당 상세페이지로 이동시키기
post가 3개 존재하는 경우 detail/1 , detail/2, detail/3 각각 만들어야 할까?
그렇지 않다!
URL 파라미터 문법을 사용하면 파라미터에 따라 자동으로 url을 생성할 수 있다
/detail/:id
이렇게 콜론 : 뒤에 아무 텍스트나 작성하면 이게 파라미터가 된다
하지만 코드 이해를 위해 id로 작성하는 것 추천 !
그리고 글 상세페이지로 이동 시 detail.ejs 를 띄우면 될 것 같다
이게 가능한 이유는 ejs 파일은 마음대로 db 데이터를 사용할 수 있기 때문이다
➡️ 그래서 db에 따라 동적으로 페이지 생성이 가능하다
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href="/main.css" rel="stylesheet">
</head>
<body class="grey-bg">
<%- include('nav.ejs') %>
<div class="detail-bg">
<h4><%= details.title %></h4>
<p><%= details.content %></p>
</div>
</body>
</html>
여기서 잠깐,,
이 부분에서 문제가 발생했었다
main.css 가 detail/:id 경로에만 적용이 안된다는 것이다
/list 나 /write에는 스타일이 잘 적용되지만 왜 여기서는 안되는지 ..! 정말 한참을 끙끙댔다
문제는 내가href="main.css"
로 작성을 했었다는 것이다원인
이건 상대경로라 현재 페이지의 url에 따라 상대적으로 파일을 찾는 방법이라고 한다
예를 들어 detail/123 페이지에서 main.css 를 찾으면 브라우저는http://yourdomain.com/detail/main.css
를 참조한다
main.css 는 pulic 의 하위에 존재하기에 이러면 스타일을 찾을 수 없다해결
해결방법은 절대경로로 변경하는 것이다
href="/main.css
"로 작성을 하면 웹 사이트의 루트 디렉토리에서 main.css 를 찾는다
즉, 현재 페이지의 위치에 상관없이 내 웹사이트의 URL인http://yourdomain.com
에서 스타일을 찾아http://yourdomain.com/main.css
를 참조하게 된다
➡️그래서 url경로에 상관없이 ! 즉 라우트가 바뀌더라도 동일한 css 파일을 참조하게 된다
다시 돌아와서 ...
이 document에서 특정된 document 1개를 찾는 방법은 뭘까?
⬇️ 이것이 모든 post의 모든 document를 찾는 방법이었다면
await db.collection('post').find().toArray()
⬇️ 이것은 _id로 특정 1개를 찾는 방법이다
await db.collection('post').findOne({_id : new ObjectId('64bfde3b02d2932a4c06ffba')})
ObjectId(~)로 _id를 찾을 수 있지만!
사용하기 위해서는new
키워드를 붙여야 한다
const { ObjectId } = require('mongodb')
그리고 server.js에 이것도 추가해야 한다
app.get('/detail/:id', async(req,res)=>{
//<상세페이지 기능>
//1. 유저가 detail:xx 접속하면( 상세페이지 )
//2. {id:~} 를 db에서 찾아서
let result= await db.collection('post').findOne({_id: new ObjectId(req.params.id)}) //하나만 찾고싶을때, find.toArray() 는 전부 다
console.log(result)
//3. ejs 파일에 박아서 보내준다
//let result= await db.collection('post').find().toArray() //모든 결과 출력하기
res.render('detail.ejs',{details:result})
})
- app.get('/detail/:id' ~
req.params
: 유저가 입력한 파라미터 자리에 입력한 파라미터가 object 형으로 출력된다- ejs에서 데이터를 사용하기 위해
details
이라는 이름으로result
를 받아온다
<h4><%= details.title %></h4>
<p><%= details.content %></p>
그러면 detail.ejs에서 이렇게 사용 가능하다 !
list.ejs 의 title을 a 태그로 감싸기
<% for (let i=0; i<lists.length; i++) { %>
<div class="list-box">
<h4><a href="/detail/<%= lists[i]._id%>"><%= lists[i].title %></a></h4>
<p><%= lists[i].content %></p>
</div>
<% } %>
a 태그의 href 또한 <%%> 문법으로 작성가능하다
➡️ 어떤 post가 추가되던지 detail/id 로 바로바로 이동 가능하다
이러면 텍스트 링크에 밑줄이 쳐져있는데 이게 싫으면
a태그에 text-decoration : none
스타일을 추가하면된다
만약 유저가 detail/ 글의 _id 를 입력하는게 아니라 detail/ 잘못된 id를 입력해서 서버로 요청하면 어떻게 될까?
방지하기 위해 예외처리를 try-catch 문으로 해주기
app.get('/detail/:id', async(req,res)=>{
// 없는 id를 입력 시 에러발생, 에러를 방지하기 위한 try,catch 문
try{
//<상세페이지 기능>
//1. 유저가 detail:xx 접속하면( 상세페이지 )
//2. {id:~} 를 db에서 찾아서
let result= await db.collection('post').findOne({_id: new ObjectId(req.params.id)}) //하나만 찾고싶을때, find.toArray() 는 전부 다
console.log(result)
//3. ejs 파일에 박아서 보내준다
//let result= await db.collection('post').find().toArray() //모든 결과 출력하기
res.render('detail.ejs',{details:result})
}catch(e){
console.log(e)
res.status(400).send('url 주소가 잘못됨')
}
})