기획자와 디자이너, 개발자가 정해진 방식의 UI 컴포넌트를 미리 디자인하고 개발해 일의 효율성을 높히는 방식을 말한다.
기획자가 처음 제시한 페이지 기획을 통해 디자이너와 개발자가 함께 개발을 완료 한 후, 예상치 못하게 버튼을 추가하는 추가 기획이 도착했다고 했을 때 페이지를 새로 만드는 것이 아니라 어느 페이지에서든지 버튼을 추가하고 기능을 구현할 수 있는 UI 컴포넌트를 공유한다면 효과적일 것이다.
CDD는 부품 단위로 UI 컴포넌트를 만들어 나가는 개발방법이다.
이를 쉽게 개발하기 위해 storybook이라는 UI 개발도구에 대해 공부해보자.
각각의 컴포넌트들을 따로 볼 수 있게 구성해주어 한 번에 하나의 컴포넌트에서 작업할 수 있다.
// button 컴포넌트 생성
import React from "react";
import { Button } from "@storybook/react/demo";
export default {
title: "Button",
component: Button
};
//button 컴포넌트를 커스텀한 primary 컴포넌트
export const Primary = () => (
<Button>Hello Button</Button>
);
//button 컴포넌트를 커스텀한 Secondary 컴포넌트
export const Secondary = () => (
<Button>Bye Button</Button>
);
컴포넌트를 효율적으로 관리하는 것 처럼, CSS도 이러한 관점에서 많은 개발자들이 효율적인 방법을 고민해왔는데 그 이유는 크게 4가지다.
이러한 CSS 방법론은 같이 일하는 팀 동료들의 팀워크와도 연결되기 때문에 여러 팀원이 함께 작업하는 상황에서는 규칙을 정하는 것이 도움이 된다.
Block,Element,Modifier로 구분하여 클래스명을 작성하는 방법
.header__navigation-navi-text
//Block Element Modifier
클래스명을 3가지로 나누어 작성하게되면, 여러 번 반복하여 재사용할 수 있게 되며 HTML/CSS/SASS 파일에서도 일관성 있는 코딩구조를 만들어준다.
그러나 클래스명이 길어지고 재사용할 때마다 모든 UI 컴포넌트를 명시적으로 확장해야 했다.
또한 어플리케이션의 개발 방향이 진화하면서 컴포넌트 단위 개발은 캡슐화(외부에서 내부로직이 보이지 않는 것)를 요구하게됐고, 이는 CSS-in-JS에서도 Styled-Component가 해결하게 된다.
Styled-Component는 React 컴포넌트 기반 개발 환경에서 스타일링을 위한 CSS의 성능 향상을 위해 탄생했다. Styled-Component를 사용하면 기존 CSS 문법으로도 스타일 속성이 추가된 React 컴포넌트를 만들 수 있다.
//a 태그 안에 백틱사용해서 기존 css문법을 사용해서 스타일을 정의한다.
const Button = styled.a`
display : inline-block;
border-radius : 3px;
padding : 0.5rem 0;
margin : 0.5rem 1rem;
width : 11rem;
`
import styled from "styled-components";
// <h1> 태그를 렌더링 할 title component를 만듭니다.
const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
// <section> 태그를 렌더링 할 Wrapper component를 만듭니다.
const Wrapper = styled.section`
padding: 4em;
background: papayawhip;
`;
export default function App() {
// 일반적으로 컴포넌트를 사용하는 것처럼 Title과 Wrapper를 사용하시면 됩니다!
return (
<Wrapper>
<Title>Hello World!</Title>
</Wrapper>
);
}
컴포넌트를 정의하고 이를 다른함수에 props로도 전달할 수 있다.
//Button component
background : ${(props) => (props.primary ? "palevioletred" : "white")}
color : ${(props) -> (props.primary ? "white" : "palevioletred")}
//App component
<Button>Normal</Button>
<Button primary>Primary</Button>
기존 컴포넌트를 수정하고 싶을 때는 styled
태그로 감싼 뒤 변경하고 싶은 속성만 수정해주면 된다.
const Tomato = styled(Button)`
color : tomato;
border-color : tomato;
`'
import "./styles.css";
import styled from "styled-components";
const Button = styled.button`
/* Adapt the colors based on primary prop */
background: ${(props) => (props.primary ? "palevioletred" : "white")};
color: ${(props) => (props.primary ? "white" : "palevioletred")};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
const Tomato = styled(Button)`
color: tomato;
border-color: tomato;
`;
export default function App() {
return (
<div className="App">
<Button>Normal</Button>
<Button primary>Primary</Button>
<Tomato>Tomato</Tomato>
</div>
);
}
styled-component는 props로 전달된 스타일 속성을 우선적용하며 전달된 속성이 없다면 기본설정으로 적용한다.
import styled from "styled-components";
// Styled Component로 만들어진 Input 컴포넌트 입니다.
const Input = styled.input`
padding: 0.5em;
margin: 0.5em;
color: ${(props) => props.inputColor || "red"};
background: papayawhip;
border: none;
border-radius: 3px;
`;
export default function App() {
return (
<div>
{/* 아래 Input 컴포넌트는 styled component인 Input 컴포넌트에 지정된 inputColor(red)가 적용되었습니다. */}
<Input defaultValue="김코딩" type="text" />
{/* 아래 Input 컴포넌트는 props로 전달된 커스텀 inputColor(blue)가 적용되었습니다. */}
<Input defaultValue="박해커" type="text" inputColor="blue" />
</div>
);
}
useRef을 사용하는 대표적인 상황을 이해해보자.
JavaScript를 사용할 때는 우리가 특정 DOM을 선택해야하는 상황이 있다. 보통 getElementById
querySelector
와 같은 DOM Selector 함수를 사용한다.
하지만 React를 사용할 때 useRef Hooks를 사용하게 되면 특정 DOM을 선택할 수 있게 된다.
원하는 위치에 ref={} 형태로 작성하면 특정 DOM을 사용할 수 있게 된다.
useRef()
를 사용해 Ref 객체를 만든다.ref
값으로 설정해준다.import React, { useState, useRef } from 'react';
function InputSample() {
const [inputs, setInputs] = useState({
name: '',
nickname: ''
});
const nameInput = useRef();
const { name, nickname } = inputs; // 비구조화 할당을 통해 값 추출
const onChange = e => {
const { value, name } = e.target; // 우선 e.target 에서 name 과 value 를 추출
setInputs({
...inputs, // 기존의 input 객체를 복사한 뒤
[name]: value // name 키를 가진 값을 value 로 설정
});
};
const onReset = () => {
setInputs({
name: '',
nickname: ''
});
nameInput.current.focus();
};
return (
<div>
//input DOM에 useRef 적용하기.
<input
name="name"
placeholder="이름"
onChange={onChange}
value={name}
ref={nameInput}
/>
<input
name="nickname"
placeholder="닉네임"
onChange={onChange}
value={nickname}
/>
<button onClick={onReset}>초기화</button>
<div>
<b>값: </b>
{name} ({nickname})
</div>
</div>
);
}
export default InputSample;