최근에 리액트에서 import 시에 wrapper 패턴을 활용했다는 글을 읽었다.
lodash나 Framer Motion를 전체 라이브러리 단위로 import하는 상황이 종종 있다고 한다.
예를 들어, lodash를 <<이전>> 과 같이 import하는 경우와 같다.
<< 이전 >>
import _ from 'lodash' -> imported 71.78KB
<< 이후 >>
import debounce from "lodash/debounce"; -> imported 3.41KB
import merge from 'lodash/merge'; -> imported 16KB
물론 전체 라이브러리를 import하고 있지는 않지만, 글쓴이가 언급한 바와 같이,
여기저기 흩어져 있는 파일들마다 framer-motion나 className/bind를 import하고 있는 상황이었다.
해당 경우 문제들이 있었는데,
1. 리펙토링이 어렵다. 만약 라이브러리를 변경한다거나 라이브러리에 변경사항(e.g import 해오는 패키지 이름이 변경되는 등)이 생기면 일일이 import를 해줬던 파일들에 들어가서 변경을 해줘야 한다는 것이다. 물론 vscode로 일괄 적용을 해서 변경해 주면 되지만, import해줬던 파일들만큼 pr이 커진다.
2. 휴먼 에러에 취약하다. Import를 업데이트해줘야하는 경우, 놓칠 수 있다는 문제가 있다. 예를 들면 해당 패키지에 두 가지, 혹은 세 가지 이상의 모듈을 import할 경우도 있는데, 하나만 import해오는 경우만 검색해서 변경하는 경우가 생길 수도 있다.
3. 브랜치 관리가 어려워진다. PR merge를 하려고 하는데 conflict이 발생한다고 하자. 해당 import를 한 파일이 10개 있다면 변경 사항을 다 체크하려고 10개의 파일들을 다 살펴봐야한다는 번거로움이 발생한다.
wrapper를 활용하는 것이 번들 사이즈를 줄이는 역할을 하지 않지만, 유지/관리를 용이해주기 위한 장치로 쓸 수 있다.
지금 여러 파일들에 공통으로 import를 하는 패키지에는 motion과 classNames/bind가 있다.
- motion-framer의 경우
- /wrappers/motion-wrapper.tsx
import { AnimationProps, motion, MotionStyle, SVGMotionProps, Variant, Variants } from 'framer-motion';
export type MotionVariant = Variant;
export type MotionVariants = Variants;
export type MotionAnimationProps = AnimationProps;
export type MotionStyleProps = MotionStyle;
export type MotionSVGProps = SVGMotionProps<SVGPathElement>;
// 컴포넌트들에 쓰이는 프롭스
export interface MotionProps {
variants: Variants;
animationProps: AnimationProps;
motionStyle: MotionStyle;
svgProps: SVGMotionProps<SVGPathElement>;
}
// motion framer 컴포넌트들
export const Motion = {
Div: motion.div,
Button: motion.button,
Section: motion.section,
Span: motion.span,
Li: motion.li,
Ul: motion.ul,
Img: motion.img,
Path: motion.path,
Nav: motion.nav,
};
export default Motion;
- 마찬가지로 classNames도 다음과 같이
- wrappers/classNames.ts
import classNames from 'classnames/bind';
export default classNames;
그리고 index.tsx에 다음과 같이 추가해주면
import classNames from './classNames';
import Motion, { MotionProps } from './motion-wrapper';
// Type error: Re-exporting a type when 'isolatedModules' is enabled requires using 'export type'.
export { classNames, Motion, type MotionProps };
다음과 같이 import를 해올 수 있다.

이전에는 변경 사항이 필요했으면 모든 파일들을 확인하며 변경해줬어야 했지만, 이제는 wrappers에서만 변경해주면 된다.
+ import size를 추적하고 싶다면 vscode extension 중 "Import Cost"를 활용해 볼 수 있다.


References
Don’t use React imports like this. Use Wrapper Pattern instead
While working on a real-life project, I encountered an inefficient React.js import strategy. Learn how to import the right way!
medium.com
'👩🏻💻 dev' 카테고리의 다른 글
세션 스토리지, 로컬 스토리지 어떤 걸 써야할까? (0) | 2025.03.13 |
---|---|
로컬 스토리지 vs 세션 스토리지 vs 쿠키 (0) | 2025.03.13 |
👋 굿바이 CRA (Sunsetting Create React App) (1) | 2025.03.09 |
[Nextjs] Dynamic metadata tag 생성하기 (Part.2) (1) | 2025.02.26 |
[Nextjs] Dynamic metadata tag 생성하기 (SEO 지표 54 ➡️ 91) (0) | 2025.02.25 |