redux 구조 jQuery에 얹어보기

StarSeeker·2023년 4월 12일
0

동기

현재 내가 있는 팀이 개발하고 있는 마케팅 플랫폼의 어드민 페이지의 소스는 jQuery로 구성되어있고 SaaS의 특성상 어드민페이지가 굉장히 복잡하다.
한페이지에 굉장히 많은 폼데이터들이 있고 그 데이터들에 의해 여러 UI가 바뀌어야 하는 구조이다.
이렇다보니 점점 더 폼데이터의 상태값들을 추적하기가 힘들어졌고 소스코드 내에서 이것을 파악하기가 굉장히 어려워졌다.

이전에 React를 공부하면서 redux의 Flux 패턴에 대해 공부한게 있었는데 갑자기 그 생각이 나게되었다.
지금 현재의 상태관리를 Flux 패턴처럼 단방향으로 적용되게 한다면 좀 더 예측가능한 코드구조로 바뀔수 있을 것 같았다.

Redux 의 동기 페이지에서도 이와 비슷한 얘기를 한다.

항상 변하는 상태를 관리하기란 어렵습니다.
모델이 다른 모델을 업데이트하고, 그리고 뷰가 모델을 업데이트 할 수 있고, 이 뷰가 다시 다른 모델을 업데이트하고, 이에 따라 또 다른 뷰가 업데이트 됩니다.
어느 시점에서는 프로그래머조차 애플리케이션에서 무슨 일이 일어나는지 알 수 없게 됩니다.
상태를 언제, 왜, 어떻게 업데이트할지 제어할 수 없는 지경에 이르고 맙니다.
시스템이 불투명하고 비결정적일 때 버그를 재현하거나 새로운 기능들을 추가하기란 매우 어렵습니다.

고민

어떻게 적용하면 좋을까
일단 redux의 원칙부터 살펴보기로 했다.

  • Redux의 3가지 원칙
  1. 진실은 하나의 근원으로부터
  2. 상태는 읽기 전용이다
  3. 변화는 순수 함수로 작성되어야한다
  • 하나의 근원
    Form 데이터를 하나의 근원 으로 만들려면 일단 사용자가 입력하는 데이터가 바로 렌더링 되지 않게 막는게 우선이다.
    마치 React에서 input값을 입력할때 state값이 바뀌지않으면 입력이 되지 않는 것처럼 만들면 어떨까?
  • 상태는 읽기 전용이다.
    화면의 상태를 읽기 전용으로 만들기 위해서 가운데 store라는 전역변수를 만들고 거기에서 데이터를 관리하면 어떨까
  • 변화는 순수 함수로 작성되어야한다.
    store를 변화시키는 setter 함수를 통해서만 store를 변화시킨다면?

이와 더불어 store를 변화시킬때 렌더링되는 함수들을 중앙화해서 store를 통해서만 렌더링 되게끔 하면 마치 redux를 사용하는 react와 비슷한 느낌을 주지않을까 라는 생각이 들었다.

구현

  1. 모든 렌더링은 하나의 근원 으로부터
    일단 jQuery 함수를 이용해서 이벤트리스너에서 받는 모든 form의 input값을 초기화했다.

input에 렌더링되는 값을 초기화한뒤 그 변경된 값을 store로 보낸다.
이렇게 함으로써 모든 input값은 사용자가 입력한 데이터에 의해 렌더링되는게 아닌 store에 의해 렌더링 된다.

  1. 상태는 읽기 전용
    일단 상태는 전역변수로 선언하여 페이지에서 하나씩 관리되도록 하였다. 이 전역변수는 곧 store가 되고 이때 이 변수는 일부가 변경되는것이 아닌 교체되는 것이다.
    이를 위해 jQuery의 extends 함수를 사용해 상태가 교체될때마다 deepCopy를 할수 있게 하였다.

    const copiedState = $.extend(true, originState, setData);

    이렇게 하면 현재 상태의 깊은 depth에 있는 상태까지도 deepCopy할수 있게 된다.

  2. 변화는 순수 함수로 작성되어야한다.
    store에 변화를 주는 set 함수를 구현해야하는데 set 함수가 실행될때마다 render 함수도 같이 실행되어야 했다.
    이를 위해 Object.defineProperty 함수를 사용하기로 했다.

const store = {}

const state = {}
Object.defineProperty(store, 'state', {
                    get() { return state; },
                    // store 의 데이터가 바뀔때마다 실행되는 set 함수.
                    set(newValue) {
                        state = newValue;
                        // 현재 포커스된 input에 따라 렌더함수가 결정됨.
                        render(newValue);
                    },
                    enumerable: true,
                    configurable: true
                })

store.state = {text: 'test'} //set 함수가 실행되고 새로운 상태값에 의한 렌더링함수가 실행됨.

변화

  1. 렌더링 로직이 중앙화되어서 보다 코드의 가독성이 높아지고 어떤 때에 렌더링이 되는지보다 명확해졌다.
  2. 하나의 근원으로부터 렌더링이 되므로 언제 폼데이터의 state값이 변화하게 되는지 예측가능한 코드가 되었다.
  3. 화면상 렌더링 버그가 발생해도 store 의 state값만 추적하면 된다.
    (기존에는 jquery로 선언한 이벤트 리스너 그 리스너안에있는 렌더링 로직들을 일일히 다 살펴야했다.)

위의 flux구조와 똑같을 순 없겠지만 양방향이었던 렌더링 흐름을 단방향으로 바꿀수 있어서 많은 이점을 얻을 수 있었다.

결론

사실 모던한 프론트엔드 환경을 공부하면서 jQuery의 환경이 너무 못나보였던건 사실이지만 결국엔 jQuery의 유산에서 시작해 지금까지 이르게된 과정이 분명히 있었다는 것을 공감했다.

이런 환경을 경험하지 못했다면 레거시 환경이 얼마나 불편했는지 어떠한 동기에의해서 새로운 패러다임이 등장했는지 몸소 느끼지 못했을 것 같다.
내가 있는 환경에서 최대한 어떤부분을 개선할수 있을지 고민하는게 가장 중요하다는 것을 깨닫는 계기가 되었다.

profile
춤추듯 개발하고 싶은 사람

0개의 댓글