
얼마전 데브코스에서 진행한 최종 프로젝트를 끝 마쳤는데, 사실 기간이 넉넉하지 않아서 아쉬운 점이 많았다. 그래서 부족하다고 느낌점 + 내가 구현하지 않은 부분 구현을 위해서 개인적으로 리팩토링을 진행하기 시작 했고. 생각보다 MUI를 customize 하는데 애를 먹어서 관련 사항을 정리하고자 한다.
MUI 공식 문서
이 글에서는 Button 컴포넌트를 예시로 진행하려고 한다.
기본적으로 MUI가 제공하는 color가 싫을 수도 있지만, 아마 대부분의 프로젝트에는 보통 main color를 지정하기 마련이다. 따라서 MUI의 color 대신 내 컬러를 사용하고 싶다면 먼저 palette를 수정 해주어야 한다.
// theme.ts
import { createTheme } from "@mui/material/styles";
export const theme = createTheme({
palette: {
primary: {
main: "#4AD395",
// light: main값을 통해 계산됨
// dark: main값을 통해 계산됨
// contrastText: main값을 통해 계산됨
},
}
});
위와 같이 theme을 생성 하였다면 ThemeProvider에 theme을 전달 해주어야 한다.
// index.tsx
import { theme } from "@/styles/theme";
......
root.render(
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
);
위 처럼 적용하면 아래 사진처럼 색상이 변한 것을 확인 할 수 있다.
// code
<Button variant="contained" color="primary">
hello world
</Button>

처음에는 달라진 text 색상 때문에 component option으로 설정 해주었는데 그냥 간단히 contrastText 값에 #fff 값을 주었더니 해결 되었다. 이 외에도 success, info등의 색상을 위처럼 변경 해줄 수 있다.
하지만 단순히 primary를 바꾸는 것이 아닌 자신만의 palette 값을 생성하여 사용하고 싶을 수도 있다.JS의 경우 단순히 palette에 원하는 값을 넣어 주면 되지만 Typescript를 사용하는 경우 선언 파일을 만들어 주어야 한다.(custom값은 rg로 진행)
// theme.ts
import { createTheme } from "@mui/material/styles";
export const theme = createTheme({
palette: {
rg: {
main: "#4AD395",
contrastText: "#fff",
dark: "#339368",
},
},
});
// theme.d.ts
declare module "@mui/material/styles" {
interface Palette {
rg: Palette["primary"];
}
interface PaletteOptions {
rg: PaletteOptions["palette"];
}
export function createTheme(options: ThemeOptions): Theme;
}
하지만 위에 방식까지 적용하고 난 뒤 막상 color에 지정하려고 하면 type error가 발생한다.
// 에러 발생!!
<Button variant="contained" color="rg">
hello world
</Button>
여기서 버튼 컴포넌트 API를 보면 color를 props로 가지고 있다. 또한 type을 보면 inherit, primary, secondary, success, error, info, warning, string으로 되어 있는 것을 볼 수 있다(근데 정작 Button.d.ts에는 string이 빠져있다). 즉 palette에 rg를 추가하기는 했지만, 해당 컴포넌트의 color props에 추가해주지 않아서 이러한 현상이 발생한 것이다. 그럼 여기서 어떻게 props에 rg를 추가 해줄 수 있을까?
이 방법은 공식문서를 보거나 node_modules의 Button.d.ts 파일을 열어보면 알 수 있다.
일단 Button.d.ts 파일을 보면
.....
export interface ButtonPropsColorOverrides {}
.....
props: {
color?: OverridableStringUnion<
'inherit' | 'primary' | 'secondary' | 'success' | 'error' | 'info' | 'warning',
ButtonPropsColorOverrides>;
}
.....
위와 같이 되어 있는데 여기서 ButtonPropsColorOverrides 를 사용하여 override 해주면 원하는 값을 사용할 수 있게 된다.
// theme.tsx
import { createTheme } from "@mui/material/styles";
declare module "@mui/material" {
interface ButtonPropsColorOverrides {
rg: true;
}
}
export const theme = createTheme({
palette: {
rg: {
main: "#4AD395",
contrastText: "#fff",
dark: "#339368",
},
},
});
위 코드 처럼 작성하면 아래 코드의 에러가 사라지는 것을 볼 수 있다.
<Button variant="contained" color="rg">
hello world
</Button>

(다른 컴포넌트들 또한 몇몇 props들은 override 가능하게 해두었다. 만약 override 할 생각이면 해당 컴포넌트 선언 파일을 열어보는 것을 추천한다)
MUI의 컴포넌트 또한 createTheme을 통해서 커스터마이징 가능하다.
MUI API문서를 보면 친절하게 css와 컴포넌트 이름에 관한 내용이 정리 되어 있다.


export const theme = createTheme({
components: {
//Component name
MuiButton: {
styleOverrides: {
// css Rule name
root: {
// css....
},
}
}
}
});
위와 같은 방법으로 사전에 원하는 css를 컴포넌트에 적용 시킬 수 있다.
사실 공식문서만으로 해결하기 힘든 사항들은 위와 같았고, 나머지 커스터 마이징은 MUI 공식문서를 확인하면 쉽게 해결 할 수 있다고 생각한다.