Skip to content

refact: refactor all user list - #41

Merged
Junkov0 merged 1 commit into
developfrom
feature/user-find-refactoring
Jul 24, 2026
Merged

Junkov0 merged 1 commit into
developfrom
feature/user-find-refactoring

Conversation

@jaejo

@jaejo jaejo commented Jul 24, 2026

Copy link
Copy Markdown
Collaborator

작업 내용

전체 사용자 목록 프론트엔드 수정

변경 사항

체크리스트

  • 테스트 코드 작성 완료
  • 리뷰어 지정 완료

참고 사항

관련 이슈

Summary by CodeRabbit

  • New Features
    • 슈퍼관리자 사용자 목록에 검색, 역할·공간 필터, 정렬, 무한 스크롤을 추가했습니다.
    • 사용자 목록에 소속 공간, 역할, 정지 상태, 가입·수정·탈퇴 일시 정보를 표시합니다.
    • 사용자 수 통계가 필터 조건에 따라 정확히 표시됩니다.
  • Bug Fixes
    • 사용자 검색의 대소문자 구분을 개선했습니다.
    • 검색어의 + 문자가 올바르게 처리됩니다.
    • 커서 기반 페이지 이동의 안정성을 개선했습니다.
  • Style
    • Pretendard 글꼴과 새 페이지 제목을 적용했습니다.

@jaejo
jaejo requested review from Junkov0 and idktomorrow July 24, 2026 03:46
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

사용자 응답 필드와 검색 조건이 확장되었으며, 백엔드 커서 검색과 슈퍼관리자 사용자 목록의 필터·정렬·무한 스크롤이 연동되었습니다. OAuth2·JWT 인증은 변경된 isBanned 및 빌더 기반 응답 생성을 사용합니다.

Changes

사용자 관리 흐름

Layer / File(s) Summary
사용자 데이터 계약 확장
momogo-core/src/main/java/com/momogo/core/domain/user/dto/..., momogo-core/src/main/java/com/momogo/core/domain/user/mapper/UserMapper.java, momogo-frontend/src/types/user.ts
UserResponseisBanned, 시간·공간 필드가 추가되고, 사용자 검색 요청과 커서 응답 타입이 확장되었습니다.
커서 검색 및 정렬 처리
momogo-core/src/main/java/com/momogo/core/domain/user/repository/UserRepositoryImpl.java, momogo-core/src/main/java/com/momogo/core/domain/user/service/UserServiceImpl.java
공간명·역할 필터, 대소문자 무시 검색, 마이크로초 커서, 정렬별 deletedAt 조건이 적용되었습니다.
인증 사용자 응답 생성
momogo-api/src/main/java/com/momogo/api/auth/...
OAuth2·JWT 경로의 UserResponse 생성이 빌더 방식으로 변경되고 계정 잠금 판정이 isBanned를 참조합니다.
슈퍼관리자 사용자 목록 UI
momogo-frontend/src/pages/DashboardPage.tsx, momogo-frontend/src/services/api.ts, momogo-frontend/src/styles/*, momogo-frontend/index.html
사용자 목록에 검색·정렬·역할 필터, 총계, 무한 스크롤, 공간·상태·날짜 컬럼과 isBanned 토글이 추가되었습니다. URL 파라미터의 + 인코딩과 기본 글꼴·페이지 스타일도 갱신되었습니다.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant 관리자
  participant DashboardPage
  participant request
  participant UserServiceImpl
  participant UserRepositoryImpl

  관리자->>DashboardPage: 검색·정렬 조건 입력
  DashboardPage->>request: 쿼리 파라미터 직렬화
  request->>UserServiceImpl: 커서 기반 사용자 조회 요청
  UserServiceImpl->>UserRepositoryImpl: UserSearchCondition 전달
  UserRepositoryImpl-->>UserServiceImpl: 사용자 데이터·총계·다음 커서 반환
  UserServiceImpl-->>DashboardPage: UserCursorResponse 반환
  DashboardPage-->>관리자: 사용자 테이블과 총계 렌더링
Loading

Possibly related PRs

Suggested reviewers: idktomorrow, junkov0

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive 제목은 사용자 목록 리팩터링과 관련은 있지만, "refact"와 "all user list"가 다소 포괄적이라 변경 핵심을 충분히 드러내지 못합니다. 사용자 목록의 페이징·필터링·무한스크롤 개선처럼 핵심 변경을 더 구체적으로 반영한 제목으로 바꿔주세요.
✅ Passed checks (3 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.
✨ 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 feature/user-find-refactoring

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.

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

🧹 Nitpick comments (1)
momogo-frontend/src/pages/DashboardPage.tsx (1)

502-514: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

[개선 제안] 추가 로딩 가드가 중복 요청을 완전히 막지 못합니다.

무한 스크롤 트리거가 세 곳(IntersectionObserver, scroll 리스너, setTimeout)에서 동시에 발생할 수 있습니다. loadNextUserPageuserLoadingMoreRef.current로 방어하지만, 이 ref는 렌더 시점(Line 102)에만 갱신됩니다. 즉 setUserLoadingMore(true)(Line 513) 후 리렌더가 반영되기 전까지는 ref가 여전히 false라, 짧은 시간에 여러 트리거가 가드를 통과해 같은 페이지를 중복 요청할 수 있습니다. 지금은 existingIds 중복 제거(Line 561-563) 덕분에 화면은 깨지지 않지만, 불필요한 네트워크 호출이 발생합니다.

또한 Line 502의 가드는 상태값 userLoadingMore를 읽는데, loadNextUserPageuseCallback([])로 첫 렌더의 loadSuperAdminUsers를 캡처하므로 이 값은 항상 초기값(false)으로 고정되어 페이징 경로에서는 사실상 무력화됩니다.

로딩 시작 시점에 ref를 동기적으로 세팅하고, 가드도 상태 대신 ref를 사용하는 것을 권장합니다.

♻️ 제안 수정
-    if (cursorVal && userLoadingMore) return;
+    if (cursorVal && userLoadingMoreRef.current) return;
     try {
       if (!cursorVal) {
         userCursorRef.current = null;
         userNextIdAfterRef.current = null;
         userHasNextRef.current = false;
         setUserCursor(null);
         setUserNextIdAfter(null);
         setUserHasNext(false);
         setAllUsers([]);
       } else {
+        userLoadingMoreRef.current = true; // 리렌더 전 동기 가드
         setUserLoadingMore(true);
       }
🤖 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 `@momogo-frontend/src/pages/DashboardPage.tsx` around lines 502 - 514, Update
loadNextUserPage and its loading guard to use userLoadingMoreRef.current instead
of the stale userLoadingMore state, and set the ref synchronously when
pagination begins before triggering the state update or request. Ensure every
trigger path—IntersectionObserver, scroll, and setTimeout—returns immediately
while the ref indicates an active load, then keep the ref synchronized when
loading completes or resets.
🤖 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 `@momogo-frontend/src/services/api.ts`:
- Around line 144-150: Remove the global plus-to-%2B replacement from the
query-string construction in the URL parameter flow. Keep URLSearchParams
serialization unchanged so spaces remain encoded as + while literal plus signs
retain their existing %2B encoding.

In `@momogo-frontend/src/styles/theme.css`:
- Line 45: Update the font-family declaration to remove quotes from the
single-token Pretendard and Inter font names, while preserving the remaining
fallback fonts and their order.

---

Nitpick comments:
In `@momogo-frontend/src/pages/DashboardPage.tsx`:
- Around line 502-514: Update loadNextUserPage and its loading guard to use
userLoadingMoreRef.current instead of the stale userLoadingMore state, and set
the ref synchronously when pagination begins before triggering the state update
or request. Ensure every trigger path—IntersectionObserver, scroll, and
setTimeout—returns immediately while the ref indicates an active load, then keep
the ref synchronized when loading completes or resets.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 024f8959-8e48-4c17-a053-af4bb6459df1

📥 Commits

Reviewing files that changed from the base of the PR and between a488d39 and a074e0b.

📒 Files selected for processing (14)
  • momogo-api/src/main/java/com/momogo/api/auth/details/MoMoGoUserDetails.java
  • momogo-api/src/main/java/com/momogo/api/auth/details/OAuth2UserDetailsService.java
  • momogo-api/src/main/java/com/momogo/api/auth/jwt/JwtTokenProvider.java
  • momogo-core/src/main/java/com/momogo/core/domain/user/dto/UserSearchCondition.java
  • momogo-core/src/main/java/com/momogo/core/domain/user/dto/request/UserPageRequest.java
  • momogo-core/src/main/java/com/momogo/core/domain/user/dto/response/UserResponse.java
  • momogo-core/src/main/java/com/momogo/core/domain/user/mapper/UserMapper.java
  • momogo-core/src/main/java/com/momogo/core/domain/user/repository/UserRepositoryImpl.java
  • momogo-core/src/main/java/com/momogo/core/domain/user/service/UserServiceImpl.java
  • momogo-frontend/index.html
  • momogo-frontend/src/pages/DashboardPage.tsx
  • momogo-frontend/src/services/api.ts
  • momogo-frontend/src/styles/theme.css
  • momogo-frontend/src/types/user.ts

Comment on lines +144 to 150
// URL 파라미터 조립 (ISO-8601 커서 등 + 기호가 포함된 파라미터의 %2B 인코딩 보장)
let url = resolvedPath;
if (params) {
const searchParams = new URLSearchParams(params);
url += `?${searchParams.toString()}`;
const queryString = searchParams.toString().replace(/\+/g, '%2B');
url += `?${queryString}`;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
node -e "const p=new URLSearchParams({nameLike:'김 철수',cursor:'2024-01-01T00:00:00+09:00'}); const s=p.toString(); console.log('raw:', s); console.log('replaced:', s.replace(/\+/g,'%2B')); console.log('decoded nameLike:', new URLSearchParams(s.replace(/\+/g,'%2B')).get('nameLike'));"

Repository: MoMoGo-QuizPlatform/MoMoGo

Length of output: 362


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate and inspect the relevant request handling around URLSearchParams and cursor types.
fd -a 'api\.ts$' . | sed 's#^\./##' | while read -r f; do
  echo "== $f =="
  wc -l "$f"
  cat -n "$f" | sed -n '1,230p' | sed -n '120,170p'
done

Repository: MoMoGo-QuizPlatform/MoMoGo

Length of output: 2471


🏁 Script executed:

#!/bin/bash
set -euo pipefail
node - <<'JS'
const samples = {
  searchWithSpace: { nameLike: '김 철수' },
  isoCursorWithPlus: { cursor: '2024-01-01T00:00:00+09:00' },
  literalPlus: { tagLike: 'a+b' },
  plusSignSpaceSign: { tagLike: 'a + b' }
};
for (const [label, params] of Object.entries(samples)) {
  const p = new URLSearchParams(params);
  const s = p.toString();
  const replaced = s.replace(/\+/g, '%2B');
  console.log(label);
  console.log(' raw quoted:', s);
  console.log(' quoted with replace:', replaced);
  const decoded = new URLSearchParams(replaced);
  console.log(' decoded:', Object.fromEntries(decoded));
  console.log();
}
JS

Repository: MoMoGo-QuizPlatform/MoMoGo

Length of output: 737


공백 인코딩된 +를 다시 %2B로 바꾸지 마세요.

URLSearchParams.toString()은 application/x-www-form-urlencoded 직렬화를 사용하므로 값의 공백은 +로 나오고, 기존 +는 이미 %2B로 인코딩됩니다. 따라서 .replace(/\+/g, '%2B')nameLike="김 철수" 같은 요청을 김+철수처럼 서버로 보내는 오프셋을 만듭니다.

🐛 제안 수정
-  // URL 파라미터 조립 (ISO-8601 커서 등 + 기호가 포함된 파라미터의 %2B 인코딩 보장)
   let url = resolvedPath;
  	if (params) {
-    const searchParams = new URLSearchParams(params);
-    const queryString = searchParams.toString().replace(/\+/g, '%2B');
-    url += `?${queryString}`;
+    const searchParams = new URLSearchParams(params);
+    url += `?${searchParams.toString()}`;
   }
📝 Committable suggestion

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

Suggested change
// URL 파라미터 조립 (ISO-8601 커서 등 + 기호가 포함된 파라미터의 %2B 인코딩 보장)
let url = resolvedPath;
if (params) {
const searchParams = new URLSearchParams(params);
url += `?${searchParams.toString()}`;
const queryString = searchParams.toString().replace(/\+/g, '%2B');
url += `?${queryString}`;
}
let url = resolvedPath;
if (params) {
const searchParams = new URLSearchParams(params);
url += `?${searchParams.toString()}`;
}
🤖 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 `@momogo-frontend/src/services/api.ts` around lines 144 - 150, Remove the
global plus-to-%2B replacement from the query-string construction in the URL
parameter flow. Keep URLSearchParams serialization unchanged so spaces remain
encoded as + while literal plus signs retain their existing %2B encoding.


body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-family: 'Pretendard', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

[사소] 폰트 이름의 불필요한 따옴표 (lint 오류).

Stylelint의 font-family-name-quotes 규칙이 'Pretendard', 'Inter'의 따옴표를 오류로 보고합니다. 공백이나 특수문자가 없는 단일 토큰 폰트명은 따옴표가 필요 없으며, 그대로 두면 lint 단계에서 실패할 수 있습니다. 따옴표를 제거해 규칙을 만족시키는 것을 권장합니다.

🎨 제안 수정
-  font-family: 'Pretendard', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+  font-family: Pretendard, Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
📝 Committable suggestion

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

Suggested change
font-family: 'Pretendard', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-family: Pretendard, Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 45-45: Expected no quotes around "Pretendard" (font-family-name-quotes)

(font-family-name-quotes)


[error] 45-45: Expected no quotes around "Inter" (font-family-name-quotes)

(font-family-name-quotes)

🤖 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 `@momogo-frontend/src/styles/theme.css` at line 45, Update the font-family
declaration to remove quotes from the single-token Pretendard and Inter font
names, while preserving the remaining fallback fonts and their order.

Source: Linters/SAST tools

@idktomorrow idktomorrow left a comment

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.

새벽까지 작성하시느라 고생 많으셨습니다 ❤️

@Junkov0 Junkov0 left a comment

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.

수정하시느라 수고많으셨습니다.
LGTM!

@Junkov0
Junkov0 merged commit bc5f8c1 into develop Jul 24, 2026
2 checks passed
@jaejo
jaejo deleted the feature/user-find-refactoring branch July 31, 2026 07:13
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.

3 participants