본문 바로가기

FrontEnd

Recoil로 Excel(SpreadSheet) 만들기

반응형

원래 Xstate로 만드려다가 실패했다.

 

Xstate는 이전 비즈니스 로직에서 다음 비즈니스 로직으로의 전환을 관리하는덴 좋지만,

지금같은 Reactivity가 필요한 솔루션에는 별 도움이 안되는것 같다~

라고 생각했는데 해당 내용을 정리하면서 다시 한번 생각해보니 굳이 XState로 만들려 하면 할 수도 있을 것 같다.

 

원래 Recoil과 같이 변경되는 부분만 최적화 하는게 어려울 것이라 생각했는데, selector를 잘 응용하면 될것 같기도 하다.

Recoil로 중간에 변경한 이유는 중첩 참조 때문인데, 구현해보니 어차피 중첩 참조는 직접 구현해줘야 했다(...)

 

일단 cellsAtom에는 순수하게 입력한 input만 넣어두고,

셀렉터로 input을 평가해서 화면에 뿌려준다.

왜냐햐면 input에 포커스가 가면 value를 보여줘야 하기 때문이다.

그리고 포커스를 잃으면(onBlur) cellsAtom의 값을 변경한다.

그러면 해당 아톰에 의존하는 셀렉터들의 값이 변경된다.

 

그리고 =로 시작하는 expr은 재귀 솔루션으로 해결한다.

jotai 개발자의 솔루션을 베끼려 했는데, 중첩 참조 부분을 구현을 안해두어서 첨부터 다시했다.

자기 자신을 넘겨줄 때 스택 오버플로가 발생하기에 id를 이용해 필터링 해줘야한다.

이 부분은 이전에 jotai 내부구현을 보면서 배운거라 금세 해결할 수 있었다.

    function evalCells(cell: Cell, id: string): string {
      switch (cell.type) {
        case "exp": {
          const targets = cell.val.match(/\b([A-Z]\d{1,2})\b/g) || [];
          const result = targets
            .filter((d) => d !== id)
            .reduce(
              (acc, d) => acc.replaceAll(d, evalCells(get(cellsAtom(d)), d)),
              cell.val.slice(1)
            );
          return result;
        }
        case "val": {
          return cell.val ?? "#ERROR";
        }
      }
    }

프로젝트 이름이 XState이긴 하지만... cells 프로젝트는 리코일로 되어있다.

 

이번에는 recoil을 공부했다 생각하고... 다음에 XState로 다시 시도해봐야겠다.

 

위 솔루션에는 없는 resize 기능은 아래를 참고하면 된다. 물론 좀 수정이 필요하다.

(이것도 별거 아니어보이지만 참조한 블로그 코드에 오류가 있었고,

컬럼 사이즈 조절은 있는데 row size 조절을 참고할 자료가 없어서 찾다가 찾다가 그냥 내가 만들었다.)

 

1. 그리드 레이아웃으로 전환

2. useRef 부분을 전달하는 훅으로 잘 떼어내서 리팩터링

3. 맨 아래, 맨 오른쪽 하단의 리사이즈 기능 제거

 

나중에 시간되면 좀 더 고도화해봐야 겠다.

 

 

반응형