Node.js

node>채팅기능 만들기 2 (채팅방/상세페이지 숙제)

연습노트 2024. 9. 19. 09:38

새로운 것은 없고 저번시간 숙제만 해보기 때문에 

잘 해왔으면 다음강의 넘어가도 될듯 합니다.

 

전 어떻게 했는지 요약하자면 

1. 채팅버튼 누르면 /chat/request 로 요청날리고

/chat/request로 요청들어오면 chatroom이라는 컬렉션에 채팅방용 document 하나 발행해서 

{ member : [내_id, 글쓴이_id] } 같은거 저장해둠

 

2. /chat/list 로 접속하면 채팅방 목록페이지 (chatList.ejs) 보여줌 

- 근데 DB에서 내 _id가 member 필드에 적혀있는 document를 다 찾아와서 chatList.ejs파일에 넣어서 보여줌 

 

3. 채팅방 상세페이지를 만들어야하는데 채팅방은 100만개가 있으므로

/chat/detail/바보 로 접속하면 채팅방의 _id가 '바보'인 document를 찾아와서 chatDetail.ejs 에 넣어서 보여줌 

그리고 chatList.ejs에서 채팅방 제목을 누르면 상세페이지로 이동하는 링크도 만들어놨음 

 

 

 

 

1. 채팅버튼 누르면 채팅방 발행

 

 

(detail.ejs)

<a href="/chat/request">채팅하기</a> 

저는 그냥 상세페이지에 채팅버튼 만들었습니다.

이거 누르면 서버에서 채팅방 document를 하나 발행해줍시다.

채팅방 document에는 뭘 적으면 좋을까요? 

누가 참여했는지 / 채팅메세지 / 날짜 이런걸 보관하면 좋을 것 같으니 그렇게 합시다.

 

그래서 서버에서 현재유저_id, 글쓴이 _id 이런게 필요할텐데

현재유저_id는 쉽게 꺼내쓸 수 있을텐데 글쓴이 _id는 어딨죠?

그건 유저에게 보내라고 합시다.

아마 detail.ejs 안에선 <%= result %> 변수 출력해보면 글쓴이 _id도 나오지 않을까요.

 

 

 

(detail.ejs)

<a href="/chat/request?writerId=<%= result.user %>">채팅하기</a>

그래서 이렇게 채팅버튼을 만들어봤습니다.

누르면 /chat/request로 GET요청 되는데

그럼 서버로 가서 채팅방 만들어주는 기능을 만들어봅시다.

 

 

 

app.get('/chat/request', async (요청, 응답)=>{
  await db.collection('chatroom').insertOne({
    member : [요청.user._id, new ObjectId(요청.query.writerId)],
    date : new Date()
  })
  응답.redirect('채팅방목록페이지')
})}) 

채팅방은 그냥 document입니다.

그래서 서버에선 chatroom 컬렉션에 document 하나 발행하라고 했습니다.

document 내용은 여러분 맘대로 채웁시다.

 

 

 

 

 

 

2. 내가 들어있는 채팅방 목록 보여주는 페이지

 

 

app.get('/chat/list', async (요청, 응답)=>{
  let result = await db.collection('chatroom').find({ member : 요청.user._id }).toArray()
  응답.render('chatList.ejs', {글목록 : result})
}) 

내가 속한 채팅방들을 다 가져와서 보여주는 페이지도 필요해서 하나 만들어봤습니다.

누가 /chat/list 접속하면 채팅방 document 중에 내 _id가 기재된걸 다 가져와서 chatList.ejs에 박아서 보내줍니다.

 

Q. 지금 document에 { member : [내_id, 글쓴이_id] }이런 식으로 array로 저장되어있는데 어떻게 찾음?

- 그냥 { member : 내_id } 찾아오라고 작성해도 { member : [내_id, 글쓴이_id] } 이런거 잘 찾아옵니다.

정확히 하려면 $in 연산자도 있습니다.

 

 

참고용 chatList.ejs 파일 레이아웃

 

<div class="white-bg">
    <% for (let i = 0; i < result.length; i++){ %>
      <div class="list-box">
        <h4>
          <a>채팅방제목</a>
        </h4>
        <p>채팅방설명~~</p>
      </div>
    <% } %>
</div> 

 

[collapse]

 

 

 

 

 

3. 채팅방 하나 누르면 그 채팅방의 상세페이지가 뜸

 

chatList.ejs 파일에 있던 채팅방 하나 클릭하면

그 채팅방 document 내용이 적힌 상세페이지같은거 하나 만들어줍시다.

 

app.get('/chat/detail', async (요청, 응답)=>{
  응답.render('chatDetail.ejs')
}) 

서버에 상세페이지 보여주는 API부터 하나 만들어봤습니다.

chatDetail.ejs 레이아웃은 아마 저번 강의에 있음

 

근데 채팅방이 100만개 될텐데 그거마다 API를 각각 만들어줘야겠죠?

누가 /chat/detail/a 로 접속하면 채팅방 _id가 a인걸 가져와서 상세페이지에서 보여주고 

누가 /chat/detail/b 로 접속하면 채팅방 _id가 b인걸 가져와서 상세페이지에서 보여주고 

이렇게 이렇게 100만개 쓰면 될거같은데 그게 싫으면...

 

 

app.get('/chat/detail/:id', async (요청, 응답)=>{
  let result = await db.collection('chatroom').findOne({ _id : new ObjectId(요청.params.id)})
  응답.render('chatDetail.ejs', {result : result})
}) 

URL 파라미터 씁시다. 실은 query string 으로 만들어도 상관없음

- 누가 /chat/detail/어쩌구로 접속하면

- 채팅방 id가 어쩌구인걸 DB에서 찾아서 그 document 내용을 ejs파일에 박으라고 했습니다.

이제 chatDetail.ejs 페이지에서 result 변수 출력해보면 document 내용 나올텐데

그걸로 html 잘 꾸미면 되겠군요.

 

 

 

 

 

채팅방 상세페이지로 이동하는 링크도 만들었음

 

(chatList.ejs)

<h4>나의 채팅방 목록 </h4>
  <div class="white-bg">
    <% for (let i = 0; i < 글목록.length; i++){ %>
      <div class="list-box">
        <h4>
          <a href="/chat/detail/<%= 글목록[i]._id %>">
             채팅방 <%= i %>
         </a>
      </h4>
      <p><%= 글목록[i]._id %></p>
    </div>
  <% } %>
</div> 

방금 만든 /chat/detail/어쩌구 페이지로 이동하는 버튼도

채팅목록페이지에 만들어놨습니다.

 

 

 

그리고 마지막으로 예외처리 같은 것도 잘 해주면 좋겠죠?

내가 속한 채팅방이 아닌데도 그걸 보려고 하는 사람들은 막는 코드를 서버에 추가하는게 좋을 것 같은데

그런건 집에서 알아서 해봅시다.