Skip to content

Refactor: Context API로 BottomSheet onClose props drilling 제거 - #200

Merged
ssilver01 merged 3 commits into
developfrom
refactor/#54/bottom-sheet-props-drilling
Apr 23, 2026
Merged

Refactor: Context API로 BottomSheet onClose props drilling 제거#200
ssilver01 merged 3 commits into
developfrom
refactor/#54/bottom-sheet-props-drilling

Conversation

@ssilver01

@ssilver01 ssilver01 commented Apr 21, 2026

Copy link
Copy Markdown
Collaborator

📝 PR 유형

  • 🚀 feature 기능 추가
  • 🐞 버그 발생
  • 🔨 리팩토링
  • 📋 문서작성
  • 🌍 빌드 설정 및 문제
  • ETC

🔔 관련된 이슈 넘버

✅ 작업 목록

문제 상황: Compound Component 패턴 사용 시 props drilling이 심화되어 유지보수성 저하 우려

BottomSheet가 이미 onClose를 갖고 있음에도, 그 안에 렌더되는 컴포넌트들도 독립적으로 onClose를 prop으로 받아서 아래로 전달해야 했습니다.

ExpenseEditBottomSheet
  ├─ onClose 소유
  ├─ <BottomSheet onClose={onClose}>              ← BottomSheet에 전달
  └─ <ExpenseFormBottomSheet onClose={onClose}>   ← 또 전달 (drilling)
       └─ <BaseBottomSheetTemplate.Header onClose={onClose}>  ← 또 전달

변경 내용

1. BottomSheetContext 생성

// BottomSheetContext.tsx
export const BottomSheetContext = createContext<{ onClose: () => void } | null>(null);
export const useBottomSheetContext = () => useContext(BottomSheetContext);

2. BottomSheet가 Context 제공

// BottomSheet.tsx - children을 Provider로 감쌈
<BottomSheetContext.Provider value={{ onClose }}>
  {children}
</BottomSheetContext.Provider>

3. Header가 Context에서 직접 읽음

// BaseBottomSheetTemplate.tsx
const BottomSheetHeader = ({ text, type, onClickAddBtn }) => {
  const { onClose } = useBottomSheetContext(); // ← prop 대신 Context
  ...
}

개선된 구조

ExpenseEditBottomSheet
  ├─ onClose 소유
  └─ <BottomSheet onClose={onClose}>   ← 여기 한 번만 전달, Context 제공
       └─ <ExpenseFormBottomSheet>     ← onClose prop 불필요
            └─ <Header>                ← Context에서 직접 읽음

onClose를 소유한 BottomSheet와 실제로 사용하는 Header 사이의 중간 컴포넌트들이 onClose를 전혀 알 필요가 없어졌습니다. 앞으로 새 템플릿을 만들 때도 props에 onClose를 선언하지 않아도 됩니다.

Summary by CodeRabbit

릴리스 노트

  • 리팩토링
    • 바텀시트 컴포넌트의 닫기 기능 처리 방식을 개선했습니다. React Context를 활용한 새로운 구조로 변경하여 코드 관리를 단순화했습니다. 사용자 경험에는 변화가 없습니다.

@vercel

vercel Bot commented Apr 21, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
nitrogen-front-web Ready Ready Preview, Comment Apr 21, 2026 7:25am

@coderabbitai

coderabbitai Bot commented Apr 21, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@ssilver01 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 55 minutes and 0 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 55 minutes and 0 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 82b322bf-8b94-4903-9bbb-e5006dabf4b5

📥 Commits

Reviewing files that changed from the base of the PR and between cfabfb3 and a925bfd.

📒 Files selected for processing (1)
  • apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx

전체 요약

개요

BottomSheet의 onClose props drilling을 개선하기 위해 Context API를 도입했습니다. BottomSheetContext를 새로 생성하고, 기존에 props로 전달되던 onClose 콜백을 컨텍스트를 통해 직접 접근하도록 리팩토링했습니다. 여러 컴포넌트와 스토리에서 onClose props 전달을 제거했습니다.

변경 사항

코호트 / 파일(들) 설명
Context API 인프라
apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx, apps/web/src/shared/ui/bottomSheet/BottomSheet.tsx, apps/web/src/shared/ui/bottomSheet/index.ts
BottomSheetContextValue 인터페이스와 useBottomSheetContext 훅 추가. BottomSheet 컴포넌트가 BottomSheetContext.Provider로 children을 래핑하도록 변경. 새로운 context 기반 API를 공개 export로 추가.
헤더 컴포넌트
apps/web/src/shared/ui/bottomSheet/templates/BaseBottomSheetTemplate.tsx
BottomSheetHeaderProps에서 onClose props 제거. BottomSheetHeader가 useBottomSheetContext()로 컨텍스트에서 onClose 핸들러를 직접 가져오도록 수정.
DatePicker 바텀시트
apps/web/src/features/datePickerModal/ui/DatePickerBottomSheet.tsx, apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.tsx, apps/web/src/features/datePickerModal/ui/DatePickerFeature.tsx, apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.stories.tsx
DatePickerBottomSheetTemplateProps에서 onClose props 제거. 컴포넌트 호출 시 onClose prop 전달 제거. 스토리북 문서에서 onClose argType 및 예시 코드 제거.
비용 폼 바텀시트
apps/web/src/features/expense/ui/expenseBottomSheet/ExpenseFormBottomSheet.tsx, apps/web/src/features/expense/ui/expenseBottomSheet/ExpenseFormBottomSheet.stories.tsx, apps/web/src/features/expense/ui/ExpenseEditBottomSheet.tsx
ExpenseFormBottomSheetProps에서 onClose props 제거. 템플릿 호출 시 onClose prop 전달 제거. 스토리북에서 onClose argType 및 사용 예시 제거.
아이콘 선택 바텀시트
apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.tsx, apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.stories.tsx, apps/web/src/features/expense/ui/steps/AddCategoryStep/AddCategoryStep.tsx, apps/web/src/widgets/addCategory/ui/AddCategory.tsx
IconPickerBottomSheetTemplateProps에서 onClose props 제거. 템플릿 호출 시 onClose prop 전달 제거. 스토리북 문서 업데이트.
캘린더 바텀시트
apps/web/src/features/expense/ui/steps/AmountDateStep/CalendarBottomSheet.tsx, apps/web/src/features/expense/ui/steps/AmountDateStep/AmountDateStep.tsx
CalendarBottomSheetTemplateProps에서 onClose props 제거. 헤더 렌더링 시 onClose 핸들러 전달 제거.

코드 리뷰 노력 추정

🎯 3 (보통) | ⏱️ ~20분

시 🐰

Context의 바람이 살랑, 아래로 내려와 🌬️
Props 체인은 끝났고, 직접 접근하네 ✨
BottomSheet의 마음, 이제 더 자유로워
깊은 구조도 편하게, Context가 들어줄게
리팩토링의 춤, 우아하고 가벼워 💃🎭

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 주요 변경 사항을 명확하게 반영하고 있습니다. Context API를 사용하여 BottomSheet onClose props drilling을 제거하는 리팩토링이 정확히 표현되어 있습니다.
Linked Issues check ✅ Passed PR은 #54의 모든 코딩 요구사항을 충족합니다. BottomSheetContext 생성, useBottomSheetContext 훅 구현, BaseBottomSheetTemplate.Header에서 Context로 onClose 접근하는 수정이 완료되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경 사항이 Context API를 통한 props drilling 제거라는 목표에 정렬되어 있습니다. 범위를 벗어난 변경이나 무관한 수정은 없습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/#54/bottom-sheet-props-drilling

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.

@ssilver01 ssilver01 changed the title Refactor/#54/bottom sheet props drilling Refactor: Context API로 BottomSheet onClose props drilling 제거 Apr 21, 2026
@ssilver01 ssilver01 self-assigned this Apr 21, 2026
@ssilver01 ssilver01 added the 🔨 Refactor 코드 리팩토링 label Apr 21, 2026
@github-actions

github-actions Bot commented Apr 21, 2026

Copy link
Copy Markdown

🎨 Storybook 배포 완료

📚 Storybook: https://6960ec095e9394ddeaa0f9f3-glqgbntsra.chromatic.com/
🔍 Chromatic 빌드: https://www.chromatic.com/build?appId=6960ec095e9394ddeaa0f9f3&number=200

UI 변경사항을 확인해주세요!

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx`:
- Line 1: This file uses React client-only hooks createContext and useContext
but lacks the Next.js Client Component directive; add the string directive "use
client" as the very first line of the BottomSheetContext module (before any
imports) so createContext/useContext are executed on the client.

In `@apps/web/src/shared/ui/bottomSheet/templates/BaseBottomSheetTemplate.tsx`:
- Line 15: BaseBottomSheetTemplate currently always calls
useBottomSheetContext(), causing errors when rendering the header with
type='add' where onClose isn't needed; move the hook call out of the top-level
render and into the close-button-specific component (e.g., the CloseButton or
headerCloseHandler) so useBottomSheetContext() is only invoked when a closable
header is rendered and onClose is required; update BaseBottomSheetTemplate to
render the close-button component conditionally for non-'add' types and remove
any unconditional useBottomSheetContext() usage, ensuring onClose is passed down
from the hook into that close-button component only when present.
🪄 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

Run ID: a5190b07-58a8-4f4e-a768-7af3bed2b43b

📥 Commits

Reviewing files that changed from the base of the PR and between 5aaeb42 and cfabfb3.

📒 Files selected for processing (17)
  • apps/web/src/features/datePickerModal/ui/DatePickerBottomSheet.tsx
  • apps/web/src/features/datePickerModal/ui/DatePickerFeature.tsx
  • apps/web/src/features/expense/ui/ExpenseEditBottomSheet.tsx
  • apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.stories.tsx
  • apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.tsx
  • apps/web/src/features/expense/ui/expenseBottomSheet/ExpenseFormBottomSheet.stories.tsx
  • apps/web/src/features/expense/ui/expenseBottomSheet/ExpenseFormBottomSheet.tsx
  • apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.stories.tsx
  • apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.tsx
  • apps/web/src/features/expense/ui/steps/AddCategoryStep/AddCategoryStep.tsx
  • apps/web/src/features/expense/ui/steps/AmountDateStep/AmountDateStep.tsx
  • apps/web/src/features/expense/ui/steps/AmountDateStep/CalendarBottomSheet.tsx
  • apps/web/src/shared/ui/bottomSheet/BottomSheet.tsx
  • apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx
  • apps/web/src/shared/ui/bottomSheet/index.ts
  • apps/web/src/shared/ui/bottomSheet/templates/BaseBottomSheetTemplate.tsx
  • apps/web/src/widgets/addCategory/ui/AddCategory.tsx
💤 Files with no reviewable changes (8)
  • apps/web/src/widgets/addCategory/ui/AddCategory.tsx
  • apps/web/src/features/expense/ui/steps/AmountDateStep/AmountDateStep.tsx
  • apps/web/src/features/datePickerModal/ui/DatePickerFeature.tsx
  • apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.stories.tsx
  • apps/web/src/features/expense/ui/ExpenseEditBottomSheet.tsx
  • apps/web/src/features/expense/ui/steps/AddCategoryStep/AddCategoryStep.tsx
  • apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.stories.tsx
  • apps/web/src/features/expense/ui/expenseBottomSheet/ExpenseFormBottomSheet.stories.tsx

Comment thread apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx
import { vars } from '../../theme.css';
import { IcClear, IcPlusSimple } from 'public/icons';
import { Button } from '../../button';
import { useBottomSheetContext } from '../BottomSheetContext';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: BaseBottomSheetTemplate.Header의 add 타입 사용처를 확인합니다.
rg -nP -C3 "<BaseBottomSheetTemplate\\.Header[^>]*type=['\"]add['\"]" --glob '*.tsx'

Repository: Central-MakeUs/Monit_Front

Length of output: 929


🏁 Script executed:

#!/bin/bash
# 1. BaseBottomSheetTemplate.tsx 파일 크기 확인
wc -l apps/web/src/shared/ui/bottomSheet/templates/BaseBottomSheetTemplate.tsx

# 2. 파일 내용 읽기
cat -n apps/web/src/shared/ui/bottomSheet/templates/BaseBottomSheetTemplate.tsx

Repository: Central-MakeUs/Monit_Front

Length of output: 3438


🏁 Script executed:

#!/bin/bash
# 3. Header 컴포넌트의 직접 import 사용 여부 검색
rg -n "import.*Header.*from.*BottomSheetTemplate|from.*BaseBottomSheetTemplate.*Header" --glob '*.tsx'

Repository: Central-MakeUs/Monit_Front

Length of output: 52


🏁 Script executed:

#!/bin/bash
# 4. 전체 type='add' 사용처 재검색 (더 광범위)
rg -n "type=['\"]add['\"]" apps/web/src/features --glob '*.tsx' | grep -i "header\|template"

Repository: Central-MakeUs/Monit_Front

Length of output: 239


type='add' 헤더에서 불필요한 컨텍스트 의존성 제거 필요

Line 43-44에서 useBottomSheetContext()를 항상 호출하므로, onClose가 필요 없는 type='add' 헤더도 컨텍스트가 존재하지 않으면 에러가 발생합니다. 현재 사용처는 모두 BaseBottomSheetTemplate 내부에서 렌더링되어 안전하지만, 훅 호출을 onClose가 필요한 close 버튼 전용 컴포넌트로 이동하면 더 안전한 구조가 됩니다.

🐛 제안 수정
 import { Button } from '../../button';
 import { useBottomSheetContext } from '../BottomSheetContext';
@@
-const BottomSheetHeader = ({ text, type = 'close', onClickAddBtn }: BottomSheetHeaderProps) => {
+const BottomSheetCloseButton = () => {
   const { onClose } = useBottomSheetContext();
+
+  return <IcClear className={headerIcon} color={vars.color.icon.subtle} onClick={onClose} />;
+};
+
+const BottomSheetHeader = ({ text, type = 'close', onClickAddBtn }: BottomSheetHeaderProps) => {
   return (
     <div className={bottomSheetHeaderWrapper}>
@@
       {type === 'close' ? (
-        <IcClear className={headerIcon} color={vars.color.icon.subtle} onClick={onClose} />
+        <BottomSheetCloseButton />
       ) : (
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/shared/ui/bottomSheet/templates/BaseBottomSheetTemplate.tsx` at
line 15, BaseBottomSheetTemplate currently always calls useBottomSheetContext(),
causing errors when rendering the header with type='add' where onClose isn't
needed; move the hook call out of the top-level render and into the
close-button-specific component (e.g., the CloseButton or headerCloseHandler) so
useBottomSheetContext() is only invoked when a closable header is rendered and
onClose is required; update BaseBottomSheetTemplate to render the close-button
component conditionally for non-'add' types and remove any unconditional
useBottomSheetContext() usage, ensuring onClose is passed down from the hook
into that close-button component only when present.

@github-actions

Copy link
Copy Markdown

🎉 구현한 기능 Preview: https://nitrogen-front-2zicl2jix-ssilver01s-projects.vercel.app

@ssilver01
ssilver01 requested a review from hyun907 April 21, 2026 07:27

@hyun907 hyun907 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Context 경계와 데이터 소유권이 잘 보이는 리팩토링입니다! props-drilling도 깔끔하게 정리되고, 잘못 쓰면 throw로 바로 드러나는 점도 좋습니다! Good!

@ssilver01
ssilver01 merged commit 92ff43c into develop Apr 23, 2026
11 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.

[ Refactor ] BottomSheet onClose props drilling 개선 (Context API)

2 participants