[React] Container-Presenter 패턴

do_large·2020년 11월 24일
3

React

목록 보기
9/11
post-thumbnail

개요(인척하는 넋두리)

React의 가장 기본적인 디자인 패턴인 Container Presenter 패턴을 오늘처음알게되었다..

혼자 공부하면서 내 코드가 많이 복잡하고 유지보수가 어려운 코드라는 것을 알면서도 더 나은방법을 몰랐었기때문에, 작동하는데에 의의를 두고 개발을 했었다. 기존에는 싱글파일 컴포넌트 형태로 개발을 했었는데, 컴포넌트내부에 ui와 로직 api호출들이 점점 많아지게 되면서 가독성이 너무 떨어졌다.

그러던 중 이 패턴을 알게되었는데 기능과 ui를 분리하여 개발하게되면 코드관리에 도움이 될 것같아서 이 디자인패턴에 대해 알아보고자 한다.

container + presenter 패턴은
데이터처리와 데이터출력을 분리하는 것이다

즉,
Container에서는 API Request, Exception Error, state변경, redux, dispatch...
Presenter에서는 props, UI... 를 관리하는 것이다

Container에서 처리하거나 받아온 데이터들을 Presenter 컴포넌트에 props로 넘긴다

예시

// src/components/blog/Blog.js
import React, {Component} from 'react';

class Blog extends Component {
    state = {
        loading: true
    };
    componentDidMount() {
        fetch('/api/blog')
            .then(res => res.json())
            .then(
                posts =>
                this.setState({
                    loading: false,
                    posts
                }),
                error => this.setState({
                    loading: false,
                    error
                })
            );
    }
    render() {
        if ( this.state.loading){
            return <div>Loading...</div>;
        } else {
            this,state.posts.map(post => <div key={post.id}>{post.title}</div>);
        }
    }
}

위의 코드는 하나의 컴포넌트 내부에서 api를 통해 데이터를 받아오고, 그 데이터를 컴포넌트 내부의 state로 관리하면서 데이터를 표현하는 구조이다.
비록 지금은 단순해보이지만 데이터를 처리하는 로직과 UI를 표현하는 로직의 길이가 길어지게 될수록 코드의 가독성이 떨어질것이다.

그래서 Container-Presenter 패턴으로 처리와 출력의 역할을 나눠본다면 아래와 같이 나눌 수 있다.

// src/components/blog/BlogContainer.js

import React, {Component} from 'react';
import Blog from './Blog';

class BlogContainer extends Component {
    state = {
        loading: true
    };
    componentDidMount() {
        fetch('/api/blog')
            .then(res => res.json())
            .then(
                posts =>
                this.setState({
                    loading: false,
                    posts
                }),
                error => this.setState({
                    loading: false,
                    error
                })
            );
    }
    render() {
        <Blog { ...this.state} />;
    }
}

export default BlogContainer;

container component에서는 api에서 데이터를 받아와 props로 presenter container에 넘겨준다.


// src/components/blog/Blog.js

import React from 'react';

class Blog extends Component {
    _renderLoading = () => {
        return <div>Loading...</div>
    };

    _renderError = () => {
        return <div>Error occurs! Please try again.</div>;
    };

    _renderPosts = () => {
        const { posts } = this.props;
        return posts.map(post => <div key={post.id}>{post.title}</div>);
    };

    render() {
        if(this.props.loading) {
            return this._renderLoading();
        } else if(this.props.posts) {
            return this._renderPosts();
        } else {
            return this._renderError();
        }
    }
}

export default Blog;

presenter container에서는 props로 받아온 데이터에 따라서 엘리먼트를 출력한다.
즉, UI에 관한 작업만 수행하게 된다

Container Presenter 방식의 장점?

데이터 처리부분과 보여지는 부분이 나뉘어 있다는 것!
데이터를 보여주는 부분을 수정하고 싶으면 Presenter파일로 가면 되고, 데이터 요청 및 처리에 관련된 코드를 구현하고 싶다면 Container파일로 가서 코드를 작성하면 된다

https://13akstjq.github.io/blockcar/2019/10/10/08-design-pattern.html

0개의 댓글