Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat[#56] : QnA 게시글 좋아요, 좋아요 취소 기능 생성 #80

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from

Conversation

GoonManDoo
Copy link
Contributor

@GoonManDoo GoonManDoo commented Mar 13, 2024

이슈 연결

구현한 API

  • [좋아요] : /api/v1/likes
  • [좋아요 취소] : /api/v1/likes/{id}

작업 사항

  • QnA 좋아요 등록
  • QnA 게시글 좋아요가 존재할 시 좋아요 취소

[24. 03. 22 수정]

  • 좋아요, 좋아요 취소 분리
  • LikesRequestDto : qna 객체 -> qna_id로 수정
  • 좋아요, 취소 시 현재 로그인 되어 있는 사용자 ID를 자동으로 가져오게 수정
  • LikesResponseDto 삭제 [미사용]
  • 기타 타입 수정

[24. 08. 05 수정]

  • 좋아요 반환값 수정
  • 좋아요 로직 순서 변경
  • BusinessException으로 에러 처리 커스텀 후 적용

리뷰 요청 사항

  • 늦어서 죄송합니다..

@JaeyoungChoi98 JaeyoungChoi98 added the Feat 새로운 기능 추가 label Mar 14, 2024
Copy link
Contributor

@JaeyoungChoi98 JaeyoungChoi98 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다!

private final LikesService likesService;

@PostMapping("/{id}")
public ResponseEntity<?> likesQna(@PathVariable Long id, @RequestBody LikesRequestDto likesRequestDto) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사전에 request만 사용하면 이상한거 같다고 하셨는데 그래서 PathVariable를 추가해서 받고 계신건가요? Service에 넘어가도 PathVariable로 받아온 id는 사용되지가 않아서 무슨 id인지 잘 모르겠습니다! 아니면 놓친걸 수 도;;

또한 LikesRequestDto에 Qna랑 Member를 받아오시더라구요! 그래서 저 id의 정체가 더욱 궁금합니다!


ResponseEntity<?>로 반환하시는데 ?로 하신 이유가 있나요? Service 보니까 Likes가 반환되는거 같더라구요! 그렇다면 LikesResponseDto가 사용되는 곳은 어디인가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 좋아요, 좋아요 취소를 한 로직에서 만들다보니 있어야 할 거 같아서 만들었는데 이제와서 보니 좋아요와 취소를 따로 분리해서 만들어야 될 거 같아서 뜯어고칠 예정입니다 !
  2. LikesResponseDto는 처음에 만들었다가 등록, 삭제밖에 없어서 사용을 안했습니다 ! 삭제한다는게 까먹고 그냥 커밋을 했습니다 !


@Entity
@Getter
@Setter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

객체의 값을 업데이트하는 함수가 없는거 같은데 @Setter을 사용하신 이유가 있나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Setter도 기본 틀을 복붙하다가 같이 딸려온 거 같습니다 ! 수정 예정입니다 !

public class LikesRequestDto {

private Qna qna;
private Member member;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request 변수를 Long 타입의 id를 받아오는게 아니라 Entity 형식으로 받으면 어떻게 동작하나요? 프론트에서 Qna 객체를 넘겨줘야 하나요? 아니면 id값을 보내줘야 하나요?


member같은 경우는 현재 이 요청을 보낸 사용자의 정보를 가져올 수 있는 방법이 있습니다! 저희는 로그인하여 앱을 사용하기 때문에 사용자 정보를 가지고 있어요! springboot Security와 연관지어서 로그인한 사용자 정보 가져오는 방법을 찾아보시는게 좋을거 같아요! 아니면 이미 저희 프로젝에서 사용중이기 때문에 club이나 다른곳에서 회원 id를 가져오는 로직을 참고하셔도 좋을거 같아요!

왜냐하면 지금 로그인된 사용자가 객체를 생성할때 필요하기 때문에 서버쪽에서 알 수 있어서 Request 값으로 받지 않기 때문이에요! 저는 그렇게 생각하고 있습니다 :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 재영님 말씀하신 것처럼 이런 방법이 있을 것 같았는데 몰라서 그냥 했는데 재영님이 말씀해주신 방법으로 해보겠습니다 !

private String nickName;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "Asia/Seoul")
private Instant createAt;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 데이터들이 사용되는 페이지가 어디인지 알려주실 수 있나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위에서 답변한 것처럼 LikesResponseDto는 처음에 만들었다가 등록, 삭제밖에 없어서 사용을 안했습니다 ! 삭제한다는게 까먹고 그냥 커밋을 했습니다 !




public Object likesQna(Long id, LikesRequestDto likesRequestDto) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋아요하는것과 취소하는 동작을 하나로 합치신 이유가 있을까요?


반환값이 Object인데 반환하는 타입이 여러가지 인가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. 좋아요와 좋아요 취소를 하나로 만드는게 더 효율적이라고 생각해서 만들었는데 생각해보니 분리하는게 더 나아보여서 분리할 예정입니다 !
  2. ResponseEntity<?>을 사용하면 Object로만 반환할 수 있다고 본 거 같았는데 수정하면서 한번 더 찾아보겠습니다 !

Likes likes = likesRepository.findByMemberIdAndQnaId(member.getId(), qna.getId())
.orElseThrow(() -> new IllegalArgumentException("좋아요가 없습니다 !"));
likesRepository.delete(likes);
return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋아요랑 좋아요 취소를 하나의 함수로 반환하는 걸로 보입니다.
이 때문에 null을 반환하는 걸로 보이는데, null 반환은 널 포인터 에러 때문에 가급적 피하는게 좋다고 생각합니다.
그래서 함수를 좋아요, 좋아요 취소로 나누는게 어떠신가요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

재원님 말씀처럼 좋아요, 좋아요 취소로 나눌 예정입니다 !

Copy link
Contributor

@JaeyoungChoi98 JaeyoungChoi98 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다!

private final LikesRepository likesRepository;


public Object addLikesQna(LikesRequestDto likesRequestDto, Long memberId) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반환값이 Object이네요? 로직상 반환값은 하나로 처리되는거 같아요! 반환값이 여러개가 아니라면 Fix 시키는게 안전할거 같습니다! 가독성도 좋구용

.orElseThrow(() -> new IllegalArgumentException("회원이 없습니다 ! : " + memberId));

// 이미 사용자가 해당 게시글에 좋아요를 눌렀는지 확인
boolean alreadyLikes = likesRepository.existsByMemberIdAndQnaId(memberId, qna.getId());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 저라면 먼저 좋아요 여부를 검사할거 같아요! request로 qnaId값은 가지고 있으니까 member만 먼저 조회해서 없으면 에러를 던지는식으로요

기존에 순서가

  1. qna 불러오기
  2. member 불러오기
  3. 좋아요 여부 확인
  4. if문으로 좋아요 상태에 따른 반환값 처리

이렇게 된다면 순서를 뒤집어서 좋아요 여부를 먼저 처리하면

  1. 좋아요 여부에 따른 에러 처리 -> 여기서 실패한다면 2,3,4 로직 처리를 안해도됨!
  2. qna 불러오기
  3. member 불러오기
  4. 저장 및 반환

요런식의 차이로 인해서 의견을 드렸습니다~


/* 사용자 조회 */
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new IllegalArgumentException("회원이 없습니다 ! : " + memberId));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

에러 처리가 IllegalArgumentException 사용하셨는데 저희 BusinessException으로 커스텀해서 사용하고 있어서 이번기회에 사용해보셔도 좋을거 같아요!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feat 새로운 기능 추가
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants