[Node.js/mongoDB] 8. 상세페이지 만들기

지렁·2023년 10월 28일
1

게시판의 경우는 글 제목을 클릭하면 상세페이지로 이동한다

이 기능을 구현해볼 것이다

detail/글 id 에 따라 해당 상세페이지로 이동시키기

post가 3개 존재하는 경우 detail/1 , detail/2, detail/3 각각 만들어야 할까?
그렇지 않다!
URL 파라미터 문법을 사용하면 파라미터에 따라 자동으로 url을 생성할 수 있다



🖤 URL 파라미터 문법

/detail/:id

이렇게 콜론 : 뒤에 아무 텍스트나 작성하면 이게 파라미터가 된다
하지만 코드 이해를 위해 id로 작성하는 것 추천 !

그리고 글 상세페이지로 이동 시 detail.ejs 를 띄우면 될 것 같다

  • 유저가 /detail/1 로 접속해도 detail.ejs 보내주고
  • 유저가 /detail/2 로 접속해도 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 파일을 참조하게 된다


다시 돌아와서 ...

🖤 DB에서 특정 document 1개 찾기

이 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에 이것도 추가해야 한다


🖤 유저가 입력한 URL 가져오기

  • 플로우
  1. /detail/:id 접속하면
  2. 해당 id를 DB에서 찾아와서
  3. ejs에 데이터바인딩을 하여 유저에게 보내기
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})

})
  1. app.get('/detail/:id' ~
  2. req.params : 유저가 입력한 파라미터 자리에 입력한 파라미터가 object 형으로 출력된다
  3. ejs에서 데이터를 사용하기 위해 details 이라는 이름으로 result 를 받아온다
<h4><%= details.title %></h4>
 <p><%= details.content %></p>

그러면 detail.ejs에서 이렇게 사용 가능하다 !


🖤 list의 post 제목을 링크로 변경하여 바로 상세페이지로 이동시키기

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 주소가 잘못됨')
    }
})
profile
공부 기록 공간 🎈💻

0개의 댓글