Skip to content

SISC-BE-게시물-좋아요-북마크#147

Merged
Kosw6 merged 15 commits intomainfrom
SIsC1-151-BE-게시판-추가
Nov 27, 2025

Hidden character warning

The head ref may contain hidden characters: "SIsC1-151-BE-\uac8c\uc2dc\ud310-\ucd94\uac00"
Merged

SISC-BE-게시물-좋아요-북마크#147
Kosw6 merged 15 commits intomainfrom
SIsC1-151-BE-게시판-추가

Conversation

@nayoung04
Copy link
Contributor

@nayoung04 nayoung04 commented Nov 27, 2025

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능
    • 게시물 목록 및 상세 조회에서 사용자의 "좋아요"와 "북마크" 상태 표시 추가
    • 사용자 인증 기반 개인화된 게시물 데이터 제공

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 27, 2025

Walkthrough

사용자 인증 정보를 기반으로 게시물 조회 메서드들에 userId 파라미터를 추가하고, PostResponse에 isLiked와 isBookmarked 필드를 도입하여 사용자별 게시물 상태(좋아요, 북마크) 추적 기능을 구현했습니다.

Changes

Cohort / File(s) 변경 요약
컨트롤러 인증 통합
backend/src/main/java/org/sejongisc/backend/board/controller/BoardController.java
5개 메서드(getPosts, searchPosts, getPostDetail, getParentBoards, getChildBoards)에 @AuthenticationPrincipal CustomUserDetails 파라미터 추가하고 userId를 서비스 호출에 전달하도록 수정
DTO 응답 필드 확장
backend/src/main/java/org/sejongisc/backend/board/dto/PostResponse.java
Boolean 타입의 isLiked와 isBookmarked 필드 2개 추가
서비스 계약 업데이트
backend/src/main/java/org/sejongisc/backend/board/service/PostService.java
getPosts, searchPosts, getPostDetail 메서드에 UUID userId 파라미터 추가, getChildBoards와 deleteBoard 메서드 선언 추가
서비스 구현 확장
backend/src/main/java/org/sejongisc/backend/board/service/PostServiceImpl.java
userId 파라미터를 받는 메서드들 구현 수정, user-aware post 매핑 로직(mapToPostResponse, getCommonPostBuilder) 추가로 PostLikeRepository와 PostBookmarkRepository를 이용한 사용자별 상태 조회
테스트 초기화 및 검증
backend/src/test/java/org/sejongisc/backend/attendance/service/AttendanceServiceTest.java, backend/src/test/java/org/sejongisc/backend/board/service/PostServiceImplTest.java
AttendanceServiceTest에 visibility(SessionVisibility.PUBLIC) 빌더 호출 추가, PostServiceImplTest에서 userId 기반 서비스 호출로 수정하고 isLiked/isBookmarked 검증 로직 추가

Sequence Diagram

sequenceDiagram
    participant Client
    participant BoardController
    participant PostService
    participant UserRepository
    participant PostRepository
    participant PostLikeRepository
    participant PostBookmarkRepository

    Client->>BoardController: getPosts(boardId, page, size) + auth
    BoardController->>BoardController: extract userId from `@AuthenticationPrincipal`
    BoardController->>PostService: getPosts(boardId, userId, page, size)
    PostService->>UserRepository: findById(userId)
    PostService->>PostRepository: findByBoardId(boardId, page)
    loop for each post
        PostService->>PostLikeRepository: existsByUserUserIdAndPostPostId(userId, postId)
        PostService->>PostBookmarkRepository: existsByUserUserIdAndPostPostId(userId, postId)
        PostService->>PostService: mapToPostResponse(post, user, isLiked, isBookmarked)
    end
    PostService-->>BoardController: Page<PostResponse>
    BoardController-->>Client: ResponseEntity<Page<PostResponse>>
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • PostServiceImpl의 user-aware 매핑 로직: mapToPostResponse와 getCommonPostBuilder 메서드에서 PostLikeRepository 및 PostBookmarkRepository와의 상호작용 검증 필요
  • 데이터베이스 쿼리 성능: 각 게시물에 대해 좋아요/북마크 존재 여부를 조회하는 로직으로 인한 N+1 쿼리 가능성 검토
  • 테스트 커버리지: PostServiceImplTest의 새로운 검증 로직(isLiked, isBookmarked 어설션)이 모든 테스트 케이스에 일관되게 적용되었는지 확인

Possibly related PRs

Suggested reviewers

  • discipline24

Poem

🐰 userId를 품은 posts는
좋아요와 북마크로 반짝이네
사용자 맥락 담아 응답하고
저장소는 정성스레 검색하니
이제 진정한 내 게시물이 되었네 🌟

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목 'SISC-BE-게시물-좋아요-북마크'는 변경 사항의 주요 내용인 게시물의 좋아요와 북마크 기능 추가를 명확하게 설명합니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch SIsC1-151-BE-게시판-추가

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

Comment @coderabbitai help to get the list of available commands and usage tips.

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: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
backend/src/main/java/org/sejongisc/backend/board/controller/BoardController.java (1)

158-179: 잘못된 주석 수정 필요

Line 158과 Line 170의 주석이 "게시판 생성"으로 되어 있지만, 실제로는 각각 부모 게시판 조회와 하위 게시판 조회 메서드입니다.

-  // 게시판 생성
+  // 부모 게시판 목록 조회
   @Operation(
       summary = "부모 게시판 목록 조회",
       ...


-  // 게시판 생성
+  // 하위 게시판 목록 조회
   @Operation(
           summary = "하위 게시판 목록 조회",
           ...
🧹 Nitpick comments (4)
backend/src/main/java/org/sejongisc/backend/board/service/PostServiceImpl.java (3)

195-195: 불필요한 return 문 제거

void 메서드의 마지막에 있는 return; 문은 불필요합니다.

     targetBoardIds.forEach(boardRepository::deleteById);
-    return;
   }

240-243: Fail-fast를 위해 사용자 조회 순서 변경 권장

게시물 조회 후 사용자를 조회하고 있어, 존재하지 않는 사용자의 경우 불필요한 게시물 조회가 발생합니다. getPosts 메서드(Line 212-214)와 동일하게 게시물 조회 전에 사용자를 먼저 조회하는 것이 일관성과 성능 면에서 좋습니다.

     // 게시판 조회
     Board board = boardRepository.findById(boardId)
         .orElseThrow(() -> new CustomException(ErrorCode.BOARD_NOT_FOUND));

+    // 유저 조회
+    User user = userRepository.findById(userId)
+        .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
+
     // 해당 키워드가 들어간 게시물 검색
     Page<Post> posts = postRepository.searchByBoardAndKeyword(
         board, keyword, pageable);

-    // 유저 조회
-    User user = userRepository.findById(userId)
-        .orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_FOUND));
-
     return posts.map(post -> mapToPostResponse(post, user));

338-345: @Override 어노테이션 누락

getChildBoards 메서드에 @Override 어노테이션이 누락되었습니다. 다른 인터페이스 구현 메서드들과 일관성을 위해 추가해 주세요.

   // 하위 게시판 조회
+  @Override
   @Transactional(readOnly = true)
   public List<BoardResponse> getChildBoards() {
backend/src/test/java/org/sejongisc/backend/board/service/PostServiceImplTest.java (1)

267-267: searchPosts 메서드에 대한 테스트 누락

getPostsgetPostDetail에 대한 테스트는 userId 매개변수와 isLiked/isBookmarked 검증이 추가되었지만, searchPosts 메서드에 대한 테스트가 없습니다. 동일한 사용자 컨텍스트 로직을 사용하므로 테스트 추가를 권장합니다.

searchPosts 테스트 코드를 생성해 드릴까요?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d3e7963 and 53b44f5.

📒 Files selected for processing (8)
  • backend/src/main/java/org/sejongisc/backend/board/controller/BoardController.java (3 hunks)
  • backend/src/main/java/org/sejongisc/backend/board/dto/PostResponse.java (1 hunks)
  • backend/src/main/java/org/sejongisc/backend/board/service/PostService.java (1 hunks)
  • backend/src/main/java/org/sejongisc/backend/board/service/PostServiceImpl.java (7 hunks)
  • backend/src/test/java/org/sejongisc/backend/attendance/service/AttendanceRoundServiceTest.java (0 hunks)
  • backend/src/test/java/org/sejongisc/backend/attendance/service/AttendanceServiceTest.java (1 hunks)
  • backend/src/test/java/org/sejongisc/backend/attendance/service/SessionLocationUpdateTest.java (0 hunks)
  • backend/src/test/java/org/sejongisc/backend/board/service/PostServiceImplTest.java (6 hunks)
💤 Files with no reviewable changes (2)
  • backend/src/test/java/org/sejongisc/backend/attendance/service/SessionLocationUpdateTest.java
  • backend/src/test/java/org/sejongisc/backend/attendance/service/AttendanceRoundServiceTest.java
🔇 Additional comments (3)
backend/src/main/java/org/sejongisc/backend/board/dto/PostResponse.java (1)

31-32: LGTM!

사용자별 좋아요/북마크 상태를 나타내는 새로운 필드가 올바르게 추가되었습니다. Boolean wrapper 타입 사용은 향후 비인증 사용자 지원 시 null 값을 허용할 수 있어 적절한 선택입니다.

backend/src/main/java/org/sejongisc/backend/board/service/PostService.java (1)

23-29: LGTM!

사용자 컨텍스트를 위한 userId 매개변수가 일관되게 추가되었습니다. 인터페이스 설계가 명확하고 사용자별 좋아요/북마크 상태 조회를 위한 요구사항을 잘 반영하고 있습니다.

backend/src/test/java/org/sejongisc/backend/board/service/PostServiceImplTest.java (1)

248-266: LGTM!

사용자 조회 및 좋아요/북마크 상태에 대한 모킹과 검증이 올바르게 추가되었습니다. 새로운 userId 매개변수와 isLiked/isBookmarked 응답 필드에 대한 테스트 커버리지가 적절합니다.

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

♻️ Duplicate comments (1)
backend/src/main/java/org/sejongisc/backend/board/controller/BoardController.java (1)

101-104: 비인증 요청 시 customUserDetails가 null 가능하여 NPE 위험 (게시글 조회/검색/상세/게시판 삭제)

현재 @AuthenticationPrincipal CustomUserDetails customUserDetails에 대해 별도 null 처리 없이 곧바로 customUserDetails.getUserId()를 호출하고 있습니다. 기존 SecurityConfig 설정상 /api/board/**에 대해 별도의 인증 요구가 없고 .anyRequest().permitAll() 인 경우, 비로그인 사용자가 해당 엔드포인트에 접근하면 customUserDetails는 null 이고 NPE가 발생합니다.

의도에 따라 다음 중 한 가지로 정리하는 것을 권장합니다.

  1. 엔드포인트 인증 강제: SecurityConfig/api/board/** (또는 필요한 경로들: 목록/검색/상세/삭제 포함)에 대해 .requestMatchers("/api/board/**").authenticated() 를 추가해 항상 CustomUserDetails가 존재하도록 만들기
  2. 게스트 허용 + null 안전 처리: 컨트롤러에서
    UUID userId = customUserDetails != null ? customUserDetails.getUserId() : null;
    처럼 null-safe 하게 처리하고, 서비스 계층에서 userId == null 인 경우에는 게스트로 간주해 isLiked/isBookmarked 등을 기본값(false)으로 처리하거나 권한 에러를 반환하는 방식으로 정리

위 전략 중 하나를 선택해 getPosts, searchPosts, getPostDetail, deleteBoard 에 일관되게 적용하는 것이 좋겠습니다. (이 이슈는 이전 리뷰 코멘트에서 이미 한번 언급된 내용과 동일한 류의 문제입니다.)

다음 스크립트를 통해 SecurityConfig 에서 /api/board 관련 매칭이 실제로 존재하는지 한 번 확인해 보실 수 있습니다:

#!/bin/bash
# /api/board 관련 보안 설정이 있는지 확인
rg -n "/api/board" backend/src/main/java/org/sejongisc/backend/common/auth/config/SecurityConfig.java

Also applies to: 119-122, 136-139, 189-193

🧹 Nitpick comments (1)
backend/src/main/java/org/sejongisc/backend/board/controller/BoardController.java (1)

158-167: 부모/하위 게시판 조회에서 사용되지 않는 @AuthenticationPrincipal 파라미터 정리 제안

getParentBoards, getChildBoards 메서드 시그니처에 @AuthenticationPrincipal CustomUserDetails customUserDetails 가 추가되었지만, 메서드 내부에서는 전혀 사용되지 않습니다.

  • 이 두 엔드포인트가 완전히 공개된 조회 API이고 현재로서 사용자별 분기 로직이 없다면, 시그니처를 단순화하기 위해 @AuthenticationPrincipal 파라미터를 제거하는 것도 고려할 수 있습니다.
  • 반대로, 향후 권한 제어나 개인화(예: 특정 사용자만 볼 수 있는 게시판)를 위해 미리 추가해 둔 것이라면 그대로 유지해도 되지만, 그 경우에도 상단의 /api/board/** 인증 정책과의 정합성(게스트 접근 허용 여부)은 한 번 더 점검해 두는 편이 좋습니다.

크리티컬한 문제는 아니며, 코드 가독성과 API 설계를 조금 더 명확히 하기 위한 선택 사항입니다.

SecurityConfig 에서 이 두 경로(/api/board/parents, /api/board/childs)의 인증 요구 여부를 다시 확인해 보시는 것을 추천드립니다.

Also applies to: 170-177

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 53b44f5 and b73527d.

📒 Files selected for processing (1)
  • backend/src/main/java/org/sejongisc/backend/board/controller/BoardController.java (6 hunks)

@Kosw6 Kosw6 merged commit b80c836 into main Nov 27, 2025
1 check passed
@Kosw6 Kosw6 deleted the SIsC1-151-BE-게시판-추가 branch November 27, 2025 04:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants