
랜딩페이지 프로젝트를 진행하면서,
컴포넌트 설계에 대해 정말 많은 고민을 했었다. 어떻게 설계를 하는 것이 좋을까 생각하며 디자인 패턴에 대해 공부하고자 설계 방법론중 중 대표적인 방법론인Presentational and Container pattern에 대해 정리해보았다.
(atom design pattern은 다음에 정리해보도록 하겠다.)
리덕스의 창시자인 댄 아브라모프가 제안한 컴포넌트 관리 패턴 방식이다. 컴포넌트의 재사용성 및 유지 보수의 향상을 위해 데이터 관련 처리가 이루어지는 로직 관련 Container component와 UI만을 담당하는 View 관련 Presentational component 로 나뉜다. 이 둘은 다음과 같은 특징들을 갖고 있다.
일반적으로 DOM markup(JSX or TSX), style 관련 요소들을 갖고 있지 않다.
stateful 한 경향을 갖고 있다. (데이터 관련 로직, 상탯값 등)
Presentaional에 state나 callback 함수를 props 를 통해 전달한다.
DOM markup(JSX or TSX), style 등 UI 관련 요소들을 갖고 있다.
data 관련이 아닌, UI에 관련된 상태값이라면 갖고 있을 수 있다.
props를 통해서, Container에서 관리하는 data나 callback 함수를 전달받는다.
props.children을 통해 다른 컴포넌트를 전달받을 수 있다.
stateless한 경향을 갖고 있다. (store, flux action등 상태 관련 데이터가 존재하지 않는다.)
state나 life cycle 혹은 성능 최적화 관련이 필요함에도 불구하고 함수형 컴포넌트이어야만 한다. (이는 React hooks가 나오기 전에 개념이 도입됐기 때문에 현재는 크게 관계 없는 듯하다.)
// TestContainer.js import React, { useState } from "react"; import TestPresenter from "./TestPresenter.js"; // export default function TestContainer() { const [number, setNumber] = useState(10); // const handleClick = () => { console.log("hello"); }; // return <TestPresenter number={number} handleClick={handleClick} />; }
TestContainer는, 실제 UI로 나타날 TestPresenter를 리턴하며 에서 state 및 handleClick이라는 콜백함수를 props로 전달해준다. (DOM markup, style 관련 요소는 존재하지 않았다.)// TestPresenter.js import React from "react"; // export default function TestPresenter({ number, handleClick }) { return <div onClick={handleClick}>{number}</div>; }
TestPresenter는 UI 관련 요소만 존재하며 TestContainer에서 props로 받은 number, handleClick 함수를 받아 기능이 구현됨을 알 수 있다.