데옹의 블로그

Node.js 로 간단 쪽지 기능 구현 (2) 본문

NodeJS

Node.js 로 간단 쪽지 기능 구현 (2)

성띠용 2022. 8. 25. 10:41

Node.js 로 간단 쪽지 기능 구현 (1)
에서 말한 것처럼 API는 총 5개고 이번에는 나머지 2개를 해보겠습니다.


이번 포스트 에서는 아래 두개를 다룰거에요.

  • 쪽지 방 (socket에선 room?) 을 생성
  • 쪽지 방 확인하기 (카톡 방 처럼 리스트로 보이게 하려 했음)
  • 쪽지 보내기
  • 쪽지 확인하기
  • 쪽지 방 나가기

4. 쪽지 확인하기

여기서부터는 생각도 꽤 하고 수정도 해가면서 만들었습니다.

 

우선 쪽지 방을 만들게 되면 그 곳엔 2명의 사람이 있을 것이고, 어떤게 내가 보냈는 지를 확인할 수 있어야 한다고 생각했습니다.

 

그러기 위해서 userIdx와 matchIdx를 따로 받을 수도 있었겠지만 그러지 않고 roomId에 식별자가 들어가있게 설정을 해두었으니 그 것과 JWT로 들어올 userIdx를 비교하여 무엇이 받는 쪽지고 무엇이 보낸 쪽지인지 확인할 수 있게 했습니다.


  • Controller.js
// 쪽지 내용 확인
exports.getMsg = async function (req, res) {
  const userIdxFromJWT = req.verifiedToken.userIdx;
  const roomId = req.body.roomId;				// '1_2' 의 형식으로 들어옴
  
  if(!roomId) {
    return res.send(response(baseResponse.MSG_ROOMID_EMPTY));	// error code
  }

  const arr = roomId.split("_");				// * 참고 1
  const userIdx = arr[0];					// '1_2' 에서 1
  const matchIdx = arr[1];					// '1_2' 에서 2

  // 보낸/받는 사람 구별
  if (userIdxFromJWT == userIdx) {		// JWT로 받은 인덱스가 arr[0]과 같다면
    const sender = userIdx;			// 우리는 위 주석에서 1에 해당하는 사람으로 인식됩니다.
    const receiver = matchIdx;

    const result = await msgProvider.getMsg(roomId, sender, receiver);
    return res.send(response(baseResponse.SUCCESS, result));
  }
  else if (userIdxFromJWT == matchIdx) {	// 반대의 경우
    const sender = matchIdx;
    const receiver = userIdx;

    const result = await msgProvider.getMsg(roomId, sender, receiver);
    return res.send(response(baseResponse.SUCCESS, result));
  }
};

**** 변수 명은 먼저 아무거나 알아보기 편하게 설정한 것이니 의미 부여 너무 하지 않기 ****

 

* 참고 1

split이라는 함수를 사용해서 body로 받아온 roomId를 분리한 것입니다.

위에서는 split("_") 으로 했는데 이 것은 _를 기준으로 나누는거에요. 그럼 '1_2' 가 1 과 2 로 분리가 됩니다.

 

위에 주석에 간단히 써놨는데 더 자세히 써보자면

 

JWT로 넘어온 userIdx 가 1이라고 했을 때 DB의 senderIdx가 1이면 '보낸 쪽지', 1이 아니면 '받은 쪽지'로 나와야 합니다.

그걸 하나의 쿼리로 다 뽑기 위해서 if문을 사용한건데

 

jwt로 받은 userIdx와 MsgRoom에 있는 userIdx가 동일하면 userIdx가 sender가 되고 그 반대는 matchIdx가 sender가 됩니다. (userIdx = 채팅방 만든 사람, matchIdx = 채팅방에 참여한 사람)

 

고대로 파라미터를 Provider.js로 보내줍니다.


  • Provider.js
exports.getMsg = async function (roomId, sender, receiver) {
    try {
        const params = [sender, receiver, roomId];
        const connection = await pool.getConnection(async (conn) => conn);

        const getMsgResult = await msgDao.getMsg(connection, params);
        
        connection.release();
        return getMsgResult;

        } catch (err) {
        logger.error(`getMsg Provider error\n: ${err.message}`);
        return errResponse(baseResponse.DB_ERROR);
    }
};

위에서 이미 sender와 receiver를 구분해서 값을 받아왔기 때문에 딱히 뭔가를 해줄 필요는 없습니다.

그냥 이대로 Dao로 넘기면 될 것 같아요.


  • Dao.js
SELECT (CASE
		WHEN senderIdx = ? THEN 'send'
		WHEN senderIdx = ? THEN 'receive'
        END) AS status, text, sendAt
FROM Message WHERE roomId = ? ORDER BY sendAt ASC;

간단한 select문인데 case when을 추가하여 각 상황에 맞게 나올 수 있도록 했습니다.

1과 2가 쪽지를 주고 받을 때 Controller에서 1 이라는 userIdx를 sender로 인식했다면 Provider에서의 파라미터 값은

[ 1, 2, 1_2] 가 되겠죠. (sender, receiver, roomId)

이 순서대로 쿼리문에 들어갈테니

senderIdx = 1 이면 'send'

senderIdx = 2 이면 'receive'로 표시가 될 것입니다.

이 것들을 보낸 시각 즉 sendAt을 오름차순으로 정렬을 했습니다.

 

이렇게 쪽지 보내기는 마무기가 됩니다.


4. 쪽지 방 삭제하기

마지막으로 쪽지 삭제하기 입니다.

우선 쪽지 삭제는 이렇게 진행이 돼요..

roomId = '1_2' 라고 예를 들게요~!

  • 1이 쪽지 방을 삭제하더라도 2는 이전에 쪽지를 볼 수 있어야 한다.
  • 둘 다 나가면 DB에서 삭제

대충 이런 목적을 갖고 만들었는데, 함 볼게여


  • Controller.js
exports.deleteMsg = async function (req, res) {
  const userIdx = req.verifiedToken.userIdx;
  const roomId = req.body.roomId;

  if(!roomId) {
    return res.send(response(baseResponse.MSG_ROOMID_EMPTY));	// error code
  }

  const arr = roomId.split("_");
  const userIdxAtRoom = arr[0];
  const matchIdxAtRoom = arr[1];		// roomId를 분리하면서 Index 파악

  const getRoomIdxResult = await msgProvider.getRoomIdx(roomId);	// DB에 있는 index 확인
  const MsgRoomUserIdx = getRoomIdxResult[0].userIdx;
  const MsgRoomMatchIdx = getRoomIdxResult[0].matchIdx;		// 할당

  if(MsgRoomUserIdx == 7 || MsgRoomMatchIdx == 7) {			// 만약 둘 중 하나라고 7이라면
    const result = await msgService.deleteMsg(roomId);		// 방 바로 삭제
  } else if(userIdx == userIdxAtRoom) {
    const result = await msgService.updateExitUserIdx(roomId, MsgRoomMatchIdx, 1);
  } else if(userIdx == matchIdxAtRoom) {
    const result = await msgService.updateExitUserIdx(roomId, MsgRoomUserIdx, 2);
  } 	// 나머지 else if문은 내가 해당되는 index를 바꿔주기 위함

  return res.send(baseResponse.SUCCESS);
}

보기 전에 7이라는 userIdx는 제가 그냥 dummy data로 넣은 것입니다. 그냥 제가 만들기 편할 것 같아서 넣었어요.

 

roomId를 분리하는 것까진 위에서 했으니 따로 하진 않겠습니다.

 

DB에 있는 index확인은 왜 하냐면.. 거기에 지금 dummy data가 있는지 확인하고 값들을 할당해주기 위함입니다. 아까 말한 상황들을 제대로 수행하려면 확인하고 둘 중 하나라고 dummy data가 있는지 확인해야해요!

 

그 밑의 할당이라고 쓴 주석은 그냥 진짜 할당만 해준거에요. 바로 위에서 얻은 값들을요.

간단한 get 즉 select문이기 때문에 따로 Provider와 Dao를 적지는 않겠습니다.

 

그 밑의 if문을 보겠습니다.

우선 만약 둘 중 하나라도 이미 7 즉 dummy data라면 그냥 방을 아예 DB에서 삭제해버리는 겁니다.

 

근데 그 밑의 것들은 좀 달라요..

둘 중 하나라고 더미데이터가 아닌 상황인데, 그럼 제가 해당되는 컬럼의 index를 더미데이터로 바꿔줘야겠죠.

 

그 부분을 위해서 2명이 쪽지하는거니까 2개의 상황을 만든거고, Service로 넘어가는 파라미터 중 1,2 는 index가 아니고 Service에서 type별로 로직을 나눠뒀기 때문에 여기서 한 번에 보내주는 거에요!

 

바로 Service 보겠습니다.


  • Service.js
exports.deleteMsg = async function (roomId) {
    try {
        const connection = await pool.getConnection(async (conn) => conn);
        
        const deleteMsgResult = await msgDao.deleteMsg(connection, roomId);

        connection.release();
        return response(baseResponse.SUCCESS);
    }
    catch (err) {
        logger.error(`App - deleteMsg Service error\n: ${err.message}`);
        return errResponse(baseResponse.DB_ERROR);
    }
}

첫번째로 둘 중 하나라도 dummy data가 있으면 방을 아예 삭제해버린다고 했죠.

그냥 간단하게 DB에서 삭제해버리는 로직입니다.

Dao도 굉장히 간단해요.

DELETE FROM MessageRoom
WHERE roomId = ?;

그냥 이 정도....

근데 이제 두개 다 dummy data가 아니다..?

exports.updateExitUserIdx = async function (roomId, remain, type) {
    try {
        var params;

        if(type == 1) {
            params = [7, remain, roomId];
        } else if(type == 2) {
            params = [remain, 7, roomId];
        }

        const connection = await pool.getConnection(async (conn) => conn);
        
        const updateExitUserIdx = await msgDao.updateExitUserIdx(connection, params);

        connection.release();
        return response(baseResponse.SUCCESS);
    }
    catch (err) {
        logger.error(`App - updateExitUserIdx Service error\n: ${err.message}`);
        return errResponse(baseResponse.DB_ERROR);
    }
}

다른건 사실 볼 필요가 없고 if문에 들어가 있는 것만 보면 됩니다.

아까 Controller에서 type별로 1,2 나눠서 파라미터를 전송해줬습니다. 그 안의 코드는 내가 어느 컬럼에 속해있는지 판단해서 타입별로 나눠 보내게 된 것이었는데요.

 

1번의 경우 내 userIdx가 roomId = '1_2' 중 1이었다면 그 위치의 컬럼을 dummy data로 바꿔버릴거에요.

2번은 그 반대구요.

remain에는 roomId에서 내 userIdx가 아닌 index가 들어가있습니다.

UPDATE MessageRoom
SET userIdx = ?, matchIdx = ?
WHERE roomId = ?;

그래서 따로 정리할 것 없이 이렇게 해버리면 1번의 경우엔 userIdx = 7, matchIdx = 2 가 되겠죠.

그럼 성공입니다 ㅎㅎ userIdx 에 속한 사람은 나갔다고 표시가 될거에요!


여기까지가 끝입니다..

완벽한 코드도 아니고 그냥 제가 만들어보고 싶어서 만들었어요.

그래도 좀 종이에 로직을 써가며 어떤 오류가 생기는지 보면서 테스트 했고, 나름 괜찮은 결과를 얻은 것 같습니다.

같은 팀 내의 프론트엔드 분께 일단 API sheet를 전달해드렸는데 오늘 결과물이 나올 것 같네요 ㅠㅠ

결과물이 나온다면 또 쓰러 와야지...

 

아직 뭔가를 다루는 것이 어설픈 것 같은데 언제쯤 능숙해져서 시니어 개발자처럼 멋있어질지 모르겠네요.

Nodejs도 정말 좋지만, 제가 취업하고 싶은 회사는 Spring을 사용하기에..

함 도전해보려 합니다

그럼 20000

'NodeJS' 카테고리의 다른 글

Node.js 로 간단 쪽지 기능 구현 (1)  (0) 2022.08.12