React Story Book 사용기

keepgoing·2023년 6월 3일

React

목록 보기
4/6
post-thumbnail

⭐️ 메인 프로젝트가 끝난 후..

  • 메인 프로젝트에서 재사용 가능한 컴포넌트 작성과 문서화의 중요성을 느꼈다.
  • 재 사용성을 위하여 기존 코드를 typeScript로 리팩토링하려고 했다.
    -> 기존의 코드는 JavaScript로 작성한 후 Jsdoc를 사용하여 다른 팀원들이 사용하기 쉽게 작성하였다.
  • 그러던 중 storybook을 발견하여 같이 사용 해보기로 하였다.

🤔 Jsdoc과 typeScript??

  1. JsDoc : JSDoc은 JavaScript에 문서화를 추가하는 도구이다.
    주석을 통해 함수나 클래스, 변수 등의 설명을 제공하고 예상되는 입출력, 동작을 문서화한다.
    JS 코드 자체에는 영향을 미치지 않는다.


2. TypeScript : [책"러닝 타입스크립트"]에서 TypeScript는 네 가지로 설명된다고 한다.

  • 프로그래밍 언어 : 자바스크립트의 모든 구문과, 타입을 정의하고 사용하기 위한 새로운 타입스크립트 고유 구문이 포함된 언어
  • 타입 검사기 : 작성된 파일에서 생성된 구성 요소를 이해하고, 잘못 구성된 부분을 알려주는 프로그램
  • 컴파일러 : 타입 검사기를 실행하고 문제를 보고한 후 이에 대응되는 자바스크립트 코드를 생성하는 프로그램
  • 언어서비스 : 타입 검사기를 사용해 비주얼 스튜디오 코드와 같은 편집기에서 개발자에게 유용한 유틸리티 제공법을 알려주는 프로그램

즉 TypeScript는 정적 타이핑과 관련됨 장점을 제공하기 위해 설계 되었다.

🤔 Story book??

Storybook은 사용자 인터페이스 컴포넌트를 독립적으로 개발하고 테스트 할 수 있는 환경을 제공하는 도구

Why?

  1. 컴포넌트 기반 개발 : 재사용성을 높이고, 개발 속도를 향상 시키고, 개별 정돈 편리
  2. 인터랙티브 문서화 : Storybook은 컴포넌트의 다양한 상태를 시각적으로 표현할 수 있다.
  3. 개발자 경험 개선 : 자동 테스트, 접근성 검사등 테스트가 용이하다.

코드를 작성해보자.

개발 환경 구성
1. typescript 템플릿 기반 React 애플리케이션 생성
npx create-react-app . --template typescript
2. storybook 설치
npx sb init or 현재 공식 문서 npx storybook@latest init
3. styled-components 사용
npm install styled-components
npm install --save-dev @types/styled-components

step1. 버튼 확인 하기

  • 버튼 코드를 먼저 작성해보자
  • app.js에서 CustomButton.tsx을 먼저 확인 해보자.
  1. 처음으로 작성한 코드 tsx와 인라인 스타일을 사용하였다.
export interface ButtonProps {
  clickHandler: () => void;
  buttonText: string;
  backgroundColor: string;
  color: string;
}

function CustomButton({ buttonText, backgroundColor = "blue", color, clickHandler }: ButtonProps) {
  const style = {
    backgroundColor,
    color,
  };
  return (
    <button onClick={clickHandler} style={style}>
      {buttonText}
    </button>
  );
}

export default CustomButton;

App.tsx의 코드이다.
코드를 작성하다보니 너무 조잡한 것 같아 다른 방법을 찾아보았다.

import CustomButton, { ButtonProps } from "./components/CustomButton";

function App() {
  const handleClick = () => {
    console.log("버튼을 클릭합니다.");
  };

  const buttonProps: ButtonProps = {
    clickHandler: handleClick,
    buttonText: "테스트 버튼",
    backgroundColor: "blue",
    color: "white",
  };
  return (
    <div className="App">
      <CustomButton {...buttonProps} />
    </div>
  );
}

export default App;
  1. props로 전달하는 방식의 코드

App.tsx만 수정 되었다.

하지만 성능에 영향을 주는 코드 🥹
핸들러 함수(clickHandler)가 매번 렌더링될 때마다 새로 생성된다.
=> useCallback 훅을 사용하여 함수를 메모제이션 해야한다.

import CustomButton from "./components/CustomButton";

function App() {
  return (
    <div className="App">
      <CustomButton buttonText="테스트버튼" backgroundColor="blue" color="white" clickHandler={() => console.log("버튼을 클릭합니다.")} />
    </div>
  );
}

export default App;
  1. props로 전달하는 방식의 코드 + useCallback을 사용하기

🤔 의존성 배열이란?

  • 의존성 배열이 비어 있으면 useCallback이나 useEffect는 해당 컴포넌트가 처음 렌더링될 때만 콜백을 생성하거나 효과를 실행
  • 의존성 배열에 특정 값을 넣게 되면, 그 값이 변경될 때마다 새로운 콜백을 생성하거나 효과를 실행
  • 특정 state 값을 의존성 배열에 포함할 수 있다!
import React, { useCallback } from "react";
import CustomButton from "./components/CustomButton";

// 버전2 useCallBack 사용
function App() {
  const handleClick = useCallback(() => {
    console.log("버튼을 클릭합니다.");
  }, []); // 의존성 배열이 비어 있으므로, handleClick은 컴포넌트가 처음 렌더링될 때 한 번만 생성
  return (
    <div className="App">
      <CustomButton buttonText="Click me!" backgroundColor="blue" color="white" clickHandler={handleClick} />
    </div>
  );
}

export default App;

컴포넌트 테스트하기

  • 기존 코드를 재 작성 후 테스트 시작하기
  • Cra에 기존에 설치되어 있는 테스팅 툴을 사용하여 테스트해보자.

Jest Test Coverage

-> 코드가 얼만큼 테스트되고 있는지를 나타내는 소프트웨어의 품질 지표
-> 소프트웨어의 품질 관리를 위한 테스트 작성하기
-> pakage.json에 설정

"jest": {
  "collectCoverageFrom": [
    // 코드 커버리지를 수집할 파일들을 지정합니다.
    "<rootDir>/src/components/**/*.{ts,tsx}",
    // "<rootDir>"은 프로젝트의 루트 디렉토리를 가리킵니다.
    // "*.{ts,tsx}"는 .ts 또는 .tsx로 끝나는 모든 파일을 선택합니다.
    "!**/node_modules/**",
    // "!"로 시작하는 패턴은 이 패턴에 해당하는 파일을 제외하라는 의미입니다.
    // 따라서 node_modules 디렉토리 안의 모든 파일들은 제외됩니다.
    "!**/*.stories.{ts,tsx}"
    // 마찬가지로 .stories.ts 또는 .stories.tsx로 끝나는 파일들도 제외합니다. 
    // 이는 주로 스토리북 스토리 파일들에 해당합니다.
  ]
}

스크립트 명령어 추가 "test:coverage" : "react-scripts test --watchAll=false --coverage"

결과는 coverage/icov-report/index.html을 보면 확인이 가능하다.

커버율이 나오는데 기존 100프로가 되지 않았기에 아래 코드를 추가 작성하고 100%로 작성하였다.


test("CustomButton 렌더링 테스트 - 기본값", () => {
  render(<CustomButton label="Default Button" />);

  const button = screen.getByRole("button");

  expect(button).toHaveTextContent("Default Button");
  expect(button).toHaveStyle("backgroundColor: black");
  expect(button).toHaveStyle("color: white");
});
profile
매일매일

0개의 댓글