Skip to content

[WTH-251] post comment 작성자 타입을 club member로 변경#48

Merged
soo0711 merged 8 commits intodevfrom
refactor/WTH-251-Post-Comment-작성자-타입을-ClubMember로-변경
Apr 7, 2026

Hidden character warning

The head ref may contain hidden characters: "refactor/WTH-251-Post-Comment-\uc791\uc131\uc790-\ud0c0\uc785\uc744-ClubMember\ub85c-\ubcc0\uacbd"
Merged

[WTH-251] post comment 작성자 타입을 club member로 변경#48
soo0711 merged 8 commits intodevfrom
refactor/WTH-251-Post-Comment-작성자-타입을-ClubMember로-변경

Conversation

@soo0711
Copy link
Copy Markdown
Collaborator

@soo0711 soo0711 commented Apr 7, 2026

📌 Summary

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

post/comment 작성자 타입을 clubMember로 변경했습니다.

📝 Changes

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

What

post/comment user 필드 -> clubMember 필드로 수정

Why

user가 club을 탈퇴/삭제할 시 필터링이 안되는 문제 발생

How

user -> clubMember 필드 수정
useReader 제거 -> clubMember 참조
memberMap 제거 -> clubMember 참조
관련 테스트 수정

📸 Screenshots / Logs

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

스크린샷 2026-04-07 오후 2 00 41 스크린샷 2026-04-07 오후 2 03 13

💡 Reviewer 참고사항

리뷰에 참고할 내용을 작성해주세요.

로컬 스웨거에서 post/comment 확인했습니다.
머지 전에 마이그레이션이 필요합니다.

✅ Checklist

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

Summary by CodeRabbit

릴리스 노트

  • 리팩토링
    • 내부 데이터 모델 구조를 개선하여 시스템 안정성을 강화했습니다.
    • 게시글 및 댓글의 작성자 정보 처리 방식을 최적화했습니다.

참고: 이번 업데이트는 주로 내부 기술 개선으로, 사용자 인터페이스나 기능에는 변화가 없습니다.

@soo0711 soo0711 requested a review from hyxklee April 7, 2026 05:11
@soo0711 soo0711 self-assigned this Apr 7, 2026
@soo0711 soo0711 added the 🔨 Refactor 코드 구조 개선 및 리팩토링 label Apr 7, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 7, 2026

📝 Walkthrough

Walkthrough

Post와 Comment 엔티티가 User 대신 ClubMember와 연결되도록 변경되었습니다. 이에 따라 PostMapper, CommentMapper 등의 매퍼에서 authorMember 매개변수가 제거되었으며, 작성자 정보는 post.clubMember 또는 comment.clubMember에서 직접 파생됩니다. 쿼리 서비스의 memberMap 빌드 로직도 함께 제거되었습니다.

Changes

Cohort / File(s) Summary
도메인 엔티티
src/main/kotlin/com/weeth/domain/board/domain/entity/Post.kt, src/main/kotlin/com/weeth/domain/comment/domain/entity/Comment.kt
user 필드를 clubMember로 변경하고 join column을 user_id에서 club_member_id로 수정. isOwnedBy() 메서드를 clubMember.user.id 기반으로 업데이트. 팩토리 메서드 시그니처도 함께 변경됨.
포스트 매퍼 및 쿼리 서비스
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/GetPostQueryService.kt
PostMapper의 toDetailResponse/toListResponse에서 authorMember 매개변수 제거. ManagePostUseCase에서 UserReader 의존성 제거 및 clubMember 기반 생성 로직으로 변경. GetPostQueryService의 memberMap 빌드 로직 제거.
댓글 매퍼 및 쿼리 서비스
src/main/kotlin/com/weeth/domain/comment/application/mapper/CommentMapper.kt, src/main/kotlin/com/weeth/domain/comment/application/usecase/command/ManageCommentUseCase.kt, src/main/kotlin/com/weeth/domain/comment/application/usecase/query/GetCommentQueryService.kt
CommentMapper에서 authorMember 매개변수 제거. ManageCommentUseCase에서 UserReader를 ClubMemberPolicy로 변경. GetCommentQueryService의 toCommentTreeResponses에서 memberMap 매개변수 제거.
리포지토리 및 Entity Graph
src/main/kotlin/com/weeth/domain/board/domain/repository/PostRepository.kt, src/main/kotlin/com/weeth/domain/comment/domain/repository/CommentRepository.kt
@EntityGraph attributePaths를 user 대신 clubMember 및 clubMember.user로 변경. PostRepository의 여러 쿼리 메서드 및 CommentRepository의 findByIdAndPostId, findAllByPostId 업데이트.
대시보드 매퍼 및 쿼리 서비스
src/main/kotlin/com/weeth/domain/dashboard/application/mapper/DashboardMapper.kt, src/main/kotlin/com/weeth/domain/dashboard/application/usecase/query/GetDashboardQueryService.kt
DashboardMapper.toPostResponse에서 authorMember 매개변수 제거. GetDashboardQueryService의 memberMap 빌드 로직 및 buildMemberMap 헬퍼 제거.
포스트 관련 테스트
src/test/kotlin/com/weeth/domain/board/application/mapper/PostMapperTest.kt, src/test/kotlin/com/weeth/domain/board/application/usecase/command/ManagePostUseCaseTest.kt, src/test/kotlin/com/weeth/domain/board/application/usecase/query/GetPostQueryServiceTest.kt, src/test/kotlin/com/weeth/domain/board/fixture/PostTestFixture.kt
PostTestFixture에서 user 매개변수를 clubMember로 변경. 테스트 setup에서 post.clubMember 기반 모킹으로 조정. UserReader 의존성 제거 및 ClubMember 기반 fixture 사용.
댓글 관련 테스트
src/test/kotlin/com/weeth/domain/comment/application/usecase/command/ManageCommentUseCaseTest.kt, src/test/kotlin/com/weeth/domain/comment/application/usecase/command/CommentConcurrencyTest.kt, src/test/kotlin/com/weeth/domain/comment/application/usecase/query/GetCommentQueryServiceTest.kt, src/test/kotlin/com/weeth/domain/comment/application/usecase/query/CommentQueryPerformanceTest.kt, src/test/kotlin/com/weeth/domain/comment/domain/entity/CommentEntityTest.kt, src/test/kotlin/com/weeth/domain/comment/fixture/CommentTestFixture.kt
CommentTestFixture에서 user를 clubMember로 변경. 모든 Comment 생성을 clubMember 기반으로 수정. memberMap 관련 test setup 제거. UserReader 모킹 제거 및 ClubMemberPolicy 사용.
대시보드 테스트
src/test/kotlin/com/weeth/domain/dashboard/application/usecase/query/GetDashboardQueryServiceTest.kt
PostTestFixture 생성에서 clubMember 사용. clubMemberReader 모킹 기대값 제거.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Possibly related PRs

Suggested reviewers

  • hyxklee

Poem

🐰 ClubMember의 품에 안긴
Post와 Comment들이 새 집을 찾았네요
User를 떠나 memberMap도 빠져나고
더 깔끔한 관계의 춤을 추며
엔티티들이 웃음 짓는구나! 🎉

🚥 Pre-merge checks | ✅ 2 | ❌ 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 (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항인 'post/comment 작성자 타입을 clubMember로 변경'을 명확히 설명하고 있습니다.
Description check ✅ Passed PR 설명은 요구 사항을 대부분 충족하지만 일부 섹션이 불완전합니다.

✏️ 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-251-Post-Comment-작성자-타입을-ClubMember로-변경

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.

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/domain/repository/PostRepository.kt (1)

69-83: ⚠️ Potential issue | 🟡 Minor

findByIdWithLockclubMember EntityGraph가 누락되었습니다.

다른 조회 메서드들(findAllByBoardIds, findByBoardId, findById 등)은 ["clubMember", "clubMember.user"]를 포함하도록 설정되어 있지만, findByIdWithLock["board", "board.club"]만 포함합니다.

현재 TogglePostLikeUseCase에서는 post.belongsToClub()post.board.isAccessibleBy()만 호출하므로 문제가 없습니다. 그러나 향후 코드가 post.isOwnedBy() 또는 post.clubMember에 접근하면 LazyInitializationException이 발생할 수 있습니다.

🛠️ EntityGraph에 clubMember 추가
-    `@EntityGraph`(attributePaths = ["board", "board.club"])
+    `@EntityGraph`(attributePaths = ["board", "board.club", "clubMember", "clubMember.user"])
     `@Lock`(LockModeType.PESSIMISTIC_WRITE)
     `@QueryHints`(QueryHint(name = "jakarta.persistence.lock.timeout", value = "2000"))
🤖 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/domain/repository/PostRepository.kt`
around lines 69 - 83, The EntityGraph on findByIdWithLock currently only loads
["board", "board.club"] which can cause LazyInitializationException if callers
later access post.clubMember or call post.isOwnedBy(); update the EntityGraph
attributePaths of findByIdWithLock to include "clubMember" and "clubMember.user"
(so it matches other methods like findAllByBoardIds/findByBoardId/findById)
while keeping the existing pessimistic lock and query hints intact.
src/test/kotlin/com/weeth/domain/comment/application/usecase/command/CommentConcurrencyTest.kt (1)

301-305: ⚠️ Potential issue | 🟠 Major

Atomic 경로가 userId를 무시해 벤치마크 비교가 왜곡됩니다.

Line 313에서 모든 요청의 작성자를 post.clubMember로 고정하면, pessimistic 경로(요청 사용자 기준)와 동등 비교가 깨집니다. 성능 수치가 과대/과소 측정될 수 있고 권한·작성자 경로 회귀도 가려집니다.

제안 패치
                 transactionTemplate.executeWithoutResult {
                     val post = entityManager.getReference(Post::class.java, postId)
-                    // 벤치마크 전용: commentCount 동시성 측정이 목적이므로 userId 대신 post 작성자의 ClubMember를 재사용
-                    val clubMember = post.clubMember
+                    val clubMember =
+                        entityManager
+                            .createQuery(
+                                "select cm from ClubMember cm where cm.club.id = :clubId and cm.user.id = :userId",
+                                ClubMember::class.java,
+                            )
+                            .setParameter("clubId", post.board.club.id)
+                            .setParameter("userId", userId)
+                            .resultList
+                            .firstOrNull()
+                            ?: throw IllegalArgumentException("clubMember not found for userId=$userId")

Also applies to: 313-326

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

In
`@src/test/kotlin/com/weeth/domain/comment/application/usecase/command/CommentConcurrencyTest.kt`
around lines 301 - 305, The atomic path in savePostCommentWithAtomicIncrement
currently hardcodes the author to post.clubMember (lines around 313-326), which
ignores the userId parameter and skews benchmark comparison with the pessimistic
path; change the atomic-path code in savePostCommentWithAtomicIncrement to use
the incoming userId (and any derived user-related lookups) as the
requester/author instead of post.clubMember so both atomic and pessimistic flows
run with the same request user; update any variables or calls within that block
that set the creator/author or perform permission checks to derive from userId
to keep test conditions equivalent.
🧹 Nitpick comments (3)
src/test/kotlin/com/weeth/domain/board/application/mapper/PostMapperTest.kt (1)

49-56: 작성자 매핑 단언을 추가해 회귀를 막아주세요.

이번 변경의 핵심이 작성자 소스를 clubMember로 바꾼 것인데, 현재 테스트는 response.author를 검증하지 않아 해당 경로 회귀를 놓칠 수 있습니다.

제안 패치
                 response.id shouldBe 1L
+                response.author.id shouldBe 1L
+                response.author.name shouldBe "테스터"
+                response.author.role shouldBe MemberRole.USER
                 response.hasFile shouldBe true
                 response.isNew shouldBe true
@@
                 response.id shouldBe 1L
+                response.author.id shouldBe 1L
+                response.author.name shouldBe "테스터"
+                response.author.role shouldBe MemberRole.USER
                 response.commentCount shouldBe 2
                 response.comments.size shouldBe 1
                 response.fileUrls.size shouldBe 1

Also applies to: 59-91

🤖 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/mapper/PostMapperTest.kt`
around lines 49 - 56, The test in PostMapperTest for toListResponse currently
omits asserting the mapped author, risking regressions when the source was
changed to clubMember; update the spec block(s) (the it() cases invoking
mapper.toListResponse) to assert response.author matches the expected author
info derived from the post/clubMember fixture (e.g., compare expected
name/id/clubMember-related fields), ensuring the mapping from clubMember ->
response.author is validated alongside id, hasFile, and isNew.
src/test/kotlin/com/weeth/domain/comment/application/usecase/query/CommentQueryPerformanceTest.kt (1)

88-90: 사용하지 않는 SetupResult 래퍼는 제거해도 됩니다.

현재 runComparison에서 setupData(...) 반환값을 사용하지 않아 타입/반환 객체가 노이즈가 됩니다.

제안 패치
-        data class SetupResult(
-            val commentIds: List<Long>,
-        )
-
         fun setupData(
             rootCount: Int,
             childrenPerRoot: Int,
             filesPerComment: Int,
-        ): SetupResult {
+        ) {
@@
-            return SetupResult(commentIds)
+            // no-op
         }

Also applies to: 144-145, 154-159

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

In
`@src/test/kotlin/com/weeth/domain/comment/application/usecase/query/CommentQueryPerformanceTest.kt`
around lines 88 - 90, The SetupResult data class is unused noise—remove the
SetupResult declaration and update any references so setupData(...) returns the
raw value(s) needed directly; specifically delete the data class SetupResult and
change runComparison calls (and any other usages around setupData, e.g., in
CommentQueryPerformanceTest's setupData invocation) to accept/handle the direct
returned type instead of wrapping/unwrapping SetupResult. Ensure tests compile
by adjusting function signatures (setupData) and any destructuring or
assignments that expected SetupResult.
src/test/kotlin/com/weeth/domain/comment/application/usecase/command/ManageCommentUseCaseTest.kt (1)

37-38: ClubMemberPolicy를 relaxed로 두면 권한 검증 경로 회귀를 놓치기 쉽습니다.

Line 37/Line 53 기준으로 현재는 getActiveMember(...) 호출 누락·인자 오류가 있어도 테스트가 통과할 수 있습니다. 이 의존성은 명시적으로 stubbing/verify 해서 테스트 의도를 고정하는 편이 안전합니다.

Also applies to: 53-58

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

In
`@src/test/kotlin/com/weeth/domain/comment/application/usecase/command/ManageCommentUseCaseTest.kt`
around lines 37 - 38, 현재 테스트에서 mockk<ClubMemberPolicy>(relaxed = true) 사용으로
getActiveMember(...) 호출 누락이나 인자 오류가 무시될 수 있으므로 relaxed 플래그를 제거하고
ClubMemberPolicy의 getActiveMember 메서드를 명시적으로 stub 및 검증하세요: mock 인스턴스 생성 시
relaxed = true 를 빼고 every { clubMemberPolicy.getActiveMember(expectedMemberId,
any()) } returns expectedMember (또는 적절한 값) 처럼 필요한 입력에 대해 명시적 반환을 설정한 뒤, 테스트 끝에
verify { clubMemberPolicy.getActiveMember(expectedMemberId, any()) } 를 추가해 실제
호출과 인자를 검사하도록 수정하고 동일한 패턴으로 다른 테스트용 relaxed mock들(파일 내 다른 relaxed mock 생성 지점)도
동일하게 명시적 stubbing 및 verify로 교체하세요.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/main/kotlin/com/weeth/domain/board/domain/repository/PostRepository.kt`:
- Around line 69-83: The EntityGraph on findByIdWithLock currently only loads
["board", "board.club"] which can cause LazyInitializationException if callers
later access post.clubMember or call post.isOwnedBy(); update the EntityGraph
attributePaths of findByIdWithLock to include "clubMember" and "clubMember.user"
(so it matches other methods like findAllByBoardIds/findByBoardId/findById)
while keeping the existing pessimistic lock and query hints intact.

In
`@src/test/kotlin/com/weeth/domain/comment/application/usecase/command/CommentConcurrencyTest.kt`:
- Around line 301-305: The atomic path in savePostCommentWithAtomicIncrement
currently hardcodes the author to post.clubMember (lines around 313-326), which
ignores the userId parameter and skews benchmark comparison with the pessimistic
path; change the atomic-path code in savePostCommentWithAtomicIncrement to use
the incoming userId (and any derived user-related lookups) as the
requester/author instead of post.clubMember so both atomic and pessimistic flows
run with the same request user; update any variables or calls within that block
that set the creator/author or perform permission checks to derive from userId
to keep test conditions equivalent.

---

Nitpick comments:
In `@src/test/kotlin/com/weeth/domain/board/application/mapper/PostMapperTest.kt`:
- Around line 49-56: The test in PostMapperTest for toListResponse currently
omits asserting the mapped author, risking regressions when the source was
changed to clubMember; update the spec block(s) (the it() cases invoking
mapper.toListResponse) to assert response.author matches the expected author
info derived from the post/clubMember fixture (e.g., compare expected
name/id/clubMember-related fields), ensuring the mapping from clubMember ->
response.author is validated alongside id, hasFile, and isNew.

In
`@src/test/kotlin/com/weeth/domain/comment/application/usecase/command/ManageCommentUseCaseTest.kt`:
- Around line 37-38: 현재 테스트에서 mockk<ClubMemberPolicy>(relaxed = true) 사용으로
getActiveMember(...) 호출 누락이나 인자 오류가 무시될 수 있으므로 relaxed 플래그를 제거하고
ClubMemberPolicy의 getActiveMember 메서드를 명시적으로 stub 및 검증하세요: mock 인스턴스 생성 시
relaxed = true 를 빼고 every { clubMemberPolicy.getActiveMember(expectedMemberId,
any()) } returns expectedMember (또는 적절한 값) 처럼 필요한 입력에 대해 명시적 반환을 설정한 뒤, 테스트 끝에
verify { clubMemberPolicy.getActiveMember(expectedMemberId, any()) } 를 추가해 실제
호출과 인자를 검사하도록 수정하고 동일한 패턴으로 다른 테스트용 relaxed mock들(파일 내 다른 relaxed mock 생성 지점)도
동일하게 명시적 stubbing 및 verify로 교체하세요.

In
`@src/test/kotlin/com/weeth/domain/comment/application/usecase/query/CommentQueryPerformanceTest.kt`:
- Around line 88-90: The SetupResult data class is unused noise—remove the
SetupResult declaration and update any references so setupData(...) returns the
raw value(s) needed directly; specifically delete the data class SetupResult and
change runComparison calls (and any other usages around setupData, e.g., in
CommentQueryPerformanceTest's setupData invocation) to accept/handle the direct
returned type instead of wrapping/unwrapping SetupResult. Ensure tests compile
by adjusting function signatures (setupData) and any destructuring or
assignments that expected SetupResult.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a9a18a85-ba72-442f-aae3-dde3f59a658c

📥 Commits

Reviewing files that changed from the base of the PR and between 8030bdc and ead8e1f.

📒 Files selected for processing (23)
  • 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/GetPostQueryService.kt
  • src/main/kotlin/com/weeth/domain/board/domain/entity/Post.kt
  • src/main/kotlin/com/weeth/domain/board/domain/repository/PostRepository.kt
  • src/main/kotlin/com/weeth/domain/comment/application/mapper/CommentMapper.kt
  • src/main/kotlin/com/weeth/domain/comment/application/usecase/command/ManageCommentUseCase.kt
  • src/main/kotlin/com/weeth/domain/comment/application/usecase/query/GetCommentQueryService.kt
  • src/main/kotlin/com/weeth/domain/comment/domain/entity/Comment.kt
  • src/main/kotlin/com/weeth/domain/comment/domain/repository/CommentRepository.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/test/kotlin/com/weeth/domain/board/application/mapper/PostMapperTest.kt
  • src/test/kotlin/com/weeth/domain/board/application/usecase/command/ManagePostUseCaseTest.kt
  • src/test/kotlin/com/weeth/domain/board/application/usecase/query/GetPostQueryServiceTest.kt
  • src/test/kotlin/com/weeth/domain/board/fixture/PostTestFixture.kt
  • src/test/kotlin/com/weeth/domain/comment/application/usecase/command/CommentConcurrencyTest.kt
  • src/test/kotlin/com/weeth/domain/comment/application/usecase/command/ManageCommentUseCaseTest.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/comment/domain/entity/CommentEntityTest.kt
  • src/test/kotlin/com/weeth/domain/comment/fixture/CommentTestFixture.kt
  • src/test/kotlin/com/weeth/domain/dashboard/application/usecase/query/GetDashboardQueryServiceTest.kt
💤 Files with no reviewable changes (1)
  • src/main/kotlin/com/weeth/domain/dashboard/application/usecase/query/GetDashboardQueryService.kt

Copy link
Copy Markdown
Contributor

@hyxklee hyxklee left a comment

Choose a reason for hiding this comment

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

고생하셨습니다! 머지하면서 디비 마이그레이션까지 부탁드릴게요!

@soo0711 soo0711 merged commit d94f5c7 into dev Apr 7, 2026
2 checks passed
@soo0711 soo0711 deleted the refactor/WTH-251-Post-Comment-작성자-타입을-ClubMember로-변경 branch April 7, 2026 12:04
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