新規開発だからこそデザインシステムは導入すべき
こんにちは。LayerXのしばです。
LayerXではFintech事業部に所属し、三井物産とのJVである三井物産デジタルアセットマネジメント(以下MDM)で、個人向け事業(ALTERNA)の立ち上げをしています。
自宅では、ウイスキーのアドベントカレンダーを楽しんでます。
※本記事は LayerX Tech Advent Calendar 2022 6日目の記事となります。
MDMでのお仕事
MDMではALTERNAの開発を担当しています。フロントエンドもバックエンドも開発しますが、フロントエンドをメインで担当しています。
ALTERNAは個人向けのデジタル証券の取引プラットフォームです。
今冬のリリースを目指しており、開発状況としてもリリースに向けて大詰めという状況です。
リリースに先駆けて、事前登録受付中なのでぜひチェックしてみてください!
今日のテーマ
この記事ではMDMでのフロントエンドの開発プロセスを振り返ります。
ALTERNAでは開発初期からデザインシステムを導入しました。
それにより、開発生産性が高く、変更に強いフロントエンド基盤を実現できたのでその方法について書いていきます。
新規開発におけるデザインシステムの運用
モチベーション
過去のプロダクトの反省からALTERNAの開発においてはデザインシステムの整備を行い、開発の効率化をしたい思いがありました。
cssが共通化されておらず、新規画面開発の度にコピペしてcssを記述しており1画面あたりの開発コストが高い。
フォントや色定義が定数管理されていないため、画面間でデザインに差が発生したり、修正漏れが発生しやすい。
開発初期からデザインシステムの整備・共通コンポーネントの開発を行うと、要件・デザインの変更によって作り直しが発生する可能性が高いと思います。
また、コンポーネントなどの基盤整備が開発のブロッカーとなることも想定されます。
そのため、共通化などを後回しにして機能開発を優先することは不確実性の高い新規開発においてはよくあると思います。
一方で、リリースが近づき運用が始まってしまうと手が入れられなくなる部分でもあります。(忙しさやデグレの恐怖ですね)
MDMの開発プロセス
MDMの開発プロセスの特徴はデモドリブンで開発することを目指しています。そのため、改善のサイクルはとても速いです。
過去の反省と開発プロセスの特徴から、開発生産性が高く、変更に強いフロントエンド基盤にしたいという思いがあり、開発初期からデザインシステムの整備を推進しました。
ALTERNAのフロントエンドの開発は以下のフローで進めました。
メイン画面を数パターンデザイン作成し、潜在ユーザにヒアリングを実施しつつプロダクト全体のトンマナを決定
主要画面のデザイン作成
主要画面のデザインからコンポーネントを抽出しデザインシステムを整備
storybookを用いてコンポーネントを開発
コンポーネントを利用して各画面を実装
このデザインシステム・コンポーネントの整備を開発の初期から実践したのが開発プロセス上の特徴です。
また、最初から全てのコンポーネントを定義しないのも大事な特徴です。
デザインからコンポーネントを抽出して必要なコンポーネントを整備するようにしています。
ChakraUIを使ったコンポーネント開発
ALTERNAのフロントエンドはNext.jsとChakra UIを利用しています。
CSSフレームワークとして、MUIと比較検討をしてChakra UIを採用しました。
Chakra UIの選定理由
ALTERNAでは、MUIと比較検討Chakra UIを採用しました。採用理由は以下です。
MUIの場合、リッチなアニメーションなどが標準で実装されており、それをデザインに合わせて無効化するコストが高い
フォーム関連のコンポーネントの多くがuncontrolled componentなので、react-hook-formと組み合わせやすい
MDMの別プロジェクトで利用しているため、ナレッジシェアによるシナジーへの期待
サンプル
コンポーネント実装はChakra UIのテーマカスタマイズ機能を最大限利用する形で実装しました。
以下がサンプルです。
_app.tsx
function MyApp(props: MyAppProps) {
...
return (
...
// ChakraProviderを設定
<ChakraProvider theme={theme}>
{getLayout(<Component {...pageProps} />)}
</ChakraProvider>
)
}
theme.ts
import { extendTheme } from '@chakra-ui/react'
export const theme = extendTheme({
...
// fontやsizeなどのglobalな定義を記述
components: {
baseStyle: {},
sizes: {
lg: {},
md: {},
sm: {},
},
variants: {
primary: {
// ここに個別のvariantに対する定義を記述
},
secondary: {},
},
defaultProps: {
variant: 'primary',
size: 'lg',
},
}
})
Button.tsx
import React from 'react'
import { Button as CButton, ButtonProps as CButtonProps } from '@chakra-ui/react'
// variantは利用可能なもののみを指定可能とする
export type Props = {
variant?: 'primary' | 'secondary'
} & Omit<CButtonProps, 'variant'>
function Button(props: Props) {
// 連打抑止などの共通処理を必要に応じて実装
return <CButton {...props} onClick={onClick} />
}
export default memo(Button)
基本的には公式の方法に沿って、テーマをカスタマイズして利用しています。ポイントは以下です。
variantを独自に定義し、propsでchakraのデフォルトのvariantをオーバーライドしています。これによって、デザインシステム上で定義していないvariantは使用不可にできることと、開発中にvariantの種類に補完が効くメリットがあります。
Chakraのコンポーネントを直接importするのではなく、ラップしたコンポーネントを用意することで、chakraを利用したコンポーネントから自前のコンポーネントに移行する際のコストを最小化できます。
storybookを用いた開発
コンポーネント開発において、storybookが大きく役立ちました。
コンポーネント開発は、storybookを記述することから始めます。
ローカルのstorybookでコンポーネント単体での動作を確認しつつ開発を進められます。
また、chromaticと連携することで開発したコンポーネント単位でレビューも可能です。
新規開発でデザインシステムを導入する意義
開発初期からデザインシステムの整備とコンポーネントを整備することには自分は強いこだわりがあったので、デザイナーさんと一緒にデザインシステムの導入を推進しました。
結果として、デザインシステムの導入は意図通り以下の効果をもたらしてくれました。
デザインの変更に対して、最小限の修正で変更が完了するので、修正漏れが発生しない。それによって、変更を恐れずに改善を進められる。
使用可能なコンポーネントが決まっているので、画面開発のコストが劇的に下がった。
今後について
ここまで、うまくいった話をしてきましたが、まだまだ足りないところが沢山あるのが現状です。
今後はフロントエンドのテストコードの整備やネイティブアプリの開発などやりたいことは沢山あります。
一緒に働く仲間を募集しています
ALTERNAはこれからグロースと新規開発を並行して進めていくフェーズになります。そのための、デザイナー・エンジニア共に募集しています。
興味がある方、是非ご応募お待ちしてます!