[React] Custom Component

Hyun Jin·2023년 2월 20일
0

REACT

목록 보기
3/6

Chapter1. Component Driven Development

Chapter1-1. CDD

Component Driven Development (CDD) : 부품 단위로 UI 컴포넌트를 만들어 나가는 개발.

재사용할 수 있는 컴포넌트를 개발 가능하며, 컴포넌트 단위로 만들어 페이지를 조립하는 개발 방식인 상향식 개발에 가까움.

Chapter1-2. CSS-in-JS

구조화된 CSS 작성 방식의 발전

CSS 의 진화 참고 링크

구조화된 CSS의 필요성이 대두된 배경

  1. 프로젝트의 규모나 복잡도가 점점 커지고 함께 작업해야 할 팀원 수도 많아짐
  2. 다양한 디바이스들의 등장으로 더 복잡해진 CSS

CSS 구조화를 위한 다양한 시도

  1. CSS Preprocessor (CSS 전처리기) : CSS 가 구조적으로 작성될 수 있게 도움을 주는 도구. 프로그래밍 개념(변수, 함수, 상속 등) 활용

  2. SASS (Syntactically Awesome Style Sheets) : CSS 를 확장해 주는 스크립팅 언어. 변수 및 여러곳에서 변수 재사용 등의 기능을 가짐. SCSS 코드를 읽어서 전처리한 후 컴파일해서 전역 CSS 번들 파일을 만들어주는 전처리기(Preprocessor)의 역할을 함.
    그러나 CSS 구조화를 해결해주는 것의 장점보다 컴파일된 CSS의 용량이 어마어마하게 커지는 단점이 발견됨.

  3. BEM, OOCSS, SMACSS 같은 CSS 방법론의 대두

    • 방법론의 공통 지향점
      • 코드의 재사용
      • 코드의 간결화(유지 보수 용이)
      • 코드의 확장성
      • 코드의 예측성(클래스 명으로 의미 예측)
    • BEM
      Block, Element, Modifier로 구분하여 클래스명을 작성하는 방법이며, Block, Element, Modifier 각각은 —와 __로 구분함.
      클래스명은 BEM 방식의 이름을 여러 번 반복하여 재사용할 수 있도록 하며 HTML/CSS/SASS 파일에서도 더 일관된 코딩 구조를 만들어 주지만,
      클래스명 선택자가 장황해지고, 이런 긴 클래스명 때문에 마크업이 불필요하게 커지며, 재사용하려고 할 때마다 모든 UI 컴포넌트를 명시적으로 확장해야만 하는 단점 존재. 또한 SASS와 BEM도 고치지 못했던 몇 가지 문제들은 언어 로직 상에 진정한 캡슐화(encapsulation : 객체의 속성과 행위를 하나로 묶고 실제 구현 내용 일부를 외부에 감추어 은닉하는 개념)의 개념이 없다는 것이었고, 이로 인해 개발자들이 유일한 클래스명을 선택하는 것에 의존할 수밖에 없었음.
  4. CSS-in-JS의 등장 - Styled-Component

    Styled-Component는 기능적(Functional) 혹은 상태를 가진 컴포넌트들로부터 UI를 완전히 분리해 사용할 수 있는 아주 단순한 패턴을 제공함.

Chapter2. CDD 개발 도구

Chapter2-1. Styled Components

CSS in JS 라이브러리를 사용하면 CSS도 쉽게 Javascript 안에 넣어줄 수 있으므로, HTML + JS + CSS까지 묶어서 하나의 JS파일 안에서 컴포넌트 단위로 개발할 수 있게 됩니다. 이런 CSS in JS 라이브러리 중에서 현재 가장 인기 있는 라이브러리가 바로 Styled Components 입니다.

Styled Components 설치하기

  1. npm install
# with npm
$ npm install --save styled-components

# with yarn
$ yarn add styled-components
  1. Styled Components는 package.json에 다음 코드를 추가하도록 권장하고 있음(아래의 코드를 추가하면 여러 버전의 Styled Components가 설치되어 발생하는 문제를 줄여줌)
{
  "resolutions": {
    "styled-components": "^5"
  }
}
  1. 사용할 파일로 Styled Components import 해오기.
import styled from "styled-components"

Styled Components 문법

1. 컴포넌트 만들기

Styled Components는 ES6의 Templete Literals 문법, 즉 따옴표가 아닌 백틱(`)을 사용함

Untitled

컴포넌트를 선언한 후 styled.태그종류를 할당하고, 백틱 안에 기존에 CSS를 작성하던 문법과 똑같이 스타일 속성을 작성해주면 됩니다. 이렇게 만든 컴포넌트를 React 컴포넌트를 사용하듯 리턴문 안에 작성해주면 스타일이 적용된 컴포넌트가 렌더되는 것을 확인할 수 있습니다.

Untitled

https://codesandbox.io/s/confident-driscoll-w6i4t6?file=/src/App.js

2. 컴포넌트를 재활용해서 새로운 컴포넌트 만들기

이미 만들어진 컴포넌트를 재활용해서 새로운 컴포넌트를 만들 수도 있습니다. 컴포넌트를 선언하고 styled() 에 재활용할 컴포넌트를 전달해준 다음, 추가하고 싶은 스타일 속성을 작성해주면 됩니다.

Untitled

이미 만들어진 컴포넌트를 재활용해서 새로운 컴포넌트를 만들 수도 있습니다. 컴포넌트를 선언하고 styled() 에 재활용할 컴포넌트를 전달해준 다음, 추가하고 싶은 스타일 속성을 작성해주면 됩니다.

Untitled

https://codesandbox.io/s/proud-platform-kt7obx

3. Props 활용하기

Styled Component로 만든 컴포넌트도 React 컴포넌트처럼 props를 내려줄 수 있습니다. 내려준 props 값에 따라서 컴포넌트를 렌더링하는 것도 가능합니다.

Styled Components는 템플릿 리터럴 문법( ${ } )을 사용하여 JavaScript 코드를 사용할 수 있습니다. props를 받아오려면 props를 인자로 받는 함수를 만들어 사용하면 됩니다.

1) Props로 조건부 렌더링하기

Untitled

위 코드의 경우는 삼항연산자를 활용해 <Button> 컴포넌트에 skyblue 라는 props가 있는지 확인하고, 있으면 배경색으로 skyblue를, 없을 경우 white를 지정해주는 코드입니다. 이 코드에 따라 렌더링된 <Button> 컴포넌트는 아래 그림과 같을 것입니다.

Untitled

Button1 의 경우는 skyblue 라는 props가 있어 배경색이 skyblue 로 지정됐고, Button2의 경우는 props가 아예 없어 배경색이 white 로 지정된 것을 확인할 수 있습니다.

Untitled

2) Props 값으로 렌더링하기

3번과 비슷하게, props의 값을 통째로 활용해서 컴포넌트 렌더링에 활용할 수 있습니다.

Untitled

똑같이 삼항연산자를 사용하고 있지만, 이번에는 props.color 가 없다면 white를, props.color 가 있다면 props.color의 값을 그대로 가져와서 스타일 속성 값으로 리턴해주고 있는 것을 볼 수 있습니다. 그 결과 color 라는 이름으로 받은 props의 값으로 배경색이 지정된 것을 확인할 수 있습니다.

Untitled

꼭 삼항연산자만 사용해야하는 것은 아닙니다. JavaScript 코드라면 무엇이든 사용할 수 있으므로 원하는 값을 사용할 수 있도록 함수 코드를 만들어서 사용하면 됩니다. 따라서 위 예시와 같은 코드도 활용할 수 있을 것입니다. props도 원하는 만큼 받아서 사용할 수 있으니 다양하게 활용해보세요.

Untitled

https://codesandbox.io/s/exciting-kapitsa-sghyky?file=/src/App.js

4. 전역 스타일 설정하기

스타일을 컴포넌트로 만들 수 있다는 것은 좋지만, 전역에 스타일을 설정하고 싶을 땐 어떻게하면 좋을까요? Styled Components는 이런 경우를 대비한 컴포넌트도 준비해놓았습니다.

우선 전역 스타일을 설정하기 위해 Styled Components에서 createGlobalStyle 함수를 불러옵니다.

import { createGlobalStyle } from "styled-components";

그 다음 이 함수를 사용해 CSS 파일에서 작성하듯 설정해주고 싶은 스타일을 작성합니다.

const GlobalStyle = createGlobalStyle`
	button {
		padding : 5px;
    margin : 2px;
    border-radius : 5px;
	}
`

이렇게 만들어진 <GlobalStyle> 컴포넌트를 최상위 컴포넌트에서 사용해주면 전역에 <GlobalStyle> 컴포넌트의 스타일이 적용됩니다.

function App() {
	return (
		<>
			<GlobalStyle />
			<Button>전역 스타일 적용하기</Button>
		</>);
}

잘 살펴보면 3. Props 활용하기의 예제에서 이미 위 코드와 같은 전역 스타일이 설정되어 있음을 알 수 있습니다. 코드를 보고 <GlobalStyle> 이 어떻게 적용되어 있는지 살펴보세요.

실습

hover 속성 적용하기

const RoundBtn = styled.button`
  background: ${(props) => props.color || "white"};
  border-radius: 35px;

// hover 를 넣을 스타일 컴포넌트 안에 &hover 를 넣고 그 안에 호버시에 변경될 CSS 내용을 적어주면 됨.

  &:hover {
    background: purple;
    color: white;
  }
`;

Chapter2-2. Storybook

컴포넌트 UI 개발을 위한 Storybook

Storybook이 무엇인가요?

Storybook은 UI 개발 즉, Component Driven Development를 하기 위한 도구입니다. 각각의 컴포넌트들을 따로 볼 수 있게 구성해 주어 한 번에 하나의 컴포넌트에서 작업할 수 있습니다. 복잡한 개발 스택을 시작하거나, 특정 데이터를 데이터베이스로 강제 이동하거나, 애플리케이션을 탐색할 필요 없이 전체 UI를 한눈에 보고 개발할 수 있습니다.

Storybook은 재사용성을 확대하기 위해 컴포넌트를 문서화하고, 자동으로 컴포넌트를 시각화하여 시뮬레이션할 수 있는 다양한 테스트 상태를 확인할 수 있습니다. 이를 통해 버그를 사전에 방지할 수 있도록 도와줍니다. 또한 테스트 및 개발 속도를 향상시키는 장점이 있으며, 애플리케이션 또한 의존성을 걱정하지 않고 빌드할 수 있습니다.

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

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

아래 예시처럼 회사의 내부 개발자들을 위해 문서화(documentation)를 하여 회사의 UI 라이브러리로써 사용하거나, 외부 공개용 디자인 시스템(Design System)을 개발하기 위한 기본 플랫폼으로 사용할 수 있습니다.

Untitled

Storybook에서 지원하는 주요 기능은 다음과 같습니다.

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

튜토리얼

https://github.com/storybookjs/storybook

Introduction to Storybook

유어클래스 | 코드스테이츠 학습 플랫폼 UrClass

Chapter3. useRef

DOM reference를 잘 활용할 수 있는 useRef

지금까지 React를 공부하면서 익히셨던 내용을 돌이켜보면, React만 가지고 거의 대부분의 프론트엔드 요구사항을 구현할 수 있었습니다. DOM 지식이 필요 없다고 생각하실지도 모르겠습니다. 하지만 React로 모든 개발 요구 사항을 충족할 수는 없습니다. 아래와 같이 DOM 엘리먼트의 주소값을 활용해야 하는 경우 특히 그렇습니다.

  • focus
  • text selection
  • media playback
  • 애니메이션 적용
  • d3.js, greensock 등 DOM 기반 라이브러리 활용

React는 이런 예외적인 상황에서 useRef 로 DOM 노드, 엘리먼트, 그리고 React 컴포넌트 주소값을 참조할 수 있습니다. 아래 예시 코드처럼 작성하시면 주소값을 활용할 수 있습니다.

const 주소값을_담는_그릇 = useRef(참조자료형)
// 이제 주소값을_담는_그릇 변수에 어떤 주소값이든 담을 수 있습니다.
return (
    <div>
      <input ref={주소값을_담는_그릇} type="text" />
        {/* React에서 사용 가능한 ref라는 속성에 주소값을_담는_그릇을 값으로 할당하면*/}
        {/* 주소값을_담는_그릇 변수에는 input DOM 엘리먼트의 주소가 담깁니다. */}
        {/* 향후 다른 컴포넌트에서 input DOM 엘리먼트를 활용할 수 있습니다. */}
    </div>);

이 주소값은 컴포넌트가 re-render 되더라도 바뀌지 않습니다. 이 특성을 활용하여 아래의 제한된 상황에서 useRef 를 활용할 수 있습니다.

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>);
}

제시된 상황 제외한 대부분의 경우 기본 React 문법을 벗어나 useRef 를 남용하는 것은 부적절하고, React의 특징이자 장점인 선언형 프로그래밍 원칙과 배치되기 때문에, 조심해서 사용해야 합니다.

profile
새싹 프론트엔드 개발자

0개의 댓글