[리액트 독학] "리액트 인터뷰 가이드"로 한 단계 더 성장하기

2024. 10. 6. 21:00Web Programming(웹 개발)/React(리액트)

안녕하세요

여러분 제가 또 돌아왔습니다!!!

 

요새 회사 분위기가 뒤숭숭하고 일도 바쁘다보니 

포스팅을 이렇게 좀 늦게 한다는 점...이해 부탁드리겠습니다 ㅜㅠ

 

제 글을 보러 오셨다면, 아마 리액트에 적어도 관심있으신 분들이시겠죠?

혹시 모르니 간단히 리액트를 설명하자면...

이렇게 간단하게 설명할 수 있네요
 

 

오늘은 "리액트 인터뷰 가이드"에서 다룬 리덕스에 대해 이야기해보려고 합니다.

리덕스는 쉽게 말하면 애플리케이션에서 상태 관리를 보다 효율적으로 할 수 있도록 도와주는 도구인데요, 그 매력을 한번 살펴볼까요?

 

리덕스(Redux)는 애플리케이션의 상태(state)를 효율적으로 관리하기 위해 사용되는 자바스크립트 라이브러리입니다. 리액트와 함께 많이 사용되지만, 리액트에 종속적인 것은 아니고, Vue.jsAngular 같은 다른 프레임워크와도 함께 사용할 수 있습니다. 리덕스는 특히 복잡한 상태 관리가 필요한 대규모 애플리케이션에서 유용합니다.

 

학습하기 전에 플럭스 패턴과 MVC 패턴을 이해해야하는데요

 

1. 플럭스 패턴이란 무엇인가?

1) 개념

- 플럭스란 애플리케이션에서 단방향 데이터 프름을 관리하는 패턴으로 전통적인  MVC 패턴을 대체한다. 

 

2) 플럭스의 데이터 흐름

- 플럭스의 데이터 흐름에는 4가지 주요 컴포넌트인 액션, 디스패처, 스토어, 뷰가 존재

액션: 데이터 흐름을 트리거하는 디스패처로 보내지는 자바스크립트 객체를 의미
디스패처: 스토어를 업데이트하기 위한 콜백을 위한 싱글턴 레지스트리로, 플러스 애플리케이션 내의 데이터 흐름의 중앙 허브 역할을 담당한다. 디스패처는 실제로 별도 로직이 존재하지 않으며 단순히 액션에서 스토어로 페이로드만 전달하는 역할을 함
스토어: 애플리케이션 상태와 로직을 보관하는 곳, 오직 하나만 존재하며 모든 상태가 이곳에서 관리됨
: 스토어로부터 데이터를 받아 애플리케이션을 다시 렌더링함. 뷰는 사용자 상호 작용에 따른 액션을 트리거하기도 함.

그림1. 플럭스 데이터 흐름

 

※ 플럭스 데이터 흐름
1. 사용자가 UI 상호 작용 수행하면 이벤트가 생성되고 뷰는 디스패처에 액션을 보낸다. 
2. 디스패처는 해당 액션을 각 스토어에 보낸다.
3. 스토어는 상태를 업데이트하고 뷰에 다시 렌더링하도록 알린다. 

 

3) MVC와 플럭스의 주요 차이점

구분 MVC 플럭스
데이터 흐름 양방향 데이터 흐름 단방향 데이터 흐름
구조 모델, 뷰, 컨트롤러로 구성 액션, 디스패처, 스토어로 구성
상태 관리 컨트롤러가 상태를 업데이트(로직도 담당) 스토어가 상태를 관리(로직도 담당)
복잡도 복잡한 구조에서 관리 어려움 데이터 흐름이 명확하여 관리 용이

- MVC와 플럭스는 각각의 장단점이 있고, 플럭스는 MVC보다 한층 더 향상된 모습을 가지고 있다.

- MVC는 비교적 간단한 구조의 애플리케이션에 적합

- 플럭스는 상태 관리가 복잡한 대규모 애플리케이션에 효과적

 

 

2.  리덕스란 무엇인가?

1) 개념

- 애플리케이션의 상태를 중앙에서 관리할 수 있게 해주는 라이브러리
특히, 리액트와 함께 사용되면서 복잡한 애플리케이션의 상태를 더욱 쉽게 다룰 수 있도록 돕는다.
상태 관리의 중요성을 이해하는 것은 리액트 개발자에게 필수적!

 

리덕스 환경 설정

$ mkdir react-redux-tutorial
$ cd react-redux-tutorial
$ npm init vite
$ npm install
$ npm install redux react-redux

 

2) 리덕스 주요 개념

  1. 스토어(Store): 애플리케이션의 전체 상태를 저장하는 객체. 스토어는 오직 하나만 존재하며, 모든 상태는 이곳에서 관리됨.
  2. 액션(Action): 상태를 변경하기 위해 스토어에 보내는 정보. 액션은 JavaScript 객체로, type 속성과 필요에 따라 다른 속성들을 가짐. 예를 들어, 사용자의 로그인 상태를 변경하는 액션은 다음과 같을 수 있음.
  3. 리듀서(Reducer): 액션을 처리하여 새로운 상태를 반환하는 함수. 현재 상태와 액션을 받아 새로운 상태를 만들어냄. 예를 들어, 로그인 액션을 처리하는 리듀서는 다음과 같음.
     

책에서 발췌한 리듀서에 대한 설명_리액트 가이드 인터뷰

 

3.  리덕스의 핵심 원칙: 3가지

1) 단일 진실 공급원 (Single Source of Truth)

- 리덕스에서는 애플리케이션의 상태가 하나의 스토어에 저장된다. 이 스토어는 애플리케이션의 모든 상태를 관리하며, 이를 통해 상태를 쉽게 추적하고 관리할 수 있다. 여러 개의 스토어가 존재하지 않기 때문에, 상태의 일관성을 유지할 수 있다.

// 스토어 생성
const store = createStore(counterReducer);

// 현재 상태 출력
console.log(store.getState());

 

2) 상태는 읽기 전용 (State is Read-Only)

- 리덕스의 상태는 직접적으로 변경할 수 없고, 상태를 변경하려면 반드시 액션을 통해야 한다. 이 원칙은 애플리케이션의 상태 변화를 예측 가능하게 만들어 주며, 상태 변화의 기록을 명확하게 관리할 수 있게 한다.

// 액션을 디스패치해서  cities 상태에 새로운 도시를 추가하는 방법

store.dispatch({
	type: 'ADD_CITY',
    payload: 'London',
})

 

3) 변경은 순수 함수로만 일어난다 (Changes are Made with Pure Functions)

- 상태를 변경하는 로직은 리듀서라는 순수 함수 안에서 수행됨. 순수 함수란 입력이 동일할 때 항상 같은 출력을 반환하며, 외부 상태를 변경하지 않는 함수를 말한다. 이 원칙은 상태 변경의 예측 가능성을 높여준다.

// 액션을 디스패치해서  cities 상태에 새로운 도시를 추가하는 방법

store.dispatch({
	type: 'ADD_CITY',
    payload: 'London',
})

 

 

"단일 진실 공급원"으로 상태를 중앙 집중화하고,
"상태는 읽기 전용"으로 직접적인 변경을 방지하며,
"변경은 순수 함수로만 일어난다"는 원칙으로 안정성을 높인다.

 

4.  리덕스 미들웨어: 사가와 썽크

1) 리덕스 미들웨어란 무엇인가

- 리덕스 애플리케이션에서 비동기 작업을 처리하는 것은 중요합니다. 이때 리덕스 미들웨어가 큰 역할을 합니다. 특히, 리덕스 사가(Redux Saga)와 리덕스 썽크(Redux Thunk)는 두 가지 인기 있는 미들웨어로, 비동기 액션을 처리하는 데 도움

 

2) 리덕스 썽크

- 리덕스의 미들웨어로, 액션 생성자가 함수를 반환할 수 있게 해줌

- 이 함수를 사용하면 비동기 작업을 수행한 후, 특정 액션을 디스패치할 수 있다. 주로 API 호출과 같은 비동기 작업에 많이 사용

 

설치 명령어

npm install redux-thunk

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';

// 초기 상태
const initialState = { data: null };

// 리듀서
const dataReducer = (state = initialState, action) => {
    switch (action.type) {
        case 'FETCH_DATA_SUCCESS':
            return { ...state, data: action.payload };
        default:
            return state;
    }
};

// 액션 생성자
const fetchData = () => {
    return (dispatch) => {
        fetch('https://api.example.com/data')
            .then(response => response.json())
            .then(data => {
                dispatch({ type: 'FETCH_DATA_SUCCESS', payload: data });
            });
    };
};

// 스토어 생성
const store = createStore(dataReducer, applyMiddleware(thunk));

// 비동기 액션 디스패치
store.dispatch(fetchData());

 

 

3) 리덕스 사가 

- 제너레이터 함수를 사용하여 비동기 작업을 관리

- 비동기 작업을 처리하기 위해 사가는 yield 키워드를 사용하며, 이로 인해 비동기 로직을 더 쉽게 작성하고 테스트할 수 있음.

- 복잡한 비동기 흐름을 관리하는 데 특히 유용

 

※ 자주 사용되는 함수

takeEvery: 특정 액션이 발생할 때마다 사가를 실행하는 함수

call: 함수를 호출할 때 사용하는 함수

put: 액션을 디스패치하는 함수

takeLatest:특정 액션이 발생할 때, 가장 최근에 발생한 액션에 대해서만 사가를 실행하는 함수

yield: 자바스크립트의 제너레이터 함수를 순차적으로 사용하도록 해주는 내장 함수

import { createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { takeEvery, call, put } from 'redux-saga/effects';

// 초기 상태
const initialState = { data: null };

// 리듀서
const dataReducer = (state = initialState, action) => {
    switch (action.type) {
        case 'FETCH_DATA_SUCCESS':
            return { ...state, data: action.payload };
        default:
            return state;
    }
};

// 비동기 작업을 위한 사가
function* fetchDataSaga() {
    const response = yield call(fetch, 'https://api.example.com/data');
    const data = yield response.json();
    yield put({ type: 'FETCH_DATA_SUCCESS', payload: data });
}

// 루트 사가
function* rootSaga() {
    yield takeEvery('FETCH_DATA', fetchDataSaga);
}

// 스토어 생성
const sagaMiddleware = createSagaMiddleware();
const store = createStore(dataReducer, applyMiddleware(sagaMiddleware));

// 사가 실행
sagaMiddleware.run(rootSaga);

// 비동기 액션 디스패치
store.dispatch({ type: 'FETCH_DATA' });

 

4) 사가와 썽크 비교

구분 리덕스 썽크 리덕스 사가
구현 방식 액션 생성자가 함수를 반환 제너레이터 함수를 사용
비동기 작업 더 간단한 비동기 작업 처리 복잡한 비동기 흐름 관리에 유리
테스트 용이성 비교적 쉬움 테스트가 쉽고 명확함

 

 

 

 

리덕스는 애플리케이션의 상태 관리를 간소화하고 예측 가능하게 만들어주는 강력한 도구입니다.

오늘 소개한 개념들, 즉 리덕스의 핵심 원칙, 미들웨어인 사가와 썽크, 그리고 yield의 활용을 이해함으로써

더욱 효과적이고 효율적인 리액트 애플리케이션을 개발할 수 있으니 

앞으로의 프로젝트에 리덕스를 적극 활용해보세요!

 

질문이나 추가하고 싶은 내용이 있다면 언제든지 댓글로 남겨주세요

그리고 도서 구매하고 싶으신 분들은 하단 링크 참고해주세요!

 

 

도서 구매 링크 하단 참고

https://www.yes24.com/Product/Goods/130271536