들어가기
최근 곰곰 다이어리를 리팩토링을 하고 있다.
⭐️ [as is]
JavaScript, 스타일링: css module, 전역 상태 관리: recoil
🌟 [to be]
TypeScript, 스타일링: Styled components, 전역 상태 관리: jotai + tanstack Query
사실 신규 기술의 도입을 위해서가 아니라 기존 코드를 뜯어 고칠 게 너무 많아서 시작했는데,
하는 김에 그냥 다 고쳐 버리는 게 좋을 것 같아 전부터 조금씩 하다 요 며칠 불이 붙었다.
이렇게 고치게 된 경위는 다음과 같다.
- 기존 코드에서 UI / 비즈니스 로직 분리가 하나도 되지 않음
- 커스텀 훅을 거의 도입하지 않아 코드가 300줄(;)이 넘는 경우가 많음
- 의미가 모호한 변수, 오타, 실제로 사용하지 않는 스타일링 코드들이 발견됨
- 기존에 사용하던 recoil이 지속 가능한지에 대한 의구심
- 클라이언트 상태와 서버 상태가 복잡하게 혼용되고 있음
7월인가 8월쯤에 트래픽이 대거 몰렸고 그 때 마주하게 된 버그를 해결하는 과정에서
내 코드를 파악하기가 쉽지 않아 빨리 대처를 하지 못한 게 좀 충격적이었다.
아무리 개발을 못해도 내가 짠 것도 못 알아볼 정도라니...
물론 규모가 커지면 그럴 순 있겠지만, 그렇게 큰 규모도 아닌데...
클린 코드라는 개념을 나와는 먼 것으로만 여겼던 안일함에 부끄러움을 느꼈다.
그래서 빨리 고쳐야지 고쳐야지 했는데, 리팩토링은 정말 쉽게 손이 가지 않더라 🥹
더 이상 미룰 수 없다 나의 코드 나의 리팩토링!
아예 싹 고치면서 디자인도 조금 더 손보고, 로띠도 넣을 수 있는 곳에 넣어보고...
익숙하지 않은 TypeScript로 시행착오도 겪어보고 최적화도 더 해보자.
그 과정에서 만난 크고 작은 새로 배운 점들, 잊고 있었던 것들을 정리한다.
엊그제부터 이미 좀 많이 고쳐서 시간 순은 아니지만 어쨌거나 기록 기록 📝
타입 추론이 되지 않는 배열
TypeScript는 알아서 타입을 추론하기 때문에 구태여 타입을 명시할 필요가 없다고 배웠다.
실제로도 타입 추론이 잘 되기 때문에 딱히 명시한 적이 몇 없는데...
[상황]
- responseArr 는 jotai로 관리하는 전역 상태로 type은 Array다.
- 유저가 문항에 답할 때마다 responseArr에 response라는 문자열을 얕은 복사로 추가해준다.
[문제]
setResponseArr([...responseArr, response]);
import { atom } from 'jotai';
export const responseArrAtom = atom([]);
Type 'string' is not assignable to type 'never'.ts(2322)
const responseArr: never[]
첫 번째 코드와 같이 responseArr에 배열을 넣어주려는데 responseArr가 never[]라고 한다.
[원인 및 해결]
- TypeScript가 responseArr의 타입을 올바르게 추론하지 못하고 있다.
- jotai의 atom 초기값으로 []을 사용할 때 타입 정보를 명시하지 않으면 기본적으로 타입을 never[]로 추론한다.
- 빈 배열에는 아무 값도 없기 때문에 해당 배열이 어떤 타입의 요소를 가질지 알 수 없기 때문이다.
- never는 절대 발생할 수 없는 타입으로 이 경우 해당 배열에 어떤 값도 추가할 수 없다.
- 상태 관리 라이브러리에서는 상태의 일관성을 유지하기 위해 초기값의 타입이 명확해야 한다.