처음 만난 리덕스 (Redux) 문서


7.6 connect()

마지막 react-redux의 함수는 connect() 함수 입니다.

사실, 앞에서 배운 mapStateToProps() 함수와 mapDispatchToProps() 함수는 이 connect() 함수를 호출하기 위해서 필요한 함수들입니다.
그리고 mapStateToProps() 함수와 mapDispatchToProps() 함수는 규칙에 맞춰서 개발자가 직접 작성하는 함수였습니다.
하지만 이 connect() 함수는 react-redux 패키지에서 제공하는 함수이기 때문에 그냥 호출해서 사용하면 됩니다.

connect() 함수는 이름이 가진 의미 그대로 어떤 것들을 연결시키는 역할을 하는데, 바로 Redux와 React 컴포넌트를 연결시켜 주는 역할을 합니다.

Redux Container

앞에서 Redux와 리액트 컴포넌트들을 연결하면 그것이 바로 Container가 된다고 말했습니다.
그리고 바로 이 중간에서 연결을 담당하는 함수가 바로 react-redux 패키지의 connect() 함수입니다.
실제로 Container를 만드는 역할을 하는 함수죠.

그럼 실제로 connect() 함수는 어떻게 호출해야 하는지 살펴볼까요?

function connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)

여기에 connect() 함수의 파라미터들이 나와 있습니다.

먼저 첫 번째 파라미터와 두 번째 파라미터는 각각 앞에서 나왔던 mapStateToProps() 함수와 mapDispatchToProps() 함수입니다.
그리고 세 번째 파라미터는 mergeProps라고 되어 있는데, 이것은 연결하는 컴포넌트에 최종적으로 전달될 props를 결정하는 함수입니다.
그리고 마지막 파라미터인 options에는 추가적인 옵션들을 사용하기 위한 객체가 들어갑니다.

어떻게 보면 connect() 함수의 파라미터가 굉장히 많아 보이는데 우리는 모든 파라미터에 대해서 외울 필요까지는 없습니다.
앞에서도 말한 것처럼, 이 방식은 과거에 사용하던 방식이기 때문에 과거에 어떤 형태로 Redux를 React와 연동해서 사용을 했고 그 방식이 어떻게 발전해서 최근의 표준인 Redux Toolkit까지 흘러왔는지 정도만 이해해도 충분합니다.

여기에서는 mapStateToProps() 함수와 mapDispatchToProps() 함수가 connect() 함수의 파라미터로 들어가서 실제 리액트 컴포넌트에 어떤 형태로 전달이 되는지 그 과정과 개념에 대해서만 잘 이해하면 됩니다.

어찌됐든 이렇게 connect() 함수를 사용해서 호출하면 Wrapper Function을 리턴하게 됩니다.
그리고 이 Wrapper Function은 어떤 리액트 컴포넌트든지 파라미터로 넣어서 호출하면 Redux에 연결시킬 수 있는 함수입니다.
즉, Wrapper Function의 호출 결과는 Redux에 연결된 Container Component가 되는 것이죠.

자, 그럼 실제 connect() 함수를 사용하는 예시코드를 한 번 볼까요?

import Counter from '../components/Counter';

function mapStateToProps(state) {
    return {
        count: state.count,
    }
}

function mapDispatchToProps (dispatch) {
    return {
        increaseCount: () => {
            dispatch({ type: 'INCREASE_COUNT' });
        },
        decreaseCount: () => {
            dispatch({ type: 'DECREASE_COUNT' });
        },
    }
}

// Step 1: 어떤 리액트 컴포넌트든지 파라미터로 넣어서 호출하면 Redux에 연결시킬 수 있는 Wrapper Function를 리턴
const connectCount = connect(mapStateToProps, mapDispatchToProps);
// Step 2: Redux와 연결(connect)된 Container 컴포넌트를 리턴
const CounterContainer = connectCount(Counter);

// Step 1, 2를 한 번에 처리하는 방식
const CounterContainer = connect(mapStateToProps, mapDispatchToProps)(Counter);

export default CounterContainer;

이 코드는 리액트의 Counter 컴포넌트를 Redux와 연결시키는 코드입니다.

먼저 mapStateToProps() 함수와 mapDispatchToProps() 함수를 만들었습니다.
그리고 만든 함수들을 Step 1처럼 connect() 함수의 파라미터로 넣어서 호출합니다.
이렇게 호출하게 되면 Wrapper Function이 리턴되는데, 이 Wrapper Function을 사용하면 어떤 리액트 컴포넌트든지 Container로 만들 수 있습니다.

다음 Step 2에서는 Wrapper Function을 사용해서 실제로 Redux와 Counter컴포넌트를 연결시킵니다.
그리고 이 Wrapper Function의 호출 결과는 Container Component가 됩니다.
그래서 일부러 이름을 CounterContainer라고 지었습니다.

이렇게 각 Step을 나눠서 Container를 만들 수도 있지만, 코드 하단에 나온 방식처럼 Step을 나누지 않고 한 번에 Container를 만들 수도 있습니다.
이 방식은 connect() 함수를 호출해서 만들어진 Wrapper Function을 곧바로 호출해서 Container를 만들어내는 방식입니다.

어찌됐든 두 방식의 결과는 동일합니다.
그리고 마지막 줄에서는 이렇게 만들어진 CounterContainerexport하고 있습니다.
실제 리액트에서는 이렇게 export된 Container를 사용하면 됩니다.

자 여기서 처음 Redux를 사용하는 분들이 가장 많이 하는 실수를 하나 말씀드리려고 합니다.

import Counter from './components/Counter';

function MainPage() {
    return (
        <Counter />
    )
}
import CounterContainer from './redux/containers/CounterContainer';

function MainPage() {
    return (
        <CounterContainer />
    )
}

여기에 두 개의 코드가 있습니다.
위쪽에 있는 코드는 기존 리액트의 Counter 컴포넌트를 import해서 렌더링하는 코드입니다.
그리고 아래쪽에 있는 코드는 Counter 컴포넌트를 Redux에 connect 시킨 CounterContainer를 import해서 렌더링하는 코드입니다.

자, 이 두 가지 방법 중 어떤 방법이 올바른 사용법일까요?
바로 아래쪽 방법이 올바른 사용법입니다.
왜냐하면, Counter 컴포넌트를 리액트에 connect 시킨 이유는 Redux에 있는 state나 Action을 dispatch하는 함수를 컴포넌트에서 사용하기 위함입니다.
그런데 Redux에 연결된 Container Component를 사용하지 않고, 그냥 기존의 리액트 컴포넌트를 사용하게 되면 에러가 발생할 수 있습니다.

그래서 꼭 connect 된 컴포넌트를 사용해야 한다는 것을 기억하기 바랍니다.
그리고 여기서 connect 된 컴포넌트가 바로 이번 장에서 계속해서 배우고 있는 Container라는 것도 다시 한 번 외워두기 바랍니다.

지금까지 react-redux 패키지의 connect() 함수에 대해서 배워보았습니다.
우리가 배운 내용 이외에 다양한 형태로 connect() 함수를 사용할 수 있는데, 더 자세한 내용이 궁금한 분들은 아래 링크로 접속하면 다양한 예시 코드를 볼 수 있으니 참고하기 바랍니다.

https://react-redux.js.org/api/connect


마지막 업데이트: 2023년 07월 14일 00시 00분

이 문서의 저작권은 이인제(소플)에 있습니다. 무단 전재와 무단 복제를 금합니다.