[React] Custom Component
CDD(Component Driven Development)
CDD는 재사용할 수 있는 UI 컴포넌트를 미리 생성하고, 컴포넌트를 결합하여 페이지를 조립하는 개발 방법입니다.
CDD 특징
- 부품단위로 UI 컴포넌트를 만들어 나가는 개발을 진행할 수 있다.
- 컴포넌트 단위로 만들어 페이지를 조립하는 개발 방식인 상향식 개발이다.
- 재사용할 수 있는 컴포넌트를 개발할 수 있다.
CSS in JS
구조화된 CSS 등장배경
프로젝트의 규모나 복잡도가 커짐에 따라 CSS 작업을 효율적으로 하기 위해 구조화된 CSS의 필요성이 대두되었고, CSS를 구조화하는 방법에 대한 연구가 필요해졌습니다.
CSS 전처리기 등장
이러한 문제점들을 해결하기 위해 CSS 전처리기(CSS Preprocessor)라는 개념이 등장했습니다. CSS 전처리기란 CSS가 구조적으로 작성될 수 있게 도움을 주는 도구로, 이 CSS 전처리기 자체만으로는 웹 서버가 인지하지 못하기 때문에 각 CSS에 맞는 Compiler를 사용해야 합니다. 이를 통해 CSS 파일들을 잘 구조화할 수 있게 되었고, 최소한 CSS 파일을 몇 개의 작은 파일로 분리할 수 있는 방법이 생겼습니다.
CSS 전처리기 중에서 가장 유명한 SASS(Syntactically Awesome Style Sheets)는 CSS를 확장해 주는 스크립팅 언어입니다. SASS는 자바스크립트처럼 특정 속성의 값을 변수로 선언하여 필요한 곳에 적용할 수 있는 재사용할 수 있게 해 주는 등의 기능을 가졌지만 CSS의 구조화를 해결해 주는 것의 장점보다 컴파일된 CSS의 용량이 어마어마하게 커지는 등의 다른 문제들을 더 많이 만들어낸다는 것이 밝혀졌습니다.
CSS 방법론
CSS 전처리기의 문제를 보완하기 위해 BEM, OOCSS, SMACSS 같은 CSS 방법론이 대두되었습니다. 각각의 장단점이 있으나 결국 세 방법론 모두 같은 지향점을 가지고 있습니다.
방법론의 공통 지향점
- 코드의 재사용
- 코드의 간결화(유지보수 용이)
- 코드의 확장성
- 코드의 예측성(클래스 명으로 의미 예측 가능)
CSS-in-JS의 등장
위의 방법론들에서 클래스명 선택자가 장황해지고, 이런 긴 클래스명 때문에 마크업이 불필요하게 커지며, 재사용하려고 할 때마다 모든 UI 컴포넌트를 명시적으로 확장해야 했습니다. 또한 SASS와 BEM도 고치지 못했던 몇 가지 문제들은 언어 로직 상에 진정한 캡슐화의 개념이 없다는 것이었고, 이로 인해 개발자들이 유일한 클래스명을 선택하는 것에 의존해야 했습니다.
애플리케이션으로 개발 방향이 진화하면서 컴포넌트 단위의 개발은 캡슐화의 중요성을 불러왔습니다. 하지만 CSS는 컴포넌트 기반의 방식을 위해 만들어진 적이 없었고, 결국 CSS도 컴포넌트 영역으로 불러들이기 위해서 CSS-in-JS 가 탄생하게 되었습니다.
CSS-in-JS에는 대표적으로 Styled-Component가 있고, Styled-Component는 기능적 혹은 상태를 가진 컴포넌트들로부터 UI를 완전히 분리해 사용할 수 있는 아주 단순한 패턴을 제공합니다.
Styled Components
CSS in JS 라는 개념이 대두되면서 나온 라이브러리입니다. CSS in JS 라이브러리를 사용하면 CSS도 쉽게 Javascript 안에 넣어줄 수 있으므로, HTML + JS + CSS까지 묶어서 하나의 JS파일 안에서 컴포넌트 단위로 개발할 수 있게 됩니다.
Styled Component 설치하기
1. 터미널에 아래 명령어로 설치
# with npm
$ npm install --save styled-components
# with yarn
$ yarn add styled-components
2. package.json 에 아래 코드 추가하기
// package.json
{
"resolutions": {
"styled-components": "^5"
}
}
3. 사용할 파일에 불러오기
import styled from "styled-components"
Styled Components 문법
1. 기본문법
Styled Compnents 는 ES6의 Templete Literals 문법을 사용합니다. 즉, 백틱(`)을 사용합니다.
const 컴포넌트 이름 = styled.태그종류`
CSS속성 : 속성값;
`
// background-color와 hover 효과
const CustomBtn = styled.button`
background-color:blue;
&:hover{
background-color : skyblue;
color : blue
}
`;
<CustomBtn>CustomBtn</CustomBtn>
2. 컴포넌트 재활용
이미 만들어진 컴포넌트를 재활용해서 새로운 컴포넌트를 만들 수도 있습니다. 컴포넌트를 선언하고 styled() 에 재활용할 컴포넌트를 전달해 준 다음, 추가하고 싶은 스타일 속성을 작성해 주면 됩니다.
const 컴포넌트 이름 = styled(재활용할 컴포넌트)`
추가할 CSS속성 : 속성값;
`;
const CustomBigBtn = styled(CustomBtn)`
margin-top:10px;
`;
3. Props 활용하기
이미 만들어진 컴포넌트를 재활용해서 새로운 컴포넌트를 만들 수도 있습니다. 컴포넌트를 선언하고 styled() 에 재활용할 컴포넌트를 전달해 준 다음, 추가하고 싶은 스타일 속성을 작성해 주면 됩니다.
사용법
const 컴포넌트 이름 = styled.태그종류`
CSS속성 : ${(props) => 함수 코드}
`;
활용 예제
// GlobalStyle.js
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
button {
padding : 5px;
margin : 2px;
border-radius : 5px;
}
`;
export default GlobalStyle;
// App.js
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>
</>
);
}
4. 전역 스타일 설정하기
전역에 스타일을 설정하고 싶을 땐 createGlobalStyle 을 사용합니다.
// GlobalStyle.js
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
button {
padding : 5px;
margin : 2px;
border-radius : 5px;
}
`
// App.js
function App() {
return (
<>
<GlobalStyle />
<Button>Button</Button>
</>
);
}
도움 되는 vscode extension : VSCode-Styled-Components (CSS 백틱 문자열 자동 완성)
Storybook
CDD 가 트렌드로 자리 잡게 되면서 이를 지원하는 도구 중 하나인 Component Explorer(컴포넌트 탐색기)가 등장했습니다. 그 중 하나가 Storybook 입니다.
Storybook은 UI 개발 즉, CDD를 하기 위한 도구입니다. 각각의 컴포넌트들을 따로 볼 수 있게 구성해 주어 한 번에 하나의 컴포넌트에서 작업할 수 있습니다. 재사용성을 확대하기 위해 컴포넌트를 문서화하고, 자동으로 컴포넌트를 시각화하여 시뮬레이션할 수 있는 다양한 테스트 상태를 확인할 수 있습니다.이를 통해 버그를 사전에 방지하여 테스트 및 개발 속도를 향상하는 장점이 있으며, 애플리케이션 또한 의존성을 걱정하지 않고 빌드할 수 있습니다.
사용법
storybook 환경 구축(설치가 완료되면 src/stories 폴더가 설치됩니다)
$ npx stroybook@latest init
$ npm run storybook
명령어를 입력하고 localhost:60060으로 접근하여 Stroybook을 실행시킵니다
useRef
React로 모든 개발 요구 사항을 충족할 수는 없습니다. React 는 가상돔을 사용하기 때문에 DOM을 직접 건드리지 않습니다. 하지만 DOM 객체 주소가 필요한 상황이 계속 발생하여 useRef 메서드가 탄생했습니다.
아래와 같이 DOM 엘리먼트의 주소값을 활용해야 하는 경우에는 특히 그렇습니다.
- focss
- text selection
- media playback
- 애니메이션 적용
- d3.js, greensock 등 DOM 기반 라이브러리 활용
useRef 특징
- DOM 노드, 엘리먼트, 그리고 React 컴포넌트 주소값을 참조할 수 있다
- useRef를 통해 값을 저장 시 리렌더링 후 값이 초기화 되지 않습니다.
- useRef를 남용하는 것은 부적절하고, React의 선언형 프로그래밍 원칙과 배치된다.
function TextInputWithFocusButton() {
// const 주소값을_담는_그릇 = useRef(참조자료형)
const inputEl = useRef(null);
const onButtonClick = () => {
inputEl.current.focus();
};
return (
<>
// <input ref={주소값을_담는_그릇} type="text" />
<input ref={inputEl} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>);
}
위 예제에서 inputEl에는 input DOM이 담깁니다. 이 주소값은 컴포넌트가 re-render 되더라고 바뀌지 않습니다.
'프론트엔드 > Section3' 카테고리의 다른 글
| 네트워크 (2) | 2023.05.01 |
|---|---|
| 웹 표준 & 접근성 (3) | 2023.04.25 |
| React 상태관리 Redux (0) | 2023.04.24 |
| 와이어프레임 & 프로토타입 (1) | 2023.04.13 |
| 사용자 친화 웹 UI/UX (2) | 2023.04.13 |