Skip to content

Conversation

@Ivoryeee
Copy link
Collaborator

@Ivoryeee Ivoryeee commented Jul 26, 2025

🔥 Related Issues

✅ 작업 리스트

  • overlay-kit 적용
  • 기존 모달 컴포넌트들을 Overlay 기반으로 교체

🔧 작업 내용

기존 ModalWrapper를 제거하고, overlay-kit을 활용한 Overlay 컴포넌트를 새로 정의했습니다.
모달 로직을 간결하게 유지하면서도 재사용성과 확장성을 고려했습니다.

✔️ Overlay-kit 라이브러리 설치

pnpm install overlay-kit

✔️ App.tsx에 OverlayProvider 추가

const App = () => {
	return (
		<QueryClientProvider client={queryClient}>
			<div style={{ fontSize: '16px' }}>
				<ReactQueryDevtools initialIsOpen={false} />
			</div>
			<OverlayProvider>
				<Provider>
					<RouterProvider router={router} />
				</Provider>
			</OverlayProvider>
		</QueryClientProvider>
	);
};

OverlayProvider는 overlay-kit의 핵심 상태 관리 컨텍스트를 제공하여, 앱 전역에서 모달과 오버레이 컴포넌트의 열림/닫힘 상태를 일관되게 관리하기 위해 추가했습니다. 이를 통해 여러 곳에서 호출되는 모달이 충돌 없이 정상적으로 작동하도록 돕습니다.

✔️ Overlay 컴포넌트

import { overlay } from 'overlay-kit';
import { ReactNode } from 'react';

interface OverlayProps {
	backdrop?: boolean;
	content: (props: { isOpen: boolean; close: () => void }) => ReactNode;
}

// Overlay 컴포넌트 구현
export const Overlay = ({ content, backdrop = true }: OverlayProps) => {
	// overlay.open: 모달 열기 함수 (overlay-kit 제공)
	overlay.open(({ isOpen, close }) =>
		isOpen ? (
			<div
				className={`fixed inset-0 z-50 flex items-center justify-center ${
					backdrop ? 'bg-[rgba(0,0,0,0.7)]' : 'bg-transparent'
				}`}
				// 바깥 영역 클릭 시 모달 닫기
				onClick={close}
			>
				{/* 모달 내용 컨테이너,  내부 클릭 시 바깥(onClick)으로 이벤트 전파되지 않도록 차단 */}
				<div onClick={(e) => e.stopPropagation()}>
					{/* 사용자에게 전달된 content 함수 실행, isOpen/close 전달 */}
					{content({ isOpen, close })}
				</div>
			</div>
		) : null, // 모달이 닫혔을 경우 렌더링하지 않음
	);
};

✔️ Overlay 사용법

Overlay({
  backdrop: false, // 배경을 투명하게 표시하고 싶을 때
  content: ({ isOpen, close }) => ( <~~Modal isOpen={isOpen} isClose={close} />,) //  isOpen, close는 필요한 값만 사용
});

✔️ ModalWrapper -> Overlay 교체 작업

(기존)

	const handleCloseDeleteAccountModal = () => {
		deleteAccountModalRef.current?.close();
	};

	const handleOpenDeleteAccountModal = () => {
		deleteAccountModalRef.current?.open();
	};

	<ModalWrapper ref={deleteAccountModalRef} backdrop>
		{(_) => (
			<ModalContentsAlert.DeleteAccount
					onConfirm={handleDeleteAccount}
					onCloseModal={handleCloseDeleteAccountModal}
					userEmail={props.email}
				/>
			)}
	</ModalWrapper>

(교체)

	const handleLogoutModal = () => {
		Overlay({
			backdrop: true,
			content: ({ close }) => (
				<ModalContentsAlert.Logout onConfirm={reloginWithoutLogout} onCloseModal={close} userEmail={props.email} />
			),
		});
	};

해당 pr에 대한 전 과정을 노션에 간략히 정리해 뒀습니다!
https://www.notion.so/Overlay-kit-23893c660098802a9e6cca308a354edf?source=copy_link

🧐 새로 알게된 점

  • overlay-kit을 사용하면 imperative하게도 모달 제어가 가능하며, 내부 상태와 이벤트 흐름을 간결하게 관리할 수 있다

🤔 궁금한 점

📸 스크린샷 / GIF / Link

  • 각 모달이 정상적으로 작동하는지 확인하며 적용 완료했습니다.

@Ivoryeee Ivoryeee self-assigned this Jul 26, 2025
@Ivoryeee Ivoryeee added the ♻️ Refactor 코드 리팩토링 label Jul 26, 2025
@pull-request-size pull-request-size bot added size/XL and removed size/L labels Aug 2, 2025
@10tacion
Copy link
Member

10tacion commented Aug 2, 2025

@Ivoryeee 감사합니다~~~ 고생많으셨어요🙇‍♂️🙇‍♂️🙇‍♂️

  • overlay의 open은 컴포넌트라기 보다는, 컴포넌트를 화면에 마운트 시키는 유틸함수로 호출해서 사용합니다. 그래서 util 함수로 분리했습니다.
  • overlay provider 하위 컴포넌트 중에 react-router의 api를 사용하는 경우가 있다면, 리액트 라우터 컨텍스트 하위에 있어야 합니다. 그래서 프로바이더 위치를 Router.tsx로 옮겨주었습니다.

@10tacion 10tacion merged commit ee4feba into develop Aug 2, 2025
1 check passed
@10tacion 10tacion deleted the refactor/#323/overlay branch August 2, 2025 01:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

♻️ Refactor 코드 리팩토링 size/XL

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[ Refactor ] 오버레이 컴포넌트 재설계

3 participants