웹 어플리케이션을 개발할 때 돔 요소에 스타일을 적용하기 위해서 CSS 를 이용합니다.
CSS 를 작성하는 전통적인 방법은 CSS를 별도의 파일로 작성하고 HTML의 link 태그를 이용해서 사용자에게 전달하는 것입니다.
순수 CSS 문법은 코드를 재사용하기 힘들기 때문에 SaSS (syntactically awesome stylesheets)를 이용하기도 합니다.
SaSS 에서는 변수와 믹스인 개념이 있어서 중복 코드를 많이 줄일 수 있습니다.
리액트의 UI는 컴포넌트의 조합으로 표현되며, 컴포넌트 하나를 잘 만들어서 여러 곳에 재사용하는 것이 좋습니다.
그렇게 하기 위해서 각 컴포넌트는 서로 간의 의존성을 최소화 하면서 내부적으로는 응집도를 높여주어야 합니다.
컴포넌트는 화면에 보이는 한 부분이므로 당연히 CSS 코드가 필요하게 됩니다.
응집도가 높은 컴포넌트를 작성하기 위해 CSS 코드도 컴포넌트 내부에서 관리하는게 좋습니다.
컴포넌트 내부에서 CSS 코드를 관리하는 방법으로 css-module, css-on-js를 알아보겠습니다.
CSS 를 공부해보기 위해서 폴더를 새로만들기위해 터미널위치를 bookreactjs (지금 코드들을 작성하는곳의 최상단 경로)로 이동시키고 css-test 폴더를 만들면서 설치해보겠습니다.
npx create-react-app css-test 이렇게 만들어보겠습니다.
이렇게 css-test 라는 이름으로 프로젝트를 생성했습니다.
일반적인 CSS 파일로 작성하기
일반적인 css 파일로 스타일을 적용하는 방법을 알아보겠습니다.
src 폴더 밑에 Button1.js Button1.css 파일을 만들고 다음 코드를 입력해 보겠습니다.
Button1.css
.big {
width: 100px;
}
.small {
width: 50px;
}
.button {
height: 30px;
background-color: #aaaaaa;
}
button1.js
import React from 'react';
import './Button1.css';
function Button({ size }) {
if (size === 'big') {
return <button className="button big">큰 버튼</button>;
} else {
return <button className="button small">작은 버튼</button>;
}
}
export default Button;
1. button1.css 파일은 일반적인 CSS파일입니다.
2. CSS 파일도 ESM문법을 이용해서 자바스크립트로! 가져올수 있습니다.
3. button1.css 파일에 정의된 css클래스 명을 입력합니다.
같은 방식으로 Box 컴포넌트를 만들어서 스타일을 적용해 보도록하겠습니다.
Box1.js, Box2.css 파일을 만든다음 코드를 입력합니다.
box1.css
.big {
width: 200px;
}
.small {
width: 100px;
}
.box {
height: 50px;
background-color: #aaaaaa;
}
box1.js
import React from 'react';
import './Box1.css';
function Box({ size }) {
if (size === 'big') {
return <div className="box big">큰 박스</div>;
} else {
return <div className="box small">작은 박스</div>;
}
}
export default Box;
앞의 코드는 버튼 파일의 내용과 크게 다르지 않습니다. 이제 button, box 컴포넌트를 사용하여 App.js 파일을 다음과 같이 수정해보겠습니다.
App.js의 기본내용들을 모두 지운다음 해당 내용을 추가해주겠습니다.
import React from 'react';
import Button from './button1';
import Box from './box1';
export default function App() {
return (
<div>
<Button size="big" />
<Button size="small" />
<Box size="big" />
<Box size="small" />
</div>
);
}
이제 이것을 실행하면 화면에 버튼 두개와 박스 두개가 보입니다.
하지만 버튼의 너비가 조금 이상합니다. 그리고 button1.css 파일에서 small, big 클래스로 정의한 너비가 제대로 적용되지 않은 것같습니다.
npm run build 를 실행해서 build/static/css 폴더 밑에 생성된 css 파일을 확인해 보겠습니다.
보시는 바와 같이 .big 클래스가 중복되어 위의 사진처럼 버튼과 박스 css가 같게보이는 원인이 되는것입니다.
css 클래스명이 같기 때문에 대체되었습니다. 그래서 일반적인 css파일에는 클래스명이 충돌할 수 있습니다.
그 러 나
CSS-module 로 작성하기
css-module 을 사용하면 일반적인 CSS 파일에서 클래스명이 충돌할 수 있는 단점을 극복할 수 있습니다.
css-module은 간결한 클래스명을 이용해서 컴포넌트 단위로 스타일을 적용할 때 좋습니다.
이제 또 테스트를 위해 현재 폴더에서
button2.module.css 파일을 만들어 보겠습니다.
.big {
width: 200px;
}
.small {
width: 100px;
}
.box {
height: 50px;
background-color: #aaaaaa;
}
내용은 동일합니다. 버튼1.css를 복사해서 이름만 바꾸어서 만들었습니다.
그리고 button2.js 의 경우 버튼2.모듈.css 를 임포트해주는쪽으로 작성해보겠습니다.
import React from 'react';
import style from './button2.module.css';
function Button({size}) {
if (size === 'big') {
return <button className={`${style.button}${style.big}` }>큰 버튼</button>;
} else {
return <button className={`${style.button}${style.small}` }>작은 버튼</button>;
}
}
console.log(style);
export default Button;
css-module은 클래스명 정보를 담고 있는 객체를 내보냅니다. css파일에서 정의한 클래스명이 style 객체의 속성 이름으로 존재합니다.
npm run build 를 통해 다시 css를 보겠습니다.
button2.module.css 파일에서 입력한 내용이 변경되어 들어있었습니다.
클래스명에 해시값이 포함되어 있기 떄문에 다른 css 파일에서 같은 이름의 클래스명을 사용하더라도
이름 충돌은 발생하지 않게 되는 것입니다.
button2.js 파일에서 className에 속성값을 입력하는 코드가 번거롭기도 합니다.
그래서 classname 패키지를 이용하면 코드를 개선할 수 있습니다.
classnames 패키지를 설치하고 수정해보겠습니다.
npm install classnames
이제 버튼2.js코드를 리팩토링 해보겠습니다.
import React from 'react';
import style from './Button2.module.css';
import cn from 'classnames';
function Button({ size }) {
if (size === 'big') {
return <button className={cn(style.button, style.big)}>큰 버튼</button>;
} else {
return <button className={cn(style.button, style.small)}>작은 버튼</button>;
}
}
console.log(style);
export default Button;
박스 컴포넌트도 css-module 방식으로 다시 작성해보겠습니다. box1을 복사하고 box2.module.css 파일로 만들겠습니다.
box2.module.css 작성해줍니다.
.big {
width: 200px;
}
.small {
width: 100px;
}
.box {
height: 50px;
background-color: #aaaaaa;
}
box2.js입니다.
import React from 'react';
import style from './Box2.module.css';
import cn from 'classnames';
function Box({ size }) {
const isBig = size === 'big';
const label = isBig ? '큰 박스' : '작은 박스';
return (
<div
className={cn(style.box, { [style.big]: isBig, [style.small]: !isBig })}
>
{label}
</div>
);
}
export default Box;
박스 컴포넌트도 css-module 방식으로 작성해보았습니다.
SaSS로 작성하기
Sass 는 CSS와 비슷하지만 별도 문법을 이용해서 생산성이 높은 스타일 코드를 작성할 수 있게 도와줍니다.
Sass 문법에 있는 변수, 믹스인 등의 개념을 이용하면 스타일코드를 재사용할 수 있습니다.
create-react-app에서 Sass 를 사용하고 싶으면 다음 패키지를 설치해야합니다.
npm install node-sass
node-sass 패키지는 sass를 css로 빌드할 때 사용된다. create-react-app 에는 Sass를 위한 시스템이 구축되어 있습니다.
자바스크립트에서 scss 확장자를 가지는 파일을 불러오면 자동으로 Sass파일이 css파일로 컴파일됩니다.
먼저 공통으로 사용되는 코드를 관리할 shared.scss 파일을 만든 다음 내용을 입력해보겠습니다.
shared.scss 파일내용
$infoColor: #aaaaaa;
Sass 를 이용해서 이전에 작성한 버튼 컴포넌트에 스타일을 적용해 보겠습니다.
button2.module.css, button2.js 파일을 복사해서 button3.module.scss , button3.js 파일을 만들어보겠습니다.
button3.module.scss
@import './shared.scss';
.big {
width: 100px;
}
.small {
width: 50px;
}
.button {
height: 30px;
background-color: $infoColor;
}
button3.js
import style from './button3.module.css';
기존 버튼2.모듈.css 를 맞게 수정했습니다.
box3.module.scss 도 추가해주겠습니다.
@import './shared.scss';
.big {
width: 100px;
}
.small {
width: 50px;
}
.button {
height: 30px;
background-color: $infoColor;
}
box3.js 에도 해당 부분을 수정해주겠습니다.
import style from './Button3.module.scss';
이렇게 한다면 Sass 모듈 시스템 덕분에 스타일 코드를 재사용할 수 있습니다.
App.js 파일에서 button3.js, box3.js 파일을 가져오도록 수정하고
npm start 를 한다면 의도한대로 스타일이 적용된것을 확인 할수 있었습니다.
shared.scss에서 색상정보를 변경해 보겠습니다.
HRM이 동작하면서 변경된 내용이 자동으로 브라우저 화면에 반영됩니다.
npm run build 를 실행 후 생성된 css 파일을 열어보겠습니다.
shared.scss 파일의 변수가 .box, .button 스타일에 적용된 것을 확인할 수 있습니다.
Css-in-js 로 작성하기
css-in-js코드를 자바스크립트 파일안에서 작성합니다.
css코드가 자바스크립트 안에서 관리되기 때문에 공통되는 css 코드를 변수로 관리할 수 있습니다.
또한 동적으로 CSS코드를 작성하기 쉽습니다.
css-in-js를 지원하는 패키지 중에서 가장 유명한 styled-components를 사용해서 간단한 코드를 작성해 보겠습니다.
css-in-js방식을 위해 Box1.js파일을 또 복사해서 마지막으로 box4.js 파일을 만든후 내용을 변경해 보겠습니다.
box4.js
import React from 'react';
import styled from 'styled-components';
const boxCommon = styled.div `
height: 50px;
background-color: #aaaaaa;
`;
const BoxBig = styled(boxCommon)`
width: 200px;
`;
const BoxSmall = styled(boxCommon)`
width: 100px;
`;
function Box({size}) {
if (size === 'big') {
return <BoxBig>큰 박스</BoxBig>;
} else {
return <BoxSmall>작은 박스</BoxSmall>;
}
}
export default Box;
공통 css 코드를 담고있는 styled-componets 컴포넌트를 만들었습니다.
마치 클래스 상속처럼 이전에 만든 boxCommon 컴포넌트를 확장해서 새로운 styled-components 컴포넌트를
만들 수 있습니다.
styled-components 컴포넌트는 일반적인 리액트 컴포넌트처럼 사용될 수 있습니다. styled-componets 컴포넌트를
만들때 사용된 문법이 생소해 보일 수 있습니다. 이는 ES6 에 추가된 태그된 템플릿 리터럴 문법입니다.
App.js 파일에서 box4.js 파일을 가져오게 수정해보겠습니다.
import Box from './box4.js';
실행을 한다면 의도한대로 동작하는 것을 확인할 수 있습니다.
css파일 없이 자바스크립트 파일만으로 스타일을 작성하는데 성공합니다.
css-in-js의 장점인 동적 스타일을 적용해 보겠습니다.
box4.js를 수정해 보겠습니다.
import React from 'react';
import styled from 'styled-components';
const BoxCommon = styled.div `
width : ${props => (props.isBig ? 200 : 100)}px;
heigh : 50px;
background-color : #aaaaaa;`;
function Box({size}) {
const isBig = size ==='big';
const label = isBig ? 'big box' : 'small box';
return <BoxCommon isBig = {isBig}> {label}</BoxCommon>
}
export default Box;
바뀌는 것을 보기위해 한글 큰박스를 영어로 바꾸었습니다.
템플릿 리터럴에서 표현식을 사용하면 컴포넌트의 속성값을 매개변수로 갖는 함수를 작성할 수 있습니다.
동적으로 스타일을 변경하기 때문에 styled-componets 컴포넌트는 하나로 충분합니다.
isBig속성값은 styled-compoents 컴포넌트의 표현식에서 사용됩니다.
'리액트 공부' 카테고리의 다른 글
단일 페이지 애플리케이션 만들기 (0) | 2022.01.23 |
---|---|
AUTOPREFIXER (0) | 2022.01.21 |
Create-react-app으로 시작하기 (0) | 2022.01.20 |
웹팩의 기본 개념 이해하기 (0) | 2022.01.19 |
바벨 사용해 보기 (0) | 2022.01.19 |
댓글