heyday2024 님의 블로그
버전 관련 트러블 슈팅 본문
문제
- 상황:
// NewProductList.tsx {/* @ts-expect-error Async Server Component */} const NewProductList = async () => { const res = await fetch("http://localhost:4001/products", { cache: "no-store", }); const data = await res.json(); const newData = data.filter((p) => p.isNew); return ( <div className="flex gap-2 overflow-auto"> {newData.map((product) => ( <div className="flex" key={product.id}> <img className="rounded-sm object-scale-down" width={80} src={product.images} alt={product.title} /> <div className="flex flex-col justify-between"> <h2 className="text-md font-medium">{product.title}</h2> <p className="mt-4 font-thin">{product.price.amount}$</p> </div> </div> ))} </div> ); }; export default NewProductList;
- NewProductList 컴포넌트를 Server Component로 구현하면서 async 키워드를 사용하여 데이터를 비동기로 가져옴. NewProducList를 page.tsx에서 import 해와서 return에 넣어주었으나. 이 NewProducList에 빨간 줄이 생김(오류 발생....)
- yarn dev 개발 모드에서는 오류를 무시하고 페이지에서는 렌더링되었으나, 의도한대로 렌더링되지 않았음. 그래서 yarn build && yarn start를 터미널에 입력해서 확인해보니 아래와 같은 에러 확인이 가능했음.
- 에러 내용:
- NewProductList가 JSX 요소로 사용할 수 없다는 에러(TS2786)가 발생:
'NewProductList' cannot be used as a JSX component. Its type '() => Promise<JSX.Element>' is not a valid JSX element type.
- NewProductList가 JSX 요소로 사용할 수 없다는 에러(TS2786)가 발생:
- 문제 원인
- 비동기 컴포넌트의 타입 제한:
- React는 JSX 구성 요소로 사용 가능한 타입을 ReactNode로 제한함.
- async 함수는 항상 Promise<JSX.Element>를 반환하므로, 이는 ReactNode와 호환되지 않아 TypeScript에서 타입 에러가 발생.
- TypeScript 및 React 타입 버전 문제:
- TypeScript 5.1.3 이상과 @types/react 18.2.8 이상 버전에서는 비동기 컴포넌트 사용을 공식적으로 지원.
- 기존 버전에서는 이러한 기능이 제대로 지원되지 않거나, 비동기 컴포넌트가 JSX 구성 요소로 사용될 때 타입 검사를 통과하지 못함.
- 비동기 컴포넌트의 타입 제한:
해결 과정
- 코드 수정 시도:
- 비동기 컴포넌트의 타입 제한 오류를 맞이했기에 나의 코드 구조와 비동기 작업을 처리하는 코드 부분을 위주로 점검하며 문제를 해결하고자 했으나, 결국 원인을 찾지 못하고 동일한 에러 발생.
- 또한 강의에서 제공한 코드 스니펫과 내가 작성한 코드와 다른 부분이 없어서 코드를 잘못 짠 것이 원인은 아니라고 생각함.
- 문제 본질적인 원인 다시 탐색 시도:
- 튜터님의 도움과 에러 메시지를 바탕으로 StackOverflow에서 유사 사례를 확인.
- 문제는 TypeScript 버전과 @types/react 버전이 Next.js의 Server Component 타입 처리 요구사항과 일치하지 않는 데서 비롯된 것으로 판단.
- 버전 점검 및 최신화:
- TypeScript가 최소 5.1.3 이상인지, @types/react가 최소 18.2.8 이상인지 확인:
- 기존 프로젝트의 typescript와 @types/react는 각각 ^5와 ^18로 설정되어 있었음.
- 5버전 중 최신, 18 버전 중 최신이라지만 이렇게 명확하지 않을 때에는 최신버전을 다시 그냥 설치해버리는 것도 좋다고 판단.
- 최신 버전 설치 명령어 실행:
- 혹은 yarn으로 설치npm install typescript@latest @types/react@latest
- TypeScript가 최소 5.1.3 이상인지, @types/react가 최소 18.2.8 이상인지 확인:
- 검증:
- 설치 후 yarn build 및 yarn start 명령 실행함. 오류 메세지 사라지고, 빌드 성공함. 또한 내가 의도한 대로 정상 동작되었음을 확인함.
문제의 원인 다시 정리
- TypeScript와 React 타입의 불일치:
- 최신 Next.js에서는 Server Component를 비동기 함수로 정의할 때, 특정 타입 정의가 필요.
- 구형 @types/react에서는 async 함수가 반환하는 Promise<JSX.Element>를 허용하지 않아 발생한 문제.
- 개발 모드와 프로덕션 모드의 차이:
- 개발 모드(yarn dev):
- 타입 체크가 비교적 느슨하게 작동하며, 비동기 Server Component도 런타임에서 처리.
- 프로덕션 모드(yarn build):
- 엄격한 타입 검사가 이루어져 비동기 함수로 인한 타입 불일치가 에러로 처리됨.
- 개발 모드(yarn dev):
최신 버전 설치로 해결된 이유
- TypeScript 5.1.3 이상:
- Server Component의 비동기 타입 처리를 위한 개선 사항이 포함.
- @types/react 18.2.8 이상:
- React.FC와 같은 타입이 async Server Component를 적절히 처리하도록 업데이트.
최종적으로 에러없이 suspense까지 잘 이용함!
느낀점
- 작성한 코드에 문제가 없어 보이는데도 에러가 발생할 때는 당황하지 말고, 해당 오류가 버전과 관련이 있는지 차분히 확인해보는 자세가 필요하다는 것을 배웠다. 버전마다 새롭게 제공되는 기능과 더 이상 지원되지 않는 기능을 확인하는 습관이 정말 중요하다는 점도 깨달았다.
- 또한, 팀원들과 개발 환경을 공유하는 과정에서 원활한 협업을 위해 사용할 프레임워크나 라이브러리의 버전을 미리 정하는 것이 필요하다. 평소에 버전별 변경 사항과 요구사항을 주기적으로 검토하는 습관을 들인다면, 팀원들과 환경을 구성할 때 이러한 정보가 큰 도움이 될 것이라고 생각한다.