storybook을 발견하여 같이 사용 해보기로 하였다.
2. TypeScript : [책"러닝 타입스크립트"]에서 TypeScript는 네 가지로 설명된다고 한다.
즉 TypeScript는 정적 타이핑과 관련됨 장점을 제공하기 위해 설계 되었다.
Storybook은 사용자 인터페이스 컴포넌트를 독립적으로 개발하고 테스트 할 수 있는 환경을 제공하는 도구
Why?
개발 환경 구성
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

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;
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;
🤔 의존성 배열이란?
- 의존성 배열이 비어 있으면 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;
-> 코드가 얼만큼 테스트되고 있는지를 나타내는 소프트웨어의 품질 지표
-> 소프트웨어의 품질 관리를 위한 테스트 작성하기
-> 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");
});