Next.jsでAtomic Designを導入してフロントを構成してみよう！

本記事では「Atomic Design」についてご紹介させていただきます。

フロントはNext.jsとTypeScript、デザインパータンとしてAtomic Designを採用して紹介しています。

# 定義

Brad Frost氏によって作成されたUI設計方法論で、パーツ単位でUIデザインを設計する手法のことです。
最小のコンポーネント単位を原子(Atom)に設定してそれを基に上位コンポーネントを作ってコードの再利用を最大化することができます。
最近のJavaScriptを用いた、Webフロント開発はフレームワーク・ライブラリとして主にVueやReactを使用して開発を行う事例が増えてきています。
Vue、Reactはコンポーネント単位で開発を進めることが特徴であるため、コンポーネント中心の設計パターンであるAtomic Designがさらに注目されています。

## Atomic Designのメリット

Atomic Designでは、段階別にコンポーネントを分けることでコンポーネントのリサイクル性を高める仕組みを設計することができます。

- コンポーネントのリサイクル性を高めることができる。
- アプリケーションと分離してコンポーネントを開発・テストできる。 (別のライブラリであるStorybook、Jest等を利用するとコンポーネント単位で確認やテストが可能です)
- 特定のコンポーネントにCSSが強く結合されているため、CSSを管理しやすい。
- 既存のコンポーネントを再利用しているため、デザインを一貫して統一できる。

## Atomic Designのデメリット

コンポーネントのリサイクル性を高める設計が必要になるため、事前のページ要素の確認が必要になり、構成コンポーネントが増えることによる複雑性が高くなる可能性があります。

- リサイクル性の高いコンポーネント設計がないと簡単に進められない。
- コンポーネントの修正が頻繁に発生すると、複雑になり、メンテナンスが困難になる可能性がある。

# 工夫したこと

## フロントエンド開発のコンポーネント構造

### PresentationalコンポーネントとContainerコンポーネントを分ける

Presentationalコンポーネントは画面の見た目を構成する役割を、ContainerコンポーネントはAPIのコールやフロント側のロジックを実行する役割を担っています。

MyContainer.tsx
```
const MyContainer: React.FC<Props> = ({ setErrorRequest }) => {
const { statusForCancellation, cancellationOfferDate, callGetCancellationStatus } = useCancellationStatus();
const { authorizationInfo, memberType } = useAuth();

useEffect(() => {
  ...
}, []);

useEffect(() => {
  ...
}, [currentItem]);


const initSet = async () => {
  try {
    //　APIコールやレンダーする際に必要なデータの設定
    ...
  } finally {
    ...
  }
};

const onChangeCurrentItem = (currentSlideNumber: number) => {
  // イベントロジック処理
  ...
};
/**
  * 渡されたPropsや設定されたstateとflagなどでレンダー判定を行う
  * 判定に従うcomponentをレンダーする。
  * 各コンポーネントはPresentationalコンポーネントに組み立てている
*/
return isLoading ? (
  <Loading />
) : (
  <div className="p-mypage">
    <div className="l-container">
      <div className="l-content--center">
        <MypageEstimateInfo
          data={estimateInfo}
          getEstimateInfo={getEstimateInfo}
          setErrorRequest={setErrorRequest}
        />
      </div>
      <div className="l-content--center">
        <MypageContactContent data={entryInfo} memberType={memberType} />
      </div>
      <ErrorModal
        isOpen={errorDialogRequest.isOpen}
        errorDialogRequest={errorDialogRequest.error}
        onClose={() => setErrorDialogRequest({ ...errorDialogRequest, isOpen: false })}
      />
    </div>
  </div>
);
};
export default MyContainer;
```

MyContactContent.tsx
```
const MyContactContent: React.FC<Props> = ({ data, isContactForm = true, memberType }) => {
return (
  <>
    <div className="o-contactContent">
      <ContentsHeadLine label="お問い合わせ" /> // --> atom
      {isContactForm && <ContactAddressWithFormLink />} // --> molecules
      <TypographyH4>電話でのお問い合わせ</TypographyH4> // --> atom
      <ContactAddressWithForAccident // --> molecules
        tel={CONTACT_ADDRESS_TEL.member}
        isShowForAccident={memberType === MEMBER_TYPE.MEMBER}
      />
    </div>
  </>
);
};
export { MyContactContent };
```
上記のcontainerコンポーネントでAPIから取得した値やロジック処理後に設定した値に基づいて、コンポーネントの構成を判定していることが確認できます。
そして、レンダーされるコンポーネントはcontainerからPropsとして渡された値を通じてpresentationalコンポーネントを組み立てて画面を表示するようになります。

### コンポーネントグループの構成(Atoms, Molecules, Organisms, Template, Pages)

#### 1. Atom
これ以上分解できないデフォルトのコンポーネントです。Atomを結合してMolecule、Organism単位で有用に使用できます。
#### 2. Molecules
複数のAtomを結合して、独自の特性を持ちます。Moleculeの重要な点は一つ仕事をすることですね。

#### 3. Organisms
前のステップよりも複雑で、サービスで表現できる明確な領域と特定のコンテキストを持ちます。Atom、Moleculeに比べてより具体的に表現されるかつ、コンテキストを持つため相対的に再使用性が低くなる特性を持っています。

#### 4. Template
ページを作成できるように、複数のOrganism、Moleculeで構成できます。実際のコンポーネントをレイアウトに配置し、構造化するワイヤフレームです。

#### 5. Pages
ユーザーが見ることができる実際のコンテンツを盛り込んでいます。Templateのインスタンスと言えます。

### Storybookとのシナジー効果がある

StorybookはオープンソースのUIテスターツールです。 Storybookを使えば、UIコンポーネントを作成しながらすぐに描画内容を確認できます。
Storybookライブラリと連携でUI管理がもっとしやすくなります。(UIテストが簡単にできます。)


# まとめ

Atomic Designをプロジェクトに適用しながら、感じたことについてまとめてみました。

- 実際に適用するにあたって曖昧な部分があり、コンポーネントのグルーピングの範囲や分類をプロジェクトに合わせて変形させました。(Organismの範囲外に想定されているコンポーネントはFeaturesという単位で管理するとか)
- 最初から明確な設計がされていないと途中でコンポーネントを再設計・再作成したり、再分類するケースも発生するので注意を払う必要がありました。(階層構造にもっと多くの段階を置くとか)
- デザインチームと開発チームの連携やコミュニケーションがすごく重要だと思いました。(デザインから Atom、Molecule、Orgaism に細分化されて設計されなければならないため)
 各コンポーネントグルーピングの基準についての認識合わせが必要があります。
 設計はデザイナーが担当して開発は開発者がするため、コンポーネント単位の体系化された設計になるためには開発者とデザイナーが一緒に会議で認識を合わせる必要があります。


Atomic Designはメリットとデメリットが確実に存在するため、適用する前にチーム全体として明確に理解して設計すれば協業しやすくメンテナンスが容易なフロント開発環境を構築できると思います。

以上です。
お読みいただきありがとうございます。