Skip to content

Conversation

@Gyuhyeok99
Copy link
Contributor

관련 이슈

작업 내용

소식지 좋아요 관련 기능을 추가했습니다!
기존 대학 지원 정보 좋아요 관련 기능을 최대한 참고하며 진행했습니다!

상태확인, 좋아요, 좋아요 취소에 대해 무얼 응답하면 좋을지에 대해 아직 확정이 나지 않아 우선은 모두 id와 좋아요중인지를 응답하는 방식으로 통일해두었습니다!
(사실 전 지금 방식도 괜찮은 거 같긴 한데 의견 남겨주시면 좋을 거 같습니다!)

특이 사항

소식지가 존재하지 않는 경우에 대해서는 따로 테스트 코드를 작성하지 않았습니다!

리뷰 요구사항 (선택)

1. 불필요한 find는 좋지 않다고 알고 있기에 기존 대학 지원 정보와 달리 JPA의 exist를 활용했는데 괜찮은가요?

2. 좋아요 상태 확인 함수명

getNewsLikeStatus로 일단 해두긴 했는데 뭐가 적절한지 모르겠네요 기존 대학 지원 정보에서는 getIsLiked로 되어있었긴 합니다!

@coderabbitai
Copy link

coderabbitai bot commented Jul 7, 2025

Walkthrough

  1. 새로운 에러 코드 추가
     - ErrorCode enum에 뉴스 좋아요 관련 에러 코드인 ALREADY_LIKED_NEWSNOT_LIKED_NEWS가 HTTP 400 상태 코드와 함께 추가되었습니다.

  2. 뉴스 좋아요 API 엔드포인트 3종 추가
     - NewsController에 GET, POST, DELETE 방식의 /news/{news-id}/like 엔드포인트가 신설되어, 뉴스 좋아요 상태 조회, 좋아요 추가, 좋아요 취소 기능이 각각 구현되었습니다.

  3. LikedNews 도메인에 생성자 추가
     - LikedNews 클래스에 newsIdsiteUserId를 받는 public 생성자가 새로 추가되어 필드를 초기화합니다.

  4. LikedNewsResponse DTO 신규 도입
     - isLike라는 boolean 필드를 가진 LikedNewsResponse 레코드가 도입되었고, of라는 정적 팩토리 메서드가 제공됩니다.

  5. LikedNewsRepository 인터페이스 신설
     - LikedNews 엔티티를 위한 JpaRepository 기반 LikedNewsRepository가 추가되었으며, existsByNewsIdAndSiteUserIdfindByNewsIdAndSiteUserId 메서드를 제공합니다.

  6. NewsLikeService 서비스 클래스 신설
     - 뉴스 좋아요 상태 조회, 좋아요 추가, 좋아요 취소 기능을 담당하는 NewsLikeService가 구현되었고, 각 메서드는 상황에 맞는 CustomException을 던집니다.

  7. NewsLikeService 단위 테스트 추가
     - NewsLikeService의 주요 기능에 대해 정상 동작과 예외 상황을 검증하는 단위 테스트가 새롭게 작성되었습니다.

Suggested reviewers

  • wibaek
  • nayonsoso
  • whqtker

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a635ca3 and e70bdd8.

📒 Files selected for processing (1)
  • src/main/java/com/example/solidconnection/common/exception/ErrorCode.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/example/solidconnection/common/exception/ErrorCode.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/test/java/com/example/solidconnection/news/service/NewsLikeServiceTest.java (1)

23-126: 테스트 코드가 포괄적으로 잘 작성되었습니다

다음과 같은 장점들이 있습니다:

  1. 구조화된 테스트: 중첩 클래스로 기능별 테스트 그룹화
  2. 시나리오 완전성:
    • 좋아요 상태 조회 (좋아요O/좋아요X)
    • 좋아요 등록 (성공/이미 좋아요한 경우)
    • 좋아요 취소 (성공/좋아요하지 않은 경우)
  3. 예외 처리 확인: 커스텀 예외와 에러 메시지 검증
  4. 데이터베이스 상태 검증: 실제 저장/삭제 확인

PR 목표에서 언급하신 "존재하지 않는 소식지" 테스트 케이스 추가를 고려해 보시기 바랍니다.

추가 고려사항:

@Test
void 존재하지_않는_소식지에_좋아요_시도시_예외_발생() {
    // given
    long nonExistentNewsId = 999L;
    
    // when & then
    assertThatCode(() -> newsLikeService.addNewsLike(user.getId(), nonExistentNewsId))
        .isInstanceOf(CustomException.class)
        .hasMessage(NEWS_NOT_FOUND.getMessage());
}
src/main/java/com/example/solidconnection/news/service/NewsLikeService.java (1)

1-55: 전체적으로 견고한 서비스 구현이지만 테스트 케이스 추가를 고려해보세요!

현재 구현이 매우 잘 되어 있지만, PR에서 언급한 대로 추가 테스트 케이스를 고려해볼 수 있습니다:

  1. 현재 잘 구현된 부분:

    • 트랜잭션 경계 설정
    • 예외 처리
    • 비즈니스 로직 검증
  2. 고려해볼 추가 테스트:

    • 존재하지 않는 뉴스에 대한 각 메서드 호출
    • 동시성 상황에서의 중복 좋아요 처리

존재하지 않는 뉴스에 대한 테스트 케이스를 추가로 작성해드릴까요?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fe7aefc and 5e57fc6.

📒 Files selected for processing (7)
  • src/main/java/com/example/solidconnection/common/exception/ErrorCode.java (1 hunks)
  • src/main/java/com/example/solidconnection/news/controller/NewsController.java (3 hunks)
  • src/main/java/com/example/solidconnection/news/domain/LikedNews.java (1 hunks)
  • src/main/java/com/example/solidconnection/news/dto/LikedNewsResponse.java (1 hunks)
  • src/main/java/com/example/solidconnection/news/repository/LikedNewsRepository.java (1 hunks)
  • src/main/java/com/example/solidconnection/news/service/NewsLikeService.java (1 hunks)
  • src/test/java/com/example/solidconnection/news/service/NewsLikeServiceTest.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (10)
src/main/java/com/example/solidconnection/news/domain/LikedNews.java (1)

37-40: 생성자 중복 문제 확인이 필요합니다

@AllArgsConstructor가 이미 모든 필드를 포함하는 생성자를 생성하므로, 추가로 정의한 생성자와 중복될 수 있습니다.

다음 중 하나를 선택하여 수정하는 것을 권장합니다:

  1. @AllArgsConstructor 제거 후 필요한 생성자만 직접 정의
  2. 현재 추가한 생성자 제거 후 @AllArgsConstructor 사용
-@AllArgsConstructor
 @NoArgsConstructor(access = AccessLevel.PROTECTED)
 @Table(uniqueConstraints = {
         @UniqueConstraint(
                 name = "uk_liked_news_site_user_id_news_id",
                 columnNames = {"site_user_id", "news_id"}
         )
 })
 public class LikedNews {
     // ... 기존 필드들 ...
     
     public LikedNews(long newsId, long siteUserId) {
         this.newsId = newsId;
         this.siteUserId = siteUserId;
     }
+
+    public LikedNews(Long id, long newsId, long siteUserId) {
+        this.id = id;
+        this.newsId = newsId;
+        this.siteUserId = siteUserId;
+    }
 }

Likely an incorrect or invalid review comment.

src/main/java/com/example/solidconnection/common/exception/ErrorCode.java (1)

102-103: 에러 코드 추가가 적절합니다

기존 대학 지원 정보 좋아요 기능의 에러 코드(ALREADY_LIKED_UNIV_APPLY_INFO, NOT_LIKED_UNIV_APPLY_INFO)와 일관성을 유지하여 추가되었습니다. 메시지도 명확하고 HTTP 상태 코드도 적절합니다.

src/main/java/com/example/solidconnection/news/dto/LikedNewsResponse.java (1)

3-11: DTO 구조가 깔끔합니다

  1. 레코드 클래스 사용으로 불변성 보장
  2. 정적 팩토리 메서드 제공으로 생성 방식 통일
  3. 필드명이 명확하고 직관적

PR 목표에서 언급하신 대로 응답 구조가 적절한지 확인해 보시기 바랍니다. 현재 구조는 ID와 좋아요 상태를 포함하고 있어 충분해 보입니다.

src/main/java/com/example/solidconnection/news/repository/LikedNewsRepository.java (1)

8-13: 리포지토리 구조가 최적화되어 있습니다

PR 목표에서 언급하신 대로 JPA의 exists 메서드를 활용하여 성능을 최적화했습니다:

  1. existsByNewsIdAndSiteUserId - 불필요한 find 작업 없이 존재 여부만 확인
  2. findByNewsIdAndSiteUserId - 실제 엔티티가 필요한 경우에만 사용
  3. Spring Data JPA 네이밍 컨벤션을 정확히 따름

이는 기존 대학 지원 정보 좋아요 기능 대비 성능 개선된 접근 방식입니다.

src/main/java/com/example/solidconnection/news/controller/NewsController.java (4)

4-4: 의존성 주입이 깔끔하게 구현되었습니다!

새로운 좋아요 기능을 위한 의존성들이 적절히 추가되었습니다:

  1. LikedNewsResponse DTO 임포트
  2. NewsLikeService 서비스 임포트 및 주입

기존 패턴과 일관성을 유지하면서 깔끔하게 구현되었네요.

Also applies to: 10-10, 36-36


84-91: 좋아요 상태 조회 엔드포인트가 잘 구현되었습니다!

좋아요 상태를 조회하는 GET 엔드포인트가 다음과 같이 적절히 구현되었습니다:

  1. 적절한 HTTP 메서드 사용 (GET)
  2. 인증된 사용자 정보 활용
  3. 서비스 레이어로의 적절한 위임

기존 컨트롤러 패턴과 일관성을 유지하고 있어 좋습니다.


93-100: 좋아요 추가 엔드포인트가 적절히 구현되었습니다!

좋아요를 추가하는 POST 엔드포인트가 다음과 같이 잘 구현되었습니다:

  1. 적절한 HTTP 메서드 사용 (POST)
  2. 인증된 사용자 정보 활용
  3. 서비스 레이어로의 적절한 위임

RESTful 원칙을 잘 따르고 있습니다.


102-109: 좋아요 취소 엔드포인트가 적절히 구현되었습니다!

좋아요를 취소하는 DELETE 엔드포인트가 다음과 같이 잘 구현되었습니다:

  1. 적절한 HTTP 메서드 사용 (DELETE)
  2. 인증된 사용자 정보 활용
  3. 서비스 레이어로의 적절한 위임

전체적으로 RESTful API 설계 원칙을 잘 따르고 있습니다.

src/main/java/com/example/solidconnection/news/service/NewsLikeService.java (2)

1-22: 서비스 클래스 구조가 깔끔하게 설계되었습니다!

새로운 NewsLikeService 클래스가 다음과 같이 잘 구현되었습니다:

  1. 적절한 패키지 구조 및 임포트
  2. 의존성 주입을 위한 @RequiredArgsConstructor 사용
  3. 서비스 레이어 표시를 위한 @Service 어노테이션
  4. 필요한 리포지토리들의 명확한 주입

전체적으로 Spring의 모범 사례를 잘 따르고 있습니다.


23-30: 좋아요 상태 조회 메서드가 효율적으로 구현되었습니다!

좋아요 상태를 조회하는 메서드가 다음과 같이 적절히 구현되었습니다:

  1. @Transactional(readOnly = true) 적용으로 읽기 전용 트랜잭션 최적화
  2. PR에서 언급한 대로 existsById() 사용으로 효율적인 존재 확인
  3. 적절한 예외 처리 및 응답 생성

find 대신 exists 메서드를 사용한 것은 성능상 좋은 선택입니다.

Copy link
Collaborator

@nayonsoso nayonsoso left a comment

Choose a reason for hiding this comment

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

깔끔하게 잘 구현하셨네요! 😊
회의에서 나왔던 응답 형식(200, OK)만 반영하시고, 멘션 주세요!
수고하셨습니다~ 🎉🎉

Copy link
Member

@whqtker whqtker left a comment

Choose a reason for hiding this comment

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

고생 많으셨습니다 ~!

  1. 저도 존재 여부 파악이 목적이라면 find 보다 exists 가 성능 상 유리하다고 알고 있습니다.
  2. 추후 대학 지원 좋아요 여부 확인 함수명을 '대학 지원 정보' 라는 정보가 들어가게끔 수정하면 좋을 거 같습니다 !

현재 post 엔티티에는 post_like 필드가 있어 필드 값으로 바로 게시글 좋아요 개수를 알 수 있습니다. news 엔티티에도 news_like 필드가 있으면 좋을 거 같습니다. 흠 ..... 근데 이 PR에 적절한 내용인지는 고민되네요.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/main/java/com/example/solidconnection/news/dto/LikedNewsResponse.java (1)

3-5: 필드명 개선을 위한 제안

  1. 문법적 정확성: isLike 보다는 isLiked가 더 자연스러운 영어 표현입니다.
    • 현재: "좋아요인가?" 보다는 "좋아요를 했는가?"가 더 적절합니다.

다음과 같이 수정하는 것을 제안합니다:

public record LikedNewsResponse(
-        boolean isLike
+        boolean isLiked
) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5e57fc6 and 6e1aa83.

📒 Files selected for processing (4)
  • src/main/java/com/example/solidconnection/news/controller/NewsController.java (3 hunks)
  • src/main/java/com/example/solidconnection/news/dto/LikedNewsResponse.java (1 hunks)
  • src/main/java/com/example/solidconnection/news/service/NewsLikeService.java (1 hunks)
  • src/test/java/com/example/solidconnection/news/service/NewsLikeServiceTest.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/test/java/com/example/solidconnection/news/service/NewsLikeServiceTest.java
  • src/main/java/com/example/solidconnection/news/service/NewsLikeService.java
  • src/main/java/com/example/solidconnection/news/controller/NewsController.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (1)
src/main/java/com/example/solidconnection/news/dto/LikedNewsResponse.java (1)

7-9: 팩토리 메서드 구현 확인

  1. 일관성 유지: 다른 DTO와의 일관성을 위해 팩토리 메서드를 제공하는 것은 좋은 접근입니다.

    • 향후 확장성이나 추가 로직이 필요할 때 유용할 수 있습니다.
  2. 단순성: 현재는 단순한 생성자 호출이지만, 코드의 일관성 측면에서 적절합니다.

팩토리 메서드명도 필드명과 일치하도록 수정하는 것을 고려해보세요:

-    public static LikedNewsResponse of(boolean isLike) {
-        return new LikedNewsResponse(isLike);
+    public static LikedNewsResponse of(boolean isLiked) {
+        return new LikedNewsResponse(isLiked);

@Gyuhyeok99
Copy link
Contributor Author

Gyuhyeok99 commented Jul 8, 2025

현재 post 엔티티에는 post_like 필드가 있어 필드 값으로 바로 게시글 좋아요 개수를 알 수 있습니다. news 엔티티에도 news_like 필드가 있으면 좋을 거 같습니다. 흠 ..... 근데 이 PR에 적절한 내용인지는 고민되네요.

저는 소식지의 경우에는 post보다는 대학지원정보와 더 비슷하다고 생각하여 구현하지 않았습니다! 혹시 기획에서 필요하다고 하면 다른 pr에서 작업하겠습니다!

추후 대학 지원 좋아요 여부 확인 함수명을 '대학 지원 정보' 라는 정보가 들어가게끔 수정하면 좋을 거 같습니다 !

좋습니다~~

Copy link
Collaborator

@nayonsoso nayonsoso left a comment

Choose a reason for hiding this comment

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

  1. 불필요한 find는 좋지 않다고 알고 있기에 기존 대학 지원 정보와 달리 JPA의 exist를 활용했는데 괜찮은가요?

좋습니다~ 👍

  1. 좋아요 상태 확인 함수명

status 는 전체 프로젝트 맥락 상(?) enum 으로 관리되는 무언가를 연상시키는 것 같습니다..!
예를 들어 verifyStatus / exchangeStatus 같은 것들이요.
그래소 boolean 응답임을 명시할 수 있는 isLiked가 포함되면 좋겠습니다.

(제가 그 함수 만든 사람이라 그렇게 생각하는걸수도 있어욧..)

Copy link
Member

@whqtker whqtker left a comment

Choose a reason for hiding this comment

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

코멘트 확인했습니다 ! 고생하셨어요

Copy link
Collaborator

@nayonsoso nayonsoso left a comment

Choose a reason for hiding this comment

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

너무 깔끔하게 구현하셔서.. 리뷰할게 많지 않았던 것 같아요☺️
수고하셨습니다!

Copy link
Contributor

@lsy1307 lsy1307 left a comment

Choose a reason for hiding this comment

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

수고하셨습니다! 의문점만 한 가지 있는데 답변해주시면 감사하겠습니다!!

@Gyuhyeok99 Gyuhyeok99 merged commit 163d0a3 into solid-connection:develop Jul 10, 2025
2 checks passed
@Gyuhyeok99 Gyuhyeok99 deleted the feat/376-liked-news-api branch July 10, 2025 07:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: 소식지 좋아요 기능 구현

4 participants