Skip to content

좋아요 #10

@Ji-eun1

Description

@Ji-eun1

😎   결과

2022-09-02.3.47.19.mov


💭   내 생각

좋아요를 구현하는 것은 생각보다 어려웠다.
처음에는 forum, comment 모델 안에 heart 필드를 넣어두었는데,

결국은 하트를 모델로 따로 분리하고
forum, comment 에서 aggregate > $lookup 으로 하트를 조인하는 것으로 변경했다.

왜냐하면 이게 훨씬 더 깔끔해 보였기 때문이다.



🔑   작업과정

백엔드

1. heart model


하트모델은 유저 ObjectId, 게시물 ObjectId, 댓글 ObjectId 필드로 구성하였다.

const heartSchema = new Schema({
    _user: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User',
        required: true
    },
    _forum: {
        type: mongoose.Schema.Types.ObjectId, 
        ref: 'Forum'
    },
    _comment: {
        type: mongoose.Schema.Types.ObjectId, 
        ref: 'Comment'
    },
})

2. heart controller


하트는 update, delete controller 만 만들었다.

updateHeart
=> 유저가 하트를 클릭할 때 작동한다.

  1. 하트가 있을 경우 => 타겟 하트 db 삭제, fixHeartCount: -1, heartFill: false 응답
  2. 하트가 없을 경우 => 타겟 하트 db 생성, fixHeartCount: +1, heartFill: true 응답

deleteHearts
=> 유저가 게시물이나 댓글을 삭제할 경우 작동한다.

  1. 게시물을 삭제할 경우 => 타겟 게시물 id를 가진 하트 db 모두 삭제
  2. 댓글을 삭제할 경우 => 타겟 댓글 id 가진 하트 db 모두 삭제
const updateHeart = async (req, res) => {
    const _user = req.user.id; 
    const _comment = ( req.body._comment ? req.body._comment : null );
    const _forum = req.body._forum; // forum id 반드시 필요
    const data = { _user, _comment, _forum };

    try{
        const heart = await Heart.findOne({ 
            $and: [ 
                { _user: _user }, { _comment: _comment }, { _forum: _forum }
            ] 
        })
     
        if(heart) {
            await heart.delete()
            res.status(200).json({
                fixHeartCount: -1,
                heartFill: false,
                msg: 'heart -1'
            })
        } else{
            const newHeart = new Heart(data);
            await newHeart.save()
            res.status(200).json({
                fixHeartCount: +1,
                heartFill: true,
                msg: 'heart +1'
            })
        }
    } catch (err) {
        console.log(err)
        res.status(400).json(err)
    }
}

const deleteHearts = async (req, res, next) => {
    const _comment = ( req._comment ? req._comment : null );
    const _forum = ( req._forum ? req._forum : null );

    try{
        await Heart.deleteMany(( _comment ? { _comment: _comment } : { _forum: _forum } ))
        if(_comment === null) {
            next();
        } else {
            res.status(200).json('Comment, Hearts deleted')
        }
    } catch (err) {
        console.log(err)
        res.status(400).json({
            error: true,
            msg: 'Server Error'
        })
    }
}

3. heart router


heart delete controller 는 forum delete / comment delete controllers 에서 next() 로 연결하였다.

router.post('/update', auth, updateHeart);

프론트

1. updateHeart


forumList, commentList, forumView
=> 타겟 인덱스를 찾아 heartCount, heartFill 만 수정하여 바로 업데이트한다.

// 예시 forumList.tsx
const updateHeart = async (e: BtnMouseEventType, forumId: Types['forumId']) => {  
    e.preventDefault();

    const body = {
        _forum: forumId,
    }

    Hearts.postHeart(body)
    .then((data) => {
        let newForums = [...forums];
        const findIndex = forums.findIndex(el => el.forumId == forumId);
        const newHeartCount = forums[findIndex].heartCount + data.fixHeartCount;
        const newHeartFill = data.heartFill;

        if(findIndex !== -1) {
            newForums[findIndex] = {
                ...newForums[findIndex], 
                heartCount: newHeartCount, 
                heartFill: newHeartFill
            };
            
            if(selectValue === 'whatILike'){
                newForums = newForums.filter(forum => forum.heartFill === true);
            } else if(selectValue === 'heartOrder') {
                newForums = newForums.sort((a, b) => b.heartCount - a.heartCount)
            } 

            setForums(newForums)
        }
    })
    .catch((err) => {
        console.log(err);
    })
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions