MUI v4에서 v5로 이사 준비
Material UI라 불리던 라이브러리가 버전 5가 나오면서 MUI로 이름이 변경되고, 여러가지 변경점이 생겼습니다.
MUI 버전 4의 마이너 버전을 사용하고 있었는데, 아예 버전 4의 마지막 버전 말고 버전 4의 마이너 버전들의 문서가 사라졌습니다...
또한 사용하기 편해진 부분들과 자잘한 버그 픽스들이 있기도 해서, 버전 5로 마이그레이션 준비를 해보겠습니다.
준비하기 전에 리액트와 타입스크립트 최소 요구사항이 아래처럼 변경되었기 때문에 확인해주세요.
The minimum supported version of React was increased from v16.8.0 to v17.0.0.
The minimum supported version of TypeScript was increased from v3.2 to v3.5.
셋업
yarn remove @material-ui/core @material-ui/icons @material-ui/lab yarn add @mui/material @mui/styled-engine-sc
기존 MUI v4 인 @material-ui/
를 삭제해줍시다.
이번 버전 5 업데이트에서 Emotion과 스타일드 컴포넌트를 지원하는데요, 저는 스타일드 컴포넌트를 사용하므로 스타일드 컴포넌트 용 엔진을 사용하겠습니다.
Codemod
Codemod는 js코드의 AST(Abstract syntax tree)를 파싱하고 트랜스폼하는 과정을 regex로 하게 해주는 페이스북에서 만든 라이브러리가 있습니다.
이 codemod 라이브러리를 툴킷형태로 만든 jscodeshift가 있는데요, AST를 estree에 맞게 만들어 주고 regex 형태가 아니라 사용이 좀 더 용이합니다.
따라서 jscodeshift를 사용하면 라이브러리의 메이저 버전이 변경되었을 때 라이브러리 사용자들에게 버전 업그레이드를 좀 더 쉽게 할 수 있도록 도와줄 수 있습니다.
MUI에서 제공하는 codemod(실제로는 jscodeshift를 사용하지만)를 사용하여 버전 4의 코드를 버전 5의 코드로 변경을 조금 더 수월하게 할 수 있습니다.
저는 MUI에서 제공하는 codemod 중 preset-safe를 사용해보겠습니다. MUI에서 버전 4에서 5로 올라가기 위한 codemod들의 코드들을 확인하고 싶다면 이 링크에서 확인해주세요.
변경된 사항들 확인
npx @mui/codemod v5.0.0/preset-safe src
일단 src 전체에게 적용해보겠습니다.
위와같은 결과가 나옵니다.
코드를 확인해보면 IconButton
컴포넌트에 size="large"
가 자동으로 추가되었는데요, size를 적용하지 않으면 디폴트로 medium이 되던 것을 다 large로 바꿔버렸네요...
또 다른 사항은 Box컴포넌트에 css로 사용하던 어트리뷰트 이름이 sx로 변경되었습니다. 이 부분은 의도된 사항이 아니라 다시 css로 전부 변경하였습니다...
현재 스타일드 컴포넌트를 사용중이라, 스타일드 컴포넌트로 css를 작성하고 컴포넌트에 css로 넘겨주거나 styled로 스타일드 컴포넌트를 만들어 사용하고 있었습니다만, v5 부터 sx prop가 추가되었습니다.
Box, Stack, Typography, Grid
에서 추가적으로 스타일드 컴포넌트를 만들 필요 없이 sx 어트리뷰트를 사용하여 인라인에서 MUI에 특화된 테일윈드 같은 단축 css 뿐만 아니라 미디어 쿼리, scss의 네스팅도 비슷한 문법으로 사용할 수 있게 되었습니다.
소개된 장점으로는 styled를 만들고 다시 만든 styled를 사용하는 과정이 없어지고, 태그에 적용된 css가 바로 보이는 점 등이 있겠네요.
단점으로 약간의 퍼포먼스 이슈, MUI 전용 css를 인식하고 있어야하는 점 등이 있겠네요.
장단점을 보고도 기존의 Box 컴포넌트 등의 css를 다 옮기면서까지 해야할 필요성은 못 느끼겠습니다... 같이 혼용에서 쓸 수는 있겠는데, 규칙이 필요할 것 같네요. ?
컴포넌트 부분 이외에도 테마로 px단위를 사용하는 경우 뒤에 px를 붙이지 않아도 되게 되었네요.
스타일드 컴포넌트용 추가 설정
스타일드 컴포넌트를 사용하는 경우 조금 라이브러리 설정이 귀찮아집니다...
서버를 키면 아래와 같은 에러가 나옵니다.
기본적으로 @mui/styled-engine
이 emotion 래퍼이기 때문에 스타일드 컴포넌트를 사용하는 경우 @mui/styled-engine-sc
를 사용하는데요, 이러면 @mui/material
디펜던시로 @mui/styled-engine
를 가지고 있기 때문에 @emotion/react
즉 이모션 설치가 필요해집니다...
하지만 스타일드 컴포넌트만 사용하려면 아래와 같이 package.json을 변경할 필요가 있습니다. (Emotion이 번들 크기도 작다는데 다음부터는 emotion 쓸려고 합니다...)
"dependencies": { ... "@mui/material": "5.0.1", "@mui/styled-engine": "npm:@mui/[email protected]", "@mui/styled-engine-sc": "5.0.0", ... }, "resolutions": { "@mui/styled-engine": "npm:@mui/[email protected]" },
어차피 @mui/styled-engine
과 @mui/styled-engine-sc
는 같은 인터페이스를 사용하기에 위와 같이 해주셔도 문제없습니다.
문서에서는 latest를 사용했지만 버전을 고정해두고 싶어 5.0.0을 사용했습니다.
위와 같이 변경하고 다시 설치해주시면 해결되는 것을 확인하실 수 있습니다.
또한, typescript의 경우 tsconfig.json에
"paths": { "@mui/styled-engine": ["./node_modules/@mui/styled-engine-sc"] }
을 추가해주시거나, skipLibCheck: true
을 설정해주시면 됩니다.
추가 라이브러리 설치
기본적으로 라이브러리 이름이 변경되면서 @material-ui 들이 @mui로 변경되었습니다.
따라서 아이콘이나 스타일, 랩 등 변경된 MUI 버전으로 설치해주셔야 합니다.
yarn add @mui/icons-material @mui/styles @mui/lab
자잘자잘한 픽스들
Select 컴포넌트 onChange 변경사항
왼쪽이 v5 오른쪽이 v4 입니다. 이벤트 타입이 변경되어서 에러를 뿜뿜하고 있었기 때문에 고쳐보겠습니다...
기존의 select 컴포넌트의 onChange를 사용하기 위해 타입을 지정하여
interface Sample { updateOption: (event: React.ChangeEvent<{ name?: string; value: unknown }>) => void; }
와 같이 updateOption을 넘겨 사용하고 있었는데요, 이를
import { SelectChangeEvent } from '@mui/material/Select'; ... interface Sample { updateOption: (event: SelectChangeEvent) => void; }
로 변경하게 되었습니다.
SelectChangeEvent의 타입은 아래와 같습니다.
타입이 숨겨지긴 했지만, 사용하는 입장에서 마우스 호버하면 타입이 보이니 문제 없을 것 같습니다. 아마도... ?
Menu 컴포넌트 getContentAnchorEl 삭제
getContentAnchorEl가 포지셔닝을 심플하게 만들기 위해 사라졌답니다... 그냥 지워줍시다.
Popover 컴포넌트의 설명에 getContentAnchorEl가 없어졌다고 나와있지만, Menu 컴포넌트도 포함인가 봅니다? 정작 Menu 컴포넌트에는 추가 설명이 없지만요...
그래서 지금 버전 올려야 하나?
모르겠습니다... 개인적으로 바로 올려야 하는 이유는 못 찾겠습니다, 어느정도 5.2.x? 5.3.x? 가 되고 나서 자료가 늘어난 후에 올려도 되지 않을까 싶습니다...
그리고 emotion이 확실히 많이 쓴다는 것을 느꼈네요.
Codemod라는 것은 처음 알아서 이것저것 알아보다 AST에 대해 공부가 좀 되었습니다.
아무튼 지금은 바로 올리지는 않을 것 같습니다. Notistack이라는 스낵바 라이브러리를 사용하고 있는데, 이 라이브러리가 아직 MUI v4 이기 때문에 v4, v5 중복되어서 설치해야하기도 하고, makeStyles로 작성한 css들이 조금씩 깨진 것 같기도 하고, 아직 보류할 것 같네요.
프로젝트 마다 에러 팡팡 터지는게 다를 것 같습니다... 화이팅임다 ☺️