
위 화면에서 오른쪽에 있는 AddNumber 파일은 리덕스를 도입하기 전에 작성했던 코드이고
왼쪽에 있는 AddNumber 파일은 리덕스를 도입하면서 변경된 코드입니다.
두 가지를 비교해보면 오른쪽에 있는 AddNumber는 부품으로써의 가치가 있습니다.
이 부품은 우리 애플리케이션 안에서도 여러 군데에 사용할 수 있고,
우리 애플리케이션이 아닌 다른 애플리케이션에서도 원한다면 사용할 수 있습니다.
그런데 왼쪽 AddNumber 경우에는 리덕스의 store를 사용하므로 우리 애플리케이션이 사용하고 있는 상태에 의존하고 있습니다.
이렇게 바뀌면서 재사용 가능한 컴포넌트가 아니게 되었습니다.
이번 시간에는 이 문제를 어떻게 해결할 수 있을까에 대해서 알아보겠습니다.
이 문제를 해결할 수 있는 방법은 wrapping하는 것입니다. wrap은 감싼다라는 뜻입니다.
그래서 AddNumber 컴포넌트를 감싸는 새로운 컴포넌트를 만드는 것을 통해 해결할 수 있습니다.
이렇게 만든 컴퍼넌트는 리덕스의 store를 핸들링하고 리덕스가 있는지 모르는 컴포넌트입니다.
기존에 있었던 AddNumber 컴포넌트 는 Presentational 컴포넌트라고 부르고,
AddNumber 컴퍼넌트를 감싸서 리덕스와 관련된 store와 관련된 작업을 처리하는 컴포넌트는 Container 컴포넌트라고 부릅니다.
AddNumber의 store에 종속 되고 있는 기능들을 대리해서 처리하는 AddNumber를 감쌀 Container 컴포넌트를 만들어봅시다.
containers라는 폴더를 만들고, 이 폴더 안에 AddNumber를 감쌀 컴퍼넌트를 AddNumber라는 똑같은 이름으로 만듭니다.
물론 이름은 다르게 만들 수 있습니다.
그리고 이 컴포넌트가 꼭 어떤 컴퍼넌트 하나를 wrapping하는 일대일 관계가 아니어도 됩니다.
Container 컴포넌트는 여러 개의 리액트 컴퍼넌트들을 감싸는 역할을 해도 됩니다.
그리고 단지 리덕스 store만 상대하는 것이 아니라 여러가지 비즈니스 로직을 처리할 수도 있습니다.
방금 생성한 Container 컴포넌트를 이어서 작성하겠습니다.
먼저 wrapping하려고 하는 AddNumber 파일을 import를 해야 합니다.
그 다음에 export default 키워드를 사용한 AddNumber 컴포넌트를 리턴하는 리액트 컴포넌트를 하나 만들겠습니다.
import AddNumber from "../components/AddNumber";
import React, { Component } from "react";
export default class extends Component{
render(){
return <AddNumber></AddNumber>
}
}
그 다음으로 AddNumberRoot.js의 AddNumber를 containers의 AddNumber로 바꿔줍니다.
이렇게 containers 폴더에 있는 AddNumber가 components 폴더에 있는 AddNumber를 가져와서 출력해주는 것입니다.
이렇게 코드를 바꿔 실행했을 때 컴포넌트 구조를 보면 APP 밑에 AddNumberRoot 밑에 AddNumber가 있었는데
중간에 Anonymous 라고 하는 방금 생성한 컴포넌트가 중간에 추가됐습니다.
즉 우리 애플리케이션과 종속되는 작업은 Container 컴포넌트인 AddNumber가 처리하고
기존에 있었던 AddNumber라는 컴퍼넌트는 화면에 표시하는 것에 집중하는 Presentational 컴퍼넌트로써
다시 옛날의 역할로 돌아가게 되는 것입니다.
다음으로 리턴해주는 AddNumber에 onClick 이벤트를 줘서 버튼을 클릭했을 때 store와 통신하도록 코드를 작성하겠습니다.
// src/containers/AddNumber.jsx 코드 추가
import store from '../store';
export default class extends Component{
render(){
return <AddNumber onClick={function(size){
store.dispatch({type:'INCREMENT', size:size});
}.bind(this)}></AddNumber>
}
}
그리고 orginal AddNumber가 갖고 있는 dispatch() 부분을 Container AddNumber 로 옮겨옵니다.
orginal AddNumber 컴포넌트도 아래와 같이 수정합니다.
<input type="button" value="+" onClick={function(){
store.dispatch({type:'INCREMENT', size:this.state.size});
this.props.onClick(this.state.size);
}.bind(this)}></input>
이제 리덕스와 관련된 작업은 AddNumber를 wrapping하는 Container 컴포넌트가 함으로써 AddNumber 컴퍼넌트는
더 이상 리덕스에 종속되지 않고 화면에 무언가를 표시해주는 Presentational 컴포넌트로 다시 돌아온 것입니다.
입력 값을 10으로 하고 + 를 누르면 똑같이 잘 동작하는 것을 확인할 수가 있습니다.
이렇게 Container 컴퍼넌트를 만들어서 Container 컴포넌트가 리덕스랑 상호 작용하게 만든 것입니다.
그에 따라 components 폴더 밑의 AddNumber 컴포넌트는 부품으로써 가치가 있도록 다시 되돌아오게 되었습니다.
생각해보기
리액트 수업을 다시 상기시켜보는 시간을 가져보세요.
리액트에서 재사용성을 높이기 위해 어떤 기능을 사용했나요? 리액트를 통해 얻는 효과는 무엇이었나요?