[React] 디자인패턴을 적용해 React의 장점을 살려보자!!!

Jinga·2024년 3월 25일
0

React

목록 보기
28/28
post-thumbnail

'컴포넌트 기반 아키텍처'
이것이 React의 가장 큰 특징 중 하나이며, 가장 큰 장점이라고 생각한다.
컴포넌트 기반 아키텍처는 가독성과 유지보수성, 재사용성이 매우 높다.
React를 사용하기만 한다고 해서는 장점을 잘 살리기는 어렵다.
그럼 어떻게 React를 사용해야 이러한 특징을 잘 살릴 수 있을까?

디자인 패턴

디자인 패턴은 프로그램을 개발하는 과정에서 발생하는 문제를 해결하기 위해 일반적으로 사용되는 설계 패턴들을 말한다. React에서는 이러한 패턴들을 통해 코드의 재사용성, 확장성, 유지보수성을 높일 수 있다.
React에서 자주 사용되는 디자인패턴 중 2가지에 대해 알아보자.

1. Presentational & Container Component Pattern

2015년 Dan Abramov가 처음 소개한 패턴으로, 가장 기본적이고 유명한 패턴이다. 이 패턴은 애플리케이션의 데이터 처리 로직과 UI 마크업을 분리하여 관리하는 방법을 제공한다.

design-container-presentational01

  • Presentational 컴포넌트

    • UI에 집중:
      Presentational 컴포넌트는 주로 UI를 어떻게 보여줄지에 대한 것을 담당한다.
      이 컴포넌트들은 애플리케이션의 스타일과 마크업 구조를 정의하며, 데이터를 직접 조작하지 않는다.

    • Props를 통한 데이터 수신:
      이 컴포넌트들은 Container 컴포넌트로부터 props를 통해 데이터를 받아오며, 이 데이터를 기반으로 화면에 정보를 표시한다.

  • Container 컴포넌트

    • 데이터 관리와 로직 수행:
      Container 컴포넌트는 데이터를 관리하고 애플리케이션의 로직을 수행하는 역할을 한다.
      이 컴포넌트는 상태 관리 라이브러리(예: Redux, Recoil)와 함께 사용되어 애플리케이션의 상태를 관리하고, 필요한 데이터를 처리한다.

    • Presentational 컴포넌트에 데이터 전달: 처리된 데이터는 props를 통해 Presentational 컴포넌트에 전달되어 사용자에게 보여진다.

  • Presentational & Container Component Pattern 코드 예시

    이 예시는 강아지 사진을 불러와 화면에 표시하는 애플리케이션을 구현한 것이다.

    Presentational 컴포넌트: DogImages.js

    import React from "react";
    
    export default function DogImages({ dogs }) {
      return (
        <div>
          {dogs.map((dog, i) => (
            <img src={dog} key={i} alt="Dog" />
          ))}
        </div>
      );
    }
    • 목적:
      Presentational 컴포넌트는 받은 dogs 데이터를 화면에 표시하는 역할을 한다. 각각의 강아지 사진을 img 태그를 사용하여 렌더링한다.
    • Props를 통한 데이터 수신:
      dogs 배열을 props로 받아, 각각의 항목을 순회하며 화면에 표시한다.

    Container 컴포넌트: DogImagesContainer.js

    import React, { useState, useEffect } from "react";
    import DogImages from "./DogImages";
    
    export default function DogImagesContainer() {
      const [dogs, setDogs] = useState([]);
    
      useEffect(() => {
        fetch("https://api.example.com/dogs")
          .then((response) => response.json())
          .then((data) => setDogs(data.dogs));
      }, []);
    
      return <DogImages dogs={dogs} />;
    }
    • 목적:
      Container 컴포넌트는 데이터를 불러오고, 상태를 관리하는 역할을 한다. 이 예시에서는 강아지 사진 데이터를 외부 API로부터 불러온다.
    • Presentational 컴포넌트에 데이터 전달:
      불러온 dogs 데이터를 DogImages 컴포넌트에 props로 전달하여 화면에 표시한다.

    이 예시를 통해 Presentational 컴포넌트와 Container 컴포넌트가 어떻게 분리되어 각각의 역할을 수행하는지 확인할 수 있다. Presentational 컴포넌트는 UI를 담당하고, Container 컴포넌트는 데이터 관리와 비즈니스 로직을 처리한다. 이러한 분리는 코드의 재사용성과 유지보수성을 높이는 데 도움이 된다.

Atomic Pattern

Atomic Design Pattern은 웹과 애플리케이션의 인터페이스 디자인을 위한 방법론으로, Brad Frost에 의해 소개되었다. 이 패턴은 자연계의 원자, 분자, 유기체 등의 개념을 디자인에 적용하여, 인터페이스를 구성하는 가장 작은 단위부터 복잡한 구조까지 체계적으로 설계할 수 있게 돕는다.

  • Atomic Design의 구성 요소

    • Atoms (원자): UI의 가장 기본적인 요소들(예: 버튼, 입력 필드)
    • Molecules (분자): 원자들이 결합하여 더 복잡한 기능을 수행하는 단위(예: 검색 바)
    • Organisms (유기체): 분자들이 모여 더 큰 기능을 수행하는 단위(예: 헤더)
    • Templates (템플릿): 페이지의 구조를 정의하는 레이아웃
    • Pages (페이지): 실제 콘텐츠를 적용하여 사용자에게 보여지는 최종 결과
  • Atomic Design Pattern 코드 예시

    이 예시는 Atomic Design Pattern을 적용한 간단한 Todo 애플리케이션의 구조를 보여준다.

    Atoms: Button.js

    import React from "react";
    
    const Button = ({ onClick, children }) => (
      <button onClick={onClick}>{children}</button>
    );
    
    export default Button;

    Molecules: TodoItem.js

    import React from "react";
    import Button from "../atoms/Button";
    
    const TodoItem = ({ todo, onRemove }) => (
      <div>
        <span>{todo.text}</span>
        <Button onClick={() => onRemove(todo.id)}>Delete</Button>
      </div>
    );
    
    export default TodoItem;

    Organisms: TodoList.js

    import React from "react";
    import TodoItem from "../molecules/TodoItem";
    
    const TodoList = ({ todos, onRemove }) => (
      <div>
        {todos.map((todo) => (
          <TodoItem key={todo.id} todo={todo} onRemove={onRemove} />
        ))}
      </div>
    );
    
    export default TodoList;

    Templates: TodoPageTemplate.js

    import React from "react";
    import TodoList from "../organisms/TodoList";
    
    const TodoPageTemplate = ({ todos, onRemove }) => (
      <div>
        <TodoList todos={todos} onRemove={onRemove} />
      </div>
    );
    
    export default TodoPageTemplate;

    Pages: TodoPage.js

    import React from "react";
    import TodoPageTemplate from "./templates/TodoPageTemplate";
    
    const TodoPage = ({ todos, onRemove }) => (
      <TodoPageTemplate todos={todos} onRemove={onRemove} />
    );
    
    export default TodoPage;

Atomic Design Pattern을 통해 구성 요소를 체계적으로 관리함으로써, UI의 재사용성과 확장성을 높일 수 있다. 각 구성 요소는 독립적으로 개발 및 테스트가 가능하여, 대규모 프로젝트에서도 효율적인 협업이 가능해진다.

정리

지금까지 가장 많이 쓰이는 기본적인 패턴과 재사용성이 좋은 패턴 두가지에 대해 알아보았다.
실제로 Atomic Pattern을 클론코딩, 토이프로젝트에 적용해보았지만 어디까지 Molecules인지, Organisms인지 기준을 정하기가 어려웠고,
Molecules에서 바로 Templates로 넘어가도 괜찮은지 등 컴포넌트를 설계하는 과정과 실제로 사용하는 과정에서 매순간 새로운 고민과 문제가 생겨났다...
분명 패턴에 익숙해지고 사용을 잘 한다면 재사용성과 가독성만큼은 정말 좋아질 것 같은데 그 수준까지 가기가 쉽지 않은 것 같다 ㅎ...

그리고 Presentational & Container Component Pattern을 공부하다보니 이거...Hooks로 대체하면 되는거 아닌가...? 하는 생각이 들어 찾아보니 그렇다고 한다 ㅎㅎ
그래도 알고 넘어가는것과 모르는데 넘어가는것은 다르니 공부하면 좋을 것 같다!.

그래서 일단 Presentational & Container Component Pattern 먼저 익숙해진 뒤, Atomic패턴에 대해 공부하며 프로젝트에 적용해보는게 지금으로선 좀 더 나은 방법인것 같다.

React를 제대로 사용하기 위해 디자인패턴은 필수이지만 위 2가지 패턴말고도 다양한 패턴이 있으니 개인적으로 혹은, 팀내에서 충분한 토의를 거친 뒤 패턴을 선정하고 적용해나가면 협업에서도 큰 도움이 될 것 같다.

profile
다크모드가 보기 좋아요

0개의 댓글

관련 채용 정보