Coding History

국비 지원 IT(웹앱개발) 취업반 강의 54일차 (Spring)

BlackBirdIT 2024. 8. 23. 00:00

어제 새로운 DB 테이블을 생성하고 끝났다.

하루종일 개인프로젝트에 대한 상담을 했고, 내 계획은 따로 텝을 생성해서 포스팅해두었다.

여하튼 좋아요 기능을 이제 DB와 연동시켜서 데이터를 남겨야하는데 이걸 만들어보자.

@Service
public class ReactionPointService {
    @Autowired
    private ReactionPointRepository reactionPointRepository;

    public List<ReactionPoint> getReactionPoints(String relTypeCode, int relId) {
        return reactionPointRepository.getReactionPoints(relTypeCode, relId);
    }

    public int getTotalReactionPoints(String relTypeCode, int relId) {
        return reactionPointRepository.getTotalReactionPoints(relTypeCode, relId);
    }
}
@Mapper
public interface ReactionPointRepository {

    @Select("SELECT * FROM reactionPoint WHERE relTypeCode = #{relTypeCode} AND relId = #{relId}")
    List<ReactionPoint> getReactionPoints(String relTypeCode, int relId);

    @Select("SELECT SUM(point) FROM reactionPoint WHERE relTypeCode = #{relTypeCode} AND relId = #{relId}")
    int getTotalReactionPoints(String relTypeCode, int relId);

}

일단은 서버와 리포지트리를 생성했고

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ReactionPoint {

    private int id;
    private String regDate;
    private String updateDate;
    private int memberId;
    private String relTypeCode;
    private int relId;
    private int point;
}

매핑할 수 있는 객체를 생성했다.

    @Autowired
    private ReactionPointService reactionPointService;

    @RequestMapping("/usr/article/detail")
    public String showDetail( Model model, int id) {

        Article article = articleService.getForPrintArticle(rq.getLoginedMemberId(), id);

        model.addAttribute("article", article);

        int likeCount = reactionPointService.getTotalReactionPoints("article", id);
        model.addAttribute("likeCount", likeCount);

        return "usr/article/detail";
    }

이후 JSP로 전달 가능하게 article Controller에서 detail 부분에 데이터를 추가해줬다.

여기까지는 했는데 JSP는 항상 헷갈린다. 기존에 만들어둔 JS 코드, 그러니까 좋아요 기능을 로컬스토리지로 상태 저장을 했었는데 이걸 버려야될지 뭔가 조금만 수정하면 될지 잘 모르겠다.

그렇게 생각하다보니까 좋아요를 조회수 처럼 메서드를 따로 분리해서 관리하는게 편할 것 같다. doReaction으로 메서드를 만들고 ReactionPointRepository에 select만 넣을게 아니라 update로 좋아요를 업데이트 하고, delete로 싫어요를 적용하면 되지 않을까 머리로 일단 구상을 해봤다.

그리고 좀 우여곡절 끝에 일단 코드를 이렇게 썼다.

    @RequestMapping("/article/doReaction")
    @ResponseBody
    public Map<String, Object> doReaction(HttpServletRequest req ,@RequestParam int id, @RequestParam String relTypeCode, @RequestParam int relId) {
        Rq rq = (Rq) req.getAttribute("rq");

        int resultPoint = reactionPointService.toggleReactionPoint(rq.getLoginedMemberId(), relTypeCode, relId);

        Map<String, Object> response = new HashMap<>();
        response.put("status", resultPoint > 0 ? "liked" : "unliked");
        return response;
    }

우선 로그인 상태인 유저가 좋아요와 싫어요 기능을 이용할 것이라고 생각해서 HttpServletRequest로 rq.getLoginedMemberId()이렇게 memberId를 가져왔다. 일단 짜 놓은 SQL을 계속 비교하면서 내가 뭘 가져와야지 제대로 작동할지 생각하면서 코드를 쓰니까 비교적 해결 자체는 잘 했다. 물론 아직 시험해보지는 않아서 제대로 써 놓은건지는 모르겠는데 일단 오류는 없으니까..

@Service
public class ReactionPointService {
    @Autowired
    private ReactionPointRepository reactionPointRepository;

    public int toggleReactionPoint(int memberId, String relTypeCode, int relId) {
        ReactionPoint reactionPoint = reactionPointRepository.getReactionPointByMemberIdAndRelId(memberId, relTypeCode,
                relId);

        if (reactionPoint != null) {
            reactionPointRepository.deleteReactionPoint(memberId, relTypeCode, relId);
            return -1; // 기존 좋아요 또는 싫어요를 취소함
        } else {
            reactionPointRepository.insertReactionPoint(memberId, relTypeCode, relId, 1);
            return 1; // 새로 좋아요를 누름
        }
    }

    public int getTotalReactionPoints(String relTypeCode, int relId) {
        Integer totalPoints = reactionPointRepository.getTotalReactionPoints(relTypeCode, relId);
        return totalPoints != null ? totalPoints : 0;
    }
}

ReactionPointService는 이렇게 업데이트를 했다.

그리고 쿼리문은 이렇게.

@Mapper
public interface ReactionPointRepository {

    @Select("SELECT * FROM reactionPoint WHERE memberId = #{memberId} AND relTypeCode = #{relTypeCode} AND relId = #{relId}")
    ReactionPoint getReactionPointByMemberIdAndRelId(int memberId, String relTypeCode, int relId);

    @Insert("INSERT INTO reactionPoint (regDate, updateDate, memberId, relTypeCode, relId, point) VALUES (NOW(), NOW(), #{memberId}, #{relTypeCode}, #{relId}, #{point})")
    void insertReactionPoint(int memberId, String relTypeCode, int relId, int point);

    @Delete("DELETE FROM reactionPoint WHERE memberId = #{memberId} AND relTypeCode = #{relTypeCode} AND relId = #{relId}")
    void deleteReactionPoint(int memberId, String relTypeCode, int relId);

    @Select("SELECT SUM(point) FROM reactionPoint WHERE relTypeCode = #{relTypeCode} AND relId = #{relId}")
    Integer getTotalReactionPoints(String relTypeCode, int relId);
}

일단 만들어 놓긴했고 JSP만 손보면 되는데 오늘 개인프로젝트 때문에 머리를 많이(?) 써서 더는 못하겠다..

내일 강사님 풀이를 보면서 수정이 필요한 부분을 고쳐야겠다.