Skip to content

[WTH-196] 인증 정책 수정, 이미지 관련 필드 수정#32

Merged
hyxklee merged 23 commits intodevfrom
refactor/WTH-196-인증-정책-수정-Role
Mar 23, 2026

Hidden character warning

The head ref may contain hidden characters: "refactor/WTH-196-\uc778\uc99d-\uc815\ucc45-\uc218\uc815-Role"
Merged

[WTH-196] 인증 정책 수정, 이미지 관련 필드 수정#32
hyxklee merged 23 commits intodevfrom
refactor/WTH-196-인증-정책-수정-Role

Conversation

@hyxklee
Copy link
Copy Markdown
Contributor

@hyxklee hyxklee commented Mar 23, 2026

📌 Summary

어떤 작업인지 한 줄 요약해 주세요.

다중 동아리를 지원함에 따라 기존 Jwt에 Role을 저장해 검증하던 로직을 제거하고, 비즈니스 로직 내부에서 검증하도록 수정했습니다.
이미지 URL을 저장하던 것에서 StorageKey를 저장해 추후 CDN 도입시 문제가 없도록 했습니다.

📝 Changes

변경사항을 what, why, how로 구분해 작성해 주세요.

What

다중 동아리 지원을 위한 인증 정책 수정
이미지 관련 필드 수정

Why

다중 동아리 지원을 위해서, 추후 CDN 도입을 위해서

How

JWT에서 Role 제거 (마스터 토큰 업데이트 완료)
WTH-209 작업에서 추가된 UserInfo에 MemberRole을 반환하도록 처리 + ClubMember의 ProfileImage를 반환하도록 매핑 처리 (N+1이 발생하지 않도록 전부 조회해서 Map으로 변환한 후 꺼내다 쓰는 방식으로 처리했습니다.)
Club, ClubMember에서 사용되는 이미지의 StorageKey를 저장하도록 처리

📸 Screenshots / Logs

필요시 스크린샷 or 로그를 첨부해주세요.

💡 Reviewer 참고사항

리뷰에 참고할 내용을 작성해주세요.
Club은 아직 File 도메인과 연동은 되어있지 않는데, 해당 작업에서 처리하면 너무 커질 것 같아 분리하기로 했습니당
UpdateBio는 사용처가 없어 제거했고, 약관동의 메서드도 경고가 뜨길래 true로 설정해주도록 수정했습니당

✅ Checklist

  • PR 제목 설정 완료 (WTH-123 인증 필터 설정)
  • 테스트 구현 완료
  • 리뷰어 등록 완료
  • 자체 코드 리뷰 완료

Summary by CodeRabbit

  • New Features

    • 동아리별 멤버 권한(MemberRole)에 따른 접근·쓰기 권한 적용 및 멤버 기반 작성자 정보 노출
  • Bug Fixes

    • 프로필·클럽 이미지 처리 방식: 직접 URL 대신 저장 키(storageKey) 기반으로 전환
  • Refactor

    • JWT에서 전역 역할 제거하고 동아리 멤버십으로 권한 판단 전환
    • 관리자 권한 판정에 리드(LEAD)를 포함하도록 변경
    • 일부 전역 사용자 API 정리 및 클럽 범위 API로 전환/비추천 처리

@hyxklee hyxklee requested a review from soo0711 March 23, 2026 04:32
@hyxklee hyxklee self-assigned this Mar 23, 2026
@hyxklee hyxklee added the 🔨 Refactor 코드 구조 개선 및 리팩토링 label Mar 23, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 23, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

사용자 도메인의 Role을 제거하고 Club 도메인의 MemberRole로 전환, ClubMember 기반 권한 검사 도입, 이미지 URL을 저장소 키로 변경, JWT 레이어에서 role 정보 제거 및 관련 매퍼/컨트롤러/리포지토리/테스트를 대규모로 변경함.

Changes

Cohort / File(s) Summary
Role → MemberRole 전환
src/main/kotlin/com/weeth/domain/board/application/dto/request/CreateBoardRequest.kt, src/main/kotlin/com/weeth/domain/board/application/dto/request/UpdateBoardRequest.kt, src/main/kotlin/com/weeth/domain/board/domain/vo/BoardConfig.kt, src/main/kotlin/com/weeth/domain/board/domain/entity/Board.kt, src/main/kotlin/com/weeth/domain/user/application/dto/request/UserRoleUpdateRequest.kt, src/main/kotlin/com/weeth/domain/user/application/dto/response/UserInfo.kt, .../UserProfileResponse.kt, .../UserSummaryResponse.kt
다수 DTO/VO/엔티티의 Role 타입을 MemberRole로 변경하고 관련 스키마/기본값을 업데이트함.
ClubMember 기반 권한 검사 도입
.../ManagePostUseCase.kt, .../GetBoardQueryService.kt, .../GetPostQueryService.kt, .../ClubMemberPolicy.kt, .../GetSessionQueryService.kt
외부 role 파라미터 제거, 활성 ClubMember 조회(clubMemberPolicy)로 권한 판정 로직 전환 및 메서드 시그니처 변경.
이미지 URL → 저장소 키 전환
src/main/kotlin/com/weeth/domain/club/application/dto/request/ClubCreateRequest.kt, .../ClubUpdateRequest.kt, src/main/kotlin/com/weeth/domain/club/domain/entity/Club.kt, .../ClubMember.kt, .../ClubMapper.kt, .../ManageClubMemberUsecase.kt, .../ManageClubUseCase.kt
클럽 및 클럽멤버 이미지 필드를 URL에서 storageKey로 변경, 관련 매퍼/유스케이스에서 storageKey 사용 및 FileAccessUrlPort 도입/조정.
매퍼 및 DTO/Response 업데이트
src/main/kotlin/com/weeth/domain/board/application/mapper/PostMapper.kt, .../BoardDetailResponse.kt, .../comment/mapper/CommentMapper.kt, .../dashboard/mapper/DashboardMapper.kt, .../DashboardMyInfoResponse.kt, .../user/mapper/UserMapper.kt
FileAccessUrlPort 주입, ClubMember 전달로 UserInfo 생성 변경(역할+프로필 이미지 해석 포함).
User 엔터티 및 Role 제거
src/main/kotlin/com/weeth/domain/user/domain/entity/User.kt, src/main/kotlin/com/weeth/domain/user/domain/enums/Role.kt
User에서 role·profileImageUrl 제거, 관련 factory/메서드 삭제 및 Role enum 제거.
JWT/인증 레이어 변경
.../JwtTokenExtractor.kt, .../JwtManageUseCase.kt, .../JwtTokenProvider.kt, .../RefreshTokenStorePort.kt, .../JwtAuthenticationProcessingFilter.kt, .../RedisRefreshTokenStoreAdapter.kt, .../AuthenticatedUser.kt, .../CurrentUserRole.kt
토큰/저장소/인증 객체에서 role 제거, 액세스 토큰 생성에서 role 미포함, 권한은 고정 ROLE_USER 사용, CurrentUserRole 어노테이션/리졸버 제거.
컨트롤러 시그니처·보안 설정 변경
src/main/kotlin/com/weeth/domain/board/presentation/BoardController.kt, .../PostController.kt, .../BoardAdminController.kt, .../UserController.kt, src/main/kotlin/com/weeth/global/config/SecurityConfig.kt, .../WebMvcConfig.kt
@CurrentUserRole 파라미터 제거, BoardAdminController의 @PreAuthorize 제거, 일부 엔드포인트 제거/Deprecated 표기, SecurityConfig에서 admin 경로 권한 완화, 리졸버 등록 제거.
리포지토리 확장
src/main/kotlin/com/weeth/domain/club/domain/repository/ClubMemberReader.kt, .../ClubMemberRepository.kt
findAllByClubIdAndUserIds(clubId, userIds) 추가로 다중 userId 기반 ClubMember 조회 지원.
MemberRole 기능 추가
src/main/kotlin/com/weeth/domain/club/domain/enums/MemberRole.kt
isAdminOrLead() 메서드 추가(ADMIN 또는 LEAD 판정).
Comment/CommentTree 흐름 변경
src/main/kotlin/com/weeth/domain/comment/application/usecase/query/GetCommentQueryService.kt, .../CommentMapper.kt
comment 매핑에 ClubMember 전달, memberMap을 재귀로 전파하여 author 정보 및 프로필 이미지 해석 처리.
User 서비스·로그인 변경
src/main/kotlin/com/weeth/domain/user/application/usecase/query/GetUserQueryService.kt, .../SocialLoginUseCase.kt
findMyProfile에 clubId 추가, findMyInfo 오버로드/Deprecated 추가, JWT 생성에서 role 제거.
테스트 및 픽스처 업데이트
src/test/... (다수)
Role 제거에 따른 테스트 수정: MemberRole 사용, ClubMember 픽스처/Reader 목 추가, FileAccessUrlPort 목 추가, 시그니처 변경 반영.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Controller
    participant UseCase
    participant ClubMemberPolicy
    participant Repository
    participant Domain

    Client->>Controller: POST /api/v4/clubs/{clubId}/boards/{boardId}/posts (요청)
    Controller->>UseCase: save(clubId, userId, postRequest)

    UseCase->>ClubMemberPolicy: getActiveMember(clubId, userId)
    ClubMemberPolicy->>Repository: findByClubIdAndUserId(clubId, userId)
    Repository-->>ClubMemberPolicy: ClubMember(memberRole=ADMIN|LEAD|USER)
    ClubMemberPolicy-->>UseCase: ClubMember

    UseCase->>Repository: getBoard(boardId)
    Repository-->>UseCase: Board(writePermission=MemberRole.ADMIN)

    UseCase->>Domain: canWriteBy(member.memberRole)
    Domain-->>UseCase: true/false (isAdminOrLead 허용)

    alt Can Write
        UseCase->>Repository: save(Post)
        Repository-->>UseCase: saved Post
        UseCase-->>Controller: PostResponse
        Controller-->>Client: 200 OK
    else Cannot Write
        UseCase-->>Controller: NotAuthorizedWriteException
        Controller-->>Client: 403 Forbidden
    end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~100+ minutes

Possibly related PRs

Suggested reviewers

  • soo0711

🐰 역할을 치우쳐 Club의 품으로
이미지는 열쇠로, 권한은 멤버로
User는 가벼워지고
JWT는 조용해지고
모두 Club 중심으로 모여든다! 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.00% 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
Title check ✅ Passed PR 제목이 주요 변경사항인 인증 정책 수정과 이미지 필드 수정을 명확하게 요약하고 있습니다.
Description check ✅ Passed PR 설명이 제목, Summary, Changes(What/Why/How), Reviewer 참고사항을 포함하여 템플릿의 주요 항목들을 충실히 작성했습니다.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/WTH-196-인증-정책-수정-Role

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

Caution

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

⚠️ Outside diff range comments (2)
src/main/kotlin/com/weeth/domain/board/application/usecase/command/ManagePostUseCase.kt (1)

87-102: ⚠️ Potential issue | 🟡 Minor

사용되지 않는 user 변수

delete 메서드에서 user를 조회하지만 실제로 사용되지 않습니다. 불필요한 DB 조회를 제거하세요.

🔧 수정 제안
     `@Transactional`
     fun delete(
         clubId: Long,
         postId: Long,
         userId: Long,
     ) {
         val member = clubMemberPolicy.getActiveMember(clubId, userId)
-        val user = userReader.getById(userId)
         val post = findPost(postId)
         if (post.board.club.id != clubId) throw PostNotFoundException()
         validateOwner(post, userId)
         validateWritePermission(post.board, member)

         markPostFilesDeleted(post.id)
         post.markDeleted()
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/kotlin/com/weeth/domain/board/application/usecase/command/ManagePostUseCase.kt`
around lines 87 - 102, The delete method in ManagePostUseCase is performing an
unnecessary DB lookup via userReader.getById(userId) and storing it in the
unused variable user; remove the call and the user variable from the delete
function (and any now-unused imports) so delete only gets member, post,
validates, marks files deleted, and marks the post deleted; update
ManagePostUseCase.delete and remove references to userReader.getById to
eliminate the redundant query.
src/main/kotlin/com/weeth/domain/user/application/usecase/query/GetUserQueryService.kt (1)

3-16: 🛠️ Refactor suggestion | 🟠 Major

User query에서 Club 도메인 정책을 직접 물지 않는 편이 좋겠습니다.

지금 구조는 GetUserQueryServiceClubMemberPolicy를 통해 club 쪽 조회/판정을 함께 끌어오고 있어서, user usecase 레이어가 다른 도메인 서비스에 직접 묶입니다. 여기서는 Reader/Port 경계로 active member를 조회하도록 맞춰 두는 편이 의존 방향과 테스트 경계가 덜 흔들립니다. As per coding guidelines, "Cross-domain reads must use Reader interfaces; cross-domain writes call Repository directly."

Also applies to: 20-37

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/kotlin/com/weeth/domain/user/application/usecase/query/GetUserQueryService.kt`
around lines 3 - 16, GetUserQueryService currently depends directly on
ClubMemberPolicy; replace that cross-domain dependency with a read-only port
(e.g., define a ClubReader or ClubMemberReader interface in the club domain) and
inject that reader into GetUserQueryService instead of ClubMemberPolicy, then
change calls that query active membership to use the new reader's method (the
methods you currently call on ClubMemberPolicy) so the user use-case stays
decoupled from club domain implementation and tests can mock the reader port.
🧹 Nitpick comments (10)
src/test/kotlin/com/weeth/domain/attendance/fixture/AttendanceTestFixture.kt (1)

21-21: 메서드 이름이 실제 동작과 불일치합니다.

createAdminUser는 이제 createActiveUser와 동일한 동작을 하므로, 메서드 이름이 오해를 불러일으킵니다. Role이 User 도메인에서 제거되고 ClubMember의 MemberRole로 관리되는 현재 구조에서는 이 메서드를 createActiveUserForAdmin으로 이름을 변경하거나, 테스트에서 직접 createActiveUser를 호출하도록 리팩토링하는 것이 좋습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/kotlin/com/weeth/domain/attendance/fixture/AttendanceTestFixture.kt`
at line 21, 메서드 이름 불일치: 현재 createAdminUser(name: String) 가
createActiveUser(name) 를 그대로 호출해 혼동을 초래하므로, 테스트 픽스처의 createAdminUser를 삭제하거나 이름을
명확히 변경하세요 — 예를 들어 createActiveUserForAdmin으로 리네임하거나 호출부를 직접 createActiveUser로
변경하고, 관련 테스트에서 ClubMember/MemberRole로 역할이 관리되는 현재 도메인 구조를 반영하도록 모든
호출부(createAdminUser 및 해당 테스트 코드)를 업데이트하여 혼동을 없애세요.
src/main/kotlin/com/weeth/domain/club/domain/entity/ClubMember.kt (1)

124-128: 메서드 이름이 현재 동작과 맞지 않습니다.

Line 124의 updateProfileImageUrl은 URL이 아니라 storageKey를 처리하므로, 호출자 입장에서 의미 오해가 생길 수 있습니다. 메서드명을 updateProfileImageStorageKey로 맞추는 것을 권장합니다.

✏️ 제안 diff
-    fun updateProfileImageUrl(storageKey: String?) {
+    fun updateProfileImageStorageKey(storageKey: String?) {
         val trimmed = storageKey?.trim()?.takeIf { it.isNotBlank() }
         require((trimmed?.length ?: 0) <= 500) { "프로필 이미지 storageKey는 500자 이하여야 합니다." }
         this.profileImageStorageKey = trimmed
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/kotlin/com/weeth/domain/club/domain/entity/ClubMember.kt` around
lines 124 - 128, The method name updateProfileImageUrl on class ClubMember is
misleading because it handles a storageKey; rename the function to
updateProfileImageStorageKey and update all call sites to use the new name,
ensuring the implementation still trims, validates length (<=500) and assigns to
profileImageStorageKey; optionally add a small deprecated wrapper named
updateProfileImageUrl that delegates to updateProfileImageStorageKey to preserve
backward compatibility while you migrate usages.
src/main/kotlin/com/weeth/domain/club/domain/service/ClubMemberPolicy.kt (1)

42-47: requireAdmin 메서드명과 실제 권한 조건이 불일치합니다.

현재는 ADMIN/LEAD 둘 다 허용하므로, 메서드명을 requireAdminOrLead처럼 실제 정책과 맞추는 편이 유지보수에 안전합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/kotlin/com/weeth/domain/club/domain/service/ClubMemberPolicy.kt`
around lines 42 - 47, The method requireAdmin()'s name doesn't match its
behavior (it allows ADMIN or LEAD via isAdminOrLead()); rename the function to
requireAdminOrLead to reflect the actual policy, keeping the implementation
(calls to getActiveMember(...) and the NotClubAdminException) unchanged, and
update all call sites to the new requireAdminOrLead identifier so usages compile
and intent is clear.
src/main/kotlin/com/weeth/domain/dashboard/application/usecase/query/GetDashboardQueryService.kt (1)

82-89: getValue 대신 안전한 조회로 예외 전파를 줄여주세요.

Line [88]의 memberMap.getValue(post.user.id)는 키가 없을 때 예외를 던집니다. 데이터 불일치가 생기면 게시글 목록 전체가 실패할 수 있어 null-safe 처리(또는 명시적 도메인 예외)로 바꾸는 편이 안전합니다.

🔧 제안 수정안
-        val memberMap = clubMemberReader.findAllByClubIdAndUserIds(clubId, authorIds).associateBy { it.user.id }
+        val memberMap =
+            if (authorIds.isEmpty()) emptyMap()
+            else clubMemberReader.findAllByClubIdAndUserIds(clubId, authorIds).associateBy { it.user.id }

         return posts.map { post ->
             dashboardMapper.toPostResponse(
                 post = post,
-                authorMember = memberMap.getValue(post.user.id),
+                authorMember =
+                    memberMap[post.user.id]
+                        ?: throw IllegalStateException("ClubMember not found for postId=${post.id}, userId=${post.user.id}, clubId=$clubId"),
                 files = filesByPostId[post.id] ?: emptyList(),
                 now = now,
             )
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/kotlin/com/weeth/domain/dashboard/application/usecase/query/GetDashboardQueryService.kt`
around lines 82 - 89, Replace the unsafe memberMap.getValue(post.user.id) lookup
with a null-safe access and handle missing members explicitly: inside
GetDashboardQueryService (where posts are mapped) use memberMap[post.user.id]
(or .get(post.user.id)) and then either pass a nullable authorMember to
dashboardMapper.toPostResponse or throw a clear domain exception (e.g.,
MemberNotFoundForPost) with post/user context before calling
dashboardMapper.toPostResponse; ensure the change is applied to the posts.map
block that currently builds post responses and that
clubMemberReader.findAllByClubIdAndUserIds remains the source used to build
memberMap.
src/main/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubMemberUsecase.kt (2)

46-47: fileAccessUrlPort 의존성이 사용되지 않음

fileAccessUrlPort가 주입되었지만, 이 파일 내에서 더 이상 사용되지 않습니다. Line 112에서 storageKey를 직접 사용하도록 변경되어 이 의존성이 불필요해 보입니다.

♻️ 사용되지 않는 의존성 제거 제안
 class ManageClubMemberUsecase(
     private val clubRepository: ClubRepository,
     private val clubMemberRepository: ClubMemberRepository,
     private val clubMemberCardinalRepository: ClubMemberCardinalRepository,
     private val cardinalReader: CardinalReader,
     private val sessionReader: SessionReader,
     private val attendanceRepository: AttendanceRepository,
     private val userReader: UserReader,
     private val clubMemberPolicy: ClubMemberPolicy,
     private val fileRepository: FileRepository,
-    private val fileAccessUrlPort: FileAccessUrlPort,
 ) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubMemberUsecase.kt`
around lines 46 - 47, The injected dependency fileAccessUrlPort in
ManageClubMemberUsecase is unused (you now use storageKey directly); remove the
unused constructor/property and any related imports to clean up the class:
delete the fileAccessUrlPort parameter from the constructor and any class field
named fileAccessUrlPort, update usages if any (ensure storageKey and
FileRepository usage remain unchanged), and run a build to remove leftover
references or unused import warnings.

112-112: 메서드명과 실제 동작 간 불일치

updateProfileImageUrl 메서드가 호출되지만, 이제 URL이 아닌 storageKey를 저장합니다. CDN 준비를 위한 변경이라면 메서드명도 updateProfileImageStorageKey로 변경하는 것이 일관성 있습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubMemberUsecase.kt`
at line 112, The call members.forEach {
it.updateProfileImageUrl(file.storageKey.value) } stores a storageKey, not a
URL, so rename the method to reflect the actual data (e.g.,
updateProfileImageStorageKey) and update all usages; specifically, in
ManageClubMemberUsecase.kt change the call to use the new name and refactor the
corresponding member/entity method (updateProfileImageUrl ->
updateProfileImageStorageKey) so its parameter and implementation store
storageKey.value, and update any callers/tests referencing updateProfileImageUrl
to the new method name.
src/main/kotlin/com/weeth/domain/club/application/mapper/ClubMapper.kt (1)

73-91: LGTM!

storageKey를 통한 이미지 URL 해석 패턴이 일관되게 적용되었습니다. resolveClubImage 헬퍼 메서드를 통해 중복 코드를 줄였습니다.

참고: toMemberProfileResponse의 Line 86에서도 resolveClubImage 헬퍼를 재사용할 수 있지만, 현재 구현도 정상 동작합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/kotlin/com/weeth/domain/club/application/mapper/ClubMapper.kt`
around lines 73 - 91, Refactor toMemberProfileResponse to reuse the
resolveClubImage helper instead of resolving profileImageStorageKey inline:
replace the expression that builds profileImageUrl from
member.profileImageStorageKey?.let { fileAccessUrlPort.resolve(it) } with a call
to resolveClubImage(member.profileImageStorageKey) so the logic centralizes in
resolveClubImage; update references to symbols to ensure
toMemberProfileResponse, resolveClubImage, and member.profileImageStorageKey are
used consistently.
src/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubMemberUseCaseTest.kt (1)

169-170: 메서드 이름을 필드명에 맞춰 변경하기

profileImageStorageKey 필드의 이름과 일관성을 위해 메서드 이름을 updateProfileImageUrl()에서 updateProfileImageStorageKey()로 변경하세요. 현재 메서드명은 필드명, 파라미터명(storageKey), 그리고 메서드 내부 에러 메시지와 모두 불일치합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubMemberUseCaseTest.kt`
around lines 169 - 170, Rename the method updateProfileImageUrl to
updateProfileImageStorageKey across the codebase to match the field
profileImageStorageKey: update the method declaration (e.g., in the entity/class
that defines updateProfileImageUrl), rename its parameter to storageKey if not
already, update internal error/messages to mention "profileImageStorageKey" and
"storageKey", and change all call sites such as ManageClubMemberUseCaseTest
where member1.updateProfileImageUrl(...) and member2.updateProfileImageUrl(...)
are invoked to use member1.updateProfileImageStorageKey(...) /
member2.updateProfileImageStorageKey(...).
src/test/kotlin/com/weeth/domain/board/application/usecase/query/GetPostQueryServiceTest.kt (1)

140-149: 작성자 ClubMember 누락 케이스를 한 번 더 묶어두면 좋겠습니다.

이번 변경은 author 정보를 clubMemberReader + memberMap 경로에서 꺼내오도록 바뀌어서, 탈퇴/비활성 작성자처럼 매핑이 비는 경우를 한 케이스라도 잡아두면 이후 회귀를 훨씬 빨리 확인할 수 있습니다.

Also applies to: 285-292

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/test/kotlin/com/weeth/domain/board/application/usecase/query/GetPostQueryServiceTest.kt`
around lines 140 - 149, Add a test setup that simulates the author ClubMember
being absent from the clubMemberReader mapping so the code path that looks up
author via clubMemberReader + memberMap is exercised for a missing/withdrawn
author; specifically, in the test around queryService.findPost(...) add an
additional stubbed case where
clubMemberReader.findAllByClubIdAndUserIds(actualClubId, any()) returns an empty
list (or omits the post.authorId) and then assert the behaviour (e.g.,
postMapper.toDetailResponse is still called with a null/absent member or the
expected fallback), adjusting the expected detail/mapper inputs accordingly so
the missing-author mapping is covered.
src/main/kotlin/com/weeth/domain/user/domain/entity/User.kt (1)

115-122: agreeTerms 구현이 약간 중복적이나 의도된 것으로 보임

require(termsAgreed && privacyAgreed) 검증 후 this.termsAgreed = true로 설정하는 패턴은 파라미터를 그대로 할당해도 동일한 결과입니다. PR 설명에 따르면 경고 제거 목적으로 보이므로 현재 구현도 괜찮습니다.

♻️ 선택적 간소화
     fun agreeTerms(
         termsAgreed: Boolean,
         privacyAgreed: Boolean,
     ) {
         require(termsAgreed && privacyAgreed) { "모든 약관에 동의해야 합니다." }
-        this.termsAgreed = true
-        this.privacyAgreed = true
+        this.termsAgreed = termsAgreed
+        this.privacyAgreed = privacyAgreed
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/kotlin/com/weeth/domain/user/domain/entity/User.kt` around lines 115
- 122, agreeTerms에서 require 검사 후 항상 true로 설정하는 중복을 제거하려면, 검증한 입력값을 그대로 할당하도록
변경하세요: User.agreeTerms 함수에서 require(termsAgreed && privacyAgreed) 검증은 유지하고
this.termsAgreed = true / this.privacyAgreed = true 대신 this.termsAgreed =
termsAgreed 및 this.privacyAgreed = privacyAgreed로 할당하여 의도를 명확히 하고 중복 경고를 제거하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/kotlin/com/weeth/domain/board/application/usecase/query/GetPostQueryService.kt`:
- Around line 113-118: The code uses memberMap.getValue(post.user.id) which can
throw an uncontrolled NoSuchElementException; replace this with an explicit
lookup and consistent error handling (e.g., val member = memberMap[post.user.id]
?: throw MemberNotFoundException("member not found: ${post.user.id}") ) and pass
that member to postMapper.toListResponse; apply the same change in the
searchPosts path so both places (buildMemberMap usage in GetPostQueryService and
the searchPosts method) handle missing members consistently.
- Around line 85-90: The code uses memberMap.getValue(post.user.id) which will
throw NoSuchElementException for posts authored by withdrawn users; change it to
safely retrieve the member (e.g., memberMap[post.user.id] ?:
createWithdrawnMemberRepresentation()) and pass that into
postMapper.toListResponse (or adjust toListResponse to accept a nullable
member), mirroring the fix used in findPost; reference buildMemberMap,
postMapper.toListResponse, fileExistsByPostId and the posts.map block to apply
the safe-lookup and fallback for withdrawn members.
- Around line 60-66: The current code calls memberMap.getValue(post.user.id)
which throws NoSuchElementException if the post author has no ClubMember entry
(e.g., withdrew); change GetPostQueryService to use memberMap[post.user.id]
(nullable) and handle the null by either providing a safe fallback ClubMember
placeholder (constructed via buildMemberMap or a new factory) or by modifying
postMapper.toDetailResponse to accept a nullable ClubMember? and handle display
for withdrawn users; update the call site in GetPostQueryService so it passes
the safe value (memberMap[post.user.id] ?: fallbackMember) or nullable member
accordingly instead of getValue(...).

In
`@src/main/kotlin/com/weeth/domain/club/application/dto/request/ClubUpdateRequest.kt`:
- Around line 20-27: Add length validation to the ClubUpdateRequest image
storage key fields: annotate profileImageStorageKey and
backgroundImageStorageKey with a validation constraint such as `@field`:Size(max =
500) (from javax.validation.constraints or jakarta.validation.constraints
depending on project) so the DTO enforces a 500-character max at the API
boundary and prevents overly long values reaching the service layer.

In `@src/main/kotlin/com/weeth/domain/club/domain/entity/Club.kt`:
- Around line 107-114: updateImageStorageKey와 엔티티 생성(create 경로)에서
profileImageStorageKey와 backgroundImageStorageKey를 그대로 대입하는 대신 ClubMember와 동일한
규칙(앞뒤 공백 trim, 빈 문자열은 null로 변환, 길이 최대 500자 검증)을 엔티티 내부에서 강제하세요; 구체적으로
updateImageStorageKey 함수와 생성자/팩토리(혹은 create 메서드)에서 입력값을 normalize(trim → if
blank then null)하고 null이 아닐 경우 length <= 500을 검증해 실패시 예외를 throw하거나 적절히 처리하도록
변경하여 엔티티 불변식을 보장합니다 (참조 심볼: updateImageStorageKey, profileImageStorageKey,
backgroundImageStorageKey, ClubMember의 동일 로직).

In
`@src/main/kotlin/com/weeth/domain/club/domain/repository/ClubMemberRepository.kt`:
- Around line 97-109: In GetDashboardQueryService, protect the call to
ClubMemberRepository.findAllByClubIdAndUserIds(clubId, authorIds) by checking if
authorIds is empty and returning an empty map immediately (same pattern used in
GetPostQueryService); this prevents passing an empty collection into the JPQL
"IN :userIds" clause which can fail on some DB dialects. Locate the method in
GetDashboardQueryService where authorIds is built (around the current call site)
and add a guard like "if (authorIds.isEmpty()) return emptyMap()" before
invoking findAllByClubIdAndUserIds; keep the
ClubMemberRepository.findAllByClubIdAndUserIds signature unchanged.

In
`@src/main/kotlin/com/weeth/domain/comment/application/usecase/query/GetCommentQueryService.kt`:
- Around line 64-65: The current use of memberMap.getValue(comment.user.id) in
GetCommentQueryService will throw NoSuchElementException if the author
ClubMember is missing; change this to safely handle absence by using a safe
lookup (e.g., memberMap[comment.user.id]) and then either (1) supply a
fallback/placeholder ClubMember (soft-deleted or unknown author) before calling
commentMapper.toCommentDto, or (2) pass a nullable author into toCommentDto and
let the mapper translate that into a domain-safe representation; ensure you do
not let getValue propagate an exception—convert missing author into a controlled
domain exception or fallback path so comment tree rendering never fails.

---

Outside diff comments:
In
`@src/main/kotlin/com/weeth/domain/board/application/usecase/command/ManagePostUseCase.kt`:
- Around line 87-102: The delete method in ManagePostUseCase is performing an
unnecessary DB lookup via userReader.getById(userId) and storing it in the
unused variable user; remove the call and the user variable from the delete
function (and any now-unused imports) so delete only gets member, post,
validates, marks files deleted, and marks the post deleted; update
ManagePostUseCase.delete and remove references to userReader.getById to
eliminate the redundant query.

In
`@src/main/kotlin/com/weeth/domain/user/application/usecase/query/GetUserQueryService.kt`:
- Around line 3-16: GetUserQueryService currently depends directly on
ClubMemberPolicy; replace that cross-domain dependency with a read-only port
(e.g., define a ClubReader or ClubMemberReader interface in the club domain) and
inject that reader into GetUserQueryService instead of ClubMemberPolicy, then
change calls that query active membership to use the new reader's method (the
methods you currently call on ClubMemberPolicy) so the user use-case stays
decoupled from club domain implementation and tests can mock the reader port.

---

Nitpick comments:
In `@src/main/kotlin/com/weeth/domain/club/application/mapper/ClubMapper.kt`:
- Around line 73-91: Refactor toMemberProfileResponse to reuse the
resolveClubImage helper instead of resolving profileImageStorageKey inline:
replace the expression that builds profileImageUrl from
member.profileImageStorageKey?.let { fileAccessUrlPort.resolve(it) } with a call
to resolveClubImage(member.profileImageStorageKey) so the logic centralizes in
resolveClubImage; update references to symbols to ensure
toMemberProfileResponse, resolveClubImage, and member.profileImageStorageKey are
used consistently.

In
`@src/main/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubMemberUsecase.kt`:
- Around line 46-47: The injected dependency fileAccessUrlPort in
ManageClubMemberUsecase is unused (you now use storageKey directly); remove the
unused constructor/property and any related imports to clean up the class:
delete the fileAccessUrlPort parameter from the constructor and any class field
named fileAccessUrlPort, update usages if any (ensure storageKey and
FileRepository usage remain unchanged), and run a build to remove leftover
references or unused import warnings.
- Line 112: The call members.forEach {
it.updateProfileImageUrl(file.storageKey.value) } stores a storageKey, not a
URL, so rename the method to reflect the actual data (e.g.,
updateProfileImageStorageKey) and update all usages; specifically, in
ManageClubMemberUsecase.kt change the call to use the new name and refactor the
corresponding member/entity method (updateProfileImageUrl ->
updateProfileImageStorageKey) so its parameter and implementation store
storageKey.value, and update any callers/tests referencing updateProfileImageUrl
to the new method name.

In `@src/main/kotlin/com/weeth/domain/club/domain/entity/ClubMember.kt`:
- Around line 124-128: The method name updateProfileImageUrl on class ClubMember
is misleading because it handles a storageKey; rename the function to
updateProfileImageStorageKey and update all call sites to use the new name,
ensuring the implementation still trims, validates length (<=500) and assigns to
profileImageStorageKey; optionally add a small deprecated wrapper named
updateProfileImageUrl that delegates to updateProfileImageStorageKey to preserve
backward compatibility while you migrate usages.

In `@src/main/kotlin/com/weeth/domain/club/domain/service/ClubMemberPolicy.kt`:
- Around line 42-47: The method requireAdmin()'s name doesn't match its behavior
(it allows ADMIN or LEAD via isAdminOrLead()); rename the function to
requireAdminOrLead to reflect the actual policy, keeping the implementation
(calls to getActiveMember(...) and the NotClubAdminException) unchanged, and
update all call sites to the new requireAdminOrLead identifier so usages compile
and intent is clear.

In
`@src/main/kotlin/com/weeth/domain/dashboard/application/usecase/query/GetDashboardQueryService.kt`:
- Around line 82-89: Replace the unsafe memberMap.getValue(post.user.id) lookup
with a null-safe access and handle missing members explicitly: inside
GetDashboardQueryService (where posts are mapped) use memberMap[post.user.id]
(or .get(post.user.id)) and then either pass a nullable authorMember to
dashboardMapper.toPostResponse or throw a clear domain exception (e.g.,
MemberNotFoundForPost) with post/user context before calling
dashboardMapper.toPostResponse; ensure the change is applied to the posts.map
block that currently builds post responses and that
clubMemberReader.findAllByClubIdAndUserIds remains the source used to build
memberMap.

In `@src/main/kotlin/com/weeth/domain/user/domain/entity/User.kt`:
- Around line 115-122: agreeTerms에서 require 검사 후 항상 true로 설정하는 중복을 제거하려면, 검증한
입력값을 그대로 할당하도록 변경하세요: User.agreeTerms 함수에서 require(termsAgreed && privacyAgreed)
검증은 유지하고 this.termsAgreed = true / this.privacyAgreed = true 대신 this.termsAgreed
= termsAgreed 및 this.privacyAgreed = privacyAgreed로 할당하여 의도를 명확히 하고 중복 경고를
제거하세요.

In
`@src/test/kotlin/com/weeth/domain/attendance/fixture/AttendanceTestFixture.kt`:
- Line 21: 메서드 이름 불일치: 현재 createAdminUser(name: String) 가 createActiveUser(name)
를 그대로 호출해 혼동을 초래하므로, 테스트 픽스처의 createAdminUser를 삭제하거나 이름을 명확히 변경하세요 — 예를 들어
createActiveUserForAdmin으로 리네임하거나 호출부를 직접 createActiveUser로 변경하고, 관련 테스트에서
ClubMember/MemberRole로 역할이 관리되는 현재 도메인 구조를 반영하도록 모든 호출부(createAdminUser 및 해당 테스트
코드)를 업데이트하여 혼동을 없애세요.

In
`@src/test/kotlin/com/weeth/domain/board/application/usecase/query/GetPostQueryServiceTest.kt`:
- Around line 140-149: Add a test setup that simulates the author ClubMember
being absent from the clubMemberReader mapping so the code path that looks up
author via clubMemberReader + memberMap is exercised for a missing/withdrawn
author; specifically, in the test around queryService.findPost(...) add an
additional stubbed case where
clubMemberReader.findAllByClubIdAndUserIds(actualClubId, any()) returns an empty
list (or omits the post.authorId) and then assert the behaviour (e.g.,
postMapper.toDetailResponse is still called with a null/absent member or the
expected fallback), adjusting the expected detail/mapper inputs accordingly so
the missing-author mapping is covered.

In
`@src/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubMemberUseCaseTest.kt`:
- Around line 169-170: Rename the method updateProfileImageUrl to
updateProfileImageStorageKey across the codebase to match the field
profileImageStorageKey: update the method declaration (e.g., in the entity/class
that defines updateProfileImageUrl), rename its parameter to storageKey if not
already, update internal error/messages to mention "profileImageStorageKey" and
"storageKey", and change all call sites such as ManageClubMemberUseCaseTest
where member1.updateProfileImageUrl(...) and member2.updateProfileImageUrl(...)
are invoked to use member1.updateProfileImageStorageKey(...) /
member2.updateProfileImageStorageKey(...).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 18aa210d-85e7-4fb0-8418-ce78bfeff1d8

📥 Commits

Reviewing files that changed from the base of the PR and between 1ce5373 and 09efe8d.

📒 Files selected for processing (76)
  • src/main/kotlin/com/weeth/domain/board/application/dto/request/CreateBoardRequest.kt
  • src/main/kotlin/com/weeth/domain/board/application/dto/request/UpdateBoardRequest.kt
  • src/main/kotlin/com/weeth/domain/board/application/dto/response/BoardDetailResponse.kt
  • src/main/kotlin/com/weeth/domain/board/application/mapper/PostMapper.kt
  • src/main/kotlin/com/weeth/domain/board/application/usecase/command/ManagePostUseCase.kt
  • src/main/kotlin/com/weeth/domain/board/application/usecase/query/GetBoardQueryService.kt
  • src/main/kotlin/com/weeth/domain/board/application/usecase/query/GetPostQueryService.kt
  • src/main/kotlin/com/weeth/domain/board/domain/entity/Board.kt
  • src/main/kotlin/com/weeth/domain/board/domain/vo/BoardConfig.kt
  • src/main/kotlin/com/weeth/domain/board/presentation/BoardAdminController.kt
  • src/main/kotlin/com/weeth/domain/board/presentation/BoardController.kt
  • src/main/kotlin/com/weeth/domain/board/presentation/PostController.kt
  • src/main/kotlin/com/weeth/domain/club/application/dto/request/ClubCreateRequest.kt
  • src/main/kotlin/com/weeth/domain/club/application/dto/request/ClubUpdateRequest.kt
  • src/main/kotlin/com/weeth/domain/club/application/dto/request/UpdateMemberBioRequest.kt
  • src/main/kotlin/com/weeth/domain/club/application/mapper/ClubMapper.kt
  • src/main/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubMemberUsecase.kt
  • src/main/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCase.kt
  • src/main/kotlin/com/weeth/domain/club/domain/entity/Club.kt
  • src/main/kotlin/com/weeth/domain/club/domain/entity/ClubMember.kt
  • src/main/kotlin/com/weeth/domain/club/domain/enums/MemberRole.kt
  • src/main/kotlin/com/weeth/domain/club/domain/repository/ClubMemberReader.kt
  • src/main/kotlin/com/weeth/domain/club/domain/repository/ClubMemberRepository.kt
  • src/main/kotlin/com/weeth/domain/club/domain/service/ClubMemberPolicy.kt
  • src/main/kotlin/com/weeth/domain/comment/application/mapper/CommentMapper.kt
  • src/main/kotlin/com/weeth/domain/comment/application/usecase/query/GetCommentQueryService.kt
  • src/main/kotlin/com/weeth/domain/dashboard/application/dto/response/DashboardMyInfoResponse.kt
  • src/main/kotlin/com/weeth/domain/dashboard/application/mapper/DashboardMapper.kt
  • src/main/kotlin/com/weeth/domain/dashboard/application/usecase/query/GetDashboardQueryService.kt
  • src/main/kotlin/com/weeth/domain/session/application/usecase/query/GetSessionQueryService.kt
  • src/main/kotlin/com/weeth/domain/user/application/dto/request/UserRoleUpdateRequest.kt
  • src/main/kotlin/com/weeth/domain/user/application/dto/response/UserInfo.kt
  • src/main/kotlin/com/weeth/domain/user/application/dto/response/UserProfileResponse.kt
  • src/main/kotlin/com/weeth/domain/user/application/dto/response/UserSummaryResponse.kt
  • src/main/kotlin/com/weeth/domain/user/application/mapper/UserMapper.kt
  • src/main/kotlin/com/weeth/domain/user/application/usecase/command/SocialLoginUseCase.kt
  • src/main/kotlin/com/weeth/domain/user/application/usecase/query/GetUserQueryService.kt
  • src/main/kotlin/com/weeth/domain/user/domain/entity/User.kt
  • src/main/kotlin/com/weeth/domain/user/domain/enums/Role.kt
  • src/main/kotlin/com/weeth/domain/user/presentation/UserController.kt
  • src/main/kotlin/com/weeth/global/auth/annotation/CurrentUserRole.kt
  • src/main/kotlin/com/weeth/global/auth/jwt/application/service/JwtTokenExtractor.kt
  • src/main/kotlin/com/weeth/global/auth/jwt/application/usecase/JwtManageUseCase.kt
  • src/main/kotlin/com/weeth/global/auth/jwt/domain/port/RefreshTokenStorePort.kt
  • src/main/kotlin/com/weeth/global/auth/jwt/domain/service/JwtTokenProvider.kt
  • src/main/kotlin/com/weeth/global/auth/jwt/filter/JwtAuthenticationProcessingFilter.kt
  • src/main/kotlin/com/weeth/global/auth/jwt/infrastructure/RedisRefreshTokenStoreAdapter.kt
  • src/main/kotlin/com/weeth/global/auth/model/AuthenticatedUser.kt
  • src/main/kotlin/com/weeth/global/auth/resolver/CurrentUserRoleArgumentResolver.kt
  • src/main/kotlin/com/weeth/global/config/SecurityConfig.kt
  • src/main/kotlin/com/weeth/global/config/WebMvcConfig.kt
  • src/test/kotlin/com/weeth/domain/attendance/fixture/AttendanceTestFixture.kt
  • src/test/kotlin/com/weeth/domain/board/application/mapper/PostMapperTest.kt
  • src/test/kotlin/com/weeth/domain/board/application/usecase/command/ManageBoardUseCaseTest.kt
  • src/test/kotlin/com/weeth/domain/board/application/usecase/command/ManagePostUseCaseTest.kt
  • src/test/kotlin/com/weeth/domain/board/application/usecase/query/GetBoardQueryServiceTest.kt
  • src/test/kotlin/com/weeth/domain/board/application/usecase/query/GetPostQueryServiceTest.kt
  • src/test/kotlin/com/weeth/domain/board/domain/converter/BoardConfigConverterTest.kt
  • src/test/kotlin/com/weeth/domain/board/domain/entity/BoardEntityTest.kt
  • src/test/kotlin/com/weeth/domain/board/fixture/BoardTestFixture.kt
  • src/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubMemberUseCaseTest.kt
  • src/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCaseTest.kt
  • src/test/kotlin/com/weeth/domain/club/application/usecase/query/GetClubMemberQueryServiceTest.kt
  • src/test/kotlin/com/weeth/domain/club/domain/entity/ClubTest.kt
  • src/test/kotlin/com/weeth/domain/comment/application/usecase/query/CommentQueryPerformanceTest.kt
  • src/test/kotlin/com/weeth/domain/comment/application/usecase/query/GetCommentQueryServiceTest.kt
  • src/test/kotlin/com/weeth/domain/dashboard/application/usecase/query/GetDashboardQueryServiceTest.kt
  • src/test/kotlin/com/weeth/domain/user/application/usecase/command/SocialLoginUseCaseTest.kt
  • src/test/kotlin/com/weeth/domain/user/domain/entity/UserTest.kt
  • src/test/kotlin/com/weeth/domain/user/fixture/UserTestFixture.kt
  • src/test/kotlin/com/weeth/global/auth/jwt/application/service/JwtTokenExtractorTest.kt
  • src/test/kotlin/com/weeth/global/auth/jwt/application/usecase/JwtManageUseCaseTest.kt
  • src/test/kotlin/com/weeth/global/auth/jwt/domain/service/JwtTokenProviderTest.kt
  • src/test/kotlin/com/weeth/global/auth/jwt/filter/JwtAuthenticationProcessingFilterTest.kt
  • src/test/kotlin/com/weeth/global/auth/jwt/infrastructure/store/RedisRefreshTokenStoreAdapterTest.kt
  • src/test/kotlin/com/weeth/global/auth/resolver/CurrentUserArgumentResolverTest.kt
💤 Files with no reviewable changes (14)
  • src/main/kotlin/com/weeth/domain/club/application/dto/request/UpdateMemberBioRequest.kt
  • src/main/kotlin/com/weeth/domain/user/domain/enums/Role.kt
  • src/main/kotlin/com/weeth/domain/board/presentation/BoardAdminController.kt
  • src/test/kotlin/com/weeth/domain/user/fixture/UserTestFixture.kt
  • src/test/kotlin/com/weeth/domain/user/domain/entity/UserTest.kt
  • src/main/kotlin/com/weeth/domain/dashboard/application/dto/response/DashboardMyInfoResponse.kt
  • src/main/kotlin/com/weeth/global/config/WebMvcConfig.kt
  • src/main/kotlin/com/weeth/global/auth/model/AuthenticatedUser.kt
  • src/main/kotlin/com/weeth/global/auth/jwt/application/service/JwtTokenExtractor.kt
  • src/main/kotlin/com/weeth/global/auth/jwt/domain/port/RefreshTokenStorePort.kt
  • src/main/kotlin/com/weeth/global/auth/resolver/CurrentUserRoleArgumentResolver.kt
  • src/main/kotlin/com/weeth/global/auth/jwt/infrastructure/RedisRefreshTokenStoreAdapter.kt
  • src/main/kotlin/com/weeth/global/auth/jwt/domain/service/JwtTokenProvider.kt
  • src/main/kotlin/com/weeth/global/auth/annotation/CurrentUserRole.kt

hyxklee added 4 commits March 23, 2026 15:25
# Conflicts:
#	src/main/kotlin/com/weeth/domain/club/application/dto/request/ClubUpdateRequest.kt
#	src/main/kotlin/com/weeth/domain/club/application/mapper/ClubMapper.kt
#	src/main/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCase.kt
#	src/main/kotlin/com/weeth/domain/club/domain/entity/Club.kt
#	src/main/kotlin/com/weeth/domain/user/domain/entity/User.kt
#	src/test/kotlin/com/weeth/domain/club/application/usecase/command/ManageClubUseCaseTest.kt
#	src/test/kotlin/com/weeth/domain/club/domain/entity/ClubTest.kt
Copy link
Copy Markdown
Collaborator

@soo0711 soo0711 left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!!

Comment on lines +209 to +210
club.clubContact.phoneNumber shouldBe "01099998888"
club.clubContact.phoneNumber shouldBe "010-9999-8888"
club.clubContact.phoneNumber shouldBe "01099998888"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

요기 중복된 검증이 있습니닷ㅅ

@hyxklee hyxklee merged commit 9af4bb2 into dev Mar 23, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🔨 Refactor 코드 구조 개선 및 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants