네이버 블로그에서 이전, 원글 작성일시 : 2021.10.03.23:48
Riot API, React, Express 를 이용해서 진행 중인 Let U Win 프로젝트.
이름만 들어도 대충 어떤 것인지 이해는 되리라 생각한다.
프로젝트 진행 중,
"React를 쓰는 건 OK, 근데 나 디자인 같은거 할줄 모르는데?"
이때 알아낸것이 UI Library, Material UI(이하 MUI) 이다.
React UI Library라고 구글에 검색하면 몇가지가 나오는데,
이 중에서 "요거 써야지"하고 선택한 것은 아니다.
챔피언 선택창을 구현하기 위해서는 여러 이미지들이 한 컨테이너에 정렬되어 담기는 컴포넌트가 필요했는데,
물색하다보니 MUI에 ImageList가 가장 흡사해서 사용하게 되었다.
설치는 간단하다. npm을 이용하면 끝
궁금하다면 아래를 참고하시길 바란다.
https://mui.com/getting-started/installation/
그 다음은 사용법인데, 별다를게 없다.
1. 위 링크로 들어가서 Components에서 내 마음에 맞는 녀석을 찾는다.
2. 코드를 긁어온다.
3. 내 입맛에 맞게 이것저것 건드리면서 변경
4. 모르는 내용은 Components API 참고!
정말 간단히 사용할 수 있지만 3번 과정 중, 몇가지 헤매다가 알게된 점을 얘기해보려고 한다.
이미 만들어져있는 컴포넌트를 사용하면 좋지만,
생각보다 자잘한 부분에서 내 마음에 안들때가 있더라.
그럼 그부분을 CSS로 간단히 수정해줘야 하는데 어떻게 해야하나?
1. makeStyles()
한가지 예를 들어보자.
import * as React from 'react';
import Button from '@material-ui/core';
export default function BasicButtons() {
return (
<Button variant="text">Text</Button>
);
}
위 Button 컴포넌트의 배경색을 빨간색으로 바꾸고 싶다.
makeStyles()를 이용해서 바꿔보자.
사실 진짜 간단한 거라면, 아래와 같이 바꾸는 것만으로도 가능하다.
하지만 이건 MUI에서만 사용하는 방법은 아니니 패스
<Button variant="text" style={{background:'black'}}>Text</Button>
makeStyle을 사용했을때는 어떻게 되는지 살펴보자
import * as React from 'react';
import Button from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
const useStyles = makeStyles((theme) => ({
root: {
background: 'black',
}
}))
export default function BasicButtons() {
const classes = useStyles();
return (
<Button className={classes.root} variant="text">Text</Button>
);
}
'root' 같은 키는 알아서 적당히 정해주면 된다.
2. CSS in API
MUI에서 컴포넌트를 만들때, 여러 html 태그를 조합해서 만들었을 것이다.
그렇기 때문에 우린 속사정은 알지못하고 밖에서만 조절해야했다.
하지만 불가피하게도 안쪽의 디테일한 부분들을 수정해야할 때가 있는데,
이를 위해 API에 CSS항목이 따로 설명되어 있다.
예를 들어보자.
ImageListItem라는 컴포넌트가 있다.
ImageList 안에 들어가는 아이템, 내 경우에는 작은 정사각형의 챔피언 초상화가 되겠다.
위에서 '가렌' 텍스트를 포함하는 옅은 검은띠가 ImageListItemBar이다.
이 ImageListItemBar의 텍스트 스타일을 바꾸고 싶다면? 어떻게 해야할까.
궁서체로 바꾸거나 글자크기를 수정하거나, 볼드체로 변경할건데,
이전처럼 makeStyles()에 정의해서 ImageListItemBar의 className으로 전달하면 될까?
해보면 알겠지만, 해봐서 알지만, 안된다.
MUI에서 ImageListItemBar API를 찾아보면 아래와 같은 내용이 있다.
ImageListItemBar 안에서의 title에 접근하려면 여길 참고해야한다. 그럼 어떻게 해야할까?
코드를 참고하는편이 빠르겠다.
import {React, useRef} from 'react';
import { makeStyles } from '@material-ui/core/styles';
import ImageList from '@material-ui/core/ImageList';
import ImageListItem from '@material-ui/core/ImageListItem';
import ImageListItemBar from '@material-ui/core/ImageListItemBar';
const useStyles = makeStyles((theme) => ({
imageList: {
width: 560,
height: 550,
alignContent:'flex-start',
},
title: {
fontSize: '0.6em',
fontFamily: ['궁서', '궁서체'],
fontWeight: 'bold'
},
titleWrap: {
margin:'8px'
}
}));
export default function MyImageList(props) {
const classes = useStyles();
return (
<div>
<ImageList rowHeight='auto' className={classes.imageList} cols={6}>
<ImageListItem style={{height:'90px', width:'90px'}}>
<img src="Garen.png" alt="Garen" style={{width:'90px'}}/>
<ImageListItemBar
title="가렌"
classes={{title:classes.title, titleWrap:classes.titleWrap}}
style={{ height: '30px', textAlign:'left'}
}
/>
</ImageListItem>
</ImageList>
</div>
);
}
ImageListItemBar의 classes prop에 위 CSS에서 본 Rule Name을 참고해서 객체형식으로 전달하면 된다.
{
title:classes.title,
titleWrap:classes.titleWrap,
//Rule name : style from makeStyles,
}
이리저리 찾아보며 알게된 뭐랄까, 내 소중한 경험이었지만,
아쉽게도 MUI v5 부터는 위 방법이 deprecated 되었다고 한다.
나도 그동안 프로젝트의 MUI를 업데이트하지 않았어서, 지금 포스팅 중에 찾아보면서 알게되었다.
아쉽지만 미래의 나를 위해 MUI v5 버전 스타일 적용법을 간단히 적어보려고 한다.
(제대로 알아본게 아니고, 당장 예전 버전 코드를 수정해야하니까 찾아본 방법이니 정확하지 않을 수 있다.
더 자세히 알게되는대로 수정할 예정이다.)
사용하는 관점에서 components의 스타일을 수정하는 방법은, 내가 알아본 바로 4가지이다.
1. styled()
import * as React from 'react';
import { styled } from '@mui/system';
import Button from '@mui/material/Button';
const MyComponent = styled(Button)({
background:'black'
});
export default function BasicUsage() {
return <MyComponent>MyBtn</MyComponent>;
}
styled()에서 매개변수로 주어지는 값은 문자열로 주어지면 html 기본 태그와 MUI component인 것으로 보인다.
ex) 'div' -> div 태그, Button -> MUI Button 컴포넌트
말하자면, 베이스 컴포넌트로부터 내입맛에 맞는 컴포넌트를 만들어내서 사용하는 원리이다.
2. sx prop
import * as React from 'react';
import Button from '@mui/material/Button';
export default function BasicButtons() {
return (
<Button sx={{background:'black'}} variant="text">Text</Button>
);
}
공식 설명으로는 CSS를 모두 포함하는 CSS의 상위 집합이라고 한다.
3. createTheme
theme에 대한 설명이 엄청 많던데, 아직은 잘 모르겠으니, 컴포넌트에 적용하는 방법만 보자.
import * as React from 'react';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import Button from '@mui/material/Button';
const theme = createTheme({
components: {
MuiButton: {
styleOverrides: {
root: {
fontSize: '1rem',
background: 'black',
},
},
}
},
});
export default function GlobalThemeOverride() {
return (
<ThemeProvider theme={theme}>
<Button>MyBtn</Button>
</ThemeProvider>
);
}
복잡해보인다...
4. Global CSS
위에서 언급했던 API에서 확인할 수 있는 CSS에서 Global class를 이용해 정적으로 스타일을 적용하는 방법이다.
위 ImageListItemBar를 이용해 간단히 설명해보자면,
아래 root의 global class는 '.MuiImageListItemBar-root'이다.
그렇다면 GlobalCssImageListItemBar.css 파일을 만들어서 아래와 같이 작성하고 저장.
.MuiImageListItemBar-root {
background: red;
}
사용 또는 정의하는 곳에가서 import 만 시키면 끝.
나도 아직 v5에서는 사용해보지 않았기 때문에 어떤 방법이 우선적용되는지 등은 자세히 알지 못한다.
고난이 예상된다... 😮💨
이때까지 deprecated되는 녀석들을 자연스레 피할 수 있었다.
IDE 자체에서 알려주기도 하니까, 내가 조심해야할 부분은 아니라고 생각했다.
흔히들 시대가 빨리 변한다고들 하는데, 막상 피부로 경험하게 되니 신기하면서도 쉽지않다는 걸 느낀다.