[Reactjs] 리액트 정리 1편 : redux project 소개(1)

안녕하세요? 정리하는 개발자 워니즈 입니다. 필자가 초년 개발자 시절에는 프론트엔드를 주로했었습니다. 프론트엔드라곤 하지만 운영프로젝트에 소속이 되어서 자바스크립트 를 활용하여 소소하게 기능 수정을 하는 수준이였습니다.

그러던 중, reactjs 라는 것을 알게되었고 17년 4월즈음에는 5일짜리 교육도 다녀왔었습니다. 리액트 js의 가장 기초적인 부분을 배웠지만, 기존에 개발하던 방식과는 사뭇 달랐습니다.

콤포넌트들을 만들어두고 그것을 마치 레고 블록 조립하듯이 화면을 개발해가는 과정이였습니다.

급하게나마 리액트 & 리덕스를 사용해본 내용을 정리해보고자 합니다.

지난 글들은 아래를 참고 해주시면 됩니다.

1. 리덕스를 사용하는 이유?

리액트만 사용하면 되지 리덕스까지 같이 사용할 필요가 있을까? 라는 생각을 했었습니다. 그런데 요즘의 웹의 추세는 빠른 속도로 사용자에게 제공을 해주어 만족도를 높여야 합니다. 그러기 위해서는 DOM 구조의 특성을 봐야 합니다.

  • 왼쪽의 그림에서 보이시는 것처럼 root component에서 제일 최하위 컴포넌트까지 변화를 일으키기 위해서 거쳐가야될 수많은 컴포넌트들이 있습니다. 한개를 업데이트 하기 위해서는 비효율적인 상태 변경을 보입니다 .
  • 리덕스의 가장큰 장점은 명확하게 상태를 관리한다는 것입니다. Store라는 객체를 사용하여 상태 저장소처럼 사용을 하고 모든 컴포넌트들은 이 Store의 변경에 따라서 자신의 컴포넌트 상태를 개별로 업데이트 합니다.

  • 리덕스를 사용하는 또하나의 가장큰 이유는 상태 변경에 대한 시간 여행이 가능하다는 부분이다. 리덕스로 만들어진 앱은 모든 상태들의 변경에 대해서 내부적으로 이력관리를 하고 있습니다. 그렇기 때문에 버그를 찾는 부분에서 굉장히 수월해집니다.

2. 리덕스로 진행중인 앱 소개

wonizz github

  • Project Structure
.
├── build                    # 전체 소스 빌드
├── public                   # Main HTML page and Static public assets 
├── src                      # Application source code
│   ├── components           # Global Reusable Components
│   │   └── Article          # PD page all component
│   │   └── Home             # Home page all component
│   ├── constants            # action 정의서 
│   ├── reducers             # all reducers definition
│   │   ├── createStore.js   # Create and instrument redux store
│   │   └── reducers.js      # Reducer registry and injection
│   └── agent.js             # 외부 API 연계 호출 (데이터)
│   └── index.js             # 페이지 Router 정의 

필자의 소스를 완벽히 공유할 순 없지만, 만들어진 소스에 대한 소개를 해보려고 합니다.

크게는 2개의 폴더로 보시면 됩니다 .

  • public – Main HTML (index.html)
  • src – App source

3. 컴포넌트 구조

  • Component Structure
├── src                      # Application source code
│   ├── components           # Global Reusable Components
│   │   └── Article          # PD page all component
│   │   └── Home             # Home page all component
│   │        └── index.js    # Home page default component 
│   ├── constants            # action 정의서 
│   ├── reducers             # all reducers definition
│   │   ├── createStore.js   # Create and instrument redux store
│   │   └── reducers.js      # Reducer registry and injection
│   │   └── articleList.js   # 제품 목록 노출 reducer
│   └── agent.js             # 외부 API 연계 호출 (데이터)
│   └── index.js             # 페이지 Router 정의 

위의 소스중에서 Router 가 정의된 index.js에 대해서 먼저 보겠습니다.

  • Router index.js
ReactDOM.render((
  
    
      
        
      
    
  
), document.getElementById('root'));

웹페이지가 호출되면, IndexRouter 인 Home 컴포넌트가 호출이 됩니다.

  • Home > index.js
  componentWillMount() {
    const tab = this.props.token ? 'feed' : 'all';
    const articlesPromise = this.props.token ?
      agent.Articles.feed :
      agent.Articles.all;
    this.props.onLoad(tab, articlesPromise, Promise.all([agent.Tags.getAll(), articlesPromise()]));
  }

Home에서 default component 인 index.js가 호출이 될 것이고, 그중에서더 위의 부분과 같이 componentWillmount 함수가 호출되는 시점을 확인해보겠습니다.

Home 페이지가 노출이 될 때, Main List들이 노출이 되어야 되는데 이부분을 API를 통해서 가져오는 부분입니다. 현재는 위와 같이 this.props.onLoad 의 함수가 호출이 됨과 동시에 props에 있는 onLoad함수를 호출합니다.



const mapDispatchToProps = dispatch => ({
  onClickTag: (tag, pager, payload) =>
    dispatch({ type: APPLY_TAG_FILTER, tag, pager, payload }),
  onLoad: (tab, pager, payload) =>
    dispatch({ type: HOME_PAGE_LOADED, tab, pager, payload }),
  onUnload: () =>
    dispatch({  type: HOME_PAGE_UNLOADED })
});

그러면 `HOME_PAGE_LOADED’ 라는 타입으로 reducer에게 store를 업데이트 하도록 전달합니다.(dispatch)

  • redcucer > articleList.js
case HOME_PAGE_LOADED:
      return {
        ...state,
        pager: action.pager,
        tags: action.payload[0].tags,
        articles: action.payload[1].articles,
        articlesCount: action.payload[1].articlesCount,
        currentPage: 0,
        tab: action.tab
};

위에 보시는것처럼 HOME_PAGE_LOADED 타입으로 전달이 될 때, state에다가 각 객체들을 담아 둡니다.
그리고나서 Home의 index.js 에서 mapStateToProps 를 통해서 모든 상태를 props로 전달합니다.

  • ArticleList.js (view component)

위에서 전달된 pros를 아래와 같이 viewing component에서는 그냥 노출만 하면됩니다.

{ props.articles.map(article => { return ( ); }) }

4. 마치며..

위의 내용에서 보이시는 것처럼 한눈에 보이시나요? 리덕스의 가장큰 단점! 이라고 생각하면 러닝 커브가 있다는 것입니다. 개념에 대해서 완벽히 숙지하고 익히지 않으면, 내용이 다소 어려울 수 있습니다. 그런데 기본적으로 reducer, store, component 정도의 개념만 있으면 우선 반은 성공한거라고 생각합니다.

component에서 액션이 일어나면, reducer에게 전달이 되고, store를 업데이트 한 뒤, 다시 상태변경에 대해서 component에서 변경을 해주면 됩니다.

다음시간에는 리액트 소스를 빌드 해 서, S3로 웹호스팅 해보는 방법에 대해서 올리도록 하겠습니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다