문제

새로운 프로젝트를 시작하며 Next.js를 굳이 CSR로 사용하지 않고 SSR을 그대로 사용하기로 하였다. 그랬더니 CSR을 사용하도록 유도한 프로젝트에선 나지 않던 hydration 에러가 나기 시작했다.

hydration 에러 발생 상황을 디버깅하다보니 디자인 시스템 Select 컴포넌트에서 생기는 것을 확인하였다.

Select 컴포넌트 코드를 하나씩 삭제해보며 테스트 해보았을 때 Reakit이라는 사용성 UI 컴포넌트에서 생기는 에러임을 확인하고 코드를 뜯어보았다. 코드 내에서 React portal을 사용하는데 portal container 생성은 클라이언트 사이드에서 하는건 잘 해두었지만 조건이 잘못되어 있었다.

const [isCSR, setIsCSR] = useState(false);

useEffect(() ⇒ {
  setIsCSR(true);
}, []);

위와 같이해야 hydration 에러가 나지 않는 반면 (Next js error docs에서 말하는 방식이다.)

const [isCSR, setIsCSR] = useState(typeof window !== undefined);

Reakit 내부에선 위와같이 코드가 짜여있었다.

수정 PR을 날렸지만 반영을 안해줘서 직접 유지보수 하기로 하였다.

PR: https://github.com/ariakit/ariakit/pull/2570

문제 해결 과정

  1. 이미 내 개인 레포지토리로 포크해와서 수정까지한 코드가 있기 때문에 이 상태 그대로 사내 monorepo 안에 패키지로 집어넣어서 관리하는 방향으로 생각했다.
  2. 회사 monorepo에 패키지로 추가하는 과정에서 Reakit은 이미 lerna 기반 monorepo로 관리되고 있었기에 monorepo안에 monorepo를 넣기엔 어려움이 생겼다.
  3. 이슈 자체는 개발할 때 조금 불편하긴 하지만 프로덕션 환경에선 문제가 없었기에 빠른 개발을 위해 포크뜬 개인 레포지토리에 있는 패키지를 npm에 배포하였다.
  4. 배포한 패키지를 디자인 시스템 package.json에서 alias로 가져와서 사용하였다. (”reakit”: “npm:@syi0808/reakit”)