💡 이번 시간에는 UI 컴포넌트를 테스트할 수 있는 Storybook이라는 툴에 대해 알아보았다!
1. storybook이란
1) 스토리북은 무엇일까?
- 스토리북은 UI 컴포넌트의 동작을 독립적인 환경에서 테스트할 수 있는 툴이다.
- 스토리북에 추가된 컴포넌트는 서비스와 독립된 환경에서 렌더링되기에, 재사용 가능한 컴포넌트여야 한다.
- 스토리북은 개발자가 컴포넌트의 동작을 파악하는데 도움을 준다.
- 또한 figma 연동도 가능하기에 디자이너와의 커뮤니케이션에도 효과가 있다.
- 아래 gif는 스토리북의 예시이다.
🤔 컴포넌트를 테스트하기 위해 스토리북을 쓰는 거라면, 이 툴을 쓰지 않고 서버를 구동해서 컴포넌트 동작을 확인하면 안될까? 그렇게 해도 된다.
- 하지만 재사용가능한 컴포넌트가 UI 컨셉에 맞게 구현되어 있는지 여부를 알고 싶거나
- UI 컴포넌트의 커스텀 속성이나 동작을 알고 싶거나
- 특정 로직을 거쳐야 접근 가능한 컴포넌트인 경우(회원탈퇴시 보이는 안내문) 스토리북이 유용하다.
2) 스토리북 구성
💡 스토리북에는 “스토리”라는 개념이 존재하는데,
스토리는 UI 컴포넌트의 랜더링된 상태를 캡처한 걸 말한다.
개발자는 스토리북 서버를 구동하여, 각 스토리의 동작이나 UI를 확인할 수 있다.
스토리북 서버를 구동하면 아래와 같은 화면이 나오는데 크게Canvas
,Docs
로 구성된다.
(1) Canvas 영역
구성 | 설명 |
---|---|
A. Story 리스트 | - 추가한 Story목록이다. |
B. 미리보기 영역 | - 해당 Story를 미리 보거나, 마우스 인터렉션을 통해 이벤트를 확인할 수 있다. |
C. 애드온 영역 | - StoryBook에서 애드온을 추가하여 기능 확장이 가능하다. (대부분의 스토리북 기능은 애드온으로 구현) - Controls 애드온의 경우, Story의 이벤트 체크는 물론, props 값을 변경하여 스타일을 확인할 수 있다. |
(2) Docs 영역
구성 | 설명 |
---|---|
D. Docs | - 스토리에 대한 Props, 이벤트에 대한 설명을 볼 수 있다. - 자동 생성되며, 커스터마이징할 수 있다. |
3) 스토리북 환경설정하는 방법
💡 vite + vue3 환경에서 스토리북을 어떻게 설정하는지 알아보자
(1) 환경 구축하기
- yarn으로
vite
를 설정한다.
yarn create vite
- 그 다음 아래 명령어를 사용해
storybook
설정을 한다.
npx sb init --builder @storybook/builder-vite
yarn add -D @storybook/cli
npx storybook@next automigrate
- 만약
sass
기반으로 스타일링을 한다면,sass
를 추가하자.
yarn add -D sass
yarn storybook
을 했을 때, 아래 이미지와 같은 화면이 나오면 성공이다!
yarn storybook
(2) Story 작성하기
💡 스토리북 설정도 했겠다.
예시 컴포넌트(BaseInput.vue
)의 스토리를 작성해보자! (레포)src/components/ui/BaseInput.vue
코드는 더보기에서 여기서 확인 가능하다.
- src/stories에
BaseInput.stories.js
를 추가한다. - 컴포넌트 스토리에 대한 기본 설정을 한다.(title, component, argTypes)
import BaseInput from "../components/ui/BaseInput.vue";
// 컴포넌트 스토리 기본 설정
export default {
title: "Example/BaseInput", // 스토리 제목
component: BaseInput, // 사용할 컴포넌트 등록
argTypes: { // 컴포넌트의 props 목록, 스토리북에서 조작할 수 있도록 설정
label: "",
placeholder: "",
onInput: {},
},
};
- 컴포넌트 템플릿을 정의한다.
스토리북에서 컴포넌트 렌더링시, 어떤 데이터를 바인딩하고 어떤 형태로 보여줄지 정의하는 것이다.
// 컴포넌트 템플릿 정의
const Template = (args) => ({
components: { BaseInput },
// args는 setup() 메서드를 통해 템플릿에 매핑되어야 함
setup() {
return { args };
},
// 그리고 `args`는 `v-bind="args"`형태로 컴포넌트에 바인딩됨
template: '<base-input v-bind="args" />',
});
- 상세 스토리를 정의한다.
// 상세 스토리를 정의
export const NameInput = Template.bind({}); // 앞서 정의한 템플릿을 사용함
NameInput.args = {
label: "이름",
placeholder: "이름을 입력하세요",
};
- 서버를 구동해보면, 아래와 같은 화면을 볼 수 있다.
개발자는Controls
를 사용해 데이터를 변경하거나Actions
에서 이벤트를 확인할 수 있다.
- 더 많은 예시를 보고 싶다면 이 스토리북 공식 링크로 이동하자!
2. storybook 구현시 주의사항
💡 UI 컴포넌트를 독립된 환경에서 볼 수 있는 툴이라니! 너무 좋은데?
그런데 이 Storybook을 구현할 때 주의해야할 몇 가지 있다. 같이 알아보자~
(1) 컴포넌트를 데이터에 종속시키지 말자
- 스토리는 독립된 환경에서 작동되어야 한다.
- 그러나 만약 스토리에서 렌더링하는 컴포넌트 내부에 api나 route 로직이 있다면?
- 해당 컴포넌트만 분리해서 스토리에 등록시 무수히 많은 에러를 보게될 것이다 😖
- 만약 데이터가 필요하다면, 외부에서 데이터를 인자로 넘겨주는 방식으로 컴포넌트를 수정하자.
(2) 데이터 타입을 명시하자
- 만약 스토리에
Button
컴포넌트가 있고, 이 컴포넌트가size
값에 따라 형태가 달라진다고 가정해보자.
// stories/Button.stories.js
export default {
title: 'Example/Button',
component: MyButton,
argTypes: {
...
size: 'small', // 'small', 'medium', 'large'
},
};
- 그런데 만약 개발자가 size를 컨트롤할 때
String
값을 입력하게 한다면, 의도된 렌더링을 할 수 없다ㅠ
- 이 경우, 의도된 데이터대로 값을 조작해야 한다면, 옵션 형태로 제공하는 게 좋다.
// stories/Button.stories.js
export default {
title: "Example/Button",
component: MyButton,
argTypes: {
...
size: {
control: { type: "select" }, // this!
options: ["small", "medium", "large"], // this!
},
},
};
- 다행히 스토리북에서는 컨트롤하는 데이터의 타입을 정의할 수 있다 🙂
- 타입 종류는 여기서 확인하자!
(3) 컴포넌트가 재사용성이 떨어지면 안된다.
- 버튼 컴포넌트에 대한 스토리를 추가하고자 한다.
- 해당 버튼은 A 서비스에서 쓰일 때는 버튼 상단에 20px 여백이 필요하다.
- 그래서 버튼 컴포넌트를 만들 때 버튼 상단을 20px로 고정해두었다.
<!-- Button.vue -->
<button type="button" class="simple-btn" @click="onClick">
{{ label }}
</button>
<style lang="scss" scoped>
.simple-btn {
margin-top: 20px; /* 상단 위치 고정 지정 */
}
</style>
💡 하지만 B 서비스에서 쓰일 때는 버튼 상단 여백이 10px이어야 한다면?
- B 서비스용 버튼 컴포넌트를 만들어야 할까? 아니다.
- 각 서비스 별로 버튼 컴포넌트의 상단 여백 값이 달라져야 한다면, 상단 여백값을 컨트롤할 수 있게 정의해야 한다.
<!-- Button.vue -->
<button type="button" class="simple-btn" @click="onClick" :style="props.style">
{{ label }}
</button>
<script>
const props = defineProps({
style: { // this!
type: Object,
default: () => { marginTop: '20px' }
}
})
</script>
- 이처럼 스토리에 추가되는 컴포넌트의 경우, 재사용성을 가지는지 체크하는 게 좋다.
💡 이번 시간에는 스토리북에 대해 알아보았다.
스토리북은 재사용 가능한 UI 컴포넌트에 대한 동작을 미리 볼 수 있는 툴로서,
개발자와 디자이너간의 소통을 원활히 해준다.
환경 설정의 경우 큰 어려움없이 가능하다.
단, 도입시 UI 컴포넌트에 대해 팀과 팀의 소통과 협의 과정이 중요하다고 생각된다.
'개발 기술 > 개발 이야기' 카테고리의 다른 글
[JS] AbortController로 웹 요청 취소하기(비동기, dom 이벤트) (0) | 2023.02.26 |
---|---|
[npm] package.json의 version 방식, tilde(~)와 caret(^) (0) | 2023.01.29 |
리플로우, 리페인트와 브라우저 렌더링 알아보기 (2) | 2023.01.02 |
[CSS/JS] 웹 폰트를 최적화하는 5가지 방법 (0) | 2022.12.04 |
husky로 Conventional Commit 체크하기 (2) | 2022.11.19 |
댓글