Skip to content

Conversation

@weeast1521
Copy link
Contributor

@weeast1521 weeast1521 commented Jul 11, 2025

refactor : PostController, PostService, PostRepository, PostConverter 커서 페이지네이션에 맞게 코드 리팩토링

📍 PR 타입 (하나 이상 선택)

  • 기능 추가
  • 버그 수정
  • 의존성, 환경 변수, 빌드 관련 코드 업데이트
  • 기타 사소한 수정

🏷️ 관련 이슈

Close #44

📌 개요

  • Post 관련 속성 추가 및 페이지네이션 구현

🔁 변경 사항

  • Post 속성에 들어갈 BoardType ENUM 추가
  • 커서 기반 페이지네이션에 맞는 PostController, PostService, PostRepository, PostConverter로 코드 변경

📸 스크린샷

✅ 체크리스트

  • 코드가 정상적으로 동작하는지 확인
  • PR에 적절한 라벨을 선택
  • 관련 테스트 코드 작성
  • 문서(README, Swagger 등) 업데이트

💡 추가 사항 (리뷰어가 참고해야 할 것)

Summary by CodeRabbit

  • New Features

    • Introduced board categories (FREE, INFO) for posts, allowing users to interact with posts by board type.
    • Added cursor-based pagination to post listings, including indicators for next page availability.
    • Post previews now display the author's nickname and comment count.
  • Improvements

    • API endpoints for posts are now organized by board type for clearer navigation.
    • Enhanced API documentation for post-related endpoints.
    • User actions such as liking and scrapping posts now rely on authentication, removing the need for user ID in requests.

refactor : PostController, PostService, PostRepository, PostConverter 커서 페이지네이션에 맞게 코드 리팩토링
@weeast1521 weeast1521 self-assigned this Jul 11, 2025
@weeast1521 weeast1521 added feature 기능 추가 refactor 코드 리팩토링 라벨 labels Jul 11, 2025
@coderabbitai
Copy link

coderabbitai bot commented Jul 11, 2025

"""

Walkthrough

The codebase was refactored to implement cursor-based pagination for post retrieval, introduce board type context in post APIs, and update method signatures and entities accordingly. These changes span controllers, services, repositories, converters, and DTOs, ensuring board-aware, paginated post listing and consistent use of authenticated user details.

Changes

File(s) Change Summary
.../auth/principal/PrincipalDetails.java Added getId() method to expose user ID.
.../domain/post/controller/PostController.java Refactored endpoints to support boardType in paths, cursor pagination, and authenticated user context.
.../domain/post/converter/PostConverter.java Updated toPost method for boardType and user; added author/commentNum to preview DTO; commented out list DTO.
.../domain/post/dto/PostReqDTO.java Imported BoardType enum.
.../domain/post/dto/PostResDTO.java Added author and commentNum to PostPreviewDTO; added nextCursor and hasNext to PostPreviewListDTO.
.../domain/post/entity/Post.java Added boardType field.
.../domain/post/enums/BoardType.java Introduced new enum BoardType with FREE and INFO.
.../domain/post/repository/PostRepository.java Added findByBoardTypeAndCursor method for cursor-based pagination.
.../domain/post/service/command/PostCommandService.java, PostCommandServiceImpl.java Updated method signatures to include boardType and use PrincipalDetails for user context.
.../domain/post/service/query/PostQueryService.java, PostQueryServiceImpl.java Updated getPostList to support boardType, cursor, and size for pagination.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller
    participant Service
    participant Repository

    Client->>Controller: GET /boards/{boardType}/posts?cursor={cursor}&size={size}
    Controller->>Service: getPostList(boardType, cursor, size)
    Service->>Repository: findByBoardTypeAndCursor(boardType, cursor, pageable)
    Repository-->>Service: Slice<Post>
    Service->>Controller: PostPreviewListDTO (with nextCursor, hasNext)
    Controller-->>Client: Response (paginated posts)
Loading

Assessment against linked issues

Objective Addressed Explanation
PostRepository 수정 (#44)
PostQueryService 수정 (#44)
PostController 수정 (#44)

Assessment against linked issues: Out-of-scope changes

No out-of-scope changes found.

Poem

Oh, cursor hops and boardy bounds,
Pagination magic newly found!
With every hop, a page anew—
BoardType guides us, posts in view.
Rabbits code and rabbits cheer,
For tidy lists and paging here!
🐇✨
"""


📜 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 8518f86 and 980bcc5.

📒 Files selected for processing (2)
  • src/main/java/naughty/tuzamate/domain/post/entity/Post.java (2 hunks)
  • src/main/java/naughty/tuzamate/domain/post/repository/PostRepository.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/naughty/tuzamate/domain/post/entity/Post.java
  • src/main/java/naughty/tuzamate/domain/post/repository/PostRepository.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-docker-image
✨ 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: 1

🧹 Nitpick comments (3)
src/main/java/naughty/tuzamate/domain/post/repository/PostRepository.java (1)

11-17: LGTM: Well-implemented cursor-based pagination query.

The JPQL query correctly implements cursor-based pagination with the following strengths:

  • Proper filtering by boardType and optional cursor
  • Correct ordering with ORDER BY p.id DESC for cursor pagination
  • Appropriate use of Slice<Post> return type for pagination

The cursor condition (:cursor IS NULL OR p.id < :cursor) properly handles both initial page load and subsequent pagination.

Consider adding an index on (boardType, id) for optimal query performance:

CREATE INDEX idx_post_board_type_id ON post (board_type, id DESC);
src/main/java/naughty/tuzamate/domain/post/converter/PostConverter.java (1)

43-44: Consider performance implications of comment count calculation.

The implementation correctly adds author and comment count fields to the DTO. However, post.getComments().size() may trigger an additional database query if comments are lazily loaded.

Consider optimizing the comment count calculation by:

  1. Using a dedicated query with COUNT() in the repository
  2. Adding a commentCount field to the Post entity that's updated when comments are added/removed
  3. Using a JOIN FETCH or projection in the repository query to avoid N+1 queries
// Alternative approach using COUNT query in repository
@Query("SELECT p, COUNT(c) FROM Post p LEFT JOIN p.comments c WHERE p.id = :postId GROUP BY p")
Optional<Object[]> findPostWithCommentCount(@Param("postId") Long postId);
src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryServiceImpl.java (1)

34-50: LGTM: Well-implemented cursor-based pagination logic.

The implementation correctly handles cursor-based pagination with proper:

  • Repository method invocation with board type and cursor filtering
  • Stream-based DTO conversion
  • Next cursor calculation from the last item's ID
  • Pagination metadata (hasNext) from the slice

The logic properly handles both initial page load and subsequent pagination requests.

Consider adding null safety for the cursor calculation:

-Long nextCursor = slice.hasNext() ? previews.get(previews.size() - 1).id() : null;
+Long nextCursor = slice.hasNext() && !previews.isEmpty() ? 
+    previews.get(previews.size() - 1).id() : null;

This prevents potential IndexOutOfBoundsException if the previews list is unexpectedly empty.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e056ba5 and 8518f86.

📒 Files selected for processing (12)
  • src/main/java/naughty/tuzamate/auth/principal/PrincipalDetails.java (1 hunks)
  • src/main/java/naughty/tuzamate/domain/post/controller/PostController.java (2 hunks)
  • src/main/java/naughty/tuzamate/domain/post/converter/PostConverter.java (3 hunks)
  • src/main/java/naughty/tuzamate/domain/post/dto/PostReqDTO.java (1 hunks)
  • src/main/java/naughty/tuzamate/domain/post/dto/PostResDTO.java (1 hunks)
  • src/main/java/naughty/tuzamate/domain/post/entity/Post.java (2 hunks)
  • src/main/java/naughty/tuzamate/domain/post/enums/BoardType.java (1 hunks)
  • src/main/java/naughty/tuzamate/domain/post/repository/PostRepository.java (1 hunks)
  • src/main/java/naughty/tuzamate/domain/post/service/command/PostCommandService.java (1 hunks)
  • src/main/java/naughty/tuzamate/domain/post/service/command/PostCommandServiceImpl.java (6 hunks)
  • src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryService.java (1 hunks)
  • src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryServiceImpl.java (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (3)
src/main/java/naughty/tuzamate/domain/post/dto/PostResDTO.java (1)
src/main/java/naughty/tuzamate/global/apiPayload/CustomResponse.java (1)
  • Builder (15-74)
src/main/java/naughty/tuzamate/domain/post/service/command/PostCommandServiceImpl.java (2)
src/main/java/naughty/tuzamate/domain/post/dto/PostReqDTO.java (1)
  • PostReqDTO (5-18)
src/main/java/naughty/tuzamate/domain/post/dto/PostResDTO.java (1)
  • PostResDTO (8-52)
src/main/java/naughty/tuzamate/domain/post/service/command/PostCommandService.java (2)
src/main/java/naughty/tuzamate/domain/post/dto/PostReqDTO.java (1)
  • PostReqDTO (5-18)
src/main/java/naughty/tuzamate/domain/post/dto/PostResDTO.java (1)
  • PostResDTO (8-52)
⏰ 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-docker-image
🔇 Additional comments (37)
src/main/java/naughty/tuzamate/auth/principal/PrincipalDetails.java (1)

27-29: LGTM! Clean abstraction for accessing user ID.

The addition of getId() method properly exposes the user's ID through the security principal, supporting the refactoring to use PrincipalDetails instead of explicitly passing user IDs. This centralized approach aligns well with Spring Security practices.

src/main/java/naughty/tuzamate/domain/post/enums/BoardType.java (1)

1-5: LGTM! Well-defined enum for board categorization.

The BoardType enum is properly defined with clear values (FREE, INFO) that support the board categorization feature. The implementation follows Java naming conventions and is appropriately minimal.

src/main/java/naughty/tuzamate/domain/post/entity/Post.java (2)

6-6: LGTM! Proper import for BoardType enum.

The import statement correctly brings in the BoardType enum for use in the entity.


33-34: LGTM! Proper enum field implementation.

The boardType field is correctly implemented with @Enumerated(EnumType.STRING) annotation, which will persist the enum values as strings in the database. This approach provides better readability and maintainability compared to ordinal values.

src/main/java/naughty/tuzamate/domain/post/dto/PostResDTO.java (2)

23-25: LGTM! Enhanced PostPreviewDTO with useful fields.

The addition of author and commentNum fields enhances the post preview data with essential information. The Korean comment clearly explains the purpose of these fields, making the code more maintainable.


33-35: LGTM! Proper cursor-based pagination implementation.

The modification to PostPreviewListDTO correctly implements cursor-based pagination with nextCursor and hasNext fields. This aligns with the PR objectives and follows standard cursor pagination patterns for better performance and user experience.

src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryService.java (2)

4-4: LGTM: Added BoardType import for new functionality.

The import is correctly added to support the new board type filtering capability.


9-9: LGTM: Interface updated for cursor-based pagination and board filtering.

The method signature change properly defines the contract for cursor-based pagination with board type filtering. The parameters are well-named and follow standard pagination patterns.

src/main/java/naughty/tuzamate/domain/post/repository/PostRepository.java (1)

4-6: LGTM: Added necessary imports for cursor-based pagination.

The imports for BoardType, Pageable, Slice, and Query are correctly added to support the new repository method.

Also applies to: 8-8

src/main/java/naughty/tuzamate/domain/post/converter/PostConverter.java (3)

8-9: LGTM: Added imports for enhanced domain model.

The imports for BoardType and User are correctly added to support the expanded post creation functionality.


18-18: LGTM: Enhanced post creation with board type and user context.

The updated method signature and entity construction properly incorporate board type categorization and user association, aligning with the domain model enhancements.

Also applies to: 23-24


51-59: Verify if commented-out method removal is intentional.

The toPostPreviewListDTO method is commented out, which appears to be related to the cursor pagination refactoring. Please confirm this is intentional and the method is no longer needed.

src/main/java/naughty/tuzamate/domain/post/service/query/PostQueryServiceImpl.java (1)

7-7: LGTM: Added necessary imports for cursor pagination implementation.

The imports for BoardType, PageRequest, Slice, and List are correctly added to support the new implementation.

Also applies to: 11-12, 16-16

src/main/java/naughty/tuzamate/domain/post/service/command/PostCommandService.java (2)

3-3: LGTM: Added imports for enhanced authentication and board context.

The imports for PrincipalDetails and BoardType are correctly added to support the improved API design with authenticated user context and board categorization.

Also applies to: 7-7


11-11: LGTM: Enhanced interface design with proper authentication context.

The method signature updates improve the API design by:

  • Adding BoardType to createPost for proper board categorization
  • Using PrincipalDetails instead of simple user ID for better authentication context
  • Providing consistent parameter patterns across all user-dependent operations

These changes align well with the overall refactoring objectives and follow Spring Security best practices.

Also applies to: 14-17

src/main/java/naughty/tuzamate/domain/post/service/command/PostCommandServiceImpl.java (9)

4-4: Import addition looks good.

The PrincipalDetails import is correctly added to support the authentication context refactoring.


9-9: BoardType import properly added.

The BoardType enum import is correctly added to support the board categorization feature.


35-36: User retrieval pattern is consistent.

The user retrieval using userRepository.getReferenceById(principalDetails.getId()) is consistent and efficient, using a reference instead of a full entity load since only the ID is needed for the relationship.


70-74: Authentication pattern correctly implemented.

The postLike method properly uses PrincipalDetails to get the authenticated user ID, maintaining security by not relying on client-provided user IDs.


80-84: PostLike builder formatting improved.

The PostLike builder has been reformatted for better readability with proper indentation and line breaks.


93-97: Consistent authentication pattern in deleteLike.

The deleteLike method properly uses PrincipalDetails for user authentication, maintaining consistency with other methods.


108-112: Authentication pattern correctly applied to postScrap.

The postScrap method uses PrincipalDetails consistently with other methods for secure user identification.


125-129: Consistent authentication in deleteScrap.

The deleteScrap method properly implements the PrincipalDetails authentication pattern.


33-41: PostConverter.toPost signature correctly matches expected parameters

The toPost method in src/main/java/naughty/tuzamate/domain/post/converter/PostConverter.java is defined as:

public static Post toPost(BoardType boardType, PostReqDTO.CreatePostRequestDTO reqDTO, User user)

which aligns exactly with the call in createPost. No further changes are needed.

src/main/java/naughty/tuzamate/domain/post/controller/PostController.java (13)

3-7: Swagger and authentication imports properly added.

The necessary imports for OpenAPI documentation and Spring Security authentication are correctly added.


11-11: BoardType enum import added.

The BoardType enum import is correctly added to support board categorization.


16-16: Authentication principal import added.

The @AuthenticationPrincipal import is correctly added for dependency injection of user authentication details.


22-22: API documentation tag added.

The @tag annotation provides proper API documentation for the controller.


28-38: CreatePost endpoint properly refactored.

The createPost endpoint has been correctly updated to include BoardType as a path variable and use PrincipalDetails for authentication. The API documentation is also properly added.


40-46: Single post endpoint updated with board context.

The getPost endpoint now includes BoardType in the path, maintaining consistency with the board-centric URL structure.


48-57: Post list endpoint with pagination parameters.

The getPostList endpoint properly includes cursor-based pagination parameters with appropriate validation (@max(30) for size). The BoardType path variable maintains consistency with the board-centric design.


59-67: Update endpoint includes board context.

The updatePost endpoint maintains consistency with the board-centric URL structure by including BoardType in the path.


69-75: Delete endpoint updated with board context.

The deletePost endpoint properly includes BoardType in the path for consistency.


77-85: Like endpoint uses authentication principal.

The like endpoint correctly uses PrincipalDetails for authentication instead of explicit user ID parameters, improving security.


87-96: Delete like endpoint properly secured.

The deleteLike endpoint uses PrincipalDetails for secure user authentication.


98-107: Scrap endpoint uses authentication principal.

The postScrap endpoint correctly implements PrincipalDetails authentication for security.


109-118: Delete scrap endpoint properly secured.

The deleteScrap endpoint uses PrincipalDetails for secure authentication.

@@ -1,5 +1,7 @@
package naughty.tuzamate.domain.post.dto;

import naughty.tuzamate.domain.post.enums.BoardType;
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify if BoardType import is needed.

The BoardType enum is imported but not used in any of the DTO records. Ensure this import is necessary or remove it if unused to keep the code clean.


🏁 Script executed:

#!/bin/bash
# Description: Check if BoardType is used in PostReqDTO or related validation
# Expected: Find usage of BoardType in PostReqDTO context

# Search for BoardType usage in the file
rg -A 5 -B 5 "BoardType" src/main/java/naughty/tuzamate/domain/post/dto/PostReqDTO.java

# Search for validation annotations or other usage patterns
rg -A 3 -B 3 "@Valid|@NotNull|@Validated" src/main/java/naughty/tuzamate/domain/post/dto/PostReqDTO.java

Length of output: 384


Remove unused BoardType import in PostReqDTO

The BoardType enum is imported in PostReqDTO.java but isn’t referenced anywhere in that file. Please remove the unused import to keep the code clean.

• File to update:
src/main/java/naughty/tuzamate/domain/post/dto/PostReqDTO.java

• Suggested diff:

--- a/src/main/java/naughty/tuzamate/domain/post/dto/PostReqDTO.java
+++ b/src/main/java/naughty/tuzamate/domain/post/dto/PostReqDTO.java
@@
-import naughty.tuzamate.domain.post.enums.BoardType;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import naughty.tuzamate.domain.post.enums.BoardType;
🤖 Prompt for AI Agents
In src/main/java/naughty/tuzamate/domain/post/dto/PostReqDTO.java at line 3, the
import statement for BoardType is unused. Remove the line importing
naughty.tuzamate.domain.post.enums.BoardType to clean up the code and avoid
unnecessary imports.

@weeast1521 weeast1521 merged commit deedf6a into dev Jul 11, 2025
2 checks passed
weeast1521 added a commit that referenced this pull request Jul 27, 2025
feat : BoardType ENUM 속성 POST에 추가, refactor : postController,Service,Repository,Converter 코드를 커서 페이지네이션 기반으로 수정
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature 기능 추가 refactor 코드 리팩토링 라벨

Projects

None yet

Development

Successfully merging this pull request may close these issues.

♻️ [Refactor] 게시글 조회에 대한 리펙토링(커서 페이지네이션 구현)

2 participants