Skip to content

Feat/326 modified api - #336

Merged
shinwokkang merged 4 commits into
devfrom
feat/326-modified-api
May 21, 2026
Merged

shinwokkang merged 4 commits into
devfrom
feat/326-modified-api

Conversation

@shinwokkang

@shinwokkang shinwokkang commented May 21, 2026 •

Copy link
Copy Markdown
Contributor

📌 개요 (Summary)

  • 회원 차단(Block), 해제(Unblock), 차단 관리 목록 조회(GetBlocks) API 연동 및 이에 따른 실시간 캐시 무효화, 예외 에러 대응, 댓글 마스킹 UI 고도화 작업을 진행했습니다.
  • 관련 이슈: feat: 차단 및 신고 수정된 API 연동 #326 (회원 차단 시스템 구축 및 피드/댓글 예외 대응)

🛠️ 변경 사항 (Changes)

  • 새로운 기능 추가
  • 버그 수정
  • 코드 리팩토링
  • 문서 업데이트
  • 기타 (설명: 캐시 실시간 정합성 동기화)

1. 타입 및 에러 매핑 레이어 (types/member.ts, lib/api/errorMapper.ts)

  • 차단된 회원 정보(BlockedUser) 및 목록 응답(BlockListResponse) 규격 신규 정의.
  • 차단으로 발생할 수 있는 서버 에러 규격에 맞게 매핑 추가:
    • BLOCK_400: 자기 자신 차단 불가
    • BLOCK_401: 이미 차단한 회원
    • BLOCK_402: 차단하지 않은 회원
    • BLOCK_404: 차단한 사용자 프로필 접근 예외
    • BLOCK_405: 차단 당한 프로필 접근 예외
    • BOOK_STORY_408: 차단 관계 내 책 이야기 좋아요 불가 예외
    • COMMENT_405: 차단 관계 내 댓글/대댓글 작성 불가 예외

2. API & Data 서비스 레이어 (lib/api/endpoints/member.ts, services/memberService.ts)

  • 차단 토글 API(POST/DELETE /api/members/{nickname}/block) 및 차단 조회 API(GET /api/members/me/blocks) 엔드포인트 연동.
  • 커서 기반 페이징 처리가 내장된 getBlockedList 및 blockMember, unblockMember 서비스 추상화 구현.

3. React Query 데이터 레이어 (hooks/queries/useMemberQueries.ts, hooks/mutations/useMemberMutations.ts, hooks/mutations/useStoryMutations.ts)

  • 무한 스크롤 및 다음 커서 매핑을 갖는 useBlockedUsersQuery 훅 신규 구축.
  • useBlockMemberMutation / useUnblockMemberMutation 구현:
    • 차단/해제 성공 시 차단 목록 캐시 무효화(memberKeys.blocks()) 연동.
    • 실시간 UI 갱신: 차단/해제 성공 시 현재 탐색 중인 책이야기 캐시(storyKeys.all)를 깜빡임 없이 즉시 만료(refetchType: 'none') 처리하여, 페이지 재접근 시 마스킹 상태가 자동 동기화되도록 조치.
  • useToggleStoryLikeMutation의 onError 내에 BOOK_STORY_408 에러 코드가 검출될 시 적절한 토스트 에러 팝업을 표시하도록 분기 처리.

4. UI/UX 연동 레이어

  • 차단 관리 설정 화면 (app/(main)/setting/block/page.tsx):
    • Mock 데이터를 100% 제거하고 useBlockedUsersQuery 기반 무한 스크롤(Intersection Observer) 구현.
    • 해제 버튼 클릭 시 useUnblockMemberMutation을 즉시 유기적으로 연동.
  • 프로필 상세 화면 (ProfileUserInfo.tsx):
    • handleBlockSubmitLogic 내의 Mock 딜레이를 제거하고 실제 차단 Mutation 적용.
    • BLOCK_404, BLOCK_405 예외 발생 시 전용 마스킹 안내 UI로 치환 처리 및 PM/기획 변경 사항 대응을 위한 주석 마킹 추가.
  • 책 이야기 상세 화면 (stories/[id]/page.tsx):
    • 차단 관계 사용자의 게시글 진입으로 인한 로드 에러(BLOCK_404/BLOCK_405) 발생 시 전용 404 차단 마스킹 템플릿 제공.
  • 댓글 섹션 및 목록 화면 (comment_section_bookcase.tsx, comment_list.tsx, comment_item.tsx):
    • 서버 마스킹 규격(nickname === "차단된 사용자입니다")에 맞춰 isBlocked 판별자 도입.
    • 차단된 사용자의 댓글의 경우 텍스트 이탤릭/회색 비활성화 스타일 적용, 프로필 링크 제거(클릭 불가), 답글 및 신고 버튼 제외 처리.
    • 차단 관계 중 댓글/답글 작성 시도 시 발생하는 COMMENT_405 에러 토스트 피드백 세부 처리.

5. 토스트 노출 개선

  • 차단 완료 시 중복으로 호출되던 showCustomToast 트랙을 파악하여 useReportBlockFlow.ts 측 호출을 제거하고, Mutation의 onSuccess 1개 트랙으로 통합 정리하여 단일 토스트만 출력되도록 버그 수정.
  • [참고사항]: 차단/해제 토스트는 기획 스타일 템플릿을 준수하기 위해 toast.success 대신 기존의 showCustomToast를 적용했으나, 배경색에 대한 스타일은 현재 프로젝트의 시그니처 톤 유지를 위해 기존 스타일 테두리(opacity 및 #8C7B70/80) 버전을 유지하도록 반영했습니다.

📸 스크린샷 (Screenshots)

✅ 체크리스트 (Checklist)

  • 빌드가 성공적으로 수행되었나요? (pnpm build -> Exit code: 0)
  • 린트 에러가 없나요? (pnpm tsc --noEmit -> 검사 완료)
  • 불필요한 콘솔 로그나 주석을 제거했나요?

Summary by CodeRabbit

  • New Features

    • Added ability to block and unblock members
    • Added blocked users list page with infinite scroll pagination
  • UI/UX Improvements

    • Blocked comments now display with muted, italic styling and are non-interactive
    • Enhanced error messages for blocked relationship scenarios, including when accessing blocked users' stories or attempting to comment on restricted content

Review Change Stack

@shinwokkang shinwokkang self-assigned this May 21, 2026
@shinwokkang shinwokkang added ✨ feat 새로운 기능 추가 🐛 bug 버그 수정 labels May 21, 2026
@vercel

vercel Bot commented May 21, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
checkmo Ready Ready Preview, Comment May 21, 2026 2:52pm

@coderabbitai

coderabbitai Bot commented May 21, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 42f3ebe7-11b5-4dea-a8b9-4bcdae3acb29

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/326-modified-api

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request implements the user blocking feature by replacing mock data with real API integrations across the settings, story details, and profile pages. Key changes include the addition of block/unblock mutations, infinite scroll for the blocked users list, and specialized UI handling for blocked comments and profiles. Feedback focuses on improving the robustness of the service layer to handle relative URLs, centralizing error message retrieval via the existing errorMapper, and avoiding hardcoded string comparisons for identifying blocked users to ensure better maintainability and i18n support.

Comment thread src/services/memberService.ts Resolved
Comment thread src/app/(main)/stories/[id]/page.tsx Resolved

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

Caution

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

⚠️ Outside diff range comments (1)
src/app/(main)/stories/[id]/page.tsx (1)

33-33: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix conditional hook usage in src/app/(main)/stories/[id]/page.tsx

if (!id || isNaN(storyId)) returns before calling useStoryDetailQuery(storyId) (and before the mutation hooks right below it), so those hooks are conditionally invoked, violating React Hooks ordering constraints.

useStoryDetailQuery already has enabled: !!id in src/hooks/queries/useStoryQueries.ts, so restructure to call hooks unconditionally and render the “잘못된 접근” UI based on validity afterward, relying on enabled to skip the fetch.

🤖 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/app/`(main)/stories/[id]/page.tsx at line 33, Remove the early return
that checks `if (!id || isNaN(storyId))` before invoking hooks so that
`useStoryDetailQuery(storyId)` and the mutation hooks are always called; rely on
`useStoryDetailQuery`'s `enabled: !!id` option to prevent fetching when id is
falsy, then after hooks run render the "잘못된 접근" UI when `!id || isNaN(storyId)`
is true. Concretely, delete or move the conditional that returns before hook
calls in page.tsx, call `useStoryDetailQuery(storyId)` and the mutation hooks
unconditionally, and perform the validity check only for rendering (e.g., show
the error UI) afterward.
🤖 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/components/base-ui/Comment/comment_item.tsx`:
- Line 38: derivedCanReport and other menu-condition booleans (e.g., the logic
around derivedCanReport) ignore the isBlocked flag which allows the action menu
to remain visible even when handlers are removed; update the condition-building
in comment_item.tsx (the variables named derivedCanReport / any derived*
permission booleans and the function that computes menu visibility) to
short-circuit and return false when isBlocked is true (and keep the existing
isMine checks), so blocked comments cannot show the report/edit/delete menu
items or actions; ensure all places where derivedCanReport (and similar derived*
flags defined between lines ~64-70) are used incorporate the isBlocked check.

In `@src/components/base-ui/Comment/comment_section_bookcase.tsx`:
- Around line 128-134: Change both onError handlers in
comment_section_bookcase.tsx from using err: any to err: unknown and narrow the
error before reading its code; implement a small type-narrow check (e.g. ensure
typeof err === "object" && err !== null && "code" in err) or a reusable
predicate like isCommentError(err) to guard access, then check (err as { code?:
string }).code === "COMMENT_405" to show the block-specific toast and fall back
to the generic failure toast; extract the COMMENT_405 check into a single
reusable predicate/helper and reuse it for both the comment and reply onError
handlers to avoid duplication.

In `@src/hooks/mutations/useMemberMutations.ts`:
- Around line 407-410: The onError handlers in useBlockMemberMutation and
useUnblockMemberMutation currently type the error parameter as any; change the
signature to onError: (error: unknown) and narrow it safely before accessing
fields (either add a small type guard or helper like extractErrorMessage(error:
unknown): string). Inside the handler, check for non-null objects and the
presence of response/data/message (or use AxiosError type guard if Axios is
available) to derive errorMessage, falling back to String(error) or a default
Korean message; then pass that string to toast.error and log the error. Ensure
both functions (useBlockMemberMutation and useUnblockMemberMutation) are updated
symmetrically.

In `@src/hooks/mutations/useStoryMutations.ts`:
- Around line 287-294: Change the onError handler in useStoryMutations to avoid
using the any type: replace the parameter type (currently "err: any") with "err:
unknown" and narrow it before reading properties; for example, add a type-guard
or conditional that checks typeof err === 'object' && err !== null and 'code' in
err (or use a helper isErrorWithCode) and then safely check err.code ===
"BOOK_STORY_408" to decide which toast to show; keep the existing console.error
call but pass the narrowed error for safer logging.

---

Outside diff comments:
In `@src/app/`(main)/stories/[id]/page.tsx:
- Line 33: Remove the early return that checks `if (!id || isNaN(storyId))`
before invoking hooks so that `useStoryDetailQuery(storyId)` and the mutation
hooks are always called; rely on `useStoryDetailQuery`'s `enabled: !!id` option
to prevent fetching when id is falsy, then after hooks run render the "잘못된 접근"
UI when `!id || isNaN(storyId)` is true. Concretely, delete or move the
conditional that returns before hook calls in page.tsx, call
`useStoryDetailQuery(storyId)` and the mutation hooks unconditionally, and
perform the validity check only for rendering (e.g., show the error UI)
afterward.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8769d7cf-90ec-4d46-9c76-c7656d5e2c7a

📥 Commits

Reviewing files that changed from the base of the PR and between a3a9595 and 992062b.

📒 Files selected for processing (14)
  • src/app/(main)/setting/block/page.tsx
  • src/app/(main)/stories/[id]/page.tsx
  • src/components/base-ui/Comment/comment_item.tsx
  • src/components/base-ui/Comment/comment_list.tsx
  • src/components/base-ui/Comment/comment_section_bookcase.tsx
  • src/components/base-ui/Profile/OtherUser/ProfileUserInfo.tsx
  • src/hooks/mutations/useMemberMutations.ts
  • src/hooks/mutations/useStoryMutations.ts
  • src/hooks/queries/useMemberQueries.ts
  • src/hooks/useReportBlockFlow.ts
  • src/lib/api/endpoints/member.ts
  • src/lib/api/errorMapper.ts
  • src/services/memberService.ts
  • src/types/member.ts

@shinwokkang
shinwokkang merged commit 0d88983 into dev May 21, 2026
3 checks passed
@shinwokkang
shinwokkang deleted the feat/326-modified-api branch May 21, 2026 14:53
@coderabbitai coderabbitai Bot mentioned this pull request May 22, 2026

This branch was successfully deployed

1 active deployment
Preview — 1fb76ddb Deployed May 21, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🐛 bug 버그 수정 ✨ feat 새로운 기능 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant