✍️ TILog_01

은유로그·2021년 9월 13일
0

🔥 Log

목록 보기
3/29

목차

  1. storybook 활용 방법
  2. 구조적인 CSS 작성 방법의 발전과 이유
  3. Styled-Component 라이브러리 활용 방법
  4. 리액트의 useRef Hook 활용 방법

Component Driven Development (CDD) 방법론

예를 들어, 한 기획자로부터 A페이지 기획이 도착했고 이를 바탕으로 디자이너와 개발자가 협력해 A페이지를 만들었다. 이후 기획자는 디자이너와 개발자에게 B페이지 기획을 전달했다. B페이지 기획을 살펴보니 A페이지에 동일한 기능을 가진 '버튼'을 사용하도록 요청되었다. 그럼 디자이너와 개발자는 B페이지에 들어가는 '버튼'을 새로 만들어야 할까요?
'버튼' UI 컴포넌트를 만든다면, A페이지 뿐만 아니라 B페이지에서도 사용이 가능하다. 즉, 재사용이 가능한 UI 컴포넌트를 만들면 된다. 이를 해결하기 위해 등장한 것이 바로 Component Driven Development ( CDD ) 방법론이다.

실제로 CDD 방법을 활용하여 UI 를 구축하는 사이트 : BBC

Storybook

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

Storybook 설치 - 공식 문서

구조적인 CSS 작성 방법의 발전과 이유

요즘은 PC 뿐만 아니라 모바일, 태블릿PC를 통해 다양한 환경(디바이스)에서 인터넷 사용을 한다. 그 말은 다양한 디바이스에 적용시키기 위해 CSS가 복잡해졌다는 뜻이다. 그래서 작업을 효율적으로 하기 위해 구조화된 CSS의 필요성이 대두되었고, 구조화하는 방법에 대한 연구가 필요해졌다. 이러한 문제점을 해결하기 위해 CSS 전처리기(CSS Preprocessor)라는 개념이 등장했다. 그러나 전처리기가 내부에서 어떤 작업을 하는지도 모른채 스타일이 겹치는 문제를 해결하기 위해 단순히 계층 구조를 만들기 급급했고, 용량은 어마어마하게 커졌다. 이 문제점을 보완하기 위해 BEM, OOCSS, SMACSS 같은 CSS 방법론이 나타났고 아래와 같은 지향점을 갖고있다.

  • 코드의 재사용
  • 코드의 간결화(유지보수 용이)
  • 코드의 확장성
  • 코드의 예측성(클래스 명으로 의미 예측)

그러나 이러한 방법론들에서도 문제점이 나타났다. 클래스명 선택자가 장황해지고, 이러한 긴 클래스명 때문에 마크업이 불필요하게 커지며 재사용할 때마다 모든 UI 컴포넌트를 명시적으로 확장해야만 했다. 또한 캡슐화의 개념이 없었기 때문에 개발자들은 유일한 클래스명을 선택하는 것에 의존할 수 밖에 없었다.
결국 CSS-in-JS가 탄생하고 이 문제를 정확하게 해결했다. 대표적으로 Styled-Component가 있다. Styled-Component는 기능적 혹은 상태를 가진 컴포넌트들로부터 UI를 완전 분리해 사용할 수 있는 아주 단순한 패턴을 제공한다.

Styled-Component

Styled Component는 React 의 컴포넌트 기반 개발 환경에서 스타일링을 위한 CSS의 성능 향상을 위해 탄생했다. Styled Component 를 사용하면 기존 CSS 문법으로도 스타일 속성이 추가된 React 컴포넌트를 만들 수 있다.

const Button = styled.a`
  display: inline-block;
  border-radius: 3px;
  padding: 0.5rem 0;
  margin: 0.5rem 1rem;
  width: 11rem;
`;

위의 코드를 해석해보자면,
Button이란 변수를 선언하고 tag 속성을 정의한다. 위 코드에선 a태그를 정의했다. 그 뒤 백틱(``) 안에 기존 CSS 문법을 이용해 스타일 속성을 정의했다.
Styled Component의 특징은 아래와 같다.

  • Automatic critical CSS : Styled Component 는 화면에 어떤 컴포넌트가 렌더링 되었는지 추적해서 해당하는 컴포넌트에 대한 스타일을 자동으로 삽입한다.

  • No class name bugs : Styled Component 는 스스로 유니크한 className 을 생성한다.

  • Easier deletion of CSS : 모든 스타일 속성이 특정 컴포넌트와 연결되어 있기 때문에 만약 컴포넌트를 더 이상 사용하지 않아 삭제할 경우 이에 대한 스타일 속성도 함께 삭제된다.

  • Simple dynamic styling : className을 일일이 수동으로 관리할 필요 없이 React 의 props 나 전역 속성을 기반으로 컴포넌트에 스타일 속성을 부여하기 때문에 간단하고 직관적이다.

  • Painless maintenance : 컴포넌트에 스타일을 상속하는 속성을 찾아 다른 CSS 파일들을 검색하지 않아도 되기 때문에 코드의 크기가 커지더라도 유지보수가 어렵지 않다.

  • Automatic vendor prefixing : 개별 컴포넌트마다 기존의 CSS 를 이용하여 스타일 속성을 정의하면 된다. 이외의 것들은 Styled Component 가 알아서 처리해준다.

styled-component 설치 방법

!! 터미널에 아래 명령어 둘 중 하나를 입력한다 !!
# with npm
$ npm install --save styled-components

# with yarn 
$ yarn add styled-components


!! Styled Component 에서는 package.json에 다음 코드를 추가하도록 권장하고 있습니다. 아래의 코드를 추가하면 여러 버전의 Styled Component가 설치되어 발생하는 문제를 줄여줍니다. !!
{
  "resolutions": {
    "styled-components": "^5"
  }
}

리액트의 useRef Hook 활용 방법

React에 내장된 Hook API 중 useRef 설명 공식 문서

const refContainer = useRef(initialValue); // useState처럼 따로 선언해준다
// const 주소값을_담는_그릇 = useRef(참조자료형)

...생략...

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      // React에서 사용 가능한 ref라는 속성에 주소값을_담는_그릇을 값으로 할당하면
      // 주소값을_담는_그릇 변수에는 input DOM 엘리먼트의 주소가 담깁니다.
      // 향후 다른 컴포넌트에서 input DOM 엘리먼트를 활용할 수 있습니다.
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}

위 코드는 리액트 공식 문서 중 useRef 설명 부분에서 긁어온 코드다.

import React, { useRef } from "react";

const Focus = () => { // Focus 컴포넌트 정의
  const firstRef = useRef(null);
  const secondRef = useRef(null);
  const thirdRef = useRef(null);

  const handleInput = (event) => { // handleInpu 이벤트 정의
    console.log(event.key, event);
    if (event.key === "Enter") { // 엔터 키를 입력했으면
      if (event.target === firstRef.current) { // firstFef의 현재와 입력된 타겟이 같으면
        secondRef.current.focus(); // secondRef로 집중!
        event.target.value = ""; // 입력된 타켓은 빈 문자열로 초기화
      } else if (event.target === secondRef.current) {
        thirdRef.current.focus();
        event.target.value = "";
      } else if (event.target === thirdRef.current) {
        firstRef.current.focus();
        event.target.value = "";
      } else {
        return;
      }
    }
  };

  return (
    <div>
      <h1>타자연습</h1>
      <h3>각 단어를 바르게 입력하고 엔터를 누르세요.</h3>
      <div>
        <label>hello </label>
        <input ref={firstRef} onKeyUp={handleInput} />
      </div>
      <div>
        <label>world </label>
        <input ref={secondRef} onKeyUp={handleInput} />
      </div>
      <div>
        <label>codestates </label>
        <input ref={thirdRef} onKeyUp={handleInput} />
      </div>
    </div>
  );
};

export default Focus;


위 코드는
만약 hello 문자열 옆 input에 무언가를 작성하고 엔터키를 눌렀을 때, world 문자열 옆 input으로 focus 되고, hello 문자열 옆 input에 적혀있던 문자열은 사라진다.
world 문자열 옆 input에 무언가를 작성하고 엔터키를 눌렀을 때, codestates 문자열 옆 input으로 focus 되고, world 문자열 옆 input에 적혀있던 문자열은 사라진다.
codestates 문자열 옆 input도 위와 똑같이 실행된다.

profile
๑•‿•๑

0개의 댓글