Skip to content

[FEAT] 마이페이지 키스크린 통합 데이터 컬럼 추가#138

Merged
icarus0616 merged 2 commits into
devfrom
feat/key-screen-facade/2
Feb 8, 2026
Merged

[FEAT] 마이페이지 키스크린 통합 데이터 컬럼 추가#138
icarus0616 merged 2 commits into
devfrom
feat/key-screen-facade/2

Conversation

@icarus0616
Copy link
Copy Markdown
Collaborator

@icarus0616 icarus0616 commented Feb 8, 2026

#137

Summary by CodeRabbit

  • New Features
    • Enhanced the My Page dashboard to display additional user statistics including follower and following counts, completed books, booklogs, and bookmarks.
    • Profile information now includes email address in the dashboard response.

@icarus0616 icarus0616 self-assigned this Feb 8, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 8, 2026

📝 Walkthrough

Walkthrough

Refactored MyPage controller (renamed from MeMyPageController), updated its facade service to accept user email alongside userId, and introduced a new stats-aware profile DTO with repository and service layer to retrieve user profiles enriched with follower/following counts and engagement metrics.

Changes

Cohort / File(s) Summary
Controller Refactoring
booklog/src/main/java/com/example/booklog/domain/users/controller/MyPageKeyScreenController.java
Renamed class from MeMyPageController to MyPageKeyScreenController; updated parameter from me to userDetails and refactored to pass both userId and email (derived from userDetails.getUsername()) to facade service.
New Profile DTO
booklog/src/main/java/com/example/booklog/domain/users/dto/MeProfileWithStatsResponse.java
Added new record with user profile fields (userId, nickname, avatarUrl) plus privacy flags and engagement stats (email, followerCount, followingCount, completedBookCount, myBooklogCount, bookmarkCount).
Response DTO Updates
booklog/src/main/java/com/example/booklog/domain/users/dto/MyPageKeyScreenResponse.java
Updated of() method to accept MeProfileWithStatsResponse instead of MeProfileResponse; expanded ProfileSummary nested record to include email and engagement counts; changed profile image accessor from profileImageUrl() to avatarUrl().
New Repository Layer
booklog/src/main/java/com/example/booklog/domain/users/repository/MeProfileWithStatsQueryRepository.java, booklog/src/main/java/com/example/booklog/domain/users/repository/projection/MeProfileWithStatsProjection.java
Introduced repository interface with native SQL query joining users and user\_settings to fetch profile with aggregated stats; added projection interface defining contract for query result mapping.
New Service Layer
booklog/src/main/java/com/example/booklog/domain/users/service/MeProfileWithStatsService.java
Added service to retrieve user profile with stats, handling user validation and normalizing null values; includes helper methods for boolean defaulting and numeric type conversion.
Facade Service Updates
booklog/src/main/java/com/example/booklog/domain/users/service/MyPageKeyScreenFacadeService.java
Updated getMyPage() method signature to accept email parameter; replaced meProfileService with meProfileWithStatsService for profile retrieval.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Controller as MyPageKeyScreenController
    participant Facade as MyPageKeyScreenFacadeService
    participant ProfileService as MeProfileWithStatsService
    participant Repository as MeProfileWithStatsQueryRepository
    participant Database

    Client->>Controller: GET /mypage?month=YYYY-MM
    Controller->>Controller: Extract userId, email from userDetails
    Controller->>Facade: getMyPage(userId, email, month)
    Facade->>ProfileService: getMyProfileWithStats(userId, email)
    ProfileService->>Repository: findMeProfileWithStats(userId, "DONE")
    Repository->>Database: Execute native SQL query
    Database-->>Repository: MeProfileWithStatsProjection
    Repository-->>ProfileService: Query result
    ProfileService->>ProfileService: Map to MeProfileWithStatsResponse
    ProfileService-->>Facade: MeProfileWithStatsResponse
    Facade->>Facade: Build MyPageKeyScreenResponse with profile + insights
    Facade-->>Controller: MyPageKeyScreenResponse
    Controller->>Controller: Wrap in ApiResponse
    Controller-->>Client: ApiResponse<MyPageKeyScreenResponse>
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly Related Issues

Possibly Related PRs

Suggested Labels

enhancement

Suggested Reviewers

  • jaehyeon4406
  • millkk04
  • ktg3891

Poem

🐰 A keyscreen dashboard blooms so bright,
With stats and profiles dancing right,
New dtos hop through service layers deep,
Email trails where counts all creep,
The MyPage now knows all!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: adding new profile statistics columns (email, follower/following counts, completed book count, myBooklog count, bookmark count) to the MyPage key screen integrated response.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 feat/key-screen-facade/2

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
Copy Markdown

@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

🤖 Fix all issues with AI agents
In
`@booklog/src/main/java/com/example/booklog/domain/users/dto/MyPageKeyScreenResponse.java`:
- Around line 34-39: MyPageKeyScreenResponse currently exposes the user's email
(PII) via the ProfileSummary/ email field; remove or hide it from the serialized
API response by either removing the email property from
MyPageKeyScreenResponse/ProfileSummary or marking the email accessor with a
serialization ignore (e.g., annotate getEmail in ProfileSummary or the email
field in MyPageKeyScreenResponse with `@JsonIgnore`) and ensure any internal-only
access uses a separate internal DTO or method; also audit usages of
MyPageKeyScreenResponse/ProfileSummary to avoid caching or debug-logging the
email (remove logging of email or wrap with redaction) so PII is never sent to
shared caches or logs.

In
`@booklog/src/main/java/com/example/booklog/domain/users/repository/MeProfileWithStatsQueryRepository.java`:
- Around line 13-48: Add missing DB indexes used by
MeProfileWithStatsQueryRepository's native query: update the JPA entity for the
user_follows table to include two `@Index` entries named idx_user_follows_follower
(columnList="follower_id") and idx_user_follows_followee
(columnList="followee_id"), and update the booklog_bookmark entity to add an
`@Index` named idx_booklog_bookmark_user (columnList="user_id"); ensure these
annotations are placed on the `@Table`(...) of the corresponding entity classes so
COUNT subqueries in MeProfileWithStatsQueryRepository will use single-column
indexes for follower_id, followee_id and user_id.

Comment on lines +34 to +39
String email,
long followerCount,
long followingCount,
long completedBookCount,
long myBooklogCount,
long bookmarkCount
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Consider whether email should be exposed in this API response.

The user's email (PII) is now included in the ProfileSummary returned by the MyPage endpoint. Since this is the authenticated user's own profile, it's likely intentional, but ensure this response is not cached in shared caches or logged at debug level, as it would leak PII.

🤖 Prompt for AI Agents
In
`@booklog/src/main/java/com/example/booklog/domain/users/dto/MyPageKeyScreenResponse.java`
around lines 34 - 39, MyPageKeyScreenResponse currently exposes the user's email
(PII) via the ProfileSummary/ email field; remove or hide it from the serialized
API response by either removing the email property from
MyPageKeyScreenResponse/ProfileSummary or marking the email accessor with a
serialization ignore (e.g., annotate getEmail in ProfileSummary or the email
field in MyPageKeyScreenResponse with `@JsonIgnore`) and ensure any internal-only
access uses a separate internal DTO or method; also audit usages of
MyPageKeyScreenResponse/ProfileSummary to avoid caching or debug-logging the
email (remove logging of email or wrap with redaction) so PII is never sent to
shared caches or logs.

Comment on lines +13 to +48
@Query(value = """
SELECT
u.user_id AS userId,
u.nickname AS nickname,
u.profile_image_url AS avatarUrl,

/* settings 없으면 기본 true(=1) */
IFNULL(us.is_shelf_public, 1) AS isShelfPublic,
IFNULL(us.is_post_public, 1) AS isBooklogPublic,

(SELECT COUNT(*)
FROM user_follows f
WHERE f.followee_id = u.user_id) AS followerCount,

(SELECT COUNT(*)
FROM user_follows f
WHERE f.follower_id = u.user_id) AS followingCount,

(SELECT COUNT(*)
FROM user_books ub
WHERE ub.user_id = u.user_id
AND ub.status = :completedStatus) AS completedBookCount,

(SELECT COUNT(*)
FROM booklog_posts p
WHERE p.user_id = u.user_id) AS myBooklogCount,

(SELECT COUNT(*)
FROM booklog_bookmark b
WHERE b.user_id = u.user_id) AS bookmarkCount

FROM users u
LEFT JOIN user_settings us ON us.user_id = u.user_id
WHERE u.user_id = :userId
LIMIT 1
""", nativeQuery = true)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

find . -type f \( -name "*.sql" -o -name "*Migration*.java" -o -name "*migration*.xml" \) | head -20

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 57


🏁 Script executed:

rg -l "user_follows|user_books|booklog_posts|booklog_bookmark" --type sql --type java | head -20

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 1789


🏁 Script executed:

rg -n "CREATE INDEX|ADD INDEX|@Index|@Table" -C 3 --type sql --type java | grep -A3 -B3 "user_follows\|user_books\|booklog_posts\|booklog_bookmark\|user_settings" | head -60

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 4992


🏁 Script executed:

# Look for the entity files themselves
fd -e java "User" -o "Book" -o "Follow" -o "Post" | grep -i "entity\|domain" | head -20

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 202


🏁 Script executed:

# Check the specific file being reviewed
cat -n "booklog/src/main/java/com/example/booklog/domain/users/repository/MeProfileWithStatsQueryRepository.java"

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 2139


🏁 Script executed:

cat -n booklog/src/main/java/com/example/booklog/domain/users/entity/UserFollows.java

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 2898


🏁 Script executed:

cat -n booklog/src/main/java/com/example/booklog/domain/booklog/entity/BooklogBookmark.java

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 1110


🏁 Script executed:

# Search for ReadingStatus enum and completedStatus usage
rg -n "ReadingStatus\|completedStatus" --type java -B2 -A2 | head -60

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 57


🏁 Script executed:

# Find the service/controller that calls findMeProfileWithStats to check enum handling
rg -n "findMeProfileWithStats\|ReadingStatus.COMPLETED" --type java -B3 -A3

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 57


🏁 Script executed:

# Search for ReadingStatus enum
rg -n "enum ReadingStatus|class ReadingStatus" --type java -A10

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 2258


🏁 Script executed:

# Search for where MeProfileWithStatsQueryRepository is called
rg -n "MeProfileWithStatsQueryRepository|findMeProfileWithStats" --type java -B2 -A4

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 4930


🏁 Script executed:

# Look for migration files that might define indexes
find . -type f \( -name "*migration*" -o -name "*Migration*" -o -name "*.sql" \) 2>/dev/null | head -20

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 57


🏁 Script executed:

# Check if there are Flyway or Liquibase migrations
find . -path "*/db/migration*" -o -path "*/flyway*" -o -path "*/liquibase*" 2>/dev/null | head -20

Repository: Project-BookLog/BookLog-BackEnd

Length of output: 57


Add missing indexes on user_follows and booklog_bookmark tables for query performance.

The correlated subqueries are acceptable for single-user lookups, but three of the five subquery tables lack the necessary indexes:

  • user_follows: No @Index on followee_id or follower_id. These columns are part of a composite primary key but filtering by a single column requires individual indexes. Add:

    indexes = {
        `@Index`(name = "idx_user_follows_follower", columnList = "follower_id"),
        `@Index`(name = "idx_user_follows_followee", columnList = "followee_id")
    }
  • booklog_bookmark: Has a unique constraint on (user_id, post_id) but no dedicated index on user_id alone. Add:

    `@Index`(name = "idx_booklog_bookmark_user", columnList = "user_id")
  • user_books and booklog_posts already have the required indexes.

Without these indexes, the COUNT queries will degrade as these tables grow.

🤖 Prompt for AI Agents
In
`@booklog/src/main/java/com/example/booklog/domain/users/repository/MeProfileWithStatsQueryRepository.java`
around lines 13 - 48, Add missing DB indexes used by
MeProfileWithStatsQueryRepository's native query: update the JPA entity for the
user_follows table to include two `@Index` entries named idx_user_follows_follower
(columnList="follower_id") and idx_user_follows_followee
(columnList="followee_id"), and update the booklog_bookmark entity to add an
`@Index` named idx_booklog_bookmark_user (columnList="user_id"); ensure these
annotations are placed on the `@Table`(...) of the corresponding entity classes so
COUNT subqueries in MeProfileWithStatsQueryRepository will use single-column
indexes for follower_id, followee_id and user_id.

@icarus0616 icarus0616 merged commit 5bad905 into dev Feb 8, 2026
1 check passed
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.

1 participant