Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Web Development
Code

Redux로 시작하기: Redux와 React의 연결

by
Difficulty:IntermediateLength:MediumLanguages:

Korean (한국어) translation by Jin Ah Chon (you can also view the original English article)

Redux로 시작하기 시리즈 중에 세 번째입니다. 이번 튜토리얼에서는 Redux 저장소를 React와 연결하는 방법에 대해 공부하겠습니다. Redux는 독립적인 라이브러리로 대다수 대중화된 프론트엔드 라이브러리와 프레임워크와 같이 동작합니다. 함수형 접근 방식이기에 React와 완벽하게 동작합니다.

이 튜토리얼을 이해하려고 이전 시리즈의 내용을 읽을 필요는 없습니다. 만약에 React와 Redux를 사용하는 것을 배우려고 여기 왔다면, 아래 있는 요약을 보고 나서 앞부분에 있는 코드를 확인하고 거기서 시작하세요.

요약

첫 번째 글에서는 Redux 워크플로우에 관해 공부하고 질문에 답변을 했었습니다. 왜 Redux인가? 꽤 단순한 데모용 애플리케이션을 만들었고 여러분에게 action, reducer, store 같은 다양한 Redux 컴포넌트들이 어떻게 연결이 되는지 보여드렸습니다.

이전 글에서는 연락처를 추가하고 난 다음에 화면에 목록으로 뿌려주는 연락처 목록 애플리케이션 개발을 시작했습니다. 연락처 목록을 위한 Redux store를 생성하고 한 두개의 reducer와 action을 추가했습니다. store.dispatch()store.getState() 같은 저장 메서드를 이용해 action을 dispatch하고 새 state를 가져오는 것을 시도했었습니다.

이 글이 끝나기 전에 여러분은 다음 내용을 알게 될 것입니다.

  1. container 컴포넌트와 presentational 컴포넌트의 차이점
  2. react-redux 라이브러리에 대하여
  3. connect()를 이용해 react와 redux bind하는 방법
  4. mapDispatchToProps를 이용해 action을 dispatch하기
  5. mapStateToProps를 이용해 state 가져오기

튜토리얼에 쓰인 코드는 GitHub의 react-redux-demo 저장소에서 이용 가능합니다. v2 브랜치에서 코드를 받아 이 튜토리얼의 출발점으로 그 코드를 사용하세요. 이 튜토리얼 마지막에 완성될 애플리케이션이 어떻게 생겼는지 궁금하다면 v3 브랜치를 사용해 보세요. 본격적으로 시작해 보죠.

컴포넌트 계층구조 설계: 데이터 처리하는 컴포넌트 대 데이터 처리 못 하는 컴포넌트

여러분이 아마도 이 개념을 예전에 들어본 적 있을 것입니다. 그래도 데이터를 처리하는 컴포넌트와 그렇지 않은 컴포넌트의 차이점을 간략히 봅시다. 컴포넌트 넣을 디렉토리 두 개를 각각 생성했던 것을 기억해 보세요. 하나의 디렉토리 이름은 containers/이고 다른 하나는 components/ 입니다. 이런 접근 방법은 동작(behavior) 로직이 뷰(view)와 분리되어 좋습니다.

presentational 컴포넌트는 어떻게 보이는가와 관련되므로  데이터 처리 능력이 없습니다. 이는 애플리케이션의 비즈니스 로직과 분리되고, props를 통해 오로지 부모 컴포넌트로부터 데이터와 콜백(callback)을 받습니다.  데이터가 부모 컴포넌트의 로컬 state에서 온다면 애플리케이션이 Redux store에 연결되었는지 여부에 관심이 없습니다.

그와 달리 container 컴포넌트에는 동작 부분을 처리하며  DOM 마크업과 스타일은 얼마 되지 않습니다. 렌더링 되어야 할 데이터를 props로써 데이터 처리 능력이 없는 컴포넌트로 전달합니다.

제가 React에서 Stateful 대 Stateless 함수형 컴포넌트라는 튜토리얼에서 그 토픽에 대해 자세히 다루었습니다.

계속해서 컴포넌트를 어떤 식으로 구조화할지 알아봅시다.

Designing component Hierarchy

Presentational 컴포넌트

다음은 이 튜토리얼에서 사용할 presentational 컴포넌트입니다.

components/AddContactForm.jsx

새 연락처를 추가할 용도로 작성된 HTML 폼입니다. 컴포넌트가 onInputChange와 onFormSubmit 콜백을 props로 받습니다. onInputChange 이벤트는 input 값이 변할 때 동작하고, onFormSubmit 이벤트는 폼이 전송될 때 동작합니다.

components/ContactList.jsx

이 컴포넌트는 contact 객체 배열을 props로 받으므로 그 이름이 ContactList 입니다. 연락처의 개별 상세 내용을 뽑아내는데 Array.map() 메서드를 사용하고 그 데이터를 <ContactCard />로 넘깁니다.

components/ContactCard.jsx

이 컴포넌트는 contact 객체를 받아 연락처 이름과 이미지를 보여줍니다. 연습용 애플리케이션이므로 클라우드에서 자바스크립트 이미지를 호스트하는 게 맞을 수도 있겠군요.

container 컴포넌트

가장 핵심인 container 컴포넌트들도 구축하겠습니다.

containers/Contacts.jsx

returnContactList() 함수는 contact 객체 배열을 가져와서 ContactList 컴포넌트로 전달합니다. returnContactList()가 store에서 데이터를 불러오기 때문에 당분간 그 로직을 빈 채로 남겨두겠습니다.

containers/AddContacts.jsx

우리는 세 가지 action에 대응하는 가장 중요한 핸들러 메서드를 작성했습니다. 모두 state를 업데이트하는데 action을 dispatch합니다. render 메서드에서는 state를 페치(fetch)해야 하므로 폼을 보이고 숨기기 위한 로직을 남겼습니다.

이제는 react와 redux를 함께 bind하는 방법을 알아보죠.

react-redux 라이브러리

기본적으로 Redux에서는 React binding을 이용할 수 없습니다. 그래서 우선 react-redux라는 명칭의 라이브러리를 추가로 설치해야 합니다.

라이브러리에서는 여러분이 기억해야 할 단 두 가지 API를 내보내는데, <Provider />컴포넌트와 connect()로 잘 알려진 고차 함수(higher-order function)입니다.

Provider 컴포넌트

Redux와 같은 라이브러리들은 root 컴포넌트부터 시작해서 전체 React 컴포넌트로 접근이 가능한 store 데이터를 만들어야 합니다. Provider 패턴은 라이브러리가 데이터를 위에서 아래로 전달하게 해줍니다. 아래의 코드는 Provider가 어떻게 state에 마법같이 컴포넌트 tree에 있는 컴포넌트를 모두 추가하는지 보여줍니다.

데모용 코드

앱 전체에서 store에 접속해야 합니다. 그렇기에 app 컴포넌트를 provider로 감싸고 나서 tree 컨텍스트에서 필요로 하는 데이터를 추가합니다. 그 다음에 컴포넌트의 자식들이 데이터에 접속합니다.

connect() 메서드

애플리케이션에 store를 제공했으므로 React를 store에 연결해야 합니다. store와 교류할 수 있는 유일한 방법은 action을 dispatch 하고 state를 업데이트하는 것입니다. 우리는 이전에 action을 dispatch 하는데 store.dispatch()를, state의 최신 스냅샷(snapshot)을 찾는데 store.getState()를 사용해 봤습니다. connect()가 바로 이 작업을 하게 됩니다. 하지만 mapDispatchToPropsmapStateToProps라는 두 개의 메서드가 도와주어야 합니다. 제가 이 개념을 아래 예제에서 보여드리겠습니다.

데모용 코드

mapStateToPropsmapDispatchToProps 둘 다 객체를 반환합니다. 이 객체의 key는 연결된 컴포넌트의 prop이 됩니다. 예를 들면, state.contacts.newContactprops.newContact와 매핑이 되는 거죠. action 크리에이터인 addContact()props.addContact과 매핑 됩니다.

이것이 제대로 작동하기 위해서는 위의 코드에서 마지막 줄이 있어야 합니다.

AddContact 컴포넌트로 직접 내보내는 대신에 연결된 컴포넌트로 내보내겠습니다. connect는 <AddContact />addContactnewContact를 prop으로 제공합니다.

React와 Redux를 어떻게 연결할까?

다음으로 여러분이 React와 Redux를 연결하는데 밟아야 할 단계를 알아보겠습니다.

react-redux 라이브러리를 설치하기

아직 설치하지 않았다면, react-redux 라이브러리를 설치합니다. NPM이나 Yarn을 사용해 설치할 수 있습니다.

 App 컴포넌트에 store 제공

먼저 store를 만듭니다. 그리고 나서 store객체를 <Provider />에 prop으로써 전달해서 여러분의 컴포넌트 tree에 접근할 수 있게 합니다.

index.js

React container와 Redux 연결

connect 함수는 React container를 Redux에 bind 하는데 사용합니다. 이는 여러분의 connect 피처(feature)가 다음과 같이 사용된다는 의미입니다.

  1. store에 subscribe하고 그 state를 prop과 매핑함
  2. action을 dispatch 하고 dispatch callback을 prop에 맵핑함

일단 애플이케이션을 Redux에 연결했으면, this.props를 현재 state에 접속하고 action을 dispatch 하는 데도 쓸 수 있습니다. AddContact 컴포넌트에 관한 프로세스를 보여드리겠습니다. AddContact세 개의 action을 dispatch 해야 하며 store에서 온 두 개의 property의 state를 받아야 합니다. 코드를 살펴 보시죠.

우선, AddContact.jsx에서 connect를 가져오세요.

두 번째로 mapStateToPropsmapDispatchToProps 두 개의 메서드를 작성하세요.

mapStateToProps는 store의 state를 인수로 받습니다. store의 state는 props와 맵핑되는 방식을 만들 객체를 반환합니다. mapDispatchToProps는 dispatch action이 props와 맵핑되는 방식을 만들 유사한 객체를 반환합니다.

마지막으로 우리는 AddContact 컴포넌트를 두 개의 함수로 bind 하기 위해 connect를 다음과 같이 사용했습니다.

props를 이용한 container 컴포넌트 업데이트

이제 컴포넌트의 props는 store로부터 state를 읽고 action을 dispatch 할 준비가 갖춰졌습니다. handleInputChangehandleSubmit, showAddContactBox에 관한 로직은 다음과 같이 업데이트 되어야 합니다.

우리는 handler 메서드를 정의했었습니다. 하지만 한 군데를 여전히 빠뜨리고 있죠. render 함수에 들어갈 조건 문장(conditional statement)입니다.

만약 isHidden이 false라면 폼이 렌더링되어집니다. 그렇지 않다면, 버튼이 렌더링 되고요.

연락처 보이기

가장 작업하기 힘든 부분을 완료했습니다. 이제 연락처를 목록으로 보여주는 부분이 남아 있습니다. Contacts container는 해당 로직을 적을 가장 좋은 위치입니다.

우리는 Contacts 컴포넌트를 Redux store와 연결하는데 위에서 따라했던 같은 방식을 적용했습니다. mapStateProps 함수는 store 객체를 contactList props와 맵핑시킵니다. 그러고 나서 props 값을 Contact 컴포넌트와 bind 할 목적으로 connect를 씁니다. connect에 있는 두 번째 인수는 null입니다. 어떤 action도 dispatch 되지 않게 하기 위해서이죠. Redux store의 state로 app 통합을 마무리 했습니다.

다음 튜토리얼에서 다룰 내용은?

다음 글에서는 미들웨어를 좀 더 상세히 살펴보고, 서버에서 불러올 데이터를 연관시킬 action을 dispatch 해보겠습니다. 여러분의 생각을 댓글에서 공유해 주세요!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.