[TIL 35] 컴포넌트 주도 개발 (Component Driven Development, CDD)

yezo cha·2021년 7월 5일
2

React

목록 보기
5/8
post-thumbnail

컴포넌트 중심으로 UI를 개발하는 방법론에 대해 알아보자.

컴포넌트 주도 개발 (CDD)

  • 컴포넌트를 모듈 단위로 개발하여 사용자 인터페이스(UI) 구축에 도달하는 개발 및 설계 방법론.
  • 기본적인 컴포넌트 단위부터 시작해서 UI view를 구성하기 위해 점진적으로 조립해가는 상향적(bottom-up) 특징을 가지고 있다.

프로젝트 초기부터 UI 컴포넌트를 중심으로

<Button ... />
<Modal ... />
<Chart ... />

와 같이 개발하여 아래의 이점들을 얻기 위함이다.

CDD 장점

  • 디자인 체계화 & 디자이너와 효율적인 협업 : Storybook 같은 UI 컴포넌트 익스플러어 툴을 통해 체계적으로 관리, 디자이너와 쉽게 소통.
  • 평행화 개발(Parallelize development) : 다른 프로젝트에서도 쉽게 쓰고 공유 가능.
  • Decoupling : CSS, JS, I18n, UI 단위 테스트 등

Storybook

Component Driven Development, CDD를 지원하는 UI 컴포넌트 익스플러어 툴.

  • 각각의 컴포넌트를 따로 볼 수 있게 구성하여 한 번에 하나의 컴포넌트에서 작업이 가능하다.
  • 전체 UI를 한눈에 보고 개발할 수 있다.
  • 재사용성을 확대하기 위해 컴포넌트를 문서화하고, 자동으로 컴포넌트를 시각화하여 시뮬레이션할 수 있는 다양한 테스트 상태를 확인할 수 있다.
    -> 버그를 사전에 방지할 수 있고, 테스트 및 개발 속도를 향상시킬 수 있다.

Storybook과 같은 UI 개발 도구를 왜 사용할까?

Storybook은 기본적으로 독립적인 개발환경에서 실행된다.
개발자는 애플리케이션의 다양한 상황에 구애받지 않고 UI 컴포넌트를 집중적으로 개발할 수 있다.

Storybook에서 지원하는 주요 기능

  • UI 컴포넌트카탈로그화
  • 컴포넌트 변화를 Stories로 저장
  • 핫 모듈 재로딩과 같은 개발 툴 경험 제공
  • 리액트를 포함한 다양한 뷰 레이어 지원

리액트 컴포넌트 스타일링

리액트에서 컴포넌트를 스타일링 할 때 가장 기본적인 방법은 css파일을 만들어 컴포넌트에서 import 해서 사용하는 것이다.
이 방법도 충분히 편리할 수 있지만, 더 편하게 쉽게 작업할 수 있는 방법을 알아보자.

  • Sass
  • CSS Module
  • styled-component

Sass

Sass : Syntactically Awesome Style Sheets ; 문법적으로 완전 멋진 스타일 시트.
SassCSS pre-processor로서, 복잡한 작업을 쉽게 할 수 있게 도와주고, 코드의 재활용성을 높여준다.
또한, 코드의 가독성을 높여주어 유지보수를 쉽게 해준다.

Sass에서는 두가지의 확장자(.scss/ .sass)를 지원한다.

sass

$font-stack: Helvetica, sans-serif
$primary-color: #eaeaea

body
  font: 100% $font-stack
  color: $primary-color

scss

$font-stack: Helvetica, sans-serif;
$primary-color: #eaeaea;

body {
  font: 100% $font-stack;
  color: $primary-color;
}
$blue: #228be6;				// 변수 선언

.Button {
  display: inline-flex;
  color: white;
  cursor: pointer;
  background: $blue;			// 사용
  &:hover {
    background: lighten($blue, 10%);	// 색상 10% 밝게
  }
  &:active {
    background: darken($blue, 10%);	// 색상 10% 어둡게
  }
}

더 많은 차이점은 여기에서 확인하자.
보통 scss 문법이 더 많이 사용된다.

CSS Module

리액트 프로젝트에서 컴포넌트를 스타일링 할 때, CSS Module을 사용하면 CSS 클래스가 중첩되는 것을 완벽하게 방지할 수 있다.

레거시 프로젝트에 리액트를 도입하게 될 경우,
또는 클래스 이름 짓는 규칙을 정하기 힘든 상황이거나 번거로울 때 사용하면 좋다 !
CSS 네이밍 규칙을 만들고 따르기 싫다면, CSS Module을 사용하자..

Box.module.css

.Box {
  background: lightgray;
  padding: 2rem;
}

Box.js

import React from 'react';
import styles from './Box.module.css';

function Box() {
  return <div className={styles.Box}>{styles.Box}</div>;
}
export default Box;

className을 설정 할 때에는 styles.Box처럼 import로 불러온 styles 객체 안에 있는 값을 참조해줘야 한다.

Styled-Component

  • Styled-Component는 현존하는 CSS in JS 관련 리액트 라이브러리 중에서 가장 인기 있는 라이브러리.
  • Styled-Component 의 설치는 간단하다.
# with npm
$ npm install --save styled-components

Tagged Template Literal

styled-component를 사용하기 전에, Tagged Template Literal 문법에 대해 짚고 넘어가면 styled-component가 내부적으로 어떻게 작동하는지 이해할 수 있다.

일단, Template Literal에 대해서는 익숙할 것이다.

const name = 'yezo';
const message = `hello ${name}`;

console.log(message);	// "hello yezo"

만약, Template Literal을 사용할 때 ${}안에 문자열, 숫자가 아닌 객체를 넣는다면 어떻게 될까 ?

const obj = { a: 1 };
const message = `${odj}`;

console.log(message);	// "[object Object]"

함수를 넣는다면 어떻게 될까 ?

const fn = () => true;
const message = `${fn}`;

console.log(message);	// "() => true"

Template Literal을 사용하면서, 그 내부에 넣은 자바스크립트 값을 조회하고 싶을 땐 Tagged Template Literal 문법을 사용할 수 있다.

const red = '빨강'
const blue = '파랑'
function favoriteColor(texts, ...values) {
  console.log(texts);
  console.log(values);
}
favoriteColors`내가 좋아하는 색은 ${red}${blue}이다.`

// (3) ["내가 좋아하는 색은 ", "과 ", "이다.", raw: Array(3)]
// (2) ["빨강", "파랑"]

props Styles

styled-component에서는 스타일 속성을 가진 컴포넌트를 정의할 때 함수를 전달하고 그 함수 안에서 props를 읽어오기도 한다.

const styleDiv = styled`
  background: ${props => props.color};
`;
import React from 'react'
import styled from 'styled-component'

const Circle = styled.div`
  width: 5rem;
  height: 5rem;
  background: ${props => props.color || 'black'};
  border-radius: 50%;
`;

function App() {
  return <Circle color='blue' />;
}
export default App;
// Button component
...
  background: ${props => props.primary ? 'palevioletred' : 'white'};
  color: ${props => props.primary ? 'white' : 'palevioletred'};
...

// App component
...
  <Button>Normal</Button>
  <Button primary>Primary</Button>

Extending Styles

같은 스타일 속성을 지닌 여러 개의 컴포넌트들 중에 몇 개의 컴포넌트에는 변화를 주고 싶은 경우, 상속받고자 하는 스타일 속성을 지닌 컴포넌트를 styled()로 감싼 뒤 변경하고 싶은 속성만 새로 정의해준다.
기존 속성을 확장해서 사용 가능하다.

// 기존의 Button 컴포넌트에서 Tomato 컴포넌트만을 위한 새로운 속성을 추가.
const Tomato = styled(Button)`
  color: tomato;
  border-color: tomato;
`;

Advanced

  • styled-component중첩 스타일링을 위해 scss와 같은 전처리 기능을 자동으로 지원하며 ampersnad(&) 기호를 사용한다.
    • ampersnad(&)를 사용하지 않으면 그냥 후손 셀렉터처럼 동작.
    • ampersnad(&) 기호는 컴포넌트 안에서 적용되는 CSS규칙을 확장해 줌으로써 순수 CSSstyled-component를 혼용해야 하는 경우에 각 스타일 간의 충돌을 피하는 데에 유용하다.
  • styled-component의 정의는 render메서드 밖에 정의한다.
    • 만약, 리턴문 안에서 정의된다면 컴포넌트가 리렌더링 될 때마다 스타일 속성을 지닌 컴포넌트가 매번 새로 정의되기 때문에 렌더링 속도 저하에 많은 영향을 준다.
const Thing = styled.div`
  color: blue;

  &:hover {
    color: red; // <Thing> when hovered
  }

  & ~ & {
    background: tomato; // <Thing> as a sibling of <Thing>, but maybe not directly next to it
  }

  & + & {
    background: lime; // <Thing> next to <Thing>
  }

  &.apple {
    background: orange; // <Thing> tagged with an additional CSS class ".apple"
  }

  .banana & {
    border: 1px solid; // <Thing> inside another element labeled ".banana"
  }

  .blueberry {
    background-color: yellow; // an element labeled ".blueberry" inside <Thing> without ampersand(&)
  }
`;
profile
(ง •̀_•́)ง

0개의 댓글