Skip to content

feat: [alt-248] 사용자 목록 응답에 프로필 이미지 필드 추가#90

Merged
ysw789 merged 5 commits into
devfrom
feat/alt-248
Jun 11, 2026
Merged

feat: [alt-248] 사용자 목록 응답에 프로필 이미지 필드 추가#90
ysw789 merged 5 commits into
devfrom
feat/alt-248

Conversation

@ysw789

@ysw789 ysw789 commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

변경사항

사용자 기본 프로필 도입

  • WorkerInfo/ManagerWorkerInfo 팩토리 및 응답 DTO에 profileImageUrl 매핑
  • 대타요청 요청자/수락자/대상자 정보에 profileImageUrl 추가
  • 워크스페이스 워커/매니저 목록에 profileImageUrl 추가

Summary by CodeRabbit

  • New Features
    • 근무자/사용자 응답에 프로필 이미지 URL 추가
    • 대타 요청 목록·상세 조회에 요청자 및 수락자 프로필 이미지 표시
    • 요청 대상자 및 워크스페이스 근무자 정보에 프로필 이미지 포함
    • 관리자용 대타 요청 목록 및 화면에서 프로필 이미지 노출 개선

ysw789 added 3 commits June 10, 2026 14:13
- getWorkspaceWorkerListWithCursor: 매니저 근무자 목록
- getUserWorkspaceWorkerListWithCursor: 유저 근무자 목록
- getExchangeableWorkerListWithCursor: 대타 대상 근무자 선택 목록
- getUserWorkspaceManagerListWithCursor: 유저 매니저 목록
- getManagerWorkspaceManagerListWithCursor: 매니저 매니저 목록

File 엔티티를 USER_PROFILE + ATTACHED 조건으로 left join하고
file.fileUrl을 projection하여 각 워커/매니저의 프로필 이미지 URL 포함
- getReceivedRequestListWithCursor: 요청자, 수락자
- getSentRequestDetail: 요청자, 수락자, 각 대상자
- getManagerRequestListWithCursor: 요청자, 수락자

각 인물별 QFile 별칭(requesterFile/acceptedFile/targetFile)으로
USER_PROFILE + ATTACHED 조건 left join하여 프로필 이미지 URL 포함
- WorkerInfo.of(): Long workerId, String workerName, String profileImageUrl
- ManagerWorkerInfo.of(): 동일 확장
- ReceivedSubstituteRequestResponseDto.of(): requester/acceptedWorker profileImageUrl 전달
- SubstituteRequestDetailResponseDto.of(): requester/acceptedWorker/targets profileImageUrl 전달
- ManagerSubstituteRequestResponseDto.of(): requester/acceptedWorker profileImageUrl 전달
- SubstituteRequestTargetResponseDto.of(): target profileImageUrl 전달

readonly 응답의 프로필 URL을 inbound DTO의 nested WorkerInfo로 매핑
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ysw789, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 7 minutes and 46 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b779adab-bb63-4505-902a-f1ac247ac4d0

📥 Commits

Reviewing files that changed from the base of the PR and between 7be0c64 and af99cb6.

📒 Files selected for processing (1)
  • src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/SubstituteRequestQueryRepositoryImpl.java
📝 Walkthrough

워크스루

이 PR은 근무자 및 사용자 응답 데이터 전반에 프로필 이미지 URL 정보를 추가하는 기능 변경입니다. WorkerInfo 계약을 확장하고, 모든 관련 DTO와 쿼리를 업데이트하여 프로필 이미지 URL을 일관되게 제공합니다.

변경사항

프로필 이미지 URL 기능 추가

레이어 / 파일(들) 요약
WorkerInfo 및 ManagerWorkerInfo 데이터 계약 업데이트
src/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/WorkerInfo.java, src/main/java/com/dreamteam/alter/adapter/inbound/manager/schedule/dto/ManagerWorkerInfo.java
WorkerInfo와 ManagerWorkerInfo에 profileImageUrl 필드를 추가하고, 정적 팩토리 메서드 of(...)의 시그니처를 (workerId, workerName, profileImageUrl) 형태로 확장했다.
읽기 전용 응답 엔티티에 profileImageUrl 필드 추가
src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/*Response.java
ReceivedSubstituteRequestListResponse, SentSubstituteRequestDetailResponse, SubstituteRequestTargetInfo, UserWorkspaceWorkerResponse, WorkspaceWorkerResponse 등에 profileImageUrl 필드를 추가하여 데이터 계약을 확장했다.
일반 스케줄 응답 DTO 업데이트
src/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/ReceivedSubstituteRequestResponseDto.java, src/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/SubstituteRequestDetailResponseDto.java, src/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/SubstituteRequestTargetResponseDto.java
확장된 WorkerInfo.of(...) 시그니처를 호출할 때 requester, acceptedWorker, target의 profileImageUrl을 전달하도록 매핑 로직을 수정했다.
사용자 작업공간 응답 DTO 업데이트
src/main/java/com/dreamteam/alter/adapter/inbound/general/user/dto/UserWorkspaceWorkerResponseDto.java
UserWorkspaceWorkerResponseDto에 profileImageUrl 필드 및 Swagger @Schema 주석을 추가하고, of(...) 팩토리 메서드에서 엔티티의 profileImageUrl을 매핑했다.
관리자 스케줄 응답 DTO 업데이트
src/main/java/com/dreamteam/alter/adapter/inbound/manager/schedule/dto/ManagerSubstituteRequestResponseDto.java
확장된 ManagerWorkerInfo.of(...) 시그니처를 사용하여 requester와 acceptedWorker 모두에 profileImageUrl을 포함하도록 변경했다.
관리자 작업공간 응답 DTO 업데이트
src/main/java/com/dreamteam/alter/adapter/inbound/manager/workspace/dto/WorkspaceWorkerResponseDto.java
WorkspaceWorkerResponseDto에 profileImageUrl 필드 및 스키마 주석을 추가하고, of(...) 메서드에서 엔티티의 profileImageUrl을 매핑했다.
대타 요청 쿼리 리포지토리 - 프로필 이미지 URL 조회
src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/SubstituteRequestQueryRepositoryImpl.java
getReceivedRequestListWithCursor, getSentRequestDetail, 대상자 조회, getManagerRequestListWithCursor에서 QueryDSL을 확장하여 QFile을 USER_PROFILE+ATTACHED 조건으로 leftJoin하고, 응답 Projection에 requesterFile.fileUrl과 acceptedFile.fileUrl을 추가했다.
작업공간 근무자 쿼리 리포지토리 - 프로필 이미지 URL 조회
src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.java
getWorkspaceWorkerListWithCursor, getUserWorkspaceWorkerListWithCursor, getExchangeableWorkerListWithCursor, getUserWorkspaceManagerListWithCursor, getManagerWorkspaceManagerListWithCursor 각 메서드에서 QFile을 leftJoin하고 응답 Projection에 qFile.fileUrl을 추가하며 groupBy에도 포함시켰다.

🎯 3 (Moderate) | ⏱️ ~20 분

제안 레이블

FEAT

제안 리뷰어

  • hodoon
  • juny0955
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.55% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed PR 제목은 변경사항의 핵심을 명확하게 반영하고 있다. 사용자 목록 응답에 프로필 이미지 필드를 추가하는 것이 주요 변경사항이며, 제목이 이를 정확히 설명한다.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/alt-248

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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)
src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.java (1)

524-536: ⚠️ Potential issue | 🟠 Major

leftJoin으로 인해 중복 row(커서/응답 왜곡) 가능—사용자당 ATTACHED 1건 보장 필요

WorkspaceQueryRepositoryImpl.getUserWorkspaceManagerListWithCursor에서 qFileleftJoin하고( USER_PROFILE + ATTACHED ), groupBy/distinct 없이 fetch()합니다. 따라서 한 사용자에게 ATTACHED USER_PROFILE 파일이 2건 이상 존재하면 동일 매니저가 여러 row로 반환될 수 있습니다(페이지/커서 결과가 깨지거나 fileUrl 의미가 흔들림).

File 엔티티에는 idunique=true로 보이고, (targetType, targetId, status=ATTACHED) 같은 복합 유니크 제약(또는 단일 ATTACHED 강제) 근거가 없습니다.

다음 중 하나로 “사용자당 ATTACHED 1건”을 강제해 주세요.

  • DB 레벨 유니크 제약/인덱스로 (target_type, target_id, status=ATTACHED) 단일화를 보장
  • 또는 조회 시 사용자/매니저 기준으로 ATTACHED 파일을 1건만 고정해서 조인(서브쿼리/exists 등)
  • 또는 첨부 로직에서 기존 ATTACHED 전체를 정리하고 최종적으로 1건만 유지
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.java`
around lines 524 - 536, The leftJoin of qFile in
WorkspaceQueryRepositoryImpl.getUserWorkspaceManagerListWithCursor can return
duplicate rows when a user has multiple ATTACHED USER_PROFILE files; fix by
limiting the join to at most one ATTACHED file per user: replace the direct
leftJoin(qFile) with a join to a subquery that selects a single ATTACHED file
per targetId (e.g., the latest by id or createdAt) and join on that subquery
(matching targetType=FileTargetType.USER_PROFILE, status=FileStatus.ATTACHED,
and targetId=qUser.id.stringValue()), or alternatively enforce uniqueness at DB
level by adding a unique index on (target_type, target_id, status) for ATTACHED
files; ensure the change is applied within getUserWorkspaceManagerListWithCursor
and keeps the existing where(cursorConditions(...)), orderBy(qUser.name.asc(),
qManagerUser.id.asc()), limit(pageRequest.pageSize()) and uses
pageRequest.cursor() semantics.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/SubstituteRequestQueryRepositoryImpl.java`:
- Around line 200-211: Extract the repeated leftJoin block that joins a profile
image file (the pattern using requesterFile/acceptedFile,
FileTargetType.USER_PROFILE, .targetId.eq(<user>.id.stringValue()), and
FileStatus.ATTACHED) into a private helper inside
SubstituteRequestQueryRepositoryImpl (e.g., addProfileImageLeftJoin or
joinProfileImageForUser). Replace each repeated block (where
requesterFile/acceptedFile are joined against requesterUser/acceptedUser via
acceptedWorker, substituteRequest, etc.) with calls to that helper, passing the
file alias (requesterFile, acceptedFile), the user alias/expression
(requesterUser, acceptedUser or acceptedWorker.user), and the target type/status
constants (FileTargetType.USER_PROFILE, FileStatus.ATTACHED) so the join logic
(targetType, targetId, status) is centralized and reused.
- Around line 200-211: The left joins on requesterFile and acceptedFile using
(FileTargetType.USER_PROFILE, targetId, FileStatus.ATTACHED) can produce
duplicate rows if multiple ATTACHED user-profile files exist; update
SubstituteRequestQueryRepositoryImpl to ensure only one file per user is joined
(either by enforcing uniqueness in the DB/domain or by changing the join to a
subquery that picks a single file per target, e.g., select the latest/first
attached profile file) — modify the leftJoin calls for requesterFile and
acceptedFile (the .leftJoin(requesterFile).on(...) and
.leftJoin(acceptedFile).on(...)) to join against a subselect that filters and
limits to one row per targetId (or add an explicit dedup predicate such as
comparing to a max(id) or createdAt) so the request/accepted user rows are not
duplicated.

In
`@src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.java`:
- Around line 196-201: 반복되는 프로필 이미지 leftJoin 패턴(qFile.leftJoin 조건:
qFile.targetType.eq(FileTargetType.USER_PROFILE),
qFile.targetId.eq(qUser.id.stringValue()),
qFile.status.eq(FileStatus.ATTACHED))을 헬퍼 메서드로 추출해 재사용하세요; 예를 들어
WorkspaceQueryRepositoryImpl과 SubstitueRequestQueryRepositoryImpl에서 사용 중인 qFile,
qUser를 파라미터로 받아 JPAQuery에 동일한 leftJoin 조건을 적용하는 메서드(예: applyProfileImageLeftJoin
또는 joinUserProfileImage)를 추가하고 기존 쿼리들(문제 지적된 위치들과 동일한 패턴이 사용된 303-308, 418-423,
524-529, 586-591 등)을 해당 헬퍼 호출로 대체해 중복을 제거하세요.

---

Outside diff comments:
In
`@src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.java`:
- Around line 524-536: The leftJoin of qFile in
WorkspaceQueryRepositoryImpl.getUserWorkspaceManagerListWithCursor can return
duplicate rows when a user has multiple ATTACHED USER_PROFILE files; fix by
limiting the join to at most one ATTACHED file per user: replace the direct
leftJoin(qFile) with a join to a subquery that selects a single ATTACHED file
per targetId (e.g., the latest by id or createdAt) and join on that subquery
(matching targetType=FileTargetType.USER_PROFILE, status=FileStatus.ATTACHED,
and targetId=qUser.id.stringValue()), or alternatively enforce uniqueness at DB
level by adding a unique index on (target_type, target_id, status) for ATTACHED
files; ensure the change is applied within getUserWorkspaceManagerListWithCursor
and keeps the existing where(cursorConditions(...)), orderBy(qUser.name.asc(),
qManagerUser.id.asc()), limit(pageRequest.pageSize()) and uses
pageRequest.cursor() semantics.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2a7d2ca2-1d0c-4e83-aad6-ff21f3d6bea0

📥 Commits

Reviewing files that changed from the base of the PR and between 3f776bc and b49f414.

📒 Files selected for processing (16)
  • src/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/ReceivedSubstituteRequestResponseDto.java
  • src/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/SubstituteRequestDetailResponseDto.java
  • src/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/SubstituteRequestTargetResponseDto.java
  • src/main/java/com/dreamteam/alter/adapter/inbound/general/schedule/dto/WorkerInfo.java
  • src/main/java/com/dreamteam/alter/adapter/inbound/general/user/dto/UserWorkspaceWorkerResponseDto.java
  • src/main/java/com/dreamteam/alter/adapter/inbound/manager/schedule/dto/ManagerSubstituteRequestResponseDto.java
  • src/main/java/com/dreamteam/alter/adapter/inbound/manager/schedule/dto/ManagerWorkerInfo.java
  • src/main/java/com/dreamteam/alter/adapter/inbound/manager/workspace/dto/WorkspaceWorkerResponseDto.java
  • src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/SubstituteRequestQueryRepositoryImpl.java
  • src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/WorkspaceQueryRepositoryImpl.java
  • src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/ManagerSubstituteRequestListResponse.java
  • src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/ReceivedSubstituteRequestListResponse.java
  • src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/SentSubstituteRequestDetailResponse.java
  • src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/SubstituteRequestTargetInfo.java
  • src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/UserWorkspaceWorkerResponse.java
  • src/main/java/com/dreamteam/alter/adapter/outbound/workspace/persistence/readonly/WorkspaceWorkerResponse.java

@ysw789 ysw789 changed the title feat: [alt-248] 사용자 기본 프로필 도입 feat: [alt-248] 사용자 목록 응답에 프로필 이미지 필드 추가 Jun 11, 2026
@ysw789 ysw789 merged commit 9f0c297 into dev Jun 11, 2026
3 checks 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