TIL 38일차

안광의·2021년 8월 9일
0

Today I Learned

목록 보기
38/64
post-thumbnail
post-custom-banner

시작하며

오늘은 CSS를 컴포넌트로 분리하여 개발할 수 있는 Component Driven Development 관련 내용을 학습하였고 자주 사용되는 React 기능중 useRef를 학습하였다. 이전에는 CSS의 기본적인 내용을 배웠다면 오늘은 복잡한 프로젝트를 진행하거나 재사용 가능한 컴포넌트를 만들때 필요한 새로운 방법을 학습할 수 있었다.

React

Component Driven Development

Component Driven Development(CDD)란 디자인과 개발 단계에서부터 재사용할 수 있는 UI 컴포넌트를 미리 디자인하고 개발하여 레고처럼 조립해 나갈 수 있는 부품 단위로 UI 컴포넌트를 만들어 나가는 방법을 말한다.

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

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

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



CSS in JS

프로젝트의 규모나 복잡도가 점점 커지고 함께 작업해야할 팀원 수도 많아짐에 따라 CSS를 작성하는 일관된 패턴이 없다는 것은 개발자들에게 가장 큰 걸림돌이 되었고 모바일이나 태블릿을 비롯한 다양한 디바이스들의 등장으로 웹사이트들이 다양한 디스플레이를 커버해야 하기 때문에 CSS는 더 복잡해지게 되었기 때문에 CSS 작업을 효율적으로 하기 위해 구조화된 CSS의 필요성이 대두되었고, CSS를 구조화하는 다양한 방법이 모색되었다.

방법론의 공통 지향점

  • 코드의 재사용
  • 코드의 간결화(유지보수 용이)
  • 코드의 확장성
  • 코드의 예측성(클래스 명으로 의미 예측)
특징장점단점
CSS기본적인 스타일일 방법-일관된 패턴을 갖기 어려움,
!important의 남용
SASS
(preprocessor)
프로그래밍 방법론을 도입하여,
컴파일된 CSS를 만들어내는 전처리기
변수/함수/상속 개념을
활용하여 재사용 가능
CSS의 구조화
전처리 과정이 필요,
디버깅의 어려움이 있음
컴파일한 CSS 파일이 거대해짐
BEMCSS 클래스명 작성에
일관된 패턴을 강제하는 방법론
네이밍으로 문제해결,
전처리 과정 불필요
선택자의 이름이 장황하고,
클래스 목록이 너무 많아짐
Styled-Component
(CSS-in-JS)
컴포넌트 기반으로
CSS를 작성할 수 있게
도와주는 라이브러리
CSS를 컴포넌트 안으로 캡슐화,
네이밍이나 최적화를 신경 쓸
필요가 없음
빠른 페이지 로드에 불리함



Styled Component

styled-components란 Javascript 파일 내에서 CSS를 사용할 수 있게 해주는 대표적인 CSS-in-JS 라이브러리로 React 프레임워크를 주요 대상으로 한 라이브러리이다.

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

JavaScript에서 변수를 선언하듯이(혹은 React 에서 컴포넌트를 만들듯이) Button 을 만들고, tag 의 속성을 정의하고 (여기서는 a tag), back-ticks (``) 안에 기존 CSS 문법을 이용하여 스타일 속성을 정의해 주면 된다.

특징

  • Automatic critical CSS
    Styled Component 는 화면에 어떤 컴포넌트가 렌더링 되었는지 추적해서 해당하는 컴포넌트에 대한 스타일을 자동으로 삽입합니다. 따라서 코드를 적절히 분배해 놓으면 사용자가 어플리케이션을 사용할 때 최소한의 코드만으로 화면이 띄워지도록 할 수 있다.

  • No class name bugs
    Styled Component 는 스스로 유니크한 className 을 생성합니다. 이는 className 의 중복이나 오타로 인한 버그를 줄여준다.

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

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

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

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




Adapting based on props & Extending Styles

// Button component
  background: ${(props) => (props.primary ? "palevioletred" : "white")};
  color: ${(props) => (props.primary ? "white" : "palevioletred")};
// App component
  <Button>Normal</Button>
  <Button primary>Primary</Button>

Styled Component 는 스타일 속성을 지닌 컴포넌트를 정의할 때에 함수를 전달하고, 그 함수 안에서 props 를 사용할 수도 있다.

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

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




useRef

React는 아래와 같이 DOM 엘리먼트의 주소값을 활용해야 하는 경우 useRef으로 DOM 노드, 엘리먼트, 그리고 리액트 컴포넌트 주소값을 참조할 수 있다.

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

예제

import React, { useRef } from "react";
const Focus = () => {
  const firstRef = useRef(null);
  const secondRef = useRef(null);
  const thirdRef = useRef(null);
  const handleInput = (event) => {
    console.log(event.key, event);
    if (event.key === "Enter") {
      if (event.target === firstRef.current) {
        secondRef.current.focus();
        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;
import { useRef } from "react";
export default function App() {
  const videoRef = useRef(null);
  const playVideo = () => {
    videoRef.current.play();
  };
  const pauseVideo = () => {
    videoRef.current.pause();
  };
  return (
    <div className="App">
      <div>
        <button onClick={playVideo}>Play</button>
        <button onClick={pauseVideo}>Pause</button>
      </div>
      <video ref={videoRef} width="320" height="240" controls>
        <source
          type="video/mp4"
          src="https://player.vimeo.com/external/544643152.sd.mp4?s=7dbf132a4774254dde51f4f9baabbd92f6941282&profile_id=165"
        />
      </video>
    </div>
  );
}

마치며

코스를 진행하면서 CSS에 대한 지식이 다른 언어에 비해서 부족하다고 생각했는데 이번 챕터를 통해서 이전 내용을 돌아보고 React의 새로운 내용을 통해 CSS in JS를 학습할 수 있어서 좋은 기회였다. 내일 진행할 스프린트도 잘 진행해서 무리없이 마칠 수 있도록 준비할 예정이다.

profile
개발자로 성장하기
post-custom-banner

0개의 댓글