v7로 업그레이드하기
v7로 업그레이드하기 (Upgrade to v7)
Material UI v6에서 v7로 업그레이드하는 방법을 설명하는 가이드예요. 주요 변경 사항과 마이그레이션 단계를 하나씩 짚어볼게요.
출처: 문서
본문
이 가이드는 Material UI v6에서 v7로 업그레이드하는 방법을 설명해요.
Material UI v7로 업그레이드해야 하는 이유 (Why you should upgrade to Material UI v7)
향상된 ESM 지원 (Improved ESM support)
패키지 레이아웃이 업데이트되어 이제 package.json의 exports 필드를 통해 유효한 ESM과 CommonJS를 모두 명확하게 지원해요. 패키지 exports에 대해 더 자세히 알고 싶다면 Node.js 문서를 참고하세요.
이 업데이트는 Vite와 webpack 같은 인기 번들러의 여러 문제를 해결하고, Node.js에서 ES 모듈로 MUI 패키지를 로드할 수 있게 해줘요.
삶의 질 개선 (Quality-of-life improvements)
Material UI v7은 다른 삶의 질 개선 사항도 제공해요:
- 모든 컴포넌트에서 slot 패턴 표준화
- 클라이언트 사이드 앱의
StyledEngineProvider와 Next.js App Router 앱의AppRouterCacheProvider에서enableCssLayerprop을 통한 CSS layers 지원 - 더 이상 사용되지 않는 API를 제거해서 API 표면을 줄이고 문서를 탐색하기 쉽게 만들기
다음 패키지 중 하나를 사용하고 있다면 버전도 "7.0.0"으로 업데이트해야 해요:
@mui/icons-material@mui/system@mui/lab@mui/material-nextjs@mui/styled-engine@mui/styled-engine-sc@mui/utils
MUI X 패키지는 Material UI와 동일한 버전 전략을 따르지 _않는다_는 점을 참고하세요. 다음 패키지 중 하나를 사용하고 있다면 업그레이드 과정에서 그대로 두어야 해요:
@mui/x-data-grid@mui/x-data-grid-pro@mui/x-data-grid-premium@mui/x-date-pickers@mui/x-date-pickers-pro@mui/x-charts@mui/x-tree-view@mui/x-tree-view-pro
최소 TypeScript 버전 (Minimum TypeScript version)
지원되는 TypeScript 최소 버전이 v4.7에서 4.9로 올라갔어요.
:::info
우리는 DefinitelyTyped(npm에 @types 네임스페이스로 게시됨)의 지원 창(support window)에 맞춥니다.
Material UI의 마이너 버전에서는 최소 지원 버전을 변경하지 않을 거예요. 하지만 DefinitelyTyped가 지원하는 가장 낮은 버전보다 오래된 TypeScript 버전을 사용하지 않는 것이 좋아요. :::
@types/react* 패키지의 경우, 사용 중인 react의 메이저 버전과 같은 메이저 버전인지 확인하세요. 필요하다면 아래 스니펫을 사용해서 프로젝트를 업데이트할 수 있어요(<version>을 사용 중인 react의 메이저 버전으로 바꾸세요):
npm install @types/react@<version> @types/react-dom@<version>
pnpm add @types/react@<version> @types/react-dom@<version>
yarn add @types/react@<version> @types/react-dom@<version>
:::warning 애플리케이션이 오류 없이 실행되는지 확인하고, 다음 단계로 넘어가기 전에 변경 사항을 커밋하세요. :::
React 18 이하 (React 18 and below)
React 18 이하를 사용하고 있다면, 사용 중인 react와 같은 버전으로 react-is 패키지의 resolution을 설정해야 해요.
예를 들어 [email protected]을 사용하고 있다면 다음 단계를 수행하세요:
[email protected]을 설치해요.
npm install [email protected]
pnpm add [email protected]
yarn add [email protected]
package.json에서 resolutions 또는 overrides를 설정해요.
{
…
"overrides": {
"react-is": "^18.3.1"
}
}
{
…
"overrides": {
"react-is": "^18.3.1"
}
}
{
…
"resolutions": {
"react-is": "^18.3.1"
}
}
왜 이것이 필요한가요? (Why is this needed?)
Material UI v7은 React 요소 식별 방식을 변경한 react-is@19를 사용해요.
React 18 이하를 사용 중이라면, 버전이 맞지 않는 react-is가 prop 타입 검사에서 런타임 오류를 일으킬 수 있어요. react-is를 React 버전과 일치시키면 이러한 오류를 방지해요.
더 이상 사용되지 않는 기능 (Deprecations)
Material UI v7을 사용하기 위해 즉시 deprecation을 처리할 필요는 없어요.
deprecations 페이지를 확인하면서 자신의 페이스대로 진행할 수 있어요. 이 deprecation들은 다음 메이저 버전에서 제거될 거예요.
주요 변경 사항 (Breaking changes)
v7은 새 메이저 릴리스이므로 공개 API에 영향을 주는 몇 가지 변경 사항이 포함돼 있어요. Material UI v6에서 v7로 마이그레이션하기 위해 취해야 할 단계는 아래에 설명되어 있어요.
패키지 레이아웃 업데이트 (Package layout updated)
패키지 레이아웃이 Node.js exports 필드를 사용하도록 업데이트됐어요. 이로 인해 몇 가지 변경 사항이 생겨요:
한 단계를 초과하는 deep import는 전혀 동작하지 않게 됐어요(이미 비공개 API로 간주됐어요). 예를 들어:
-import createTheme from '@mui/material/styles/createTheme';
+import { createTheme } from '@mui/material/styles';
이것은 공식적으로 지원된 적이 없지만, 이제 번들러와 런타임에 의해 제한될 거예요.
번들 크기를 줄일 가능성이 더 이상 크지 않기 때문에 modern 번들도 제거됐어요. 이 번들에 대한 alias를 구성했다면 지금 제거해야 해요.
{
resolve: {
alias: {
- '@mui/material': '@mui/material/modern',
- '@mui/styled-engine': '@mui/styled-engine/modern',
- '@mui/system': '@mui/system/modern',
- '@mui/base': '@mui/base/modern',
- '@mui/utils': '@mui/utils/modern',
- '@mui/lab': '@mui/lab/modern',
}
}
}
:::info
이 가이드의 이전 버전에서는 mui-modern 조건부 exports의 존재를 언급했어요. 이후로 이것은 제거됐어요. 이는 비파괴적인 변경이며, 번들러는 ESM 번들로 대체될 거예요.
:::
아이콘 패키지에 ESM import를 강제하기 위해 Vite alias를 사용하고 있다면, 더 이상 필요하지 않으므로 제거해야 해요:
// vite.config.js
resolve: {
alias: [
- {
- find: /^@mui\/icons-material\/(.*)/,
- replacement: "@mui/icons-material/esm/$1",
- },
],
},
테마를 augmentation하고 중첩 import에 대한 선언을 사용하고 있다면, @mui/material/styles로 교체해야 해요. 일부 인터페이스는 @mui/material/styles에서 다른 이름으로 내보내지므로 이름을 바꿔야 할 수도 있어요:
-declare module '@mui/material/styles/createTypography' {
+declare module '@mui/material/styles' {
- interface TypographyOptions {
+ interface TypographyVariantsOptions {
// ...
}
- interface Typography {
+ interface TypographyVariants {
// ...
}
}
Grid와 Grid2 이름 변경 (Grid and Grid2 renamed)
더 이상 사용되지 않는 Grid 컴포넌트는 GridLegacy로 이름이 바뀌었어요. Grid2 컴포넌트는 Grid 네임스페이스로 이동했어요. 프로젝트에 따라 다음 접근 방식 중 하나를 따를 수 있어요:
-
사용하지 않는 grid를 사용 중이고 업그레이드하고 싶다면 다음 codemod를 실행해요:
npx @mui/codemod@latest v7.0.0/grid-props <path/to/folder>자세한 내용은 Grid upgrade guide를 참고하세요.
-
사용하지 않는 grid를 계속 사용하고 싶다면 다음과 같이
Grid참조를 업데이트해요:// imports -import Grid, { gridClasses, GridProps } from '@mui/material/Grid'; +import Grid, { gridLegacyClasses, GridLegacyProps } from '@mui/material/GridLegacy'; -import { Grid } from '@mui/material'; +import { GridLegacy as Grid } from '@mui/material'; // theme const theme = createTheme({ components: { - MuiGrid: { + MuiGridLegacy: { // ... }, }, }); // CSS classes -.MuiGrid-root +.MuiGridLegacy-root -
Grid2를 사용하고 있다면 다음과 같이
Grid2참조를 업데이트해요:// imports -import Grid, { grid2Classes as gridClasses, Grid2Props as GridProps } from '@mui/material/Grid2'; +import Grid, { gridClasses, GridProps } from '@mui/material/Grid'; -import { Grid2 as Grid } from '@mui/material'; +import { Grid } from '@mui/material'; // theme const theme = createTheme({ components: { - MuiGrid2: { + MuiGrid: { // ... }, }, }); // CSS classes -.MuiGrid2-root +.MuiGrid-root
InputLabel size prop 표준화 (InputLabel size prop standardized)
InputLabel의 size prop은 이제 Button과 TextField 같은 다른 컴포넌트에서 사용되는 표준 명명 규칙을 따르게 돼요. 일관성을 위해 'normal'이 'medium'으로 대체됐어요.
size="normal"을 사용하고 있었다면 size="medium"으로 업데이트해요:
-<InputLabel size="normal">Label</InputLabel>
+<InputLabel size="medium">Label</InputLabel>
기본 동작은 변경되지 않았으므로, 명시적으로 size="normal"을 설정한 경우가 아니라면 업데이트할 필요가 없어요.
이 codemod를 사용해서 size 값을 자동으로 업데이트할 수 있어요:
npx @mui/codemod@latest v7.0.0/input-label-size-normal-medium <path/to/folder>
참고: InputLabel의 기본 size가 normal에서 medium으로 변경됐기 때문에 MuiInputLabel‑sizeMedium 클래스는 더 이상 추가되지 않아요. 커스텀 스타일링에 이 클래스에 의존했다면 다른 클래스를 사용하세요.
SvgIcon의 data-testid 제거 (SvgIcon's data-testid removed)
@mui/icons-material의 아이콘에서 기본 data-testid prop이 프로덕션 번들에서 제거됐어요. 이 변경으로 data-testid prop이 필요한 곳에서만 정의되고, 이름 충돌 가능성을 줄이며 프로덕션에서 불필요한 속성을 제거할 수 있어요.
TablePaginationActions 타입 import 경로 변경 (TablePaginationActions types import path changed)
타입의 import 경로가 @mui/material/TablePagination/TablePaginationActions에서 @mui/material/TablePaginationActions로 변경됐어요.
- import type { TablePaginationActionsProps } from '@mui/material/TablePagination/TablePaginationActions';
+ import type { TablePaginationActionsProps } from '@mui/material/TablePaginationActions';
테마 동작 변경 (Theme behavior changes)
CSS 테마 변수가 내장된 라이트/다크 color scheme과 함께 활성화되면, 테마는 더 이상 모드 사이에서 변경되지 않아요. 아래 스니펫은 사용자가 다크 모드를 토글할 때의 동작을 보여줘요 — useColorScheme의 mode 상태는 변경되지만, 테마 객체는 더 이상 변경되지 않아요:
import {
ThemeProvider,
createTheme,
useTheme,
useColorScheme,
} from '@mui/material/styles';
const theme = createTheme({
cssVariables: {
colorSchemeSelector: 'class',
},
colorSchemes: {
light: true,
dark: true,
},
});
console.log(theme.palette.mode); // 'light' is the default mode
function ColorModeToggle() {
const { setMode, mode } = useColorScheme();
const theme = useTheme();
React.useEffect(() => {
console.log(mode); // logged 'light' at first render, and 'dark' after the button click
}, [mode]);
React.useEffect(() => {
// logged 'light' at first render, no log after the button click
console.log(theme.palette.mode);
}, [theme]);
return <button onClick={() => setMode('dark')}>Toggle dark mode</button>;
}
function App() {
return (
<ThemeProvider theme={theme}>
<ColorModeToggle />
</ThemeProvider>
);
}
이 기본 동작은 모드가 변경될 때 불필요한 재렌더링을 피해 성능을 개선하기 위해 만들어졌어요.
CSS 변수를 직접 참조하려면 스타일의 값으로 theme.vars.*를 사용하는 것이 좋아요:
const Custom = styled('div')(({ theme }) => ({
color: theme.vars.palette.text.primary,
background: theme.vars.palette.primary.main,
}));
런타임 계산이 필요하다면 가능하면 JavaScript 대신 CSS를 사용하는 것이 좋아요. 예를 들어 색상의 알파 채널을 조정하는 것은 color-mix 함수로 할 수 있어요:
const Custom = styled('div')(({ theme }) => ({
color: `color-mix(in srgb, ${theme.vars.palette.text.primary}, transparent 50%)`,
}));
하지만 CSS 접근이 불가능하다면, theme.colorSchemes 객체에서 값을 직접 접근한 다음 라이트와 다크 스타일을 모두 적용할 수 있어요:
const Custom = styled('div')(({ theme }) => ({
color: alpha(theme.colorSchemes.light.palette.text.primary, 0.5),
...theme.applyStyles('dark', {
color: alpha(theme.colorSchemes.dark.palette.text.primary, 0.5),
}),
}));
위의 방법 중 어느 것도 프로젝트에 맞지 않다면, ThemeProvider 컴포넌트에 forceThemeRerender prop을 전달해서 이 동작을 선택 해제(opt out)할 수 있어요:
<ThemeProvider forceThemeRerender />
더 이상 사용되지 않는 API 제거 (Deprecated APIs removed)
v5에서 더 이상 사용되지 않았던 API가 v7에서 제거됐어요.
createMuiTheme 함수
더 이상 사용되지 않는 createMuiTheme 함수가 제거됐어요. 대신 createTheme을 사용하세요.
-import { createMuiTheme } from '@mui/material/styles';
+import { createTheme } from '@mui/material/styles';
Dialog의 onBackdropClick prop
Dialog 컴포넌트에서 더 이상 사용되지 않는 onBackdropClick prop이 제거됐어요. 대신 이벤트와 다이얼로그가 닫히는 이유를 받는 onClose 콜백을 사용하세요. 사용 예시는 다음과 같아요:
function Example() {
const [open, setOpen] = React.useState(false);
const handleClose = (event, reason) => {
if (reason === 'backdropClick') {
// Handle the backdrop click
}
setOpen(false);
};
return (
<Dialog open={open} onClose={handleClose}>
{/* Dialog content */}
</Dialog>
);
}
experimentalStyled 함수
더 이상 사용되지 않는 experimentalStyled 함수가 제거됐어요. 대신 styled를 사용하세요.
-import { experimentalStyled as styled } from '@mui/material/styles';
+import { styled } from '@mui/material/styles';
Hidden 및 PigmentHidden 컴포넌트
더 이상 사용되지 않는 Hidden 및 PigmentHidden 컴포넌트가 제거됐어요.
implementation="css"를 대체하려면 sx prop을 사용하세요:
-<Hidden implementation="css" xlUp><Paper /></Hidden>
+<Paper sx={{ display: { xl: 'none', xs: 'block' } }} />
-<Hidden implementation="css" mdDown><Paper /></Hidden>
+<Paper sx={{ display: { xs: 'none', md: 'block' } }} />
implementation="js"를 대체하려면 useMediaQuery 훅을 사용하세요:
-<Hidden implementation="js" xlUp><Paper /></Hidden>
+const hidden = useMediaQuery(theme => theme.breakpoints.up('xl'));
+return hidden ? null : <Paper />;
Modal의 onBackdropClick prop
Modal 컴포넌트에서 더 이상 사용되지 않는 onBackdropClick prop이 제거됐어요. 대신 이벤트와 모달이 닫히는 이유를 받는 onClose 콜백을 사용하세요. 사용 예시는 다음과 같아요:
function Example() {
const [open, setOpen] = React.useState(false);
const handleClose = (event, reason) => {
if (reason === 'backdropClick') {
// Handle the backdrop click
}
setOpen(false);
};
return (
<Modal open={open} onClose={handleClose}>
{/* Modal content */}
</Modal>
);
}
Rating의 MuiRating-readOnly CSS 클래스
더 이상 사용되지 않는 MuiRating-readOnly 클래스가 Mui-readOnly 전역 클래스를 대신 사용하고자 제거됐어요.
-.MuiRating-readOnly
+.Mui-readOnly
StepButtonIcon 타입
더 이상 사용되지 않는 StepButtonIcon 타입이 제거됐어요. 대신 StepButtonProps['icon']을 사용하세요.
-import { StepButtonIcon } from '@mui/material/StepButton';
+import { StepButtonProps } from '@mui/material/StepButton';
-StepButtonIcon
+StepButtonProps['icon']
StyledEngineProvider import 경로
'@mui/material'에서 StyledEngineProvider를 import하는 것은 더 이상 사용되지 않았고 이제 제거됐어요. 대신 '@mui/material/styles'에서 import하세요:
-import { StyledEngineProvider } from '@mui/material';
+import { StyledEngineProvider } from '@mui/material/styles';
Lab 컴포넌트가 메인 패키지로 이동 (Lab components moved to the main package)
다음 @mui/lab 컴포넌트와 훅이 @mui/material로 이동했어요:
- Alert
- AlertTitle
- Autocomplete
- AvatarGroup
- Pagination
- PaginationItem
- Rating
- Skeleton
- SpeedDial
- SpeedDialAction
- SpeedDialIcon
- ToggleButton
- ToggleButtonGroup
- usePagination
이 컴포넌트와 훅을 계속 사용하려면 @mui/lab 대신 @mui/material에서 import하세요.
-import Alert from '@mui/lab/Alert';
+import Alert from '@mui/material/Alert';
-import { Alert } from '@mui/lab';
+import { Alert } from '@mui/material';
import를 자동으로 업데이트하려면 이 codemod를 사용하세요:
npx @mui/codemod@latest v7.0.0/lab-removed-components <path/to/folder>
:::warning codemod는 컴포넌트와 관련된 타입 import는 다루지 않아요. :::
더 알아보기 (Learn more)
- Deprecations 페이지 — 제거될 예정인 API 목록
- Grid upgrade guide — Grid 업그레이드 가이드
- Node.js — Package exports