[다담다] 타입스크립트 프로젝트에서 jsx import하기

한낱·2023년 10월 3일
0

재앙의 시작...

프로젝트 '보드' 기능에 DND 기능을 이용하기로 하였다. 공식 document에서 제공하는 예제와 유튜버의 코드를 클론코딩해보고 DND-kit라는 라이브러리를 사용하기로 하였다.

왜냐하면 제공되는 예제가 많았고, 그 중 한 예제가 제작중인 서비스와 아주 유사하여 코드를 약간만 수정하면 될 것이라고 판단했기 때문이다.

참고한 DND-kit의 예제
(column을 기준으로 하는 칸반 형태의 DND를 사용하는 예제로 요소의 제거나 column의 추가도 DND를 통해 할 수 있는 형태이다.)

문제는, 해당 예제는 칸반 보드의 예제이기 때문에 요소의 data가 단순 string으로만 이루어져 있지만, 우리 서비스는 북마크 서비스이기 때문에 스크랩의 다양한 정보(제목, 설명, 저자, 이미지 URL 등)를 가지는 복잡한 형태로 이루어져 있다는 것이었다. 더불어, 해당 요소는 스크랩 뿐만 아니라 메모 형태도 가능해야 했다.

일단은 가보자고...!


무식해서 용감했던 n일 전 나는 일단 요소의 type을 변경해보았다.

Items 타입 변경

// 변경 전
{
    A: ['A1', 'A2', 'A3'],
    B: ['B1', 'B2', 'B3'],
    C: ['C1', 'C2', 'C3'],
    D: ['D1', 'D2', 'D3'],
}

// 변경 후
{
	A: [scrapCardDataMock],
}

기존 Items의 형태는 A, B, C, D와 같이 UniqueIdentifier 타입을 key로 가지고, value로는 UniqueIdentifier 타입의 배열을 가지는 object 형태였다. 하지만, 현재 서비스에서는 value로 단순한 UniqueIdentifier 타입 배열이 아닌 복잡한 scrap 정보 타입 배열을 가지도록 변경하였다.

// 변경 전
type Items = Record<UniqueIdentifier, UniqueIdentifier[]>;
// 변경 후
type Items = Record<UniqueIdentifier, contentProps['content'][]>;

(스크랩 정보 타입이 contentProps['content']로 다른 파일에 정의되어 있다.)

task 렌더링

<div
  style={style}
  data-cypress="draggable-item"
  {...(!handle ? listeners : undefined)}
  {...props}
  tabIndex={!handle ? 0 : undefined}
>
  {value}
</div>

<div
  style={style}
  data-cypress="draggable-item"
  {...(!handle ? listeners : undefined)}
  {...props}
  tabIndex={!handle ? 0 : undefined}
>
  <ScrapCard content={value} />
</div>

기존에는 칸반 보드의 task에 해당하는 부분을 그릴 때 단순 string만 그려주고 있었다. ( {value} 부분)
코드를 수정할 때에는 해당 부분을 다른 페이지에서 사용하고 있던 ScrapCard 컴포넌트로 바꾸고 contentProps['content'] 타입에 해당하는 값을 넘겨주어 원하는 카드 모양을 그리도록 하였다.

그리고 놀랍게도,

이게 먹혔었다...

문제는...


어마무시한 타입스크립트 오류가 발생하게 되었다.

당시 총 27개의 ts 오류가 발생했고, 그 중 23개가 저 파일이었다. (참고로 해당 파일은 1000줄짜리 파일이다 ^^)

각 오류를 모두 따라가 오류만 발생하지 않도록 수정을 해보았는데 오히려 기능이 하나씩 동작하지 않게 되었다. (task 이동이 동작하지 않거나, 아예 렌더링이 되지 않는 오류 등이 발생했었다.)

그렇게 n일간 고생을 해보다 이상한 점을 발견하게 되었는데...

const findContainer = (id: UniqueIdentifier) => {
  if (id in items) {
    return id;
  }

  return Object.keys(items).find((key) => items[key].includes(id));
};

이 함수가 DND-kit 예제에서 반환하는 값은 task의 UniqueIdentifier이다. 즉, 앞선

A: ['A1', 'A2', 'A3'],
B: ['B1', 'B2', 'B3'],
C: ['C1', 'C2', 'C3'],
D: ['D1', 'D2', 'D3'],

형태를 예로 들자면, 'A1', 'A2', 'A3', 'B1', ... 'D3' 중 하나가 반환된다는 소리이다. 하지만 타입을 바꾼 이후 boolean 값이 return되고 있었다. 이를 발견하고 return이 id에 맞는 scrap 정보를 return하도록 변경해보았는데, 오히려 오류가 나버렸다. 이 개고생까지 지난 n일을 다 사용했다. 그래서 오늘, 결단을 내렸다.

타입스크립트 개나 줘

과격하지만 해당 파일에서만 타입스크립트가 아닌 자바스크립트를 사용하도록 확장자를 jsx로 변경하였다. 물론 이러면 안 된다. 실제로 오류도 난다. 하지만, 이미 며칠이나 소모한 뒤라 극단적이지만 확실한 해결책을 택했다.

이후 추가로 발생한 오류는 무엇이었고, 어떻게 해결했느냐면...

타입 떼어내기

아무래도 기존 코드가 tsx로 작성되어 있어서 모든 타입스크립트 문법 부분을 제거하였다. type 키워드나 interface 키워드로 시작하는 코드도 모두 제거했고, 함수나 useState에서 어떤 타입을 사용할 것인지 알려주던 부등호 내부 등을 모두 제거했다. 추가로, 함수 parameter에 ':' 기호를 통해 타입을 명시하던 부분 모두 제거했다.

import 오류 해결

이후에는 해당 파일을 import 구문으로 불러오던 상위 파일에서 해당 파일을 찾지 못하는 문제가 발생하였다. 이는 프로젝트를 타입스크립트로 생성하면서 jsx 파일을 읽지 못해 생기는 문제로, tsconfig에 설정을 추가해주어 해결할 수 있다.

{
  // tsconfig.json 파일
  "compilerOptions": {
    // "allowJs" 설정을 추가하여 jsx 확장자 파일을 import할 수 있다.
    "allowJs": true,
    ...
  }
}

오늘 하루 요약


꼭 짬짬이 해당 코드를 살펴서 왜 됐고 왜 안 되었는지 알아내야지...

profile
제일 재밌는 개발 블로그(희망 사항)

0개의 댓글