React로 CDD 할수 있는 대표적 도구인 Styled Components의 사용법과,
컴포넌트들을 문서화하고 관리할 수 있는 도구인 Storybook의 사용법을 알아보자.
Styled Components는 CSS를 컴포넌트화해 React 환경에서 사용 가능한 라이브러리이다.
“CSS in JS” 개념에서 파생된 라이브러리로, Styled Components를 사용하면 CSS도 javaScript 안에 넣어줄 수 있어
⇒ “HTML + JS + CSS” 까지 묶어 하나의 JS파일 안에서 컴포넌트 단위로 개발이 가능하다.
# with npm
$ npm install --save styled-components
{
"resolutions": {
"styled-components": "^5"
}
}
import styled from "styled-components"
1)컴포넌트를 선언한 후
2)**styled.태그종류** 를 할당하고
3)백틱 안에 기존 CSS와 같이 스타일 속성을 작성한다.
4)완성한 컴포넌트는 react 컴포넌트를 사용하듯 리턴문 안에 작성해주면
=> 스타일이 적용된 컴포넌트가 렌더된다.
import styled from "styled-components";
//Styled Components로 컴포넌트를 만들고
const BlueButton = styled.button**`**
background-color: blue;
color: white;
**`**;
export default function App() {
// React 컴포넌트를 사용하듯이 사용하면 됩니다.
return <BlueButton>Blue Button</BlueButton>;
}
1)컴포넌트를 선언하고
2)styled() 에 재활용할 컴포넌트를 전달한 다음
3)추가하고픈 스타일 속성을 작성한다.
import styled from "styled-components";
const BlueButton = styled.button`
background-color: blue;
color: white;
`;
//만들어진 컴포넌트를 재활용해 컴포넌트를 만들 수 있습니다.
const BigBlueButton = styled(BlueButton)`
padding: 10px;
margin-top: 10px;
`;
//재활용한 컴포넌트를 재활용할 수도 있습니다.
const BigRedButton = styled(BigBlueButton)`
background-color: red;
`;
export default function App() {
return (
<>
<BlueButton>Blue Button</BlueButton>
<br />
<BigBlueButton>Big Blue Button</BigBlueButton>
<br />
<BigRedButton>Big Red Button</BigRedButton>
</>
);
}
props
를 내려줄 수 있고, 내려준props
값에 따라 컴포넌트를 렌더링할 수 있다.**${ }**
)을 사용해 JavaScript 코드를 사용할 수 있다.const 컴포넌트이름 = styled.태그종류`
css 속성 : ${(props) => 함수코드}
`
삼항연산자를 활용해 <Button>
컴포넌트에 skyblue
라는 props
가 있는지 확인하고
→ 있다면 배경색을 skyblue
로, 없다면 white
로 지정해준다.
const Button = styled.button `
background: ${(props) => props.skyblue ? "skyblue" : "white" }
`;
import styled from "styled-components";
import GlobalStyle from "./GlobalStyle";
//받아온 prop에 따라 조건부 렌더링 가능하다.
const Button1 = styled.button`
background: ${(props) => (props.skyblue ? "skyblue" : "white")};
`;
export default function App() {
return (
<>
<GlobalStyle />
<Button1>Button1</Button1>
<Button1 skyblue>Button1</Button1>
</>
);
}
props.color
가 없다면 white
를 ↔ props.color
가 있다면 props.color
에 있는 스타일 속성 값 그대로를 리턴해준다.const Button = styled.button`
background: ${(props) => props.color ? props.color : "white"}
`;
const Button = styled.button`
background: ${(props) => props.color || "white"}
`;
import styled from "styled-components";
import GlobalStyle from "./GlobalStyle";
//받아온 prop 값을 그대로 이용해 렌더링할 수도 있습니다
const Button1 = styled.button`
background: ${(props) => (props.color ? props.color : "white")};
`;
//다음과 같은 형식으로도 활용할 수 있습니다.
const Button2 = styled.button`
background: ${(props) => props.color || "white"};
`;
export default function App() {
return (
<>
<GlobalStyle />
<Button1>Button1</Button1>
<Button1 color="orange">Button1</Button1>
<Button1 color="tomato">Button1</Button1>
<br />
<Button2>Button2</Button2>
<Button2 color="pink">Button2</Button2>
<Button2 color="turquoise">Button2</Button2>
</>
);
}
createGlobalStyle
함수를 불러온다.import { createGlobalStyle } from "styled-components";
**createGlobalStyle
의 스타일을 설정한다.**const GlobalStyle = createGlobalStyle`
button {
padding : 5px;
margin : 2px;
border-radius : 5px;
}
`
<GlobalStyle>
컴포넌트를 최상위 컴포넌트에서 사용하면 → 전역에 <GlobalStyle>
컴포넌트의 스타일이 적용된다.function App() {
return (
<>
**<GlobalStyle />**
<Button>전역 스타일 적용하기</Button>
</>
);
}
import styled from "styled-components";
import { createGlobalStyle } from "styled-components";
//1. createGlobalStyle로 전역 스타일을 설정하고,
const GlobalStyle = createGlobalStyle`
button {
margin: 0.5rem;
padding: 1rem;
font-size: 2rem;
border-radius: 1rem;
transition: 0.5s;
}
`;
//2. Styled Components로 컴포넌트를 만든다.
const Button = styled.button`
background-color: powderblue;
color: black;
&:hover {
background-color: cornflowerblue;
color: white;
transition: 0.5s;
}
` ;
export default function App() {
return (
<>
<GlobalStyle/>
<Button id="practice">Practice!</Button>
</>
)
}
https://codesandbox.io/s/unruffled-tree-yiwv4?from-embed=&file=/src/App.js
hover
속성 → Styled Components 컴포넌트에 적용하는 방법import styled from "styled-components"; const Button = styled.button` & :hover { background-color : skyblue; color : blue } . . . `;
UI 개발 도구 “Storybook ”
CDD가 트렌드로 자리 잡게 되면서 이를 지원하는 도구 중 하나인 component Explorer(컴포넌트 탐색기)가 등장했는데,
→ 이 컴포넌트 탐색기엔 많은 UI 개발 도구가 있고 그 중 하나가 바로 “storybook”이다.
1)각각의 컴포넌트들을 따로 볼 수 있게 구성해주어 -> 한 번에 하나의 컴포넌트에서 작업할 수 있다.
=> 이를 통해 복잡한 개발 스택을 시작하거나 or 특정 데이터를 데이터베이스로 강제 이동하거나 or 애플리케이션을 탐색할 필요 없이 전체 UI를 한 눈에 보고 개발할 수 있다.
2)재사용을 확대하기 위해 컴포넌트를 -> 문서화하고, 자동으로 컴포넌트를 시각화해 시뮬레이션이 가능한 다양한 테스트 상태를 확인할 수 있다.
=> 이를 통해 버그를 사전에 방지할 수 있다.
3)테스트 및 개발 속도를 향상시키고,
4)애플리케이션도 의존성을 걱정하지 않고 빌드할 수 있다.
- storybook은 기본적으로 독립적인 개발환경에서 실행한다.
→ 덕분에 개발자는 애플리케이션의 다양한 상황에 구애받지 않고 UI 컴포넌트를 집중적으로 개발할 수 있다.- 또 회사 내부 개발자들을 위해 문서화하여 → 회사의 UI 라이브러리로 사용하거나 or 외부 공개용 디자인 시스템을 개발 하기 위한 플랫폼으로도 사용할 수 있다.
package.json
을 통해 사용중인 프론트엔드 라이브러리에 맞는 storybook 사용환경을 만들어 주므로 → 리액트 외에도 다양한 프론트엔드 라이브러리에서 사용 가능하다.npx create-react-app storybook-practice
cd ..
npx storybook init
/.storybook
폴더(in storybook 관련 설정 파일), /.src/stories
폴더(in Storybook 예시 파일)이 생성된다.명령어를 통해 react가 localhost:3000
으로 접근하듯, localhost:6006
으로 접근해 storybook을 실행한다.
실행하면 /.src/stories
폴더에 있는 예시스토리를 확인 할수 있다.
→ storybook 사용으로 (애플리케이션을 실행하고 이벤트를 통해 상태를 변경하는)과정을 거치지 않아도 ⇒ 상태 변화에 따른 컴포넌트의 변화를 확인 할 수 있다.
npm run storybook
#Title.js 파일
import React from "react";
// title은 h1 요소의 textContent, textColor은 글자색이 되는 props입니다.
const Title = ({title, textColor}) => (
<h1 style={{color: textColor}}>{title}</h1>
);
export default Title;
❗️ /.storybook
안에 있는 Storybook 설정 파일에 의해 컴포넌트 파일과 똑같은 파일 이름에 .stories
를 붙여 파일을 만들면 → 알아서 스토리로 인식한다.
#Title.stories.js 파일
// 앞에서 작성한 컴포넌트를 불러옵니다.
import Title from "./Title";
// title : 컴포넌트 이름으로, '/'를 넣어 카테고리화 할 수 있습니다.
// 이후 예시에서 조금 더 자세히 설명합니다.
// component : 어떤 컴포넌트를 가져와서 스토리로 만들 것인지 명시합니다.
// argTypes : 컴포넌트에 필요한 전달인자의 종류와 타입을 정해줍니다.
// 지금은 title, textColor이라는 전달인자에 text 타입이 필요함을 의미합니다.
export default {
title: "Practice/Title",
component: Title,
argTypes: {
title: { control: "text" },
textColor: {control: "text"}
}
}
// 템플릿을 만들어줍니다. 이 템플릿에서는
// Title 컴포넌트가 args를 전달받아 props로 내려줍니다.
const Template = (args) => <Title {...args} />
// Storybook에서 확인하고 싶은 컴포넌트는 export const로 작성합니다.
// 템플릿을 사용하여 Storybook에 넣어줄 스토리를 하나 만들어주었습니다.
// Template.bins({}); 는 정해진 문법이라고 생각하고 사용하시면 됩니다.
export const RedTitle = Template.bind({});
// 만들어준 스토리의 전달인자를 작성해줍니다.
RedTitle.args= {
title: "Red Title",
textColor: "red"
}
// 스토리를 하나 더 만듭니다.
export const BlueTitle = Template.bind({});
// 스토리의 전달인자를 작성해줍니다.
BlueTitle.args= {
title: "Blue Title",
textColor: "blue"
}
❗️storybook은 핫 모듈 리로딩을 지원하므로 → 새로고침 하지 않아도 변경사항을 바로 확인할 수 있다.
title: “Practice/Title”
로 작성한 코드가 좌측 메에서 카테고리로 적용된다.title.stories.js
안에서 만든 두개의 스토리(RedTitle, BlueTitle)가 Title 안에 드러간다.#Title.stories.js 파일 이어서...
export const StorybookTitle = (args) =>{
return <Title {...args} />
}
⇒ 해당 스토리는 전달인자 그대로 변한다.
1️⃣ Button.js 파일 만들고 컴포넌트를 작성한다.
#Button.js 파일
import React from "react";
import styled from "styled-components"
const StyledButton = styled.button`
//props.color가 있으면 props.color를, 그렇지않다면 힌색 배경을 사용한다.
background: ${ (props) => props.color || "white" };
//props.size가 "big"이면 200px를, 그렇지 않다면 100px를 너비로 사용한다.
width: ${ (props) => (props size === "big" ? "200px" : "100px") };
//props.size가 "big"이면 80px를, 그렇지 않다면 4px를 높이로 사용한다.
height: ${ (props) => (props size === "big" ? "80px" : "40px") }
`
const Button = ({color, size, text}) => (
//위에서 작성한 props + text를 받아 textContent로 사용한다.
<StyledButton color={color} size {size} >{text}</StyledButton>
);
export default Button
2️⃣ Button.stories.js 파일도 작성한다.
#Button.stories.js 파일
// 컴포넌트를 불러옵니다.
import Button from "./Button";
export default {
title: "Practice/Button",
component: Button,
// 이번에 작성한 전달인자의 타입은 Storybook을 보고 직접 확인해보세요.
argTypes: {
color: { control: 'color'},
size: { control: { type:'radio', options : ['big', 'small'] }},
text: { control: 'text'}
}
};
export const StorybookButton = (args) => (
<Button {...args}></Button>
)
**control**
로 작성한 control: ‘color’
와 control: { type: ‘radio’, options: [] }
가 각각 어떤 형태로 인자를 전달하는지 확인할 수 있다.참고 : Storybook 공식 문서