Redux를 통해서 로그인 모달창 상태관리 하기

hoon·2023년 4월 28일
0

Redux를 통해서 로그인 모달창을 상태관리 하기전에 상태관리에 대해서 먼저 알아보자.

상태관리란?

어플리케이션에서 상태란, 사용자의 입력, 시스템의 이벤트 등의 외부적인 요소로 인해 변화되는 값들을 말한다. 상태관리는 이러한 값을 저장하고, 관리하며, 이러한 값이 변화될 때마다 어플리케이션의 다른 부분에도 그 변화를 반영한다.

프로젝트에서 Redux를 통해서 상태관리하게 된 이유

기존의 프로젝트의 상태관리는 Proxy와 옵저버 패턴을 통해서 진행하였다. 하지만 JavaScript 프로젝트에서 React프로젝트로 전환하고 프로젝트의 규모 역시 커지고 있는 상황이었기 때문에 Redux를 통해서 상태관리를 하기로 결정하였다.

Redux란 무엇인가?

Redux는 크로스 컴포넌트 또는 앱 와이드 상태를 위한 상태관리 시스템으로 상태를 변경하고 화면에 표시하는 데이터를 관리하도록 도와준다.

상태는 크게 3가지로 구분을 할 수 있다.

  1. Local State
    로컬 상태는 데이터가 변경되어서 하나의 컴포넌트에 속하는 UI에 영향을 미치는 상태이다. 예를 들어 우리는 사용자 입력을 청취하고 useState를 사용해서 그 입력을 모든 키 입력과 함께 state 변수에 저장한다.보통 useState를 사용해서 컴포넌트 안에서 로컬 상태를 관리한다.

  2. Cross-Component State
    바로 크로스 컴포넌트 상태는 하나의 컴포넌트가 아니라 다수의 컴포넌트에 영향을 미치는 상태이다. 예를 들면 모달 오버레이를 열거나 닫는 버튼이 있다면 그런 모달 컴포넌트는 다수의 컴포넌트에 영향을 미칠 수 있다.

  3. App-Wide State
    앱 와이드 상태는 앱의 모든 컴포넌트에 영향을 미치는 상태도 이다. 예를 들면 사용자인증이 있다.

리덕스는 앱의 중앙 저장소로, 앱의 모든 상태를 저장한다. 이를 통해 컴포넌트에서 저장소의 데이터를 사용할 수 있다. 예를 들어, 사용자 인증 상태가 변경되면 컴포넌트는 이를 감지하여 UI를 업데이트한다. 컴포넌트는 중앙 저장소와의 구독을 통해 데이터 변경을 인지한다.

데이터를 변경할 때는 컴포넌트가 직접 조작하지 않고, 리듀서라는 개념을 사용한다. 리듀서 함수는 데이터 변형을 처리하며, 입력을 받아 변환하고 축소하는 역할을 한다.

Redux를 프로젝트에 적용하기

  1. 먼저 리덕스를 사용하기 위해 필요한 라이브러리들을 설치한다.
npm install redux react-redux redux-thunk
  1. 이제 애플리케이션의 상태를 관리할 리덕스 스토어를 설정하고, 모달의 상태를 관리하는 액션 생성자와 리듀서를 작성한다.
//src/store/actions.js:
export const SHOW_MODAL = 'SHOW_MODAL';
export const HIDE_MODAL = 'HIDE_MODAL';

export const showModal = () => ({
  type: SHOW_MODAL,
});

export const hideModal = () => ({
  type: HIDE_MODAL,
});
//src/store/reducer.js:
import { SHOW_MODAL, HIDE_MODAL } from './actions';

const initialState = {
  isModalVisible: false,
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case SHOW_MODAL:
      return { ...state, isModalVisible: true };
    case HIDE_MODAL:
      return { ...state, isModalVisible: false };
    default:
      return state;
  }
};

export default reducer;
  1. 리덕스 스토어를 설정했으므로, 이제 Provider 컴포넌트를 사용하여 애플리케이션에 스토어를 연결한다.
//src/store/index.js:
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducer';

const store = createStore(rootReducer, applyMiddleware(thunk));

export default store;

/src/store/index.js 파일은 리덕스 스토어를 설정하고 생성하는 파일이며, 여기에서 스토어를 생성하고 미들웨어를 적용한 다음, 생성된 스토어를 다른 파일에서 사용할 수 있도록 내보낸다.

  1. 이제 리덕스 스토어에서 모달 상태를 관리할 수 있다. 이 상태를 사용하여 로그인 모달과 오버레이를 표시하거나 숨기는 로직을 구현할 수 있다.
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);
  1. LoginModal 컴포넌트에서 useSelector와 useDispatch 함수를 사용하여 리덕스 상태를 가져오고, 액션 디스패치를 한다.
// src/components/LoginModal/LoginModal.jsx
import React, { useEffect, useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux';

import { hideModal } from '../../store/actions';

const LoginModal = () => {
  const isModalVisible = useSelector(state => state.isModalVisible);
  const dispatch = useDispatch();
  const loginModalRef = useRef(null);

  const handleHideModal = () => {
    dispatch(hideModal());
  };

  const handleModalOutsideClick = event => {
    if (
      loginModalRef.current &&
      !loginModalRef.current.contains(event.target)
    ) {
      handleHideModal();
    }
  };

  useEffect(() => {
    if (isModalVisible) {
      document.addEventListener('mousedown', handleModalOutsideClick);
    } else {
      document.removeEventListener('mousedown', handleModalOutsideClick);
    }

    return () => {
      document.removeEventListener('mousedown', handleModalOutsideClick);
    };
  }, [isModalVisible]);

  if (!isModalVisible) {
    return null;
  }

  return (
    <LoginModalContainer ref={loginModalRef}>
      {/* 다른 컴포넌트들  */}
    </LoginModalContainer>
  );
};

export default LoginModal;
profile
프론트엔드 학습 과정을 기록하고 있습니다.

0개의 댓글