2019/11/15 - [띡딱똑띡 개발자 Hanna] - NodeJS와 MongoDB로 SNS 만들어보기 - user_ment (댓글/대댓글 라우터)
ㄴ 이전 글
* 현재까지 설명한 router => 7번 (user_passport), 10번 (user_profile), 4번 (user_follow),
8번 (user_posting), 9번 (user_postingPlus), 6번 (user_ment)
* 현재 설명하고자 하는 router => 5번 (user_likey)
> user_likey
user_likey.js는 게시글/댓글/대댓글 좋아요 관련 라우터를 정의한 파일입니다.
이 파일에서 정의된 라우터는 하나인데, 좋아요 상태를 바꿔주는 라우터입니다.
좋아요를 한 상태라면 좋아요를 해제시키고, 하지 않은 상태라면 좋아요 설정을 합니다.
/flipLike/:mode/:objectId/:postId
> mode는 좋아요 상태를 바꿀 것이 '게시글'인지 '댓글'인지 '대댓글'인지 알려주는 변수입니다.
게시글이라면 post, 댓글이면 upment, 대댓글이면 downment라는 키워드를 사용합니다.
> objectId는 좋아요 상태를 바꿀 것의 ObjectId입니다.
> postId는 부모 게시글의 ObjectId값으로, '댓글' 및 '대댓글' 경우 필요합니다.
'게시글'의 경우에는 어떤 값이됐든 사용하지 않습니다만,
GET요청시 postId부분에 무언가 쓰지 않으면 해당 라우터로
요청이 오지 않기 때문에 아무 값(보통 0)으로 보내면 됩니다.
라우터가 하나밖에 없는만큼 함수 구조도 추가적으로 설명해보겠습니다.
라우터 자체에서는 setLike 함수만을 불러오는 간단한 구조인데,
setLike (좋아요 상태 변경) 함수에서 getUserLike (좋아요 상태 반환) 함수
updateCount (좋아요 수±) 함수를 사용합니다.
// enum (이름 체크 함수 리턴 값에 사용)
const TYPE = Object.freeze({
'Post': 2,
'Upment': 1,
'Downment': 0
});
module.exports = function (router) {
console.log('user_likey 호출됨.');
// 좋아요 표기
router.route('/flipLike/:mode/:objectId/:postId').get(function (req, res) {
if (로그인한 유저가 아닌 경우) {
res.status(400).json({ 에러났다고 결과 알림 });
return;
}
파라미터 설정 (유저 ObjectId, mode, objectId, postId)
if (데이터베이스 존재) {
//좋아요 설정/해제
setLike(database, modeType, paramPostId, paramObjId, paramID,
function (err, result, isAdd, likeNum) {
if (err) {
res.status(400).json({ 에러났다고 결과 알림 });
return;
}
if (result 존재하는 경우) {
res.status(200).json({ 좋아요를 설정했는지 해제했는지 알림, 현재 총 좋아요 수를 반환 });
}
else {
// [case 1]
// 사용자 A가 게시글 조회 중 => 게시자가 게시글/댓글/대댓글 삭제
// => 사용자 A가 좋아요 누름 => 해당 게시글/댓글/대댓글은 존재하지 않음.
// [case 2]
// 사용자 A가 좋아요 누름 => 파라미터가 잘못됨
// 파라미터에 해당하는 게시글/댓글/대댓글은 존재하지 않음.
// 위와 같은 경우 result가 존재하지 않게 된다.
res.status(200).json({ 해당 게시글/댓글/대댓글이 존재하지 않음을 알림 });
}
}
}
else {
res.status(500).json({ 데이터베이스 에러났다고 알림 });
}
}
ㄴ 라우터 코드 흐름
// 좋아요 여부에 따른 LikePostModel 생성
var setLike = function (database, type, paramPostId, objectID, userID, callback) {
if (게시글이면) {
// 해당 게시글 좋아요 여부 반환
getUserLike(database, type, objectID, userID, function (err, result) {
// 해당 좋아요 여부에 따라 좋아요 개수 조작
updateLikeCount(database, isAdd, type, objectID, function (err, result) {
if (좋아요 설정하는 경우) {
// 좋아요 테이블에 정보 생성
database.LikePostModel.create(...);
// setLike 최종 결과 반환
callback(err, result, isAdd, likeNum);
}
else {
// 좋아요 테이블 정보 삭제
database.LikeUpmentModel.findOneAndRemove(...);
// setLike 최종 결과 반환
callback(err, result, isAdd, likeNum);
}
}
}
}
else if (댓글이면) {
// ... 게시글과 같은 흐름으로 진행
}
else if (대댓글이면) {
// ... 게시글과 같은 흐름으로 진행
}
}
ㄴ setLike 함수 코드 흐름
// 해당 유저의 좋아요/북마크 여부 반환
var getUserLike = function (database, type, objectID, userID, callback) {
if (게시글이면) {
database.LikePostModel.findOne(...);
callback(err, 좋아요 여부);
}
else if (댓글이면) {
database.LikeUpmentModel.findOne(...);
callback(err, 좋아요 여부);
}
else if (대댓글이면) {
database.LikeDownmentModel.findOne(...);
callback(err, 좋아요 여부);
}
}
// 게시글/댓글/대댓글 count 값 수정
var updateLikeCount = function (database, isAdd, type, ID, callback) {
// 좋아요 해제/설정에 따른 count 값 수정
if (게시글이면) {
database.PostModel.findOneAndUpdate(...);
callback(err, result);
}
else if (댓글이면) {
database.UpmentModel.findOneAndUpdate(...);
callback(err, result);
}
else if (대댓글이면) {
database.DownmentModel.findOneAndUpdate(...);
callback(err, result);
}
}
ㄴ getUserLike, updateLikeCount 함수 코드 흐름
--- 여기서부터는 실질 코드 모습입니다.
//enum (게시글/댓글/대댓글 판별 시 사용)
const TYPE = Object.freeze({
'Post': 2,
'Upment' : 1,
'Downment' : 0
});
module.exports = function (router) {
console.log('user_likey 호출됨.');
// 좋아요 표기
router.route('/flipLike/:mode/:objectId/:postId').get(function (req, res) {
console.log('/flipLike/' + req.params.mode + "/" + req.params.objectId + "/" + req.params.postId + '패스 요청됨.');
// 인증 안된 경우
if (!req.user) {
console.log('사용자 인증 안된 상태임.');
res.status(403).json({
isLike: false,
errorMsg: '로그인 필요 (flipLike)'
});
return;
}
// 파라미터 설정
var paramID = req.user._id;
var paramMode = req.params.mode;
var paramObjId = req.params.objectId;
var paramPostId = req.params.postId;
var modeType;
// 댓글/대댓글은 소속 게시판 id도 있어야 함.
if (paramMode == "post") {
modeType = TYPE.Post;
} else if (paramMode == "upment" && paramPostId) {
modeType = TYPE.Upment;
} else if (paramMode == "downment" && paramPostId) {
modeType = TYPE.Downment;
} else {
res.status(403).json({
isLike: false,
errorMsg: '파라미터 에러 (flipLike)'
});
return;
}
// 데이터베이스 객체 참조
var database = req.app.get('database');
if (database.db) {
// 좋아요 상태에 따른 설정/해제
setLike(database, modeType, paramPostId, paramObjId, paramID, function (err, result, isAdd, likeNum) {
// 에러 처리
if (err) {
console.error(err.stack);
res.status(400).json({
isLike: false,
errorMsg: err.stack
});
return;
}
var keyword = (modeType == TYPE.Post) ? "게시글" : (modeType == TYPE.Upment) ? "댓글" : "대댓글";
if (result) {
keyword = keyword + " 좋아요";
if (isAdd) {
keyword = keyword + " 설정";
} else {
keyword = keyword + " 해제";
}
console.log(keyword);
res.status(200).json({
isLike: true,
status: isAdd ? 1 : 0,
likeNum: likeNum
});
} else {
keyword = "삭제된 " + keyword + "입니다.";
res.status(200).json({
isLike: false,
errorMsg: keyword
});
}
});
} else { // 데이터베이스 객체가 초기화되지 않은 경우 실패 응답 전송
res.status(500).json({
isLike: false,
errorMsg: "데이터베이스 연결 실패"
});
}
});
}
ㄴ 라우터 모습
// 좋아요 여부에 따른 LikePostModel 생성
var setLike = function (database, type, paramPostId, objectID, userID, callback) {
var isAdd;
if (type == TYPE.Post) {
var conditions = {
"post_id": objectID,
"user_id": userID
};
// 해당 게시글 정보 반환
getUserLike(database, type, objectID, userID, function (err, result) {
if (err) {
callback(err, null, null, null);
}
// 좋아요 돼있으면 좋아요 해제, 안돼있으면 좋아요 설정
if (!result) {
isAdd = true;
} else {
isAdd = false;
}
// 좋아요 개수 조작
updateLikeCount(database, isAdd, type, objectID, function (err, result) {
if (err) {
callback(err, null, null, null);
}
if (!result) {
// 게시글이 삭제된 경우
callback(null, false, null, null);
} else {
var likeNum = result.count.like_count;
if (isAdd) {
// 좋아요 추가
database.LikePostModel.create(conditions, function (err, res) {
if (err) {
callback(err, null, null, null);
return;
}
if (!res) {
callback("likePost 데이터 생성 오류", null);
} else {
callback(null, true, isAdd, likeNum);
}
}
);
}
else {
// 좋아요 삭제
database.LikePostModel.findOneAndRemove(conditions, function (err) {
if (err) {
callback(err, null, null, null);
return;
}
callback(null, true, isAdd, likeNum);
}
);
}
}
});
});
} else if (type == TYPE.Upment) {
var conditions = {
"post_id": paramPostId,
"upment_id": objectID,
"user_id": userID
};
// 해당 게시글 정보 반환
getUserLike(database, type, objectID, userID, function (err, result) {
if (err) {
callback(err, null, null, null);
}
// 좋아요 돼있으면 좋아요 해제, 안돼있으면 좋아요 설정
if (!result) {
isAdd = true;
} else {
isAdd = false;
}
// 좋아요 개수 조작
updateLikeCount(database, isAdd, type, objectID, function (err, result) {
if (err) {
callback(err, null, null, null);
}
if (!result) {
// 게시글이 삭제된 경우
callback(null, false, null, null);
} else {
var likeNum = result.count.like_count;
if (isAdd) {
// 좋아요 추가
database.LikeUpmentModel.create(conditions, function (err, res) {
if (err) {
callback(err, null, null, null);
return;
}
if (!res) {
callback("likePost 데이터 생성 오류", null);
} else {
callback(null, true, isAdd, likeNum);
}
}
);
}
else {
// 좋아요 삭제
database.LikeUpmentModel.findOneAndRemove(conditions, function (err) {
if (err) {
callback(err, null, null, null);
return;
}
callback(null, true, isAdd, likeNum);
}
);
}
}
});
});
} else {
var conditions = {
"post_id": paramPostId,
"downment_id": objectID,
"user_id": userID
};
// 해당 게시글 정보 반환
getUserLike(database, type, objectID, userID, function (err, result) {
if (err) {
callback(err, null, null);
}
// 좋아요 돼있으면 좋아요 해제, 안돼있으면 좋아요 설정
if (!result) {
isAdd = true;
} else {
isAdd = false;
}
// 좋아요 개수 조작
updateLikeCount(database, isAdd, type, objectID, function (err, result) {
if (err) {
callback(err, null, null, null);
}
if (!result) {
// 게시글이 삭제된 경우
callback(null, false, null, null);
} else {
var likeNum = result.count.like_count;
if (isAdd) {
// 좋아요 추가
database.LikeDownmentModel.create(conditions, function (err, res) {
if (err) {
callback(err, null, null, null);
return;
}
if (!res) {
callback("likePost 데이터 생성 오류", null);
} else {
callback(null, true, isAdd, likeNum);
}
}
);
}
else {
// 좋아요 삭제
database.LikeDownmentModel.findOneAndRemove(conditions, function (err) {
if (err) {
callback(err, null, null, null);
return;
}
callback(null, true, isAdd, likeNum);
}
);
}
}
});
});
}
}
ㄴ setLike 함수 모습
// 해당 유저의 좋아요/북마크 여부 반환
var getUserLike = function (database, type, objectID, userID, callback) {
if (type == TYPE.Post) {
var conditions = {
"post_id": objectID,
"user_id": userID
};
database.LikePostModel.findOne(conditions, function (err, result) {
if (err) {
callback(err, null);
}
if (!result) {
callback(null, false);
}
else {
callback(null, true);
}
}
);
} else if (type == TYPE.Upment) {
var conditions = {
"upment_id": objectID,
"user_id": userID
};
database.LikeUpmentModel.findOne(conditions, function (err, result) {
if (err) {
callback(err, null);
}
if (!result) {
callback(null, false);
}
else {
callback(null, true);
}
}
);
} else {
var conditions = {
"downment_id": objectID,
"user_id": userID
};
database.LikeDownmentModel.findOne(conditions, function (err, result) {
if (err) {
callback(err, null);
}
if (!result) {
callback(null, false);
}
else {
callback(null, true);
}
}
);
}
}
ㄴ getUserLike 함수 모습
// 게시글/댓글/대댓글 count 값 수정
var updateLikeCount = function (database, isAdd, type, ID, callback) {
// UserModel을 이용해 업데이트
var conditions = {
"_id": ID
};
var data;
// 좋아요 추가 like_count + 1
if (isAdd) {
data = {
$inc: {
"count.like_count": 1
}
}
}
// 좋아요 추가 like_count - 1
else {
data = {
$inc: {
"count.like_count": -1
}
}
}
var options = {
new: true,
runValidators: true
}
// 게시글의 경우
if (type == TYPE.Post) {
database.PostModel.findOneAndUpdate(conditions, data, options, function (err, result) {
if (err) {
callback(err, null);
return;
}
callback(null, result);
});
}
// 댓글의 경우
else if (type == TYPE.Upment) {
database.UpmentModel.findOneAndUpdate(conditions, data, options, function (err, result) {
if (err) {
callback(err, null);
return;
}
callback(null, result);
});
}
// 대댓글의 경우
else {
database.DownmentModel.findOneAndUpdate(conditions, data, options, function (err, result) {
if (err) {
callback(err, null);
return;
}
callback(null, result);
});
}
}
ㄴ updateLikeCount 함수 모습
* Router 상세 정보 *
GET /flipLike/:mode/:objectId/:postId
* 게시글/댓글/대댓글 좋아요 상태 변경
>> 필요 파라미터 (링크 뒤에 붙여서 보내주세요!) <<
{
mode : "post" or "upment" or "downment" (String)
objectId : 해당 게시글/댓글/대댓글의 ObjectId (String)
postId : "upment" or "downment"에 한해 소속 게시글의 ObjectId (String)
ㄴ 게시글 경우에는 "0"으로 보내주시면 되세요!
}
> 에러 발생 시
{
isLike: false (boolean),
errorMsg: 에러 메세지 (String)
}
> 정상 작동 시
{
isLike: true (boolean),
status: 결과적으로 좋아요 상태가 어떻게 된건지 (boolean),
likeNum: 현재 좋아요 총 수 (int)
}
ㄴ 프론트(Flutter)를 위한 라우터 상세 정보 입니다.
'띡딱똑띡 개발자 Hanna' 카테고리의 다른 글
NodeJS와 MongoDB로 SNS 만들어보기 - user_clip (게시글 북마크 기능 라우터) (0) | 2019.11.16 |
---|---|
NodeJS와 MongoDB로 SNS 만들어보기 - user_ment (댓글/대댓글 라우터) (0) | 2019.11.15 |
NodeJS와 MongoDB로 SNS 만들어보기 - user_postingPlus (게시글 라우터2) (0) | 2019.11.14 |
NodeJS와 MongoDB로 SNS 만들어보기 - user_posting (게시글 라우터) (0) | 2019.11.14 |
NodeJS와 MongoDB로 SNS 만들어보기 - user_follow (팔로우 라우터) (0) | 2019.11.14 |
댓글