redux 만들어 보기

Views:
6
Category:
Post
Posted on:
2024. 2. 1.

상태관리의 고인물 redux 만들어 보기

갑자기 뭔 redux 만들기????

현재 자바스크립트 만을 활용해 블로그에 채팅모듈을 만들고 있는 중이다.

순수 자바스크립트 만을 이용해 만들며 많은 고충이 있었는데,

그 중에 하나가 상태 관리였다...ㅋㅋㅋ 리엑트를 사용하며 여태껏 엄청 편하게 상태를 관리하고 있었던 것이다....

그래서 구글링을 통해 알아 보았고, 생각보다 어렵지 않게 구현 할 수 있었다.

redux란??

리덕스는 쉽게 state(상태)를 관리할 수 있는 툴이다. 그냥 상태라고 하기 보다는 전역 상태라고 하는 것이

좋을 것이다. 리엑트로 개발을 해 보았던 분이라면 상태 관리를 하며 느꼈던 부분이 있을 것이다.

props로 전달한 state가 props로 또 전달 되고, 전달받은 props가 또 그 자식에게 또 전달되고....

귀찮은 것을 떠나서...문제는 그 state가 정작 필요하지 않은 자식 컴포넌트에도 전달 되어야 비로소 state가

필요한 마지막 자식에게 전달 된 다는 것이다.

그래서 전역으로 상태를 관리할 수 있는 다양한 툴들이 나왔고, 그 중에 하나가 redux 인 것이다.

전역으로 상태를 관리 할 수 있는 툴들은 redux, zustand, recoil 등 다양하게 존재한다.

자바스크립트 만으로 모듈을 개발하면서 느꼈던 상태관리의 귀찮음과 중요성을 통해 공부할 수 있는 계기가 되었다.

왜 rddux????

1.일단은 사용해 봤던 툴이라 익숙하다.

2.오래된 상태관리 툴이지만, 아직도 많은 프로젝트에서 사용되고 있다.

3.툴을 사용하기 위한 boilerplate code가 많지만, 컨셉이 상당히 마음에 들었다. <<< 이 부분이 상당히 만족

비전공자 출신이고 처음 부트캠프에서 상태관리 툴으로 redux를 배웠었다. 처음엔 그냥 뭔지 모르고 그냥 배웠었고,

그냥 이렇게 사용하는 구나 하고 무작정 따라 하기에 바빳다.

부트캠프 졸업한 이후 개발 업무를 많이 한 것은 아니지만, 조금씩 공부 하면서 redux의 컨셉이 상태관리 함에 있어

상당히 마음에 들었다.

흐름

action의 dispatch >> store update >> subscribe 전달 >> view update or action dispatch

단방향으로 단순하게 흐르는 것이 redux인 것이다.

이러 이러한 action이 발생(dispatch) 하면 나는 store를(reducer에 정의된) 이러 이러하게 업데이트 할거야.

store가 업데이트 되면 구독하고 있는곳에 상태가 바뀌었다고 알려 줄거야. 아름답지 않은가????......

아무튼 redux를 간단하게 구현 해 보자.

store 만들기

const createStore = (reducer) => {
    //*  initial state는 프로젝트에 필요에 따라 작성 한다.
     let state = {
        number: 0
    };
    
    const getState = () => ({ ...state });
    const dispatch = (action) => {
        state = reducer(state, action);
    };

    return {
        getState,
        dispatch
    }
};

reducer 만들기

//* reducer는  이전의 state와 action을 받아 상태를 업데이트 하는 함수이다.
//* 상태를 직접 변경하는게 아니라 새로운 객체를 반환해야 한다. 
//* 이전 객체(원래 state)의 주소값, 업데이트된(새로만든 객체)객체의 주소값이 다르기 때문에
//* 상태가 변경이 되었다고 판단할 수 있다.
//* 자바스크립트를 처음 공부할때는 이해하기 힘들 수 있다. 
import { INCREASE } from "주소"';

const reducer = (state, action) => {
    switch(action.type) {
        case INCREASE:
            //* return {}; 객체 리터럴(새로운 객체 만듦)
            //* ...state: 원래 state spread를 통해 새로운 객체에 원래의 state 값 복사
            //* 원래 객체를 직접 변경한게 아니라 새로운 객체에 값만 붙여 넣은 꼴이라 새로운 객체임
            //* 다른 주소를 가리킴 
            return {
               ...state,
               number: state.number + 1
            };
        ...
        defualt: 
            return state;
    }
}

action 만들기

//* 상수 정의(관용적으로 이런 패턴으로 사용하는 것 같음)
const INCREASE = "counter_INCREASE"; 

export const increase = () => ({ type: INCREASE });

상태 업데이트 알리기

const createStore = (reducer) => {
    //*  initial state는 프로젝트에 필요에 따라 작성 한다.
     let state = {
        number: 0
    };

    const listener = [];
    
    const getState = () => ({ ...state });
    const dispatch = (action) => {
        state = reducer(state, action);
        //* 상태를 사용하는 컴포넌트에서 등록한 함수들을 실행 한다.
        //* 전역 상태가 업데이트 되면 실행될 함수이다.
        //* 전역 상태가 업데이트 되면 나는 이 컴포넌트를 전역 상태에 따라 이렇게 업데이트 할거야
        //* 위의 increase 함수가 실행되면 (type: INCREASE)
        //* reducer에 의해 전역상태의 number 값이 1 증가 한다. 
        //* subscribe에 등록된 함수가 실행 된다
        //* 그 등록된 함수는 html의 number요소를 지금 state number값에 맞게 다시 구조화 할거야.
        //*  라는 함수를 subscribe에 등록
        listener.forEach(fn => fn());
    };
    
    //* 각 컴포넌트에서 상태가 업데이트 되면 실행될 함수를 등록한다.
    const subscribe = (fn) => listener.push(fn);

    return {
        getState,
        dispatch,
        subscribe
    }
};

사용 하는 곳

//* 리엑트는 보통 main.js???
import reducer from "주소";
export const store = createStore(reducer);

//* store의 상태가 필요한 곳
import { store } from "주소";
const state = store.getState();

//* 구독 등록(subscribe)
import { store } from "주소";
...
//* html을 만드는 함수 안의 상태 초기화 
const state = store.getState(); or 
//* html을 만드는 class 안의 상태 초기화 
class {
    state = store.getState();
}
//* 그 뒤 
store.subscribe(함수 혹은 class내 html을 조작하는 함수 등의 로직);
//* 위의 store.subscribe의 인자로 넣은 함수는 전역 상태가 업데이트 되면 실행되기에
//* 새롭게 업데이트 된 상태값으로 html을 변경 할 수 있는 함수 등을 넣는다.
...
# 상태관리의 고인물 redux 만들어 보기

갑자기 뭔 redux 만들기????  

현재 자바스크립트 만을 활용해 블로그에 채팅모듈을 만들고 있는 중이다. 

순수 자바스크립트 만을 이용해 만들며 많은 고충이 있었는데,

그 중에 하나가 상태 관리였다...ㅋㅋㅋ 리엑트를 사용하며 여태껏 엄청 편하게 상태를 관리하고 있었던 것이다....

그래서 구글링을 통해 알아 보았고, 생각보다 어렵지 않게 구현 할 수 있었다. 

### redux란??
리덕스는 쉽게 state(상태)를 관리할 수 있는 툴이다. 그냥 상태라고 하기 보다는 전역 상태라고 하는 것이 

좋을 것이다. 리엑트로 개발을 해 보았던 분이라면 상태 관리를 하며 느꼈던 부분이 있을 것이다. 

props로 전달한 state가 props로 또 전달 되고, 전달받은 props가 또 그 자식에게 또 전달되고....

귀찮은 것을 떠나서...문제는 그 state가 정작 필요하지 않은 자식 컴포넌트에도 전달 되어야 비로소 state가 

필요한 마지막 자식에게 전달 된 다는 것이다. 

그래서 전역으로 상태를 관리할 수 있는 다양한 툴들이 나왔고, 그 중에 하나가 redux 인 것이다. 

전역으로 상태를 관리 할 수 있는 툴들은 redux, zustand,  recoil 등 다양하게 존재한다. 

자바스크립트 만으로 모듈을 개발하면서 느꼈던 상태관리의 귀찮음과 중요성을 통해 공부할 수 있는 계기가 되었다.

### 왜 rddux????

1.일단은 사용해 봤던 툴이라 익숙하다.

2.오래된 상태관리 툴이지만, 아직도 많은 프로젝트에서 사용되고 있다.

3.툴을 사용하기 위한 boilerplate code가 많지만, 컨셉이 상당히 마음에 들었다. <<< 이 부분이 상당히 만족

비전공자 출신이고 처음 부트캠프에서 상태관리 툴으로 redux를 배웠었다. 처음엔 그냥 뭔지 모르고 그냥 배웠었고, 

그냥 이렇게 사용하는 구나 하고 무작정 따라 하기에 바빳다. 

부트캠프 졸업한 이후 개발 업무를 많이 한 것은 아니지만, 조금씩 공부 하면서 redux의 컨셉이 상태관리 함에 있어

상당히 마음에 들었다. 

### 흐름

> action의 dispatch  >> store update >> subscribe 전달 >> view update or action dispatch

단방향으로 단순하게 흐르는 것이 redux인 것이다. 


이러 이러한 action이 발생(dispatch) 하면 나는 store를(reducer에 정의된) 이러 이러하게 업데이트 할거야.

store가 업데이트 되면 구독하고 있는곳에 상태가 바뀌었다고 알려 줄거야. 아름답지 않은가????......

아무튼 redux를 간단하게 구현 해 보자. 

### store 만들기 
```js
const createStore = (reducer) => {
    //*  initial state는 프로젝트에 필요에 따라 작성 한다.
     let state = {
        number: 0
    };
    
    const getState = () => ({ ...state });
    const dispatch = (action) => {
        state = reducer(state, action);
    };

    return {
        getState,
        dispatch
    }
};
```

###  reducer 만들기

```js
//* reducer는  이전의 state와 action을 받아 상태를 업데이트 하는 함수이다.
//* 상태를 직접 변경하는게 아니라 새로운 객체를 반환해야 한다. 
//* 이전 객체(원래 state)의 주소값, 업데이트된(새로만든 객체)객체의 주소값이 다르기 때문에
//* 상태가 변경이 되었다고 판단할 수 있다.
//* 자바스크립트를 처음 공부할때는 이해하기 힘들 수 있다. 
import { INCREASE } from "주소"';

const reducer = (state, action) => {
    switch(action.type) {
        case INCREASE:
            //* return {}; 객체 리터럴(새로운 객체 만듦)
            //* ...state: 원래 state spread를 통해 새로운 객체에 원래의 state 값 복사
            //* 원래 객체를 직접 변경한게 아니라 새로운 객체에 값만 붙여 넣은 꼴이라 새로운 객체임
            //* 다른 주소를 가리킴 
            return {
               ...state,
               number: state.number + 1
            };
        ...
        defualt: 
            return state;
    }
}
```

### action 만들기
```js
//* 상수 정의(관용적으로 이런 패턴으로 사용하는 것 같음)
const INCREASE = "counter_INCREASE"; 

export const increase = () => ({ type: INCREASE });
```

### 상태 업데이트 알리기
```js
const createStore = (reducer) => {
    //*  initial state는 프로젝트에 필요에 따라 작성 한다.
     let state = {
        number: 0
    };

    const listener = [];
    
    const getState = () => ({ ...state });
    const dispatch = (action) => {
        state = reducer(state, action);
        //* 상태를 사용하는 컴포넌트에서 등록한 함수들을 실행 한다.
        //* 전역 상태가 업데이트 되면 실행될 함수이다.
        //* 전역 상태가 업데이트 되면 나는 이 컴포넌트를 전역 상태에 따라 이렇게 업데이트 할거야
        //* 위의 increase 함수가 실행되면 (type: INCREASE)
        //* reducer에 의해 전역상태의 number 값이 1 증가 한다. 
        //* subscribe에 등록된 함수가 실행 된다
        //* 그 등록된 함수는 html의 number요소를 지금 state number값에 맞게 다시 구조화 할거야.
        //*  라는 함수를 subscribe에 등록
        listener.forEach(fn => fn());
    };
    
    //* 각 컴포넌트에서 상태가 업데이트 되면 실행될 함수를 등록한다.
    const subscribe = (fn) => listener.push(fn);

    return {
        getState,
        dispatch,
        subscribe
    }
};
```

### 사용 하는 곳
```js
//* 리엑트는 보통 main.js???
import reducer from "주소";
export const store = createStore(reducer);

//* store의 상태가 필요한 곳
import { store } from "주소";
const state = store.getState();

//* 구독 등록(subscribe)
import { store } from "주소";
...
//* html을 만드는 함수 안의 상태 초기화 
const state = store.getState(); or 
//* html을 만드는 class 안의 상태 초기화 
class {
    state = store.getState();
}
//* 그 뒤 
store.subscribe(함수 혹은 class내 html을 조작하는 함수 등의 로직);
//* 위의 store.subscribe의 인자로 넣은 함수는 전역 상태가 업데이트 되면 실행되기에
//* 새롭게 업데이트 된 상태값으로 html을 변경 할 수 있는 함수 등을 넣는다.
...
```